dsh-opencode-go 0.1.7 → 0.1.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.en.md +30 -52
- package/README.md +30 -72
- package/docs/assets/install-via-dsh.gif +0 -0
- package/docs/verification.md +32 -0
- package/lib/client.js +486 -358
- package/lib/index.js +108 -13
- package/lib/types/catalog.d.ts +5 -0
- package/lib/types/client/ModelEditor.d.ts +13 -0
- package/lib/types/client/locales.d.ts +16 -1
- package/lib/types/client/section-controller.d.ts +15 -3
- package/lib/types/config.d.ts +2 -0
- package/lib/types/index.d.ts +2 -2
- package/lib/types/model-metadata.d.ts +2 -0
- package/lib/types/models-contract.d.ts +23 -0
- package/lib/types/models.d.ts +12 -0
- package/lib/types/remote-contract.d.ts +3 -0
- package/lib/types/remotes.d.ts +3 -0
- package/package.json +24 -22
package/lib/client.js
CHANGED
|
@@ -38,9 +38,61 @@ __export(index_exports, {
|
|
|
38
38
|
module.exports = __toCommonJS(index_exports);
|
|
39
39
|
|
|
40
40
|
// src/client/Section.tsx
|
|
41
|
+
var import_react2 = require("react");
|
|
42
|
+
var import_dsh_client_ui_primitives2 = require("@deepseek-ai/dsh-client-ui-primitives");
|
|
43
|
+
var primitives = __toESM(require("@deepseek-ai/dsh-client-ui-primitives"), 1);
|
|
44
|
+
|
|
45
|
+
// src/client/ModelEditor.tsx
|
|
41
46
|
var import_react = require("react");
|
|
42
47
|
var import_dsh_client_ui_primitives = require("@deepseek-ai/dsh-client-ui-primitives");
|
|
43
|
-
|
|
48
|
+
|
|
49
|
+
// src/models-contract.ts
|
|
50
|
+
function validReleaseDate(value) {
|
|
51
|
+
return typeof value === "string" && /^\d{4}-\d{2}-\d{2}$/.test(value) && Number.isFinite(Date.parse(value)) && new Date(value).toISOString().slice(0, 10) === value;
|
|
52
|
+
}
|
|
53
|
+
function isNewModel(model, now = Date.now()) {
|
|
54
|
+
if (model.deprecated || !validReleaseDate(model.releaseDate)) return false;
|
|
55
|
+
const days = Math.floor(now / 864e5) - Date.parse(model.releaseDate) / 864e5;
|
|
56
|
+
return days >= 0 && days < 7;
|
|
57
|
+
}
|
|
58
|
+
function sortModels(models, now = Date.now()) {
|
|
59
|
+
const rank = (model) => model.deprecated ? 2 : isNewModel(model, now) ? 0 : 1;
|
|
60
|
+
return [...models].sort((a, b) => rank(a) - rank(b) || (isNewModel(a, now) && isNewModel(b, now) ? b.releaseDate.localeCompare(a.releaseDate) : 0));
|
|
61
|
+
}
|
|
62
|
+
function parseGoModels(value) {
|
|
63
|
+
if (!Array.isArray(value)) throw new Error("Invalid OpenCode Go model list");
|
|
64
|
+
return value.map((entry) => {
|
|
65
|
+
if (!entry || typeof entry !== "object") throw new Error("Invalid OpenCode Go model");
|
|
66
|
+
const row = entry;
|
|
67
|
+
if (typeof row.id !== "string" || !row.id) throw new Error("Missing OpenCode Go model id");
|
|
68
|
+
const model = { id: row.id };
|
|
69
|
+
if (typeof row.name === "string") model.name = row.name;
|
|
70
|
+
for (const key of ["contextWindow", "maxTokens"]) {
|
|
71
|
+
if (typeof row[key] === "number" && Number.isSafeInteger(row[key]) && row[key] > 0) model[key] = row[key];
|
|
72
|
+
}
|
|
73
|
+
if (typeof row.deprecated === "boolean") model.deprecated = row.deprecated;
|
|
74
|
+
if (validReleaseDate(row.releaseDate)) model.releaseDate = row.releaseDate;
|
|
75
|
+
return model;
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
var codec = {
|
|
79
|
+
mode: "strict",
|
|
80
|
+
typeSymbol: "dsh-opencode-go#GoModels",
|
|
81
|
+
schema: { parse: parseGoModels },
|
|
82
|
+
create: () => ({ parse: parseGoModels })
|
|
83
|
+
};
|
|
84
|
+
var modelsRemote = {
|
|
85
|
+
package: "dsh-opencode-go",
|
|
86
|
+
descriptors: [{
|
|
87
|
+
id: "dsh-opencode-go#opencodeGoModels/read",
|
|
88
|
+
service: "opencodeGoModels",
|
|
89
|
+
namespace: "opencodeGoModels",
|
|
90
|
+
method: "read",
|
|
91
|
+
invocation: { kind: "direct" },
|
|
92
|
+
parameters: [],
|
|
93
|
+
result: codec
|
|
94
|
+
}]
|
|
95
|
+
};
|
|
44
96
|
|
|
45
97
|
// plugin-css:/Users/tanglei/Desktop/dsh-opencode-go/src/client/Section.module.css
|
|
46
98
|
var id = "dsh-opencode-go/Section.module.css";
|
|
@@ -48,22 +100,190 @@ if (!document.querySelector("style[data-plugin-css=" + JSON.stringify(id) + "]")
|
|
|
48
100
|
const style = document.createElement("style");
|
|
49
101
|
style.dataset.plugin = "dsh-opencode-go";
|
|
50
102
|
style.dataset.pluginCss = id;
|
|
51
|
-
style.textContent =
|
|
103
|
+
style.textContent = '.BtKYva_page{flex-direction:column;min-width:0;height:100%;min-height:0;display:flex;container-type:size}.BtKYva_pageBody{scrollbar-gutter:stable;flex:1;min-height:0;padding-right:4px;overflow-y:auto}.BtKYva_field{flex-direction:column;gap:6px;padding:12px 0;display:flex}.BtKYva_field+.BtKYva_field{border-top:.5px solid var(--dsw-alias-border-l2)}.BtKYva_head{align-items:center;gap:8px;display:flex}.BtKYva_label{min-width:0;color:var(--dsw-alias-label-primary);flex:1;font-size:13px;font-weight:500;line-height:1.5}.BtKYva_badges{align-items:center;gap:8px;display:inline-flex}.BtKYva_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}.BtKYva_reset:hover:not(:disabled){color:var(--dsw-alias-label-primary)}.BtKYva_reset:disabled{cursor:default}.BtKYva_reset:focus-visible,.BtKYva_disclosure:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:3px}.BtKYva_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}.BtKYva_input:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:1px;border-color:var(--dsw-alias-brand-primary)}.BtKYva_input:disabled{color:var(--dsw-alias-label-tertiary);cursor:default}.BtKYva_inputInvalid{border-color:var(--dsw-alias-label-error);}.BtKYva_invalid{color:var(--dsw-alias-label-error);margin:0;font-size:12px;line-height:1.5}.BtKYva_hint{color:var(--dsw-alias-label-tertiary);margin:0;font-size:12px;line-height:1.5}.BtKYva_intro{color:var(--dsw-alias-label-secondary);margin:0 0 8px;font-size:13px;line-height:1.5}.BtKYva_disclosure{font:inherit;text-align:left;cursor:pointer;background:0 0;border:none;align-items:center;gap:8px;margin:0;padding:0;display:flex}.BtKYva_disclosure:hover .BtKYva_label{color:var(--dsw-alias-brand-primary)}.BtKYva_chevron,.BtKYva_chevronOpen{width:14px;height:14px;color:var(--dsw-alias-label-tertiary);flex:none}.BtKYva_chevron{transform:rotate(-90deg)}.BtKYva_advanced{flex-direction:column;gap:4px;padding:4px 0 0 22px;display:flex}.BtKYva_advanced .BtKYva_field+.BtKYva_field{border-top:none}.BtKYva_chips{flex-wrap:wrap;gap:6px;display:flex}.BtKYva_limitsEditor{flex-direction:column;gap:10px;padding-top:4px;display:flex}.BtKYva_limitsToolbar{grid-template-columns:minmax(0,1fr) auto;align-items:end;gap:6px 10px;display:grid}.BtKYva_limitsFilterLabel{color:var(--dsw-alias-label-secondary);grid-column:1/-1;font-size:12px;font-weight:500;line-height:1.5}.BtKYva_limitsSummary{color:var(--dsw-alias-label-tertiary);white-space:nowrap;padding-bottom:8px;font-size:12px;line-height:1.5}.BtKYva_limitsId,.BtKYva_limitsModelId{text-overflow:ellipsis;white-space:nowrap;display:block;overflow:hidden}.BtKYva_limitsId{color:var(--dsw-alias-label-primary);font-size:13px;line-height:1.4}.BtKYva_limitsModelId{color:var(--dsw-alias-label-tertiary);margin-top:2px;font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:11px;line-height:1.4}.BtKYva_visuallyHidden{clip:rect(0, 0, 0, 0);white-space:nowrap;border:0;width:1px;height:1px;margin:-1px;padding:0;position:absolute;overflow:hidden}@media (width<=560px){.BtKYva_limitsToolbar{grid-template-columns:1fr}.BtKYva_limitsSummary{padding-bottom:0}}.BtKYva_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}.BtKYva_failedNote{color:var(--dsw-alias-label-error);margin:0;font-size:12px;line-height:1.5}.BtKYva_pageTop{align-items:flex-start;gap:16px;display:flex}.BtKYva_pageTop .BtKYva_intro{flex:1}.BtKYva_advancedTrigger{flex-shrink:0;margin-left:auto;}.BtKYva_advancedTrigger .BtKYva_label{color:var(--dsw-alias-label-tertiary);font-size:12px}.BtKYva_filters{flex-wrap:wrap;gap:6px;display:flex}.BtKYva_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}.BtKYva_filter[aria-pressed=true]{color:var(--dsw-alias-label-primary);background:var(--dsw-alias-bg-layer-3)}.BtKYva_filter span{color:var(--dsw-alias-label-tertiary);margin-left:4px}.BtKYva_modelLayout{border:.5px solid var(--dsw-alias-border-l4);border-radius:10px;grid-template-columns:minmax(0,43fr) minmax(0,57fr);height:clamp(240px,100cqh - 460px,480px);display:grid;overflow:hidden}.BtKYva_modelList{border-right:.5px solid var(--dsw-alias-border-l2);min-height:0;padding:6px;overflow-y:auto}.BtKYva_modelChoice{text-align:left;width:100%;color:var(--dsw-alias-label-primary);cursor:pointer;background:0 0;border:0;border-radius:6px;padding:12px 9px;display:block}.BtKYva_modelChoice[aria-pressed=true],.BtKYva_modelChoice:hover{background:var(--dsw-alias-bg-layer-3)}.BtKYva_modelName{overflow-wrap:anywhere;flex-wrap:wrap;align-items:center;gap:5px;font-size:13px;display:flex}.BtKYva_modelDetails{flex-direction:column;align-items:stretch;gap:10px;min-width:0;padding:18px;display:flex;overflow-y:auto}.BtKYva_modelDetails h3{overflow-wrap:anywhere;margin:0;font-size:16px}.BtKYva_modelHeading{flex-wrap:wrap;align-items:center;gap:6px;display:flex}.BtKYva_modelDetails .BtKYva_field{border:0;padding:8px 0}.BtKYva_modelDetails .BtKYva_input{box-sizing:border-box;width:100%;min-width:0}.BtKYva_modelDetails .BtKYva_reset{align-self:flex-start}.BtKYva_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}.BtKYva_releaseDate{color:var(--dsw-alias-label-tertiary);margin-top:4px;font-size:10px;display:block}.BtKYva_modelChoice:focus-visible,.BtKYva_filter:focus-visible,.BtKYva_advancedTrigger:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:-2px}@container (width<=440px){.BtKYva_pageTop{flex-wrap:wrap}.BtKYva_modelLayout{grid-template-columns:minmax(0,1fr);height:auto}.BtKYva_modelList{border-right:0;border-bottom:.5px solid var(--dsw-alias-border-l2);max-height:240px}.BtKYva_modelDetails{max-height:460px}}.BtKYva_keySection{border-top:.5px solid var(--dsw-alias-border-l2);padding:12px 0}.BtKYva_keySection summary{cursor:pointer;list-style:none}.BtKYva_keySection summary:after{content:"\u2304";color:var(--dsw-alias-label-tertiary)}.BtKYva_keySection summary::-webkit-details-marker{display:none}.BtKYva_keySection>.BtKYva_input{box-sizing:border-box;width:100%;margin:10px 0 6px}.BtKYva_keySection summary:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:2px}';
|
|
52
104
|
document.head.appendChild(style);
|
|
53
105
|
}
|
|
54
|
-
var Section_default = { "
|
|
106
|
+
var Section_default = { "page": "BtKYva_page", "limitsToolbar": "BtKYva_limitsToolbar", "modelChoice": "BtKYva_modelChoice", "modelDetails": "BtKYva_modelDetails", "limitsEditor": "BtKYva_limitsEditor", "modelHeading": "BtKYva_modelHeading", "limitsId": "BtKYva_limitsId", "filters": "BtKYva_filters", "head": "BtKYva_head", "chevron": "BtKYva_chevron", "limitsFilterLabel": "BtKYva_limitsFilterLabel", "limitsModelId": "BtKYva_limitsModelId", "visuallyHidden": "BtKYva_visuallyHidden", "newBadge": "BtKYva_newBadge", "hint": "BtKYva_hint", "limitsSummary": "BtKYva_limitsSummary", "keySection": "BtKYva_keySection", "input": "BtKYva_input", "chips": "BtKYva_chips", "actions": "BtKYva_actions", "pageBody": "BtKYva_pageBody", "advanced": "BtKYva_advanced", "disclosure": "BtKYva_disclosure", "advancedTrigger": "BtKYva_advancedTrigger BtKYva_disclosure", "field": "BtKYva_field", "intro": "BtKYva_intro", "pageTop": "BtKYva_pageTop", "releaseDate": "BtKYva_releaseDate", "filter": "BtKYva_filter", "chevronOpen": "BtKYva_chevronOpen", "inputInvalid": "BtKYva_inputInvalid BtKYva_input", "reset": "BtKYva_reset", "badges": "BtKYva_badges", "invalid": "BtKYva_invalid", "modelLayout": "BtKYva_modelLayout", "modelList": "BtKYva_modelList", "failedNote": "BtKYva_failedNote", "label": "BtKYva_label", "modelName": "BtKYva_modelName" };
|
|
55
107
|
|
|
56
|
-
// src/client/
|
|
108
|
+
// src/client/ModelEditor.tsx
|
|
57
109
|
var import_jsx_runtime = require("react/jsx-runtime");
|
|
110
|
+
function hasCapacityOverride(limit) {
|
|
111
|
+
return limit?.contextWindow != null || limit?.maxTokens != null;
|
|
112
|
+
}
|
|
113
|
+
function ModelEditor({ models, draft, t, disabled, onEdit }) {
|
|
114
|
+
const [query, setQuery] = (0, import_react.useState)("");
|
|
115
|
+
const [filter, setFilter] = (0, import_react.useState)("all");
|
|
116
|
+
const [selected, setSelected] = (0, import_react.useState)();
|
|
117
|
+
const [now, setNow] = (0, import_react.useState)(Date.now);
|
|
118
|
+
(0, import_react.useEffect)(() => {
|
|
119
|
+
const timer = setInterval(() => {
|
|
120
|
+
setNow(Date.now());
|
|
121
|
+
}, 6e4);
|
|
122
|
+
return () => {
|
|
123
|
+
clearInterval(timer);
|
|
124
|
+
};
|
|
125
|
+
}, []);
|
|
126
|
+
const all = sortModels(models.status === "ready" ? models.entries : [], now);
|
|
127
|
+
const normalized = query.trim().toLocaleLowerCase();
|
|
128
|
+
const entries = all.filter((model2) => `${model2.name ?? ""} ${model2.id}`.toLocaleLowerCase().includes(normalized) && (filter === "all" || filter === "new" && isNewModel(model2, now) || filter === "custom" && hasCapacityOverride(draft[model2.id]) || filter === "deprecated" && model2.deprecated));
|
|
129
|
+
const model = entries.find((entry) => entry.id === selected) ?? entries[0];
|
|
130
|
+
const customized = all.filter((entry) => hasCapacityOverride(draft[entry.id])).length;
|
|
131
|
+
const filters = [
|
|
132
|
+
["all", "filterAll", all.length],
|
|
133
|
+
["new", "filterNew", all.filter((entry) => isNewModel(entry, now)).length],
|
|
134
|
+
["custom", "filterCustom", customized],
|
|
135
|
+
["deprecated", "filterDeprecated", all.filter((entry) => entry.deprecated).length]
|
|
136
|
+
];
|
|
137
|
+
const write = (id3, field, value) => {
|
|
138
|
+
const current = draft[id3] === null ? { contextWindow: null, maxTokens: null } : draft[id3] ?? {};
|
|
139
|
+
onEdit({ ...draft, [id3]: { ...current, [field]: value ?? null } });
|
|
140
|
+
};
|
|
141
|
+
const badges = (entry) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
142
|
+
isNewModel(entry, now) ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: Section_default.newBadge, title: t("newHint"), children: "NEW" }) : null,
|
|
143
|
+
entry.deprecated ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.Tag, { tone: "warning", children: t("deprecatedBadge") }) : null
|
|
144
|
+
] });
|
|
145
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: Section_default.limitsEditor, children: [
|
|
146
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("label", { className: Section_default.visuallyHidden, htmlFor: "opencode-go-model-filter", children: t("limitsFilterLabel") }),
|
|
147
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
148
|
+
"input",
|
|
149
|
+
{
|
|
150
|
+
id: "opencode-go-model-filter",
|
|
151
|
+
className: Section_default.input,
|
|
152
|
+
type: "search",
|
|
153
|
+
autoComplete: "off",
|
|
154
|
+
placeholder: t("limitsFilterPlaceholder"),
|
|
155
|
+
value: query,
|
|
156
|
+
onChange: (event) => {
|
|
157
|
+
setQuery(event.target.value);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
),
|
|
161
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: Section_default.filters, role: "group", "aria-label": t("filterLabel"), children: filters.map(([key, label, count]) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
162
|
+
"button",
|
|
163
|
+
{
|
|
164
|
+
type: "button",
|
|
165
|
+
className: Section_default.filter,
|
|
166
|
+
"aria-pressed": filter === key,
|
|
167
|
+
onClick: () => {
|
|
168
|
+
setFilter(key);
|
|
169
|
+
},
|
|
170
|
+
children: [
|
|
171
|
+
t(label),
|
|
172
|
+
" ",
|
|
173
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: count })
|
|
174
|
+
]
|
|
175
|
+
},
|
|
176
|
+
key
|
|
177
|
+
)) }),
|
|
178
|
+
model ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: Section_default.modelLayout, children: [
|
|
179
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("nav", { className: Section_default.modelList, "aria-label": t("modelsLabel"), children: entries.map((entry) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
180
|
+
"button",
|
|
181
|
+
{
|
|
182
|
+
type: "button",
|
|
183
|
+
className: Section_default.modelChoice,
|
|
184
|
+
"aria-pressed": entry.id === model.id,
|
|
185
|
+
onClick: () => {
|
|
186
|
+
setSelected(entry.id);
|
|
187
|
+
},
|
|
188
|
+
children: [
|
|
189
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: Section_default.modelName, children: [
|
|
190
|
+
entry.name ?? entry.id,
|
|
191
|
+
" ",
|
|
192
|
+
badges(entry)
|
|
193
|
+
] }),
|
|
194
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("code", { className: Section_default.limitsModelId, translate: "no", children: entry.id }),
|
|
195
|
+
isNewModel(entry, now) ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: Section_default.releaseDate, children: t("releasedOn", { date: entry.releaseDate }) }) : null
|
|
196
|
+
]
|
|
197
|
+
},
|
|
198
|
+
entry.id
|
|
199
|
+
)) }),
|
|
200
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("section", { className: Section_default.modelDetails, "aria-label": t("modelDetails"), children: [
|
|
201
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: Section_default.modelHeading, children: [
|
|
202
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("h3", { children: model.name ?? model.id }),
|
|
203
|
+
badges(model)
|
|
204
|
+
] }),
|
|
205
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("code", { className: Section_default.limitsModelId, translate: "no", children: model.id }),
|
|
206
|
+
model.deprecated ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: Section_default.hint, children: t("deprecatedHint") }) : null,
|
|
207
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Capacity, { model, field: "contextWindow", limit: draft[model.id], t, disabled, onChange: write }),
|
|
208
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Capacity, { model, field: "maxTokens", limit: draft[model.id], t, disabled, onChange: write }),
|
|
209
|
+
hasCapacityOverride(draft[model.id]) ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
210
|
+
"button",
|
|
211
|
+
{
|
|
212
|
+
type: "button",
|
|
213
|
+
className: Section_default.reset,
|
|
214
|
+
disabled,
|
|
215
|
+
onClick: () => {
|
|
216
|
+
onEdit({ ...draft, [model.id]: null });
|
|
217
|
+
},
|
|
218
|
+
children: t("limitsResetModel")
|
|
219
|
+
}
|
|
220
|
+
) : null,
|
|
221
|
+
model.releaseDate ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: Section_default.hint, children: t("releaseSource", { date: model.releaseDate }) }) : null,
|
|
222
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: Section_default.hint, children: t("limitsHint") })
|
|
223
|
+
] })
|
|
224
|
+
] }) : models.status === "ready" && all.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: Section_default.hint, children: t("limitsNoMatches", { query }) }) : null,
|
|
225
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: Section_default.head, children: [
|
|
226
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: Section_default.limitsSummary, children: t("limitsSummary", { count: customized }) }),
|
|
227
|
+
Object.values(draft).some(hasCapacityOverride) ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
228
|
+
"button",
|
|
229
|
+
{
|
|
230
|
+
type: "button",
|
|
231
|
+
className: Section_default.reset,
|
|
232
|
+
disabled,
|
|
233
|
+
onClick: () => {
|
|
234
|
+
onEdit(Object.fromEntries(Object.keys(draft).map((id3) => [id3, null])));
|
|
235
|
+
},
|
|
236
|
+
children: t("limitsResetAll")
|
|
237
|
+
}
|
|
238
|
+
) : null
|
|
239
|
+
] })
|
|
240
|
+
] });
|
|
241
|
+
}
|
|
242
|
+
function Capacity({ model, field, limit, disabled, t, onChange }) {
|
|
243
|
+
const id3 = `opencode-go-${field}-${encodeURIComponent(model.id)}`;
|
|
244
|
+
const defaultValue = model[field];
|
|
245
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: Section_default.field, children: [
|
|
246
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("label", { className: Section_default.label, htmlFor: id3, children: t(field === "contextWindow" ? "limitsContext" : "limitsOutput") }),
|
|
247
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
248
|
+
"input",
|
|
249
|
+
{
|
|
250
|
+
id: id3,
|
|
251
|
+
className: Section_default.input,
|
|
252
|
+
type: "number",
|
|
253
|
+
min: 1,
|
|
254
|
+
step: 1,
|
|
255
|
+
inputMode: "numeric",
|
|
256
|
+
"aria-label": t(field === "contextWindow" ? "limitsContextLabel" : "limitsOutputLabel", { name: model.name ?? model.id }),
|
|
257
|
+
"aria-describedby": `${id3}-default`,
|
|
258
|
+
value: limit?.[field] ?? "",
|
|
259
|
+
placeholder: defaultValue === void 0 ? t("capacityMissing") : String(defaultValue),
|
|
260
|
+
disabled,
|
|
261
|
+
onChange: (event) => {
|
|
262
|
+
const text = event.target.value.trim();
|
|
263
|
+
const value = Number(text);
|
|
264
|
+
if (text === "") onChange(model.id, field, void 0);
|
|
265
|
+
else if (Number.isSafeInteger(value) && value > 0) onChange(model.id, field, value);
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
),
|
|
269
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { id: `${id3}-default`, className: Section_default.hint, children: [
|
|
270
|
+
t("capacityDefault", { value: defaultValue === void 0 ? t("capacityMissing") : defaultValue.toLocaleString("en-US") }),
|
|
271
|
+
limit?.[field] != null ? ` \xB7 ${t("overridden")}` : ""
|
|
272
|
+
] })
|
|
273
|
+
] });
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
// src/client/Section.tsx
|
|
277
|
+
var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
58
278
|
var ChevronDown = primitives.IconChevronDownOutlineRegular ?? primitives.IconChevronDownOutline14;
|
|
59
279
|
function ValueField(props) {
|
|
60
280
|
const hintId = `${props.id}-hint`;
|
|
61
|
-
return /* @__PURE__ */ (0,
|
|
62
|
-
/* @__PURE__ */ (0,
|
|
63
|
-
/* @__PURE__ */ (0,
|
|
64
|
-
props.field.overridden ? /* @__PURE__ */ (0,
|
|
65
|
-
/* @__PURE__ */ (0,
|
|
66
|
-
/* @__PURE__ */ (0,
|
|
281
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: Section_default.field, children: [
|
|
282
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: Section_default.head, children: [
|
|
283
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("label", { className: Section_default.label, htmlFor: props.id, children: props.label }),
|
|
284
|
+
props.field.overridden ? /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: Section_default.badges, children: [
|
|
285
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_dsh_client_ui_primitives2.Tag, { tone: "neutral", children: props.overriddenLabel }),
|
|
286
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
67
287
|
"button",
|
|
68
288
|
{
|
|
69
289
|
type: "button",
|
|
@@ -75,7 +295,7 @@ function ValueField(props) {
|
|
|
75
295
|
)
|
|
76
296
|
] }) : null
|
|
77
297
|
] }),
|
|
78
|
-
/* @__PURE__ */ (0,
|
|
298
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
79
299
|
"input",
|
|
80
300
|
{
|
|
81
301
|
id: props.id,
|
|
@@ -93,176 +313,24 @@ function ValueField(props) {
|
|
|
93
313
|
}
|
|
94
314
|
}
|
|
95
315
|
),
|
|
96
|
-
/* @__PURE__ */ (0,
|
|
316
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { id: hintId, className: props.field.invalid ? Section_default.invalid : Section_default.hint, children: props.field.invalid ? props.invalidLabel : props.hint })
|
|
97
317
|
] });
|
|
98
318
|
}
|
|
99
319
|
function ModelsBody({ models, t }) {
|
|
100
320
|
if (models.status === "failed") {
|
|
101
|
-
return /* @__PURE__ */ (0,
|
|
102
|
-
/* @__PURE__ */ (0,
|
|
103
|
-
/* @__PURE__ */ (0,
|
|
321
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
|
|
322
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: Section_default.failedNote, role: "alert", children: t("modelsFailed") }),
|
|
323
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: Section_default.hint, children: models.message })
|
|
104
324
|
] });
|
|
105
325
|
}
|
|
106
|
-
if (models.status !== "ready") return /* @__PURE__ */ (0,
|
|
107
|
-
if (models.count === 0) return /* @__PURE__ */ (0,
|
|
326
|
+
if (models.status !== "ready") return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: Section_default.hint, role: "status", "aria-live": "polite", children: t("modelsLoading") });
|
|
327
|
+
if (models.count === 0) return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: Section_default.hint, children: t("modelsEmpty") });
|
|
108
328
|
return null;
|
|
109
329
|
}
|
|
110
|
-
function LimitsTable({ models, draft, t, disabled, onEdit }) {
|
|
111
|
-
const [query, setQuery] = (0, import_react.useState)("");
|
|
112
|
-
const known = new Map((models.status === "ready" ? models.entries : []).map((model) => [model.id, model]));
|
|
113
|
-
for (const [id3, limit] of Object.entries(draft)) {
|
|
114
|
-
if (hasCapacityOverride(limit) && !known.has(id3)) known.set(id3, { id: id3 });
|
|
115
|
-
}
|
|
116
|
-
if (known.size === 0) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: Section_default.hint, children: t("limitsEmpty") });
|
|
117
|
-
const normalizedQuery = query.trim().toLocaleLowerCase();
|
|
118
|
-
const entries = [...known.values()].filter((model) => {
|
|
119
|
-
if (normalizedQuery === "") return true;
|
|
120
|
-
return `${model.name ?? ""} ${model.id}`.toLocaleLowerCase().includes(normalizedQuery);
|
|
121
|
-
});
|
|
122
|
-
const customizedCount = Object.values(draft).filter(hasCapacityOverride).length;
|
|
123
|
-
const write = (id3, field, value) => {
|
|
124
|
-
const current = draft[id3] === null ? { contextWindow: null, maxTokens: null } : draft[id3] ?? {};
|
|
125
|
-
const merged = { ...current };
|
|
126
|
-
merged[field] = value ?? null;
|
|
127
|
-
const next = { ...draft, [id3]: merged };
|
|
128
|
-
onEdit(next);
|
|
129
|
-
};
|
|
130
|
-
const clearModel = (id3) => {
|
|
131
|
-
const next = { ...draft };
|
|
132
|
-
next[id3] = null;
|
|
133
|
-
onEdit(next);
|
|
134
|
-
};
|
|
135
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: Section_default.limitsEditor, children: [
|
|
136
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: Section_default.limitsToolbar, children: [
|
|
137
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("label", { className: Section_default.limitsFilterLabel, htmlFor: "opencode-go-model-filter", children: t("limitsFilterLabel") }),
|
|
138
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
139
|
-
"input",
|
|
140
|
-
{
|
|
141
|
-
id: "opencode-go-model-filter",
|
|
142
|
-
className: Section_default.input,
|
|
143
|
-
type: "search",
|
|
144
|
-
name: "model-filter",
|
|
145
|
-
autoComplete: "off",
|
|
146
|
-
spellCheck: false,
|
|
147
|
-
placeholder: t("limitsFilterPlaceholder"),
|
|
148
|
-
value: query,
|
|
149
|
-
onChange: (event) => {
|
|
150
|
-
setQuery(event.target.value);
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
),
|
|
154
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: Section_default.limitsSummary, role: "status", "aria-live": "polite", children: t("limitsSummary", { count: customizedCount }) })
|
|
155
|
-
] }),
|
|
156
|
-
entries.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: Section_default.hint, children: t("limitsNoMatches", { query }) }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: Section_default.limitsScroll, children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("table", { className: Section_default.limitsTable, children: [
|
|
157
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("caption", { className: Section_default.visuallyHidden, children: t("limitsLabel") }),
|
|
158
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("thead", { children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("tr", { children: [
|
|
159
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("th", { scope: "col", children: t("limitsModel") }),
|
|
160
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("th", { scope: "col", children: t("limitsContext") }),
|
|
161
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("th", { scope: "col", children: t("limitsOutput") }),
|
|
162
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("th", { scope: "col", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: Section_default.visuallyHidden, children: t("limitsResetModel") }) })
|
|
163
|
-
] }) }),
|
|
164
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("tbody", { children: entries.map((model) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
165
|
-
LimitRow,
|
|
166
|
-
{
|
|
167
|
-
model,
|
|
168
|
-
limit: draft[model.id],
|
|
169
|
-
disabled,
|
|
170
|
-
t,
|
|
171
|
-
onChange: write,
|
|
172
|
-
onReset: clearModel
|
|
173
|
-
},
|
|
174
|
-
model.id
|
|
175
|
-
)) })
|
|
176
|
-
] }) }),
|
|
177
|
-
customizedCount > 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", className: Section_default.reset, disabled, onClick: () => {
|
|
178
|
-
onEdit(Object.fromEntries(Object.keys(draft).map((id3) => [id3, null])));
|
|
179
|
-
}, children: t("limitsResetAll") }) : null
|
|
180
|
-
] });
|
|
181
|
-
}
|
|
182
|
-
function LimitRow({ model, limit, disabled, t, onChange, onReset }) {
|
|
183
|
-
const name = model.name ?? model.id;
|
|
184
|
-
const contextId = `opencode-go-context-${inputKey(model.id)}`;
|
|
185
|
-
const outputId = `opencode-go-output-${inputKey(model.id)}`;
|
|
186
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("tr", { children: [
|
|
187
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("th", { scope: "row", className: Section_default.limitsName, children: [
|
|
188
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: Section_default.limitsId, translate: "no", children: name }),
|
|
189
|
-
model.name !== void 0 && model.name !== model.id ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("code", { className: Section_default.limitsModelId, translate: "no", children: model.id }) : null,
|
|
190
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: Section_default.hint, children: t("limitsAdvertised", { context: capacityLabel(model.contextWindow), output: capacityLabel(model.maxTokens) }) })
|
|
191
|
-
] }),
|
|
192
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("td", { children: [
|
|
193
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("label", { className: Section_default.visuallyHidden, htmlFor: contextId, children: t("limitsContextLabel", { name }) }),
|
|
194
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
195
|
-
"input",
|
|
196
|
-
{
|
|
197
|
-
id: contextId,
|
|
198
|
-
className: Section_default.input,
|
|
199
|
-
type: "number",
|
|
200
|
-
name: contextId,
|
|
201
|
-
autoComplete: "off",
|
|
202
|
-
inputMode: "numeric",
|
|
203
|
-
min: 1,
|
|
204
|
-
step: 1,
|
|
205
|
-
value: limit?.contextWindow ?? "",
|
|
206
|
-
disabled,
|
|
207
|
-
onChange: (event) => {
|
|
208
|
-
const text = event.target.value.trim();
|
|
209
|
-
if (text === "") onChange(model.id, "contextWindow", void 0);
|
|
210
|
-
else {
|
|
211
|
-
const value = positiveInteger(text);
|
|
212
|
-
if (value !== void 0) onChange(model.id, "contextWindow", value);
|
|
213
|
-
}
|
|
214
|
-
}
|
|
215
|
-
}
|
|
216
|
-
)
|
|
217
|
-
] }),
|
|
218
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("td", { children: [
|
|
219
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("label", { className: Section_default.visuallyHidden, htmlFor: outputId, children: t("limitsOutputLabel", { name }) }),
|
|
220
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
221
|
-
"input",
|
|
222
|
-
{
|
|
223
|
-
id: outputId,
|
|
224
|
-
className: Section_default.input,
|
|
225
|
-
type: "number",
|
|
226
|
-
name: outputId,
|
|
227
|
-
autoComplete: "off",
|
|
228
|
-
inputMode: "numeric",
|
|
229
|
-
min: 1,
|
|
230
|
-
step: 1,
|
|
231
|
-
value: limit?.maxTokens ?? "",
|
|
232
|
-
disabled,
|
|
233
|
-
onChange: (event) => {
|
|
234
|
-
const text = event.target.value.trim();
|
|
235
|
-
if (text === "") onChange(model.id, "maxTokens", void 0);
|
|
236
|
-
else {
|
|
237
|
-
const value = positiveInteger(text);
|
|
238
|
-
if (value !== void 0) onChange(model.id, "maxTokens", value);
|
|
239
|
-
}
|
|
240
|
-
}
|
|
241
|
-
}
|
|
242
|
-
)
|
|
243
|
-
] }),
|
|
244
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("td", { children: hasCapacityOverride(limit) ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", className: Section_default.reset, disabled, onClick: () => {
|
|
245
|
-
onReset(model.id);
|
|
246
|
-
}, children: t("limitsResetModel") }) : null })
|
|
247
|
-
] });
|
|
248
|
-
}
|
|
249
|
-
function hasCapacityOverride(limit) {
|
|
250
|
-
return limit?.contextWindow != null || limit?.maxTokens != null;
|
|
251
|
-
}
|
|
252
|
-
function positiveInteger(value) {
|
|
253
|
-
const parsed = Number(value);
|
|
254
|
-
return Number.isSafeInteger(parsed) && parsed > 0 ? parsed : void 0;
|
|
255
|
-
}
|
|
256
|
-
function capacityLabel(value) {
|
|
257
|
-
return value === void 0 ? "\u2014" : String(value);
|
|
258
|
-
}
|
|
259
|
-
function inputKey(value) {
|
|
260
|
-
return encodeURIComponent(value);
|
|
261
|
-
}
|
|
262
330
|
function OpencodeGoSection(props) {
|
|
263
|
-
const { useOpencodeGo, edit, resetField, save, discard, loadModels, setEnabled, t } = props;
|
|
264
|
-
if (useOpencodeGo === void 0 || edit === void 0 || resetField === void 0 || save === void 0 || discard === void 0 || loadModels === void 0 || setEnabled === void 0 || t === void 0) return null;
|
|
265
|
-
return /* @__PURE__ */ (0,
|
|
331
|
+
const { useOpencodeGo, edit, resetField, save, discard, loadModels, setEnabled, setShowDeprecatedModels, t } = props;
|
|
332
|
+
if (useOpencodeGo === void 0 || edit === void 0 || resetField === void 0 || save === void 0 || discard === void 0 || loadModels === void 0 || setEnabled === void 0 || setShowDeprecatedModels === void 0 || t === void 0) return null;
|
|
333
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
266
334
|
Loaded,
|
|
267
335
|
{
|
|
268
336
|
state: useOpencodeGo((snapshot) => snapshot),
|
|
@@ -272,19 +340,19 @@ function OpencodeGoSection(props) {
|
|
|
272
340
|
save,
|
|
273
341
|
discard,
|
|
274
342
|
loadModels,
|
|
275
|
-
setEnabled
|
|
343
|
+
setEnabled,
|
|
344
|
+
setShowDeprecatedModels
|
|
276
345
|
}
|
|
277
346
|
);
|
|
278
347
|
}
|
|
279
348
|
function Loaded(props) {
|
|
280
349
|
const { t, state, loadModels } = props;
|
|
281
|
-
const [advanced, setAdvanced] = (0,
|
|
282
|
-
|
|
283
|
-
(0, import_react.useEffect)(() => {
|
|
350
|
+
const [advanced, setAdvanced] = (0, import_react2.useState)(false);
|
|
351
|
+
(0, import_react2.useEffect)(() => {
|
|
284
352
|
if (state.available && state.models.status === "idle") loadModels();
|
|
285
353
|
}, [state.available, state.models.status, loadModels]);
|
|
286
354
|
if (!state.available) {
|
|
287
|
-
return /* @__PURE__ */ (0,
|
|
355
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: Section_default.intro, children: t("unavailable") });
|
|
288
356
|
}
|
|
289
357
|
const disabled = !state.writable;
|
|
290
358
|
const fieldProps = {
|
|
@@ -294,119 +362,31 @@ function Loaded(props) {
|
|
|
294
362
|
disabled
|
|
295
363
|
};
|
|
296
364
|
const advancedOverridden = state.apiKeyEnv.overridden || state.baseURL.overridden || state.refreshMinutes.overridden || state.streamIdleTimeoutMs.overridden || state.maxRequestImageBytes.overridden || state.requestImagePixelBudget.overridden || state.requestImageMaxBytes.overridden;
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
304
|
-
import_dsh_client_ui_primitives.Switch,
|
|
365
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: Section_default.page, children: [
|
|
366
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: Section_default.pageBody, children: [
|
|
367
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: Section_default.pageTop, children: [
|
|
368
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: Section_default.intro, children: t("intro") }),
|
|
369
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
|
|
370
|
+
"button",
|
|
305
371
|
{
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
372
|
+
type: "button",
|
|
373
|
+
className: Section_default.advancedTrigger,
|
|
374
|
+
"aria-expanded": advanced,
|
|
375
|
+
"aria-controls": "opencode-go-advanced",
|
|
376
|
+
onClick: () => {
|
|
377
|
+
setAdvanced(!advanced);
|
|
378
|
+
},
|
|
379
|
+
children: [
|
|
380
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(ChevronDown, { className: advanced ? Section_default.chevronOpen : Section_default.chevron }),
|
|
381
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: Section_default.label, children: t("advancedLabel") }),
|
|
382
|
+
advancedOverridden ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_dsh_client_ui_primitives2.Tag, { tone: "neutral", children: t("overridden") }) : null
|
|
383
|
+
]
|
|
310
384
|
}
|
|
311
385
|
)
|
|
312
386
|
] }),
|
|
313
|
-
/* @__PURE__ */ (0,
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: Section_default.head, children: [
|
|
317
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("label", { className: Section_default.label, htmlFor: "opencode-go-key", children: t("keyLabel") }),
|
|
318
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: Section_default.badges, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.Tag, { tone: state.apiKeyConfigured ? "success" : "warning", children: state.apiKeyConfigured ? t("keyConfigured") : t("keyMissing") }) })
|
|
319
|
-
] }),
|
|
320
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
321
|
-
"input",
|
|
322
|
-
{
|
|
323
|
-
id: "opencode-go-key",
|
|
324
|
-
name: "api-key",
|
|
325
|
-
className: Section_default.input,
|
|
326
|
-
type: "password",
|
|
327
|
-
autoComplete: "off",
|
|
328
|
-
"aria-describedby": "opencode-go-key-hint",
|
|
329
|
-
value: state.apiKey.text,
|
|
330
|
-
disabled: !state.apiKeyWritable,
|
|
331
|
-
onChange: (event) => {
|
|
332
|
-
props.edit("apiKey", event.target.value);
|
|
333
|
-
}
|
|
334
|
-
}
|
|
335
|
-
),
|
|
336
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { id: "opencode-go-key-hint", className: Section_default.hint, children: state.apiKeyWritable ? t("keyHint") : t("keyNotWritable") })
|
|
337
|
-
] }),
|
|
338
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: Section_default.field, children: [
|
|
339
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: Section_default.head, children: [
|
|
340
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: Section_default.label, children: t("modelsLabel") }),
|
|
341
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: Section_default.badges, children: [
|
|
342
|
-
state.models.status === "ready" ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.Tag, { tone: "neutral", children: t("modelsCount", { count: state.models.count }) }) : null,
|
|
343
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
344
|
-
"button",
|
|
345
|
-
{
|
|
346
|
-
type: "button",
|
|
347
|
-
className: Section_default.reset,
|
|
348
|
-
disabled: state.models.status === "loading",
|
|
349
|
-
onClick: loadModels,
|
|
350
|
-
children: t("modelsRefresh")
|
|
351
|
-
}
|
|
352
|
-
)
|
|
353
|
-
] })
|
|
354
|
-
] }),
|
|
355
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(ModelsBody, { models: state.models, t })
|
|
356
|
-
] }),
|
|
357
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: Section_default.field, children: [
|
|
358
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
359
|
-
"button",
|
|
360
|
-
{
|
|
361
|
-
type: "button",
|
|
362
|
-
className: Section_default.disclosure,
|
|
363
|
-
"aria-expanded": limitsOpen,
|
|
364
|
-
"aria-controls": "opencode-go-model-limits",
|
|
365
|
-
onClick: () => {
|
|
366
|
-
setLimitsOpen(!limitsOpen);
|
|
367
|
-
},
|
|
368
|
-
children: [
|
|
369
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(ChevronDown, { "aria-hidden": "true", className: limitsOpen ? Section_default.chevronOpen : Section_default.chevron }),
|
|
370
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: Section_default.label, children: t("limitsLabel") }),
|
|
371
|
-
customizedModels > 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.Tag, { tone: "neutral", children: t("limitsSummary", { count: customizedModels }) }) : null
|
|
372
|
-
]
|
|
373
|
-
}
|
|
374
|
-
),
|
|
375
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: Section_default.hint, children: t("limitsHint") }),
|
|
376
|
-
limitsOpen ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { id: "opencode-go-model-limits", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
377
|
-
LimitsTable,
|
|
378
|
-
{
|
|
379
|
-
models: state.models,
|
|
380
|
-
draft: state.modelLimitDraft,
|
|
381
|
-
t,
|
|
382
|
-
disabled,
|
|
383
|
-
onEdit: (next) => {
|
|
384
|
-
props.edit("modelLimits", JSON.stringify(next));
|
|
385
|
-
}
|
|
386
|
-
}
|
|
387
|
-
) }) : null
|
|
388
|
-
] }),
|
|
389
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: Section_default.field, children: [
|
|
390
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
391
|
-
"button",
|
|
392
|
-
{
|
|
393
|
-
type: "button",
|
|
394
|
-
className: Section_default.disclosure,
|
|
395
|
-
"aria-expanded": advanced,
|
|
396
|
-
"aria-controls": "opencode-go-advanced",
|
|
397
|
-
onClick: () => {
|
|
398
|
-
setAdvanced(!advanced);
|
|
399
|
-
},
|
|
400
|
-
children: [
|
|
401
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(ChevronDown, { className: advanced ? Section_default.chevronOpen : Section_default.chevron }),
|
|
402
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: Section_default.label, children: t("advancedLabel") }),
|
|
403
|
-
advancedOverridden ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.Tag, { tone: "neutral", children: t("overridden") }) : null
|
|
404
|
-
]
|
|
405
|
-
}
|
|
406
|
-
),
|
|
407
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: Section_default.hint, children: t("advancedHint") }),
|
|
408
|
-
advanced ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { id: "opencode-go-advanced", className: Section_default.advanced, children: [
|
|
409
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
387
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: advanced ? Section_default.field : void 0, children: advanced ? /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { id: "opencode-go-advanced", className: Section_default.advanced, children: [
|
|
388
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: Section_default.hint, children: t("advancedHint") }),
|
|
389
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
410
390
|
ValueField,
|
|
411
391
|
{
|
|
412
392
|
id: "opencode-go-api-key-env",
|
|
@@ -422,7 +402,7 @@ function Loaded(props) {
|
|
|
422
402
|
}
|
|
423
403
|
}
|
|
424
404
|
),
|
|
425
|
-
/* @__PURE__ */ (0,
|
|
405
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
426
406
|
ValueField,
|
|
427
407
|
{
|
|
428
408
|
id: "opencode-go-base-url",
|
|
@@ -438,7 +418,7 @@ function Loaded(props) {
|
|
|
438
418
|
}
|
|
439
419
|
}
|
|
440
420
|
),
|
|
441
|
-
/* @__PURE__ */ (0,
|
|
421
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
442
422
|
ValueField,
|
|
443
423
|
{
|
|
444
424
|
id: "opencode-go-refresh-minutes",
|
|
@@ -455,7 +435,7 @@ function Loaded(props) {
|
|
|
455
435
|
}
|
|
456
436
|
}
|
|
457
437
|
),
|
|
458
|
-
/* @__PURE__ */ (0,
|
|
438
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
459
439
|
ValueField,
|
|
460
440
|
{
|
|
461
441
|
id: "opencode-go-stream-idle",
|
|
@@ -472,7 +452,7 @@ function Loaded(props) {
|
|
|
472
452
|
}
|
|
473
453
|
}
|
|
474
454
|
),
|
|
475
|
-
/* @__PURE__ */ (0,
|
|
455
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
476
456
|
ValueField,
|
|
477
457
|
{
|
|
478
458
|
id: "opencode-go-max-request-image-bytes",
|
|
@@ -489,7 +469,7 @@ function Loaded(props) {
|
|
|
489
469
|
}
|
|
490
470
|
}
|
|
491
471
|
),
|
|
492
|
-
/* @__PURE__ */ (0,
|
|
472
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
493
473
|
ValueField,
|
|
494
474
|
{
|
|
495
475
|
id: "opencode-go-image-pixel-budget",
|
|
@@ -506,7 +486,7 @@ function Loaded(props) {
|
|
|
506
486
|
}
|
|
507
487
|
}
|
|
508
488
|
),
|
|
509
|
-
/* @__PURE__ */ (0,
|
|
489
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
510
490
|
ValueField,
|
|
511
491
|
{
|
|
512
492
|
id: "opencode-go-image-max-bytes",
|
|
@@ -523,14 +503,100 @@ function Loaded(props) {
|
|
|
523
503
|
}
|
|
524
504
|
}
|
|
525
505
|
)
|
|
526
|
-
] }) : null
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
506
|
+
] }) : null }),
|
|
507
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: Section_default.field, children: [
|
|
508
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: Section_default.head, children: [
|
|
509
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: Section_default.label, children: t("enabledLabel") }),
|
|
510
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
511
|
+
import_dsh_client_ui_primitives2.Switch,
|
|
512
|
+
{
|
|
513
|
+
checked: state.enabled,
|
|
514
|
+
label: t("enabledLabel"),
|
|
515
|
+
disabled,
|
|
516
|
+
onChange: props.setEnabled
|
|
517
|
+
}
|
|
518
|
+
)
|
|
519
|
+
] }),
|
|
520
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: Section_default.hint, children: state.enabled ? t("enabledHint") : t("enabledOff") })
|
|
521
|
+
] }),
|
|
522
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("details", { className: Section_default.keySection, open: !state.apiKeyConfigured || state.apiKey.text.length > 0, children: [
|
|
523
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("summary", { className: Section_default.head, children: [
|
|
524
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: Section_default.label, children: t("keyLabel") }),
|
|
525
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: Section_default.badges, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_dsh_client_ui_primitives2.Tag, { tone: state.apiKeyConfigured ? "success" : "warning", children: state.apiKeyConfigured ? t("keyConfigured") : t("keyMissing") }) })
|
|
526
|
+
] }),
|
|
527
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
528
|
+
"input",
|
|
529
|
+
{
|
|
530
|
+
id: "opencode-go-key",
|
|
531
|
+
"aria-label": t("keyLabel"),
|
|
532
|
+
name: "api-key",
|
|
533
|
+
className: Section_default.input,
|
|
534
|
+
type: "password",
|
|
535
|
+
autoComplete: "off",
|
|
536
|
+
"aria-describedby": "opencode-go-key-hint",
|
|
537
|
+
value: state.apiKey.text,
|
|
538
|
+
disabled: !state.apiKeyWritable,
|
|
539
|
+
onChange: (event) => {
|
|
540
|
+
props.edit("apiKey", event.target.value);
|
|
541
|
+
}
|
|
542
|
+
}
|
|
543
|
+
),
|
|
544
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { id: "opencode-go-key-hint", className: Section_default.hint, children: state.apiKeyWritable ? t("keyHint") : t("keyNotWritable") })
|
|
545
|
+
] }),
|
|
546
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: Section_default.field, children: [
|
|
547
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: Section_default.head, children: [
|
|
548
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: Section_default.label, children: t("modelsLabel") }),
|
|
549
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: Section_default.badges, children: [
|
|
550
|
+
state.models.status === "ready" ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_dsh_client_ui_primitives2.Tag, { tone: "neutral", children: t("modelsCount", { count: state.models.count }) }) : null,
|
|
551
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
552
|
+
"button",
|
|
553
|
+
{
|
|
554
|
+
type: "button",
|
|
555
|
+
className: Section_default.reset,
|
|
556
|
+
disabled: state.models.status === "loading",
|
|
557
|
+
onClick: loadModels,
|
|
558
|
+
children: t("modelsRefresh")
|
|
559
|
+
}
|
|
560
|
+
)
|
|
561
|
+
] })
|
|
562
|
+
] }),
|
|
563
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(ModelsBody, { models: state.models, t })
|
|
564
|
+
] }),
|
|
565
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: Section_default.field, children: [
|
|
566
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: Section_default.head, children: [
|
|
567
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: Section_default.label, children: t("showDeprecatedLabel") }),
|
|
568
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
569
|
+
import_dsh_client_ui_primitives2.Switch,
|
|
570
|
+
{
|
|
571
|
+
checked: state.showDeprecatedModels,
|
|
572
|
+
label: t("showDeprecatedLabel"),
|
|
573
|
+
disabled: disabled || state.pickerSaving,
|
|
574
|
+
onChange: props.setShowDeprecatedModels
|
|
575
|
+
}
|
|
576
|
+
)
|
|
577
|
+
] }),
|
|
578
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: Section_default.hint, children: t("showDeprecatedHint") }),
|
|
579
|
+
state.pickerFailed ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: Section_default.failedNote, role: "alert", children: t("pickerFailed") }) : null,
|
|
580
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
581
|
+
ModelEditor,
|
|
582
|
+
{
|
|
583
|
+
models: state.models,
|
|
584
|
+
draft: state.modelLimitDraft,
|
|
585
|
+
t,
|
|
586
|
+
disabled: disabled || state.saving,
|
|
587
|
+
onEdit: (next) => {
|
|
588
|
+
props.edit("modelLimits", JSON.stringify(next));
|
|
589
|
+
}
|
|
590
|
+
}
|
|
591
|
+
)
|
|
592
|
+
] }),
|
|
593
|
+
disabled ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: Section_default.hint, children: t("readOnly") }) : null
|
|
532
594
|
] }),
|
|
533
|
-
|
|
595
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: Section_default.actions, children: [
|
|
596
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_dsh_client_ui_primitives2.Button, { variant: "primary", size: "md", disabled: disabled || !state.dirty || state.invalid || state.saving, onClick: props.save, children: state.saving ? t("saving") : t("save") }),
|
|
597
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_dsh_client_ui_primitives2.Button, { variant: "outline", size: "md", disabled: disabled || !state.dirty || state.saving, onClick: props.discard, children: t("discard") }),
|
|
598
|
+
state.failed ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: Section_default.failedNote, children: t("savedFailed") }) : null
|
|
599
|
+
] })
|
|
534
600
|
] });
|
|
535
601
|
}
|
|
536
602
|
|
|
@@ -797,9 +863,10 @@ var OpencodeGoSectionController = class {
|
|
|
797
863
|
* @param ctx - the page plugin's context, whose `remote.credentials` namespace
|
|
798
864
|
* answers for the credential the section references.
|
|
799
865
|
*/
|
|
800
|
-
constructor(scope, ctx) {
|
|
866
|
+
constructor(scope, ctx, readModels = () => ctx.remote.llm.discoverModels(OPENCODE_GO_NS, { provider: OPENCODE_GO_PROVIDER })) {
|
|
801
867
|
this.scope = scope;
|
|
802
868
|
this.ctx = ctx;
|
|
869
|
+
this.readModels = readModels;
|
|
803
870
|
this.form = new StagedForm(
|
|
804
871
|
scope,
|
|
805
872
|
[
|
|
@@ -828,6 +895,8 @@ var OpencodeGoSectionController = class {
|
|
|
828
895
|
credential = { ref: "", configured: false, writable: true };
|
|
829
896
|
models = { status: "idle" };
|
|
830
897
|
modelsRequest = 0;
|
|
898
|
+
pickerSaving = false;
|
|
899
|
+
pickerFailed = false;
|
|
831
900
|
face;
|
|
832
901
|
unsubscribe;
|
|
833
902
|
/** Release subscriptions without disposing the host's shared form. */
|
|
@@ -840,6 +909,9 @@ var OpencodeGoSectionController = class {
|
|
|
840
909
|
return {
|
|
841
910
|
...this.form.shell(),
|
|
842
911
|
enabled: this.enabled(),
|
|
912
|
+
showDeprecatedModels: this.scope.getSnapshot().value?.showDeprecatedModels ?? false,
|
|
913
|
+
pickerSaving: this.pickerSaving,
|
|
914
|
+
pickerFailed: this.pickerFailed,
|
|
843
915
|
apiKeyEnv: this.form.field("apiKeyEnv"),
|
|
844
916
|
baseURL: this.form.field("baseURL"),
|
|
845
917
|
refreshMinutes: this.form.field("refreshMinutes"),
|
|
@@ -894,6 +966,22 @@ var OpencodeGoSectionController = class {
|
|
|
894
966
|
setEnabled(next) {
|
|
895
967
|
void this.scope.set("enabled", next);
|
|
896
968
|
}
|
|
969
|
+
/** Visibility is immediate; failed writes leave the committed switch state visible. */
|
|
970
|
+
async setShowDeprecatedModels(next) {
|
|
971
|
+
if (this.pickerSaving || !this.scope.getSnapshot().writable) return;
|
|
972
|
+
this.pickerSaving = true;
|
|
973
|
+
this.pickerFailed = false;
|
|
974
|
+
this.store.set(this.projection());
|
|
975
|
+
try {
|
|
976
|
+
await this.scope.set("showDeprecatedModels", next);
|
|
977
|
+
this.pickerFailed = (this.scope.getSnapshot().value?.showDeprecatedModels ?? false) !== next;
|
|
978
|
+
} catch {
|
|
979
|
+
this.pickerFailed = true;
|
|
980
|
+
} finally {
|
|
981
|
+
this.pickerSaving = false;
|
|
982
|
+
this.store.set(this.projection());
|
|
983
|
+
}
|
|
984
|
+
}
|
|
897
985
|
/**
|
|
898
986
|
* Read the gateway's model listing through the Host's discovery for this
|
|
899
987
|
* adapter. Called when the page mounts and again from its refresh control.
|
|
@@ -905,7 +993,7 @@ var OpencodeGoSectionController = class {
|
|
|
905
993
|
const request = ++this.modelsRequest;
|
|
906
994
|
this.models = { status: "loading" };
|
|
907
995
|
this.store.set(this.projection());
|
|
908
|
-
void this.
|
|
996
|
+
void this.readModels().then((response) => {
|
|
909
997
|
if (request !== this.modelsRequest) return;
|
|
910
998
|
this.models = response.ok ? {
|
|
911
999
|
status: "ready",
|
|
@@ -974,6 +1062,9 @@ var OpencodeGoSectionController = class {
|
|
|
974
1062
|
setEnabled: (next) => {
|
|
975
1063
|
this.setEnabled(next);
|
|
976
1064
|
},
|
|
1065
|
+
setShowDeprecatedModels: (next) => {
|
|
1066
|
+
void this.setShowDeprecatedModels(next);
|
|
1067
|
+
},
|
|
977
1068
|
...this.form.actions()
|
|
978
1069
|
};
|
|
979
1070
|
return this.face;
|
|
@@ -1031,7 +1122,7 @@ var en = {
|
|
|
1031
1122
|
usageUnavailable: "Unavailable",
|
|
1032
1123
|
nav: "OpenCode Go",
|
|
1033
1124
|
title: "OpenCode Go",
|
|
1034
|
-
intro: "
|
|
1125
|
+
intro: "Manage your OpenCode Go subscription models and their capacities.",
|
|
1035
1126
|
enabledLabel: "Enable OpenCode Go",
|
|
1036
1127
|
enabledHint: "While this is on, OpenCode Go appears in every model picker and can serve requests. Turning it off withdraws the provider and its models immediately; this page stays reachable so you can turn it back on.",
|
|
1037
1128
|
enabledOff: "OpenCode Go is off. Its models are withdrawn from every picker and no request reaches the gateway. Turn the switch back on to use it again.",
|
|
@@ -1048,14 +1139,29 @@ var en = {
|
|
|
1048
1139
|
modelsEmpty: "The gateway currently serves no model this adapter can route.",
|
|
1049
1140
|
modelsCount: "{count} models",
|
|
1050
1141
|
limitsLabel: "Model capacities",
|
|
1051
|
-
limitsHint: "
|
|
1142
|
+
limitsHint: "Capacities come from the model API. Leave blank to use the default; save to apply your overrides.",
|
|
1052
1143
|
limitsFilterLabel: "Find a model",
|
|
1053
1144
|
limitsFilterPlaceholder: "Search by model name or id\u2026",
|
|
1054
1145
|
limitsSummary: "{count} customized",
|
|
1055
1146
|
limitsModel: "Model",
|
|
1056
1147
|
limitsContext: "Context window",
|
|
1057
1148
|
limitsOutput: "Max output",
|
|
1058
|
-
|
|
1149
|
+
capacityDefault: "Default: {value} tokens",
|
|
1150
|
+
capacityMissing: "API did not provide a value",
|
|
1151
|
+
showDeprecatedLabel: "Show deprecated models in conversations",
|
|
1152
|
+
showDeprecatedHint: "Off by default. Turning this on immediately adds deprecated models still served by the gateway to conversation model pickers.",
|
|
1153
|
+
pickerFailed: "Could not update model visibility. Please retry.",
|
|
1154
|
+
deprecatedBadge: "Deprecated",
|
|
1155
|
+
deprecatedHint: "Marked deprecated by models.dev, but still provided by this gateway.",
|
|
1156
|
+
newHint: "Released within the last seven UTC calendar days, according to models.dev.",
|
|
1157
|
+
releasedOn: "Released {date}",
|
|
1158
|
+
releaseSource: "Release date: {date} \xB7 models.dev",
|
|
1159
|
+
modelDetails: "Model configuration",
|
|
1160
|
+
filterLabel: "Filter models",
|
|
1161
|
+
filterAll: "All",
|
|
1162
|
+
filterNew: "New in 7 days",
|
|
1163
|
+
filterCustom: "Customized",
|
|
1164
|
+
filterDeprecated: "Deprecated",
|
|
1059
1165
|
limitsResetModel: "Use catalog",
|
|
1060
1166
|
limitsResetAll: "Clear all overrides",
|
|
1061
1167
|
limitsNoMatches: "No models match \u201C{query}\u201D. Try a different name or id.",
|
|
@@ -1101,7 +1207,7 @@ var zh = {
|
|
|
1101
1207
|
usageUnavailable: "\u6682\u4E0D\u53EF\u7528",
|
|
1102
1208
|
nav: "OpenCode Go",
|
|
1103
1209
|
title: "OpenCode Go",
|
|
1104
|
-
intro: "\
|
|
1210
|
+
intro: "\u7BA1\u7406 OpenCode Go \u8BA2\u9605\u6A21\u578B\u53CA\u5176\u5BB9\u91CF\u3002",
|
|
1105
1211
|
enabledLabel: "\u542F\u7528 OpenCode Go",
|
|
1106
1212
|
enabledHint: "\u5F00\u542F\u65F6\uFF0COpenCode Go \u4F1A\u51FA\u73B0\u5728\u6240\u6709\u6A21\u578B\u9009\u62E9\u5668\u4E2D\u5E76\u53EF\u5904\u7406\u8BF7\u6C42\u3002\u5173\u95ED\u540E\u5C06\u7ACB\u5373\u64A4\u4E0B\u8BE5\u63D0\u4F9B\u65B9\u53CA\u5176\u6A21\u578B\uFF1B\u672C\u9875\u4ECD\u53EF\u8BBF\u95EE\uFF0C\u65B9\u4FBF\u4F60\u968F\u65F6\u91CD\u65B0\u5F00\u542F\u3002",
|
|
1107
1213
|
enabledOff: "OpenCode Go \u5DF2\u5173\u95ED\u3002\u5176\u6A21\u578B\u5DF2\u4ECE\u6240\u6709\u9009\u62E9\u5668\u4E2D\u64A4\u4E0B\uFF0C\u4E5F\u4E0D\u4F1A\u6709\u8BF7\u6C42\u53D1\u5F80\u7F51\u5173\u3002\u9700\u8981\u65F6\u628A\u5F00\u5173\u91CD\u65B0\u6253\u5F00\u5373\u53EF\u3002",
|
|
@@ -1118,14 +1224,29 @@ var zh = {
|
|
|
1118
1224
|
modelsEmpty: "\u7F51\u5173\u5F53\u524D\u6CA1\u6709\u672C\u9002\u914D\u5668\u53EF\u8DEF\u7531\u7684\u6A21\u578B\u3002",
|
|
1119
1225
|
modelsCount: "{count} \u4E2A\u6A21\u578B",
|
|
1120
1226
|
limitsLabel: "\u6A21\u578B\u5BB9\u91CF",
|
|
1121
|
-
limitsHint: "\
|
|
1227
|
+
limitsHint: "\u5BB9\u91CF\u6765\u81EA\u6A21\u578B API\u3002\u7559\u7A7A\u4F7F\u7528\u9ED8\u8BA4\u503C\uFF0C\u4FEE\u6539\u540E\u4FDD\u5B58\u751F\u6548\u3002",
|
|
1122
1228
|
limitsFilterLabel: "\u67E5\u627E\u6A21\u578B",
|
|
1123
1229
|
limitsFilterPlaceholder: "\u6309\u6A21\u578B\u540D\u79F0\u6216 ID \u641C\u7D22\u2026",
|
|
1124
1230
|
limitsSummary: "{count} \u4E2A\u5DF2\u81EA\u5B9A\u4E49",
|
|
1125
1231
|
limitsModel: "\u6A21\u578B",
|
|
1126
1232
|
limitsContext: "\u4E0A\u4E0B\u6587\u7A97\u53E3",
|
|
1127
1233
|
limitsOutput: "\u6700\u5927\u8F93\u51FA",
|
|
1128
|
-
|
|
1234
|
+
capacityDefault: "\u9ED8\u8BA4\uFF1A{value} tokens",
|
|
1235
|
+
capacityMissing: "API \u672A\u63D0\u4F9B",
|
|
1236
|
+
showDeprecatedLabel: "\u5728\u4F1A\u8BDD\u4E2D\u663E\u793A\u8FC7\u65F6\u6A21\u578B",
|
|
1237
|
+
showDeprecatedHint: "\u9ED8\u8BA4\u5173\u95ED\u3002\u5F00\u542F\u540E\uFF0C\u7F51\u5173\u4ECD\u63D0\u4F9B\u7684\u8FC7\u65F6\u6A21\u578B\u4F1A\u7ACB\u5373\u52A0\u5165\u4F1A\u8BDD\u6A21\u578B\u5217\u8868\u3002",
|
|
1238
|
+
pickerFailed: "\u6A21\u578B\u663E\u793A\u8BBE\u7F6E\u672A\u66F4\u65B0\uFF0C\u8BF7\u91CD\u8BD5\u3002",
|
|
1239
|
+
deprecatedBadge: "\u5DF2\u5F03\u7528",
|
|
1240
|
+
deprecatedHint: "models.dev \u6807\u8BB0\u4E3A\u5DF2\u5F03\u7528\uFF0C\u5F53\u524D\u7F51\u5173\u4ECD\u63D0\u4F9B\u6B64\u6A21\u578B\u3002",
|
|
1241
|
+
newHint: "\u4F9D\u636E models.dev \u53D1\u5E03\u65E5\u671F\uFF0C\u8FD1\u4E03\u4E2A UTC \u65E5\u5386\u65E5\u5185\u53D1\u5E03\u3002",
|
|
1242
|
+
releasedOn: "{date} \u53D1\u5E03",
|
|
1243
|
+
releaseSource: "\u53D1\u5E03\u65E5\u671F\uFF1A{date} \xB7 models.dev",
|
|
1244
|
+
modelDetails: "\u6A21\u578B\u914D\u7F6E",
|
|
1245
|
+
filterLabel: "\u7B5B\u9009\u6A21\u578B",
|
|
1246
|
+
filterAll: "\u5168\u90E8",
|
|
1247
|
+
filterNew: "\u8FD1 7 \u5929\u53D1\u5E03",
|
|
1248
|
+
filterCustom: "\u5DF2\u81EA\u5B9A\u4E49",
|
|
1249
|
+
filterDeprecated: "\u8FC7\u65F6\u6A21\u578B",
|
|
1129
1250
|
limitsResetModel: "\u4F7F\u7528\u76EE\u5F55\u503C",
|
|
1130
1251
|
limitsResetAll: "\u6E05\u9664\u5168\u90E8\u8986\u76D6",
|
|
1131
1252
|
limitsNoMatches: "\u6CA1\u6709\u5339\u914D\u201C{query}\u201D\u7684\u6A21\u578B\u3002\u8BF7\u5C1D\u8BD5\u5176\u4ED6\u540D\u79F0\u6216 ID\u3002",
|
|
@@ -1192,8 +1313,14 @@ var usageRemote = {
|
|
|
1192
1313
|
}]
|
|
1193
1314
|
};
|
|
1194
1315
|
|
|
1316
|
+
// src/remote-contract.ts
|
|
1317
|
+
var goRemote = {
|
|
1318
|
+
package: "dsh-opencode-go",
|
|
1319
|
+
descriptors: [...usageRemote.descriptors, ...modelsRemote.descriptors]
|
|
1320
|
+
};
|
|
1321
|
+
|
|
1195
1322
|
// src/client/UsagePill.tsx
|
|
1196
|
-
var
|
|
1323
|
+
var import_react3 = require("react");
|
|
1197
1324
|
|
|
1198
1325
|
// plugin-css:/Users/tanglei/Desktop/dsh-opencode-go/src/client/UsagePill.module.css
|
|
1199
1326
|
var id2 = "dsh-opencode-go/UsagePill.module.css";
|
|
@@ -1204,20 +1331,20 @@ if (!document.querySelector("style[data-plugin-css=" + JSON.stringify(id2) + "]"
|
|
|
1204
1331
|
style.textContent = ".dmPm3q_root{min-width:0;display:inline-flex;position:relative}.dmPm3q_trigger{color:inherit;opacity:.75;font:inherit;cursor:pointer;white-space:nowrap;background:0 0;border:0;border-radius:6px;padding:4px 6px;font-size:12px}.dmPm3q_trigger:hover,.dmPm3q_trigger:focus-visible{opacity:1;background:color-mix(in srgb, currentColor 8%, transparent)}.dmPm3q_panel{z-index:100;border:1px solid color-mix(in srgb, currentColor 18%, transparent);width:280px;max-width:calc(100vw - 32px);color:var(--dsw-alias-label-primary,CanvasText);background:var(--dsw-specific-menu,Canvas);border-radius:12px;padding:16px;font-size:12px;position:absolute;bottom:calc(100% + 12px);right:0;box-shadow:0 8px 30px #0002}.dmPm3q_hint{opacity:.65;font-size:11px;line-height:1.6}.dmPm3q_window{margin-top:14px}.dmPm3q_row{justify-content:space-between;margin-bottom:5px;display:flex}.dmPm3q_window progress{accent-color:#39a878;width:100%;height:5px;margin-bottom:5px;display:block}.dmPm3q_window progress::-webkit-progress-bar{background:color-mix(in srgb, currentColor 15%, transparent);border-radius:4px}.dmPm3q_window progress::-webkit-progress-value{background:#39a878;border-radius:4px}.dmPm3q_window progress::-moz-progress-bar{background:#39a878;border-radius:4px}";
|
|
1205
1332
|
document.head.appendChild(style);
|
|
1206
1333
|
}
|
|
1207
|
-
var UsagePill_default = { "
|
|
1334
|
+
var UsagePill_default = { "hint": "dmPm3q_hint", "row": "dmPm3q_row", "root": "dmPm3q_root", "window": "dmPm3q_window", "trigger": "dmPm3q_trigger", "panel": "dmPm3q_panel" };
|
|
1208
1335
|
|
|
1209
1336
|
// src/client/UsagePill.tsx
|
|
1210
|
-
var
|
|
1337
|
+
var import_jsx_runtime3 = require("react/jsx-runtime");
|
|
1211
1338
|
function UsagePill({ directory, ...props }) {
|
|
1212
|
-
const state = (0,
|
|
1213
|
-
return state.current?.provider === "opencode-go" ? /* @__PURE__ */ (0,
|
|
1339
|
+
const state = (0, import_react3.useSyncExternalStore)(directory.subscribe, directory.getSnapshot, directory.getSnapshot);
|
|
1340
|
+
return state.current?.provider === "opencode-go" ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(ActiveUsage, { ...props }) : null;
|
|
1214
1341
|
}
|
|
1215
1342
|
function ActiveUsage({ readUsage, t }) {
|
|
1216
|
-
const [usage, setUsage] = (0,
|
|
1217
|
-
const [failed, setFailed] = (0,
|
|
1218
|
-
const [open, setOpen] = (0,
|
|
1219
|
-
const root = (0,
|
|
1220
|
-
(0,
|
|
1343
|
+
const [usage, setUsage] = (0, import_react3.useState)(null);
|
|
1344
|
+
const [failed, setFailed] = (0, import_react3.useState)(false);
|
|
1345
|
+
const [open, setOpen] = (0, import_react3.useState)(false);
|
|
1346
|
+
const root = (0, import_react3.useRef)(null);
|
|
1347
|
+
(0, import_react3.useEffect)(() => {
|
|
1221
1348
|
let alive = true;
|
|
1222
1349
|
let busy = false;
|
|
1223
1350
|
const refresh = async () => {
|
|
@@ -1252,7 +1379,7 @@ function ActiveUsage({ readUsage, t }) {
|
|
|
1252
1379
|
document.removeEventListener("visibilitychange", visible);
|
|
1253
1380
|
};
|
|
1254
1381
|
}, [readUsage]);
|
|
1255
|
-
(0,
|
|
1382
|
+
(0, import_react3.useEffect)(() => {
|
|
1256
1383
|
if (!open) return;
|
|
1257
1384
|
const click = (event) => {
|
|
1258
1385
|
if (!root.current?.contains(event.target)) setOpen(false);
|
|
@@ -1268,8 +1395,8 @@ function ActiveUsage({ readUsage, t }) {
|
|
|
1268
1395
|
};
|
|
1269
1396
|
}, [open]);
|
|
1270
1397
|
const label = usage ? `Go \xB7 5h ${usage.rolling.percent}% \xB7 ${t("usageWeekShort")} ${usage.weekly.percent}%` : `Go \xB7 ${failed ? t("usageUnavailable") : "\u2026"}`;
|
|
1271
|
-
return /* @__PURE__ */ (0,
|
|
1272
|
-
/* @__PURE__ */ (0,
|
|
1398
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("span", { className: UsagePill_default.root, ref: root, children: [
|
|
1399
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
1273
1400
|
"button",
|
|
1274
1401
|
{
|
|
1275
1402
|
type: "button",
|
|
@@ -1283,25 +1410,25 @@ function ActiveUsage({ readUsage, t }) {
|
|
|
1283
1410
|
children: label
|
|
1284
1411
|
}
|
|
1285
1412
|
),
|
|
1286
|
-
open && /* @__PURE__ */ (0,
|
|
1287
|
-
/* @__PURE__ */ (0,
|
|
1288
|
-
/* @__PURE__ */ (0,
|
|
1289
|
-
usage ? ["rolling", "weekly", "monthly"].map((key) => /* @__PURE__ */ (0,
|
|
1290
|
-
/* @__PURE__ */ (0,
|
|
1291
|
-
/* @__PURE__ */ (0,
|
|
1292
|
-
/* @__PURE__ */ (0,
|
|
1413
|
+
open && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: UsagePill_default.panel, role: "dialog", "aria-label": t("usageTitle"), children: [
|
|
1414
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("strong", { children: t("usageTitle") }),
|
|
1415
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { className: UsagePill_default.hint, children: t("usageHint") }),
|
|
1416
|
+
usage ? ["rolling", "weekly", "monthly"].map((key) => /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: UsagePill_default.window, children: [
|
|
1417
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: UsagePill_default.row, children: [
|
|
1418
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { children: t(`usage_${key}`) }),
|
|
1419
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("strong", { children: [
|
|
1293
1420
|
usage[key].percent,
|
|
1294
1421
|
"%"
|
|
1295
1422
|
] })
|
|
1296
1423
|
] }),
|
|
1297
|
-
/* @__PURE__ */ (0,
|
|
1298
|
-
/* @__PURE__ */ (0,
|
|
1424
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("progress", { "aria-label": t(`usage_${key}`), max: 100, value: Math.min(100, usage[key].percent) }),
|
|
1425
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: UsagePill_default.hint, children: [
|
|
1299
1426
|
t("usageResets"),
|
|
1300
1427
|
" ",
|
|
1301
1428
|
new Date(usage[key].resetsAt).toLocaleString()
|
|
1302
1429
|
] }),
|
|
1303
|
-
usage[key].status === "rate-limited" && /* @__PURE__ */ (0,
|
|
1304
|
-
] }, key)) : /* @__PURE__ */ (0,
|
|
1430
|
+
usage[key].status === "rate-limited" && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { children: t("usageLimited") })
|
|
1431
|
+
] }, key)) : /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { children: failed ? t("usageUnavailable") : t("usageLoading") })
|
|
1305
1432
|
] })
|
|
1306
1433
|
] });
|
|
1307
1434
|
}
|
|
@@ -1309,27 +1436,23 @@ function ActiveUsage({ readUsage, t }) {
|
|
|
1309
1436
|
// src/client/usage.ts
|
|
1310
1437
|
function registerUsagePill(ctx) {
|
|
1311
1438
|
ctx.inject(["modelDirectories", "sessions", "remote.session"], (scope) => {
|
|
1312
|
-
scope.
|
|
1313
|
-
const
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
})
|
|
1330
|
-
}, UsagePill));
|
|
1331
|
-
});
|
|
1332
|
-
return unmount;
|
|
1439
|
+
scope.inject(["remote.opencodeGoUsage"], (ready) => {
|
|
1440
|
+
const readUsage = async () => {
|
|
1441
|
+
const result = await ready.remote.opencodeGoUsage.read();
|
|
1442
|
+
if (!result.ok) throw new Error("OpenCode Go usage unavailable");
|
|
1443
|
+
return result.value;
|
|
1444
|
+
};
|
|
1445
|
+
const translate = ready.locale.bind("settings.opencode-go");
|
|
1446
|
+
ready.slots.inject("conversation.input.right", () => ready.slots.register({
|
|
1447
|
+
name: "conversation.input.right",
|
|
1448
|
+
id: "opencode-go-usage",
|
|
1449
|
+
order: 1e3,
|
|
1450
|
+
inject: (sessionId) => ({
|
|
1451
|
+
directory: ready.modelDirectories.directoryFor(sessionId).store,
|
|
1452
|
+
readUsage,
|
|
1453
|
+
t: (key) => translate(key)
|
|
1454
|
+
})
|
|
1455
|
+
}, UsagePill));
|
|
1333
1456
|
});
|
|
1334
1457
|
});
|
|
1335
1458
|
}
|
|
@@ -1340,19 +1463,24 @@ var inject = ["slots", "locale", "remote", "remote.credentials", "remote.llm"];
|
|
|
1340
1463
|
function apply(ctx) {
|
|
1341
1464
|
ctx.effect(() => ctx.locale.register(NS, { zh, en }), "llm-opencode-go: copy dictionaries");
|
|
1342
1465
|
registerUsagePill(ctx);
|
|
1343
|
-
ctx.
|
|
1466
|
+
const modelsReady = ctx.remote.$mount(goRemote);
|
|
1467
|
+
ctx.effect(async () => await modelsReady);
|
|
1468
|
+
ctx.inject(["configForms", "remote.opencodeGoModels"], (child) => {
|
|
1344
1469
|
const forms = child.get("configForms");
|
|
1345
|
-
mountSettings(child, forms.get("opencode-go"));
|
|
1470
|
+
mountSettings(child, forms.get("opencode-go"), modelsReady);
|
|
1346
1471
|
});
|
|
1347
|
-
ctx.inject(["settingsScope"], (child) => {
|
|
1472
|
+
ctx.inject(["settingsScope", "remote.opencodeGoModels"], (child) => {
|
|
1348
1473
|
mountSettings(child, child.settingsScope.bind({
|
|
1349
1474
|
namespace: "llm-opencode-go",
|
|
1350
1475
|
decode: (section) => typeof section === "object" && section !== null ? section : void 0
|
|
1351
|
-
}));
|
|
1476
|
+
}), modelsReady);
|
|
1352
1477
|
});
|
|
1353
1478
|
}
|
|
1354
|
-
function mountSettings(ctx, scope) {
|
|
1355
|
-
const controller = new OpencodeGoSectionController(scope, ctx)
|
|
1479
|
+
function mountSettings(ctx, scope, modelsReady) {
|
|
1480
|
+
const controller = new OpencodeGoSectionController(scope, ctx, async () => {
|
|
1481
|
+
await modelsReady;
|
|
1482
|
+
return ctx.remote.opencodeGoModels.read();
|
|
1483
|
+
});
|
|
1356
1484
|
ctx.effect(() => () => controller.dispose());
|
|
1357
1485
|
const t = ctx.locale.bind(NS);
|
|
1358
1486
|
const injected = () => ({ ...controller.inject(), t });
|