dsh-opencode-go 0.1.20 → 0.1.22
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 +133 -127
- package/README.md +131 -127
- package/THIRD_PARTY_NOTICES.md +3 -1
- package/docs/development.md +60 -8
- package/docs/fork-review-2026-09-25.md +191 -0
- package/docs/independent-package.md +2 -2
- package/docs/verification.md +241 -0
- package/lib/build-info.json +8 -1
- package/lib/client.js +1576 -234
- package/lib/index.js +7001 -338
- package/lib/types/account-manager.d.ts +23 -0
- package/lib/types/account-operations.d.ts +31 -0
- package/lib/types/account-policy.d.ts +16 -0
- package/lib/types/account-recovery.d.ts +2 -0
- package/lib/types/account-selection.d.ts +30 -0
- package/lib/types/account-service.d.ts +12 -0
- package/lib/types/accounts-contract.d.ts +38 -0
- package/lib/types/accounts.d.ts +31 -0
- package/lib/types/adapter.d.ts +43 -9
- package/lib/types/call-trace.d.ts +54 -0
- package/lib/types/catalog-manager.d.ts +20 -0
- package/lib/types/catalog.d.ts +6 -3
- 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 +69 -0
- package/lib/types/client/host-compat.d.ts +7 -0
- package/lib/types/client/locales.d.ts +55 -1
- package/lib/types/client/section-controller.d.ts +17 -41
- package/lib/types/client/staged-form.d.ts +1 -3
- package/lib/types/client/usage.d.ts +1 -1
- package/lib/types/config-contract.d.ts +69 -0
- package/lib/types/config.d.ts +12 -47
- package/lib/types/conversion/context.d.ts +5 -1
- package/lib/types/conversion/image-pool.d.ts +24 -0
- package/lib/types/conversion/replay.d.ts +1 -1
- package/lib/types/conversion/stream.d.ts +1 -1
- package/lib/types/gateway-diagnostics.d.ts +22 -0
- package/lib/types/gateway-error.d.ts +2 -0
- package/lib/types/host-settings.d.ts +11 -0
- package/lib/types/index.d.ts +2 -1
- package/lib/types/json-response.d.ts +1 -1
- package/lib/types/model-metadata.d.ts +3 -1
- package/lib/types/models-contract.d.ts +7 -0
- package/lib/types/protocol-contract.d.ts +5 -0
- package/lib/types/protocol-policy.d.ts +4 -0
- package/lib/types/proxy-url.d.ts +2 -0
- package/lib/types/proxy.d.ts +11 -0
- package/lib/types/reasoning.d.ts +36 -6
- package/lib/types/request-control.d.ts +2 -0
- package/lib/types/sdk-types.d.ts +1568 -0
- package/lib/types/settings-bridge.d.ts +22 -0
- package/lib/types/usage-contract.d.ts +5 -0
- package/lib/types/usage.d.ts +14 -2
- package/lib/vendor-licenses.txt +103 -0
- package/package.json +8 -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");
|
|
@@ -82,6 +82,10 @@ function parseGoModels(value) {
|
|
|
82
82
|
for (const key of ["contextWindow", "maxTokens"]) {
|
|
83
83
|
if (typeof row[key] === "number" && Number.isSafeInteger(row[key]) && row[key] > 0) model[key] = row[key];
|
|
84
84
|
}
|
|
85
|
+
if (row.reasoningBudget !== null && typeof row.reasoningBudget === "object") {
|
|
86
|
+
const { min, max } = row.reasoningBudget;
|
|
87
|
+
if (typeof min === "number" && Number.isSafeInteger(min) && min > 0 && typeof max === "number" && Number.isSafeInteger(max) && max >= min) model.reasoningBudget = { min, max };
|
|
88
|
+
}
|
|
85
89
|
if (typeof row.deprecated === "boolean") model.deprecated = row.deprecated;
|
|
86
90
|
if (typeof row.configurationMissing === "boolean") model.configurationMissing = row.configurationMissing;
|
|
87
91
|
if (validReleaseDate(row.releaseDate)) model.releaseDate = row.releaseDate;
|
|
@@ -113,9 +117,11 @@ function parseSources(value) {
|
|
|
113
117
|
throw new Error("Invalid OpenCode Go catalog source timestamp");
|
|
114
118
|
}
|
|
115
119
|
if (source.error !== void 0 && typeof source.error !== "string") throw new Error("Invalid OpenCode Go catalog source error");
|
|
120
|
+
if (source.warning !== void 0 && typeof source.warning !== "string") throw new Error("Invalid OpenCode Go catalog source warning");
|
|
116
121
|
return {
|
|
117
122
|
...source.updatedAt === void 0 ? {} : { updatedAt: source.updatedAt },
|
|
118
|
-
...source.error === void 0 ? {} : { error: source.error }
|
|
123
|
+
...source.error === void 0 ? {} : { error: source.error },
|
|
124
|
+
...source.warning === void 0 ? {} : { warning: source.warning }
|
|
119
125
|
};
|
|
120
126
|
};
|
|
121
127
|
return { listing: parse(sources.listing), metadata: parse(sources.metadata) };
|
|
@@ -145,10 +151,10 @@ if (!document.querySelector("style[data-plugin-css=" + JSON.stringify(id) + "]")
|
|
|
145
151
|
const style = document.createElement("style");
|
|
146
152
|
style.dataset.plugin = "dsh-opencode-go";
|
|
147
153
|
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}}";
|
|
154
|
+
style.textContent = '.N807zW_accounts{gap:10px;margin:6px 0;padding:6px 0;display:grid}.N807zW_accountRow{border:.5px solid var(--dsw-alias-border-l2);border-radius:10px;position:relative}.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_accountRow:after{content:"";background:var(--dsw-alias-brand-primary);opacity:0;pointer-events:none;border-radius:2px;height:2px;position:absolute;left:0;right:0}.N807zW_accountRow[data-drop=before]:after{opacity:1;top:-6px}.N807zW_accountRow[data-drop=after]:after{opacity:1;bottom:-6px}.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_budgetEditor{margin-top:12px;font-size:12px}.N807zW_budgetEditor summary{cursor:pointer}.N807zW_budgetInput{align-items:center;gap:8px;margin-top:4px;display:flex}.N807zW_budgetPresets{flex-wrap:wrap;gap:6px;margin-top:8px;display:flex}.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
155
|
document.head.appendChild(style);
|
|
150
156
|
}
|
|
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" };
|
|
157
|
+
var Section_default = { "accountActions": "N807zW_accountActions", "accountBar": "N807zW_accountBar", "accountBarFill": "N807zW_accountBarFill", "accountBarTick": "N807zW_accountBarTick", "accountDetail": "N807zW_accountDetail", "accountDot": "N807zW_accountDot", "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", "budgetEditor": "N807zW_budgetEditor", "budgetInput": "N807zW_budgetInput", "budgetPresets": "N807zW_budgetPresets", "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
158
|
|
|
153
159
|
// src/client/ModelEditor.tsx
|
|
154
160
|
var import_jsx_runtime = require("react/jsx-runtime");
|
|
@@ -160,7 +166,7 @@ var MODALITY_COPY = {
|
|
|
160
166
|
pdf: "modalityPdf"
|
|
161
167
|
};
|
|
162
168
|
function hasCapacityOverride(limit) {
|
|
163
|
-
return limit?.contextWindow != null || limit?.maxTokens != null;
|
|
169
|
+
return limit?.contextWindow != null || limit?.maxTokens != null || (limit?.thinkingBudgets?.length ?? 0) > 0;
|
|
164
170
|
}
|
|
165
171
|
function ModelEditor({ models, draft, modelVisibility, t, locale, disabled, visibilitySaving, filterAction, onEdit, onModelEnabled }) {
|
|
166
172
|
const [query, setQuery] = (0, import_react.useState)("");
|
|
@@ -189,7 +195,7 @@ function ModelEditor({ models, draft, modelVisibility, t, locale, disabled, visi
|
|
|
189
195
|
["deprecated", "filterDeprecated", all.filter((entry) => entry.deprecated).length]
|
|
190
196
|
];
|
|
191
197
|
const write = (id3, field, value) => {
|
|
192
|
-
const current = draft[id3] === null ? { contextWindow: null, maxTokens: null } : draft[id3] ?? {};
|
|
198
|
+
const current = draft[id3] === null ? { contextWindow: null, maxTokens: null, thinkingBudgets: null } : draft[id3] ?? {};
|
|
193
199
|
onEdit({ ...draft, [id3]: { ...current, [field]: value ?? null } });
|
|
194
200
|
};
|
|
195
201
|
const badges = (entry) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
@@ -291,6 +297,20 @@ function ModelEditor({ models, draft, modelVisibility, t, locale, disabled, visi
|
|
|
291
297
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Modalities, { model, t })
|
|
292
298
|
] })
|
|
293
299
|
] }),
|
|
300
|
+
model.reasoningBudget ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
301
|
+
BudgetPresets,
|
|
302
|
+
{
|
|
303
|
+
model,
|
|
304
|
+
limit: draft[model.id],
|
|
305
|
+
t,
|
|
306
|
+
locale,
|
|
307
|
+
disabled,
|
|
308
|
+
onChange: (values) => {
|
|
309
|
+
write(model.id, "thinkingBudgets", values);
|
|
310
|
+
}
|
|
311
|
+
},
|
|
312
|
+
model.id
|
|
313
|
+
) : null,
|
|
294
314
|
hasCapacityOverride(draft[model.id]) ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
295
315
|
"button",
|
|
296
316
|
{
|
|
@@ -374,22 +394,541 @@ function Capacity({ model, field, limit, disabled, t, locale, onChange }) {
|
|
|
374
394
|
] })
|
|
375
395
|
] });
|
|
376
396
|
}
|
|
397
|
+
function BudgetPresets({ model, limit, disabled, t, locale, onChange }) {
|
|
398
|
+
const [text, setText] = (0, import_react.useState)("");
|
|
399
|
+
const range = model.reasoningBudget;
|
|
400
|
+
const max = Math.min(range.max, (limit?.maxTokens ?? model.maxTokens ?? range.max + 1024) - 1024);
|
|
401
|
+
const values = limit?.thinkingBudgets ?? [];
|
|
402
|
+
const tokens = Number(text);
|
|
403
|
+
const valid = text.trim() !== "" && Number.isSafeInteger(tokens) && tokens >= range.min && tokens <= max;
|
|
404
|
+
const id3 = `opencode-go-thinking-budget-${encodeURIComponent(model.id)}`;
|
|
405
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("details", { className: Section_default.budgetEditor, children: [
|
|
406
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("summary", { children: t("thinkingBudgets") }),
|
|
407
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: Section_default.hint, children: t("thinkingBudgetsHint", { min: range.min.toLocaleString(locale), max: max.toLocaleString(locale) }) }),
|
|
408
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("label", { className: Section_default.statLabel, htmlFor: id3, children: t("thinkingBudgetAddLabel", { name: model.name ?? model.id }) }),
|
|
409
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: Section_default.budgetInput, children: [
|
|
410
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
411
|
+
"input",
|
|
412
|
+
{
|
|
413
|
+
id: id3,
|
|
414
|
+
className: Section_default.input,
|
|
415
|
+
type: "number",
|
|
416
|
+
step: 1,
|
|
417
|
+
min: range.min,
|
|
418
|
+
max,
|
|
419
|
+
inputMode: "numeric",
|
|
420
|
+
value: text,
|
|
421
|
+
placeholder: "4096",
|
|
422
|
+
disabled,
|
|
423
|
+
"aria-invalid": text !== "" && !valid,
|
|
424
|
+
onChange: (event) => {
|
|
425
|
+
setText(event.target.value);
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
),
|
|
429
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
430
|
+
import_dsh_client_ui_primitives.Button,
|
|
431
|
+
{
|
|
432
|
+
variant: "outline",
|
|
433
|
+
size: "sm",
|
|
434
|
+
disabled: disabled || !valid || values.includes(tokens) || values.length >= 16,
|
|
435
|
+
onClick: () => {
|
|
436
|
+
onChange([...values, tokens].sort((a, b) => a - b));
|
|
437
|
+
setText("");
|
|
438
|
+
},
|
|
439
|
+
children: t("thinkingBudgetAdd")
|
|
440
|
+
}
|
|
441
|
+
)
|
|
442
|
+
] }),
|
|
443
|
+
values.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: Section_default.budgetPresets, children: values.map((value) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
444
|
+
"button",
|
|
445
|
+
{
|
|
446
|
+
type: "button",
|
|
447
|
+
className: Section_default.filter,
|
|
448
|
+
disabled,
|
|
449
|
+
"aria-label": t("thinkingBudgetRemove", { value }),
|
|
450
|
+
onClick: () => {
|
|
451
|
+
const next = values.filter((tokens2) => tokens2 !== value);
|
|
452
|
+
onChange(next.length > 0 ? next : void 0);
|
|
453
|
+
},
|
|
454
|
+
children: [
|
|
455
|
+
value.toLocaleString(locale),
|
|
456
|
+
" tokens \xD7"
|
|
457
|
+
]
|
|
458
|
+
},
|
|
459
|
+
value
|
|
460
|
+
)) }) : null
|
|
461
|
+
] });
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
// src/client/AccountsCard.tsx
|
|
465
|
+
var import_react2 = require("react");
|
|
466
|
+
var primitives = __toESM(require("@deepseek-ai/dsh-client-ui-primitives"), 1);
|
|
467
|
+
var import_dsh_client_ui_primitives2 = require("@deepseek-ai/dsh-client-ui-primitives");
|
|
468
|
+
|
|
469
|
+
// src/accounts.ts
|
|
470
|
+
var MAX_ACCOUNTS = 20;
|
|
471
|
+
var DEFAULT_ACCOUNT_REF = "OPENCODE_API_KEY";
|
|
472
|
+
var ACCOUNT_REF_PATTERN = /^[A-Za-z_][A-Za-z0-9_]*$/;
|
|
473
|
+
function accountRefOf(settings) {
|
|
474
|
+
return settings.apiKeyEnv || DEFAULT_ACCOUNT_REF;
|
|
475
|
+
}
|
|
476
|
+
function accountsOf(settings) {
|
|
477
|
+
const ref = accountRefOf(settings);
|
|
478
|
+
if (settings.accounts?.length === 0) return [];
|
|
479
|
+
const accounts = settings.accounts ?? [];
|
|
480
|
+
return accounts.some((account) => account.apiKeyEnv === ref) ? accounts : [
|
|
481
|
+
{ id: `legacy:${ref}`, name: "", apiKeyEnv: ref },
|
|
482
|
+
...accounts
|
|
483
|
+
];
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
// src/client/AccountsCard.tsx
|
|
487
|
+
var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
488
|
+
var WINDOWS = ["rolling", "weekly", "monthly"];
|
|
489
|
+
var TICKS = [25, 50, 75];
|
|
490
|
+
var ChevronDown = primitives.IconChevronDownOutlineRegular ?? primitives.IconChevronDownOutline14;
|
|
491
|
+
function resetText(resetsAt, t) {
|
|
492
|
+
const remaining = Date.parse(resetsAt) - Date.now();
|
|
493
|
+
if (!Number.isFinite(remaining)) return t("usageResetUnknown");
|
|
494
|
+
if (remaining <= 0) return t("usageResetDue");
|
|
495
|
+
const minutes = Math.max(1, Math.round(remaining / 6e4));
|
|
496
|
+
if (minutes < 60) return t("usageResetMinutes", { minutes });
|
|
497
|
+
const hours = Math.round(minutes / 60);
|
|
498
|
+
if (hours < 24) return t("usageResetHours", { hours });
|
|
499
|
+
return t("usageResetDays", { days: Math.round(hours / 24) });
|
|
500
|
+
}
|
|
501
|
+
function barLevel(window) {
|
|
502
|
+
if (window.status === "rate-limited" || window.percent >= 100) return "limited";
|
|
503
|
+
return window.percent >= 80 ? "high" : "ok";
|
|
504
|
+
}
|
|
505
|
+
function stampText(at, locale) {
|
|
506
|
+
const date = new Date(at);
|
|
507
|
+
const time = date.toLocaleTimeString(locale, { hour: "2-digit", minute: "2-digit" });
|
|
508
|
+
return date.toDateString() === (/* @__PURE__ */ new Date()).toDateString() ? time : `${date.toLocaleDateString(locale)} ${time}`;
|
|
509
|
+
}
|
|
510
|
+
function GripIcon() {
|
|
511
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("svg", { width: "10", height: "14", viewBox: "0 0 10 14", fill: "currentColor", "aria-hidden": "true", children: [
|
|
512
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("circle", { cx: "2.5", cy: "2.5", r: "1.3" }),
|
|
513
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("circle", { cx: "7.5", cy: "2.5", r: "1.3" }),
|
|
514
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("circle", { cx: "2.5", cy: "7", r: "1.3" }),
|
|
515
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("circle", { cx: "7.5", cy: "7", r: "1.3" }),
|
|
516
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("circle", { cx: "2.5", cy: "11.5", r: "1.3" }),
|
|
517
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("circle", { cx: "7.5", cy: "11.5", r: "1.3" })
|
|
518
|
+
] });
|
|
519
|
+
}
|
|
520
|
+
function slotAt(container, clientY) {
|
|
521
|
+
const rows = container.querySelectorAll("[data-account-row]");
|
|
522
|
+
for (let index = 0; index < rows.length; index++) {
|
|
523
|
+
const box = rows[index].getBoundingClientRect();
|
|
524
|
+
if (clientY < box.top + box.height / 2) return index;
|
|
525
|
+
}
|
|
526
|
+
return rows.length;
|
|
527
|
+
}
|
|
528
|
+
function AccountsCard({ state, actions, writable, t, locale }) {
|
|
529
|
+
const [open, setOpen] = (0, import_react2.useState)(false);
|
|
530
|
+
const [details, setDetails] = (0, import_react2.useState)(null);
|
|
531
|
+
const [dragging, setDragging] = (0, import_react2.useState)(null);
|
|
532
|
+
const [dropAt, setDropAt] = (0, import_react2.useState)(null);
|
|
533
|
+
const [editor, setEditor] = (0, import_react2.useState)(null);
|
|
534
|
+
const [name, setName] = (0, import_react2.useState)("");
|
|
535
|
+
const [key, setKey] = (0, import_react2.useState)("");
|
|
536
|
+
const disabled = state.busy || state.blocked || !writable;
|
|
537
|
+
const total = state.entries.length;
|
|
538
|
+
const ready = state.entries.filter((entry) => entry.configured === true).length;
|
|
539
|
+
const unreadable = state.entries.filter((entry) => entry.failed === true).length;
|
|
540
|
+
const preferred = state.entries.find((entry) => entry.apiKeyEnv === state.activeRef);
|
|
541
|
+
const reorderable = !disabled && total > 1;
|
|
542
|
+
const draggingFrom = dragging === null ? -1 : state.entries.findIndex((entry) => entry.apiKeyEnv === dragging);
|
|
543
|
+
const noopSlot = draggingFrom >= 0 && (dropAt === draggingFrom || dropAt === draggingFrom + 1);
|
|
544
|
+
const markAt = (index) => {
|
|
545
|
+
if (!reorderable || dropAt === null || noopSlot) return void 0;
|
|
546
|
+
if (dropAt === index) return "before";
|
|
547
|
+
return dropAt === total && index === total - 1 ? "after" : void 0;
|
|
548
|
+
};
|
|
549
|
+
const updatedAt = state.entries.reduce((latest, entry) => Math.max(latest, entry.updatedAt ?? 0), 0);
|
|
550
|
+
(0, import_react2.useEffect)(() => {
|
|
551
|
+
actions.loadAccounts();
|
|
552
|
+
const timer = setInterval(() => {
|
|
553
|
+
if (document.visibilityState !== "hidden") actions.loadAccounts();
|
|
554
|
+
}, 6e4);
|
|
555
|
+
return () => {
|
|
556
|
+
clearInterval(timer);
|
|
557
|
+
};
|
|
558
|
+
}, [actions.loadAccounts]);
|
|
559
|
+
const start = (next, label = "") => {
|
|
560
|
+
setEditor(next);
|
|
561
|
+
setName(label);
|
|
562
|
+
setKey("");
|
|
563
|
+
};
|
|
564
|
+
const cancel = () => {
|
|
565
|
+
setEditor(null);
|
|
566
|
+
setName("");
|
|
567
|
+
setKey("");
|
|
568
|
+
};
|
|
569
|
+
(0, import_react2.useEffect)(() => {
|
|
570
|
+
if (editor?.ref != null && !state.entries.some((entry) => entry.apiKeyEnv === editor.ref)) cancel();
|
|
571
|
+
}, [state.entries, editor]);
|
|
572
|
+
(0, import_react2.useEffect)(() => {
|
|
573
|
+
if (dragging !== null && !state.entries.some((entry) => entry.apiKeyEnv === dragging)) {
|
|
574
|
+
setDragging(null);
|
|
575
|
+
setDropAt(null);
|
|
576
|
+
}
|
|
577
|
+
}, [state.entries, dragging]);
|
|
578
|
+
const submit = async () => {
|
|
579
|
+
if (!editor) return;
|
|
580
|
+
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);
|
|
581
|
+
if (accepted) cancel();
|
|
582
|
+
};
|
|
583
|
+
const move = (ref, toIndex) => {
|
|
584
|
+
void actions.moveAccount(ref, toIndex);
|
|
585
|
+
};
|
|
586
|
+
const summary = total ? t("accountsSummary", { count: total, name: preferred ? preferred.name || t("accountDefault") : "" }) : t("accountsSummaryEmpty");
|
|
587
|
+
const editorTitle = (kind) => t(kind === "add" ? "accountAdd" : kind === "rename" ? "accountRename" : kind === "key" ? "accountReplaceKey" : "accountRemove");
|
|
588
|
+
const editorForm = (label = "") => editor ? /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
|
|
589
|
+
"form",
|
|
590
|
+
{
|
|
591
|
+
className: Section_default.accountEditor,
|
|
592
|
+
onSubmit: (event) => {
|
|
593
|
+
event.preventDefault();
|
|
594
|
+
void submit();
|
|
595
|
+
},
|
|
596
|
+
onKeyDown: (event) => {
|
|
597
|
+
if (event.key === "Escape") {
|
|
598
|
+
event.preventDefault();
|
|
599
|
+
cancel();
|
|
600
|
+
}
|
|
601
|
+
},
|
|
602
|
+
children: [
|
|
603
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: Section_default.accountEditorHead, children: [
|
|
604
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: Section_default.accountEditorTitle, children: editorTitle(editor.kind) }),
|
|
605
|
+
label ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: Section_default.accountEditorFor, children: label }) : null
|
|
606
|
+
] }),
|
|
607
|
+
editor.kind === "remove" ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: Section_default.hint, children: t("accountRemoveHint", { name }) }) : null,
|
|
608
|
+
editor.kind === "add" || editor.kind === "rename" ? /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("label", { className: Section_default.accountField, children: [
|
|
609
|
+
t("accountName"),
|
|
610
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
611
|
+
"input",
|
|
612
|
+
{
|
|
613
|
+
className: Section_default.input,
|
|
614
|
+
value: name,
|
|
615
|
+
maxLength: 80,
|
|
616
|
+
required: true,
|
|
617
|
+
disabled: state.busy,
|
|
618
|
+
autoFocus: true,
|
|
619
|
+
onChange: (event) => {
|
|
620
|
+
setName(event.target.value);
|
|
621
|
+
}
|
|
622
|
+
}
|
|
623
|
+
)
|
|
624
|
+
] }) : null,
|
|
625
|
+
editor.kind === "add" || editor.kind === "key" ? /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
|
|
626
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("label", { className: Section_default.accountField, children: [
|
|
627
|
+
t("keyLabel"),
|
|
628
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
629
|
+
"input",
|
|
630
|
+
{
|
|
631
|
+
className: Section_default.input,
|
|
632
|
+
type: "password",
|
|
633
|
+
autoComplete: "off",
|
|
634
|
+
value: key,
|
|
635
|
+
required: true,
|
|
636
|
+
disabled: state.busy,
|
|
637
|
+
autoFocus: true,
|
|
638
|
+
onChange: (event) => {
|
|
639
|
+
setKey(event.target.value);
|
|
640
|
+
}
|
|
641
|
+
}
|
|
642
|
+
)
|
|
643
|
+
] }),
|
|
644
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: Section_default.hint, children: t("accountKeyHint") })
|
|
645
|
+
] }) : null,
|
|
646
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: Section_default.accountEditorActions, children: [
|
|
647
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
648
|
+
import_dsh_client_ui_primitives2.Button,
|
|
649
|
+
{
|
|
650
|
+
variant: "primary",
|
|
651
|
+
size: "sm",
|
|
652
|
+
type: "submit",
|
|
653
|
+
disabled: editor.kind === "key" ? state.busy || state.blocked : disabled,
|
|
654
|
+
children: t(state.busy ? "saving" : "accountConfirm")
|
|
655
|
+
}
|
|
656
|
+
),
|
|
657
|
+
/* @__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") })
|
|
658
|
+
] })
|
|
659
|
+
]
|
|
660
|
+
}
|
|
661
|
+
) : null;
|
|
662
|
+
const detail = (account, label) => /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: Section_default.accountDetail, children: [
|
|
663
|
+
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: [
|
|
664
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { children: [
|
|
665
|
+
t(`usage_${window}`),
|
|
666
|
+
" \xB7 ",
|
|
667
|
+
account.usage[window].percent,
|
|
668
|
+
"%"
|
|
669
|
+
] }),
|
|
670
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
671
|
+
"progress",
|
|
672
|
+
{
|
|
673
|
+
"data-level": barLevel(account.usage[window]),
|
|
674
|
+
max: 100,
|
|
675
|
+
value: Math.min(100, account.usage[window].percent),
|
|
676
|
+
"aria-label": `${label} ${t(`usage_${window}`)}`
|
|
677
|
+
}
|
|
678
|
+
),
|
|
679
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: Section_default.hint, children: [
|
|
680
|
+
t("usageResets"),
|
|
681
|
+
" ",
|
|
682
|
+
new Date(account.usage[window].resetsAt).toLocaleString(locale)
|
|
683
|
+
] })
|
|
684
|
+
] }, window)) }) : /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: Section_default.hint, children: t(account.loading ? "usageLoading" : "usageUnavailable") }),
|
|
685
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: Section_default.accountActions, children: [
|
|
686
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_dsh_client_ui_primitives2.Button, { variant: "outline", size: "sm", disabled, onClick: () => {
|
|
687
|
+
start({ kind: "rename", ref: account.apiKeyEnv }, label);
|
|
688
|
+
}, children: t("accountRename") }),
|
|
689
|
+
/* @__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: () => {
|
|
690
|
+
start({ kind: "key", ref: account.apiKeyEnv }, label);
|
|
691
|
+
}, children: t("accountReplaceKey") }),
|
|
692
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_dsh_client_ui_primitives2.Button, { variant: "outline", size: "sm", disabled, onClick: () => {
|
|
693
|
+
start({ kind: "remove", ref: account.apiKeyEnv }, label);
|
|
694
|
+
}, children: t("accountRemove") })
|
|
695
|
+
] })
|
|
696
|
+
] });
|
|
697
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("section", { className: open ? Section_default.card : Section_default.card + " " + Section_default.cardFolded, children: [
|
|
698
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: Section_default.cardHead, children: [
|
|
699
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
|
|
700
|
+
"button",
|
|
701
|
+
{
|
|
702
|
+
type: "button",
|
|
703
|
+
className: Section_default.cardTrigger,
|
|
704
|
+
"aria-expanded": open,
|
|
705
|
+
"aria-controls": "opencode-go-accounts",
|
|
706
|
+
onClick: () => {
|
|
707
|
+
setOpen(!open);
|
|
708
|
+
},
|
|
709
|
+
children: [
|
|
710
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: Section_default.cardTitle, children: t("accountsTitle") }),
|
|
711
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: Section_default.cardSub, children: summary }),
|
|
712
|
+
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,
|
|
713
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(ChevronDown, { className: open ? Section_default.chevronOpen : Section_default.chevron })
|
|
714
|
+
]
|
|
715
|
+
}
|
|
716
|
+
),
|
|
717
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: Section_default.trailing, children: [
|
|
718
|
+
updatedAt > 0 ? /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: Section_default.cardStamp, title: new Date(updatedAt).toLocaleString(locale), children: [
|
|
719
|
+
t("usageLastUpdated"),
|
|
720
|
+
" ",
|
|
721
|
+
stampText(updatedAt, locale)
|
|
722
|
+
] }) : null,
|
|
723
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
724
|
+
import_dsh_client_ui_primitives2.Button,
|
|
725
|
+
{
|
|
726
|
+
variant: "outline",
|
|
727
|
+
size: "sm",
|
|
728
|
+
disabled: state.refreshing,
|
|
729
|
+
onClick: actions.loadAccounts,
|
|
730
|
+
children: t(state.refreshing ? "usageRefreshing" : "accountsRefresh")
|
|
731
|
+
}
|
|
732
|
+
)
|
|
733
|
+
] })
|
|
734
|
+
] }),
|
|
735
|
+
open ? /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { id: "opencode-go-accounts", className: Section_default.cardBody, children: [
|
|
736
|
+
state.blocked ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: Section_default.hint, children: t("accountsBlocked") }) : null,
|
|
737
|
+
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,
|
|
738
|
+
!total ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: Section_default.hint, children: t("accountsEmpty") }) : null,
|
|
739
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
740
|
+
"div",
|
|
741
|
+
{
|
|
742
|
+
className: Section_default.accounts,
|
|
743
|
+
onDragEnter: (event) => {
|
|
744
|
+
if (reorderable && dragging !== null) event.preventDefault();
|
|
745
|
+
},
|
|
746
|
+
onDragOver: (event) => {
|
|
747
|
+
if (!reorderable || dragging === null) return;
|
|
748
|
+
event.preventDefault();
|
|
749
|
+
if (event.dataTransfer) event.dataTransfer.dropEffect = "move";
|
|
750
|
+
setDropAt(slotAt(event.currentTarget, event.clientY));
|
|
751
|
+
},
|
|
752
|
+
onDrop: (event) => {
|
|
753
|
+
const source = dragging;
|
|
754
|
+
setDragging(null);
|
|
755
|
+
setDropAt(null);
|
|
756
|
+
if (source === null) return;
|
|
757
|
+
event.preventDefault();
|
|
758
|
+
const from = state.entries.findIndex((entry) => entry.apiKeyEnv === source);
|
|
759
|
+
if (from < 0) return;
|
|
760
|
+
const slot = Number.isFinite(event.clientY) ? slotAt(event.currentTarget, event.clientY) : dropAt;
|
|
761
|
+
if (slot === null) return;
|
|
762
|
+
const to = slot > from ? slot - 1 : slot;
|
|
763
|
+
if (to !== from) move(source, to);
|
|
764
|
+
},
|
|
765
|
+
onDragEnd: () => {
|
|
766
|
+
setDragging(null);
|
|
767
|
+
setDropAt(null);
|
|
768
|
+
},
|
|
769
|
+
children: state.entries.map((account, index) => {
|
|
770
|
+
const label = account.name || t("accountDefault");
|
|
771
|
+
const rolling = account.usage?.rolling;
|
|
772
|
+
const expanded = details === account.apiKeyEnv;
|
|
773
|
+
const panelId = `opencode-go-account-${index}`;
|
|
774
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_react2.Fragment, { children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
|
|
775
|
+
"div",
|
|
776
|
+
{
|
|
777
|
+
className: Section_default.accountRow,
|
|
778
|
+
"data-account-row": account.apiKeyEnv,
|
|
779
|
+
"data-dragging": dragging === account.apiKeyEnv ? "true" : void 0,
|
|
780
|
+
"data-drop": markAt(index),
|
|
781
|
+
onDragStart: (event) => {
|
|
782
|
+
if (!reorderable || event.target?.closest?.("[data-account-handle]") == null) {
|
|
783
|
+
event.preventDefault();
|
|
784
|
+
return;
|
|
785
|
+
}
|
|
786
|
+
if (event.dataTransfer) {
|
|
787
|
+
event.dataTransfer.effectAllowed = "move";
|
|
788
|
+
event.dataTransfer.setData("text/plain", account.apiKeyEnv);
|
|
789
|
+
if (typeof event.dataTransfer.setDragImage === "function") {
|
|
790
|
+
event.dataTransfer.setDragImage(event.currentTarget, 16, 16);
|
|
791
|
+
}
|
|
792
|
+
}
|
|
793
|
+
setDragging(account.apiKeyEnv);
|
|
794
|
+
},
|
|
795
|
+
children: [
|
|
796
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: Section_default.accountMain, "data-account-main": "", children: [
|
|
797
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
798
|
+
"button",
|
|
799
|
+
{
|
|
800
|
+
type: "button",
|
|
801
|
+
className: Section_default.accountHandle,
|
|
802
|
+
"data-account-handle": "",
|
|
803
|
+
draggable: reorderable,
|
|
804
|
+
disabled: !reorderable,
|
|
805
|
+
title: t("accountDragHandle", { name: label }),
|
|
806
|
+
"aria-label": t("accountDragHandle", { name: label }),
|
|
807
|
+
onKeyDown: (event) => {
|
|
808
|
+
if (event.key === "ArrowUp" && index > 0) {
|
|
809
|
+
event.preventDefault();
|
|
810
|
+
move(account.apiKeyEnv, index - 1);
|
|
811
|
+
}
|
|
812
|
+
if (event.key === "ArrowDown" && index < total - 1) {
|
|
813
|
+
event.preventDefault();
|
|
814
|
+
move(account.apiKeyEnv, index + 1);
|
|
815
|
+
}
|
|
816
|
+
},
|
|
817
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(GripIcon, {})
|
|
818
|
+
}
|
|
819
|
+
),
|
|
820
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("strong", { className: Section_default.accountName, title: label, children: label }),
|
|
821
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: Section_default.accountState, children: [
|
|
822
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: Section_default.accountDot, "data-off": account.configured === false ? "true" : void 0 }),
|
|
823
|
+
account.configured === void 0 ? t(account.failed ? "accountsStatusUnknown" : "usageLoading") : account.configured ? t("keyConfigured") : t("keyMissing")
|
|
824
|
+
] }),
|
|
825
|
+
rolling ? /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
|
|
826
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
|
|
827
|
+
"span",
|
|
828
|
+
{
|
|
829
|
+
className: Section_default.accountBar,
|
|
830
|
+
role: "progressbar",
|
|
831
|
+
"data-level": barLevel(rolling),
|
|
832
|
+
"aria-valuemin": 0,
|
|
833
|
+
"aria-valuemax": 100,
|
|
834
|
+
"aria-valuenow": Math.min(100, rolling.percent),
|
|
835
|
+
"aria-label": `${label} ${t("usage_rolling")}`,
|
|
836
|
+
children: [
|
|
837
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: Section_default.accountBarFill, style: { width: `${Math.min(100, rolling.percent)}%` } }),
|
|
838
|
+
TICKS.map((at) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: Section_default.accountBarTick, style: { left: `${at}%` } }, at))
|
|
839
|
+
]
|
|
840
|
+
}
|
|
841
|
+
),
|
|
842
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: Section_default.accountPercent, children: [
|
|
843
|
+
rolling.percent,
|
|
844
|
+
"%"
|
|
845
|
+
] }),
|
|
846
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: Section_default.accountReset, children: resetText(rolling.resetsAt, t) })
|
|
847
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: Section_default.accountIdle, children: account.configured === false ? t("accountConfigureHint") : t(account.loading ? "usageLoading" : "usageUnavailable") }),
|
|
848
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
849
|
+
"button",
|
|
850
|
+
{
|
|
851
|
+
type: "button",
|
|
852
|
+
className: Section_default.accountToggle,
|
|
853
|
+
"aria-expanded": expanded,
|
|
854
|
+
"aria-controls": panelId,
|
|
855
|
+
"aria-label": t(expanded ? "accountsDetailsHide" : "accountsDetails", { name: label }),
|
|
856
|
+
onClick: () => {
|
|
857
|
+
setDetails(expanded ? null : account.apiKeyEnv);
|
|
858
|
+
},
|
|
859
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(ChevronDown, { className: expanded ? Section_default.chevronOpen : Section_default.chevron })
|
|
860
|
+
}
|
|
861
|
+
)
|
|
862
|
+
] }),
|
|
863
|
+
account.failed ? /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: Section_default.accountProblems, role: "alert", children: [
|
|
864
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: Section_default.failedNote, children: account.problem ?? t(account.stale ? "usageStaleHint" : "usageRefreshFailed") }),
|
|
865
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
866
|
+
"button",
|
|
867
|
+
{
|
|
868
|
+
type: "button",
|
|
869
|
+
className: Section_default.accountRetry,
|
|
870
|
+
disabled: state.refreshing,
|
|
871
|
+
onClick: actions.loadAccounts,
|
|
872
|
+
children: t("usageRetry")
|
|
873
|
+
}
|
|
874
|
+
)
|
|
875
|
+
] }) : null,
|
|
876
|
+
expanded ? detail(account, label) : null,
|
|
877
|
+
editor?.ref === account.apiKeyEnv ? editorForm(label) : null
|
|
878
|
+
]
|
|
879
|
+
}
|
|
880
|
+
) }, account.id);
|
|
881
|
+
})
|
|
882
|
+
}
|
|
883
|
+
),
|
|
884
|
+
editor ? editor.kind === "add" ? editorForm() : null : /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
885
|
+
import_dsh_client_ui_primitives2.Button,
|
|
886
|
+
{
|
|
887
|
+
variant: "outline",
|
|
888
|
+
size: "sm",
|
|
889
|
+
disabled: disabled || total >= MAX_ACCOUNTS,
|
|
890
|
+
onClick: () => {
|
|
891
|
+
start({ kind: "add" });
|
|
892
|
+
},
|
|
893
|
+
children: t("accountAdd")
|
|
894
|
+
}
|
|
895
|
+
),
|
|
896
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: Section_default.field, children: [
|
|
897
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: Section_default.head, children: [
|
|
898
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: Section_default.label, children: t("accountAutoSwitch") }),
|
|
899
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
900
|
+
import_dsh_client_ui_primitives2.Switch,
|
|
901
|
+
{
|
|
902
|
+
checked: state.autoSwitch,
|
|
903
|
+
disabled,
|
|
904
|
+
label: t("accountAutoSwitch"),
|
|
905
|
+
onChange: (next) => {
|
|
906
|
+
void actions.setAutoSwitch(next);
|
|
907
|
+
}
|
|
908
|
+
}
|
|
909
|
+
)
|
|
910
|
+
] }),
|
|
911
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: Section_default.hint, children: t("accountAutoSwitchHint") })
|
|
912
|
+
] })
|
|
913
|
+
] }) : null
|
|
914
|
+
] });
|
|
915
|
+
}
|
|
377
916
|
|
|
378
917
|
// src/usage-display.ts
|
|
379
918
|
var USAGE_DISPLAY_MODES = ["auto", "always", "off"];
|
|
380
919
|
var DEFAULT_USAGE_DISPLAY = "auto";
|
|
381
920
|
|
|
382
921
|
// src/client/Section.tsx
|
|
383
|
-
var
|
|
384
|
-
var
|
|
922
|
+
var import_jsx_runtime3 = require("react/jsx-runtime");
|
|
923
|
+
var ChevronDown2 = primitives2.IconChevronDownOutlineRegular ?? primitives2.IconChevronDownOutline14;
|
|
385
924
|
function ValueField(props) {
|
|
386
925
|
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,
|
|
926
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: Section_default.field, children: [
|
|
927
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: Section_default.head, children: [
|
|
928
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("label", { className: Section_default.label, htmlFor: props.id, children: props.label }),
|
|
929
|
+
props.field.overridden ? /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("span", { className: Section_default.badges, children: [
|
|
930
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_dsh_client_ui_primitives3.Tag, { tone: "neutral", children: props.overriddenLabel }),
|
|
931
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
393
932
|
"button",
|
|
394
933
|
{
|
|
395
934
|
type: "button",
|
|
@@ -401,7 +940,7 @@ function ValueField(props) {
|
|
|
401
940
|
)
|
|
402
941
|
] }) : null
|
|
403
942
|
] }),
|
|
404
|
-
props.options ? /* @__PURE__ */ (0,
|
|
943
|
+
props.options ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
405
944
|
"select",
|
|
406
945
|
{
|
|
407
946
|
id: props.id,
|
|
@@ -414,14 +953,15 @@ function ValueField(props) {
|
|
|
414
953
|
onChange: (event) => {
|
|
415
954
|
props.onEdit(event.target.value);
|
|
416
955
|
},
|
|
417
|
-
children: props.options.map((option) => /* @__PURE__ */ (0,
|
|
956
|
+
children: props.options.map((option) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("option", { value: option.value, children: option.label }, option.value))
|
|
418
957
|
}
|
|
419
|
-
) : /* @__PURE__ */ (0,
|
|
958
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
420
959
|
"input",
|
|
421
960
|
{
|
|
422
961
|
id: props.id,
|
|
423
962
|
name: props.id,
|
|
424
963
|
autoComplete: "off",
|
|
964
|
+
placeholder: props.placeholder,
|
|
425
965
|
"aria-describedby": hintId,
|
|
426
966
|
className: props.field.invalid ? Section_default.inputInvalid : Section_default.input,
|
|
427
967
|
type: props.numeric === true ? "number" : "text",
|
|
@@ -434,7 +974,7 @@ function ValueField(props) {
|
|
|
434
974
|
}
|
|
435
975
|
}
|
|
436
976
|
),
|
|
437
|
-
/* @__PURE__ */ (0,
|
|
977
|
+
/* @__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
978
|
] });
|
|
439
979
|
}
|
|
440
980
|
function ModelsBody({ models, t, locale }) {
|
|
@@ -442,39 +982,46 @@ function ModelsBody({ models, t, locale }) {
|
|
|
442
982
|
const metadataOnlyFailure = sources?.metadata.error !== void 0 && sources.listing.error === void 0;
|
|
443
983
|
const sourceStatus = sources ? ["listing", "metadata"].map((source) => {
|
|
444
984
|
const status = sources[source];
|
|
445
|
-
return /* @__PURE__ */ (0,
|
|
985
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("p", { className: Section_default.hint, children: [
|
|
446
986
|
t(source === "listing" ? "modelsListingSource" : "modelsMetadataSource"),
|
|
447
987
|
": ",
|
|
448
988
|
" ",
|
|
449
989
|
status.error ? t("modelsSourceFailed") : t("modelsSourceCurrent"),
|
|
450
990
|
". ",
|
|
451
991
|
" ",
|
|
452
|
-
status.updatedAt === void 0 ? t("modelsSourceNeverFetched") : t("modelsSourceUpdated", { time: new Date(status.updatedAt).toLocaleString(locale) })
|
|
992
|
+
status.updatedAt === void 0 ? t("modelsSourceNeverFetched") : t("modelsSourceUpdated", { time: new Date(status.updatedAt).toLocaleString(locale) }),
|
|
993
|
+
status.warning ? /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
|
|
994
|
+
" ",
|
|
995
|
+
status.warning
|
|
996
|
+
] }) : null
|
|
453
997
|
] }, source);
|
|
454
998
|
}) : null;
|
|
455
999
|
if (models.status === "failed") {
|
|
456
|
-
return /* @__PURE__ */ (0,
|
|
457
|
-
/* @__PURE__ */ (0,
|
|
458
|
-
models.message ? /* @__PURE__ */ (0,
|
|
1000
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
|
|
1001
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { className: Section_default.failedNote, role: "alert", children: t(metadataOnlyFailure ? "modelsMetadataFailed" : "modelsFailed") }),
|
|
1002
|
+
models.message ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { className: Section_default.hint, children: models.message }) : null,
|
|
459
1003
|
sourceStatus
|
|
460
1004
|
] });
|
|
461
1005
|
}
|
|
462
|
-
if (models.status !== "ready") return /* @__PURE__ */ (0,
|
|
463
|
-
const progress = models.refreshing ? /* @__PURE__ */ (0,
|
|
464
|
-
if (models.stale) return /* @__PURE__ */ (0,
|
|
1006
|
+
if (models.status !== "ready") return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { className: Section_default.hint, role: "status", "aria-live": "polite", children: t("modelsLoading") });
|
|
1007
|
+
const progress = models.refreshing ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { className: Section_default.hint, role: "status", children: t("modelsRefreshing") }) : null;
|
|
1008
|
+
if (models.stale) return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
|
|
465
1009
|
progress,
|
|
466
|
-
/* @__PURE__ */ (0,
|
|
467
|
-
models.message ? /* @__PURE__ */ (0,
|
|
1010
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { className: Section_default.failedNote, role: "alert", children: t(metadataOnlyFailure ? "modelsMetadataFailed" : "modelsStale") }),
|
|
1011
|
+
models.message ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { className: Section_default.hint, children: models.message }) : null,
|
|
468
1012
|
sourceStatus
|
|
469
1013
|
] });
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
1014
|
+
const warning = sources?.listing.warning ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { className: Section_default.failedNote, role: "alert", children: sources.listing.warning }) : null;
|
|
1015
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
|
|
1016
|
+
progress,
|
|
1017
|
+
warning,
|
|
1018
|
+
models.count === 0 ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { className: Section_default.hint, children: t("modelsEmpty") }) : null
|
|
1019
|
+
] });
|
|
473
1020
|
}
|
|
474
1021
|
function OpencodeGoSection(props) {
|
|
475
1022
|
const { useOpencodeGo, edit, resetField, save, discard, loadModels, setEnabled, setModelEnabled, t } = props;
|
|
476
1023
|
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,
|
|
1024
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
478
1025
|
Loaded,
|
|
479
1026
|
{
|
|
480
1027
|
state: useOpencodeGo((snapshot) => snapshot),
|
|
@@ -486,43 +1033,63 @@ function OpencodeGoSection(props) {
|
|
|
486
1033
|
discard,
|
|
487
1034
|
loadModels,
|
|
488
1035
|
setEnabled,
|
|
489
|
-
setModelEnabled
|
|
1036
|
+
setModelEnabled,
|
|
1037
|
+
accountActions: props.loadAccounts && props.addAccount && props.renameAccount && props.removeAccount && props.selectAccount && props.setAutoSwitch && props.replaceAccountKey && props.moveAccount ? {
|
|
1038
|
+
loadAccounts: props.loadAccounts,
|
|
1039
|
+
addAccount: props.addAccount,
|
|
1040
|
+
renameAccount: props.renameAccount,
|
|
1041
|
+
removeAccount: props.removeAccount,
|
|
1042
|
+
selectAccount: props.selectAccount,
|
|
1043
|
+
setAutoSwitch: props.setAutoSwitch,
|
|
1044
|
+
replaceAccountKey: props.replaceAccountKey,
|
|
1045
|
+
moveAccount: props.moveAccount
|
|
1046
|
+
} : void 0
|
|
490
1047
|
}
|
|
491
1048
|
);
|
|
492
1049
|
}
|
|
493
1050
|
function Loaded(props) {
|
|
494
1051
|
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,
|
|
1052
|
+
const [advanced, setAdvanced] = (0, import_react3.useState)(false);
|
|
1053
|
+
const [modelsOpen, setModelsOpen] = (0, import_react3.useState)(false);
|
|
1054
|
+
const modelNotices = /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
|
|
1055
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(ModelsBody, { models: state.models, t, locale: props.locale }),
|
|
1056
|
+
state.pickerFailed ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { className: Section_default.failedNote, role: "alert", children: t("pickerFailed") }) : null
|
|
500
1057
|
] });
|
|
501
|
-
(0,
|
|
1058
|
+
(0, import_react3.useEffect)(() => {
|
|
502
1059
|
if (state.available && state.models.status === "idle") loadModels();
|
|
503
1060
|
}, [state.available, state.models.status, loadModels]);
|
|
504
1061
|
if (!state.available) {
|
|
505
|
-
return /* @__PURE__ */ (0,
|
|
1062
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { className: Section_default.intro, children: t("unavailable") });
|
|
506
1063
|
}
|
|
507
1064
|
const disabled = !state.writable;
|
|
1065
|
+
const accountCard = state.accounts && props.accountActions ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
1066
|
+
AccountsCard,
|
|
1067
|
+
{
|
|
1068
|
+
state: state.accounts,
|
|
1069
|
+
actions: props.accountActions,
|
|
1070
|
+
writable: state.writable,
|
|
1071
|
+
t,
|
|
1072
|
+
locale: props.locale
|
|
1073
|
+
}
|
|
1074
|
+
) : null;
|
|
508
1075
|
const fieldProps = {
|
|
509
1076
|
invalidLabel: t("invalidValue"),
|
|
510
1077
|
overriddenLabel: t("overridden"),
|
|
511
1078
|
resetLabel: t("reset"),
|
|
512
1079
|
disabled
|
|
513
1080
|
};
|
|
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,
|
|
1081
|
+
const advancedOverridden = state.usageDisplay.overridden || state.protocolOverrides.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;
|
|
1082
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: Section_default.page, children: [
|
|
1083
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: Section_default.pageBody, children: [
|
|
1084
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: Section_default.pageTop, children: [
|
|
1085
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("h2", { className: Section_default.title, children: t("titleLabel") }),
|
|
1086
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { className: Section_default.intro, children: t("intro") })
|
|
520
1087
|
] }),
|
|
521
|
-
/* @__PURE__ */ (0,
|
|
522
|
-
/* @__PURE__ */ (0,
|
|
523
|
-
/* @__PURE__ */ (0,
|
|
524
|
-
/* @__PURE__ */ (0,
|
|
525
|
-
|
|
1088
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("section", { className: Section_default.card, children: [
|
|
1089
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: Section_default.cardHead, children: [
|
|
1090
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("h3", { className: Section_default.cardTitle, children: t("enabledLabel") }),
|
|
1091
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
1092
|
+
import_dsh_client_ui_primitives3.Switch,
|
|
526
1093
|
{
|
|
527
1094
|
checked: state.enabled,
|
|
528
1095
|
label: t("enabledLabel"),
|
|
@@ -531,38 +1098,41 @@ function Loaded(props) {
|
|
|
531
1098
|
}
|
|
532
1099
|
)
|
|
533
1100
|
] }),
|
|
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
|
-
|
|
1101
|
+
/* @__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") }) }),
|
|
1102
|
+
accountCard ? null : /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
|
|
1103
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: Section_default.cardDivider }),
|
|
1104
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: Section_default.cardHead, children: [
|
|
1105
|
+
/* @__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: [
|
|
1106
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("circle", { cx: "5.4", cy: "8", r: "3.1" }),
|
|
1107
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("path", { d: "M8.5 8h5.3M11.9 8v2.2M10.2 8v1.6" })
|
|
1108
|
+
] }) }),
|
|
1109
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("label", { className: Section_default.label, htmlFor: "opencode-go-key", children: t("keyLabel") }),
|
|
1110
|
+
/* @__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") }) })
|
|
1111
|
+
] }),
|
|
1112
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: Section_default.cardBody, children: [
|
|
1113
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
1114
|
+
"input",
|
|
1115
|
+
{
|
|
1116
|
+
id: "opencode-go-key",
|
|
1117
|
+
name: "api-key",
|
|
1118
|
+
className: Section_default.input,
|
|
1119
|
+
type: "password",
|
|
1120
|
+
autoComplete: "off",
|
|
1121
|
+
"aria-describedby": "opencode-go-key-hint",
|
|
1122
|
+
value: state.apiKey.text,
|
|
1123
|
+
disabled: !state.apiKeyWritable,
|
|
1124
|
+
onChange: (event) => {
|
|
1125
|
+
props.edit("apiKey", event.target.value);
|
|
1126
|
+
}
|
|
558
1127
|
}
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
1128
|
+
),
|
|
1129
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { id: "opencode-go-key-hint", className: Section_default.hint, children: state.apiKeyWritable ? t("keyHint") : t("keyNotWritable") })
|
|
1130
|
+
] })
|
|
562
1131
|
] })
|
|
563
1132
|
] }),
|
|
564
|
-
|
|
565
|
-
|
|
1133
|
+
accountCard,
|
|
1134
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("section", { className: modelsOpen ? Section_default.cardModels : Section_default.cardModels + " " + Section_default.cardFolded, children: [
|
|
1135
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
566
1136
|
"button",
|
|
567
1137
|
{
|
|
568
1138
|
type: "button",
|
|
@@ -573,14 +1143,14 @@ function Loaded(props) {
|
|
|
573
1143
|
setModelsOpen(!modelsOpen);
|
|
574
1144
|
},
|
|
575
1145
|
children: [
|
|
576
|
-
/* @__PURE__ */ (0,
|
|
577
|
-
/* @__PURE__ */ (0,
|
|
1146
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: Section_default.cardTitle, children: t("modelsLabel") }),
|
|
1147
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(ChevronDown2, { className: modelsOpen ? Section_default.chevronOpen : Section_default.chevron })
|
|
578
1148
|
]
|
|
579
1149
|
}
|
|
580
1150
|
),
|
|
581
|
-
modelsOpen ? /* @__PURE__ */ (0,
|
|
1151
|
+
modelsOpen ? /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { id: "opencode-go-models", className: Section_default.cardBody, children: [
|
|
582
1152
|
modelNotices,
|
|
583
|
-
/* @__PURE__ */ (0,
|
|
1153
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
584
1154
|
ModelEditor,
|
|
585
1155
|
{
|
|
586
1156
|
models: state.models,
|
|
@@ -590,8 +1160,8 @@ function Loaded(props) {
|
|
|
590
1160
|
disabled: disabled || state.saving,
|
|
591
1161
|
modelVisibility: state.modelVisibility,
|
|
592
1162
|
visibilitySaving: state.pickerSaving,
|
|
593
|
-
filterAction: /* @__PURE__ */ (0,
|
|
594
|
-
|
|
1163
|
+
filterAction: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
1164
|
+
import_dsh_client_ui_primitives3.Button,
|
|
595
1165
|
{
|
|
596
1166
|
variant: "outline",
|
|
597
1167
|
size: "sm",
|
|
@@ -606,10 +1176,10 @@ function Loaded(props) {
|
|
|
606
1176
|
}
|
|
607
1177
|
}
|
|
608
1178
|
)
|
|
609
|
-
] }) : /* @__PURE__ */ (0,
|
|
1179
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: Section_default.cardNotes, children: modelNotices })
|
|
610
1180
|
] }),
|
|
611
|
-
/* @__PURE__ */ (0,
|
|
612
|
-
/* @__PURE__ */ (0,
|
|
1181
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("section", { className: Section_default.card, children: [
|
|
1182
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
613
1183
|
"button",
|
|
614
1184
|
{
|
|
615
1185
|
type: "button",
|
|
@@ -620,17 +1190,17 @@ function Loaded(props) {
|
|
|
620
1190
|
setAdvanced(!advanced);
|
|
621
1191
|
},
|
|
622
1192
|
children: [
|
|
623
|
-
/* @__PURE__ */ (0,
|
|
624
|
-
/* @__PURE__ */ (0,
|
|
625
|
-
advancedOverridden ? /* @__PURE__ */ (0,
|
|
626
|
-
/* @__PURE__ */ (0,
|
|
1193
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: Section_default.cardTitle, children: t("advancedLabel") }),
|
|
1194
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: Section_default.cardSub, children: t("advancedSummary") }),
|
|
1195
|
+
advancedOverridden ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_dsh_client_ui_primitives3.Tag, { tone: "neutral", children: t("overridden") }) : null,
|
|
1196
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(ChevronDown2, { className: advanced ? Section_default.chevronOpen : Section_default.chevron })
|
|
627
1197
|
]
|
|
628
1198
|
}
|
|
629
1199
|
),
|
|
630
|
-
advanced ? /* @__PURE__ */ (0,
|
|
631
|
-
/* @__PURE__ */ (0,
|
|
632
|
-
/* @__PURE__ */ (0,
|
|
633
|
-
/* @__PURE__ */ (0,
|
|
1200
|
+
advanced ? /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { id: "opencode-go-advanced", className: Section_default.cardBody, children: [
|
|
1201
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { className: Section_default.hint, children: t("advancedHint") }),
|
|
1202
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: Section_default.advancedGrid, children: [
|
|
1203
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
634
1204
|
ValueField,
|
|
635
1205
|
{
|
|
636
1206
|
id: "opencode-go-usage-display",
|
|
@@ -647,7 +1217,27 @@ function Loaded(props) {
|
|
|
647
1217
|
}
|
|
648
1218
|
}
|
|
649
1219
|
),
|
|
650
|
-
/* @__PURE__ */ (0,
|
|
1220
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
1221
|
+
ValueField,
|
|
1222
|
+
{
|
|
1223
|
+
id: "opencode-go-protocol-overrides",
|
|
1224
|
+
label: t("protocolOverridesLabel"),
|
|
1225
|
+
hint: t("protocolOverridesHint"),
|
|
1226
|
+
field: state.protocolOverrides,
|
|
1227
|
+
options: [
|
|
1228
|
+
{ value: "auto", label: t("protocolOverridesAuto") },
|
|
1229
|
+
{ value: "openai-responses", label: t("protocolOverridesResponses") }
|
|
1230
|
+
],
|
|
1231
|
+
...fieldProps,
|
|
1232
|
+
onEdit: (text) => {
|
|
1233
|
+
props.edit("protocolOverrides", text);
|
|
1234
|
+
},
|
|
1235
|
+
onReset: () => {
|
|
1236
|
+
props.resetField("protocolOverrides");
|
|
1237
|
+
}
|
|
1238
|
+
}
|
|
1239
|
+
),
|
|
1240
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
651
1241
|
ValueField,
|
|
652
1242
|
{
|
|
653
1243
|
id: "opencode-go-api-key-env",
|
|
@@ -663,7 +1253,7 @@ function Loaded(props) {
|
|
|
663
1253
|
}
|
|
664
1254
|
}
|
|
665
1255
|
),
|
|
666
|
-
/* @__PURE__ */ (0,
|
|
1256
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
667
1257
|
ValueField,
|
|
668
1258
|
{
|
|
669
1259
|
id: "opencode-go-base-url",
|
|
@@ -679,7 +1269,25 @@ function Loaded(props) {
|
|
|
679
1269
|
}
|
|
680
1270
|
}
|
|
681
1271
|
),
|
|
682
|
-
/* @__PURE__ */ (0,
|
|
1272
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
1273
|
+
ValueField,
|
|
1274
|
+
{
|
|
1275
|
+
id: "opencode-go-proxy-url",
|
|
1276
|
+
label: t("proxyURLLabel"),
|
|
1277
|
+
hint: t("proxyURLHint"),
|
|
1278
|
+
placeholder: "http://127.0.0.1:7890",
|
|
1279
|
+
field: state.proxyURL,
|
|
1280
|
+
...fieldProps,
|
|
1281
|
+
invalidLabel: t("proxyURLInvalid"),
|
|
1282
|
+
onEdit: (text) => {
|
|
1283
|
+
props.edit("proxyURL", text);
|
|
1284
|
+
},
|
|
1285
|
+
onReset: () => {
|
|
1286
|
+
props.resetField("proxyURL");
|
|
1287
|
+
}
|
|
1288
|
+
}
|
|
1289
|
+
),
|
|
1290
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
683
1291
|
ValueField,
|
|
684
1292
|
{
|
|
685
1293
|
id: "opencode-go-refresh-minutes",
|
|
@@ -696,7 +1304,7 @@ function Loaded(props) {
|
|
|
696
1304
|
}
|
|
697
1305
|
}
|
|
698
1306
|
),
|
|
699
|
-
/* @__PURE__ */ (0,
|
|
1307
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
700
1308
|
ValueField,
|
|
701
1309
|
{
|
|
702
1310
|
id: "opencode-go-stream-idle",
|
|
@@ -713,7 +1321,7 @@ function Loaded(props) {
|
|
|
713
1321
|
}
|
|
714
1322
|
}
|
|
715
1323
|
),
|
|
716
|
-
/* @__PURE__ */ (0,
|
|
1324
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
717
1325
|
ValueField,
|
|
718
1326
|
{
|
|
719
1327
|
id: "opencode-go-max-images",
|
|
@@ -730,7 +1338,7 @@ function Loaded(props) {
|
|
|
730
1338
|
}
|
|
731
1339
|
}
|
|
732
1340
|
),
|
|
733
|
-
/* @__PURE__ */ (0,
|
|
1341
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
734
1342
|
ValueField,
|
|
735
1343
|
{
|
|
736
1344
|
id: "opencode-go-max-request-image-bytes",
|
|
@@ -747,7 +1355,7 @@ function Loaded(props) {
|
|
|
747
1355
|
}
|
|
748
1356
|
}
|
|
749
1357
|
),
|
|
750
|
-
/* @__PURE__ */ (0,
|
|
1358
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
751
1359
|
ValueField,
|
|
752
1360
|
{
|
|
753
1361
|
id: "opencode-go-image-pixel-budget",
|
|
@@ -764,7 +1372,7 @@ function Loaded(props) {
|
|
|
764
1372
|
}
|
|
765
1373
|
}
|
|
766
1374
|
),
|
|
767
|
-
/* @__PURE__ */ (0,
|
|
1375
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
768
1376
|
ValueField,
|
|
769
1377
|
{
|
|
770
1378
|
id: "opencode-go-image-max-bytes",
|
|
@@ -784,12 +1392,12 @@ function Loaded(props) {
|
|
|
784
1392
|
] })
|
|
785
1393
|
] }) : null
|
|
786
1394
|
] }),
|
|
787
|
-
disabled ? /* @__PURE__ */ (0,
|
|
1395
|
+
disabled ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { className: Section_default.hint, children: t("readOnly") }) : null
|
|
788
1396
|
] }),
|
|
789
|
-
/* @__PURE__ */ (0,
|
|
790
|
-
/* @__PURE__ */ (0,
|
|
791
|
-
/* @__PURE__ */ (0,
|
|
792
|
-
/* @__PURE__ */ (0,
|
|
1397
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: Section_default.actions, children: [
|
|
1398
|
+
/* @__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") }),
|
|
1399
|
+
/* @__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") }),
|
|
1400
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
793
1401
|
"a",
|
|
794
1402
|
{
|
|
795
1403
|
className: Section_default.starLink,
|
|
@@ -798,12 +1406,12 @@ function Loaded(props) {
|
|
|
798
1406
|
rel: "noopener noreferrer",
|
|
799
1407
|
title: t("starProjectTitle"),
|
|
800
1408
|
children: [
|
|
801
|
-
/* @__PURE__ */ (0,
|
|
802
|
-
/* @__PURE__ */ (0,
|
|
1409
|
+
/* @__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" }) }),
|
|
1410
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { children: t("starProject") })
|
|
803
1411
|
]
|
|
804
1412
|
}
|
|
805
1413
|
),
|
|
806
|
-
state.failed ? /* @__PURE__ */ (0,
|
|
1414
|
+
state.failed ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { className: Section_default.failedNote, children: t("savedFailed") }) : null
|
|
807
1415
|
] })
|
|
808
1416
|
] });
|
|
809
1417
|
}
|
|
@@ -811,6 +1419,236 @@ function Loaded(props) {
|
|
|
811
1419
|
// src/provider-identity.ts
|
|
812
1420
|
var PROVIDER_ID = "dsh-opencode-go";
|
|
813
1421
|
|
|
1422
|
+
// src/config-contract.ts
|
|
1423
|
+
var SETTINGS_NAMESPACE = "llm-opencode-go";
|
|
1424
|
+
var PROFILE_ENTRY_ID = "opencode-go";
|
|
1425
|
+
|
|
1426
|
+
// src/settings-bridge.ts
|
|
1427
|
+
function settingsWriteResult(verdict, committed) {
|
|
1428
|
+
if (verdict === true) return "applied";
|
|
1429
|
+
if (verdict === false) return "rejected";
|
|
1430
|
+
return committed() ? "applied" : "unknown";
|
|
1431
|
+
}
|
|
1432
|
+
|
|
1433
|
+
// src/proxy-url.ts
|
|
1434
|
+
function assertProxyURL(raw) {
|
|
1435
|
+
const value = raw?.trim() ?? "";
|
|
1436
|
+
if (!value) return "";
|
|
1437
|
+
let url;
|
|
1438
|
+
try {
|
|
1439
|
+
url = new URL(value);
|
|
1440
|
+
} catch {
|
|
1441
|
+
throw new Error("OpenCode Go: proxy address must be a valid URL");
|
|
1442
|
+
}
|
|
1443
|
+
if (!["http:", "https:", "socks5:"].includes(url.protocol)) {
|
|
1444
|
+
throw new Error("OpenCode Go: proxy address must use http://, https:// or socks5://");
|
|
1445
|
+
}
|
|
1446
|
+
if (!url.hostname || url.port === "0" || url.pathname !== "" && url.pathname !== "/" || url.search || url.hash) {
|
|
1447
|
+
throw new Error("OpenCode Go: proxy address must contain a host and optional port, without a path, query or fragment");
|
|
1448
|
+
}
|
|
1449
|
+
try {
|
|
1450
|
+
decodeURIComponent(url.username);
|
|
1451
|
+
decodeURIComponent(url.password);
|
|
1452
|
+
} catch {
|
|
1453
|
+
throw new Error("OpenCode Go: proxy credentials contain invalid URL encoding");
|
|
1454
|
+
}
|
|
1455
|
+
return url.href;
|
|
1456
|
+
}
|
|
1457
|
+
|
|
1458
|
+
// src/protocol-contract.ts
|
|
1459
|
+
var RESPONSES_OVERRIDE_MODEL = "deepseek-v4.1-flash";
|
|
1460
|
+
|
|
1461
|
+
// src/account-operations.ts
|
|
1462
|
+
function visibleAccountsOf(settings) {
|
|
1463
|
+
const entries = [...accountsOf(settings)];
|
|
1464
|
+
for (const operation of settings.accountOperations ?? []) {
|
|
1465
|
+
if (!entries.some((account) => account.apiKeyEnv === operation.account.apiKeyEnv)) entries.push(operation.account);
|
|
1466
|
+
}
|
|
1467
|
+
return entries;
|
|
1468
|
+
}
|
|
1469
|
+
|
|
1470
|
+
// src/client/accounts-controller.ts
|
|
1471
|
+
function operationId() {
|
|
1472
|
+
return Array.from(crypto.getRandomValues(new Uint8Array(16)), (byte) => byte.toString(16).padStart(2, "0")).join("");
|
|
1473
|
+
}
|
|
1474
|
+
var GoAccountsController = class {
|
|
1475
|
+
constructor(scope, ctx, readUsage, publish, blocked, execute = async (command) => {
|
|
1476
|
+
const response = await ctx.remote.opencodeGoAccounts.execute(command);
|
|
1477
|
+
return response.ok ? response.value : "unknown";
|
|
1478
|
+
}) {
|
|
1479
|
+
this.scope = scope;
|
|
1480
|
+
this.ctx = ctx;
|
|
1481
|
+
this.readUsage = readUsage;
|
|
1482
|
+
this.publish = publish;
|
|
1483
|
+
this.blocked = blocked;
|
|
1484
|
+
this.execute = execute;
|
|
1485
|
+
this.sync();
|
|
1486
|
+
}
|
|
1487
|
+
rows = /* @__PURE__ */ new Map();
|
|
1488
|
+
busy = false;
|
|
1489
|
+
refreshing = false;
|
|
1490
|
+
failure;
|
|
1491
|
+
epoch = 0;
|
|
1492
|
+
identity = "";
|
|
1493
|
+
loaded = false;
|
|
1494
|
+
disposed = false;
|
|
1495
|
+
addition;
|
|
1496
|
+
snapshot() {
|
|
1497
|
+
const config = this.scope.getSnapshot().value ?? {};
|
|
1498
|
+
return {
|
|
1499
|
+
entries: visibleAccountsOf(config).map((account) => ({ ...this.rows.get(account.apiKeyEnv), ...account })),
|
|
1500
|
+
activeRef: accountRefOf(config),
|
|
1501
|
+
autoSwitch: config.autoSwitch === true,
|
|
1502
|
+
busy: this.busy,
|
|
1503
|
+
blocked: this.blocked(),
|
|
1504
|
+
refreshing: this.refreshing,
|
|
1505
|
+
failure: this.failure
|
|
1506
|
+
};
|
|
1507
|
+
}
|
|
1508
|
+
sync() {
|
|
1509
|
+
const config = this.scope.getSnapshot().value ?? {};
|
|
1510
|
+
const identity = JSON.stringify([
|
|
1511
|
+
visibleAccountsOf(config).map((account) => [account.id, account.apiKeyEnv]).sort((left, right) => left[1] < right[1] ? -1 : left[1] > right[1] ? 1 : 0),
|
|
1512
|
+
config.baseURL,
|
|
1513
|
+
config.proxyURL
|
|
1514
|
+
]);
|
|
1515
|
+
if (identity === this.identity) return;
|
|
1516
|
+
this.identity = identity;
|
|
1517
|
+
this.epoch++;
|
|
1518
|
+
this.rows.clear();
|
|
1519
|
+
this.refreshing = false;
|
|
1520
|
+
if (this.loaded) void this.refresh();
|
|
1521
|
+
}
|
|
1522
|
+
dispose() {
|
|
1523
|
+
this.disposed = true;
|
|
1524
|
+
this.epoch++;
|
|
1525
|
+
}
|
|
1526
|
+
invalidate(ref) {
|
|
1527
|
+
if (!visibleAccountsOf(this.scope.getSnapshot().value ?? {}).some((account) => account.apiKeyEnv === ref)) return;
|
|
1528
|
+
this.epoch++;
|
|
1529
|
+
this.rows.delete(ref);
|
|
1530
|
+
if (this.loaded) void this.refresh();
|
|
1531
|
+
}
|
|
1532
|
+
async refresh() {
|
|
1533
|
+
this.loaded = true;
|
|
1534
|
+
const epoch = ++this.epoch;
|
|
1535
|
+
const accounts = [...visibleAccountsOf(this.scope.getSnapshot().value ?? {})];
|
|
1536
|
+
this.refreshing = true;
|
|
1537
|
+
this.publish();
|
|
1538
|
+
try {
|
|
1539
|
+
const described = await this.ctx.remote.credentials.describe(accounts.map((account) => account.apiKeyEnv));
|
|
1540
|
+
if (this.disposed || epoch !== this.epoch) return;
|
|
1541
|
+
if (!described.ok) {
|
|
1542
|
+
this.failure = "read";
|
|
1543
|
+
this.markUnreadable(accounts, described.error instanceof Error ? described.error.message : String(described.error));
|
|
1544
|
+
return;
|
|
1545
|
+
}
|
|
1546
|
+
this.failure = void 0;
|
|
1547
|
+
await Promise.all(accounts.map(async (account) => {
|
|
1548
|
+
const ref = account.apiKeyEnv;
|
|
1549
|
+
const info = described.value[ref];
|
|
1550
|
+
const previous = this.rows.get(ref);
|
|
1551
|
+
this.rows.set(ref, {
|
|
1552
|
+
...previous,
|
|
1553
|
+
...account,
|
|
1554
|
+
configured: info?.configured ?? false,
|
|
1555
|
+
writable: info?.writable ?? true,
|
|
1556
|
+
loading: info?.configured === true,
|
|
1557
|
+
failed: false
|
|
1558
|
+
});
|
|
1559
|
+
this.publish();
|
|
1560
|
+
if (!info?.configured) {
|
|
1561
|
+
this.rows.set(ref, { ...account, configured: false, writable: info?.writable ?? true });
|
|
1562
|
+
return;
|
|
1563
|
+
}
|
|
1564
|
+
try {
|
|
1565
|
+
const usage = await this.readUsage(ref);
|
|
1566
|
+
if (this.disposed || epoch !== this.epoch) return;
|
|
1567
|
+
this.rows.set(ref, { ...account, configured: true, writable: info.writable, usage, updatedAt: Date.now() });
|
|
1568
|
+
} catch (error) {
|
|
1569
|
+
if (this.disposed || epoch !== this.epoch) return;
|
|
1570
|
+
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;
|
|
1571
|
+
const retain = details?.retryable === true && details.retainPrevious === true && previous?.usage?.source && previous.usage.source === details.source;
|
|
1572
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
1573
|
+
this.rows.set(ref, {
|
|
1574
|
+
...account,
|
|
1575
|
+
configured: true,
|
|
1576
|
+
writable: info.writable,
|
|
1577
|
+
failed: true,
|
|
1578
|
+
problem: message.length > 200 ? message.slice(0, 200) + "\u2026" : message,
|
|
1579
|
+
...retain ? { usage: previous.usage, updatedAt: previous.updatedAt, stale: true } : {}
|
|
1580
|
+
});
|
|
1581
|
+
}
|
|
1582
|
+
this.publish();
|
|
1583
|
+
}));
|
|
1584
|
+
} catch (error) {
|
|
1585
|
+
if (epoch === this.epoch) {
|
|
1586
|
+
this.failure = "read";
|
|
1587
|
+
this.markUnreadable(accounts, error instanceof Error ? error.message : String(error));
|
|
1588
|
+
}
|
|
1589
|
+
} finally {
|
|
1590
|
+
if (!this.disposed && epoch === this.epoch) {
|
|
1591
|
+
this.refreshing = false;
|
|
1592
|
+
this.publish();
|
|
1593
|
+
}
|
|
1594
|
+
}
|
|
1595
|
+
}
|
|
1596
|
+
/** Mark every account row as unreadable with the Host's own diagnostic. */
|
|
1597
|
+
markUnreadable(accounts, message) {
|
|
1598
|
+
const problem = message.length > 200 ? message.slice(0, 200) + "\u2026" : message;
|
|
1599
|
+
for (const account of accounts) this.rows.set(account.apiKeyEnv, { ...account, failed: true, problem });
|
|
1600
|
+
this.publish();
|
|
1601
|
+
}
|
|
1602
|
+
actions() {
|
|
1603
|
+
const command = (request) => this.execute(request).then((status) => status === "applied");
|
|
1604
|
+
return {
|
|
1605
|
+
loadAccounts: () => {
|
|
1606
|
+
void this.refresh();
|
|
1607
|
+
},
|
|
1608
|
+
addAccount: (name, key) => this.run(async () => {
|
|
1609
|
+
if (!name.trim() || name.trim().length > 80 || !key.trim()) return false;
|
|
1610
|
+
const resumed = this.scope.getSnapshot().value?.accountOperations?.find((entry) => entry.kind === "add" && entry.account.name === name.trim());
|
|
1611
|
+
if (this.addition?.name !== name.trim()) this.addition = { name: name.trim(), id: resumed?.account.id ?? operationId() };
|
|
1612
|
+
const accepted = await command({ kind: "add", id: this.addition.id, name, key });
|
|
1613
|
+
if (accepted) this.addition = void 0;
|
|
1614
|
+
return accepted;
|
|
1615
|
+
}),
|
|
1616
|
+
renameAccount: (ref, name) => this.run(() => command({ kind: "rename", ref, name })),
|
|
1617
|
+
removeAccount: (ref) => this.run(async () => {
|
|
1618
|
+
const accepted = await command({ kind: "remove", ref });
|
|
1619
|
+
if (!accepted) this.failure = "remove";
|
|
1620
|
+
return accepted;
|
|
1621
|
+
}),
|
|
1622
|
+
selectAccount: (ref) => this.run(() => command({ kind: "select", ref })),
|
|
1623
|
+
setAutoSwitch: (value) => this.run(() => command({ kind: "auto-switch", value })),
|
|
1624
|
+
replaceAccountKey: (ref, key) => this.run(async () => {
|
|
1625
|
+
if (!key.trim() || this.rows.get(ref)?.writable === false) return false;
|
|
1626
|
+
const accepted = await command({ kind: "replace-key", ref, key });
|
|
1627
|
+
if (accepted) this.invalidate(ref);
|
|
1628
|
+
return accepted;
|
|
1629
|
+
}, false),
|
|
1630
|
+
moveAccount: (ref, toIndex) => this.run(() => command({ kind: "move", ref, toIndex }))
|
|
1631
|
+
};
|
|
1632
|
+
}
|
|
1633
|
+
async run(action, requiresSettings = true) {
|
|
1634
|
+
if (this.busy || this.blocked() || requiresSettings && !this.scope.getSnapshot().writable) return false;
|
|
1635
|
+
this.busy = true;
|
|
1636
|
+
this.failure = void 0;
|
|
1637
|
+
this.publish();
|
|
1638
|
+
try {
|
|
1639
|
+
const accepted = await action();
|
|
1640
|
+
if (!accepted && !this.failure) this.failure = "write";
|
|
1641
|
+
return accepted;
|
|
1642
|
+
} catch {
|
|
1643
|
+
this.failure ??= "write";
|
|
1644
|
+
return false;
|
|
1645
|
+
} finally {
|
|
1646
|
+
this.busy = false;
|
|
1647
|
+
this.publish();
|
|
1648
|
+
}
|
|
1649
|
+
}
|
|
1650
|
+
};
|
|
1651
|
+
|
|
814
1652
|
// src/client/staged-form.ts
|
|
815
1653
|
var import_dsh_client_store = require("@deepseek-ai/dsh-client-store");
|
|
816
1654
|
function numberField(field, validate = () => true) {
|
|
@@ -910,7 +1748,7 @@ var StagedForm = class {
|
|
|
910
1748
|
available: snapshot.status === "ready",
|
|
911
1749
|
writable: snapshot.writable,
|
|
912
1750
|
dirty: plan.length > 0,
|
|
913
|
-
invalid: plan.some((item) => item.run === void 0),
|
|
1751
|
+
invalid: plan.some((item) => item.run === void 0 && item.write === void 0),
|
|
914
1752
|
saving: this.saving,
|
|
915
1753
|
failed: this.failed
|
|
916
1754
|
};
|
|
@@ -971,16 +1809,34 @@ var StagedForm = class {
|
|
|
971
1809
|
*/
|
|
972
1810
|
async save() {
|
|
973
1811
|
const plan = this.plan();
|
|
974
|
-
|
|
975
|
-
|
|
1812
|
+
if (plan.length === 0 || this.saving || plan.some((item) => !item.write && !item.run)) return;
|
|
1813
|
+
const revision = this.snapshotOf().revision;
|
|
976
1814
|
this.saving = true;
|
|
977
1815
|
this.failed = false;
|
|
978
1816
|
this.publish();
|
|
979
1817
|
let landed = true;
|
|
980
|
-
|
|
981
|
-
|
|
1818
|
+
const settings = plan.filter((item) => item.write !== void 0);
|
|
1819
|
+
const accept = (item) => {
|
|
1820
|
+
if (this.staged.get(item.field) === item.edit) this.staged.delete(item.field);
|
|
1821
|
+
};
|
|
1822
|
+
if (settings.length > 0) {
|
|
1823
|
+
const ops = settings.map(({ field, write }) => write.kind === "clear" ? { op: "unset", path: [field] } : { op: "set", path: [field], value: write.value });
|
|
1824
|
+
try {
|
|
1825
|
+
const accepted = await this.scope.mutate(ops, revision);
|
|
1826
|
+
landed = settingsWriteResult(accepted, () => settings.every((item) => item.write.kind === "clear" ? !this.stored(item.field) : sameJsonValue(this.userLayer()?.[item.field], item.write.value))) === "applied";
|
|
1827
|
+
if (landed) settings.forEach(accept);
|
|
1828
|
+
} catch {
|
|
1829
|
+
landed = false;
|
|
1830
|
+
}
|
|
1831
|
+
}
|
|
1832
|
+
if (landed) for (const item of plan.filter((item2) => item2.run !== void 0)) {
|
|
1833
|
+
try {
|
|
1834
|
+
if (await item.run()) accept(item);
|
|
1835
|
+
else landed = false;
|
|
1836
|
+
} catch {
|
|
1837
|
+
landed = false;
|
|
1838
|
+
}
|
|
982
1839
|
}
|
|
983
|
-
if (landed) this.staged.clear();
|
|
984
1840
|
this.saving = false;
|
|
985
1841
|
this.failed = !landed;
|
|
986
1842
|
this.publish();
|
|
@@ -997,30 +1853,20 @@ var StagedForm = class {
|
|
|
997
1853
|
const secret = this.secretSpecs.get(field);
|
|
998
1854
|
if (secret !== void 0) {
|
|
999
1855
|
const value = staged.text.trim();
|
|
1000
|
-
if (value !== "") plan.push({ field, run: () => secret.write(value) });
|
|
1856
|
+
if (value !== "") plan.push({ field, edit: staged, run: () => secret.write(value) });
|
|
1001
1857
|
continue;
|
|
1002
1858
|
}
|
|
1003
1859
|
const spec = this.spec(field);
|
|
1004
1860
|
if (staged.clear) {
|
|
1005
|
-
if (this.stored(field)) plan.push({ field,
|
|
1861
|
+
if (this.stored(field)) plan.push({ field, edit: staged, write: { kind: "clear" }, run: void 0 });
|
|
1006
1862
|
continue;
|
|
1007
1863
|
}
|
|
1008
1864
|
if (this.unchangedDraft(field, staged)) continue;
|
|
1009
1865
|
const write = spec.parse(staged.text);
|
|
1010
|
-
|
|
1011
|
-
else if (write.kind === "clear") plan.push({ field, run: () => this.clear(field) });
|
|
1012
|
-
else plan.push({ field, run: () => this.store(field, write.value) });
|
|
1866
|
+
plan.push({ field, edit: staged, write, run: void 0 });
|
|
1013
1867
|
}
|
|
1014
1868
|
return plan;
|
|
1015
1869
|
}
|
|
1016
|
-
async clear(field) {
|
|
1017
|
-
await this.scope.unset(field);
|
|
1018
|
-
return !this.stored(field);
|
|
1019
|
-
}
|
|
1020
|
-
async store(field, value) {
|
|
1021
|
-
await this.scope.set(field, value);
|
|
1022
|
-
return sameJsonValue(this.userLayer()?.[field], value);
|
|
1023
|
-
}
|
|
1024
1870
|
stage(field, edit) {
|
|
1025
1871
|
this.staged.set(field, edit);
|
|
1026
1872
|
this.failed = false;
|
|
@@ -1076,8 +1922,7 @@ function sameJsonValue(left, right) {
|
|
|
1076
1922
|
}
|
|
1077
1923
|
|
|
1078
1924
|
// src/client/section-controller.ts
|
|
1079
|
-
var OPENCODE_GO_NS =
|
|
1080
|
-
var DEFAULT_API_KEY_REF = "OPENCODE_API_KEY";
|
|
1925
|
+
var OPENCODE_GO_NS = SETTINGS_NAMESPACE;
|
|
1081
1926
|
var API_KEY_FIELD = "apiKey";
|
|
1082
1927
|
var OpencodeGoSectionController = class {
|
|
1083
1928
|
/**
|
|
@@ -1088,10 +1933,18 @@ var OpencodeGoSectionController = class {
|
|
|
1088
1933
|
constructor(scope, ctx, readModels = async () => {
|
|
1089
1934
|
const result = await ctx.remote.llm.discoverModels(OPENCODE_GO_NS, { provider: PROVIDER_ID });
|
|
1090
1935
|
return result.ok ? { ok: true, value: { models: result.value, stale: false } } : result;
|
|
1936
|
+
}, readUsage = async (ref) => {
|
|
1937
|
+
const result = await ctx.remote.opencodeGoUsage.readAccount(ref);
|
|
1938
|
+
if (!result.ok) throw result.error;
|
|
1939
|
+
return result.value;
|
|
1940
|
+
}, executeAccountCommand = async (command) => {
|
|
1941
|
+
const result = await ctx.remote.opencodeGoAccounts.execute(command);
|
|
1942
|
+
return result.ok ? result.value : "unknown";
|
|
1091
1943
|
}) {
|
|
1092
1944
|
this.scope = scope;
|
|
1093
1945
|
this.ctx = ctx;
|
|
1094
1946
|
this.readModels = readModels;
|
|
1947
|
+
this.executeAccountCommand = executeAccountCommand;
|
|
1095
1948
|
this.form = new StagedForm(
|
|
1096
1949
|
scope,
|
|
1097
1950
|
[
|
|
@@ -1103,8 +1956,25 @@ var OpencodeGoSectionController = class {
|
|
|
1103
1956
|
format: (value) => typeof value === "string" ? value : DEFAULT_USAGE_DISPLAY,
|
|
1104
1957
|
parse: (text) => USAGE_DISPLAY_MODES.some((mode) => mode === text) ? { kind: "set", value: text } : void 0
|
|
1105
1958
|
},
|
|
1959
|
+
{
|
|
1960
|
+
field: "protocolOverrides",
|
|
1961
|
+
format: (value) => value?.[RESPONSES_OVERRIDE_MODEL] ?? "auto",
|
|
1962
|
+
parse: (text) => text === "auto" || text === "openai-responses" ? { kind: "set", value: { [RESPONSES_OVERRIDE_MODEL]: text === "auto" ? null : text } } : void 0
|
|
1963
|
+
},
|
|
1106
1964
|
textField("apiKeyEnv"),
|
|
1107
1965
|
textField("baseURL"),
|
|
1966
|
+
{
|
|
1967
|
+
...textField("proxyURL"),
|
|
1968
|
+
// Blank explicitly disables an inherited proxy; Reset removes the override.
|
|
1969
|
+
parse: (text) => {
|
|
1970
|
+
try {
|
|
1971
|
+
assertProxyURL(text);
|
|
1972
|
+
return { kind: "set", value: text.trim() };
|
|
1973
|
+
} catch {
|
|
1974
|
+
return void 0;
|
|
1975
|
+
}
|
|
1976
|
+
}
|
|
1977
|
+
},
|
|
1108
1978
|
numberField("refreshMinutes"),
|
|
1109
1979
|
numberField("streamIdleTimeoutMs"),
|
|
1110
1980
|
numberField("maxImages", (value) => Number.isSafeInteger(value) && value > 0),
|
|
@@ -1116,9 +1986,26 @@ var OpencodeGoSectionController = class {
|
|
|
1116
1986
|
[{ field: API_KEY_FIELD, write: (text) => this.writeKey(text) }]
|
|
1117
1987
|
);
|
|
1118
1988
|
this.store = this.form.bind(() => this.projection());
|
|
1119
|
-
|
|
1989
|
+
this.accounts = new GoAccountsController(
|
|
1990
|
+
scope,
|
|
1991
|
+
ctx,
|
|
1992
|
+
readUsage,
|
|
1993
|
+
() => {
|
|
1994
|
+
this.store.set(this.projection());
|
|
1995
|
+
},
|
|
1996
|
+
() => this.form.shell().saving || this.pickerSaving || Boolean(this.form.field(API_KEY_FIELD).text.trim()),
|
|
1997
|
+
this.executeAccountCommand
|
|
1998
|
+
);
|
|
1999
|
+
this.store.set(this.projection());
|
|
2000
|
+
const networkIdentity = () => JSON.stringify([
|
|
2001
|
+
scope.getSnapshot().value?.baseURL,
|
|
2002
|
+
scope.getSnapshot().value?.proxyURL
|
|
2003
|
+
]);
|
|
2004
|
+
let modelsEndpoint = networkIdentity();
|
|
1120
2005
|
this.unsubscribe = scope.subscribe(() => {
|
|
1121
|
-
|
|
2006
|
+
this.accounts?.sync();
|
|
2007
|
+
this.store.set(this.projection());
|
|
2008
|
+
const endpoint = networkIdentity();
|
|
1122
2009
|
if (endpoint !== modelsEndpoint) {
|
|
1123
2010
|
modelsEndpoint = endpoint;
|
|
1124
2011
|
this.modelsRequest++;
|
|
@@ -1138,8 +2025,13 @@ var OpencodeGoSectionController = class {
|
|
|
1138
2025
|
pickerFailed = false;
|
|
1139
2026
|
face;
|
|
1140
2027
|
unsubscribe;
|
|
2028
|
+
accounts;
|
|
2029
|
+
credentialRequest = 0;
|
|
2030
|
+
keyDraftRef;
|
|
1141
2031
|
/** Release subscriptions without disposing the host's shared form. */
|
|
1142
2032
|
dispose() {
|
|
2033
|
+
this.credentialRequest++;
|
|
2034
|
+
this.accounts?.dispose();
|
|
1143
2035
|
this.modelsRequest++;
|
|
1144
2036
|
this.unsubscribe();
|
|
1145
2037
|
this.form.dispose();
|
|
@@ -1147,13 +2039,17 @@ var OpencodeGoSectionController = class {
|
|
|
1147
2039
|
projection() {
|
|
1148
2040
|
return {
|
|
1149
2041
|
...this.form.shell(),
|
|
2042
|
+
saving: this.form.shell().saving || this.accounts?.snapshot().busy === true,
|
|
2043
|
+
accounts: this.accounts?.snapshot(),
|
|
1150
2044
|
enabled: this.enabled(),
|
|
1151
2045
|
usageDisplay: this.form.field("usageDisplay"),
|
|
2046
|
+
protocolOverrides: this.form.field("protocolOverrides"),
|
|
1152
2047
|
modelVisibility: this.scope.getSnapshot().value?.modelVisibility ?? {},
|
|
1153
2048
|
pickerSaving: this.pickerSaving,
|
|
1154
2049
|
pickerFailed: this.pickerFailed,
|
|
1155
2050
|
apiKeyEnv: this.form.field("apiKeyEnv"),
|
|
1156
2051
|
baseURL: this.form.field("baseURL"),
|
|
2052
|
+
proxyURL: this.form.field("proxyURL"),
|
|
1157
2053
|
refreshMinutes: this.form.field("refreshMinutes"),
|
|
1158
2054
|
streamIdleTimeoutMs: this.form.field("streamIdleTimeoutMs"),
|
|
1159
2055
|
maxImages: this.form.field("maxImages"),
|
|
@@ -1161,7 +2057,7 @@ var OpencodeGoSectionController = class {
|
|
|
1161
2057
|
requestImagePixelBudget: this.form.field("requestImagePixelBudget"),
|
|
1162
2058
|
requestImageMaxBytes: this.form.field("requestImageMaxBytes"),
|
|
1163
2059
|
apiKey: this.form.field(API_KEY_FIELD),
|
|
1164
|
-
apiKeyConfigured: this.credential.configured,
|
|
2060
|
+
apiKeyConfigured: this.credential.ref === refOf(this.scope.getSnapshot()) && this.credential.configured && accountsOf(this.scope.getSnapshot().value ?? {}).length > 0,
|
|
1165
2061
|
apiKeyWritable: this.credential.writable,
|
|
1166
2062
|
models: this.models,
|
|
1167
2063
|
modelLimits: this.form.field("modelLimits"),
|
|
@@ -1218,13 +2114,13 @@ var OpencodeGoSectionController = class {
|
|
|
1218
2114
|
}
|
|
1219
2115
|
/** Serialize immediate switches with form saves; refused writes retain committed values. */
|
|
1220
2116
|
async writePickerSetting(field, value, accepted) {
|
|
1221
|
-
if (this.pickerSaving || this.form.shell().saving || !this.scope.getSnapshot().writable) return;
|
|
2117
|
+
if (this.pickerSaving || this.form.shell().saving || this.accounts?.snapshot().busy || !this.scope.getSnapshot().writable) return;
|
|
1222
2118
|
this.pickerSaving = true;
|
|
1223
2119
|
this.pickerFailed = false;
|
|
1224
2120
|
this.store.set(this.projection());
|
|
1225
2121
|
try {
|
|
1226
|
-
await this.scope.set(field, value);
|
|
1227
|
-
this.pickerFailed =
|
|
2122
|
+
const verdict = await this.scope.set(field, value);
|
|
2123
|
+
this.pickerFailed = settingsWriteResult(verdict, accepted) !== "applied";
|
|
1228
2124
|
} catch {
|
|
1229
2125
|
this.pickerFailed = true;
|
|
1230
2126
|
} finally {
|
|
@@ -1283,13 +2179,19 @@ var OpencodeGoSectionController = class {
|
|
|
1283
2179
|
* reference in force.
|
|
1284
2180
|
*/
|
|
1285
2181
|
async readCredential() {
|
|
2182
|
+
const request = ++this.credentialRequest;
|
|
1286
2183
|
const ref = refOf(this.scope.getSnapshot());
|
|
2184
|
+
if (accountsOf(this.scope.getSnapshot().value ?? {}).length === 0) {
|
|
2185
|
+
this.credential = { ref, configured: false, writable: false };
|
|
2186
|
+
this.store.set(this.projection());
|
|
2187
|
+
return;
|
|
2188
|
+
}
|
|
1287
2189
|
if (ref !== this.credential.ref) {
|
|
1288
2190
|
this.credential = { ref, configured: false, writable: true };
|
|
1289
2191
|
this.store.set(this.projection());
|
|
1290
2192
|
}
|
|
1291
|
-
const response = await this.ctx.remote.credentials.describe([ref]);
|
|
1292
|
-
if (!response
|
|
2193
|
+
const response = await this.ctx.remote.credentials.describe([ref]).catch(() => void 0);
|
|
2194
|
+
if (!response?.ok || request !== this.credentialRequest || ref !== refOf(this.scope.getSnapshot())) return;
|
|
1293
2195
|
const view = response.value[ref];
|
|
1294
2196
|
const next = {
|
|
1295
2197
|
ref,
|
|
@@ -1311,6 +2213,7 @@ var OpencodeGoSectionController = class {
|
|
|
1311
2213
|
* @param ref - the reference the Host reports as changed.
|
|
1312
2214
|
*/
|
|
1313
2215
|
refreshCredential(ref) {
|
|
2216
|
+
this.accounts?.invalidate(ref);
|
|
1314
2217
|
if (ref !== this.credential.ref) return;
|
|
1315
2218
|
void this.readCredential();
|
|
1316
2219
|
}
|
|
@@ -1331,19 +2234,38 @@ var OpencodeGoSectionController = class {
|
|
|
1331
2234
|
setModelEnabled: (id3, next) => {
|
|
1332
2235
|
void this.setModelEnabled(id3, next);
|
|
1333
2236
|
},
|
|
1334
|
-
...this.form.actions()
|
|
2237
|
+
...this.form.actions(),
|
|
2238
|
+
...this.accounts.actions(),
|
|
2239
|
+
edit: (field, text) => {
|
|
2240
|
+
if (field === API_KEY_FIELD) {
|
|
2241
|
+
if (text.trim()) this.keyDraftRef ??= refOf(this.scope.getSnapshot());
|
|
2242
|
+
else this.keyDraftRef = void 0;
|
|
2243
|
+
}
|
|
2244
|
+
this.form.actions().edit(field, text);
|
|
2245
|
+
},
|
|
2246
|
+
discard: () => {
|
|
2247
|
+
this.keyDraftRef = void 0;
|
|
2248
|
+
this.form.actions().discard();
|
|
2249
|
+
},
|
|
2250
|
+
save: () => {
|
|
2251
|
+
if (!this.accounts?.snapshot().busy) void this.form.save().then(() => {
|
|
2252
|
+
if (!this.form.field(API_KEY_FIELD).text.trim()) this.keyDraftRef = void 0;
|
|
2253
|
+
});
|
|
2254
|
+
}
|
|
1335
2255
|
};
|
|
1336
2256
|
return this.face;
|
|
1337
2257
|
}
|
|
1338
2258
|
/**
|
|
1339
|
-
*
|
|
2259
|
+
* Ask the account service to write the staged key, then refresh its display.
|
|
1340
2260
|
* @param value - the staged credential literal.
|
|
1341
|
-
* @returns whether the Host
|
|
2261
|
+
* @returns whether the Host confirmed the write.
|
|
1342
2262
|
*/
|
|
1343
2263
|
async writeKey(value) {
|
|
1344
|
-
|
|
2264
|
+
const ref = this.keyDraftRef ?? refOf(this.scope.getSnapshot());
|
|
2265
|
+
if (await this.executeAccountCommand({ kind: "replace-key", ref, key: value }) !== "applied") return false;
|
|
2266
|
+
this.accounts?.invalidate(ref);
|
|
1345
2267
|
await this.readCredential();
|
|
1346
|
-
return
|
|
2268
|
+
return true;
|
|
1347
2269
|
}
|
|
1348
2270
|
};
|
|
1349
2271
|
function modelLimitsOf(value) {
|
|
@@ -1359,26 +2281,70 @@ function modelLimitsOf(value) {
|
|
|
1359
2281
|
const limit = {};
|
|
1360
2282
|
if (fields.contextWindow === null) limit.contextWindow = null;
|
|
1361
2283
|
if (fields.maxTokens === null) limit.maxTokens = null;
|
|
2284
|
+
if (fields.thinkingBudgets === null) limit.thinkingBudgets = null;
|
|
2285
|
+
if (Array.isArray(fields.thinkingBudgets) && fields.thinkingBudgets.length <= 16 && fields.thinkingBudgets.every((value2) => typeof value2 === "number" && Number.isSafeInteger(value2) && value2 > 0)) {
|
|
2286
|
+
limit.thinkingBudgets = fields.thinkingBudgets;
|
|
2287
|
+
}
|
|
1362
2288
|
if (typeof fields.contextWindow === "number" && Number.isSafeInteger(fields.contextWindow) && fields.contextWindow > 0) {
|
|
1363
2289
|
limit.contextWindow = fields.contextWindow;
|
|
1364
2290
|
}
|
|
1365
2291
|
if (typeof fields.maxTokens === "number" && Number.isSafeInteger(fields.maxTokens) && fields.maxTokens > 0) {
|
|
1366
2292
|
limit.maxTokens = fields.maxTokens;
|
|
1367
2293
|
}
|
|
1368
|
-
if (limit.contextWindow !== void 0 || limit.maxTokens !== void 0) limits[id3] = limit;
|
|
2294
|
+
if (limit.contextWindow !== void 0 || limit.maxTokens !== void 0 || limit.thinkingBudgets !== void 0) limits[id3] = limit;
|
|
1369
2295
|
}
|
|
1370
2296
|
return limits;
|
|
1371
2297
|
}
|
|
1372
2298
|
function refOf(snapshot) {
|
|
1373
|
-
|
|
1374
|
-
return declared !== void 0 && declared.length > 0 ? declared : DEFAULT_API_KEY_REF;
|
|
2299
|
+
return accountRefOf(snapshot.value ?? {});
|
|
1375
2300
|
}
|
|
1376
2301
|
|
|
1377
2302
|
// src/client/locales.ts
|
|
1378
2303
|
var en = {
|
|
2304
|
+
accountsTitle: "Accounts",
|
|
2305
|
+
accountsRefresh: "Refresh accounts",
|
|
2306
|
+
accountsBlocked: "Save or discard the API key draft before changing accounts.",
|
|
2307
|
+
accountsEmpty: "Add an account to use OpenCode Go.",
|
|
2308
|
+
accountsWriteFailed: "Could not apply the account change. Your input is kept; please retry.",
|
|
2309
|
+
accountsReadFailed: "Could not read account status. Please refresh.",
|
|
2310
|
+
accountsCleanupFailed: "The account entry was removed, but its stored key could not be deleted. Remove the unused reference through the host credential service.",
|
|
2311
|
+
accountsRemoveKeyFailed: "The stored key could not be deleted, so the account was kept. Please retry.",
|
|
2312
|
+
accountsStatusUnknown: "Status unknown",
|
|
2313
|
+
accountDefault: "Default account",
|
|
2314
|
+
accountAdd: "Add account",
|
|
2315
|
+
accountRename: "Rename",
|
|
2316
|
+
accountReplaceKey: "Replace key",
|
|
2317
|
+
accountRemove: "Remove account",
|
|
2318
|
+
accountRemoveHint: "Remove \u201C{name}\u201D? If it is the current account, the next account takes over. Keys added here are deleted from the credential service; existing external references are kept.",
|
|
2319
|
+
accountName: "Account name",
|
|
2320
|
+
accountKeyHint: "The key is saved through the host credential service and is never returned to this page.",
|
|
2321
|
+
accountConfirm: "Confirm",
|
|
2322
|
+
accountCancel: "Cancel",
|
|
2323
|
+
accountAutoSwitch: "Automatic fallback",
|
|
2324
|
+
accountAutoSwitchHint: "When a quota runs out or a key is unusable, the other accounts are tried in the Settings page order before any content or tool call is emitted; once an account starts producing output, it becomes the current account.",
|
|
2325
|
+
accountPreferredTag: "Current",
|
|
2326
|
+
accountSwitchAction: "Switch",
|
|
2327
|
+
accountSwitchTitle: "Switch account",
|
|
2328
|
+
accountSwitchBack: "Back to usage",
|
|
2329
|
+
accountSwitchHint: "Later requests in this profile use this account. The consumption order stays on the Settings page.",
|
|
2330
|
+
accountSwitchFailed: "Could not switch account. Please retry.",
|
|
2331
|
+
accountFallbackQuota: "The current account reached its quota; switched to",
|
|
2332
|
+
accountFallbackCredential: "The current key was unavailable or rejected; switched to",
|
|
2333
|
+
accountsSummary: "{count} accounts \xB7 Current {name}",
|
|
2334
|
+
accountsSummaryEmpty: "No accounts yet",
|
|
2335
|
+
accountsAvailability: "{ready}/{total} configured",
|
|
2336
|
+
accountsAvailabilityFailed: "{ready}/{total} configured \xB7 {failed} unreadable",
|
|
2337
|
+
accountsDetails: "Details for {name}",
|
|
2338
|
+
accountsDetailsHide: "Hide details for {name}",
|
|
2339
|
+
accountDragHandle: "Reorder {name}",
|
|
2340
|
+
accountConfigureHint: "Add a key to read usage",
|
|
2341
|
+
usageResetMinutes: "resets in {minutes} min",
|
|
2342
|
+
usageResetHours: "resets in {hours} h",
|
|
2343
|
+
usageResetDays: "resets in {days} d",
|
|
2344
|
+
usageResetDue: "resets now",
|
|
2345
|
+
usageResetUnknown: "reset time unknown",
|
|
1379
2346
|
usageTitle: "OpenCode Go usage",
|
|
1380
2347
|
usageRollingShort: "5h",
|
|
1381
|
-
usageHint: "Account usage \xB7 used percentage \xB7 refreshes every minute",
|
|
1382
2348
|
usageWeekShort: "week",
|
|
1383
2349
|
usage_rolling: "5 hours",
|
|
1384
2350
|
usage_weekly: "Weekly",
|
|
@@ -1388,6 +2354,7 @@ var en = {
|
|
|
1388
2354
|
usageLoading: "Loading usage\u2026",
|
|
1389
2355
|
usageUnavailable: "Unavailable",
|
|
1390
2356
|
usageStaleShort: "Last data",
|
|
2357
|
+
usageFallbackShort: "fallback",
|
|
1391
2358
|
usageStaleHint: "Showing the last successful usage reading. Current usage may have changed.",
|
|
1392
2359
|
usageRefreshFailed: "Refresh failed",
|
|
1393
2360
|
usageLastUpdated: "Last updated",
|
|
@@ -1430,6 +2397,11 @@ var en = {
|
|
|
1430
2397
|
limitsModel: "Model",
|
|
1431
2398
|
limitsContext: "Context window",
|
|
1432
2399
|
limitsOutput: "Max output",
|
|
2400
|
+
thinkingBudgets: "Thinking budgets",
|
|
2401
|
+
thinkingBudgetsHint: "Add token budgets to the conversation picker, then Save. Range: {min}\u2013{max} tokens. Existing reasoning choices stay available; Default uses the service settings. The SDK may reduce a budget to leave room for the answer.",
|
|
2402
|
+
thinkingBudgetAddLabel: "New thinking budget for {name}",
|
|
2403
|
+
thinkingBudgetAdd: "Add",
|
|
2404
|
+
thinkingBudgetRemove: "Remove {value} token budget",
|
|
1433
2405
|
capacityDefault: "Default: {value} tokens",
|
|
1434
2406
|
capacityMissing: "API did not provide a value",
|
|
1435
2407
|
modalityLabel: "Input modalities",
|
|
@@ -1465,7 +2437,7 @@ var en = {
|
|
|
1465
2437
|
limitsEmpty: "Read the model list first; capacities are edited per model the gateway serves.",
|
|
1466
2438
|
limitsContextLabel: "Context window for {name}",
|
|
1467
2439
|
limitsOutputLabel: "Max output for {name}",
|
|
1468
|
-
advancedSummary: "Usage display \xB7 Credential name \xB7 Gateway URL \xB7 Refresh \xB7 Idle timeout \xB7 Image limits",
|
|
2440
|
+
advancedSummary: "Usage display \xB7 Protocol \xB7 Credential name \xB7 Gateway URL \xB7 Refresh \xB7 Idle timeout \xB7 Image limits",
|
|
1469
2441
|
advancedLabel: "Advanced settings",
|
|
1470
2442
|
advancedHint: "Usage display, credential name, gateway URL, and adapter tuning. The inherited values work as they are; change them only if you know you need to.",
|
|
1471
2443
|
usageDisplayLabel: "Usage display",
|
|
@@ -1473,10 +2445,17 @@ var en = {
|
|
|
1473
2445
|
usageDisplay_auto: "Auto (default)",
|
|
1474
2446
|
usageDisplay_always: "Always",
|
|
1475
2447
|
usageDisplay_off: "Off",
|
|
2448
|
+
protocolOverridesLabel: "DeepSeek V4.1 Flash protocol",
|
|
2449
|
+
protocolOverridesHint: "Auto follows the model catalog. Responses is experimental and applies only to DeepSeek V4.1 Flash; speed depends on the gateway. Save to apply to new requests. Choose Auto to restore catalog routing.",
|
|
2450
|
+
protocolOverridesAuto: "Auto (default)",
|
|
2451
|
+
protocolOverridesResponses: "Responses (experimental)",
|
|
1476
2452
|
apiKeyEnvLabel: "Credential reference",
|
|
1477
2453
|
apiKeyEnvHint: "The name the key is resolved from, addressed through the credentials service.",
|
|
1478
2454
|
baseURLLabel: "Gateway URL",
|
|
1479
2455
|
baseURLHint: "The endpoint that serves requests and the live model list.",
|
|
2456
|
+
proxyURLLabel: "Proxy address",
|
|
2457
|
+
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.",
|
|
2458
|
+
proxyURLInvalid: "Enter an http://, https:// or socks5:// proxy address without a path, query or fragment.",
|
|
1480
2459
|
refreshMinutesLabel: "Catalog refresh (minutes)",
|
|
1481
2460
|
refreshMinutesHint: "Catalog cache lifetime for conversations and model pickers. Opening this settings page or clicking Refresh checks the gateway and online model metadata immediately.",
|
|
1482
2461
|
streamIdleTimeoutMsLabel: "Stream idle timeout (ms)",
|
|
@@ -1500,9 +2479,50 @@ var en = {
|
|
|
1500
2479
|
unavailable: "The OpenCode Go settings are not served in this deployment."
|
|
1501
2480
|
};
|
|
1502
2481
|
var zh = {
|
|
2482
|
+
accountsTitle: "\u8D26\u53F7",
|
|
2483
|
+
accountsRefresh: "\u5237\u65B0\u989D\u5EA6",
|
|
2484
|
+
accountsBlocked: "\u8BF7\u5148\u4FDD\u5B58\u6216\u653E\u5F03 API Key \u8349\u7A3F\uFF0C\u518D\u5207\u6362\u6216\u4FEE\u6539\u8D26\u53F7\u3002",
|
|
2485
|
+
accountsEmpty: "\u6DFB\u52A0\u8D26\u53F7\u540E\u5373\u53EF\u4F7F\u7528 OpenCode Go\u3002",
|
|
2486
|
+
accountsWriteFailed: "\u8D26\u53F7\u4FEE\u6539\u672A\u751F\u6548\uFF0C\u8F93\u5165\u5DF2\u4FDD\u7559\uFF0C\u8BF7\u91CD\u8BD5\u3002",
|
|
2487
|
+
accountsReadFailed: "\u672A\u80FD\u8BFB\u53D6\u8D26\u53F7\u72B6\u6001\uFF0C\u8BF7\u5237\u65B0\u91CD\u8BD5\u3002",
|
|
2488
|
+
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",
|
|
2489
|
+
accountsRemoveKeyFailed: "\u672A\u80FD\u5220\u9664\u5DF2\u4FDD\u5B58\u7684 Key\uFF0C\u8D26\u53F7\u6682\u65F6\u4FDD\u7559\uFF0C\u8BF7\u91CD\u8BD5\u3002",
|
|
2490
|
+
accountsStatusUnknown: "\u72B6\u6001\u672A\u77E5",
|
|
2491
|
+
accountDefault: "\u9ED8\u8BA4\u8D26\u53F7",
|
|
2492
|
+
accountAdd: "\u6DFB\u52A0\u8D26\u53F7",
|
|
2493
|
+
accountRename: "\u91CD\u547D\u540D",
|
|
2494
|
+
accountReplaceKey: "\u66FF\u6362 Key",
|
|
2495
|
+
accountRemove: "\u5220\u9664\u8D26\u53F7",
|
|
2496
|
+
accountRemoveHint: "\u5220\u9664\u201C{name}\u201D\uFF1F\u82E5\u5B83\u662F\u5F53\u524D\u8D26\u53F7\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",
|
|
2497
|
+
accountName: "\u8D26\u53F7\u540D\u79F0",
|
|
2498
|
+
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",
|
|
2499
|
+
accountConfirm: "\u786E\u8BA4",
|
|
2500
|
+
accountCancel: "\u53D6\u6D88",
|
|
2501
|
+
accountAutoSwitch: "\u81EA\u52A8\u4F7F\u7528\u5907\u7528\u8D26\u53F7",
|
|
2502
|
+
accountAutoSwitchHint: "\u989D\u5EA6\u8017\u5C3D\u6216 Key \u4E0D\u53EF\u7528\u65F6\uFF0C\u5728\u5C1A\u672A\u8F93\u51FA\u5185\u5BB9\u6216\u5DE5\u5177\u8C03\u7528\u524D\uFF0C\u6309\u8BBE\u7F6E\u9875\u7684\u8D26\u53F7\u987A\u5E8F\u5C1D\u8BD5\u5176\u4ED6\u8D26\u53F7\uFF1B\u4E00\u65E6\u67D0\u4E2A\u8D26\u53F7\u5F00\u59CB\u6B63\u5E38\u8F93\u51FA\uFF0C\u5F53\u524D\u8D26\u53F7\u5373\u5207\u6362\u4E3A\u5B83\u3002",
|
|
2503
|
+
accountPreferredTag: "\u5F53\u524D\u8D26\u53F7",
|
|
2504
|
+
accountSwitchAction: "\u5207\u6362",
|
|
2505
|
+
accountSwitchTitle: "\u5207\u6362\u8D26\u53F7",
|
|
2506
|
+
accountSwitchBack: "\u8FD4\u56DE\u989D\u5EA6",
|
|
2507
|
+
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",
|
|
2508
|
+
accountSwitchFailed: "\u8D26\u53F7\u5207\u6362\u672A\u751F\u6548\uFF0C\u8BF7\u91CD\u8BD5\u3002",
|
|
2509
|
+
accountFallbackQuota: "\u5F53\u524D\u8D26\u53F7\u989D\u5EA6\u8017\u5C3D\uFF0C\u5DF2\u81EA\u52A8\u5207\u6362\u4E3A\uFF1A",
|
|
2510
|
+
accountFallbackCredential: "\u5F53\u524D Key \u4E0D\u53EF\u7528\u6216\u88AB\u62D2\u7EDD\uFF0C\u5DF2\u81EA\u52A8\u5207\u6362\u4E3A\uFF1A",
|
|
2511
|
+
accountsSummary: "{count} \u4E2A \xB7 \u5F53\u524D {name}",
|
|
2512
|
+
accountsSummaryEmpty: "\u5C1A\u672A\u6DFB\u52A0\u8D26\u53F7",
|
|
2513
|
+
accountsAvailability: "{ready}/{total} \u5DF2\u914D\u7F6E",
|
|
2514
|
+
accountsAvailabilityFailed: "{ready}/{total} \u5DF2\u914D\u7F6E \xB7 {failed} \u4E2A\u8BFB\u53D6\u5931\u8D25",
|
|
2515
|
+
accountsDetails: "{name} \u7684\u8BE6\u60C5",
|
|
2516
|
+
accountsDetailsHide: "\u6536\u8D77 {name} \u7684\u8BE6\u60C5",
|
|
2517
|
+
accountDragHandle: "\u62D6\u52A8 {name} \u8C03\u6574\u987A\u5E8F",
|
|
2518
|
+
accountConfigureHint: "\u914D\u7F6E Key \u540E\u663E\u793A\u989D\u5EA6",
|
|
2519
|
+
usageResetMinutes: "{minutes} \u5206\u949F\u540E\u91CD\u7F6E",
|
|
2520
|
+
usageResetHours: "{hours} \u5C0F\u65F6\u540E\u91CD\u7F6E",
|
|
2521
|
+
usageResetDays: "{days} \u5929\u540E\u91CD\u7F6E",
|
|
2522
|
+
usageResetDue: "\u5373\u5C06\u91CD\u7F6E",
|
|
2523
|
+
usageResetUnknown: "\u91CD\u7F6E\u65F6\u95F4\u672A\u77E5",
|
|
1503
2524
|
usageTitle: "OpenCode Go \u7528\u91CF",
|
|
1504
2525
|
usageRollingShort: "5\u5C0F\u65F6",
|
|
1505
|
-
usageHint: "\u8D26\u53F7\u989D\u5EA6 \xB7 \u5DF2\u7528\u767E\u5206\u6BD4 \xB7 \u6BCF\u5206\u949F\u5237\u65B0",
|
|
1506
2526
|
usageWeekShort: "\u5468",
|
|
1507
2527
|
usage_rolling: "5 \u5C0F\u65F6",
|
|
1508
2528
|
usage_weekly: "\u6BCF\u5468",
|
|
@@ -1512,6 +2532,7 @@ var zh = {
|
|
|
1512
2532
|
usageLoading: "\u6B63\u5728\u8BFB\u53D6\u7528\u91CF\u2026",
|
|
1513
2533
|
usageUnavailable: "\u6682\u4E0D\u53EF\u7528",
|
|
1514
2534
|
usageStaleShort: "\u4E0A\u6B21\u6570\u636E",
|
|
2535
|
+
usageFallbackShort: "\u5DF2\u56DE\u9000",
|
|
1515
2536
|
usageStaleHint: "\u5F53\u524D\u663E\u793A\u4E0A\u6B21\u6210\u529F\u8BFB\u53D6\u7684\u7528\u91CF\uFF0C\u5B9E\u9645\u7528\u91CF\u53EF\u80FD\u5DF2\u53D8\u5316\u3002",
|
|
1516
2537
|
usageRefreshFailed: "\u5237\u65B0\u5931\u8D25",
|
|
1517
2538
|
usageLastUpdated: "\u66F4\u65B0\u4E8E",
|
|
@@ -1554,6 +2575,11 @@ var zh = {
|
|
|
1554
2575
|
limitsModel: "\u6A21\u578B",
|
|
1555
2576
|
limitsContext: "\u4E0A\u4E0B\u6587\u7A97\u53E3",
|
|
1556
2577
|
limitsOutput: "\u6700\u5927\u8F93\u51FA",
|
|
2578
|
+
thinkingBudgets: "\u601D\u8003\u9884\u7B97",
|
|
2579
|
+
thinkingBudgetsHint: "\u6DFB\u52A0 token \u9884\u7B97\u5E76\u4FDD\u5B58\uFF0C\u5373\u53EF\u5728\u4F1A\u8BDD\u4E2D\u9009\u62E9\u3002\u8303\u56F4\uFF1A{min}\u2013{max} tokens\u3002\u4FDD\u7559\u539F\u6709\u601D\u8003\u9009\u9879\uFF1B\u201C\u9ED8\u8BA4\u201D\u4F7F\u7528\u670D\u52A1\u5546\u8BBE\u7F6E\u3002SDK \u4F1A\u6309\u5269\u4F59\u8F93\u51FA\u7A7A\u95F4\u7F29\u5C0F\u9884\u7B97\uFF0C\u4E3A\u56DE\u7B54\u7559\u51FA\u7A7A\u95F4\u3002",
|
|
2580
|
+
thinkingBudgetAddLabel: "\u4E3A {name} \u6DFB\u52A0\u601D\u8003\u9884\u7B97",
|
|
2581
|
+
thinkingBudgetAdd: "\u6DFB\u52A0",
|
|
2582
|
+
thinkingBudgetRemove: "\u79FB\u9664 {value} token \u9884\u7B97",
|
|
1557
2583
|
capacityDefault: "\u9ED8\u8BA4\uFF1A{value} tokens",
|
|
1558
2584
|
capacityMissing: "API \u672A\u63D0\u4F9B",
|
|
1559
2585
|
modalityLabel: "\u8F93\u5165\u6A21\u6001",
|
|
@@ -1589,7 +2615,7 @@ var zh = {
|
|
|
1589
2615
|
limitsEmpty: "\u8BF7\u5148\u8BFB\u53D6\u6A21\u578B\u5217\u8868\uFF1B\u5BB9\u91CF\u6309\u7F51\u5173\u63D0\u4F9B\u7684\u6A21\u578B\u9010\u4E2A\u7F16\u8F91\u3002",
|
|
1590
2616
|
limitsContextLabel: "{name} \u7684\u4E0A\u4E0B\u6587\u7A97\u53E3",
|
|
1591
2617
|
limitsOutputLabel: "{name} \u7684\u6700\u5927\u8F93\u51FA",
|
|
1592
|
-
advancedSummary: "\u989D\u5EA6\u663E\u793A \xB7 \u51ED\u8BC1\u5F15\u7528\u540D \xB7 \u7F51\u5173\u5730\u5740 \xB7 \u76EE\u5F55\u5237\u65B0 \xB7 \u6D41\u7A7A\u95F2\u8D85\u65F6 \xB7 \u56FE\u7247 4 \u9879",
|
|
2618
|
+
advancedSummary: "\u989D\u5EA6\u663E\u793A \xB7 \u534F\u8BAE \xB7 \u51ED\u8BC1\u5F15\u7528\u540D \xB7 \u7F51\u5173\u5730\u5740 \xB7 \u76EE\u5F55\u5237\u65B0 \xB7 \u6D41\u7A7A\u95F2\u8D85\u65F6 \xB7 \u56FE\u7247 4 \u9879",
|
|
1593
2619
|
advancedLabel: "\u9AD8\u7EA7\u8BBE\u7F6E",
|
|
1594
2620
|
advancedHint: "\u989D\u5EA6\u663E\u793A\u3001\u51ED\u8BC1\u540D\u79F0\u3001\u7F51\u5173\u5730\u5740\u4E0E\u9002\u914D\u5668\u8C03\u4F18\u53C2\u6570\u3002\u7EE7\u627F\u6765\u7684\u53D6\u503C\u5373\u53EF\u6B63\u5E38\u4F7F\u7528\uFF0C\u6309\u9700\u4FEE\u6539\u3002",
|
|
1595
2621
|
usageDisplayLabel: "\u989D\u5EA6\u663E\u793A",
|
|
@@ -1597,10 +2623,17 @@ var zh = {
|
|
|
1597
2623
|
usageDisplay_auto: "\u81EA\u52A8\uFF08\u9ED8\u8BA4\uFF09",
|
|
1598
2624
|
usageDisplay_always: "\u5E38\u9A7B",
|
|
1599
2625
|
usageDisplay_off: "\u5173\u95ED",
|
|
2626
|
+
protocolOverridesLabel: "DeepSeek V4.1 Flash \u534F\u8BAE",
|
|
2627
|
+
protocolOverridesHint: "\u81EA\u52A8\u8DDF\u968F\u6A21\u578B\u76EE\u5F55\u3002Responses \u4E3A\u5B9E\u9A8C\u6027\u9009\u9879\uFF0C\u4EC5\u5F71\u54CD DeepSeek V4.1 Flash\uFF0C\u901F\u5EA6\u53D6\u51B3\u4E8E\u7F51\u5173\u3002\u4FDD\u5B58\u540E\u5BF9\u65B0\u8BF7\u6C42\u751F\u6548\uFF1B\u9009\u62E9\u81EA\u52A8\u53EF\u6062\u590D\u76EE\u5F55\u8DEF\u7531\u3002",
|
|
2628
|
+
protocolOverridesAuto: "\u81EA\u52A8\uFF08\u9ED8\u8BA4\uFF09",
|
|
2629
|
+
protocolOverridesResponses: "Responses\uFF08\u5B9E\u9A8C\u6027\uFF09",
|
|
1600
2630
|
apiKeyEnvLabel: "\u51ED\u8BC1\u5F15\u7528\u540D",
|
|
1601
2631
|
apiKeyEnvHint: "key \u89E3\u6790\u6240\u4F9D\u636E\u7684\u5F15\u7528\u540D\uFF0C\u7ECF\u51ED\u8BC1\u670D\u52A1\u5BFB\u5740\u3002",
|
|
1602
2632
|
baseURLLabel: "\u7F51\u5173\u5730\u5740",
|
|
1603
2633
|
baseURLHint: "\u540C\u65F6\u63D0\u4F9B\u6A21\u578B\u8BF7\u6C42\u4E0E\u5B9E\u65F6\u6A21\u578B\u5217\u8868\u7684\u7AEF\u70B9\u3002",
|
|
2634
|
+
proxyURLLabel: "\u4EE3\u7406\u5730\u5740",
|
|
2635
|
+
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",
|
|
2636
|
+
proxyURLInvalid: "\u8BF7\u8F93\u5165 http://\u3001https:// \u6216 socks5:// \u4EE3\u7406\u5730\u5740\uFF0C\u4E0D\u5305\u542B\u8DEF\u5F84\u3001\u67E5\u8BE2\u53C2\u6570\u6216\u7247\u6BB5\u3002",
|
|
1604
2637
|
refreshMinutesLabel: "\u76EE\u5F55\u5237\u65B0\uFF08\u5206\u949F\uFF09",
|
|
1605
2638
|
refreshMinutesHint: "\u4F1A\u8BDD\u8BF7\u6C42\u548C\u6A21\u578B\u9009\u62E9\u5668\u7684\u76EE\u5F55\u7F13\u5B58\u65F6\u957F\u3002\u6253\u5F00\u672C\u8BBE\u7F6E\u9875\u6216\u70B9\u51FB\u5237\u65B0\u65F6\uFF0C\u4F1A\u7ACB\u5373\u6838\u5BF9\u7F51\u5173\u4E0E\u5728\u7EBF\u6A21\u578B\u914D\u7F6E\u3002",
|
|
1606
2639
|
streamIdleTimeoutMsLabel: "\u6D41\u7A7A\u95F2\u8D85\u65F6\uFF08\u6BEB\u79D2\uFF09",
|
|
@@ -1625,6 +2658,11 @@ var zh = {
|
|
|
1625
2658
|
};
|
|
1626
2659
|
|
|
1627
2660
|
// src/usage-contract.ts
|
|
2661
|
+
function parseAccountSwitch(value) {
|
|
2662
|
+
const notice = value;
|
|
2663
|
+
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");
|
|
2664
|
+
return { fromRef: notice.fromRef, toRef: notice.toRef, reason: notice.reason, at: notice.at };
|
|
2665
|
+
}
|
|
1628
2666
|
function parseGoUsage(value) {
|
|
1629
2667
|
if (!value || typeof value !== "object") throw new Error("Invalid OpenCode Go usage response");
|
|
1630
2668
|
const source = value;
|
|
@@ -1635,9 +2673,12 @@ function parseGoUsage(value) {
|
|
|
1635
2673
|
}
|
|
1636
2674
|
result.source = source.source;
|
|
1637
2675
|
}
|
|
2676
|
+
if (source.lastSwitch !== void 0) {
|
|
2677
|
+
result.lastSwitch = parseAccountSwitch(source.lastSwitch);
|
|
2678
|
+
}
|
|
1638
2679
|
for (const key of ["rolling", "weekly", "monthly"]) {
|
|
1639
2680
|
const row = source[key];
|
|
1640
|
-
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))) {
|
|
2681
|
+
if (!row || row.status !== "ok" && row.status !== "rate-limited" || typeof row.percent !== "number" || !Number.isFinite(row.percent) || row.percent < 0 || row.percent > 100 || typeof row.resetsAt !== "string" || !Number.isFinite(Date.parse(row.resetsAt))) {
|
|
1641
2682
|
throw new Error("Invalid OpenCode Go usage response");
|
|
1642
2683
|
}
|
|
1643
2684
|
result[key] = { status: row.status, percent: row.percent, resetsAt: row.resetsAt };
|
|
@@ -1650,6 +2691,16 @@ var usageCodec = {
|
|
|
1650
2691
|
schema: { parse: parseGoUsage },
|
|
1651
2692
|
create: () => ({ parse: parseGoUsage })
|
|
1652
2693
|
};
|
|
2694
|
+
var parseRef = (value) => {
|
|
2695
|
+
if (typeof value !== "string" || !/^[A-Za-z_][A-Za-z0-9_]*$/.test(value)) throw new Error("Invalid account reference");
|
|
2696
|
+
return value;
|
|
2697
|
+
};
|
|
2698
|
+
var refCodec = {
|
|
2699
|
+
mode: "strict",
|
|
2700
|
+
typeSymbol: "dsh-opencode-go#AccountRef",
|
|
2701
|
+
schema: { parse: parseRef },
|
|
2702
|
+
create: () => ({ parse: parseRef })
|
|
2703
|
+
};
|
|
1653
2704
|
var usageRemote = {
|
|
1654
2705
|
package: "dsh-opencode-go",
|
|
1655
2706
|
descriptors: [{
|
|
@@ -1660,17 +2711,76 @@ var usageRemote = {
|
|
|
1660
2711
|
invocation: { kind: "direct" },
|
|
1661
2712
|
parameters: [],
|
|
1662
2713
|
result: usageCodec
|
|
2714
|
+
}, {
|
|
2715
|
+
id: "dsh-opencode-go#opencodeGoUsage/readAccount",
|
|
2716
|
+
service: "opencodeGoUsage",
|
|
2717
|
+
namespace: "opencodeGoUsage",
|
|
2718
|
+
method: "readAccount",
|
|
2719
|
+
invocation: { kind: "direct" },
|
|
2720
|
+
parameters: [{ name: "ref", wire: "ref", source: "json", codec: refCodec }],
|
|
2721
|
+
result: usageCodec
|
|
2722
|
+
}]
|
|
2723
|
+
};
|
|
2724
|
+
|
|
2725
|
+
// src/accounts-contract.ts
|
|
2726
|
+
function parseAccountCommand(value) {
|
|
2727
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) throw new Error("Invalid account command");
|
|
2728
|
+
const row = value;
|
|
2729
|
+
const fields = {
|
|
2730
|
+
add: ["kind", "id", "name", "key"],
|
|
2731
|
+
remove: ["kind", "ref"],
|
|
2732
|
+
select: ["kind", "ref"],
|
|
2733
|
+
rename: ["kind", "ref", "name"],
|
|
2734
|
+
"replace-key": ["kind", "ref", "key"],
|
|
2735
|
+
move: ["kind", "ref", "toIndex"],
|
|
2736
|
+
"auto-switch": ["kind", "value"]
|
|
2737
|
+
};
|
|
2738
|
+
if (typeof row.kind !== "string" || !Object.hasOwn(fields, row.kind) || Object.keys(row).some((key) => !fields[row.kind].includes(key)) || fields[row.kind].some((key) => !Object.hasOwn(row, key))) throw new Error("Invalid account command");
|
|
2739
|
+
if ("ref" in row && (typeof row.ref !== "string" || !ACCOUNT_REF_PATTERN.test(row.ref))) throw new Error("Invalid account reference");
|
|
2740
|
+
if ("name" in row && (typeof row.name !== "string" || !row.name.trim() || row.name.trim().length > 80)) throw new Error("Invalid account name");
|
|
2741
|
+
if ("key" in row && (typeof row.key !== "string" || !row.key.trim())) throw new Error("Missing account credential");
|
|
2742
|
+
if (row.kind === "add" && (typeof row.id !== "string" || !/^[a-f0-9]{32}$/.test(row.id))) throw new Error("Invalid account operation ID");
|
|
2743
|
+
if (row.kind === "move" && (!Number.isInteger(row.toIndex) || row.toIndex < 0)) throw new Error("Invalid account position");
|
|
2744
|
+
if (row.kind === "auto-switch" && typeof row.value !== "boolean") throw new Error("Invalid account switch");
|
|
2745
|
+
return { ...row };
|
|
2746
|
+
}
|
|
2747
|
+
function parseResult(value) {
|
|
2748
|
+
if (value !== "applied" && value !== "rejected" && value !== "unknown") throw new Error("Invalid account command result");
|
|
2749
|
+
return value;
|
|
2750
|
+
}
|
|
2751
|
+
var commandCodec = {
|
|
2752
|
+
mode: "strict",
|
|
2753
|
+
typeSymbol: "dsh-opencode-go#AccountCommand",
|
|
2754
|
+
schema: { parse: parseAccountCommand },
|
|
2755
|
+
create: () => ({ parse: parseAccountCommand })
|
|
2756
|
+
};
|
|
2757
|
+
var resultCodec = {
|
|
2758
|
+
mode: "strict",
|
|
2759
|
+
typeSymbol: "dsh-opencode-go#AccountCommandResult",
|
|
2760
|
+
schema: { parse: parseResult },
|
|
2761
|
+
create: () => ({ parse: parseResult })
|
|
2762
|
+
};
|
|
2763
|
+
var accountsRemote = {
|
|
2764
|
+
package: "dsh-opencode-go",
|
|
2765
|
+
descriptors: [{
|
|
2766
|
+
id: "dsh-opencode-go#opencodeGoAccounts/execute",
|
|
2767
|
+
service: "opencodeGoAccounts",
|
|
2768
|
+
namespace: "opencodeGoAccounts",
|
|
2769
|
+
method: "execute",
|
|
2770
|
+
invocation: { kind: "direct" },
|
|
2771
|
+
parameters: [{ name: "command", wire: "command", source: "json", codec: commandCodec }],
|
|
2772
|
+
result: resultCodec
|
|
1663
2773
|
}]
|
|
1664
2774
|
};
|
|
1665
2775
|
|
|
1666
2776
|
// src/remote-contract.ts
|
|
1667
2777
|
var goRemote = {
|
|
1668
2778
|
package: "dsh-opencode-go",
|
|
1669
|
-
descriptors: [...usageRemote.descriptors, ...modelsRemote.descriptors]
|
|
2779
|
+
descriptors: [...usageRemote.descriptors, ...modelsRemote.descriptors, ...accountsRemote.descriptors]
|
|
1670
2780
|
};
|
|
1671
2781
|
|
|
1672
2782
|
// src/client/UsagePill.tsx
|
|
1673
|
-
var
|
|
2783
|
+
var import_react4 = require("react");
|
|
1674
2784
|
|
|
1675
2785
|
// plugin-css:src/client/UsagePill.module.css
|
|
1676
2786
|
var id2 = "dsh-opencode-go/UsagePill.module.css";
|
|
@@ -1678,20 +2788,29 @@ if (!document.querySelector("style[data-plugin-css=" + JSON.stringify(id2) + "]"
|
|
|
1678
2788
|
const style = document.createElement("style");
|
|
1679
2789
|
style.dataset.plugin = "dsh-opencode-go";
|
|
1680
2790
|
style.dataset.pluginCss = id2;
|
|
1681
|
-
style.textContent =
|
|
2791
|
+
style.textContent = '.mAjYhq_root{min-width:0;display:inline-flex;position:relative}.mAjYhq_trigger{color:inherit;opacity:.75;font:inherit;cursor:pointer;white-space:nowrap;background:0 0;border:0;border-radius:6px;padding:4px 6px;font-size:12px}.mAjYhq_trigger:hover,.mAjYhq_trigger:focus-visible{opacity:1;background:color-mix(in srgb, currentColor 8%, transparent)}.mAjYhq_account{text-overflow:ellipsis;vertical-align:bottom;max-width:12ch;display:inline-block;overflow:hidden}@container (width<=460px){.mAjYhq_brand,.mAjYhq_stale,.mAjYhq_account,.mAjYhq_fallback{display:none}.mAjYhq_reading[data-stale]:after{content:"*"}.mAjYhq_trigger[data-fallback]:after{content:" \u21B3"}}@container (width<=360px){.mAjYhq_unit{display:none}}.mAjYhq_panel{z-index:100;box-sizing:border-box;border-radius:var(--dsw-radius-lg,16px);width:320px;max-width:calc(100vw - 32px);max-height:70vh;color:var(--dsw-alias-label-primary,CanvasText);isolation:isolate;--dsw-elevation-stroke-color:var(--dsw-alias-border-l1,color-mix(in srgb, currentColor 10%, transparent));box-shadow:var(--dsw-elevation-prominent,0 8px 30px #0003);border:0;flex-direction:column;font-size:12px;display:flex;position:absolute;bottom:calc(100% + 12px);right:0}.mAjYhq_material{z-index:-1;border-radius:inherit;pointer-events:none;background:var(--dsw-menu-surface-fill,var(--dsw-specific-menu,#43454a73));backdrop-filter:var(--dsw-menu-backdrop-filter,blur(40px) saturate(150%));position:absolute;inset:0}@supports not (backdrop-filter:blur(1px)){.mAjYhq_material{background:var(--dsw-alias-bg-layer-2,Canvas)}}.mAjYhq_body{overscroll-behavior:contain;box-sizing:border-box;flex-direction:column;flex:1;gap:6px;min-height:0;padding:10px;display:flex;overflow-y:auto}.mAjYhq_panelTitle,.mAjYhq_panelHead{color:var(--dsw-alias-label-tertiary,currentColor);flex:none;padding:2px 6px 0;font-size:11.5px;line-height:1.6}.mAjYhq_panelHead{align-items:center;gap:6px;display:flex}.mAjYhq_panelHead strong{color:var(--dsw-alias-label-primary,CanvasText);font-size:12px;font-weight:600}.mAjYhq_back{width:18px;height:18px;color:inherit;cursor:pointer;background:0 0;border:0;border-radius:5px;place-items:center;padding:0;display:grid}.mAjYhq_back:hover{background:color-mix(in srgb, currentColor 8%, transparent)}.mAjYhq_icon{flex:none;width:14px;height:14px}.mAjYhq_tick{color:#39a878;flex:none;width:14px;height:14px}.mAjYhq_tile{background:color-mix(in srgb, currentColor 6%, transparent);border-radius:10px;flex:none;overflow:hidden}.mAjYhq_divider{background:color-mix(in srgb, currentColor 10%, transparent);height:.5px;margin:0 12px}.mAjYhq_accHead{align-items:center;gap:8px;min-height:42px;padding:0 12px;display:flex}.mAjYhq_dot{background:#39a878;border-radius:50%;flex:none;width:7px;height:7px}.mAjYhq_accName{text-overflow:ellipsis;white-space:nowrap;flex:1;min-width:0;font-size:13.5px;font-weight:600;overflow:hidden}.mAjYhq_tag{color:#39a878;background:#39a8781f;border:.5px solid #39a87873;border-radius:999px;flex:none;padding:0 7px;font-size:10.5px;line-height:1.7}.mAjYhq_switch{font:inherit;color:var(--dsw-alias-label-tertiary,currentColor);cursor:pointer;background:0 0;border:0;border-radius:6px;flex:none;align-items:center;gap:3px;padding:3px 6px;font-size:11.5px;display:inline-flex}.mAjYhq_switch:hover:not(:disabled){background:color-mix(in srgb, currentColor 8%, transparent)}.mAjYhq_switch:disabled{opacity:.55;cursor:default}.mAjYhq_option{width:100%;min-height:38px;font:inherit;text-align:left;cursor:pointer;background:0 0;border:0;align-items:center;gap:8px;padding:0 12px;display:flex}.mAjYhq_option:hover:not(:disabled){background:color-mix(in srgb, currentColor 6%, transparent)}.mAjYhq_option:disabled{opacity:.6;cursor:default}.mAjYhq_optionName{text-overflow:ellipsis;white-space:nowrap;min-width:0;color:var(--dsw-alias-label-secondary,currentColor);flex:1;font-size:13px;overflow:hidden}.mAjYhq_option[data-selected] .mAjYhq_optionName{color:var(--dsw-alias-label-primary,CanvasText);font-weight:600}.mAjYhq_hint{opacity:.65;font-size:11px;line-height:1.6}.mAjYhq_warning{background:color-mix(in srgb, currentColor 6%, transparent);overflow-wrap:anywhere;border-radius:6px;margin:10px 0;padding:10px;line-height:1.5}.mAjYhq_warning p{margin:5px 0 0}.mAjYhq_retry{border:1px solid color-mix(in srgb, currentColor 25%, transparent);color:inherit;font:inherit;cursor:pointer;background:0 0;border-radius:6px;padding:5px 9px}.mAjYhq_retry:disabled{opacity:.6;cursor:default}.mAjYhq_back:focus-visible,.mAjYhq_switch:focus-visible,.mAjYhq_option:focus-visible,.mAjYhq_retry:focus-visible{outline-offset:2px;outline:2px solid}.mAjYhq_window{padding:10px 12px}.mAjYhq_windowRow{align-items:center;gap:10px;display:flex}.mAjYhq_windowLabel{width:48px;color:var(--dsw-alias-label-secondary,currentColor);flex:none;font-size:12.5px}.mAjYhq_windowPercent{text-align:right;font-variant-numeric:tabular-nums;flex:none;width:38px;font-size:13px;font-weight:650}.mAjYhq_window progress{appearance:none;background:color-mix(in srgb, currentColor 15%, transparent);border:0;border-radius:99px;flex:1;min-width:60px;height:10px;display:block}.mAjYhq_window progress::-webkit-progress-bar{background:0 0;border-radius:99px}.mAjYhq_window progress::-webkit-progress-value{background:#39a878;border-radius:99px}.mAjYhq_window progress::-moz-progress-bar{background:#39a878;border-radius:99px}.mAjYhq_windowReset{color:var(--dsw-alias-label-tertiary,currentColor);margin-top:6px;font-size:11px;line-height:1.6}.mAjYhq_foot{color:var(--dsw-alias-label-tertiary,currentColor);justify-content:space-between;align-items:center;gap:8px;padding:3px 6px 1px;font-size:11px;display:flex}.mAjYhq_window progress.mAjYhq_high::-webkit-progress-value{background:#e0a100}.mAjYhq_window progress.mAjYhq_high::-moz-progress-bar{background:#e0a100}.mAjYhq_window progress.mAjYhq_limited::-webkit-progress-value{background:#e5484d}.mAjYhq_window progress.mAjYhq_limited::-moz-progress-bar{background:#e5484d}.mAjYhq_limitedText{color:#e5484d;margin-top:2px;font-weight:600}';
|
|
1682
2792
|
document.head.appendChild(style);
|
|
1683
2793
|
}
|
|
1684
|
-
var UsagePill_default = { "high": "mAjYhq_high", "hint": "mAjYhq_hint", "limited": "mAjYhq_limited", "limitedText": "mAjYhq_limitedText", "panel": "mAjYhq_panel", "retry": "mAjYhq_retry", "root": "mAjYhq_root", "
|
|
2794
|
+
var UsagePill_default = { "accHead": "mAjYhq_accHead", "accName": "mAjYhq_accName", "account": "mAjYhq_account", "back": "mAjYhq_back", "body": "mAjYhq_body", "brand": "mAjYhq_brand", "divider": "mAjYhq_divider", "dot": "mAjYhq_dot", "fallback": "mAjYhq_fallback", "foot": "mAjYhq_foot", "high": "mAjYhq_high", "hint": "mAjYhq_hint", "icon": "mAjYhq_icon", "limited": "mAjYhq_limited", "limitedText": "mAjYhq_limitedText", "material": "mAjYhq_material", "option": "mAjYhq_option", "optionName": "mAjYhq_optionName", "panel": "mAjYhq_panel", "panelHead": "mAjYhq_panelHead", "panelTitle": "mAjYhq_panelTitle", "reading": "mAjYhq_reading", "retry": "mAjYhq_retry", "root": "mAjYhq_root", "stale": "mAjYhq_stale", "switch": "mAjYhq_switch", "tag": "mAjYhq_tag", "tick": "mAjYhq_tick", "tile": "mAjYhq_tile", "trigger": "mAjYhq_trigger", "unit": "mAjYhq_unit", "warning": "mAjYhq_warning", "window": "mAjYhq_window", "windowLabel": "mAjYhq_windowLabel", "windowPercent": "mAjYhq_windowPercent", "windowReset": "mAjYhq_windowReset", "windowRow": "mAjYhq_windowRow" };
|
|
1685
2795
|
|
|
1686
2796
|
// src/client/UsagePill.tsx
|
|
1687
|
-
var
|
|
2797
|
+
var import_jsx_runtime4 = require("react/jsx-runtime");
|
|
2798
|
+
var unchanged = () => 0;
|
|
2799
|
+
var noSubscription = () => () => {
|
|
2800
|
+
};
|
|
1688
2801
|
function usageFailure(error) {
|
|
1689
2802
|
if (error && typeof error === "object" && "code" in error && error.code === "opencode-go/usage-unavailable" && "details" in error && error.details && typeof error.details === "object") {
|
|
1690
2803
|
const details = error.details;
|
|
2804
|
+
let lastSwitch;
|
|
2805
|
+
try {
|
|
2806
|
+
if (details.lastSwitch) lastSwitch = parseAccountSwitch(details.lastSwitch);
|
|
2807
|
+
} catch {
|
|
2808
|
+
}
|
|
1691
2809
|
return {
|
|
1692
2810
|
..."message" in error && typeof error.message === "string" ? { message: error.message } : {},
|
|
1693
2811
|
retainPrevious: details.retryable === true && details.retainPrevious === true,
|
|
1694
|
-
...typeof details.source === "string" ? { source: details.source } : {}
|
|
2812
|
+
...typeof details.source === "string" ? { source: details.source } : {},
|
|
2813
|
+
...lastSwitch ? { lastSwitch } : {}
|
|
1695
2814
|
};
|
|
1696
2815
|
}
|
|
1697
2816
|
return { retainPrevious: false };
|
|
@@ -1700,24 +2819,50 @@ function usageLevel(window) {
|
|
|
1700
2819
|
if (window.status === "rate-limited" || window.percent >= 100) return UsagePill_default.limited;
|
|
1701
2820
|
return window.percent >= 80 ? UsagePill_default.high : void 0;
|
|
1702
2821
|
}
|
|
1703
|
-
function
|
|
1704
|
-
|
|
1705
|
-
|
|
1706
|
-
|
|
1707
|
-
|
|
2822
|
+
function ChevronRight() {
|
|
2823
|
+
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" }) });
|
|
2824
|
+
}
|
|
2825
|
+
function ChevronLeft() {
|
|
2826
|
+
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" }) });
|
|
2827
|
+
}
|
|
2828
|
+
function Tick() {
|
|
2829
|
+
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" }) });
|
|
2830
|
+
}
|
|
2831
|
+
function UsagePill({ directory, settings, credentialChanges, ...props }) {
|
|
2832
|
+
const state = (0, import_react4.useSyncExternalStore)(directory.subscribe, directory.getSnapshot, directory.getSnapshot);
|
|
2833
|
+
const readSettings = (0, import_react4.useCallback)(() => settings.getSnapshot(), [settings]);
|
|
2834
|
+
const subscribeSettings = (0, import_react4.useCallback)((listener) => settings.subscribe(listener), [settings]);
|
|
2835
|
+
const config = (0, import_react4.useSyncExternalStore)(subscribeSettings, readSettings, readSettings);
|
|
2836
|
+
const readChanges = (0, import_react4.useCallback)(() => credentialChanges?.getSnapshot() ?? unchanged(), [credentialChanges]);
|
|
2837
|
+
const subscribeChanges = (0, import_react4.useCallback)((listener) => credentialChanges?.subscribe(listener) ?? noSubscription(), [credentialChanges]);
|
|
2838
|
+
const credentialRevision = (0, import_react4.useSyncExternalStore)(subscribeChanges, readChanges, readChanges);
|
|
1708
2839
|
const mode = config.value?.usageDisplay ?? DEFAULT_USAGE_DISPLAY;
|
|
1709
2840
|
const visible = config.status === "ready" && config.value?.enabled !== false && (mode === "always" || mode === "auto" && state.current?.provider === PROVIDER_ID);
|
|
1710
|
-
|
|
2841
|
+
const accounts = accountsOf(config.value ?? {});
|
|
2842
|
+
const activeRef = accountRefOf(config.value ?? {});
|
|
2843
|
+
return visible ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
2844
|
+
ActiveUsage,
|
|
2845
|
+
{
|
|
2846
|
+
...props,
|
|
2847
|
+
accounts,
|
|
2848
|
+
activeRef,
|
|
2849
|
+
writable: config.writable
|
|
2850
|
+
},
|
|
2851
|
+
JSON.stringify([activeRef, config.value?.baseURL, config.value?.proxyURL, credentialRevision, accounts])
|
|
2852
|
+
) : null;
|
|
1711
2853
|
}
|
|
1712
|
-
function ActiveUsage({ readUsage, t, getLocale }) {
|
|
1713
|
-
const [snapshot, setSnapshot] = (0,
|
|
1714
|
-
const [failed, setFailed] = (0,
|
|
1715
|
-
const [refreshing, setRefreshing] = (0,
|
|
1716
|
-
const [open, setOpen] = (0,
|
|
1717
|
-
const
|
|
1718
|
-
const
|
|
2854
|
+
function ActiveUsage({ readUsage, t, getLocale, accounts, activeRef, writable, selectAccount }) {
|
|
2855
|
+
const [snapshot, setSnapshot] = (0, import_react4.useState)(null);
|
|
2856
|
+
const [failed, setFailed] = (0, import_react4.useState)(null);
|
|
2857
|
+
const [refreshing, setRefreshing] = (0, import_react4.useState)(false);
|
|
2858
|
+
const [open, setOpen] = (0, import_react4.useState)(false);
|
|
2859
|
+
const [switching, setSwitching] = (0, import_react4.useState)(false);
|
|
2860
|
+
const [switchFailed, setSwitchFailed] = (0, import_react4.useState)(false);
|
|
2861
|
+
const [view, setView] = (0, import_react4.useState)("usage");
|
|
2862
|
+
const root = (0, import_react4.useRef)(null);
|
|
2863
|
+
const retry = (0, import_react4.useRef)(() => {
|
|
1719
2864
|
});
|
|
1720
|
-
(0,
|
|
2865
|
+
(0, import_react4.useEffect)(() => {
|
|
1721
2866
|
let alive = true;
|
|
1722
2867
|
let busy = false;
|
|
1723
2868
|
setSnapshot(null);
|
|
@@ -1763,7 +2908,7 @@ function ActiveUsage({ readUsage, t, getLocale }) {
|
|
|
1763
2908
|
document.removeEventListener("visibilitychange", visible);
|
|
1764
2909
|
};
|
|
1765
2910
|
}, [readUsage]);
|
|
1766
|
-
(0,
|
|
2911
|
+
(0, import_react4.useEffect)(() => {
|
|
1767
2912
|
if (!open) return;
|
|
1768
2913
|
const click = (event) => {
|
|
1769
2914
|
if (!root.current?.contains(event.target)) setOpen(false);
|
|
@@ -1781,71 +2926,227 @@ function ActiveUsage({ readUsage, t, getLocale }) {
|
|
|
1781
2926
|
const current = snapshot?.reader === readUsage ? snapshot : null;
|
|
1782
2927
|
const usage = current?.usage;
|
|
1783
2928
|
const failure = failed?.reader === readUsage ? failed.failure : null;
|
|
1784
|
-
const
|
|
1785
|
-
|
|
1786
|
-
|
|
2929
|
+
const notice = usage?.lastSwitch ?? failure?.lastSwitch;
|
|
2930
|
+
const accountName = accounts.find((account) => account.apiKeyEnv === activeRef)?.name || t("accountDefault");
|
|
2931
|
+
const accountsView = view === "accounts" && accounts.length > 1;
|
|
2932
|
+
const switchable = accounts.length > 1 && writable && selectAccount !== void 0;
|
|
2933
|
+
const switchTo = (ref) => {
|
|
2934
|
+
if (ref === activeRef) {
|
|
2935
|
+
setView("usage");
|
|
2936
|
+
return;
|
|
2937
|
+
}
|
|
2938
|
+
setSwitching(true);
|
|
2939
|
+
setSwitchFailed(false);
|
|
2940
|
+
void selectAccount?.(ref).then((accepted) => {
|
|
2941
|
+
setSwitchFailed(!accepted);
|
|
2942
|
+
if (accepted) setView("usage");
|
|
2943
|
+
}).catch(() => {
|
|
2944
|
+
setSwitchFailed(true);
|
|
2945
|
+
}).finally(() => {
|
|
2946
|
+
setSwitching(false);
|
|
2947
|
+
});
|
|
2948
|
+
};
|
|
2949
|
+
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}` : ""}`;
|
|
2950
|
+
const segments = usage ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_jsx_runtime4.Fragment, { children: [
|
|
2951
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: UsagePill_default.brand, children: "Go \xB7 " }),
|
|
2952
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("span", { className: UsagePill_default.reading, "data-stale": failure ? "" : void 0, children: [
|
|
2953
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("span", { className: UsagePill_default.unit, children: [
|
|
2954
|
+
t("usageRollingShort"),
|
|
2955
|
+
" "
|
|
2956
|
+
] }),
|
|
2957
|
+
usage.rolling.percent,
|
|
2958
|
+
"%",
|
|
2959
|
+
" \xB7 ",
|
|
2960
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("span", { className: UsagePill_default.unit, children: [
|
|
2961
|
+
t("usageWeekShort"),
|
|
2962
|
+
" "
|
|
2963
|
+
] }),
|
|
2964
|
+
usage.weekly.percent,
|
|
2965
|
+
"%"
|
|
2966
|
+
] }),
|
|
2967
|
+
failure ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("span", { className: UsagePill_default.stale, children: [
|
|
2968
|
+
" \xB7 ",
|
|
2969
|
+
t("usageStaleShort")
|
|
2970
|
+
] }) : null,
|
|
2971
|
+
notice ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("span", { className: UsagePill_default.fallback, children: [
|
|
2972
|
+
" \xB7 ",
|
|
2973
|
+
t("usageFallbackShort")
|
|
2974
|
+
] }) : null,
|
|
2975
|
+
accounts.length > 1 ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("span", { className: UsagePill_default.account, children: [
|
|
2976
|
+
" \xB7 ",
|
|
2977
|
+
accountName
|
|
2978
|
+
] }) : null
|
|
2979
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_jsx_runtime4.Fragment, { children: [
|
|
2980
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: UsagePill_default.brand, children: "Go \xB7 " }),
|
|
2981
|
+
failure ? t("usageUnavailable") : "\u2026",
|
|
2982
|
+
notice ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("span", { className: UsagePill_default.fallback, children: [
|
|
2983
|
+
" \xB7 ",
|
|
2984
|
+
t("usageFallbackShort")
|
|
2985
|
+
] }) : null,
|
|
2986
|
+
accounts.length > 1 ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("span", { className: UsagePill_default.account, children: [
|
|
2987
|
+
" \xB7 ",
|
|
2988
|
+
accountName
|
|
2989
|
+
] }) : null
|
|
2990
|
+
] });
|
|
2991
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("span", { className: UsagePill_default.root, ref: root, children: [
|
|
2992
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
1787
2993
|
"button",
|
|
1788
2994
|
{
|
|
1789
2995
|
type: "button",
|
|
1790
2996
|
className: UsagePill_default.trigger,
|
|
1791
2997
|
"aria-expanded": open,
|
|
1792
2998
|
"aria-haspopup": "dialog",
|
|
2999
|
+
"data-fallback": notice ? "" : void 0,
|
|
1793
3000
|
"aria-label": `${t("usageTitle")}: ${label}`,
|
|
3001
|
+
title: label,
|
|
1794
3002
|
onClick: () => {
|
|
1795
3003
|
setOpen(!open);
|
|
3004
|
+
setView("usage");
|
|
1796
3005
|
},
|
|
1797
|
-
children:
|
|
3006
|
+
children: segments
|
|
1798
3007
|
}
|
|
1799
3008
|
),
|
|
1800
|
-
open && /* @__PURE__ */ (0,
|
|
1801
|
-
/* @__PURE__ */ (0,
|
|
1802
|
-
/* @__PURE__ */ (0,
|
|
1803
|
-
|
|
1804
|
-
|
|
1805
|
-
|
|
1806
|
-
|
|
1807
|
-
|
|
1808
|
-
failure ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
1809
|
-
"button",
|
|
1810
|
-
{
|
|
1811
|
-
type: "button",
|
|
1812
|
-
className: UsagePill_default.retry,
|
|
1813
|
-
disabled: refreshing,
|
|
1814
|
-
onClick: () => {
|
|
1815
|
-
retry.current();
|
|
1816
|
-
},
|
|
1817
|
-
children: t(refreshing ? "usageRefreshing" : "usageRetry")
|
|
1818
|
-
}
|
|
1819
|
-
) : null,
|
|
1820
|
-
current ? /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("p", { className: UsagePill_default.hint, children: [
|
|
1821
|
-
t("usageLastUpdated"),
|
|
1822
|
-
" ",
|
|
1823
|
-
new Date(current.updatedAt).toLocaleString(getLocale?.())
|
|
1824
|
-
] }) : null,
|
|
1825
|
-
usage ? ["rolling", "weekly", "monthly"].map((key) => /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: UsagePill_default.window, children: [
|
|
1826
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: UsagePill_default.row, children: [
|
|
1827
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { children: t(`usage_${key}`) }),
|
|
1828
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("strong", { children: [
|
|
1829
|
-
usage[key].percent,
|
|
1830
|
-
"%"
|
|
1831
|
-
] })
|
|
3009
|
+
open && /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: UsagePill_default.panel, role: "dialog", "aria-label": t("usageTitle"), "aria-busy": refreshing, children: [
|
|
3010
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: UsagePill_default.material, "aria-hidden": "true" }),
|
|
3011
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: UsagePill_default.body, children: accountsView ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_jsx_runtime4.Fragment, { children: [
|
|
3012
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: UsagePill_default.panelHead, children: [
|
|
3013
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("button", { type: "button", className: UsagePill_default.back, "aria-label": t("accountSwitchBack"), onClick: () => {
|
|
3014
|
+
setView("usage");
|
|
3015
|
+
}, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(ChevronLeft, {}) }),
|
|
3016
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("strong", { children: t("accountSwitchTitle") })
|
|
1832
3017
|
] }),
|
|
1833
|
-
/* @__PURE__ */ (0,
|
|
1834
|
-
|
|
1835
|
-
|
|
3018
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
3019
|
+
"div",
|
|
3020
|
+
{
|
|
3021
|
+
className: UsagePill_default.tile,
|
|
3022
|
+
role: "listbox",
|
|
3023
|
+
"aria-label": t("accountSwitchTitle"),
|
|
3024
|
+
onKeyDown: (event) => {
|
|
3025
|
+
if (event.key === "Escape") {
|
|
3026
|
+
event.stopPropagation();
|
|
3027
|
+
setView("usage");
|
|
3028
|
+
return;
|
|
3029
|
+
}
|
|
3030
|
+
const step = event.key === "ArrowDown" ? 1 : event.key === "ArrowUp" ? -1 : 0;
|
|
3031
|
+
if (step === 0) return;
|
|
3032
|
+
event.preventDefault();
|
|
3033
|
+
const options = Array.from(event.currentTarget.querySelectorAll('[role="option"]'));
|
|
3034
|
+
const at = options.indexOf(document.activeElement);
|
|
3035
|
+
options[(at + step + options.length) % options.length]?.focus();
|
|
3036
|
+
},
|
|
3037
|
+
children: accounts.map((account, index) => /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_react4.Fragment, { children: [
|
|
3038
|
+
index ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: UsagePill_default.divider }) : null,
|
|
3039
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
|
|
3040
|
+
"button",
|
|
3041
|
+
{
|
|
3042
|
+
type: "button",
|
|
3043
|
+
role: "option",
|
|
3044
|
+
"aria-selected": account.apiKeyEnv === activeRef,
|
|
3045
|
+
"data-selected": account.apiKeyEnv === activeRef ? "" : void 0,
|
|
3046
|
+
className: UsagePill_default.option,
|
|
3047
|
+
disabled: switching,
|
|
3048
|
+
onClick: () => {
|
|
3049
|
+
switchTo(account.apiKeyEnv);
|
|
3050
|
+
},
|
|
3051
|
+
children: [
|
|
3052
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: UsagePill_default.optionName, children: account.name || t("accountDefault") }),
|
|
3053
|
+
account.apiKeyEnv === activeRef ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Tick, {}) : null
|
|
3054
|
+
]
|
|
3055
|
+
}
|
|
3056
|
+
)
|
|
3057
|
+
] }, account.id))
|
|
3058
|
+
}
|
|
3059
|
+
),
|
|
3060
|
+
switchFailed ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: UsagePill_default.warning, role: "alert", children: t("accountSwitchFailed") }) : null,
|
|
3061
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: UsagePill_default.hint, children: t("accountSwitchHint") })
|
|
3062
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_jsx_runtime4.Fragment, { children: [
|
|
3063
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: UsagePill_default.panelTitle, children: t("usageTitle") }),
|
|
3064
|
+
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: [
|
|
3065
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: UsagePill_default.dot }),
|
|
3066
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: UsagePill_default.accName, children: accountName }),
|
|
3067
|
+
accounts.length > 1 ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: UsagePill_default.tag, children: t("accountPreferredTag") }) : null,
|
|
3068
|
+
accounts.length > 1 ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
|
|
3069
|
+
"button",
|
|
3070
|
+
{
|
|
3071
|
+
type: "button",
|
|
3072
|
+
className: UsagePill_default.switch,
|
|
3073
|
+
disabled: !switchable || switching,
|
|
3074
|
+
"aria-haspopup": "listbox",
|
|
3075
|
+
onClick: () => {
|
|
3076
|
+
setView("accounts");
|
|
3077
|
+
},
|
|
3078
|
+
children: [
|
|
3079
|
+
t("accountSwitchAction"),
|
|
3080
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(ChevronRight, {})
|
|
3081
|
+
]
|
|
3082
|
+
}
|
|
3083
|
+
) : null
|
|
3084
|
+
] }) }) : null,
|
|
3085
|
+
switchFailed ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: UsagePill_default.warning, role: "alert", children: t("accountSwitchFailed") }) : null,
|
|
3086
|
+
notice ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("p", { className: UsagePill_default.warning, role: "status", children: [
|
|
3087
|
+
t(notice.reason === "quota" ? "accountFallbackQuota" : "accountFallbackCredential"),
|
|
1836
3088
|
" ",
|
|
1837
|
-
|
|
1838
|
-
|
|
1839
|
-
|
|
1840
|
-
|
|
3089
|
+
accounts.find((account) => account.apiKeyEnv === notice.toRef)?.name || t("accountDefault"),
|
|
3090
|
+
" \xB7 ",
|
|
3091
|
+
new Date(notice.at).toLocaleString(getLocale?.())
|
|
3092
|
+
] }) : null,
|
|
3093
|
+
failure ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: UsagePill_default.warning, role: "alert", children: [
|
|
3094
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("strong", { children: t("usageRefreshFailed") }),
|
|
3095
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { children: failure.message ?? t("usageUnavailable") }),
|
|
3096
|
+
usage ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { children: t("usageStaleHint") }) : null
|
|
3097
|
+
] }) : null,
|
|
3098
|
+
failure ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
3099
|
+
"button",
|
|
3100
|
+
{
|
|
3101
|
+
type: "button",
|
|
3102
|
+
className: UsagePill_default.retry,
|
|
3103
|
+
disabled: refreshing,
|
|
3104
|
+
onClick: () => {
|
|
3105
|
+
retry.current();
|
|
3106
|
+
},
|
|
3107
|
+
children: t(refreshing ? "usageRefreshing" : "usageRetry")
|
|
3108
|
+
}
|
|
3109
|
+
) : null,
|
|
3110
|
+
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: [
|
|
3111
|
+
index ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: UsagePill_default.divider }) : null,
|
|
3112
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: UsagePill_default.window, children: [
|
|
3113
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: UsagePill_default.windowRow, children: [
|
|
3114
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: UsagePill_default.windowLabel, children: t(`usage_${key}`) }),
|
|
3115
|
+
/* @__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) }),
|
|
3116
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("strong", { className: UsagePill_default.windowPercent, children: [
|
|
3117
|
+
usage[key].percent,
|
|
3118
|
+
"%"
|
|
3119
|
+
] })
|
|
3120
|
+
] }),
|
|
3121
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: UsagePill_default.windowReset, children: [
|
|
3122
|
+
t("usageResets"),
|
|
3123
|
+
" ",
|
|
3124
|
+
new Date(usage[key].resetsAt).toLocaleString(getLocale?.())
|
|
3125
|
+
] }),
|
|
3126
|
+
usage[key].status === "rate-limited" && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: UsagePill_default.limitedText, children: t("usageLimited") })
|
|
3127
|
+
] })
|
|
3128
|
+
] }, key)) }) : failure ? null : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: UsagePill_default.hint, children: t("usageLoading") }),
|
|
3129
|
+
current ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: UsagePill_default.foot, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("span", { children: [
|
|
3130
|
+
t("usageLastUpdated"),
|
|
3131
|
+
" ",
|
|
3132
|
+
new Date(current.updatedAt).toLocaleString(getLocale?.())
|
|
3133
|
+
] }) }) : null
|
|
3134
|
+
] }) })
|
|
1841
3135
|
] })
|
|
1842
3136
|
] });
|
|
1843
3137
|
}
|
|
1844
3138
|
|
|
1845
3139
|
// src/client/usage.ts
|
|
1846
|
-
|
|
3140
|
+
var import_dsh_client_store2 = require("@deepseek-ai/dsh-client-store");
|
|
3141
|
+
function registerUsagePill(ctx, settings, selectAccount) {
|
|
1847
3142
|
ctx.inject(["modelDirectories", "sessions", "remote.session"], (scope) => {
|
|
1848
3143
|
scope.inject(["remote.opencodeGoUsage"], (ready) => {
|
|
3144
|
+
const credentialChanges = (0, import_dsh_client_store2.createSnapshotStore)(0);
|
|
3145
|
+
ready.effect(() => ready.remote.$on("credentials/reference-updated", (ref) => {
|
|
3146
|
+
if (accountsOf(settings.getSnapshot().value ?? {}).some((account) => account.apiKeyEnv === ref)) {
|
|
3147
|
+
credentialChanges.set(credentialChanges.getSnapshot() + 1);
|
|
3148
|
+
}
|
|
3149
|
+
}));
|
|
1849
3150
|
const readUsage = async () => {
|
|
1850
3151
|
const result = await ready.remote.opencodeGoUsage.read();
|
|
1851
3152
|
if (!result.ok) throw result.error;
|
|
@@ -1859,6 +3160,12 @@ function registerUsagePill(ctx, settings) {
|
|
|
1859
3160
|
inject: (sessionId) => ({
|
|
1860
3161
|
directory: ready.modelDirectories.directoryFor(sessionId).store,
|
|
1861
3162
|
settings,
|
|
3163
|
+
credentialChanges,
|
|
3164
|
+
selectAccount: async (ref) => {
|
|
3165
|
+
const snapshot = settings.getSnapshot();
|
|
3166
|
+
if (!snapshot.writable || !accountsOf(snapshot.value ?? {}).some((account) => account.apiKeyEnv === ref)) return false;
|
|
3167
|
+
return selectAccount ? selectAccount(ref).catch(() => false) : false;
|
|
3168
|
+
},
|
|
1862
3169
|
readUsage,
|
|
1863
3170
|
getLocale: () => ready.locale.getLocale().active,
|
|
1864
3171
|
t: (key) => translate(key)
|
|
@@ -1868,6 +3175,37 @@ function registerUsagePill(ctx, settings) {
|
|
|
1868
3175
|
});
|
|
1869
3176
|
}
|
|
1870
3177
|
|
|
3178
|
+
// src/client/host-compat.ts
|
|
3179
|
+
function mountSettingsScopes(ctx, mount) {
|
|
3180
|
+
ctx.inject(["configForms", "remote.opencodeGoModels"], (child) => {
|
|
3181
|
+
const forms = child.get("configForms");
|
|
3182
|
+
mount(child, forms.get(PROFILE_ENTRY_ID));
|
|
3183
|
+
});
|
|
3184
|
+
ctx.inject(["settingsScope", "remote.opencodeGoModels"], (child) => {
|
|
3185
|
+
mount(child, child.settingsScope.bind({
|
|
3186
|
+
namespace: SETTINGS_NAMESPACE,
|
|
3187
|
+
decode: (section) => typeof section === "object" && section !== null ? section : void 0
|
|
3188
|
+
}));
|
|
3189
|
+
});
|
|
3190
|
+
}
|
|
3191
|
+
function accountCommands(ctx) {
|
|
3192
|
+
const unavailable = async () => "unknown";
|
|
3193
|
+
let execute = unavailable;
|
|
3194
|
+
ctx.inject(["remote.opencodeGoAccounts"], (ready) => {
|
|
3195
|
+
ready.effect(() => {
|
|
3196
|
+
const connected = async (command) => {
|
|
3197
|
+
const result = await ready.remote.opencodeGoAccounts.execute(command);
|
|
3198
|
+
return result.ok ? result.value : "unknown";
|
|
3199
|
+
};
|
|
3200
|
+
execute = connected;
|
|
3201
|
+
return () => {
|
|
3202
|
+
if (execute === connected) execute = unavailable;
|
|
3203
|
+
};
|
|
3204
|
+
});
|
|
3205
|
+
});
|
|
3206
|
+
return (command) => execute(command);
|
|
3207
|
+
}
|
|
3208
|
+
|
|
1871
3209
|
// src/client/index.ts
|
|
1872
3210
|
var NS = "settings.opencode-go";
|
|
1873
3211
|
var inject = ["slots", "locale", "remote", "remote.credentials", "remote.llm"];
|
|
@@ -1875,23 +3213,27 @@ function apply(ctx) {
|
|
|
1875
3213
|
ctx.effect(() => ctx.locale.register(NS, { zh, en }), "llm-opencode-go: copy dictionaries");
|
|
1876
3214
|
const modelsReady = ctx.remote.$mount(goRemote);
|
|
1877
3215
|
ctx.effect(async () => await modelsReady);
|
|
1878
|
-
ctx
|
|
1879
|
-
const forms = child.get("configForms");
|
|
1880
|
-
mountSettings(child, forms.get("opencode-go"), modelsReady);
|
|
1881
|
-
});
|
|
1882
|
-
ctx.inject(["settingsScope", "remote.opencodeGoModels"], (child) => {
|
|
1883
|
-
mountSettings(child, child.settingsScope.bind({
|
|
1884
|
-
namespace: "llm-opencode-go",
|
|
1885
|
-
decode: (section) => typeof section === "object" && section !== null ? section : void 0
|
|
1886
|
-
}), modelsReady);
|
|
1887
|
-
});
|
|
3216
|
+
mountSettingsScopes(ctx, (child, scope) => mountSettings(child, scope, modelsReady));
|
|
1888
3217
|
}
|
|
1889
3218
|
function mountSettings(ctx, scope, modelsReady) {
|
|
1890
|
-
|
|
3219
|
+
const executeAccountCommand = accountCommands(ctx);
|
|
3220
|
+
registerUsagePill(ctx, scope, async (ref) => await executeAccountCommand({ kind: "select", ref }) === "applied");
|
|
3221
|
+
let readAccount;
|
|
3222
|
+
ctx.inject(["remote.opencodeGoUsage"], (ready) => {
|
|
3223
|
+
readAccount = async (ref) => {
|
|
3224
|
+
const result = await ready.remote.opencodeGoUsage.readAccount(ref);
|
|
3225
|
+
if (!result.ok) throw result.error;
|
|
3226
|
+
return result.value;
|
|
3227
|
+
};
|
|
3228
|
+
});
|
|
1891
3229
|
const controller = new OpencodeGoSectionController(scope, ctx, async () => {
|
|
1892
3230
|
await modelsReady;
|
|
1893
3231
|
return ctx.remote.opencodeGoModels.read();
|
|
1894
|
-
})
|
|
3232
|
+
}, async (ref) => {
|
|
3233
|
+
await modelsReady;
|
|
3234
|
+
if (readAccount === void 0) throw new Error("OpenCode Go account usage is unavailable in this session");
|
|
3235
|
+
return readAccount(ref);
|
|
3236
|
+
}, executeAccountCommand);
|
|
1895
3237
|
ctx.effect(() => () => controller.dispose());
|
|
1896
3238
|
const t = ctx.locale.bind(NS);
|
|
1897
3239
|
const injected = () => ({ ...controller.inject(), t, getLocale: () => ctx.locale.getLocale().active });
|