dsh-opendesign-corouter 0.1.7 → 0.1.8
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.md +5 -3
- package/lib/catalog.d.ts +4 -3
- package/lib/client.js +26 -7
- package/lib/device-auth.d.ts +1 -1
- package/lib/index.js +97 -63
- package/lib/index.js.map +3 -3
- package/lib/reasoning.d.ts +6 -0
- package/lib/schema-serialization.d.ts +4 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -32,7 +32,7 @@ dsh plugin --profile web add dsh-opendesign-corouter
|
|
|
32
32
|
也可打开 [Actions → CI](https://github.com/KouzakiUmi/dsh-opendesign-corouter/actions/workflows/ci.yml),从成功构建下载 **`dsh-opendesign-corouter-build`** artifact。登录 GitHub 后解压 ZIP,取得 `.tgz` 与 `.sha256`,再安装本地包:
|
|
33
33
|
|
|
34
34
|
```console
|
|
35
|
-
dsh plugin --profile web add /absolute/path/to/dsh-opendesign-corouter-0.1.
|
|
35
|
+
dsh plugin --profile web add /absolute/path/to/dsh-opendesign-corouter-0.1.8.tgz
|
|
36
36
|
```
|
|
37
37
|
|
|
38
38
|
`web` 只是示例,请替换为目标 Profile。Desktop 使用桌面安装器提供的 `dsh` 入口;独立公共 CLI 不能代管保留的 `desktop` Profile。安装后的启用与重载按目标 DSH 的管理流程进行。
|
|
@@ -59,6 +59,8 @@ dsh plugin --profile web add /absolute/path/to/dsh-opendesign-corouter-0.1.7.tgz
|
|
|
59
59
|
|
|
60
60
|
推理协议可选 **OpenAI Chat Completions、OpenAI Responses、Anthropic Messages**。模型发现始终使用当前网关的 OpenAI 兼容 `/models` 接口,不随推理协议切换。
|
|
61
61
|
|
|
62
|
+
思考档位按精确型号的厂商文档维护,并按当前协议筛选。33 款提供离散档位,4 款为固定思考或开关/预算控制,Muse Wonder 的精确别名尚待确认。旧配置中的无效默认档位可在参数设置中改为“继承默认”。[逐模型来源与网关验证状态](docs/reasoning-evidence.md)
|
|
63
|
+
|
|
62
64
|
> **分组不等于计费隔离。** 赠送额度耗尽后是否转扣套餐余额或钱包,由服务端和账号权益决定。选择“套餐赠送”不能保证绝不消耗钱包余额。
|
|
63
65
|
|
|
64
66
|
### 四层额度,不重复相加
|
|
@@ -79,11 +81,11 @@ dsh plugin --profile web add /absolute/path/to/dsh-opendesign-corouter-0.1.7.tgz
|
|
|
79
81
|
<img src="docs/previews/theme-light.png" width="1040" alt="连接与登录页,展示桌面优先开关、独立登录按钮和不回填的 API Key 输入框;模拟数据">
|
|
80
82
|
</picture>
|
|
81
83
|
|
|
82
|
-
###
|
|
84
|
+
### DeepSeek V4.1 Flash 空回答检测
|
|
83
85
|
|
|
84
86
|
独立开关,默认开启。参考 [dsh-empty-turn-guard](https://github.com/FYTXY/dsh-empty-turn-guard),将“正常 stop、没有工具调用、答案为空或只剩协议残渣”的工具对话标成 `EMPTY_RESPONSE`。
|
|
85
87
|
|
|
86
|
-
检测到空回答后,由 DSH
|
|
88
|
+
检测到空回答后,由 DSH 的重试策略决定是否重试,**重复请求可能额外消耗额度**。该附加监控仅用于 DeepSeek V4.1 Flash 的工具对话,识别 DSML、thinking 及 `<rea:tool_calls>` 残留。
|
|
87
89
|
|
|
88
90
|
## 使用前先知道
|
|
89
91
|
|
package/lib/catalog.d.ts
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* 详情页内联 `data-model="{...}"` JSON(公开页面,2026-10-26)。
|
|
7
7
|
* - group:官网首页套餐卡 `https://corouter.open-design.ai/zh/` 的
|
|
8
8
|
* `data-model-module="design-plan"` 12 款归 `plan`;其余在售对话模型归 `paid`。
|
|
9
|
-
* - `plan` 12 款的 contextWindow / maxOutputTokens / inputModalities
|
|
9
|
+
* - `plan` 原有 12 款的 contextWindow / maxOutputTokens / inputModalities
|
|
10
10
|
* 来自 Go 侧 `dsh-opendesign-go` 0.1.9 的 MODEL_DEFAULTS(同一 `amr-link` endpoint 部署资料),
|
|
11
11
|
* 作为部署参考,尚无官网能力数值的独立佐证;只用于对应的原有 12 款模型。
|
|
12
12
|
* - 客户端桌面安装(Open Design 0.26.1)不内联 CoRouter 目录;其
|
|
@@ -26,8 +26,8 @@
|
|
|
26
26
|
* - 媒体模型 `GPT Image 2`、`Nano Banana 2`、`Seedream 5 Lite / Pro`:
|
|
27
27
|
* 走 `/api/v1/media/*`,不应出现在对话模型列表里,避免选中后 chat 请求必败。
|
|
28
28
|
*
|
|
29
|
-
*
|
|
30
|
-
*
|
|
29
|
+
* 思考档位按厂商型号资料记录,来源见 docs/reasoning-evidence.md;网关逐路由行为未实测。
|
|
30
|
+
* 其余容量与模态字段仍按已有来源保留,未知值保持缺省。
|
|
31
31
|
*/
|
|
32
32
|
export interface CatalogModel {
|
|
33
33
|
id: string;
|
|
@@ -36,6 +36,7 @@ export interface CatalogModel {
|
|
|
36
36
|
contextWindow?: number;
|
|
37
37
|
maxOutputTokens?: number;
|
|
38
38
|
inputModalities?: readonly ('text' | 'image')[];
|
|
39
|
+
/** Undefined means unconfirmed; an empty array means no discrete effort selector. */
|
|
39
40
|
reasoningEfforts?: readonly string[];
|
|
40
41
|
}
|
|
41
42
|
/**
|
package/lib/client.js
CHANGED
|
@@ -20234,6 +20234,19 @@ var TYPERT_REMOTE = createTypertRemoteInfo({ package: "dsh-opendesign-corouter",
|
|
|
20234
20234
|
} }, external_exports);
|
|
20235
20235
|
var typert_remote_client_default = TYPERT_REMOTE;
|
|
20236
20236
|
|
|
20237
|
+
// src/reasoning.ts
|
|
20238
|
+
var PROTOCOL_EFFORTS = {
|
|
20239
|
+
"chat-completions": ["none", "minimal", "low", "medium", "high", "xhigh", "ultra", "max"],
|
|
20240
|
+
responses: ["none", "minimal", "low", "medium", "high", "xhigh", "max"],
|
|
20241
|
+
messages: ["none", "low", "medium", "high", "xhigh", "max"]
|
|
20242
|
+
};
|
|
20243
|
+
function protocolAcceptsEffort(protocol, effort) {
|
|
20244
|
+
return PROTOCOL_EFFORTS[protocol].includes(effort);
|
|
20245
|
+
}
|
|
20246
|
+
function modelReasoningEfforts(model, protocol) {
|
|
20247
|
+
return model.reasoningEfforts?.filter((effort) => protocolAcceptsEffort(protocol, effort));
|
|
20248
|
+
}
|
|
20249
|
+
|
|
20237
20250
|
// src/client.ts
|
|
20238
20251
|
var h = React.createElement;
|
|
20239
20252
|
var SETTINGS_NS = "llm-opendesign-corouter";
|
|
@@ -20705,8 +20718,9 @@ function EffortField({ id, model, value, disabled, onChange }) {
|
|
|
20705
20718
|
const mounted = useMounted();
|
|
20706
20719
|
const [error62, setError] = React.useState(void 0);
|
|
20707
20720
|
const listed = model.reasoningEfforts ?? [];
|
|
20708
|
-
const
|
|
20709
|
-
const
|
|
20721
|
+
const invalidDefault = value !== void 0 && !listed.includes(value);
|
|
20722
|
+
const options = invalidDefault ? [...listed, value] : listed;
|
|
20723
|
+
const unavailable = listed.length === 0;
|
|
20710
20724
|
return h(
|
|
20711
20725
|
"div",
|
|
20712
20726
|
{ className: "odc-field odc-field-compact" },
|
|
@@ -20715,8 +20729,9 @@ function EffortField({ id, model, value, disabled, onChange }) {
|
|
|
20715
20729
|
id,
|
|
20716
20730
|
className: "odc-input",
|
|
20717
20731
|
value: value ?? "",
|
|
20718
|
-
disabled: disabled ||
|
|
20732
|
+
disabled: disabled || unavailable && !invalidDefault,
|
|
20719
20733
|
"aria-describedby": `${id}-hint`,
|
|
20734
|
+
"aria-invalid": invalidDefault || error62 !== void 0,
|
|
20720
20735
|
onChange: (event) => {
|
|
20721
20736
|
const next = event.target.value;
|
|
20722
20737
|
void (async () => {
|
|
@@ -20726,13 +20741,13 @@ function EffortField({ id, model, value, disabled, onChange }) {
|
|
|
20726
20741
|
}
|
|
20727
20742
|
}, [
|
|
20728
20743
|
h("option", { key: "", value: "" }, "\u7EE7\u627F\u9ED8\u8BA4"),
|
|
20729
|
-
...options.map((effort) => h("option", { key: effort, value: effort }, effort))
|
|
20744
|
+
...options.map((effort) => h("option", { key: effort, value: effort, disabled: invalidDefault && effort === value }, invalidDefault && effort === value ? `${effort}\uFF08\u5F53\u524D\u4E0D\u53EF\u7528\uFF09` : effort))
|
|
20730
20745
|
]),
|
|
20731
20746
|
h("small", {
|
|
20732
20747
|
className: error62 === void 0 ? "odc-hint" : "odc-hint odc-field-error",
|
|
20733
20748
|
id: `${id}-hint`,
|
|
20734
20749
|
...error62 === void 0 ? {} : { role: "alert" }
|
|
20735
|
-
}, error62 ?? (
|
|
20750
|
+
}, error62 ?? (invalidDefault ? "\u5DF2\u4FDD\u5B58\u7684\u6863\u4F4D\u4E0D\u9002\u7528\u4E8E\u5F53\u524D\u6A21\u578B\u6216\u534F\u8BAE\uFF0C\u8BF7\u9009\u62E9\u5176\u4ED6\u6863\u4F4D\u6216\u7EE7\u627F\u9ED8\u8BA4\u3002" : unavailable ? "\u5F53\u524D\u6A21\u578B\u6216\u534F\u8BAE\u672A\u63D0\u4F9B\u53EF\u8C03\u6574\u7684\u601D\u8003\u6863\u4F4D\u3002" : "\u7559\u7A7A\u4F7F\u7528\u670D\u52A1\u7AEF\u9ED8\u8BA4\u6863\u4F4D\u3002"))
|
|
20736
20751
|
);
|
|
20737
20752
|
}
|
|
20738
20753
|
function ModelRow({ model, settings, authoritative, writable, pending, onCommit }) {
|
|
@@ -20902,7 +20917,11 @@ function Models({ status, formSnapshot, setFormField, pendingField, onRefreshMod
|
|
|
20902
20917
|
};
|
|
20903
20918
|
const source = status?.modelsSource === "openai" ? "\u5F53\u524D\u7F51\u5173" : status?.modelsSource === "builtin" ? "\u5185\u7F6E\u76EE\u5F55" : "\u5C1A\u672A\u786E\u8BA4";
|
|
20904
20919
|
const updated = status?.modelsUpdatedAt === void 0 ? "" : ` \xB7 \u66F4\u65B0\u4E8E ${formatTime(status.modelsUpdatedAt)}`;
|
|
20905
|
-
const
|
|
20920
|
+
const protocol = formSnapshot.value?.apiProtocol ?? status?.config.apiProtocol ?? "chat-completions";
|
|
20921
|
+
const models = (status?.models ?? []).map((model) => {
|
|
20922
|
+
const reasoningEfforts = modelReasoningEfforts(model, protocol);
|
|
20923
|
+
return { ...model, ...reasoningEfforts === void 0 ? {} : { reasoningEfforts } };
|
|
20924
|
+
});
|
|
20906
20925
|
return h(
|
|
20907
20926
|
React.Fragment,
|
|
20908
20927
|
null,
|
|
@@ -21027,7 +21046,7 @@ function Advanced({ status, formSnapshot, setFormField, pendingField }) {
|
|
|
21027
21046
|
"section",
|
|
21028
21047
|
{ className: "odc-card" },
|
|
21029
21048
|
h("h3", null, "\u7A7A\u8F6E\u76D1\u63A7"),
|
|
21030
|
-
h("p", { className: "odc-hint" }, "\u68C0\u6D4B\
|
|
21049
|
+
h("p", { className: "odc-hint" }, "\u68C0\u6D4B DeepSeek V4.1 Flash \u5DE5\u5177\u5BF9\u8BDD\u4E2D\u7684\u7A7A\u56DE\u7B54\u6216\u534F\u8BAE\u6807\u8BB0\u6B8B\u7559\u3002"),
|
|
21031
21050
|
h("div", { style: { marginTop: 14 } }, h(Switch, {
|
|
21032
21051
|
checked: formSnapshot.value?.emptyTurnGuard ?? status?.config.emptyTurnGuard ?? true,
|
|
21033
21052
|
disabled: !writable || pendingField.includes("emptyTurnGuard"),
|
package/lib/device-auth.d.ts
CHANGED
|
@@ -3,7 +3,7 @@ export interface DeviceTokens {
|
|
|
3
3
|
runtimeKey: string;
|
|
4
4
|
}
|
|
5
5
|
export declare const DEVICE_AUTH_ENDPOINT = "https://amr-api.open-design.ai/api/v1/cli/device-authorizations";
|
|
6
|
-
export declare const DEVICE_AUTH_PLUGIN_VERSION = "0.1.
|
|
6
|
+
export declare const DEVICE_AUTH_PLUGIN_VERSION = "0.1.8";
|
|
7
7
|
export declare const DEVICE_REQUEST_TIMEOUT_MS = 20000;
|
|
8
8
|
/** One bounded launch step of the temporary activation window. */
|
|
9
9
|
export declare const DEVICE_OPEN_TIMEOUT_MS = 30000;
|
package/lib/index.js
CHANGED
|
@@ -65,13 +65,17 @@ import {
|
|
|
65
65
|
// src/catalog.ts
|
|
66
66
|
var TEXT_ONLY = ["text"];
|
|
67
67
|
var TEXT_AND_IMAGE = ["text", "image"];
|
|
68
|
-
var
|
|
69
|
-
var
|
|
68
|
+
var EFFORTS_REASONING = ["low", "medium", "high", "xhigh", "max"];
|
|
69
|
+
var EFFORTS_OPENAI = ["none", ...EFFORTS_REASONING];
|
|
70
|
+
var EFFORTS_GLM52 = ["none", "minimal", "low", "medium", "high", "xhigh", "max"];
|
|
70
71
|
var EFFORTS_LOW_HIGH = ["low", "high", "max"];
|
|
72
|
+
var EFFORTS_LEVELS = ["low", "medium", "high"];
|
|
73
|
+
var EFFORTS_GROK = [...EFFORTS_LEVELS, "xhigh"];
|
|
74
|
+
var EFFORTS_MUSE = ["minimal", ...EFFORTS_REASONING];
|
|
71
75
|
var MODELS = [
|
|
72
76
|
// ── OpenAI(7) ─────────────────────────────────────────────
|
|
73
|
-
{ id: "gpt-6.1-sol", name: "GPT-6.1 Sol", group: "paid" },
|
|
74
|
-
{ id: "gpt-6-astra", name: "GPT-6 Astra", group: "paid" },
|
|
77
|
+
{ id: "gpt-6.1-sol", name: "GPT-6.1 Sol", group: "paid", reasoningEfforts: EFFORTS_REASONING },
|
|
78
|
+
{ id: "gpt-6-astra", name: "GPT-6 Astra", group: "paid", reasoningEfforts: EFFORTS_REASONING },
|
|
75
79
|
{
|
|
76
80
|
id: "gpt-6-luna",
|
|
77
81
|
name: "GPT-6 Luna",
|
|
@@ -79,20 +83,20 @@ var MODELS = [
|
|
|
79
83
|
contextWindow: 105e4,
|
|
80
84
|
maxOutputTokens: 128e3,
|
|
81
85
|
inputModalities: TEXT_AND_IMAGE,
|
|
82
|
-
reasoningEfforts:
|
|
86
|
+
reasoningEfforts: EFFORTS_OPENAI
|
|
83
87
|
},
|
|
84
|
-
{ id: "gpt-6-sol", name: "GPT-6 Sol", group: "paid" },
|
|
85
|
-
{ id: "gpt-5.6-luna", name: "GPT-5.6 Luna", group: "paid" },
|
|
86
|
-
{ id: "gpt-5.6-sol", name: "GPT-5.6 Sol", group: "paid" },
|
|
87
|
-
{ id: "gpt-5.6-terra", name: "GPT-5.6 Terra", group: "paid" },
|
|
88
|
+
{ id: "gpt-6-sol", name: "GPT-6 Sol", group: "paid", reasoningEfforts: EFFORTS_OPENAI },
|
|
89
|
+
{ id: "gpt-5.6-luna", name: "GPT-5.6 Luna", group: "paid", reasoningEfforts: EFFORTS_OPENAI },
|
|
90
|
+
{ id: "gpt-5.6-sol", name: "GPT-5.6 Sol", group: "paid", reasoningEfforts: EFFORTS_OPENAI },
|
|
91
|
+
{ id: "gpt-5.6-terra", name: "GPT-5.6 Terra", group: "paid", reasoningEfforts: EFFORTS_OPENAI },
|
|
88
92
|
// ── Anthropic(8) ──────────────────────────────────────────
|
|
89
|
-
{ id: "claude-fable-5.1", name: "Claude Fable 5.1", group: "paid" },
|
|
90
|
-
{ id: "claude-fable-5", name: "Claude Fable 5", group: "paid" },
|
|
91
|
-
{ id: "claude-opus-5.5", name: "Claude Opus 5.5", group: "paid" },
|
|
92
|
-
{ id: "claude-opus-5", name: "Claude Opus 5", group: "paid" },
|
|
93
|
-
{ id: "claude-opus-4.8", name: "Claude Opus 4.8", group: "paid" },
|
|
94
|
-
{ id: "claude-sonnet-5.5", name: "Claude Sonnet 5.5", group: "paid" },
|
|
95
|
-
{ id: "claude-sonnet-5", name: "Claude Sonnet 5", group: "paid" },
|
|
93
|
+
{ id: "claude-fable-5.1", name: "Claude Fable 5.1", group: "paid", reasoningEfforts: EFFORTS_REASONING },
|
|
94
|
+
{ id: "claude-fable-5", name: "Claude Fable 5", group: "paid", reasoningEfforts: EFFORTS_REASONING },
|
|
95
|
+
{ id: "claude-opus-5.5", name: "Claude Opus 5.5", group: "paid", reasoningEfforts: EFFORTS_REASONING },
|
|
96
|
+
{ id: "claude-opus-5", name: "Claude Opus 5", group: "paid", reasoningEfforts: EFFORTS_REASONING },
|
|
97
|
+
{ id: "claude-opus-4.8", name: "Claude Opus 4.8", group: "paid", reasoningEfforts: EFFORTS_REASONING },
|
|
98
|
+
{ id: "claude-sonnet-5.5", name: "Claude Sonnet 5.5", group: "paid", reasoningEfforts: EFFORTS_REASONING },
|
|
99
|
+
{ id: "claude-sonnet-5", name: "Claude Sonnet 5", group: "paid", reasoningEfforts: EFFORTS_REASONING },
|
|
96
100
|
{
|
|
97
101
|
id: "claude-haiku-5.5",
|
|
98
102
|
name: "Claude Haiku 5.5",
|
|
@@ -100,7 +104,7 @@ var MODELS = [
|
|
|
100
104
|
contextWindow: 1e6,
|
|
101
105
|
maxOutputTokens: 128e3,
|
|
102
106
|
inputModalities: TEXT_AND_IMAGE,
|
|
103
|
-
reasoningEfforts:
|
|
107
|
+
reasoningEfforts: EFFORTS_REASONING
|
|
104
108
|
},
|
|
105
109
|
// ── DeepSeek(4) ───────────────────────────────────────────
|
|
106
110
|
{
|
|
@@ -110,7 +114,7 @@ var MODELS = [
|
|
|
110
114
|
contextWindow: 1e6,
|
|
111
115
|
maxOutputTokens: 384e3,
|
|
112
116
|
inputModalities: TEXT_AND_IMAGE,
|
|
113
|
-
reasoningEfforts:
|
|
117
|
+
reasoningEfforts: EFFORTS_LOW_HIGH
|
|
114
118
|
},
|
|
115
119
|
{
|
|
116
120
|
id: "deepseek-v4-pro",
|
|
@@ -119,7 +123,7 @@ var MODELS = [
|
|
|
119
123
|
contextWindow: 1e6,
|
|
120
124
|
maxOutputTokens: 384e3,
|
|
121
125
|
inputModalities: TEXT_ONLY,
|
|
122
|
-
reasoningEfforts:
|
|
126
|
+
reasoningEfforts: EFFORTS_LOW_HIGH
|
|
123
127
|
},
|
|
124
128
|
{
|
|
125
129
|
id: "deepseek-v4-flash",
|
|
@@ -128,7 +132,7 @@ var MODELS = [
|
|
|
128
132
|
contextWindow: 1e6,
|
|
129
133
|
maxOutputTokens: 384e3,
|
|
130
134
|
inputModalities: TEXT_AND_IMAGE,
|
|
131
|
-
reasoningEfforts:
|
|
135
|
+
reasoningEfforts: EFFORTS_LOW_HIGH
|
|
132
136
|
},
|
|
133
137
|
{
|
|
134
138
|
id: "deepseek-v4-flash-vision-exp",
|
|
@@ -137,7 +141,7 @@ var MODELS = [
|
|
|
137
141
|
contextWindow: 1e6,
|
|
138
142
|
maxOutputTokens: 384e3,
|
|
139
143
|
inputModalities: TEXT_AND_IMAGE,
|
|
140
|
-
reasoningEfforts:
|
|
144
|
+
reasoningEfforts: EFFORTS_LOW_HIGH
|
|
141
145
|
},
|
|
142
146
|
// ── Z.ai(3) ───────────────────────────────────────────────
|
|
143
147
|
{
|
|
@@ -158,7 +162,7 @@ var MODELS = [
|
|
|
158
162
|
inputModalities: TEXT_AND_IMAGE,
|
|
159
163
|
reasoningEfforts: EFFORTS_LOW_HIGH
|
|
160
164
|
},
|
|
161
|
-
{ id: "glm-5.2", name: "GLM-5.2", group: "paid" },
|
|
165
|
+
{ id: "glm-5.2", name: "GLM-5.2", group: "paid", reasoningEfforts: EFFORTS_GLM52 },
|
|
162
166
|
// ── Moonshot(3) ───────────────────────────────────────────
|
|
163
167
|
{
|
|
164
168
|
id: "kimi-k2.7-code",
|
|
@@ -167,18 +171,18 @@ var MODELS = [
|
|
|
167
171
|
contextWindow: 262144,
|
|
168
172
|
maxOutputTokens: 262144,
|
|
169
173
|
inputModalities: TEXT_AND_IMAGE,
|
|
170
|
-
reasoningEfforts:
|
|
174
|
+
reasoningEfforts: []
|
|
171
175
|
},
|
|
172
|
-
{ id: "kimi-k3", name: "Kimi K3", group: "paid" },
|
|
173
|
-
{ id: "kimi-k3.1-pro", name: "Kimi K3.1 Pro", group: "paid" },
|
|
176
|
+
{ id: "kimi-k3", name: "Kimi K3", group: "paid", reasoningEfforts: EFFORTS_LOW_HIGH },
|
|
177
|
+
{ id: "kimi-k3.1-pro", name: "Kimi K3.1 Pro", group: "paid", reasoningEfforts: EFFORTS_LOW_HIGH },
|
|
174
178
|
// ── Google(3) ─────────────────────────────────────────────
|
|
175
|
-
{ id: "gemini-4-argon", name: "Gemini 4 Argon", group: "paid" },
|
|
176
|
-
{ id: "gemini-3.8-flash", name: "Gemini 3.8 Flash", group: "paid" },
|
|
177
|
-
{ id: "gemini-3.7-flash", name: "Gemini 3.7 Flash", group: "paid" },
|
|
179
|
+
{ id: "gemini-4-argon", name: "Gemini 4 Argon", group: "paid", reasoningEfforts: EFFORTS_LEVELS },
|
|
180
|
+
{ id: "gemini-3.8-flash", name: "Gemini 3.8 Flash", group: "paid", reasoningEfforts: EFFORTS_LEVELS },
|
|
181
|
+
{ id: "gemini-3.7-flash", name: "Gemini 3.7 Flash", group: "paid", reasoningEfforts: EFFORTS_LEVELS },
|
|
178
182
|
// ── xAI(3) ────────────────────────────────────────────────
|
|
179
|
-
{ id: "grok-4.7", name: "Grok 4.7", group: "paid" },
|
|
180
|
-
{ id: "grok-4.6", name: "Grok 4.6", group: "paid" },
|
|
181
|
-
{ id: "grok-4.5", name: "Grok 4.5", group: "paid" },
|
|
183
|
+
{ id: "grok-4.7", name: "Grok 4.7", group: "paid", reasoningEfforts: EFFORTS_GROK },
|
|
184
|
+
{ id: "grok-4.6", name: "Grok 4.6", group: "paid", reasoningEfforts: EFFORTS_GROK },
|
|
185
|
+
{ id: "grok-4.5", name: "Grok 4.5", group: "paid", reasoningEfforts: EFFORTS_LEVELS },
|
|
182
186
|
// ── Xiaomi(2) ─────────────────────────────────────────────
|
|
183
187
|
{
|
|
184
188
|
id: "mimo-v2.6-pro",
|
|
@@ -187,7 +191,7 @@ var MODELS = [
|
|
|
187
191
|
contextWindow: 1e6,
|
|
188
192
|
maxOutputTokens: 128e3,
|
|
189
193
|
inputModalities: TEXT_AND_IMAGE,
|
|
190
|
-
reasoningEfforts:
|
|
194
|
+
reasoningEfforts: []
|
|
191
195
|
},
|
|
192
196
|
{
|
|
193
197
|
id: "mimo-v2.6-flash",
|
|
@@ -196,7 +200,7 @@ var MODELS = [
|
|
|
196
200
|
contextWindow: 1e6,
|
|
197
201
|
maxOutputTokens: 128e3,
|
|
198
202
|
inputModalities: TEXT_AND_IMAGE,
|
|
199
|
-
reasoningEfforts:
|
|
203
|
+
reasoningEfforts: []
|
|
200
204
|
},
|
|
201
205
|
// ── Tencent(1) ────────────────────────────────────────────
|
|
202
206
|
{
|
|
@@ -206,13 +210,13 @@ var MODELS = [
|
|
|
206
210
|
contextWindow: 1e6,
|
|
207
211
|
maxOutputTokens: 64e3,
|
|
208
212
|
inputModalities: TEXT_ONLY,
|
|
209
|
-
reasoningEfforts:
|
|
213
|
+
reasoningEfforts: ["none", "high"]
|
|
210
214
|
},
|
|
211
215
|
// ── Alibaba(1) ────────────────────────────────────────────
|
|
212
|
-
{ id: "qwen3.7-max", name: "Qwen3.7 Max", group: "paid" },
|
|
216
|
+
{ id: "qwen3.7-max", name: "Qwen3.7 Max", group: "paid", reasoningEfforts: [] },
|
|
213
217
|
// Official API additions; display labels for undocumented entries are local formatting.
|
|
214
|
-
{ id: "minimax-m3.1-flash", name: "MiniMax M3.1 Flash", group: "plan" },
|
|
215
|
-
{ id: "muse-spark-1.3", name: "Muse Spark 1.3", group: "paid" },
|
|
218
|
+
{ id: "minimax-m3.1-flash", name: "MiniMax M3.1 Flash", group: "plan", reasoningEfforts: EFFORTS_REASONING },
|
|
219
|
+
{ id: "muse-spark-1.3", name: "Muse Spark 1.3", group: "paid", reasoningEfforts: EFFORTS_MUSE },
|
|
216
220
|
{ id: "muse-wonder", name: "Muse Wonder", group: "paid" }
|
|
217
221
|
];
|
|
218
222
|
var BY_ID = new Map(MODELS.map((model) => [model.id, model]));
|
|
@@ -294,6 +298,15 @@ function isModelEnabled(id, settings = {}) {
|
|
|
294
298
|
return settings[id]?.enabled !== false;
|
|
295
299
|
}
|
|
296
300
|
|
|
301
|
+
// src/schema-serialization.ts
|
|
302
|
+
function serializableTransform(callback) {
|
|
303
|
+
return Object.assign(callback, {
|
|
304
|
+
toJSON() {
|
|
305
|
+
return `(${serializableTransform.toString()})(${callback.toString()})`;
|
|
306
|
+
}
|
|
307
|
+
});
|
|
308
|
+
}
|
|
309
|
+
|
|
297
310
|
// src/config.ts
|
|
298
311
|
var SETTINGS_NS = "llm-opendesign-corouter";
|
|
299
312
|
var PLAN_PROVIDER = "opendesign-corouter-plan";
|
|
@@ -301,11 +314,11 @@ var PAID_PROVIDER = "opendesign-corouter-paid";
|
|
|
301
314
|
var DEFAULT_BASE_URL = "https://amr-link.open-design.ai/v1";
|
|
302
315
|
var Config = Schema.object({
|
|
303
316
|
apiKeyEnv: Schema.string().max(128).pattern(/^[A-Za-z_][A-Za-z0-9_]*$/u).default("COROUTER_API_KEY").description("CoRouter API Key \u7684\u73AF\u5883\u53D8\u91CF\u6216 DSH \u51ED\u636E\u5F15\u7528\u540D").volatile(),
|
|
304
|
-
baseURL: Schema.transform(Schema.string(), assertBaseURL).default(DEFAULT_BASE_URL).description("CoRouter \u7F51\u5173\u5730\u5740\uFF1B\u4E0D\u7528\u4E8E\u63A7\u5236\u53F0\u767B\u5F55\u6216\u989D\u5EA6\u67E5\u8BE2").volatile(),
|
|
317
|
+
baseURL: Schema.transform(Schema.string(), serializableTransform(assertBaseURL)).default(DEFAULT_BASE_URL).description("CoRouter \u7F51\u5173\u5730\u5740\uFF1B\u4E0D\u7528\u4E8E\u63A7\u5236\u53F0\u767B\u5F55\u6216\u989D\u5EA6\u67E5\u8BE2").volatile(),
|
|
305
318
|
apiProtocol: Schema.union(API_PROTOCOL_IDS).default("chat-completions").description("\u7F51\u5173\u652F\u6301\u7684\u63A8\u7406\u534F\u8BAE\uFF1B\u6A21\u578B\u76EE\u5F55\u901A\u8FC7\u8BE5\u7F51\u5173\u7684\u517C\u5BB9\u63A5\u53E3\u8BFB\u53D6").volatile(),
|
|
306
|
-
modelSettings: Schema.transform(Schema.dict(Schema.any()), parseModelSettingsMap).default({}).description("\u9010\u6A21\u578B\u542F\u7528\u72B6\u6001\u548C\u8BF7\u6C42\u53C2\u6570").volatile(),
|
|
319
|
+
modelSettings: Schema.transform(Schema.dict(Schema.any()), serializableTransform(parseModelSettingsMap)).default({}).description("\u9010\u6A21\u578B\u542F\u7528\u72B6\u6001\u548C\u8BF7\u6C42\u53C2\u6570").volatile(),
|
|
307
320
|
useDesktopCredential: Schema.boolean().default(true).description("\u4F18\u5148\u8BFB\u53D6 OpenDesign \u684C\u9762\u7AEF\u767B\u5F55\u6001\u67E5\u8BE2\u989D\u5EA6").volatile(),
|
|
308
|
-
emptyTurnGuard: Schema.boolean().default(true).description("\
|
|
321
|
+
emptyTurnGuard: Schema.boolean().default(true).description("\u68C0\u6D4B DeepSeek V4.1 Flash \u5DE5\u5177\u5BF9\u8BDD\u7684\u7A7A\u56DE\u7B54\uFF1B\u7531\u5BBF\u4E3B\u91CD\u8BD5\u7B56\u7565\u5904\u7406\uFF0C\u53EF\u80FD\u989D\u5916\u6D88\u8017\u989D\u5EA6").volatile(),
|
|
309
322
|
quotaRefreshSeconds: Schema.natural().min(5).max(3600).default(60).description("\u989D\u5EA6\u81EA\u52A8\u5237\u65B0\u95F4\u9694\uFF08\u79D2\uFF09").volatile(),
|
|
310
323
|
requestTimeoutMs: Schema.natural().min(1e3).max(36e5).default(18e5).description("\u63A8\u7406\u8BF7\u6C42\u603B\u8D85\u65F6\uFF08\u6BEB\u79D2\uFF09").volatile(),
|
|
311
324
|
streamIdleTimeoutMs: Schema.natural().min(1e3).max(18e5).default(3e5).description("\u6D41\u5F0F\u54CD\u5E94\u65E0\u6570\u636E\u8D85\u65F6\uFF08\u6BEB\u79D2\uFF09").volatile()
|
|
@@ -809,6 +822,7 @@ var RESIDUE_PATTERNS = [
|
|
|
809
822
|
/<\s*\/?\s*||DSML||[^>]*>/gu,
|
|
810
823
|
/||DSML||[^\n<>]*>?/gu,
|
|
811
824
|
/<\s*\/?\s*thinking\s*>/giu,
|
|
825
|
+
/<\s*\/?\s*rea:tool_calls\s*>/giu,
|
|
812
826
|
/<\s*\/?\s*返璞归真\s*>/gu
|
|
813
827
|
];
|
|
814
828
|
var ONLY_MARKUP_PUNCTUATION = /^[\s<>/\\||=_-]*$/u;
|
|
@@ -943,6 +957,19 @@ function streamHeaders(apiKey, extra = {}) {
|
|
|
943
957
|
};
|
|
944
958
|
}
|
|
945
959
|
|
|
960
|
+
// src/reasoning.ts
|
|
961
|
+
var PROTOCOL_EFFORTS = {
|
|
962
|
+
"chat-completions": ["none", "minimal", "low", "medium", "high", "xhigh", "ultra", "max"],
|
|
963
|
+
responses: ["none", "minimal", "low", "medium", "high", "xhigh", "max"],
|
|
964
|
+
messages: ["none", "low", "medium", "high", "xhigh", "max"]
|
|
965
|
+
};
|
|
966
|
+
function protocolAcceptsEffort(protocol, effort) {
|
|
967
|
+
return PROTOCOL_EFFORTS[protocol].includes(effort);
|
|
968
|
+
}
|
|
969
|
+
function modelReasoningEfforts(model, protocol) {
|
|
970
|
+
return model.reasoningEfforts?.filter((effort) => protocolAcceptsEffort(protocol, effort));
|
|
971
|
+
}
|
|
972
|
+
|
|
946
973
|
// src/protocols/chat-completions.ts
|
|
947
974
|
function buildChatCompletionsRequest(ctx) {
|
|
948
975
|
const { options, model } = ctx;
|
|
@@ -957,7 +984,10 @@ function buildChatCompletionsRequest(ctx) {
|
|
|
957
984
|
if (!Number.isSafeInteger(options.maxTokens) || options.maxTokens <= 0) throw new LlmError5("maxTokens \u5FC5\u987B\u662F\u6B63\u6574\u6570", "INVALID_REQUEST");
|
|
958
985
|
body.max_tokens = options.maxTokens;
|
|
959
986
|
}
|
|
960
|
-
if (options.reasoningEffort !== void 0)
|
|
987
|
+
if (options.reasoningEffort !== void 0) {
|
|
988
|
+
if (!protocolAcceptsEffort("chat-completions", options.reasoningEffort)) throw new LlmError5("Chat Completions \u534F\u8BAE\u4E0D\u63A5\u53D7\u8BE5\u601D\u8003\u6DF1\u5EA6", "UNSUPPORTED_OPTION");
|
|
989
|
+
body.reasoning_effort = options.reasoningEffort;
|
|
990
|
+
}
|
|
961
991
|
if (options.stop?.length) body.stop = options.stop;
|
|
962
992
|
return { url: inferenceEndpoint(ctx.baseURL, "chat-completions"), headers: streamHeaders(ctx.apiKey), body };
|
|
963
993
|
}
|
|
@@ -1041,7 +1071,6 @@ function anthropicUsage(raw) {
|
|
|
1041
1071
|
// src/protocols/messages.ts
|
|
1042
1072
|
var MESSAGES_DEFAULT_MAX_TOKENS = 4096;
|
|
1043
1073
|
var ANTHROPIC_VERSION = "2023-06-01";
|
|
1044
|
-
var THINKING_EFFORTS = ["low", "medium", "high", "xhigh", "max"];
|
|
1045
1074
|
var DATA_URL = /^data:([^;,]+);base64,(.*)$/su;
|
|
1046
1075
|
function messagesURL(baseURL) {
|
|
1047
1076
|
return inferenceEndpoint(baseURL, "messages");
|
|
@@ -1133,7 +1162,7 @@ function buildMessagesRequest(ctx) {
|
|
|
1133
1162
|
if (options.reasoningEffort !== void 0) {
|
|
1134
1163
|
const effort = String(options.reasoningEffort);
|
|
1135
1164
|
if (effort === "none") body.thinking = { type: "disabled" };
|
|
1136
|
-
else if (
|
|
1165
|
+
else if (protocolAcceptsEffort("messages", effort)) {
|
|
1137
1166
|
body.thinking = { type: "adaptive" };
|
|
1138
1167
|
body.output_config = { effort };
|
|
1139
1168
|
} else throw new LlmError7(`Anthropic Messages \u534F\u8BAE\u4E0D\u63A5\u53D7\u601D\u8003\u6DF1\u5EA6\u300C${effort}\u300D`, "UNSUPPORTED_OPTION");
|
|
@@ -1331,7 +1360,6 @@ import {
|
|
|
1331
1360
|
LlmError as LlmError8,
|
|
1332
1361
|
ToolCallId as ToolCallId3
|
|
1333
1362
|
} from "@deepseek-ai/dsh-llm";
|
|
1334
|
-
var REASONING_EFFORTS = ["none", "minimal", "low", "medium", "high", "xhigh", "max"];
|
|
1335
1363
|
function userContent(text2, images) {
|
|
1336
1364
|
if (!images.length) return text2;
|
|
1337
1365
|
return [
|
|
@@ -1392,7 +1420,7 @@ function buildResponsesRequest(ctx) {
|
|
|
1392
1420
|
}
|
|
1393
1421
|
if (options.reasoningEffort !== void 0) {
|
|
1394
1422
|
const effort = String(options.reasoningEffort);
|
|
1395
|
-
if (!
|
|
1423
|
+
if (!protocolAcceptsEffort("responses", effort)) throw new LlmError8(`Responses \u534F\u8BAE\u4E0D\u63A5\u53D7\u601D\u8003\u6DF1\u5EA6\u300C${effort}\u300D`, "UNSUPPORTED_OPTION");
|
|
1396
1424
|
body.reasoning = { effort, summary: "auto" };
|
|
1397
1425
|
}
|
|
1398
1426
|
if (options.stop?.length) throw new LlmError8("Responses \u534F\u8BAE\u4E0D\u652F\u6301 stop \u5E8F\u5217", "UNSUPPORTED_OPTION");
|
|
@@ -1701,7 +1729,8 @@ function outputReserve(model, protocol) {
|
|
|
1701
1729
|
function metadata(provider, row, config) {
|
|
1702
1730
|
const setting = config.modelSettings?.[row.id];
|
|
1703
1731
|
const reserve = setting?.maxTokens ?? outputReserve(row, config.apiProtocol ?? "chat-completions");
|
|
1704
|
-
const efforts = row.
|
|
1732
|
+
const efforts = modelReasoningEfforts(row, config.apiProtocol ?? "chat-completions");
|
|
1733
|
+
const defaultEffort = setting?.reasoningEffort !== void 0 && efforts?.includes(setting.reasoningEffort) ? setting.reasoningEffort : void 0;
|
|
1705
1734
|
return {
|
|
1706
1735
|
provider,
|
|
1707
1736
|
id: row.id,
|
|
@@ -1711,7 +1740,7 @@ function metadata(provider, row, config) {
|
|
|
1711
1740
|
...reserve === void 0 ? {} : { defaultMaxTokens: reserve },
|
|
1712
1741
|
...efforts?.length ? { reasoning: {
|
|
1713
1742
|
efforts: efforts.map((id) => ({ id: ReasoningEffortId(id), name: { none: "\u5173\u95ED", minimal: "\u6700\u4F4E", low: "\u4F4E", medium: "\u4E2D", high: "\u9AD8", xhigh: "\u8F83\u9AD8", ultra: "\u6781\u9AD8", max: "\u6700\u9AD8" }[id] ?? id })),
|
|
1714
|
-
...
|
|
1743
|
+
...defaultEffort === void 0 ? {} : { defaultEffort: ReasoningEffortId(defaultEffort) }
|
|
1715
1744
|
} } : {}
|
|
1716
1745
|
};
|
|
1717
1746
|
}
|
|
@@ -1758,11 +1787,13 @@ var CoRouterAdapter = class extends LlmAdapter {
|
|
|
1758
1787
|
async *#stream(options, config, row) {
|
|
1759
1788
|
const signal = AbortSignal.any([combinedSignal(options.signal, config.requestTimeoutMs), this.#lifetime.signal]);
|
|
1760
1789
|
signal.throwIfAborted();
|
|
1790
|
+
const setting = config.modelSettings?.[row.id] ?? {};
|
|
1791
|
+
const protocolId = config.apiProtocol ?? "chat-completions";
|
|
1792
|
+
const effort = options.reasoningEffort ?? (setting.reasoningEffort ? ReasoningEffortId(setting.reasoningEffort) : void 0);
|
|
1793
|
+
if (effort !== void 0 && !modelReasoningEfforts(row, protocolId)?.includes(effort)) throw new LlmError10("\u6240\u9009\u601D\u8003\u6DF1\u5EA6\u4E0D\u9002\u7528\u4E8E\u5F53\u524D\u6A21\u578B\u6216\u534F\u8BAE\uFF1B\u8BF7\u4FEE\u6539\u9ED8\u8BA4\u503C\u6216\u9009\u62E9\u5176\u4ED6\u6863\u4F4D", "UNSUPPORTED_OPTION");
|
|
1761
1794
|
const raw = await this.options.apiKey(config.apiKeyEnv, config.baseURL);
|
|
1762
1795
|
if (!raw) throw new LlmError10("\u672A\u914D\u7F6E\u5F53\u524D\u7F51\u5173\u7684\u63A8\u7406\u51ED\u636E\uFF1B\u8BF7\u5B8C\u6210\u8BBE\u5907\u6388\u6743\u6216\u914D\u7F6E\u5BF9\u5E94 API Key", "MISSING_CREDENTIAL");
|
|
1763
1796
|
const key = assertUsableApiKey(raw, "dsh-opendesign-corouter", config.apiKeyEnv);
|
|
1764
|
-
const setting = config.modelSettings?.[row.id] ?? {};
|
|
1765
|
-
const protocolId = config.apiProtocol ?? "chat-completions";
|
|
1766
1797
|
const images = /* @__PURE__ */ new Map();
|
|
1767
1798
|
const attemptedImages = /* @__PURE__ */ new Set();
|
|
1768
1799
|
const unreadableImages = /* @__PURE__ */ new Set();
|
|
@@ -1796,8 +1827,6 @@ var CoRouterAdapter = class extends LlmAdapter {
|
|
|
1796
1827
|
if (room < 1) throw new LlmError10("\u5F53\u524D\u8F93\u5165\u6CA1\u6709\u4E3A\u8F93\u51FA\u7559\u4E0B\u4E0A\u4E0B\u6587\u7A7A\u95F4", "CONTEXT_WINDOW_EXCEEDED");
|
|
1797
1828
|
maxTokens = Math.min(capped, Math.floor(room));
|
|
1798
1829
|
}
|
|
1799
|
-
const effort = options.reasoningEffort ?? (setting.reasoningEffort ? ReasoningEffortId(setting.reasoningEffort) : void 0);
|
|
1800
|
-
if (effort !== void 0 && row.reasoningEfforts && !row.reasoningEfforts.includes(effort)) throw new LlmError10("\u8BE5\u6A21\u578B\u4E0D\u652F\u6301\u6240\u9009\u601D\u8003\u6DF1\u5EA6", "UNSUPPORTED_OPTION");
|
|
1801
1830
|
const effective = {
|
|
1802
1831
|
...projectedOptions,
|
|
1803
1832
|
...(options.temperature ?? setting.temperature) === void 0 ? {} : { temperature: options.temperature ?? setting.temperature },
|
|
@@ -1846,11 +1875,12 @@ var CoRouterAdapter = class extends LlmAdapter {
|
|
|
1846
1875
|
throw gatewayError(response.status, error);
|
|
1847
1876
|
}
|
|
1848
1877
|
if (!response.body) throw new LlmError10("CoRouter \u8FD4\u56DE\u7A7A\u54CD\u5E94", "EMPTY_RESPONSE");
|
|
1849
|
-
const
|
|
1878
|
+
const monitor = row.group === "plan" && row.id === "deepseek-v4.1-flash" && config.emptyTurnGuard && Boolean(options.tools?.length);
|
|
1879
|
+
const tracker = new EmptyTurnTracker({ enabled: monitor, onEmptyTurn: () => this.options.onEmptyTurn?.() });
|
|
1850
1880
|
try {
|
|
1851
1881
|
for await (const chunk of protocol.stream(response.body, signal, config.streamIdleTimeoutMs)) {
|
|
1852
1882
|
tracker.observe(chunk);
|
|
1853
|
-
if (chunk.type === "finish" &&
|
|
1883
|
+
if (chunk.type === "finish" && monitor) yield { ...chunk, reason: tracker.resolve(chunk.reason) };
|
|
1854
1884
|
else yield chunk;
|
|
1855
1885
|
}
|
|
1856
1886
|
} catch (error) {
|
|
@@ -2200,7 +2230,7 @@ import { randomUUID } from "node:crypto";
|
|
|
2200
2230
|
|
|
2201
2231
|
// src/device-auth.ts
|
|
2202
2232
|
var DEVICE_AUTH_ENDPOINT = "https://amr-api.open-design.ai/api/v1/cli/device-authorizations";
|
|
2203
|
-
var DEVICE_AUTH_PLUGIN_VERSION = "0.1.
|
|
2233
|
+
var DEVICE_AUTH_PLUGIN_VERSION = "0.1.8";
|
|
2204
2234
|
var DEVICE_REQUEST_TIMEOUT_MS = 2e4;
|
|
2205
2235
|
var DEVICE_RESPONSE_MAX_BYTES = 65536;
|
|
2206
2236
|
var DEVICE_POLL_MIN_MS = 1e3;
|
|
@@ -3495,15 +3525,19 @@ var OpenDesignCoRouterService = class extends (_a = TypertRemoteService, _status
|
|
|
3495
3525
|
login: this._login.status(),
|
|
3496
3526
|
config: state.config,
|
|
3497
3527
|
guardedTurns: this.guardedTurns,
|
|
3498
|
-
models: this._models.map((
|
|
3499
|
-
id,
|
|
3500
|
-
|
|
3501
|
-
|
|
3502
|
-
|
|
3503
|
-
|
|
3504
|
-
|
|
3505
|
-
|
|
3506
|
-
|
|
3528
|
+
models: this._models.map((row) => {
|
|
3529
|
+
const { id, name: name2, group: group2, contextWindow, maxOutputTokens } = row;
|
|
3530
|
+
const reasoningEfforts = modelReasoningEfforts(row, state.config.apiProtocol ?? "chat-completions");
|
|
3531
|
+
return {
|
|
3532
|
+
id,
|
|
3533
|
+
name: name2,
|
|
3534
|
+
group: group2,
|
|
3535
|
+
enabled: isModelEnabled(id, state.config.modelSettings),
|
|
3536
|
+
...contextWindow === void 0 ? {} : { contextWindow },
|
|
3537
|
+
...maxOutputTokens === void 0 ? {} : { maxOutputTokens },
|
|
3538
|
+
...reasoningEfforts === void 0 ? {} : { reasoningEfforts }
|
|
3539
|
+
};
|
|
3540
|
+
}),
|
|
3507
3541
|
modelsSource: this._modelsUpdatedAt ? "openai" : "builtin",
|
|
3508
3542
|
...this._modelsUpdatedAt ? { modelsUpdatedAt: this._modelsUpdatedAt } : {},
|
|
3509
3543
|
...this._modelsError ? { modelsError: this._modelsError } : {}
|