dsh-opencode-go 0.1.21 → 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.
Files changed (48) hide show
  1. package/README.en.md +128 -167
  2. package/README.md +126 -158
  3. package/THIRD_PARTY_NOTICES.md +3 -1
  4. package/docs/development.md +56 -6
  5. package/docs/fork-review-2026-09-25.md +191 -0
  6. package/docs/independent-package.md +2 -2
  7. package/docs/verification.md +154 -0
  8. package/lib/build-info.json +8 -1
  9. package/lib/client.js +412 -262
  10. package/lib/index.js +6763 -428
  11. package/lib/types/account-manager.d.ts +23 -0
  12. package/lib/types/account-operations.d.ts +31 -0
  13. package/lib/types/account-policy.d.ts +16 -0
  14. package/lib/types/account-recovery.d.ts +2 -0
  15. package/lib/types/account-selection.d.ts +30 -0
  16. package/lib/types/account-service.d.ts +12 -0
  17. package/lib/types/accounts-contract.d.ts +38 -0
  18. package/lib/types/accounts.d.ts +5 -0
  19. package/lib/types/adapter.d.ts +30 -10
  20. package/lib/types/call-trace.d.ts +54 -0
  21. package/lib/types/catalog-manager.d.ts +20 -0
  22. package/lib/types/catalog.d.ts +5 -3
  23. package/lib/types/client/accounts-controller.d.ts +6 -17
  24. package/lib/types/client/host-compat.d.ts +7 -0
  25. package/lib/types/client/locales.d.ts +9 -0
  26. package/lib/types/client/section-controller.d.ts +11 -46
  27. package/lib/types/client/staged-form.d.ts +1 -3
  28. package/lib/types/client/usage.d.ts +1 -1
  29. package/lib/types/config-contract.d.ts +69 -0
  30. package/lib/types/config.d.ts +12 -53
  31. package/lib/types/conversion/context.d.ts +5 -1
  32. package/lib/types/conversion/image-pool.d.ts +24 -0
  33. package/lib/types/conversion/replay.d.ts +1 -1
  34. package/lib/types/conversion/stream.d.ts +1 -1
  35. package/lib/types/gateway-diagnostics.d.ts +22 -0
  36. package/lib/types/gateway-error.d.ts +2 -0
  37. package/lib/types/host-settings.d.ts +11 -0
  38. package/lib/types/index.d.ts +1 -1
  39. package/lib/types/model-metadata.d.ts +3 -1
  40. package/lib/types/models-contract.d.ts +7 -0
  41. package/lib/types/protocol-contract.d.ts +5 -0
  42. package/lib/types/protocol-policy.d.ts +4 -0
  43. package/lib/types/reasoning.d.ts +36 -6
  44. package/lib/types/request-control.d.ts +2 -0
  45. package/lib/types/sdk-types.d.ts +1568 -0
  46. package/lib/types/settings-bridge.d.ts +22 -0
  47. package/lib/vendor-licenses.txt +103 -0
  48. package/package.json +6 -2
package/lib/client.js CHANGED
@@ -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_accounts{gap:10px;margin:12px 0;display:grid}.N807zW_accountRow{border:.5px solid var(--dsw-alias-border-l2);border-radius:10px}.N807zW_accountRow[data-dragging=true]{opacity:.55}.N807zW_accountMain{grid-template-columns:16px 112px 92px minmax(0,1fr) 38px 106px 14px;align-items:center;gap:9px;padding:9px 11px;display:grid}.N807zW_accountHandle{width:16px;height:16px;color:var(--dsw-alias-label-tertiary);cursor:grab;-webkit-user-drag:element;background:0 0;border:0;place-items:center;padding:0;display:grid}.N807zW_accountHandle:disabled{cursor:default;opacity:.5}.N807zW_accountHandle:focus-visible,.N807zW_accountToggle:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:2px;border-radius:4px}.N807zW_accountName{white-space:nowrap;text-overflow:ellipsis;min-width:0;color:var(--dsw-alias-label-primary);font-size:12.5px;font-weight:600;overflow:hidden}.N807zW_accountState{min-width:0;color:var(--dsw-alias-label-tertiary);align-items:center;gap:5px;font-size:11.5px;display:inline-flex;overflow:hidden}.N807zW_accountDot{background:#39a878;border-radius:50%;flex:none;width:6px;height:6px}.N807zW_accountDot[data-off=true]{background:#d9a441}.N807zW_accountPercent{text-align:right;font-variant-numeric:tabular-nums;color:var(--dsw-alias-label-primary);font-size:12.5px;font-weight:650}.N807zW_accountBar{background:#ffffff1a;border-radius:99px;height:12px;position:relative;overflow:hidden}.N807zW_accountBarFill{background:#39a878;border-radius:99px;position:absolute;inset:0 auto 0 0}.N807zW_accountBar[data-level=high] .N807zW_accountBarFill{background:#e0a100}.N807zW_accountBar[data-level=limited] .N807zW_accountBarFill{background:#e5484d}.N807zW_accountBarTick{background:#fff3;width:1px;position:absolute;top:0;bottom:0}.N807zW_accountReset{text-align:right;color:var(--dsw-alias-label-tertiary);font-size:11.5px}.N807zW_accountIdle{text-align:right;color:var(--dsw-alias-label-tertiary);grid-column:4/7;font-size:11.5px;line-height:1.5}.N807zW_accountToggle{color:var(--dsw-alias-label-tertiary);cursor:pointer;background:0 0;border:0;place-items:center;padding:0;display:grid}.N807zW_accountProblems{align-items:baseline;gap:8px;padding:0 11px 9px 36px;display:flex}.N807zW_accountRetry{font:inherit;color:var(--dsw-alias-brand-primary);cursor:pointer;background:0 0;border:none;flex:none;padding:0;font-size:11.5px;line-height:1.5}.N807zW_accountRetry:disabled{color:var(--dsw-alias-label-tertiary);cursor:default}.N807zW_accountHandle:active{cursor:grabbing}.N807zW_accountDetail{border-top:.5px solid var(--dsw-alias-border-l2);flex-direction:column;gap:8px;padding:9px 11px 10px 36px;display:flex}.N807zW_accountDropLine{background:var(--dsw-alias-brand-primary);border-radius:2px;height:2px}.N807zW_accountUsage{grid-template-columns:repeat(3,minmax(0,1fr));gap:12px;font-size:12px;display:grid}.N807zW_accountUsage progress{accent-color:#39a878;width:100%;height:8px;margin:6px 0;display:block}.N807zW_accountUsage progress[data-level=high]{accent-color:#e0a100}.N807zW_accountUsage progress[data-level=limited]{accent-color:#e5484d}.N807zW_accountUsage .N807zW_hint{overflow-wrap:anywhere;display:block}.N807zW_accountActions{flex-wrap:wrap;gap:8px;margin-top:10px;display:flex}.N807zW_accountEditor{border:.5px solid var(--dsw-alias-border-l2);background:color-mix(in srgb, var(--dsw-alias-bg-layer-3) 25%, transparent);border-radius:10px;flex-direction:column;gap:8px;margin:0 11px 10px 36px;padding:10px 12px;display:flex}.N807zW_accountEditorHead{align-items:baseline;gap:6px;min-width:0;display:flex}.N807zW_accountEditorTitle{color:var(--dsw-alias-label-primary);flex:none;font-size:12.5px;font-weight:600;line-height:1.5}.N807zW_accountEditorFor{min-width:0;color:var(--dsw-alias-label-tertiary);overflow-wrap:anywhere;font-size:11.5px;line-height:1.5}.N807zW_accountField{color:var(--dsw-alias-label-tertiary);flex-direction:column;gap:5px;font-size:11.5px;line-height:1.5;display:flex}.N807zW_accountEditorActions{align-items:center;gap:8px;margin-top:2px;display:flex}@media (width<=480px){.N807zW_accountUsage{grid-template-columns:1fr}}.N807zW_page{flex-direction:column;min-width:0;height:100%;min-height:0;display:flex;container-type:size}.N807zW_pageBody{scrollbar-gutter:stable;flex-direction:column;flex:1;min-height:0;padding:0 4px 16px 0;display:flex;overflow-y:auto}.N807zW_pageBody,.N807zW_modelList,.N807zW_modelDetails{scrollbar-width:thin;scrollbar-color:var(--dsw-alias-border-l3) transparent}.N807zW_pageBody::-webkit-scrollbar,.N807zW_modelList::-webkit-scrollbar,.N807zW_modelDetails::-webkit-scrollbar{width:8px;height:8px}.N807zW_pageBody::-webkit-scrollbar-track,.N807zW_modelList::-webkit-scrollbar-track,.N807zW_modelDetails::-webkit-scrollbar-track{background:0 0}.N807zW_pageBody::-webkit-scrollbar-thumb,.N807zW_modelList::-webkit-scrollbar-thumb,.N807zW_modelDetails::-webkit-scrollbar-thumb{background:var(--dsw-alias-border-l3);background-clip:content-box;border:2px solid #0000;border-radius:999px}.N807zW_pageBody:hover::-webkit-scrollbar-thumb,.N807zW_modelList:hover::-webkit-scrollbar-thumb,.N807zW_modelDetails:hover::-webkit-scrollbar-thumb{background:var(--dsw-alias-label-tertiary);background-clip:content-box}.N807zW_field{flex-direction:column;gap:6px;padding:12px 0;display:flex}.N807zW_field+.N807zW_field{border-top:.5px solid var(--dsw-alias-border-l2)}.N807zW_head{align-items:center;gap:8px;display:flex}.N807zW_label{min-width:0;color:var(--dsw-alias-label-primary);flex:1;font-size:13px;font-weight:500;line-height:1.5}.N807zW_badges{align-items:center;gap:8px;display:inline-flex}.N807zW_trailing{flex:none;align-items:center;gap:8px;display:inline-flex}.N807zW_reset{font:inherit;color:var(--dsw-alias-label-secondary);cursor:pointer;background:0 0;border:none;padding:0;font-size:12px;line-height:1.5}.N807zW_reset:hover:not(:disabled){color:var(--dsw-alias-label-primary)}.N807zW_reset:disabled{cursor:default}.N807zW_reset:focus-visible,.N807zW_cardTrigger:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:3px}.N807zW_input{border:.5px solid var(--dsw-alias-border-l4);background:var(--dsw-alias-bg-layer-3);height:34px;font:inherit;color:var(--dsw-alias-label-primary);border-radius:8px;padding:0 12px;font-size:13px;line-height:1.5}.N807zW_input:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:1px;border-color:var(--dsw-alias-brand-primary)}.N807zW_input:disabled{color:var(--dsw-alias-label-tertiary);cursor:default}.N807zW_inputInvalid{border-color:var(--dsw-alias-label-error);}.N807zW_invalid{color:var(--dsw-alias-label-error);margin:0;font-size:12px;line-height:1.5}.N807zW_hint{color:var(--dsw-alias-label-tertiary);margin:0;font-size:12px;line-height:1.5}.N807zW_pageTop{flex-direction:column;gap:3px;padding:2px 0 12px;display:flex}.N807zW_title{color:var(--dsw-alias-label-primary);margin:0;font-size:15px;font-weight:600;line-height:1.4}.N807zW_intro{color:var(--dsw-alias-label-secondary);margin:0;font-size:13px;line-height:1.5}.N807zW_card,.N807zW_cardModels{border:.5px solid var(--dsw-alias-border-l2);background:color-mix(in srgb, var(--dsw-alias-bg-layer-3) 40%, transparent);border-radius:12px;padding:8px 0 10px}.N807zW_card{flex:none}.N807zW_card+.N807zW_card,.N807zW_card+.N807zW_cardModels,.N807zW_cardModels+.N807zW_card{margin-top:8px}.N807zW_cardModels{flex-direction:column;flex:1 0 auto;display:flex}.N807zW_cardFolded{flex:none}.N807zW_cardHead{align-items:center;gap:8px;min-height:24px;padding:0 14px;display:flex}.N807zW_cardTitle{min-width:0;color:var(--dsw-alias-label-primary);flex:1;font-size:13.5px;font-weight:600;line-height:1.5}.N807zW_cardSub{color:var(--dsw-alias-label-tertiary);flex:none;font-size:11.5px;line-height:1.5}.N807zW_cardStamp{white-space:nowrap;color:var(--dsw-alias-label-tertiary);flex:none;font-size:11.5px;line-height:1.5}.N807zW_cardBody{flex-direction:column;gap:8px;padding:4px 14px 0;display:flex}.N807zW_cardBody>.N807zW_input{box-sizing:border-box;width:100%}.N807zW_cardModels>.N807zW_cardBody{flex:1 0 auto}.N807zW_cardNotes{flex-direction:column;gap:8px;padding:6px 14px 2px;display:flex}.N807zW_cardNotes:empty{display:none}.N807zW_cardDivider{border-top:.5px solid var(--dsw-alias-border-l2);margin:10px 14px}.N807zW_cardTrigger{width:100%;min-height:24px;font:inherit;text-align:left;color:inherit;cursor:pointer;background:0 0;border:none;align-items:center;gap:8px;margin:0;padding:0 14px;display:flex}.N807zW_cardTrigger:hover .N807zW_cardTitle{color:var(--dsw-alias-brand-primary)}.N807zW_cardHead>.N807zW_cardTrigger{padding:0}.N807zW_advancedGrid{grid-template-columns:minmax(0,1fr) minmax(0,1fr);gap:12px 18px;display:grid}.N807zW_advancedGrid .N807zW_field{padding:0}.N807zW_advancedGrid .N807zW_field+.N807zW_field{border-top:none}.N807zW_limitsEditor{flex-direction:column;flex:1 0 auto;gap:10px;padding-top:4px;display:flex}.N807zW_limitsFoot{border-top:.5px solid var(--dsw-alias-border-l2);align-items:center;gap:8px;margin:2px -14px 0;padding:10px 14px 0;display:flex}.N807zW_limitsSummary{min-width:0;color:var(--dsw-alias-label-tertiary);white-space:nowrap;flex:1;font-size:12px;line-height:1.5}.N807zW_modelMeta{align-items:baseline;gap:10px;display:flex}.N807zW_modelMeta .N807zW_limitsModelId{flex:1;min-width:0}.N807zW_releaseDate{color:var(--dsw-alias-label-tertiary);font-variant-numeric:tabular-nums;flex:none;font-size:11px;line-height:1.4}.N807zW_limitsModelId{text-overflow:ellipsis;white-space:nowrap;color:var(--dsw-alias-label-tertiary);font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:11px;line-height:1.4;display:block;overflow:hidden}.N807zW_visuallyHidden{clip:rect(0, 0, 0, 0);white-space:nowrap;border:0;width:1px;height:1px;margin:-1px;padding:0;position:absolute;overflow:hidden}.N807zW_actions{border-top:.5px solid var(--dsw-alias-border-l2);flex-wrap:wrap;flex:none;align-items:center;gap:8px;padding:12px 0;display:flex}.N807zW_starLink{max-width:100%;color:var(--dsw-alias-label-secondary);border-radius:4px;align-items:center;gap:7px;margin-left:auto;padding:6px 0;font-size:12px;line-height:1.5;text-decoration:none;display:inline-flex}.N807zW_starLink svg{flex:none}.N807zW_starLink:hover{color:var(--dsw-alias-brand-primary)}.N807zW_starLink:hover span{text-underline-offset:3px;text-decoration:underline}.N807zW_starLink:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:3px}.N807zW_failedNote{color:var(--dsw-alias-label-error);margin:0;font-size:12px;line-height:1.5}.N807zW_slot{width:16px;height:16px;color:var(--dsw-alias-label-tertiary);flex:none;justify-content:center;align-items:center;display:inline-flex}.N807zW_slot svg{width:15px;height:15px}.N807zW_chevron,.N807zW_chevronOpen{width:14px;height:14px;color:var(--dsw-alias-label-tertiary);flex:none;transition:transform .15s}.N807zW_chevron{transform:rotate(-90deg)}.N807zW_filters{flex-wrap:wrap;align-items:center;gap:6px;display:flex}.N807zW_filterAction{align-items:center;margin-left:auto;display:inline-flex}.N807zW_filter{font:inherit;color:var(--dsw-alias-label-secondary);cursor:pointer;background:0 0;border:0;border-radius:6px;padding:6px 9px;font-size:12px}.N807zW_filter[aria-pressed=true]{color:var(--dsw-alias-label-primary);background:var(--dsw-alias-bg-layer-3)}.N807zW_filter span{color:var(--dsw-alias-label-tertiary);margin-left:4px}.N807zW_modelLayout{border:.5px solid var(--dsw-alias-border-l4);border-radius:10px;flex:auto;grid-template-columns:minmax(0,45fr) minmax(0,55fr);min-height:260px;max-height:560px;display:grid;overflow:hidden}.N807zW_modelList{border-right:.5px solid var(--dsw-alias-border-l2);min-height:0;padding:4px 6px;overflow-y:auto}.N807zW_modelRow{align-items:center;gap:8px;padding-right:6px;display:flex}.N807zW_modelRow+.N807zW_modelRow{border-top:.5px solid var(--dsw-alias-border-l2)}.N807zW_modelRowSelected{background:var(--dsw-alias-bg-layer-3);border-top-color:#0000;border-radius:6px}.N807zW_modelRow>[role=switch]{flex-shrink:0}.N807zW_modelChoice{text-align:left;min-width:0;color:var(--dsw-alias-label-primary);cursor:pointer;background:0 0;border:0;border-radius:6px;flex:1;align-items:baseline;padding:9px 3px 9px 6px;display:flex}.N807zW_modelRow:hover:not(.N807zW_modelRowSelected){background:color-mix(in srgb, var(--dsw-alias-bg-layer-3) 92%, var(--dsw-alias-label-primary));border-top-color:#0000;border-radius:6px}.N807zW_modelName{overflow-wrap:anywhere;flex-wrap:wrap;flex:0 auto;align-items:center;gap:5px;min-width:0;font-size:13px;display:flex}.N807zW_overrideDot{background:var(--dsw-alias-brand-primary);border-radius:50%;flex:none;width:6px;height:6px}.N807zW_modelDetails{flex-direction:column;gap:10px;min-height:0;padding:14px;display:flex;overflow-y:auto}.N807zW_modelDetails h3{overflow-wrap:anywhere;margin:0;font-size:14px}.N807zW_modelHeading{flex-wrap:wrap;align-items:center;gap:6px;display:flex}.N807zW_stats{flex-direction:column;gap:10px;display:flex}.N807zW_stat{flex-direction:column;gap:4px;display:flex}.N807zW_statLabel{color:var(--dsw-alias-label-tertiary);font-size:11px;line-height:1.5}.N807zW_modelDetails .N807zW_input{box-sizing:border-box;width:100%;min-width:0;height:30px;padding:0 9px;font-size:12px}.N807zW_modalities{flex-wrap:wrap;gap:4px;display:flex}.N807zW_modality,.N807zW_modalityOff{border-radius:6px;padding:2px 7px;font-size:11px;line-height:1.5}.N807zW_modality{background:var(--dsw-alias-bg-layer-3);color:var(--dsw-alias-label-secondary)}.N807zW_modalityOff{border:.5px dashed var(--dsw-alias-border-l4);color:var(--dsw-alias-label-tertiary)}.N807zW_modelDetails .N807zW_reset{align-self:flex-start}.N807zW_paneFoot{color:var(--dsw-alias-label-tertiary);margin:auto 0 0;font-size:11px;line-height:1.5}.N807zW_newBadge{color:var(--dsw-alias-label-primary);background:var(--dsw-alias-bg-layer-3);border:.5px solid var(--dsw-alias-border-l4);border-radius:4px;padding:2px 4px;font-size:9px}.N807zW_modelChoice:focus-visible,.N807zW_filter:focus-visible,.N807zW_cardTrigger:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:-2px}@container (width<=440px){.N807zW_advancedGrid{grid-template-columns:minmax(0,1fr)}.N807zW_modelLayout{flex:none;grid-template-columns:minmax(0,1fr);max-height:none}.N807zW_modelList{border-right:0;border-bottom:.5px solid var(--dsw-alias-border-l2);max-height:240px}.N807zW_modelDetails{max-height:460px}}@media (prefers-reduced-motion:reduce){.N807zW_chevron,.N807zW_chevronOpen{transition:none}}";
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 = { "accountActions": "N807zW_accountActions", "accountBar": "N807zW_accountBar", "accountBarFill": "N807zW_accountBarFill", "accountBarTick": "N807zW_accountBarTick", "accountDetail": "N807zW_accountDetail", "accountDot": "N807zW_accountDot", "accountDropLine": "N807zW_accountDropLine", "accountEditor": "N807zW_accountEditor", "accountEditorActions": "N807zW_accountEditorActions", "accountEditorFor": "N807zW_accountEditorFor", "accountEditorHead": "N807zW_accountEditorHead", "accountEditorTitle": "N807zW_accountEditorTitle", "accountField": "N807zW_accountField", "accountHandle": "N807zW_accountHandle", "accountIdle": "N807zW_accountIdle", "accountMain": "N807zW_accountMain", "accountName": "N807zW_accountName", "accountPercent": "N807zW_accountPercent", "accountProblems": "N807zW_accountProblems", "accountReset": "N807zW_accountReset", "accountRetry": "N807zW_accountRetry", "accountRow": "N807zW_accountRow", "accountState": "N807zW_accountState", "accountToggle": "N807zW_accountToggle", "accountUsage": "N807zW_accountUsage", "accounts": "N807zW_accounts", "actions": "N807zW_actions", "advancedGrid": "N807zW_advancedGrid", "badges": "N807zW_badges", "card": "N807zW_card", "cardBody": "N807zW_cardBody", "cardDivider": "N807zW_cardDivider", "cardFolded": "N807zW_cardFolded", "cardHead": "N807zW_cardHead", "cardModels": "N807zW_cardModels", "cardNotes": "N807zW_cardNotes", "cardStamp": "N807zW_cardStamp", "cardSub": "N807zW_cardSub", "cardTitle": "N807zW_cardTitle", "cardTrigger": "N807zW_cardTrigger", "chevron": "N807zW_chevron", "chevronOpen": "N807zW_chevronOpen", "failedNote": "N807zW_failedNote", "field": "N807zW_field", "filter": "N807zW_filter", "filterAction": "N807zW_filterAction", "filters": "N807zW_filters", "head": "N807zW_head", "hint": "N807zW_hint", "input": "N807zW_input", "inputInvalid": "N807zW_inputInvalid N807zW_input", "intro": "N807zW_intro", "invalid": "N807zW_invalid", "label": "N807zW_label", "limitsEditor": "N807zW_limitsEditor", "limitsFoot": "N807zW_limitsFoot", "limitsModelId": "N807zW_limitsModelId", "limitsSummary": "N807zW_limitsSummary", "modalities": "N807zW_modalities", "modality": "N807zW_modality", "modalityOff": "N807zW_modalityOff", "modelChoice": "N807zW_modelChoice", "modelDetails": "N807zW_modelDetails", "modelHeading": "N807zW_modelHeading", "modelLayout": "N807zW_modelLayout", "modelList": "N807zW_modelList", "modelMeta": "N807zW_modelMeta", "modelName": "N807zW_modelName", "modelRow": "N807zW_modelRow", "modelRowSelected": "N807zW_modelRowSelected", "newBadge": "N807zW_newBadge", "overrideDot": "N807zW_overrideDot", "page": "N807zW_page", "pageBody": "N807zW_pageBody", "pageTop": "N807zW_pageTop", "paneFoot": "N807zW_paneFoot", "releaseDate": "N807zW_releaseDate", "reset": "N807zW_reset", "slot": "N807zW_slot", "starLink": "N807zW_starLink", "stat": "N807zW_stat", "statLabel": "N807zW_statLabel", "stats": "N807zW_stats", "title": "N807zW_title", "trailing": "N807zW_trailing", "visuallyHidden": "N807zW_visuallyHidden" };
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,6 +394,72 @@ 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
+ }
377
463
 
378
464
  // src/client/AccountsCard.tsx
379
465
  var import_react2 = require("react");
@@ -382,8 +468,8 @@ var import_dsh_client_ui_primitives2 = require("@deepseek-ai/dsh-client-ui-primi
382
468
 
383
469
  // src/accounts.ts
384
470
  var MAX_ACCOUNTS = 20;
385
- var ACCOUNT_REF_PREFIX = "DSH_OPENCODE_GO_ACCOUNT_";
386
471
  var DEFAULT_ACCOUNT_REF = "OPENCODE_API_KEY";
472
+ var ACCOUNT_REF_PATTERN = /^[A-Za-z_][A-Za-z0-9_]*$/;
387
473
  function accountRefOf(settings) {
388
474
  return settings.apiKeyEnv || DEFAULT_ACCOUNT_REF;
389
475
  }
@@ -431,6 +517,14 @@ function GripIcon() {
431
517
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("circle", { cx: "7.5", cy: "11.5", r: "1.3" })
432
518
  ] });
433
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
+ }
434
528
  function AccountsCard({ state, actions, writable, t, locale }) {
435
529
  const [open, setOpen] = (0, import_react2.useState)(false);
436
530
  const [details, setDetails] = (0, import_react2.useState)(null);
@@ -445,6 +539,13 @@ function AccountsCard({ state, actions, writable, t, locale }) {
445
539
  const unreadable = state.entries.filter((entry) => entry.failed === true).length;
446
540
  const preferred = state.entries.find((entry) => entry.apiKeyEnv === state.activeRef);
447
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
+ };
448
549
  const updatedAt = state.entries.reduce((latest, entry) => Math.max(latest, entry.updatedAt ?? 0), 0);
449
550
  (0, import_react2.useEffect)(() => {
450
551
  actions.loadAccounts();
@@ -468,6 +569,12 @@ function AccountsCard({ state, actions, writable, t, locale }) {
468
569
  (0, import_react2.useEffect)(() => {
469
570
  if (editor?.ref != null && !state.entries.some((entry) => entry.apiKeyEnv === editor.ref)) cancel();
470
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]);
471
578
  const submit = async () => {
472
579
  if (!editor) return;
473
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);
@@ -629,20 +736,48 @@ function AccountsCard({ state, actions, writable, t, locale }) {
629
736
  state.blocked ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: Section_default.hint, children: t("accountsBlocked") }) : null,
630
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,
631
738
  !total ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: Section_default.hint, children: t("accountsEmpty") }) : null,
632
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: Section_default.accounts, children: [
633
- state.entries.map((account, index) => {
634
- const label = account.name || t("accountDefault");
635
- const rolling = account.usage?.rolling;
636
- const expanded = details === account.apiKeyEnv;
637
- const panelId = `opencode-go-account-${index}`;
638
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_react2.Fragment, { children: [
639
- reorderable && dropAt === index ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: Section_default.accountDropLine }) : null,
640
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
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)(
641
775
  "div",
642
776
  {
643
777
  className: Section_default.accountRow,
644
778
  "data-account-row": account.apiKeyEnv,
645
779
  "data-dragging": dragging === account.apiKeyEnv ? "true" : void 0,
780
+ "data-drop": markAt(index),
646
781
  onDragStart: (event) => {
647
782
  if (!reorderable || event.target?.closest?.("[data-account-handle]") == null) {
648
783
  event.preventDefault();
@@ -657,27 +792,6 @@ function AccountsCard({ state, actions, writable, t, locale }) {
657
792
  }
658
793
  setDragging(account.apiKeyEnv);
659
794
  },
660
- onDragOver: (event) => {
661
- if (!reorderable || dragging === null || dragging === account.apiKeyEnv) return;
662
- event.preventDefault();
663
- if (event.dataTransfer) event.dataTransfer.dropEffect = "move";
664
- const box = event.currentTarget.getBoundingClientRect();
665
- setDropAt(event.clientY < box.top + box.height / 2 ? index : index + 1);
666
- },
667
- onDrop: (event) => {
668
- const source = dragging;
669
- const slot = dropAt;
670
- setDragging(null);
671
- setDropAt(null);
672
- if (source === null || slot === null) return;
673
- event.preventDefault();
674
- const from = state.entries.findIndex((entry) => entry.apiKeyEnv === source);
675
- if (from >= 0) move(source, slot > from ? slot - 1 : slot);
676
- },
677
- onDragEnd: () => {
678
- setDragging(null);
679
- setDropAt(null);
680
- },
681
795
  children: [
682
796
  /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: Section_default.accountMain, "data-account-main": "", children: [
683
797
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
@@ -763,11 +877,10 @@ function AccountsCard({ state, actions, writable, t, locale }) {
763
877
  editor?.ref === account.apiKeyEnv ? editorForm(label) : null
764
878
  ]
765
879
  }
766
- )
767
- ] }, account.id);
768
- }),
769
- reorderable && dropAt === total ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: Section_default.accountDropLine }) : null
770
- ] }),
880
+ ) }, account.id);
881
+ })
882
+ }
883
+ ),
771
884
  editor ? editor.kind === "add" ? editorForm() : null : /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
772
885
  import_dsh_client_ui_primitives2.Button,
773
886
  {
@@ -876,7 +989,11 @@ function ModelsBody({ models, t, locale }) {
876
989
  status.error ? t("modelsSourceFailed") : t("modelsSourceCurrent"),
877
990
  ". ",
878
991
  " ",
879
- 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
880
997
  ] }, source);
881
998
  }) : null;
882
999
  if (models.status === "failed") {
@@ -894,9 +1011,12 @@ function ModelsBody({ models, t, locale }) {
894
1011
  models.message ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { className: Section_default.hint, children: models.message }) : null,
895
1012
  sourceStatus
896
1013
  ] });
897
- if (models.refreshing) return progress;
898
- if (models.count === 0) return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { className: Section_default.hint, children: t("modelsEmpty") });
899
- return null;
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
+ ] });
900
1020
  }
901
1021
  function OpencodeGoSection(props) {
902
1022
  const { useOpencodeGo, edit, resetField, save, discard, loadModels, setEnabled, setModelEnabled, t } = props;
@@ -958,7 +1078,7 @@ function Loaded(props) {
958
1078
  resetLabel: t("reset"),
959
1079
  disabled
960
1080
  };
961
- const advancedOverridden = state.usageDisplay.overridden || state.apiKeyEnv.overridden || state.baseURL.overridden || state.proxyURL.overridden || state.refreshMinutes.overridden || state.streamIdleTimeoutMs.overridden || state.maxImages.overridden || state.maxRequestImageBytes.overridden || state.requestImagePixelBudget.overridden || state.requestImageMaxBytes.overridden;
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;
962
1082
  return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: Section_default.page, children: [
963
1083
  /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: Section_default.pageBody, children: [
964
1084
  /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: Section_default.pageTop, children: [
@@ -1097,6 +1217,26 @@ function Loaded(props) {
1097
1217
  }
1098
1218
  }
1099
1219
  ),
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
+ ),
1100
1240
  /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1101
1241
  ValueField,
1102
1242
  {
@@ -1279,6 +1419,17 @@ function Loaded(props) {
1279
1419
  // src/provider-identity.ts
1280
1420
  var PROVIDER_ID = "dsh-opencode-go";
1281
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
+
1282
1433
  // src/proxy-url.ts
1283
1434
  function assertProxyURL(raw) {
1284
1435
  const value = raw?.trim() ?? "";
@@ -1304,19 +1455,33 @@ function assertProxyURL(raw) {
1304
1455
  return url.href;
1305
1456
  }
1306
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
+
1307
1470
  // src/client/accounts-controller.ts
1308
- function isSettingsConflict(error) {
1309
- if (!error || typeof error !== "object") return false;
1310
- const { name, code, message } = error;
1311
- return /conflict/i.test(`${String(name ?? "")} ${String(code ?? "")} ${String(message ?? "")}`);
1471
+ function operationId() {
1472
+ return Array.from(crypto.getRandomValues(new Uint8Array(16)), (byte) => byte.toString(16).padStart(2, "0")).join("");
1312
1473
  }
1313
1474
  var GoAccountsController = class {
1314
- constructor(scope, ctx, readUsage, publish, blocked) {
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
+ }) {
1315
1479
  this.scope = scope;
1316
1480
  this.ctx = ctx;
1317
1481
  this.readUsage = readUsage;
1318
1482
  this.publish = publish;
1319
1483
  this.blocked = blocked;
1484
+ this.execute = execute;
1320
1485
  this.sync();
1321
1486
  }
1322
1487
  rows = /* @__PURE__ */ new Map();
@@ -1327,10 +1492,11 @@ var GoAccountsController = class {
1327
1492
  identity = "";
1328
1493
  loaded = false;
1329
1494
  disposed = false;
1495
+ addition;
1330
1496
  snapshot() {
1331
1497
  const config = this.scope.getSnapshot().value ?? {};
1332
1498
  return {
1333
- entries: accountsOf(config).map((account) => ({ ...this.rows.get(account.apiKeyEnv), ...account })),
1499
+ entries: visibleAccountsOf(config).map((account) => ({ ...this.rows.get(account.apiKeyEnv), ...account })),
1334
1500
  activeRef: accountRefOf(config),
1335
1501
  autoSwitch: config.autoSwitch === true,
1336
1502
  busy: this.busy,
@@ -1342,7 +1508,7 @@ var GoAccountsController = class {
1342
1508
  sync() {
1343
1509
  const config = this.scope.getSnapshot().value ?? {};
1344
1510
  const identity = JSON.stringify([
1345
- accountsOf(config).map((account) => [account.id, account.apiKeyEnv]).sort((left, right) => left[1] < right[1] ? -1 : left[1] > right[1] ? 1 : 0),
1511
+ visibleAccountsOf(config).map((account) => [account.id, account.apiKeyEnv]).sort((left, right) => left[1] < right[1] ? -1 : left[1] > right[1] ? 1 : 0),
1346
1512
  config.baseURL,
1347
1513
  config.proxyURL
1348
1514
  ]);
@@ -1358,7 +1524,7 @@ var GoAccountsController = class {
1358
1524
  this.epoch++;
1359
1525
  }
1360
1526
  invalidate(ref) {
1361
- if (!accountsOf(this.scope.getSnapshot().value ?? {}).some((account) => account.apiKeyEnv === ref)) return;
1527
+ if (!visibleAccountsOf(this.scope.getSnapshot().value ?? {}).some((account) => account.apiKeyEnv === ref)) return;
1362
1528
  this.epoch++;
1363
1529
  this.rows.delete(ref);
1364
1530
  if (this.loaded) void this.refresh();
@@ -1366,7 +1532,7 @@ var GoAccountsController = class {
1366
1532
  async refresh() {
1367
1533
  this.loaded = true;
1368
1534
  const epoch = ++this.epoch;
1369
- const accounts = [...accountsOf(this.scope.getSnapshot().value ?? {})];
1535
+ const accounts = [...visibleAccountsOf(this.scope.getSnapshot().value ?? {})];
1370
1536
  this.refreshing = true;
1371
1537
  this.publish();
1372
1538
  try {
@@ -1434,155 +1600,36 @@ var GoAccountsController = class {
1434
1600
  this.publish();
1435
1601
  }
1436
1602
  actions() {
1603
+ const command = (request) => this.execute(request).then((status) => status === "applied");
1437
1604
  return {
1438
1605
  loadAccounts: () => {
1439
1606
  void this.refresh();
1440
1607
  },
1441
- addAccount: (name, key) => this.add(name, key),
1442
- renameAccount: (ref, name) => this.rename(ref, name),
1443
- removeAccount: (ref) => this.remove(ref),
1444
- selectAccount: (ref) => this.select(ref),
1445
- setAutoSwitch: (next) => this.run(async () => {
1446
- await this.scope.set("autoSwitch", next);
1447
- return this.scope.getSnapshot().value?.autoSwitch === next;
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;
1448
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 })),
1449
1624
  replaceAccountKey: (ref, key) => this.run(async () => {
1450
- if (!key.trim() || !this.account(ref) || this.rows.get(ref)?.writable === false) return false;
1451
- const response = await this.ctx.remote.credentials.set(ref, key.trim());
1452
- if (!response.ok) return false;
1453
- this.invalidate(ref);
1454
- return true;
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;
1455
1629
  }, false),
1456
- moveAccount: (ref, toIndex) => this.move(ref, toIndex)
1630
+ moveAccount: (ref, toIndex) => this.run(() => command({ kind: "move", ref, toIndex }))
1457
1631
  };
1458
1632
  }
1459
- /**
1460
- * Reorder the visible accounts and keep the preferred reference on the first row.
1461
- * The adapter tries the preferred reference first and the rest in array order, so
1462
- * one write is what makes top-to-bottom the real call order. A placeholder row the
1463
- * settings never stored is materialized here, which its `legacy:` id admits.
1464
- */
1465
- move(ref, toIndex) {
1466
- return this.run(async () => {
1467
- const snapshot = this.scope.getSnapshot();
1468
- const entries = [...accountsOf(snapshot.value ?? {})];
1469
- const from = entries.findIndex((account) => account.apiKeyEnv === ref);
1470
- if (from < 0 || !Number.isInteger(toIndex) || toIndex < 0 || toIndex >= entries.length || toIndex === from) return false;
1471
- const [moved] = entries.splice(from, 1);
1472
- entries.splice(toIndex, 0, moved);
1473
- await this.mutate([
1474
- { op: "set", path: ["accounts"], value: entries },
1475
- { op: "set", path: ["apiKeyEnv"], value: entries[0].apiKeyEnv }
1476
- ], snapshot.revision);
1477
- const after = this.scope.getSnapshot().value;
1478
- return after?.apiKeyEnv === entries[0].apiKeyEnv && after.accounts?.[toIndex]?.apiKeyEnv === ref;
1479
- });
1480
- }
1481
- account(ref) {
1482
- return accountsOf(this.scope.getSnapshot().value ?? {}).find((account) => account.apiKeyEnv === ref);
1483
- }
1484
- async mutate(ops, revision = this.scope.getSnapshot().revision) {
1485
- await this.scope.mutate(ops, revision);
1486
- }
1487
- add(name, key) {
1488
- return this.run(async () => {
1489
- if (!name.trim() || name.trim().length > 80 || !key.trim()) return false;
1490
- const id3 = Array.from(crypto.getRandomValues(new Uint8Array(16)), (byte) => byte.toString(16).padStart(2, "0")).join("");
1491
- const ref = ACCOUNT_REF_PREFIX + id3.replaceAll("-", "").toUpperCase();
1492
- const account = { id: id3, name: name.trim(), apiKeyEnv: ref };
1493
- const response = await this.ctx.remote.credentials.set(ref, key.trim());
1494
- if (!response.ok) return false;
1495
- for (let attempt = 0; attempt < 3; attempt++) {
1496
- const snapshot = this.scope.getSnapshot();
1497
- const existing = accountsOf(snapshot.value ?? {});
1498
- if (existing.some((entry) => entry.id === id3)) return true;
1499
- const configured = await this.configuredOf(existing.map((entry) => entry.apiKeyEnv));
1500
- const accounts = existing.filter((entry) => !(snapshot.value?.accounts == null && !entry.name && configured.get(entry.apiKeyEnv) === false));
1501
- if (accounts.length >= MAX_ACCOUNTS) break;
1502
- const first = existing.length === 0 || existing.every((entry) => configured.get(entry.apiKeyEnv) === false);
1503
- try {
1504
- await this.mutate([
1505
- { op: "set", path: ["accounts"], value: [...accounts, account] },
1506
- ...first ? [{ op: "set", path: ["apiKeyEnv"], value: ref }] : []
1507
- ], snapshot.revision);
1508
- } catch (error) {
1509
- if (attempt < 2 && isSettingsConflict(error)) continue;
1510
- return false;
1511
- }
1512
- if (this.scope.getSnapshot().value?.accounts?.some((entry) => entry.id === id3)) return true;
1513
- break;
1514
- }
1515
- try {
1516
- if (!(await this.ctx.remote.credentials.unset(ref)).ok) this.failure = "cleanup";
1517
- } catch {
1518
- this.failure = "cleanup";
1519
- }
1520
- return false;
1521
- });
1522
- }
1523
- /** Loaded rows answer from cache; anything they do not know is described on
1524
- * the spot, so a placeholder decision never races the page's first describe. */
1525
- async configuredOf(refs) {
1526
- const configured = /* @__PURE__ */ new Map();
1527
- const unknown = refs.filter((ref) => {
1528
- const known = this.rows.get(ref)?.configured;
1529
- if (known === void 0) return true;
1530
- configured.set(ref, known);
1531
- return false;
1532
- });
1533
- if (unknown.length === 0) return configured;
1534
- try {
1535
- const described = await this.ctx.remote.credentials.describe(unknown);
1536
- if (described.ok) for (const ref of unknown) configured.set(ref, described.value[ref]?.configured ?? false);
1537
- } catch {
1538
- }
1539
- return configured;
1540
- }
1541
- rename(ref, name) {
1542
- return this.run(async () => {
1543
- if (!this.account(ref) || !name.trim() || name.trim().length > 80) return false;
1544
- const accounts = accountsOf(this.scope.getSnapshot().value ?? {}).map((account) => account.apiKeyEnv === ref ? { ...account, name: name.trim() } : account);
1545
- await this.mutate([{ op: "set", path: ["accounts"], value: accounts }]);
1546
- return this.scope.getSnapshot().value?.accounts?.find((account) => account.apiKeyEnv === ref)?.name === name.trim();
1547
- });
1548
- }
1549
- select(ref) {
1550
- return this.run(async () => {
1551
- if (!this.account(ref)) return false;
1552
- await this.mutate([{ op: "set", path: ["apiKeyEnv"], value: ref }]);
1553
- return accountRefOf(this.scope.getSnapshot().value ?? {}) === ref;
1554
- });
1555
- }
1556
- remove(ref) {
1557
- return this.run(async () => {
1558
- if (!this.account(ref)) return false;
1559
- if (ref.startsWith(ACCOUNT_REF_PREFIX)) {
1560
- const described = await this.ctx.remote.credentials.describe([ref]).catch(() => void 0);
1561
- if (!described?.ok || described.value[ref] === void 0) {
1562
- this.failure = "remove";
1563
- return false;
1564
- }
1565
- if (described.value[ref].configured === true) {
1566
- let removed = false;
1567
- try {
1568
- removed = (await this.ctx.remote.credentials.unset(ref)).ok;
1569
- } catch {
1570
- }
1571
- if (!removed) {
1572
- this.failure = "remove";
1573
- return false;
1574
- }
1575
- }
1576
- }
1577
- const config = this.scope.getSnapshot().value ?? {};
1578
- const remaining = accountsOf(config).filter((account) => account.apiKeyEnv !== ref);
1579
- await this.mutate([
1580
- { op: "set", path: ["accounts"], value: remaining },
1581
- ...accountRefOf(config) === ref && remaining.length ? [{ op: "set", path: ["apiKeyEnv"], value: remaining[0].apiKeyEnv }] : []
1582
- ]);
1583
- return !this.account(ref);
1584
- });
1585
- }
1586
1633
  async run(action, requiresSettings = true) {
1587
1634
  if (this.busy || this.blocked() || requiresSettings && !this.scope.getSnapshot().writable) return false;
1588
1635
  this.busy = true;
@@ -1701,7 +1748,7 @@ var StagedForm = class {
1701
1748
  available: snapshot.status === "ready",
1702
1749
  writable: snapshot.writable,
1703
1750
  dirty: plan.length > 0,
1704
- invalid: plan.some((item) => item.run === void 0),
1751
+ invalid: plan.some((item) => item.run === void 0 && item.write === void 0),
1705
1752
  saving: this.saving,
1706
1753
  failed: this.failed
1707
1754
  };
@@ -1762,20 +1809,34 @@ var StagedForm = class {
1762
1809
  */
1763
1810
  async save() {
1764
1811
  const plan = this.plan();
1765
- const writes = plan.flatMap((item) => item.run === void 0 ? [] : [item.run]);
1766
- if (plan.length === 0 || this.saving || writes.length !== plan.length) return;
1812
+ if (plan.length === 0 || this.saving || plan.some((item) => !item.write && !item.run)) return;
1813
+ const revision = this.snapshotOf().revision;
1767
1814
  this.saving = true;
1768
1815
  this.failed = false;
1769
1816
  this.publish();
1770
1817
  let landed = true;
1771
- for (const write of writes) {
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 });
1772
1824
  try {
1773
- landed = await write() && landed;
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;
1774
1836
  } catch {
1775
1837
  landed = false;
1776
1838
  }
1777
1839
  }
1778
- if (landed) this.staged.clear();
1779
1840
  this.saving = false;
1780
1841
  this.failed = !landed;
1781
1842
  this.publish();
@@ -1792,30 +1853,20 @@ var StagedForm = class {
1792
1853
  const secret = this.secretSpecs.get(field);
1793
1854
  if (secret !== void 0) {
1794
1855
  const value = staged.text.trim();
1795
- if (value !== "") plan.push({ field, run: () => secret.write(value) });
1856
+ if (value !== "") plan.push({ field, edit: staged, run: () => secret.write(value) });
1796
1857
  continue;
1797
1858
  }
1798
1859
  const spec = this.spec(field);
1799
1860
  if (staged.clear) {
1800
- if (this.stored(field)) plan.push({ field, run: () => this.clear(field) });
1861
+ if (this.stored(field)) plan.push({ field, edit: staged, write: { kind: "clear" }, run: void 0 });
1801
1862
  continue;
1802
1863
  }
1803
1864
  if (this.unchangedDraft(field, staged)) continue;
1804
1865
  const write = spec.parse(staged.text);
1805
- if (write === void 0) plan.push({ field, run: void 0 });
1806
- else if (write.kind === "clear") plan.push({ field, run: () => this.clear(field) });
1807
- else plan.push({ field, run: () => this.store(field, write.value) });
1866
+ plan.push({ field, edit: staged, write, run: void 0 });
1808
1867
  }
1809
1868
  return plan;
1810
1869
  }
1811
- async clear(field) {
1812
- await this.scope.unset(field);
1813
- return !this.stored(field);
1814
- }
1815
- async store(field, value) {
1816
- await this.scope.set(field, value);
1817
- return sameJsonValue(this.userLayer()?.[field], value);
1818
- }
1819
1870
  stage(field, edit) {
1820
1871
  this.staged.set(field, edit);
1821
1872
  this.failed = false;
@@ -1871,8 +1922,7 @@ function sameJsonValue(left, right) {
1871
1922
  }
1872
1923
 
1873
1924
  // src/client/section-controller.ts
1874
- var OPENCODE_GO_NS = "llm-opencode-go";
1875
- var DEFAULT_API_KEY_REF = "OPENCODE_API_KEY";
1925
+ var OPENCODE_GO_NS = SETTINGS_NAMESPACE;
1876
1926
  var API_KEY_FIELD = "apiKey";
1877
1927
  var OpencodeGoSectionController = class {
1878
1928
  /**
@@ -1887,10 +1937,14 @@ var OpencodeGoSectionController = class {
1887
1937
  const result = await ctx.remote.opencodeGoUsage.readAccount(ref);
1888
1938
  if (!result.ok) throw result.error;
1889
1939
  return result.value;
1940
+ }, executeAccountCommand = async (command) => {
1941
+ const result = await ctx.remote.opencodeGoAccounts.execute(command);
1942
+ return result.ok ? result.value : "unknown";
1890
1943
  }) {
1891
1944
  this.scope = scope;
1892
1945
  this.ctx = ctx;
1893
1946
  this.readModels = readModels;
1947
+ this.executeAccountCommand = executeAccountCommand;
1894
1948
  this.form = new StagedForm(
1895
1949
  scope,
1896
1950
  [
@@ -1902,6 +1956,11 @@ var OpencodeGoSectionController = class {
1902
1956
  format: (value) => typeof value === "string" ? value : DEFAULT_USAGE_DISPLAY,
1903
1957
  parse: (text) => USAGE_DISPLAY_MODES.some((mode) => mode === text) ? { kind: "set", value: text } : void 0
1904
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
+ },
1905
1964
  textField("apiKeyEnv"),
1906
1965
  textField("baseURL"),
1907
1966
  {
@@ -1934,7 +1993,8 @@ var OpencodeGoSectionController = class {
1934
1993
  () => {
1935
1994
  this.store.set(this.projection());
1936
1995
  },
1937
- () => this.form.shell().saving || this.pickerSaving || Boolean(this.form.field(API_KEY_FIELD).text.trim())
1996
+ () => this.form.shell().saving || this.pickerSaving || Boolean(this.form.field(API_KEY_FIELD).text.trim()),
1997
+ this.executeAccountCommand
1938
1998
  );
1939
1999
  this.store.set(this.projection());
1940
2000
  const networkIdentity = () => JSON.stringify([
@@ -1983,6 +2043,7 @@ var OpencodeGoSectionController = class {
1983
2043
  accounts: this.accounts?.snapshot(),
1984
2044
  enabled: this.enabled(),
1985
2045
  usageDisplay: this.form.field("usageDisplay"),
2046
+ protocolOverrides: this.form.field("protocolOverrides"),
1986
2047
  modelVisibility: this.scope.getSnapshot().value?.modelVisibility ?? {},
1987
2048
  pickerSaving: this.pickerSaving,
1988
2049
  pickerFailed: this.pickerFailed,
@@ -2058,8 +2119,8 @@ var OpencodeGoSectionController = class {
2058
2119
  this.pickerFailed = false;
2059
2120
  this.store.set(this.projection());
2060
2121
  try {
2061
- await this.scope.set(field, value);
2062
- this.pickerFailed = !accepted();
2122
+ const verdict = await this.scope.set(field, value);
2123
+ this.pickerFailed = settingsWriteResult(verdict, accepted) !== "applied";
2063
2124
  } catch {
2064
2125
  this.pickerFailed = true;
2065
2126
  } finally {
@@ -2195,17 +2256,16 @@ var OpencodeGoSectionController = class {
2195
2256
  return this.face;
2196
2257
  }
2197
2258
  /**
2198
- * Write the staged key, then re-read whether the Host now holds one.
2259
+ * Ask the account service to write the staged key, then refresh its display.
2199
2260
  * @param value - the staged credential literal.
2200
- * @returns whether the Host reports a configured credential afterwards.
2261
+ * @returns whether the Host confirmed the write.
2201
2262
  */
2202
2263
  async writeKey(value) {
2203
2264
  const ref = this.keyDraftRef ?? refOf(this.scope.getSnapshot());
2204
- const response = await this.ctx.remote.credentials.set(ref, value);
2205
- if (!response.ok) return false;
2265
+ if (await this.executeAccountCommand({ kind: "replace-key", ref, key: value }) !== "applied") return false;
2206
2266
  this.accounts?.invalidate(ref);
2207
2267
  await this.readCredential();
2208
- return ref === this.credential.ref ? this.credential.configured : true;
2268
+ return true;
2209
2269
  }
2210
2270
  };
2211
2271
  function modelLimitsOf(value) {
@@ -2221,19 +2281,22 @@ function modelLimitsOf(value) {
2221
2281
  const limit = {};
2222
2282
  if (fields.contextWindow === null) limit.contextWindow = null;
2223
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
+ }
2224
2288
  if (typeof fields.contextWindow === "number" && Number.isSafeInteger(fields.contextWindow) && fields.contextWindow > 0) {
2225
2289
  limit.contextWindow = fields.contextWindow;
2226
2290
  }
2227
2291
  if (typeof fields.maxTokens === "number" && Number.isSafeInteger(fields.maxTokens) && fields.maxTokens > 0) {
2228
2292
  limit.maxTokens = fields.maxTokens;
2229
2293
  }
2230
- 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;
2231
2295
  }
2232
2296
  return limits;
2233
2297
  }
2234
2298
  function refOf(snapshot) {
2235
- const declared = snapshot.value?.apiKeyEnv;
2236
- return declared !== void 0 && declared.length > 0 ? declared : DEFAULT_API_KEY_REF;
2299
+ return accountRefOf(snapshot.value ?? {});
2237
2300
  }
2238
2301
 
2239
2302
  // src/client/locales.ts
@@ -2252,22 +2315,22 @@ var en = {
2252
2315
  accountRename: "Rename",
2253
2316
  accountReplaceKey: "Replace key",
2254
2317
  accountRemove: "Remove account",
2255
- accountRemoveHint: "Remove \u201C{name}\u201D? If it is selected, the next account becomes preferred. Keys added here are deleted from the credential service; existing external references are kept.",
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.",
2256
2319
  accountName: "Account name",
2257
2320
  accountKeyHint: "The key is saved through the host credential service and is never returned to this page.",
2258
2321
  accountConfirm: "Confirm",
2259
2322
  accountCancel: "Cancel",
2260
2323
  accountAutoSwitch: "Automatic fallback",
2261
- accountAutoSwitchHint: "Off by default. On quota exhaustion or a rejected key, try the other accounts in order before any content or tool call is emitted. Each account is tried at most once. Your preferred account stays selected; ordinary rate limits and network failures use host recovery.",
2262
- accountPreferredTag: "Preferred",
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",
2263
2326
  accountSwitchAction: "Switch",
2264
2327
  accountSwitchTitle: "Switch account",
2265
2328
  accountSwitchBack: "Back to usage",
2266
2329
  accountSwitchHint: "Later requests in this profile use this account. The consumption order stays on the Settings page.",
2267
2330
  accountSwitchFailed: "Could not switch account. Please retry.",
2268
- accountFallbackQuota: "The preferred account reached its quota; automatically used",
2269
- accountFallbackCredential: "The preferred key was unavailable or rejected; automatically used",
2270
- accountsSummary: "{count} accounts \xB7 Preferred {name}",
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}",
2271
2334
  accountsSummaryEmpty: "No accounts yet",
2272
2335
  accountsAvailability: "{ready}/{total} configured",
2273
2336
  accountsAvailabilityFailed: "{ready}/{total} configured \xB7 {failed} unreadable",
@@ -2334,6 +2397,11 @@ var en = {
2334
2397
  limitsModel: "Model",
2335
2398
  limitsContext: "Context window",
2336
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",
2337
2405
  capacityDefault: "Default: {value} tokens",
2338
2406
  capacityMissing: "API did not provide a value",
2339
2407
  modalityLabel: "Input modalities",
@@ -2369,7 +2437,7 @@ var en = {
2369
2437
  limitsEmpty: "Read the model list first; capacities are edited per model the gateway serves.",
2370
2438
  limitsContextLabel: "Context window for {name}",
2371
2439
  limitsOutputLabel: "Max output for {name}",
2372
- 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",
2373
2441
  advancedLabel: "Advanced settings",
2374
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.",
2375
2443
  usageDisplayLabel: "Usage display",
@@ -2377,6 +2445,10 @@ var en = {
2377
2445
  usageDisplay_auto: "Auto (default)",
2378
2446
  usageDisplay_always: "Always",
2379
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)",
2380
2452
  apiKeyEnvLabel: "Credential reference",
2381
2453
  apiKeyEnvHint: "The name the key is resolved from, addressed through the credentials service.",
2382
2454
  baseURLLabel: "Gateway URL",
@@ -2421,22 +2493,22 @@ var zh = {
2421
2493
  accountRename: "\u91CD\u547D\u540D",
2422
2494
  accountReplaceKey: "\u66FF\u6362 Key",
2423
2495
  accountRemove: "\u5220\u9664\u8D26\u53F7",
2424
- accountRemoveHint: "\u5220\u9664\u201C{name}\u201D\uFF1F\u82E5\u5B83\u662F\u5F53\u524D\u9996\u9009\uFF0C\u5C06\u4F7F\u7528\u4E0B\u4E00\u4E2A\u8D26\u53F7\u3002\u5728\u8FD9\u91CC\u6DFB\u52A0\u7684 Key \u4F1A\u4ECE\u51ED\u636E\u670D\u52A1\u5220\u9664\uFF1B\u5DF2\u6709\u5916\u90E8\u5F15\u7528\u4F1A\u4FDD\u7559\u3002",
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",
2425
2497
  accountName: "\u8D26\u53F7\u540D\u79F0",
2426
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",
2427
2499
  accountConfirm: "\u786E\u8BA4",
2428
2500
  accountCancel: "\u53D6\u6D88",
2429
2501
  accountAutoSwitch: "\u81EA\u52A8\u4F7F\u7528\u5907\u7528\u8D26\u53F7",
2430
- accountAutoSwitchHint: "\u9ED8\u8BA4\u5173\u95ED\u3002\u989D\u5EA6\u8017\u5C3D\u6216 Key \u4E0D\u53EF\u7528\u65F6\uFF0C\u5728\u5C1A\u672A\u8F93\u51FA\u5185\u5BB9\u6216\u5DE5\u5177\u8C03\u7528\u524D\u6309\u987A\u5E8F\u5C1D\u8BD5\u5176\u4ED6\u8D26\u53F7\uFF0C\u6BCF\u4E2A\u8D26\u53F7\u6700\u591A\u4E00\u6B21\u3002\u624B\u52A8\u9009\u5B9A\u7684\u9996\u9009\u8D26\u53F7\u4FDD\u6301\u4E0D\u53D8\uFF1B\u666E\u901A\u9650\u6D41\u548C\u7F51\u7EDC\u9519\u8BEF\u4EA4\u7531\u5BBF\u4E3B\u6062\u590D\u3002",
2431
- accountPreferredTag: "\u9996\u9009",
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",
2432
2504
  accountSwitchAction: "\u5207\u6362",
2433
2505
  accountSwitchTitle: "\u5207\u6362\u8D26\u53F7",
2434
2506
  accountSwitchBack: "\u8FD4\u56DE\u989D\u5EA6",
2435
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",
2436
2508
  accountSwitchFailed: "\u8D26\u53F7\u5207\u6362\u672A\u751F\u6548\uFF0C\u8BF7\u91CD\u8BD5\u3002",
2437
- accountFallbackQuota: "\u9996\u9009\u8D26\u53F7\u989D\u5EA6\u8017\u5C3D\uFF0C\u5DF2\u81EA\u52A8\u4F7F\u7528\u5907\u7528\u8D26\u53F7\uFF1A",
2438
- accountFallbackCredential: "\u9996\u9009 Key \u4E0D\u53EF\u7528\u6216\u88AB\u62D2\u7EDD\uFF0C\u5DF2\u81EA\u52A8\u4F7F\u7528\u5907\u7528\u8D26\u53F7\uFF1A",
2439
- accountsSummary: "{count} \u4E2A \xB7 \u9996\u9009 {name}",
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}",
2440
2512
  accountsSummaryEmpty: "\u5C1A\u672A\u6DFB\u52A0\u8D26\u53F7",
2441
2513
  accountsAvailability: "{ready}/{total} \u5DF2\u914D\u7F6E",
2442
2514
  accountsAvailabilityFailed: "{ready}/{total} \u5DF2\u914D\u7F6E \xB7 {failed} \u4E2A\u8BFB\u53D6\u5931\u8D25",
@@ -2503,6 +2575,11 @@ var zh = {
2503
2575
  limitsModel: "\u6A21\u578B",
2504
2576
  limitsContext: "\u4E0A\u4E0B\u6587\u7A97\u53E3",
2505
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",
2506
2583
  capacityDefault: "\u9ED8\u8BA4\uFF1A{value} tokens",
2507
2584
  capacityMissing: "API \u672A\u63D0\u4F9B",
2508
2585
  modalityLabel: "\u8F93\u5165\u6A21\u6001",
@@ -2538,7 +2615,7 @@ var zh = {
2538
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",
2539
2616
  limitsContextLabel: "{name} \u7684\u4E0A\u4E0B\u6587\u7A97\u53E3",
2540
2617
  limitsOutputLabel: "{name} \u7684\u6700\u5927\u8F93\u51FA",
2541
- 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",
2542
2619
  advancedLabel: "\u9AD8\u7EA7\u8BBE\u7F6E",
2543
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",
2544
2621
  usageDisplayLabel: "\u989D\u5EA6\u663E\u793A",
@@ -2546,6 +2623,10 @@ var zh = {
2546
2623
  usageDisplay_auto: "\u81EA\u52A8\uFF08\u9ED8\u8BA4\uFF09",
2547
2624
  usageDisplay_always: "\u5E38\u9A7B",
2548
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",
2549
2630
  apiKeyEnvLabel: "\u51ED\u8BC1\u5F15\u7528\u540D",
2550
2631
  apiKeyEnvHint: "key \u89E3\u6790\u6240\u4F9D\u636E\u7684\u5F15\u7528\u540D\uFF0C\u7ECF\u51ED\u8BC1\u670D\u52A1\u5BFB\u5740\u3002",
2551
2632
  baseURLLabel: "\u7F51\u5173\u5730\u5740",
@@ -2597,7 +2678,7 @@ function parseGoUsage(value) {
2597
2678
  }
2598
2679
  for (const key of ["rolling", "weekly", "monthly"]) {
2599
2680
  const row = source[key];
2600
- if (!row || row.status !== "ok" && row.status !== "rate-limited" || typeof row.percent !== "number" || !Number.isFinite(row.percent) || row.percent < 0 || typeof row.resetsAt !== "string" || !Number.isFinite(Date.parse(row.resetsAt))) {
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))) {
2601
2682
  throw new Error("Invalid OpenCode Go usage response");
2602
2683
  }
2603
2684
  result[key] = { status: row.status, percent: row.percent, resetsAt: row.resetsAt };
@@ -2641,10 +2722,61 @@ var usageRemote = {
2641
2722
  }]
2642
2723
  };
2643
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
2773
+ }]
2774
+ };
2775
+
2644
2776
  // src/remote-contract.ts
2645
2777
  var goRemote = {
2646
2778
  package: "dsh-opencode-go",
2647
- descriptors: [...usageRemote.descriptors, ...modelsRemote.descriptors]
2779
+ descriptors: [...usageRemote.descriptors, ...modelsRemote.descriptors, ...accountsRemote.descriptors]
2648
2780
  };
2649
2781
 
2650
2782
  // src/client/UsagePill.tsx
@@ -3006,7 +3138,7 @@ function ActiveUsage({ readUsage, t, getLocale, accounts, activeRef, writable, s
3006
3138
 
3007
3139
  // src/client/usage.ts
3008
3140
  var import_dsh_client_store2 = require("@deepseek-ai/dsh-client-store");
3009
- function registerUsagePill(ctx, settings) {
3141
+ function registerUsagePill(ctx, settings, selectAccount) {
3010
3142
  ctx.inject(["modelDirectories", "sessions", "remote.session"], (scope) => {
3011
3143
  scope.inject(["remote.opencodeGoUsage"], (ready) => {
3012
3144
  const credentialChanges = (0, import_dsh_client_store2.createSnapshotStore)(0);
@@ -3032,12 +3164,7 @@ function registerUsagePill(ctx, settings) {
3032
3164
  selectAccount: async (ref) => {
3033
3165
  const snapshot = settings.getSnapshot();
3034
3166
  if (!snapshot.writable || !accountsOf(snapshot.value ?? {}).some((account) => account.apiKeyEnv === ref)) return false;
3035
- try {
3036
- await settings.mutate([{ op: "set", path: ["apiKeyEnv"], value: ref }], snapshot.revision);
3037
- return accountRefOf(settings.getSnapshot().value ?? {}) === ref;
3038
- } catch {
3039
- return false;
3040
- }
3167
+ return selectAccount ? selectAccount(ref).catch(() => false) : false;
3041
3168
  },
3042
3169
  readUsage,
3043
3170
  getLocale: () => ready.locale.getLocale().active,
@@ -3048,6 +3175,37 @@ function registerUsagePill(ctx, settings) {
3048
3175
  });
3049
3176
  }
3050
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
+
3051
3209
  // src/client/index.ts
3052
3210
  var NS = "settings.opencode-go";
3053
3211
  var inject = ["slots", "locale", "remote", "remote.credentials", "remote.llm"];
@@ -3055,19 +3213,11 @@ function apply(ctx) {
3055
3213
  ctx.effect(() => ctx.locale.register(NS, { zh, en }), "llm-opencode-go: copy dictionaries");
3056
3214
  const modelsReady = ctx.remote.$mount(goRemote);
3057
3215
  ctx.effect(async () => await modelsReady);
3058
- ctx.inject(["configForms", "remote.opencodeGoModels"], (child) => {
3059
- const forms = child.get("configForms");
3060
- mountSettings(child, forms.get("opencode-go"), modelsReady);
3061
- });
3062
- ctx.inject(["settingsScope", "remote.opencodeGoModels"], (child) => {
3063
- mountSettings(child, child.settingsScope.bind({
3064
- namespace: "llm-opencode-go",
3065
- decode: (section) => typeof section === "object" && section !== null ? section : void 0
3066
- }), modelsReady);
3067
- });
3216
+ mountSettingsScopes(ctx, (child, scope) => mountSettings(child, scope, modelsReady));
3068
3217
  }
3069
3218
  function mountSettings(ctx, scope, modelsReady) {
3070
- registerUsagePill(ctx, scope);
3219
+ const executeAccountCommand = accountCommands(ctx);
3220
+ registerUsagePill(ctx, scope, async (ref) => await executeAccountCommand({ kind: "select", ref }) === "applied");
3071
3221
  let readAccount;
3072
3222
  ctx.inject(["remote.opencodeGoUsage"], (ready) => {
3073
3223
  readAccount = async (ref) => {
@@ -3083,7 +3233,7 @@ function mountSettings(ctx, scope, modelsReady) {
3083
3233
  await modelsReady;
3084
3234
  if (readAccount === void 0) throw new Error("OpenCode Go account usage is unavailable in this session");
3085
3235
  return readAccount(ref);
3086
- });
3236
+ }, executeAccountCommand);
3087
3237
  ctx.effect(() => () => controller.dispose());
3088
3238
  const t = ctx.locale.bind(NS);
3089
3239
  const injected = () => ({ ...controller.inject(), t, getLocale: () => ctx.locale.getLocale().active });