@dan-ai-studio/dshopencodego 0.1.12 → 0.1.14
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 +2 -2
- package/README.md +2 -2
- package/lib/client.js +43 -112
- package/lib/index.js +15 -16
- package/lib/types/catalog/contract.js +9 -3
- package/lib/types/catalog/index.js +1 -5
- package/lib/types/catalog/metadata.d.ts +12 -8
- package/lib/types/catalog/metadata.js +17 -6
- package/lib/types/catalog/reading.js +1 -3
- package/lib/types/models.d.ts +4 -6
- package/package.json +1 -1
package/README.en.md
CHANGED
|
@@ -124,8 +124,8 @@ The "OpenCode Go" section shows the live gateway catalog (42+ models) with, per
|
|
|
124
124
|
|
|
125
125
|
- **context / max input / max output**, **release date**, **price per 1M tokens** (from models.dev), and **Go allowance**;
|
|
126
126
|
- **Go allowance** comes from OpenCode's own documentation (the "usage limits / estimated requests" tables) — **no API exposes it**. It is a transcribed table (source URL and date in the `src/go-limits.ts` header); pricing or promotion changes require updating it and shipping a release;
|
|
127
|
-
- **
|
|
128
|
-
- filtering (by name/id, enabled-only, show-deprecated — **deprecated hidden by default**), sorting (newest first, monthly requests, input price, context, name, enabled first)
|
|
127
|
+
- **Input modalities**: a separate line lists the input modes models.dev declares (text / image / audio / video / PDF). These are the **model's own metadata**, not what the Harness can forward — the Harness sends text and images natively; audio/video/PDF travel as attachments and tool reads. The line is absent when the document declares none.
|
|
128
|
+
- filtering (by name/id, enabled-only, show-deprecated — **deprecated hidden by default**), sorting (newest first, monthly requests, input price, context, name, enabled first); the list is the only view, one model per row.
|
|
129
129
|
|
|
130
130
|
**Default switches**: with no explicit `modelVisibility` entries at all, the **top five models by published monthly request estimate** are enabled (deprecated, unconfigurable, and training-"contributor" models never qualify). The first explicit entry switches the whole list to explicit values. The Host picker and the settings page compute this from one rule, so they never disagree.
|
|
131
131
|
|
package/README.md
CHANGED
|
@@ -124,8 +124,8 @@ API Key 通过 Harness 凭证库提供(引用名 `OPENCODE_GO_API_KEY`),
|
|
|
124
124
|
|
|
125
125
|
- **上下文 / 输入 / 输出**(最大输入只有部分模型有官方数据)、**发布时间**、**单价 /1M**(来自 models.dev)、**Go 额度**;
|
|
126
126
|
- **Go 额度**来自 OpenCode 官方文档的「使用限制 / 预估请求数」表,**没有接口提供**,是本插件转写的数据表(见 `src/go-limits.ts` 的注释:来源 URL 与转写日期);文档调整价格或促销时需要更新该表并随发版发布。
|
|
127
|
-
-
|
|
128
|
-
- 筛选(按名称/ID、仅已启用、显示已弃用——**默认隐藏已弃用**)、排序(新发布优先 / 每月预估次数 / 输入单价 / 上下文 / 名称 /
|
|
127
|
+
- **输入模态**:单独一行列出 models.dev 声明的输入方式(文本 / 图像 / 音频 / 视频 / PDF)。这是**模型自身的元数据**,不等于 DSH 能直传:DSH 的模型输入只原生支持文本与图像,音视频/PDF 走附件与工具读取路径;文档未声明时该行不显示。
|
|
128
|
+
- 筛选(按名称/ID、仅已启用、显示已弃用——**默认隐藏已弃用**)、排序(新发布优先 / 每月预估次数 / 输入单价 / 上下文 / 名称 / 已启用优先);列表是唯一视图,逐模型纵向排列。
|
|
129
129
|
|
|
130
130
|
**默认开关规则**:没人显式配置过 `modelVisibility` 时,默认启用**每月预估次数最高的 5 个**(跳过已弃用、无法配置、以及"贡献者版"这类以数据换折扣的模型);**一旦有任一显式条目,全部按显式值走**。同一规则同时作用于模型选择器与设置页,两处不会出现不同答案。
|
|
131
131
|
|
package/lib/client.js
CHANGED
|
@@ -26,6 +26,13 @@ __export(index_exports, {
|
|
|
26
26
|
});
|
|
27
27
|
module.exports = __toCommonJS(index_exports);
|
|
28
28
|
|
|
29
|
+
// src/catalog/constants.ts
|
|
30
|
+
var MODEL_LISTING_MAX_BYTES = 1024 * 1024;
|
|
31
|
+
var MODEL_METADATA_MAX_BYTES = 16 * 1024 * 1024;
|
|
32
|
+
|
|
33
|
+
// src/catalog/metadata.ts
|
|
34
|
+
var INPUT_MODALITIES = ["text", "image", "audio", "video", "pdf"];
|
|
35
|
+
|
|
29
36
|
// src/catalog/contract.ts
|
|
30
37
|
function parseGoQuota(value) {
|
|
31
38
|
if (value === null || typeof value !== "object") throw new Error("invalid go quota");
|
|
@@ -58,6 +65,11 @@ function parseCost(value) {
|
|
|
58
65
|
...typeof row["cacheWrite"] === "number" ? { cacheWrite: rate("cacheWrite") } : {}
|
|
59
66
|
};
|
|
60
67
|
}
|
|
68
|
+
function parseModalities(value) {
|
|
69
|
+
if (!Array.isArray(value)) return {};
|
|
70
|
+
const kept = INPUT_MODALITIES.filter((modality) => value.includes(modality));
|
|
71
|
+
return kept.length === 0 ? {} : { inputModalities: kept };
|
|
72
|
+
}
|
|
61
73
|
function parseModel(value) {
|
|
62
74
|
if (value === null || typeof value !== "object") throw new Error("invalid catalog model");
|
|
63
75
|
const row = value;
|
|
@@ -74,9 +86,7 @@ function parseModel(value) {
|
|
|
74
86
|
...row["cost"] === void 0 ? {} : { cost: parseCost(row["cost"]) },
|
|
75
87
|
...row["protocolSource"] === "builtin" || row["protocolSource"] === "online" || row["protocolSource"] === "inferred" || row["protocolSource"] === "override" ? { protocolSource: row["protocolSource"] } : {},
|
|
76
88
|
...typeof row["assumedLimits"] === "boolean" ? { assumedLimits: row["assumedLimits"] } : {},
|
|
77
|
-
...
|
|
78
|
-
...typeof row["temperature"] === "boolean" ? { temperature: row["temperature"] } : {},
|
|
79
|
-
...typeof row["openWeights"] === "boolean" ? { openWeights: row["openWeights"] } : {},
|
|
89
|
+
...parseModalities(row["inputModalities"]),
|
|
80
90
|
...typeof row["configurationMissing"] === "string" ? { configurationMissing: row["configurationMissing"] } : {}
|
|
81
91
|
};
|
|
82
92
|
}
|
|
@@ -259,20 +269,12 @@ var en = {
|
|
|
259
269
|
sortEnabled: "Enabled first",
|
|
260
270
|
sortQuota: "Monthly requests",
|
|
261
271
|
sortPrice: "Input price",
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
headerIo: "In / Out",
|
|
269
|
-
headerPrice: "Price /1M",
|
|
270
|
-
headerQuota: "Go quota",
|
|
271
|
-
headerCapabilities: "Capabilities",
|
|
272
|
-
headerNotes: "Notes",
|
|
273
|
-
capStructured: "Structured",
|
|
274
|
-
capTemperature: "Temp",
|
|
275
|
-
capOpenWeights: "Open",
|
|
272
|
+
inputLabel: "Input",
|
|
273
|
+
modalityText: "Text",
|
|
274
|
+
modalityImage: "Image",
|
|
275
|
+
modalityAudio: "Audio",
|
|
276
|
+
modalityVideo: "Video",
|
|
277
|
+
modalityPdf: "PDF",
|
|
276
278
|
iosInput: "in",
|
|
277
279
|
iosOutput: "out",
|
|
278
280
|
iosContext: "ctx",
|
|
@@ -333,20 +335,12 @@ var zh = {
|
|
|
333
335
|
sortEnabled: "\u5DF2\u542F\u7528\u4F18\u5148",
|
|
334
336
|
sortQuota: "\u6BCF\u6708\u9884\u4F30\u6B21\u6570",
|
|
335
337
|
sortPrice: "\u8F93\u5165\u5355\u4EF7",
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
headerIo: "\u8F93\u5165 / \u8F93\u51FA",
|
|
343
|
-
headerPrice: "\u5355\u4EF7 /1M",
|
|
344
|
-
headerQuota: "Go \u989D\u5EA6",
|
|
345
|
-
headerCapabilities: "\u80FD\u529B",
|
|
346
|
-
headerNotes: "\u5907\u6CE8",
|
|
347
|
-
capStructured: "\u7ED3\u6784\u5316",
|
|
348
|
-
capTemperature: "\u6E29\u5EA6",
|
|
349
|
-
capOpenWeights: "\u5F00\u6E90",
|
|
338
|
+
inputLabel: "\u8F93\u5165",
|
|
339
|
+
modalityText: "\u6587\u672C",
|
|
340
|
+
modalityImage: "\u56FE\u50CF",
|
|
341
|
+
modalityAudio: "\u97F3\u9891",
|
|
342
|
+
modalityVideo: "\u89C6\u9891",
|
|
343
|
+
modalityPdf: "PDF",
|
|
350
344
|
iosInput: "\u5165",
|
|
351
345
|
iosOutput: "\u51FA",
|
|
352
346
|
iosContext: "\u4E0A\u4E0B\u6587",
|
|
@@ -396,8 +390,7 @@ var INITIAL_FILTER = {
|
|
|
396
390
|
query: "",
|
|
397
391
|
showDeprecated: false,
|
|
398
392
|
onlyEnabled: false,
|
|
399
|
-
sort: "quota"
|
|
400
|
-
view: "list"
|
|
393
|
+
sort: "quota"
|
|
401
394
|
};
|
|
402
395
|
function compactCount(value) {
|
|
403
396
|
if (value >= 1e6) return `${(value / 1e6).toFixed(value >= 1e7 ? 0 : 1)}M`;
|
|
@@ -441,12 +434,15 @@ function visibleModels(models, filter, visibility, locale) {
|
|
|
441
434
|
});
|
|
442
435
|
return sortRows(rows, filter.sort, visibility, locale);
|
|
443
436
|
}
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
437
|
+
var MODALITY_KEYS = {
|
|
438
|
+
text: "modalityText",
|
|
439
|
+
image: "modalityImage",
|
|
440
|
+
audio: "modalityAudio",
|
|
441
|
+
video: "modalityVideo",
|
|
442
|
+
pdf: "modalityPdf"
|
|
443
|
+
};
|
|
444
|
+
function inputModalityLabels(model, t) {
|
|
445
|
+
return (model.inputModalities ?? []).map((modality) => t(MODALITY_KEYS[modality]));
|
|
450
446
|
}
|
|
451
447
|
|
|
452
448
|
// plugin-css:/home/runner/work/dshopencodego/dshopencodego/src/client/section.module.css
|
|
@@ -455,10 +451,10 @@ if (!document.querySelector("style[data-plugin-css=" + JSON.stringify(id) + "]")
|
|
|
455
451
|
const style = document.createElement("style");
|
|
456
452
|
style.dataset.plugin = "@dan-ai-studio/dshopencodego";
|
|
457
453
|
style.dataset.pluginCss = id;
|
|
458
|
-
style.textContent = ".d7lz0W_root{color:var(--dsw-alias-label-primary);flex-direction:column;gap:1.25rem;display:flex}.d7lz0W_title{margin:0;font-size:1.05rem}.d7lz0W_hint{color:var(--dsw-alias-label-secondary);margin:0;font-size:.8rem}.d7lz0W_warn{color:var(--dsw-alias-state-warn-primary);margin:0;font-size:.8rem}.d7lz0W_ok{color:var(--dsw-alias-state-success-primary);font-size:.8rem}.d7lz0W_block{border:1px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-bg-layer-1);border-radius:.6rem;flex-direction:column;gap:.5rem;padding:.85rem;display:flex}.d7lz0W_row{flex-wrap:wrap;align-items:center;gap:.5rem;display:flex}.d7lz0W_row>strong{margin-right:auto}.d7lz0W_input{border:1px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-bg-base);min-width:10rem;color:var(--dsw-alias-label-primary);font:inherit;border-radius:.35rem;flex:14rem;padding:.35rem .5rem;font-size:.85rem}.d7lz0W_button{border:1px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-bg-layer-2);color:var(--dsw-alias-label-primary);font:inherit;cursor:pointer;border-radius:.35rem;padding:.35rem .7rem;font-size:.8rem}.d7lz0W_button:disabled{color:var(--dsw-alias-state-idle-primary);cursor:default}.d7lz0W_number{border:1px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-bg-base);width:5rem;color:var(--dsw-alias-label-primary);font:inherit;border-radius:.35rem;padding:.25rem .4rem;font-size:.8rem}.d7lz0W_select{border:1px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-bg-base);width:auto;max-width:100%;color:var(--dsw-alias-label-primary);font:inherit;border-radius:.35rem;padding:.25rem .4rem;font-size:.8rem}.
|
|
454
|
+
style.textContent = ".d7lz0W_root{color:var(--dsw-alias-label-primary);flex-direction:column;gap:1.25rem;display:flex}.d7lz0W_title{margin:0;font-size:1.05rem}.d7lz0W_hint{color:var(--dsw-alias-label-secondary);margin:0;font-size:.8rem}.d7lz0W_warn{color:var(--dsw-alias-state-warn-primary);margin:0;font-size:.8rem}.d7lz0W_ok{color:var(--dsw-alias-state-success-primary);font-size:.8rem}.d7lz0W_block{border:1px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-bg-layer-1);border-radius:.6rem;flex-direction:column;gap:.5rem;padding:.85rem;display:flex}.d7lz0W_row{flex-wrap:wrap;align-items:center;gap:.5rem;display:flex}.d7lz0W_row>strong{margin-right:auto}.d7lz0W_input{border:1px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-bg-base);min-width:10rem;color:var(--dsw-alias-label-primary);font:inherit;border-radius:.35rem;flex:14rem;padding:.35rem .5rem;font-size:.85rem}.d7lz0W_button{border:1px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-bg-layer-2);color:var(--dsw-alias-label-primary);font:inherit;cursor:pointer;border-radius:.35rem;padding:.35rem .7rem;font-size:.8rem}.d7lz0W_button:disabled{color:var(--dsw-alias-state-idle-primary);cursor:default}.d7lz0W_number{border:1px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-bg-base);width:5rem;color:var(--dsw-alias-label-primary);font:inherit;border-radius:.35rem;padding:.25rem .4rem;font-size:.8rem}.d7lz0W_select{border:1px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-bg-base);width:auto;max-width:100%;color:var(--dsw-alias-label-primary);font:inherit;border-radius:.35rem;padding:.25rem .4rem;font-size:.8rem}.d7lz0W_list{flex-direction:column;display:flex}.d7lz0W_item{border-top:1px solid var(--dsw-alias-border-l1);align-items:flex-start;gap:.5rem;padding:.45rem .15rem;display:flex}.d7lz0W_item input[type=checkbox]{accent-color:var(--dsw-alias-brand-primary);margin-top:.15rem}.d7lz0W_itemBody{flex-direction:column;gap:.15rem;min-width:0;display:flex}.d7lz0W_itemMain{flex-wrap:wrap;align-items:baseline;gap:.6rem;display:flex}.d7lz0W_itemMeta{color:var(--dsw-alias-label-secondary);flex-wrap:wrap;gap:.75rem;font-size:.75rem;display:flex}.d7lz0W_itemModalities{color:var(--dsw-alias-label-secondary);font-size:.75rem}.d7lz0W_name{color:var(--dsw-alias-label-primary)}.d7lz0W_mono{color:var(--dsw-alias-label-secondary);font-family:ui-monospace,SFMono-Regular,Menlo,monospace}.d7lz0W_badge{color:var(--dsw-alias-brand-primary)}";
|
|
459
455
|
document.head.appendChild(style);
|
|
460
456
|
}
|
|
461
|
-
var section_default = { "
|
|
457
|
+
var section_default = { "itemBody": "d7lz0W_itemBody", "root": "d7lz0W_root", "input": "d7lz0W_input", "name": "d7lz0W_name", "title": "d7lz0W_title", "list": "d7lz0W_list", "badge": "d7lz0W_badge", "warn": "d7lz0W_warn", "itemModalities": "d7lz0W_itemModalities", "block": "d7lz0W_block", "mono": "d7lz0W_mono", "row": "d7lz0W_row", "itemMeta": "d7lz0W_itemMeta", "button": "d7lz0W_button", "select": "d7lz0W_select", "number": "d7lz0W_number", "item": "d7lz0W_item", "ok": "d7lz0W_ok", "hint": "d7lz0W_hint", "itemMain": "d7lz0W_itemMain" };
|
|
462
458
|
|
|
463
459
|
// src/client/Section.tsx
|
|
464
460
|
var import_jsx_runtime = require("react/jsx-runtime");
|
|
@@ -898,80 +894,15 @@ function Section({ controller, t, getLocale }) {
|
|
|
898
894
|
}
|
|
899
895
|
)
|
|
900
896
|
] }),
|
|
901
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: section_default.segmented, children: [
|
|
902
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
903
|
-
"button",
|
|
904
|
-
{
|
|
905
|
-
type: "button",
|
|
906
|
-
className: state.filter.view === "list" ? section_default.segmentActive : section_default.segment,
|
|
907
|
-
onClick: () => {
|
|
908
|
-
controller.setFilter({ view: "list" });
|
|
909
|
-
},
|
|
910
|
-
children: t("viewList")
|
|
911
|
-
}
|
|
912
|
-
),
|
|
913
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
914
|
-
"button",
|
|
915
|
-
{
|
|
916
|
-
type: "button",
|
|
917
|
-
className: state.filter.view === "table" ? section_default.segmentActive : section_default.segment,
|
|
918
|
-
onClick: () => {
|
|
919
|
-
controller.setFilter({ view: "table" });
|
|
920
|
-
},
|
|
921
|
-
children: t("viewTable")
|
|
922
|
-
}
|
|
923
|
-
)
|
|
924
|
-
] }),
|
|
925
897
|
hidden > 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: section_default.hint, children: [
|
|
926
898
|
hidden,
|
|
927
899
|
" ",
|
|
928
900
|
t("filterHidden")
|
|
929
901
|
] })
|
|
930
902
|
] }),
|
|
931
|
-
reading !== void 0 &&
|
|
932
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("thead", { children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("tr", { children: [
|
|
933
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("th", {}),
|
|
934
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("th", { className: section_default.hint, children: t("headerModel") }),
|
|
935
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("th", { className: section_default.hint, children: t("headerId") }),
|
|
936
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("th", { className: section_default.hint, children: t("headerReleased") }),
|
|
937
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("th", { className: section_default.hint, children: t("headerCapacity") }),
|
|
938
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("th", { className: section_default.hint, children: t("headerIo") }),
|
|
939
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("th", { className: section_default.hint, children: t("headerPrice") }),
|
|
940
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("th", { className: section_default.hint, children: t("headerQuota") }),
|
|
941
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("th", { className: section_default.hint, children: t("headerCapabilities") }),
|
|
942
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("th", { className: section_default.hint, children: t("headerNotes") })
|
|
943
|
-
] }) }),
|
|
944
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("tbody", { children: rows.map((model) => {
|
|
945
|
-
const badge = badgeFor(model, t);
|
|
946
|
-
const capabilities = capabilityLabels(model, t).join(" \xB7 ");
|
|
947
|
-
const offered = isOffered(model, visibility);
|
|
948
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("tr", { children: [
|
|
949
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("td", { className: section_default.toggle, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
950
|
-
"input",
|
|
951
|
-
{
|
|
952
|
-
type: "checkbox",
|
|
953
|
-
"aria-label": `${t("catalogTitle")}: ${model.name}`,
|
|
954
|
-
checked: offered,
|
|
955
|
-
disabled: !editable || model.configurationMissing !== void 0,
|
|
956
|
-
onChange: (event) => {
|
|
957
|
-
controller.setVisibility(model.id, event.target.checked);
|
|
958
|
-
}
|
|
959
|
-
}
|
|
960
|
-
) }),
|
|
961
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("td", { className: section_default.name, children: model.name }),
|
|
962
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("td", { className: section_default.mono, children: model.id }),
|
|
963
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("td", { className: section_default.hint, children: model.releaseDate ?? "\u2014" }),
|
|
964
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("td", { className: section_default.hint, children: model.contextWindow === void 0 ? "\u2014" : model.contextWindow.toLocaleString(getLocale?.()) }),
|
|
965
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("td", { className: section_default.hint, children: ioLabel(model, t) }),
|
|
966
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("td", { className: section_default.hint, children: priceLabel(model) }),
|
|
967
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("td", { className: section_default.hint, children: quotaLabel(model, t) }),
|
|
968
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("td", { className: section_default.hint, children: capabilities.length === 0 ? "\u2014" : capabilities }),
|
|
969
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("td", { className: badge.length === 0 ? section_default.hint : section_default.badge, children: badge })
|
|
970
|
-
] }, model.id);
|
|
971
|
-
}) })
|
|
972
|
-
] }) }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: section_default.list, children: rows.map((model) => {
|
|
903
|
+
reading !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: section_default.list, children: rows.map((model) => {
|
|
973
904
|
const badge = badgeFor(model, t);
|
|
974
|
-
const
|
|
905
|
+
const modalities = inputModalityLabels(model, t).join(" \xB7 ");
|
|
975
906
|
const offered = isOffered(model, visibility);
|
|
976
907
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: section_default.item, children: [
|
|
977
908
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
@@ -991,7 +922,6 @@ function Section({ controller, t, getLocale }) {
|
|
|
991
922
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: section_default.name, children: model.name }),
|
|
992
923
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: section_default.mono, children: model.id }),
|
|
993
924
|
model.releaseDate !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: section_default.hint, children: model.releaseDate }),
|
|
994
|
-
capabilities.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: section_default.badge, children: capabilities }),
|
|
995
925
|
badge.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: section_default.badge, children: badge })
|
|
996
926
|
] }),
|
|
997
927
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: section_default.itemMeta, children: [
|
|
@@ -999,10 +929,11 @@ function Section({ controller, t, getLocale }) {
|
|
|
999
929
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: ioLabel(model, t) }),
|
|
1000
930
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: priceLabel(model) }),
|
|
1001
931
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: quotaLabel(model, t) })
|
|
1002
|
-
] })
|
|
932
|
+
] }),
|
|
933
|
+
modalities.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: section_default.itemModalities, children: `${t("inputLabel")} ${modalities}` })
|
|
1003
934
|
] })
|
|
1004
935
|
] }, model.id);
|
|
1005
|
-
}) })
|
|
936
|
+
}) })
|
|
1006
937
|
] })
|
|
1007
938
|
] });
|
|
1008
939
|
}
|
|
@@ -1019,7 +950,7 @@ if (!document.querySelector("style[data-plugin-css=" + JSON.stringify(id2) + "]"
|
|
|
1019
950
|
style.textContent = ".mMNkkW_root{align-items:center;display:inline-flex;position:relative}.mMNkkW_trigger{border:1px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-bg-layer-1);color:var(--dsw-alias-label-secondary);font:inherit;cursor:pointer;white-space:nowrap;border-radius:999px;padding:.35rem .6rem;font-size:.8rem;line-height:1}.mMNkkW_trigger:hover{color:var(--dsw-alias-label-primary);border-color:var(--dsw-alias-border-l2)}.mMNkkW_panel{z-index:20;border:1px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-bg-overlay);width:18rem;color:var(--dsw-alias-label-primary);border-radius:.6rem;flex-direction:column;gap:.6rem;padding:.75rem .85rem;display:flex;position:absolute;bottom:calc(100% + .5rem);right:0;box-shadow:0 8px 24px #0000002e}.mMNkkW_window{flex-direction:column;gap:.25rem;display:flex}.mMNkkW_row{justify-content:space-between;gap:.5rem;font-size:.85rem;display:flex}.mMNkkW_hint{color:var(--dsw-alias-label-secondary);margin:0;font-size:.75rem}.mMNkkW_progress{width:100%;height:.35rem;accent-color:var(--dsw-alias-brand-primary)}.mMNkkW_limited{color:var(--dsw-alias-state-warn-primary);font-size:.75rem}.mMNkkW_warning{border:1px solid var(--dsw-alias-state-warn-primary);color:var(--dsw-alias-label-primary);border-radius:.4rem;padding:.4rem .5rem;font-size:.75rem}.mMNkkW_retry{border:1px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-bg-layer-1);color:var(--dsw-alias-label-primary);font:inherit;cursor:pointer;border-radius:.35rem;align-self:flex-start;padding:.25rem .5rem;font-size:.75rem}.mMNkkW_local{border-top:1px solid var(--dsw-alias-border-l1);flex-direction:column;gap:.2rem;padding-top:.5rem;display:flex}";
|
|
1020
951
|
document.head.appendChild(style);
|
|
1021
952
|
}
|
|
1022
|
-
var pill_default = { "
|
|
953
|
+
var pill_default = { "trigger": "mMNkkW_trigger", "limited": "mMNkkW_limited", "panel": "mMNkkW_panel", "retry": "mMNkkW_retry", "local": "mMNkkW_local", "hint": "mMNkkW_hint", "progress": "mMNkkW_progress", "warning": "mMNkkW_warning", "row": "mMNkkW_row", "root": "mMNkkW_root", "window": "mMNkkW_window" };
|
|
1023
954
|
|
|
1024
955
|
// src/client/UsagePill.tsx
|
|
1025
956
|
var import_jsx_runtime2 = require("react/jsx-runtime");
|
package/lib/index.js
CHANGED
|
@@ -202,6 +202,7 @@ function decideProtocol(id, evidence) {
|
|
|
202
202
|
}
|
|
203
203
|
|
|
204
204
|
// src/catalog/metadata.ts
|
|
205
|
+
var INPUT_MODALITIES = ["text", "image", "audio", "video", "pdf"];
|
|
205
206
|
var LEVELS = ["off", "minimal", "low", "medium", "high", "xhigh", "max"];
|
|
206
207
|
function record(value) {
|
|
207
208
|
return value !== null && typeof value === "object" && !Array.isArray(value) ? value : {};
|
|
@@ -212,8 +213,11 @@ function positiveInteger(value) {
|
|
|
212
213
|
function nonEmptyString(value) {
|
|
213
214
|
return typeof value === "string" && value.length > 0 ? value : void 0;
|
|
214
215
|
}
|
|
215
|
-
function
|
|
216
|
-
|
|
216
|
+
function readInputModalities(metadata) {
|
|
217
|
+
const declared = record(metadata["modalities"])["input"];
|
|
218
|
+
if (!Array.isArray(declared)) return void 0;
|
|
219
|
+
const kept = INPUT_MODALITIES.filter((modality) => declared.includes(modality));
|
|
220
|
+
return kept.length === 0 ? void 0 : kept;
|
|
217
221
|
}
|
|
218
222
|
function validReleaseDate(value) {
|
|
219
223
|
if (typeof value !== "string" || !/^\d{4}-\d{2}-\d{2}$/.test(value)) return void 0;
|
|
@@ -344,11 +348,9 @@ function readOnlineMetadata(body, sources) {
|
|
|
344
348
|
maxTokens,
|
|
345
349
|
assumedLimits: onlineContext === void 0 && builtinContext === void 0 || onlineOutput === void 0 && builtinOutput === void 0,
|
|
346
350
|
input,
|
|
351
|
+
inputModalities: readInputModalities(metadata),
|
|
347
352
|
reasoning,
|
|
348
353
|
thinkingLevelMap: reasoning ? thinkingLevels(metadata, exact?.api === api ? exact : sibling) : void 0,
|
|
349
|
-
structuredOutput: declaredBoolean(metadata["structured_output"]),
|
|
350
|
-
temperature: declaredBoolean(metadata["temperature"]),
|
|
351
|
-
openWeights: declaredBoolean(metadata["open_weights"]),
|
|
352
354
|
compat: compatFor(api, metadata, exact, sibling),
|
|
353
355
|
cost,
|
|
354
356
|
deprecated: metadata["status"] === "deprecated",
|
|
@@ -540,13 +542,9 @@ var OpencodeGoCatalog = class {
|
|
|
540
542
|
maxTokens,
|
|
541
543
|
assumedLimits: exact === void 0,
|
|
542
544
|
input: exact?.input ?? this.options.defaults.input,
|
|
545
|
+
inputModalities: void 0,
|
|
543
546
|
reasoning: exact?.reasoning ?? false,
|
|
544
547
|
thinkingLevelMap: exact?.thinkingLevelMap,
|
|
545
|
-
// No source describes these, so the page says nothing instead of
|
|
546
|
-
// guessing: the installed catalog knows wire shapes, not capabilities.
|
|
547
|
-
structuredOutput: void 0,
|
|
548
|
-
temperature: void 0,
|
|
549
|
-
openWeights: void 0,
|
|
550
548
|
compat: exact?.compat ?? {},
|
|
551
549
|
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
|
|
552
550
|
deprecated: false,
|
|
@@ -1508,6 +1506,11 @@ function parseCost(value) {
|
|
|
1508
1506
|
...typeof row["cacheWrite"] === "number" ? { cacheWrite: rate("cacheWrite") } : {}
|
|
1509
1507
|
};
|
|
1510
1508
|
}
|
|
1509
|
+
function parseModalities(value) {
|
|
1510
|
+
if (!Array.isArray(value)) return {};
|
|
1511
|
+
const kept = INPUT_MODALITIES.filter((modality) => value.includes(modality));
|
|
1512
|
+
return kept.length === 0 ? {} : { inputModalities: kept };
|
|
1513
|
+
}
|
|
1511
1514
|
function parseModel(value) {
|
|
1512
1515
|
if (value === null || typeof value !== "object") throw new Error("invalid catalog model");
|
|
1513
1516
|
const row = value;
|
|
@@ -1524,9 +1527,7 @@ function parseModel(value) {
|
|
|
1524
1527
|
...row["cost"] === void 0 ? {} : { cost: parseCost(row["cost"]) },
|
|
1525
1528
|
...row["protocolSource"] === "builtin" || row["protocolSource"] === "online" || row["protocolSource"] === "inferred" || row["protocolSource"] === "override" ? { protocolSource: row["protocolSource"] } : {},
|
|
1526
1529
|
...typeof row["assumedLimits"] === "boolean" ? { assumedLimits: row["assumedLimits"] } : {},
|
|
1527
|
-
...
|
|
1528
|
-
...typeof row["temperature"] === "boolean" ? { temperature: row["temperature"] } : {},
|
|
1529
|
-
...typeof row["openWeights"] === "boolean" ? { openWeights: row["openWeights"] } : {},
|
|
1530
|
+
...parseModalities(row["inputModalities"]),
|
|
1530
1531
|
...typeof row["configurationMissing"] === "string" ? { configurationMissing: row["configurationMissing"] } : {}
|
|
1531
1532
|
};
|
|
1532
1533
|
}
|
|
@@ -1717,9 +1718,7 @@ function catalogReading(snapshot, visibility, listingFailure) {
|
|
|
1717
1718
|
},
|
|
1718
1719
|
protocolSource: fact.protocolSource,
|
|
1719
1720
|
assumedLimits: fact.assumedLimits,
|
|
1720
|
-
...fact.
|
|
1721
|
-
...fact.temperature === void 0 ? {} : { temperature: fact.temperature },
|
|
1722
|
-
...fact.openWeights === void 0 ? {} : { openWeights: fact.openWeights }
|
|
1721
|
+
...fact.inputModalities === void 0 ? {} : { inputModalities: fact.inputModalities }
|
|
1723
1722
|
};
|
|
1724
1723
|
}),
|
|
1725
1724
|
...[...snapshot.unavailable].map(([id, reason]) => ({ id, name: id, configurationMissing: reason }))
|
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
*
|
|
10
10
|
* @module @dan-ai-studio/dshopencodego/catalog/contract
|
|
11
11
|
*/
|
|
12
|
+
import { INPUT_MODALITIES } from "./metadata.js";
|
|
12
13
|
function parseGoQuota(value) {
|
|
13
14
|
if (value === null || typeof value !== 'object')
|
|
14
15
|
throw new Error('invalid go quota');
|
|
@@ -44,6 +45,13 @@ function parseCost(value) {
|
|
|
44
45
|
...typeof row['cacheWrite'] === 'number' ? { cacheWrite: rate('cacheWrite') } : {},
|
|
45
46
|
};
|
|
46
47
|
}
|
|
48
|
+
/** Recognised input modalities out of one wire value; absent when none survive. */
|
|
49
|
+
function parseModalities(value) {
|
|
50
|
+
if (!Array.isArray(value))
|
|
51
|
+
return {};
|
|
52
|
+
const kept = INPUT_MODALITIES.filter(modality => value.includes(modality));
|
|
53
|
+
return kept.length === 0 ? {} : { inputModalities: kept };
|
|
54
|
+
}
|
|
47
55
|
function parseModel(value) {
|
|
48
56
|
if (value === null || typeof value !== 'object')
|
|
49
57
|
throw new Error('invalid catalog model');
|
|
@@ -64,9 +72,7 @@ function parseModel(value) {
|
|
|
64
72
|
|| row['protocolSource'] === 'inferred' || row['protocolSource'] === 'override'
|
|
65
73
|
? { protocolSource: row['protocolSource'] } : {},
|
|
66
74
|
...typeof row['assumedLimits'] === 'boolean' ? { assumedLimits: row['assumedLimits'] } : {},
|
|
67
|
-
...
|
|
68
|
-
...typeof row['temperature'] === 'boolean' ? { temperature: row['temperature'] } : {},
|
|
69
|
-
...typeof row['openWeights'] === 'boolean' ? { openWeights: row['openWeights'] } : {},
|
|
75
|
+
...parseModalities(row['inputModalities']),
|
|
70
76
|
...typeof row['configurationMissing'] === 'string' ? { configurationMissing: row['configurationMissing'] } : {},
|
|
71
77
|
};
|
|
72
78
|
}
|
|
@@ -206,13 +206,9 @@ export class OpencodeGoCatalog {
|
|
|
206
206
|
maxTokens,
|
|
207
207
|
assumedLimits: exact === undefined,
|
|
208
208
|
input: exact?.input ?? this.options.defaults.input,
|
|
209
|
+
inputModalities: undefined,
|
|
209
210
|
reasoning: exact?.reasoning ?? false,
|
|
210
211
|
thinkingLevelMap: exact?.thinkingLevelMap,
|
|
211
|
-
// No source describes these, so the page says nothing instead of
|
|
212
|
-
// guessing: the installed catalog knows wire shapes, not capabilities.
|
|
213
|
-
structuredOutput: undefined,
|
|
214
|
-
temperature: undefined,
|
|
215
|
-
openWeights: undefined,
|
|
216
212
|
compat: exact?.compat ?? {},
|
|
217
213
|
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
|
|
218
214
|
deprecated: false,
|
|
@@ -16,6 +16,10 @@
|
|
|
16
16
|
*/
|
|
17
17
|
import type { Api, Model, ModelCost, ThinkingLevelMap } from '@earendil-works/pi-ai';
|
|
18
18
|
import type { ProtocolSource, WireProtocol } from './protocol.ts';
|
|
19
|
+
/** Input modalities this build can name, in display order. */
|
|
20
|
+
export declare const INPUT_MODALITIES: readonly ["text", "image", "audio", "video", "pdf"];
|
|
21
|
+
/** One input modality a model document may declare. */
|
|
22
|
+
export type InputModality = (typeof INPUT_MODALITIES)[number];
|
|
19
23
|
/** Everything this plugin knows about one advertised model. */
|
|
20
24
|
export interface ModelFacts {
|
|
21
25
|
readonly id: string;
|
|
@@ -30,16 +34,16 @@ export interface ModelFacts {
|
|
|
30
34
|
/** True when a capacity came from the route default rather than a source. */
|
|
31
35
|
readonly assumedLimits: boolean;
|
|
32
36
|
readonly input: readonly ('text' | 'image')[];
|
|
33
|
-
readonly reasoning: boolean;
|
|
34
|
-
readonly thinkingLevelMap: ThinkingLevelMap | undefined;
|
|
35
37
|
/**
|
|
36
|
-
*
|
|
37
|
-
* means
|
|
38
|
-
*
|
|
38
|
+
* Every input modality the document declares, in display order. `undefined`
|
|
39
|
+
* means it declares none this build can name — silence, not "text only".
|
|
40
|
+
* Kept beside {@link input} because the two answer different questions:
|
|
41
|
+
* `input` gates what this route may send, this one reports what the model
|
|
42
|
+
* itself accepts.
|
|
39
43
|
*/
|
|
40
|
-
readonly
|
|
41
|
-
readonly
|
|
42
|
-
readonly
|
|
44
|
+
readonly inputModalities: readonly InputModality[] | undefined;
|
|
45
|
+
readonly reasoning: boolean;
|
|
46
|
+
readonly thinkingLevelMap: ThinkingLevelMap | undefined;
|
|
43
47
|
readonly compat: Model<Api>['compat'];
|
|
44
48
|
readonly cost: ModelCost;
|
|
45
49
|
readonly deprecated: boolean;
|
|
@@ -16,6 +16,8 @@
|
|
|
16
16
|
*/
|
|
17
17
|
import { asWireProtocol, decideProtocol, protocolOfNpm } from "./protocol.js";
|
|
18
18
|
import { MODEL_METADATA_PROVIDER } from "./constants.js";
|
|
19
|
+
/** Input modalities this build can name, in display order. */
|
|
20
|
+
export const INPUT_MODALITIES = ['text', 'image', 'audio', 'video', 'pdf'];
|
|
19
21
|
const LEVELS = ['off', 'minimal', 'low', 'medium', 'high', 'xhigh', 'max'];
|
|
20
22
|
function record(value) {
|
|
21
23
|
return value !== null && typeof value === 'object' && !Array.isArray(value)
|
|
@@ -27,9 +29,20 @@ function positiveInteger(value) {
|
|
|
27
29
|
function nonEmptyString(value) {
|
|
28
30
|
return typeof value === 'string' && value.length > 0 ? value : undefined;
|
|
29
31
|
}
|
|
30
|
-
/**
|
|
31
|
-
|
|
32
|
-
|
|
32
|
+
/**
|
|
33
|
+
* Input modalities exactly as the document declares them, in display order.
|
|
34
|
+
*
|
|
35
|
+
* A modality this build cannot name is dropped rather than passed through: the
|
|
36
|
+
* settings page labels every value it renders. An absent list, or one naming
|
|
37
|
+
* nothing recognisable, stays `undefined` — the document is silent, which is a
|
|
38
|
+
* different fact from "text only".
|
|
39
|
+
*/
|
|
40
|
+
function readInputModalities(metadata) {
|
|
41
|
+
const declared = record(metadata['modalities'])['input'];
|
|
42
|
+
if (!Array.isArray(declared))
|
|
43
|
+
return undefined;
|
|
44
|
+
const kept = INPUT_MODALITIES.filter(modality => declared.includes(modality));
|
|
45
|
+
return kept.length === 0 ? undefined : kept;
|
|
33
46
|
}
|
|
34
47
|
/** A calendar date models.dev states without a timezone. */
|
|
35
48
|
function validReleaseDate(value) {
|
|
@@ -225,11 +238,9 @@ export function readOnlineMetadata(body, sources) {
|
|
|
225
238
|
assumedLimits: onlineContext === undefined && builtinContext === undefined
|
|
226
239
|
|| onlineOutput === undefined && builtinOutput === undefined,
|
|
227
240
|
input,
|
|
241
|
+
inputModalities: readInputModalities(metadata),
|
|
228
242
|
reasoning,
|
|
229
243
|
thinkingLevelMap: reasoning ? thinkingLevels(metadata, exact?.api === api ? exact : sibling) : undefined,
|
|
230
|
-
structuredOutput: declaredBoolean(metadata['structured_output']),
|
|
231
|
-
temperature: declaredBoolean(metadata['temperature']),
|
|
232
|
-
openWeights: declaredBoolean(metadata['open_weights']),
|
|
233
244
|
compat: compatFor(api, metadata, exact, sibling),
|
|
234
245
|
cost,
|
|
235
246
|
deprecated: metadata['status'] === 'deprecated',
|
|
@@ -43,9 +43,7 @@ export function catalogReading(snapshot, visibility, listingFailure) {
|
|
|
43
43
|
},
|
|
44
44
|
protocolSource: fact.protocolSource,
|
|
45
45
|
assumedLimits: fact.assumedLimits,
|
|
46
|
-
...fact.
|
|
47
|
-
...fact.temperature === undefined ? {} : { temperature: fact.temperature },
|
|
48
|
-
...fact.openWeights === undefined ? {} : { openWeights: fact.openWeights },
|
|
46
|
+
...fact.inputModalities === undefined ? {} : { inputModalities: fact.inputModalities },
|
|
49
47
|
};
|
|
50
48
|
}),
|
|
51
49
|
...[...snapshot.unavailable].map(([id, reason]) => ({ id, name: id, configurationMissing: reason })),
|
package/lib/types/models.d.ts
CHANGED
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
* @module @dan-ai-studio/dshopencodego/models
|
|
10
10
|
*/
|
|
11
11
|
import type { ProtocolSource } from './catalog/protocol.ts';
|
|
12
|
+
import type { InputModality } from './catalog/metadata.ts';
|
|
12
13
|
import type { GoQuota } from './go-limits.ts';
|
|
13
14
|
/** One model as the settings page and the picker describe it. */
|
|
14
15
|
export interface ModelSummary {
|
|
@@ -37,13 +38,10 @@ export interface ModelSummary {
|
|
|
37
38
|
/** Which ladder level decided this model's protocol. */
|
|
38
39
|
readonly protocolSource?: ProtocolSource;
|
|
39
40
|
/**
|
|
40
|
-
*
|
|
41
|
-
* document
|
|
42
|
-
* so the page leaves the cell empty instead of showing a negative.
|
|
41
|
+
* Every input modality models.dev declares, in display order. Absent when the
|
|
42
|
+
* document declares none this build can name.
|
|
43
43
|
*/
|
|
44
|
-
readonly
|
|
45
|
-
readonly temperature?: boolean;
|
|
46
|
-
readonly openWeights?: boolean;
|
|
44
|
+
readonly inputModalities?: readonly InputModality[];
|
|
47
45
|
/** True when a capacity came from the route default rather than a source. */
|
|
48
46
|
readonly assumedLimits?: boolean;
|
|
49
47
|
/** Advertised by the gateway but not configurable, with the reason. */
|
package/package.json
CHANGED