dsh-model-reasoning-defaults 0.0.1
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/LICENSE +21 -0
- package/README.md +297 -0
- package/cordis.patch.yml +26 -0
- package/lib/client.js +470 -0
- package/lib/client.js.map +1 -0
- package/lib/index.d.mts +130 -0
- package/lib/index.mjs +566 -0
- package/lib/index.mjs.map +1 -0
- package/lib/types/client/index.d.ts +71 -0
- package/lib/types/client/index.d.ts.map +1 -0
- package/package.json +85 -0
package/lib/client.js
ADDED
|
@@ -0,0 +1,470 @@
|
|
|
1
|
+
window.__ModuleLoader__.load({
|
|
2
|
+
id: "dsh-model-reasoning-defaults",
|
|
3
|
+
factory: (require) => {
|
|
4
|
+
var module = { exports: {} };
|
|
5
|
+
var exports = module.exports;
|
|
6
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
7
|
+
let react = require("react");
|
|
8
|
+
let _deepseek_ai_dsh_client_ui_primitives = require("@deepseek-ai/dsh-client-ui-primitives");
|
|
9
|
+
//#region src/client/index.ts
|
|
10
|
+
/**
|
|
11
|
+
* dsh-model-reasoning-defaults 的客户端半体。
|
|
12
|
+
*
|
|
13
|
+
* - 设置页 section:编辑本插件设置命名空间中的扁平路由表,经宿主统一的
|
|
14
|
+
* settings API 写入。Host 每次请求实时读取该层,保存即生效。
|
|
15
|
+
*
|
|
16
|
+
* 控件一律使用官方 @deepseek-ai/dsh-client-ui-primitives(平台基线模块,
|
|
17
|
+
* 宿主模块表直接应答),与设置壳视觉一致。
|
|
18
|
+
*/
|
|
19
|
+
/** 本插件的设置命名空间,与 Host 侧 UI_DEFAULTS_NAMESPACE 一致。 */
|
|
20
|
+
const SETTINGS_NS = "model-reasoning-defaults";
|
|
21
|
+
/** 已知推理等级集合(与 Host 侧 KNOWN_REASONING_EFFORTS 保持一致)。 */
|
|
22
|
+
const KNOWN_EFFORTS = [
|
|
23
|
+
"off",
|
|
24
|
+
"minimal",
|
|
25
|
+
"low",
|
|
26
|
+
"medium",
|
|
27
|
+
"high",
|
|
28
|
+
"xhigh",
|
|
29
|
+
"max"
|
|
30
|
+
];
|
|
31
|
+
/** 声明客户端所需的槽位与 settings Remote 命名空间。 */
|
|
32
|
+
const inject = [
|
|
33
|
+
"slots",
|
|
34
|
+
"remote",
|
|
35
|
+
"remote.settings"
|
|
36
|
+
];
|
|
37
|
+
/** apply 时捕获的设置 Remote;组件经模块级引用读取(单注册插件,热重载时随 apply 刷新)。 */
|
|
38
|
+
let currentApi;
|
|
39
|
+
/**
|
|
40
|
+
* 从 describe 应答中提取本插件命名空间的路由表与修订号。
|
|
41
|
+
*
|
|
42
|
+
* @param namespaces - describe 应答携带的命名空间视图列表。
|
|
43
|
+
* @returns 路由字典副本与修订号;命名空间尚未注册时为 undefined。
|
|
44
|
+
*/
|
|
45
|
+
function findOwnNamespace(namespaces) {
|
|
46
|
+
const own = namespaces.find((entry) => entry.ns === SETTINGS_NS);
|
|
47
|
+
if (own === void 0) return void 0;
|
|
48
|
+
const section = own.value;
|
|
49
|
+
return {
|
|
50
|
+
defaults: section !== null && typeof section === "object" && section.defaults !== void 0 && typeof section.defaults === "object" ? { ...section.defaults } : {},
|
|
51
|
+
revision: own.revision
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* 从 describe 应答中收集已知 provider 与 provider:model 路由键,作为输入建议。
|
|
56
|
+
*
|
|
57
|
+
* @param namespaces - describe 应答携带的命名空间视图列表。
|
|
58
|
+
* @returns 排序后的建议键列表。
|
|
59
|
+
*/
|
|
60
|
+
function collectSuggestions(namespaces) {
|
|
61
|
+
const suggestions = /* @__PURE__ */ new Set();
|
|
62
|
+
const addProvider = (id, models) => {
|
|
63
|
+
const providerId = id.trim();
|
|
64
|
+
if (providerId.length === 0) return;
|
|
65
|
+
suggestions.add(providerId);
|
|
66
|
+
for (const model of models) {
|
|
67
|
+
const modelId = model.trim();
|
|
68
|
+
if (modelId.length > 0) suggestions.add(providerId + ":" + modelId);
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
const piAi = namespaces.find((entry) => entry.ns === "llm-pi-ai")?.value;
|
|
72
|
+
if (piAi?.providers && typeof piAi.providers === "object") for (const [providerId, profile] of Object.entries(piAi.providers)) addProvider(providerId, Array.isArray(profile?.models) ? profile.models.map((m) => typeof m?.id === "string" ? m.id : "").filter((id) => id.length > 0) : []);
|
|
73
|
+
if (namespaces.some((entry) => entry.ns === "llm-deepseek")) addProvider("deepseek-official", []);
|
|
74
|
+
return [...suggestions].sort();
|
|
75
|
+
}
|
|
76
|
+
/** 建议弹层最多展示的条数;更多条目没有滚动价值,缩小查询即可。 */
|
|
77
|
+
const SUGGESTION_LIMIT = 12;
|
|
78
|
+
/**
|
|
79
|
+
* 按当前输入过滤建议键:子串匹配(路由键常以 provider 前缀开头,前缀过滤
|
|
80
|
+
* 会漏掉 model 段命中),排除与输入完全相同的项,空输入展示前若干条。
|
|
81
|
+
*
|
|
82
|
+
* @param value - 输入框当前值。
|
|
83
|
+
* @param all - 全量建议键。
|
|
84
|
+
* @returns 供弹层展示的建议键列表。
|
|
85
|
+
*/
|
|
86
|
+
function suggestionMatches(value, all) {
|
|
87
|
+
const exact = value.trim();
|
|
88
|
+
const query = exact.toLowerCase();
|
|
89
|
+
return (query.length === 0 ? all : all.filter((candidate) => candidate !== exact && candidate.toLowerCase().includes(query))).slice(0, SUGGESTION_LIMIT);
|
|
90
|
+
}
|
|
91
|
+
const sectionStyle = {
|
|
92
|
+
display: "flex",
|
|
93
|
+
flexDirection: "column",
|
|
94
|
+
gap: 12,
|
|
95
|
+
maxWidth: 720,
|
|
96
|
+
color: "var(--dsw-alias-label-primary)"
|
|
97
|
+
};
|
|
98
|
+
const titleStyle = {
|
|
99
|
+
margin: 0,
|
|
100
|
+
fontSize: 16,
|
|
101
|
+
fontWeight: 600,
|
|
102
|
+
lineHeight: 1.4
|
|
103
|
+
};
|
|
104
|
+
const rowStyle = {
|
|
105
|
+
display: "flex",
|
|
106
|
+
alignItems: "center",
|
|
107
|
+
gap: 8
|
|
108
|
+
};
|
|
109
|
+
const keyFieldStyle = {
|
|
110
|
+
flex: 1,
|
|
111
|
+
minWidth: 0
|
|
112
|
+
};
|
|
113
|
+
const mutedStyle = {
|
|
114
|
+
margin: 0,
|
|
115
|
+
fontSize: 13,
|
|
116
|
+
lineHeight: 1.6,
|
|
117
|
+
color: "var(--dsw-alias-label-tertiary)"
|
|
118
|
+
};
|
|
119
|
+
const hintStyle = {
|
|
120
|
+
margin: 0,
|
|
121
|
+
fontSize: 12,
|
|
122
|
+
lineHeight: 1.6,
|
|
123
|
+
color: "var(--dsw-alias-label-tertiary)"
|
|
124
|
+
};
|
|
125
|
+
const errorStyle = {
|
|
126
|
+
margin: 0,
|
|
127
|
+
fontSize: 12,
|
|
128
|
+
lineHeight: 1.6,
|
|
129
|
+
color: "var(--dsw-alias-state-error-primary)"
|
|
130
|
+
};
|
|
131
|
+
const okStyle = {
|
|
132
|
+
margin: 0,
|
|
133
|
+
fontSize: 12,
|
|
134
|
+
lineHeight: 1.6,
|
|
135
|
+
color: "var(--dsw-alias-state-success-primary)"
|
|
136
|
+
};
|
|
137
|
+
/**
|
|
138
|
+
* 把官方 Input 的默认几何(h32 / r8 / 字号 14)对齐到行内 sm 胶囊控件
|
|
139
|
+
* (Button.sm:h28 / r14 / 字号 12),使路由键输入框与右侧下拉、删除按钮同高同形。
|
|
140
|
+
* 建议弹层的包裹 span 由 Menu 注入为 inline 布局,这里展开成块级并撑满列宽,
|
|
141
|
+
* 让弹层与输入框左缘对齐。通过 data-plugin-css 标记幂等注入,遵循宿主插件样式约定。
|
|
142
|
+
*/
|
|
143
|
+
const COMPACT_INPUT_CSS = [
|
|
144
|
+
".dsh-mrd-input-sm {",
|
|
145
|
+
" box-sizing: border-box;",
|
|
146
|
+
" width: 100%;",
|
|
147
|
+
" height: 28px;",
|
|
148
|
+
" border-radius: 14px;",
|
|
149
|
+
" padding: 0 10px;",
|
|
150
|
+
"}",
|
|
151
|
+
".dsh-mrd-input-sm > input {",
|
|
152
|
+
" font-size: 12px;",
|
|
153
|
+
" line-height: 18px;",
|
|
154
|
+
"}",
|
|
155
|
+
".dsh-mrd-suggest {",
|
|
156
|
+
" display: block;",
|
|
157
|
+
" width: 100%;",
|
|
158
|
+
"}"
|
|
159
|
+
].join("\n");
|
|
160
|
+
const COMPACT_INPUT_STYLE_TAG = "dsh-model-reasoning-defaults/input-sm";
|
|
161
|
+
if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=\"" + COMPACT_INPUT_STYLE_TAG + "\"]") === null) {
|
|
162
|
+
const tag = document.createElement("style");
|
|
163
|
+
tag.dataset.plugin = "dsh-model-reasoning-defaults";
|
|
164
|
+
tag.dataset.pluginCss = COMPACT_INPUT_STYLE_TAG;
|
|
165
|
+
tag.textContent = COMPACT_INPUT_CSS;
|
|
166
|
+
document.head.appendChild(tag);
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* 把路由字典展开成按键排序的可编辑行。
|
|
170
|
+
*
|
|
171
|
+
* @param defaults - 路由字典。
|
|
172
|
+
* @returns 稳定排序的行列表。
|
|
173
|
+
*/
|
|
174
|
+
function rowsOf(defaults) {
|
|
175
|
+
return Object.entries(defaults).map(([key, effort]) => ({
|
|
176
|
+
key,
|
|
177
|
+
effort
|
|
178
|
+
})).sort((a, b) => a.key < b.key ? -1 : a.key > b.key ? 1 : 0);
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* 校验待保存的行集合并折叠回路由字典。
|
|
182
|
+
*
|
|
183
|
+
* @param rows - 当前编辑的行。
|
|
184
|
+
* @returns 校验通过时返回字典;失败时返回错误消息。
|
|
185
|
+
*/
|
|
186
|
+
function collapseRows(rows) {
|
|
187
|
+
const result = {};
|
|
188
|
+
for (const row of rows) {
|
|
189
|
+
const key = row.key.trim();
|
|
190
|
+
if (key.length === 0) continue;
|
|
191
|
+
if (key in result) return { error: "存在重复路由键:" + key };
|
|
192
|
+
result[key] = row.effort;
|
|
193
|
+
}
|
|
194
|
+
return result;
|
|
195
|
+
}
|
|
196
|
+
/**
|
|
197
|
+
* 设置页「推理等级默认」编辑面板。
|
|
198
|
+
*
|
|
199
|
+
* 数据流:挂载时 describe 读一次(拿路由表、修订号、只读标记与建议键);
|
|
200
|
+
* 保存时带 expectedRevision 做 update,陈旧编辑会被宿主拒绝而不是静默覆盖。
|
|
201
|
+
* 外部改动(另一标签页、手工编辑 yaml)在本组件重新挂载时可见——设置壳每次
|
|
202
|
+
* 打开都重新挂载 section,无需订阅失效事件。
|
|
203
|
+
*
|
|
204
|
+
* @param props - 无属主属性(close 由壳持有,本面板不离开设置页)。
|
|
205
|
+
* @returns 面板节点树。
|
|
206
|
+
*/
|
|
207
|
+
function ReasoningDefaultsSection(_props) {
|
|
208
|
+
const [rows, setRows] = (0, react.useState)([]);
|
|
209
|
+
const [phase, setPhase] = (0, react.useState)("loading");
|
|
210
|
+
const [writable, setWritable] = (0, react.useState)(true);
|
|
211
|
+
const [saving, setSaving] = (0, react.useState)(false);
|
|
212
|
+
const [feedback, setFeedback] = (0, react.useState)(void 0);
|
|
213
|
+
const [suggestions, setSuggestions] = (0, react.useState)([]);
|
|
214
|
+
const [openMenuIndex, setOpenMenuIndex] = (0, react.useState)(null);
|
|
215
|
+
const [suggestIndex, setSuggestIndex] = (0, react.useState)(null);
|
|
216
|
+
const revisionRef = (0, react.useState)(() => ({ revision: 0 }))[0];
|
|
217
|
+
(0, react.useEffect)(() => {
|
|
218
|
+
let cancelled = false;
|
|
219
|
+
const load = async () => {
|
|
220
|
+
const api = currentApi;
|
|
221
|
+
if (api === void 0) {
|
|
222
|
+
if (!cancelled) setPhase("unavailable");
|
|
223
|
+
return;
|
|
224
|
+
}
|
|
225
|
+
try {
|
|
226
|
+
const response = await api.describe();
|
|
227
|
+
if (cancelled) return;
|
|
228
|
+
if (!response.ok) {
|
|
229
|
+
setPhase("unavailable");
|
|
230
|
+
setFeedback({
|
|
231
|
+
kind: "error",
|
|
232
|
+
text: response.error.message
|
|
233
|
+
});
|
|
234
|
+
return;
|
|
235
|
+
}
|
|
236
|
+
const own = findOwnNamespace(response.value.namespaces);
|
|
237
|
+
if (own === void 0) {
|
|
238
|
+
setPhase("unavailable");
|
|
239
|
+
setFeedback({
|
|
240
|
+
kind: "error",
|
|
241
|
+
text: "Host 未注册 " + SETTINGS_NS + " 命名空间,请确认插件已启用并刷新页面"
|
|
242
|
+
});
|
|
243
|
+
return;
|
|
244
|
+
}
|
|
245
|
+
setRows(rowsOf(own.defaults));
|
|
246
|
+
revisionRef.revision = own.revision;
|
|
247
|
+
setWritable(response.value.writable);
|
|
248
|
+
setSuggestions(collectSuggestions(response.value.namespaces));
|
|
249
|
+
setPhase("ready");
|
|
250
|
+
} catch (error) {
|
|
251
|
+
if (!cancelled) {
|
|
252
|
+
setPhase("unavailable");
|
|
253
|
+
setFeedback({
|
|
254
|
+
kind: "error",
|
|
255
|
+
text: error instanceof Error ? error.message : String(error)
|
|
256
|
+
});
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
};
|
|
260
|
+
load();
|
|
261
|
+
return () => {
|
|
262
|
+
cancelled = true;
|
|
263
|
+
};
|
|
264
|
+
}, [revisionRef]);
|
|
265
|
+
const save = async () => {
|
|
266
|
+
const api = currentApi;
|
|
267
|
+
if (api === void 0 || saving) return;
|
|
268
|
+
const collapsed = collapseRows(rows);
|
|
269
|
+
if ("error" in collapsed) {
|
|
270
|
+
setFeedback({
|
|
271
|
+
kind: "error",
|
|
272
|
+
text: collapsed.error
|
|
273
|
+
});
|
|
274
|
+
return;
|
|
275
|
+
}
|
|
276
|
+
setSaving(true);
|
|
277
|
+
setFeedback(void 0);
|
|
278
|
+
try {
|
|
279
|
+
const response = await api.update(SETTINGS_NS, { defaults: collapsed }, revisionRef.revision);
|
|
280
|
+
if (!response.ok) {
|
|
281
|
+
setFeedback({
|
|
282
|
+
kind: "error",
|
|
283
|
+
text: response.error.message
|
|
284
|
+
});
|
|
285
|
+
return;
|
|
286
|
+
}
|
|
287
|
+
const reread = await api.describe();
|
|
288
|
+
if (reread.ok) {
|
|
289
|
+
const own = findOwnNamespace(reread.value.namespaces);
|
|
290
|
+
if (own !== void 0) {
|
|
291
|
+
setRows(rowsOf(own.defaults));
|
|
292
|
+
revisionRef.revision = own.revision;
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
setFeedback({
|
|
296
|
+
kind: "ok",
|
|
297
|
+
text: "已保存,对新请求即时生效"
|
|
298
|
+
});
|
|
299
|
+
} catch (error) {
|
|
300
|
+
setFeedback({
|
|
301
|
+
kind: "error",
|
|
302
|
+
text: error instanceof Error ? error.message : String(error)
|
|
303
|
+
});
|
|
304
|
+
} finally {
|
|
305
|
+
setSaving(false);
|
|
306
|
+
}
|
|
307
|
+
};
|
|
308
|
+
if (phase === "loading") return (0, react.createElement)("div", { style: sectionStyle }, (0, react.createElement)("p", { style: mutedStyle }, "加载推理等级配置…"));
|
|
309
|
+
if (phase === "unavailable") return (0, react.createElement)("div", { style: sectionStyle }, (0, react.createElement)("p", { style: errorStyle }, "无法读取推理等级配置。"), feedback === void 0 ? null : (0, react.createElement)("p", { style: feedback.kind === "error" ? errorStyle : okStyle }, feedback.text));
|
|
310
|
+
const children = [(0, react.createElement)("div", {
|
|
311
|
+
key: "title",
|
|
312
|
+
style: titleStyle
|
|
313
|
+
}, "推理等级默认"), (0, react.createElement)("p", {
|
|
314
|
+
key: "intro",
|
|
315
|
+
style: mutedStyle
|
|
316
|
+
}, "请求未显式指定 reasoningEffort 时按此路由表补齐。匹配顺序:provider:model → provider:* → provider/* → provider → *:model → *。")];
|
|
317
|
+
if (!writable) children.push((0, react.createElement)("p", {
|
|
318
|
+
key: "readonly",
|
|
319
|
+
style: mutedStyle
|
|
320
|
+
}, "当前设置文档为只读,修改需在 Host 侧完成。"));
|
|
321
|
+
for (let index = 0; index < rows.length; index += 1) {
|
|
322
|
+
const row = rows[index];
|
|
323
|
+
const menuOpen = openMenuIndex === index;
|
|
324
|
+
const keySuggestions = suggestionMatches(row.key, suggestions);
|
|
325
|
+
children.push((0, react.createElement)("div", {
|
|
326
|
+
key: "row-" + index,
|
|
327
|
+
style: rowStyle
|
|
328
|
+
}, (0, react.createElement)("div", {
|
|
329
|
+
key: "key",
|
|
330
|
+
style: keyFieldStyle
|
|
331
|
+
}, (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Menu, {
|
|
332
|
+
key: "key-suggest",
|
|
333
|
+
className: "dsh-mrd-suggest",
|
|
334
|
+
open: suggestIndex === index && keySuggestions.length > 0,
|
|
335
|
+
portal: true,
|
|
336
|
+
dense: true,
|
|
337
|
+
items: keySuggestions.map((candidate) => ({
|
|
338
|
+
id: candidate,
|
|
339
|
+
label: candidate
|
|
340
|
+
})),
|
|
341
|
+
onSelect: (candidate) => {
|
|
342
|
+
const next = [...rows];
|
|
343
|
+
next[index] = {
|
|
344
|
+
...row,
|
|
345
|
+
key: candidate
|
|
346
|
+
};
|
|
347
|
+
setRows(next);
|
|
348
|
+
setSuggestIndex(null);
|
|
349
|
+
},
|
|
350
|
+
onClose: () => {
|
|
351
|
+
setSuggestIndex(null);
|
|
352
|
+
},
|
|
353
|
+
anchor: (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Input, {
|
|
354
|
+
className: "dsh-mrd-input-sm",
|
|
355
|
+
value: row.key,
|
|
356
|
+
placeholder: "provider:model / provider:* / *",
|
|
357
|
+
"aria-label": "路由键",
|
|
358
|
+
style: { width: "100%" },
|
|
359
|
+
onFocus: () => {
|
|
360
|
+
setSuggestIndex(index);
|
|
361
|
+
},
|
|
362
|
+
onChange: (event) => {
|
|
363
|
+
const next = [...rows];
|
|
364
|
+
next[index] = {
|
|
365
|
+
...row,
|
|
366
|
+
key: event.target.value
|
|
367
|
+
};
|
|
368
|
+
setRows(next);
|
|
369
|
+
setSuggestIndex(index);
|
|
370
|
+
}
|
|
371
|
+
})
|
|
372
|
+
})), (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Menu, {
|
|
373
|
+
key: "effort",
|
|
374
|
+
open: menuOpen,
|
|
375
|
+
onClose: () => {
|
|
376
|
+
setOpenMenuIndex(null);
|
|
377
|
+
},
|
|
378
|
+
portal: true,
|
|
379
|
+
dense: true,
|
|
380
|
+
items: KNOWN_EFFORTS.map((level) => ({
|
|
381
|
+
id: level,
|
|
382
|
+
label: level
|
|
383
|
+
})),
|
|
384
|
+
selectedId: row.effort,
|
|
385
|
+
onSelect: (id) => {
|
|
386
|
+
const next = [...rows];
|
|
387
|
+
next[index] = {
|
|
388
|
+
...row,
|
|
389
|
+
effort: id
|
|
390
|
+
};
|
|
391
|
+
setRows(next);
|
|
392
|
+
setOpenMenuIndex(null);
|
|
393
|
+
},
|
|
394
|
+
anchor: (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
395
|
+
variant: "outline",
|
|
396
|
+
size: "sm",
|
|
397
|
+
"aria-haspopup": "menu",
|
|
398
|
+
"aria-expanded": menuOpen,
|
|
399
|
+
onClick: () => {
|
|
400
|
+
setOpenMenuIndex(menuOpen ? null : index);
|
|
401
|
+
}
|
|
402
|
+
}, row.effort, (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.IconChevronDownOutline14))
|
|
403
|
+
}), (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
404
|
+
key: "remove",
|
|
405
|
+
variant: "ghost",
|
|
406
|
+
size: "sm",
|
|
407
|
+
icon: (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.IconTrashOutline16),
|
|
408
|
+
"aria-label": "删除路由 " + row.key,
|
|
409
|
+
title: "删除该路由",
|
|
410
|
+
onClick: () => {
|
|
411
|
+
setRows(rows.filter((_, i) => i !== index));
|
|
412
|
+
setOpenMenuIndex(null);
|
|
413
|
+
setSuggestIndex(null);
|
|
414
|
+
}
|
|
415
|
+
}, "删除")));
|
|
416
|
+
}
|
|
417
|
+
children.push((0, react.createElement)("div", {
|
|
418
|
+
key: "actions",
|
|
419
|
+
style: rowStyle
|
|
420
|
+
}, (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
421
|
+
variant: "outline",
|
|
422
|
+
size: "sm",
|
|
423
|
+
icon: (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.IconPlusOutline16),
|
|
424
|
+
onClick: () => setRows([...rows, {
|
|
425
|
+
key: "",
|
|
426
|
+
effort: "medium"
|
|
427
|
+
}])
|
|
428
|
+
}, "添加路由"), (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
429
|
+
variant: "primary",
|
|
430
|
+
size: "sm",
|
|
431
|
+
disabled: saving || !writable || rows.length === 0,
|
|
432
|
+
onClick: () => {
|
|
433
|
+
save();
|
|
434
|
+
}
|
|
435
|
+
}, saving ? "保存中…" : "保存")));
|
|
436
|
+
children.push((0, react.createElement)("p", {
|
|
437
|
+
key: "hint",
|
|
438
|
+
style: hintStyle
|
|
439
|
+
}, "已知等级:" + KNOWN_EFFORTS.join(" / ") + "。生效优先级:patch 层插件配置 > 此处 > Host 各 Provider 已声明的思考等级。路由键支持 * 通配,聚焦输入框可查看已配置 Provider/Model 的建议。"));
|
|
440
|
+
if (feedback !== void 0) children.push((0, react.createElement)("p", {
|
|
441
|
+
key: "feedback",
|
|
442
|
+
style: { ...feedback.kind === "error" ? errorStyle : okStyle }
|
|
443
|
+
}, feedback.text));
|
|
444
|
+
return (0, react.createElement)("div", { style: sectionStyle }, children);
|
|
445
|
+
}
|
|
446
|
+
/**
|
|
447
|
+
* 注册设置页编辑 section。
|
|
448
|
+
*
|
|
449
|
+
* slots.inject 已绑定当前 fiber 的生命周期,不需要再套一层 effect,
|
|
450
|
+
* 注册和注销由同一个 slot owner 管理,不会留下嵌套 disposer。
|
|
451
|
+
*
|
|
452
|
+
* @param ctx - 提供槽位与连接服务的客户端上下文。
|
|
453
|
+
*/
|
|
454
|
+
function apply(ctx) {
|
|
455
|
+
currentApi = ctx.remote.settings;
|
|
456
|
+
ctx.slots.inject("settings.section", () => ctx.slots.register({
|
|
457
|
+
name: "settings.section",
|
|
458
|
+
id: SETTINGS_NS,
|
|
459
|
+
order: 15,
|
|
460
|
+
label: () => "推理等级默认"
|
|
461
|
+
}, ReasoningDefaultsSection));
|
|
462
|
+
}
|
|
463
|
+
//#endregion
|
|
464
|
+
exports.apply = apply;
|
|
465
|
+
exports.inject = inject;
|
|
466
|
+
return module.exports;
|
|
467
|
+
}
|
|
468
|
+
});
|
|
469
|
+
|
|
470
|
+
//# sourceMappingURL=client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.js","names":["useState","createElement","Menu","Input","Button","IconChevronDownOutline14","IconTrashOutline16","IconPlusOutline16"],"sources":["../src/client/index.ts"],"sourcesContent":["/**\n * dsh-model-reasoning-defaults 的客户端半体。\n *\n * - 设置页 section:编辑本插件设置命名空间中的扁平路由表,经宿主统一的\n * settings API 写入。Host 每次请求实时读取该层,保存即生效。\n *\n * 控件一律使用官方 @deepseek-ai/dsh-client-ui-primitives(平台基线模块,\n * 宿主模块表直接应答),与设置壳视觉一致。\n */\nimport { createElement, useEffect, useState } from 'react'\nimport type { ChangeEvent, CSSProperties, ReactNode } from 'react'\nimport {\n Button,\n IconChevronDownOutline14,\n IconPlusOutline16,\n IconTrashOutline16,\n Input,\n Menu,\n} from '@deepseek-ai/dsh-client-ui-primitives'\n// Type-only:拉入 SlotMap 声明面,使下方 declare module 增强可解析。\nimport type {} from '@deepseek-ai/dsh-client-ui-slots'\n\n/** 设置页 section 槽位类型由 ui-settings 壳声明;本插件不依赖该包,本地补齐面。 */\ndeclare module '@deepseek-ai/dsh-client-ui-slots' {\n interface SlotMap {\n 'settings.section': { kind: 'list'; scope: 'root'; owner: { close: () => void } }\n }\n}\n\n/** 宿主 SlotRegistry 的窄面:本插件只用 inject/register 两个入口。 */\ninterface SlotRegistry {\n inject(name: string, callback: () => () => void): () => void\n register(options: unknown, component: unknown): () => void\n}\n\n/** 本插件的设置命名空间,与 Host 侧 UI_DEFAULTS_NAMESPACE 一致。 */\nconst SETTINGS_NS = 'model-reasoning-defaults'\n\n/** 已知推理等级集合(与 Host 侧 KNOWN_REASONING_EFFORTS 保持一致)。 */\nconst KNOWN_EFFORTS = ['off', 'minimal', 'low', 'medium', 'high', 'xhigh', 'max'] as const\n\ntype ClientContext = {\n slots: SlotRegistry\n remote: {\n settings: RemoteSettings\n }\n}\n\n/** 声明客户端所需的槽位与 settings Remote 命名空间。 */\nexport const inject = ['slots', 'remote', 'remote.settings'] as const\n\n/** settings Remote 的读写方法面(宿主 API Gateway 经 Typert Remote 生成)。 */\ninterface RemoteSettings {\n describe(): Promise<RemoteResult<SettingsDescribeValue>>\n update(\n ns: string,\n patch: Record<string, unknown>,\n expectedRevision: number | undefined,\n ): Promise<RemoteResult<SettingsNamespaceView>>\n}\n\n/** Typert Remote 统一应答形状。 */\ntype RemoteResult<T> =\n | { ok: true; value: T }\n | { ok: false; error: { code: string; message: string; details: object } }\n\n/** describe 应答:每个已注册命名空间与写入能力标记。 */\ninterface SettingsDescribeValue {\n /** 设置文档是否可写。 */\n writable: boolean\n /** 是否有宿主侧的设置文档。 */\n hasDocument: boolean\n /** 已注册命名空间视图列表。 */\n namespaces: SettingsNamespaceView[]\n}\n\n/** 单个命名空间的描述视图。 */\ninterface SettingsNamespaceView {\n /** 命名空间键。 */\n ns: string\n /** 脱敏后的解析值。 */\n value: unknown\n /** 该视图读取时的修订号,写回时作为 expectedRevision。 */\n revision: number\n}\n\n/** apply 时捕获的设置 Remote;组件经模块级引用读取(单注册插件,热重载时随 apply 刷新)。 */\nlet currentApi: RemoteSettings | undefined\n\n/** 一条可编辑的路由行。 */\ninterface RouteRow {\n key: string\n effort: string\n}\n\n/** describe 应答中单个命名空间的视图子集。 */\ninterface NamespaceView {\n ns: string\n value: unknown\n revision: number\n}\n\n/**\n * 从 describe 应答中提取本插件命名空间的路由表与修订号。\n *\n * @param namespaces - describe 应答携带的命名空间视图列表。\n * @returns 路由字典副本与修订号;命名空间尚未注册时为 undefined。\n */\nfunction findOwnNamespace(namespaces: NamespaceView[]): { defaults: Record<string, string>; revision: number } | undefined {\n const own = namespaces.find(entry => entry.ns === SETTINGS_NS)\n if (own === undefined) return undefined\n const section = own.value as { defaults?: Record<string, string> } | null\n return {\n defaults: section !== null && typeof section === 'object'\n && section.defaults !== undefined && typeof section.defaults === 'object'\n ? { ...section.defaults }\n : {},\n revision: own.revision,\n }\n}\n\n/**\n * 从 describe 应答中收集已知 provider 与 provider:model 路由键,作为输入建议。\n *\n * @param namespaces - describe 应答携带的命名空间视图列表。\n * @returns 排序后的建议键列表。\n */\nfunction collectSuggestions(namespaces: NamespaceView[]): string[] {\n const suggestions = new Set<string>()\n const addProvider = (id: string, models: readonly string[]): void => {\n const providerId = id.trim()\n if (providerId.length === 0) return\n suggestions.add(providerId)\n for (const model of models) {\n const modelId = model.trim()\n if (modelId.length > 0) suggestions.add(providerId + ':' + modelId)\n }\n }\n\n const piAi = namespaces.find(entry => entry.ns === 'llm-pi-ai')?.value as {\n providers?: Record<string, { models?: Array<{ id?: unknown }> }>\n } | null\n if (piAi?.providers && typeof piAi.providers === 'object') {\n for (const [providerId, profile] of Object.entries(piAi.providers)) {\n const models = Array.isArray(profile?.models)\n ? profile.models.map(m => (typeof m?.id === 'string' ? m.id : '')).filter(id => id.length > 0)\n : []\n addProvider(providerId, models)\n }\n }\n\n if (namespaces.some(entry => entry.ns === 'llm-deepseek')) addProvider('deepseek-official', [])\n\n return [...suggestions].sort()\n}\n\n/** 建议弹层最多展示的条数;更多条目没有滚动价值,缩小查询即可。 */\nconst SUGGESTION_LIMIT = 12\n\n/**\n * 按当前输入过滤建议键:子串匹配(路由键常以 provider 前缀开头,前缀过滤\n * 会漏掉 model 段命中),排除与输入完全相同的项,空输入展示前若干条。\n *\n * @param value - 输入框当前值。\n * @param all - 全量建议键。\n * @returns 供弹层展示的建议键列表。\n */\nfunction suggestionMatches(value: string, all: string[]): string[] {\n const exact = value.trim()\n const query = exact.toLowerCase()\n const pool = query.length === 0\n ? all\n : all.filter(candidate => candidate !== exact && candidate.toLowerCase().includes(query))\n return pool.slice(0, SUGGESTION_LIMIT)\n}\n\n// 颜色一律使用 --dsw-alias-* 语义 token(随明暗主题翻转);布局遵循设置壳\n// 约定:.options 已提供 24px 内边距,section 只负责纵向节奏与最大宽度。\nconst sectionStyle: CSSProperties = {\n display: 'flex',\n flexDirection: 'column',\n gap: 12,\n maxWidth: 720,\n color: 'var(--dsw-alias-label-primary)',\n}\n\nconst titleStyle: CSSProperties = {\n margin: 0,\n fontSize: 16,\n fontWeight: 600,\n lineHeight: 1.4,\n}\n\nconst rowStyle: CSSProperties = {\n display: 'flex',\n alignItems: 'center',\n gap: 8,\n}\n\nconst keyFieldStyle: CSSProperties = {\n flex: 1,\n minWidth: 0,\n}\n\nconst mutedStyle: CSSProperties = {\n margin: 0,\n fontSize: 13,\n lineHeight: 1.6,\n color: 'var(--dsw-alias-label-tertiary)',\n}\n\nconst hintStyle: CSSProperties = {\n margin: 0,\n fontSize: 12,\n lineHeight: 1.6,\n color: 'var(--dsw-alias-label-tertiary)',\n}\n\nconst errorStyle: CSSProperties = {\n margin: 0,\n fontSize: 12,\n lineHeight: 1.6,\n color: 'var(--dsw-alias-state-error-primary)',\n}\n\nconst okStyle: CSSProperties = {\n margin: 0,\n fontSize: 12,\n lineHeight: 1.6,\n color: 'var(--dsw-alias-state-success-primary)',\n}\n\n/**\n * 把官方 Input 的默认几何(h32 / r8 / 字号 14)对齐到行内 sm 胶囊控件\n * (Button.sm:h28 / r14 / 字号 12),使路由键输入框与右侧下拉、删除按钮同高同形。\n * 建议弹层的包裹 span 由 Menu 注入为 inline 布局,这里展开成块级并撑满列宽,\n * 让弹层与输入框左缘对齐。通过 data-plugin-css 标记幂等注入,遵循宿主插件样式约定。\n */\nconst COMPACT_INPUT_CSS = [\n '.dsh-mrd-input-sm {',\n // 宿主无全局 border-box reset:content-box 下 width:100% 只是内容宽,\n // 叠加 padding/border 后总宽超出父容器 22px,溢出盖住右侧按钮。\n ' box-sizing: border-box;',\n ' width: 100%;',\n ' height: 28px;',\n ' border-radius: 14px;',\n ' padding: 0 10px;',\n '}',\n '.dsh-mrd-input-sm > input {',\n ' font-size: 12px;',\n ' line-height: 18px;',\n '}',\n '.dsh-mrd-suggest {',\n ' display: block;',\n ' width: 100%;',\n '}',\n].join('\\n')\n\nconst COMPACT_INPUT_STYLE_TAG = 'dsh-model-reasoning-defaults/input-sm'\n\n// 样式注入必须脱离 React 渲染树(模块级副作用):若以组件节点渲染,每次\n// 渲染的 DOM 幂等检查会让 React 把该节点当作\"不再渲染\"而卸载/重挂,\n// 菜单展开等重渲染期间样式短暂丢失,`.dsh-mrd-suggest` 回退为 Menu 默认的\n// inline-flex,输入框宽度塌缩(跟随宿主 tsdown.client.ts 的注入约定)。\nif (\n typeof document !== 'undefined'\n && document.querySelector('style[data-plugin-css=\"' + COMPACT_INPUT_STYLE_TAG + '\"]') === null\n) {\n const tag = document.createElement('style')\n tag.dataset.plugin = 'dsh-model-reasoning-defaults'\n tag.dataset.pluginCss = COMPACT_INPUT_STYLE_TAG\n tag.textContent = COMPACT_INPUT_CSS\n document.head.appendChild(tag)\n}\n\n/**\n * 把路由字典展开成按键排序的可编辑行。\n *\n * @param defaults - 路由字典。\n * @returns 稳定排序的行列表。\n */\nfunction rowsOf(defaults: Record<string, string>): RouteRow[] {\n return Object.entries(defaults)\n .map(([key, effort]) => ({ key, effort }))\n .sort((a, b) => (a.key < b.key ? -1 : a.key > b.key ? 1 : 0))\n}\n\n/**\n * 校验待保存的行集合并折叠回路由字典。\n *\n * @param rows - 当前编辑的行。\n * @returns 校验通过时返回字典;失败时返回错误消息。\n */\nfunction collapseRows(rows: RouteRow[]): Record<string, string> | { error: string } {\n const result: Record<string, string> = {}\n for (const row of rows) {\n const key = row.key.trim()\n // 空键行是编辑过程中的残渣:直接丢弃而不是拦住保存。\n if (key.length === 0) continue\n if (key in result) return { error: '存在重复路由键:' + key }\n result[key] = row.effort\n }\n return result\n}\n\n/**\n * 设置页「推理等级默认」编辑面板。\n *\n * 数据流:挂载时 describe 读一次(拿路由表、修订号、只读标记与建议键);\n * 保存时带 expectedRevision 做 update,陈旧编辑会被宿主拒绝而不是静默覆盖。\n * 外部改动(另一标签页、手工编辑 yaml)在本组件重新挂载时可见——设置壳每次\n * 打开都重新挂载 section,无需订阅失效事件。\n *\n * @param props - 无属主属性(close 由壳持有,本面板不离开设置页)。\n * @returns 面板节点树。\n */\nfunction ReasoningDefaultsSection(_props: { close: () => void }): ReactNode {\n const [rows, setRows] = useState<RouteRow[]>([])\n const [phase, setPhase] = useState<'loading' | 'ready' | 'unavailable'>('loading')\n const [writable, setWritable] = useState(true)\n const [saving, setSaving] = useState(false)\n const [feedback, setFeedback] = useState<{ kind: 'ok' | 'error'; text: string } | undefined>(undefined)\n const [suggestions, setSuggestions] = useState<string[]>([])\n const [openMenuIndex, setOpenMenuIndex] = useState<number | null>(null)\n const [suggestIndex, setSuggestIndex] = useState<number | null>(null)\n const revisionRef = useState<{ revision: number }>(() => ({ revision: 0 }))[0]\n\n useEffect(() => {\n let cancelled = false\n const load = async (): Promise<void> => {\n const api = currentApi\n if (api === undefined) {\n if (!cancelled) setPhase('unavailable')\n return\n }\n try {\n const response = await api.describe()\n if (cancelled) return\n if (!response.ok) {\n setPhase('unavailable')\n setFeedback({ kind: 'error', text: response.error.message })\n return\n }\n const own = findOwnNamespace(response.value.namespaces)\n if (own === undefined) {\n setPhase('unavailable')\n setFeedback({ kind: 'error', text: 'Host 未注册 ' + SETTINGS_NS + ' 命名空间,请确认插件已启用并刷新页面' })\n return\n }\n setRows(rowsOf(own.defaults))\n revisionRef.revision = own.revision\n setWritable(response.value.writable)\n setSuggestions(collectSuggestions(response.value.namespaces))\n setPhase('ready')\n } catch (error) {\n if (!cancelled) {\n setPhase('unavailable')\n setFeedback({ kind: 'error', text: error instanceof Error ? error.message : String(error) })\n }\n }\n }\n void load()\n return () => { cancelled = true }\n }, [revisionRef])\n\n const save = async (): Promise<void> => {\n const api = currentApi\n if (api === undefined || saving) return\n const collapsed = collapseRows(rows)\n if ('error' in collapsed) {\n setFeedback({ kind: 'error', text: collapsed.error })\n return\n }\n setSaving(true)\n setFeedback(undefined)\n try {\n const response = await api.update(SETTINGS_NS, { defaults: collapsed }, revisionRef.revision)\n if (!response.ok) {\n setFeedback({ kind: 'error', text: response.error.message })\n return\n }\n // 写回应答里带新修订号;再 describe 一次让行视图与存储严格一致(含 trim)。\n const reread = await api.describe()\n if (reread.ok) {\n const own = findOwnNamespace(reread.value.namespaces)\n if (own !== undefined) {\n setRows(rowsOf(own.defaults))\n revisionRef.revision = own.revision\n }\n }\n setFeedback({ kind: 'ok', text: '已保存,对新请求即时生效' })\n } catch (error) {\n setFeedback({ kind: 'error', text: error instanceof Error ? error.message : String(error) })\n } finally {\n setSaving(false)\n }\n }\n\n if (phase === 'loading') {\n return createElement('div', { style: sectionStyle }, createElement('p', { style: mutedStyle }, '加载推理等级配置…'))\n }\n\n if (phase === 'unavailable') {\n return createElement(\n 'div',\n { style: sectionStyle },\n createElement('p', { style: errorStyle }, '无法读取推理等级配置。'),\n feedback === undefined\n ? null\n : createElement('p', { style: feedback.kind === 'error' ? errorStyle : okStyle }, feedback.text),\n )\n }\n\n const children: ReactNode[] = [\n createElement('div', { key: 'title', style: titleStyle }, '推理等级默认'),\n createElement(\n 'p',\n { key: 'intro', style: mutedStyle },\n '请求未显式指定 reasoningEffort 时按此路由表补齐。匹配顺序:provider:model → provider:* → provider/* → provider → *:model → *。',\n ),\n ]\n\n if (!writable) {\n children.push(createElement('p', { key: 'readonly', style: mutedStyle }, '当前设置文档为只读,修改需在 Host 侧完成。'))\n }\n\n for (let index = 0; index < rows.length; index += 1) {\n const row = rows[index]\n const menuOpen = openMenuIndex === index\n const keySuggestions = suggestionMatches(row.key, suggestions)\n children.push(createElement(\n 'div',\n { key: 'row-' + index, style: rowStyle },\n createElement('div', { key: 'key', style: keyFieldStyle },\n // 建议弹层与等级下拉一样走 portal:设置壳的 .panel 裁剪 overflow,\n // 原地弹层会被裁掉或顶出面板(原生 datalist 更是完全不受控)。\n createElement(Menu, {\n key: 'key-suggest',\n className: 'dsh-mrd-suggest',\n open: suggestIndex === index && keySuggestions.length > 0,\n portal: true,\n dense: true,\n items: keySuggestions.map(candidate => ({ id: candidate, label: candidate })),\n onSelect: (candidate: string) => {\n const next = [...rows]\n next[index] = { ...row, key: candidate }\n setRows(next)\n setSuggestIndex(null)\n },\n onClose: () => { setSuggestIndex(null) },\n anchor: createElement(Input, {\n className: 'dsh-mrd-input-sm',\n value: row.key,\n placeholder: 'provider:model / provider:* / *',\n 'aria-label': '路由键',\n style: { width: '100%' },\n onFocus: () => { setSuggestIndex(index) },\n onChange: (event: ChangeEvent<HTMLInputElement>) => {\n const next = [...rows]\n next[index] = { ...row, key: event.target.value }\n setRows(next)\n setSuggestIndex(index)\n },\n }),\n }),\n ),\n createElement(Menu, {\n key: 'effort',\n open: menuOpen,\n onClose: () => { setOpenMenuIndex(null) },\n portal: true,\n dense: true,\n items: KNOWN_EFFORTS.map(level => ({ id: level, label: level })),\n selectedId: row.effort,\n onSelect: (id: string) => {\n const next = [...rows]\n next[index] = { ...row, effort: id }\n setRows(next)\n setOpenMenuIndex(null)\n },\n anchor: createElement(Button, {\n variant: 'outline',\n size: 'sm',\n 'aria-haspopup': 'menu',\n 'aria-expanded': menuOpen,\n onClick: () => { setOpenMenuIndex(menuOpen ? null : index) },\n }, row.effort, createElement(IconChevronDownOutline14)),\n }),\n createElement(Button, {\n key: 'remove',\n variant: 'ghost',\n size: 'sm',\n icon: createElement(IconTrashOutline16),\n 'aria-label': '删除路由 ' + row.key,\n title: '删除该路由',\n onClick: () => {\n setRows(rows.filter((_, i) => i !== index))\n setOpenMenuIndex(null)\n setSuggestIndex(null)\n },\n }, '删除'),\n ))\n }\n\n children.push(createElement(\n 'div',\n { key: 'actions', style: rowStyle },\n createElement(Button, {\n variant: 'outline',\n size: 'sm',\n icon: createElement(IconPlusOutline16),\n onClick: () => setRows([...rows, { key: '', effort: 'medium' }]),\n }, '添加路由'),\n createElement(Button, {\n variant: 'primary',\n size: 'sm',\n disabled: saving || !writable || rows.length === 0,\n onClick: () => { void save() },\n }, saving ? '保存中…' : '保存'),\n ))\n\n children.push(createElement(\n 'p',\n { key: 'hint', style: hintStyle },\n '已知等级:' + KNOWN_EFFORTS.join(' / ')\n + '。生效优先级:patch 层插件配置 > 此处 > Host 各 Provider 已声明的思考等级。'\n + '路由键支持 * 通配,聚焦输入框可查看已配置 Provider/Model 的建议。',\n ))\n\n if (feedback !== undefined) {\n children.push(createElement(\n 'p',\n { key: 'feedback', style: { ...(feedback.kind === 'error' ? errorStyle : okStyle) } },\n feedback.text,\n ))\n }\n\n return createElement('div', { style: sectionStyle }, children)\n}\n\n/**\n * 注册设置页编辑 section。\n *\n * slots.inject 已绑定当前 fiber 的生命周期,不需要再套一层 effect,\n * 注册和注销由同一个 slot owner 管理,不会留下嵌套 disposer。\n *\n * @param ctx - 提供槽位与连接服务的客户端上下文。\n */\nexport function apply(ctx: ClientContext): void {\n // 宿主 API Gateway 装配了 settings Remote 命名空间后,ctx.remote.settings 才可用;\n // inject 声明保证了装配顺序,此处直接引用。\n currentApi = ctx.remote.settings\n\n ctx.slots.inject(\n 'settings.section',\n () => ctx.slots.register({\n name: 'settings.section',\n id: SETTINGS_NS,\n order: 15,\n label: () => '推理等级默认',\n }, ReasoningDefaultsSection),\n )\n}\n"],"mappings":"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"}
|
package/lib/index.d.mts
ADDED
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import { LlmCallConfig } from "@deepseek-ai/dsh-llm";
|
|
2
|
+
import z from "@deepseek-ai/schemastery";
|
|
3
|
+
import { Context } from "@deepseek-ai/cordis";
|
|
4
|
+
//#region src/index.d.ts
|
|
5
|
+
/** 插件名(同时作为 Cordis 插件 id)。 */
|
|
6
|
+
declare const name = "dsh-model-reasoning-defaults";
|
|
7
|
+
/** 声明依赖的服务:LLM 服务就绪后装配;注册/读取设置命名空间需要设置服务。 */
|
|
8
|
+
declare const inject: readonly ["llm", "settings"];
|
|
9
|
+
/** 单个模型的推理等级配置。 */
|
|
10
|
+
interface ModelConfig {
|
|
11
|
+
/** 模型 ID(数组形式必填;字典形式以键名为准,可省略)。 */
|
|
12
|
+
id?: string;
|
|
13
|
+
/** 默认推理等级(如 off | minimal | low | medium | high | xhigh | max)。 */
|
|
14
|
+
reasoningEffort?: string;
|
|
15
|
+
}
|
|
16
|
+
/** 单个模型配置输入:既可以是等级字符串简写,也可以是配置对象。 */
|
|
17
|
+
type ModelConfigInput = string | ModelConfig;
|
|
18
|
+
/** 单个 Provider 的推理等级配置。 */
|
|
19
|
+
interface ProviderConfig {
|
|
20
|
+
/** 该 Provider 下所有模型的默认推理等级。 */
|
|
21
|
+
reasoningEffort?: string;
|
|
22
|
+
/** 该 Provider 下各模型的推理等级配置(字典或对象列表)。 */
|
|
23
|
+
models?: Record<string, ModelConfigInput> | ModelConfigInput[];
|
|
24
|
+
}
|
|
25
|
+
/** Provider 配置输入:既可以是等级字符串简写(作用于该 Provider 所有模型),也可以是配置对象。 */
|
|
26
|
+
type ProviderConfigInput = string | ProviderConfig;
|
|
27
|
+
/**
|
|
28
|
+
* 插件配置:支持按 Provider 与模型嵌入式层级配置,也可使用扁平路由字典 defaults。
|
|
29
|
+
* 两种形式是同等的一等配置入口(本仓库无历史版本,不存在"新旧兼容"语义),
|
|
30
|
+
* 归一化到同一张路由表后统一参与六级匹配。
|
|
31
|
+
*
|
|
32
|
+
* 合并后的匹配优先级从高到低为:
|
|
33
|
+
* - "provider:model":精确匹配(来自 providers[p].models[m] 或 defaults["provider:model"])
|
|
34
|
+
* - "provider:*":该 provider 下所有模型(来自 providers[p].reasoningEffort 或 defaults["provider:*"])
|
|
35
|
+
* - "provider/*":斜杠写法(来自 defaults["provider/*"])
|
|
36
|
+
* - "provider":裸 provider 写法(来自 defaults["provider"])
|
|
37
|
+
* - "*:model":跨 provider 的同名模型(来自 top-level models[m] 或 defaults["*:model"])
|
|
38
|
+
* - "*":全局匹配(来自 top-level reasoningEffort 或 defaults["*"])
|
|
39
|
+
*/
|
|
40
|
+
interface Config {
|
|
41
|
+
/** 扁平路由字典:键为上表六级路由键;与结构化配置产生同键时覆盖结构化项。 */
|
|
42
|
+
defaults?: Record<string, string>;
|
|
43
|
+
/** 按 Provider 组织的嵌入式配置。 */
|
|
44
|
+
providers?: Record<string, ProviderConfigInput>;
|
|
45
|
+
/** 跨 Provider 适用的模型默认配置(等价于 "*:model")。 */
|
|
46
|
+
models?: Record<string, ModelConfigInput> | ModelConfigInput[];
|
|
47
|
+
/** 全局默认推理等级(等价于 "*")。 */
|
|
48
|
+
reasoningEffort?: string;
|
|
49
|
+
}
|
|
50
|
+
/** Cordis 配置模式(显式注解接口类型,满足声明产物的可命名要求)。 */
|
|
51
|
+
declare const Config: z<Config>;
|
|
52
|
+
/**
|
|
53
|
+
* 将结构化 Config 归一化为统一的扁平路由字典。
|
|
54
|
+
*
|
|
55
|
+
* @param config - 插件配置对象。
|
|
56
|
+
* @returns 归一化后的键值映射;键与值均已去除首尾空白。
|
|
57
|
+
*/
|
|
58
|
+
declare function normalizeConfig(config: Config): Record<string, string>;
|
|
59
|
+
type ReasoningConfig = Pick<LlmCallConfig, 'provider' | 'model' | 'reasoningEffort'>;
|
|
60
|
+
/**
|
|
61
|
+
* 在不修改原对象的前提下应用默认推理等级。
|
|
62
|
+
*
|
|
63
|
+
* 该函数同时用于 GenerateOptions 和 LlmCallConfig,因此调用方可以保留
|
|
64
|
+
* 原请求对象中的 messages、signal 等其它字段,并安全处理深冻结输入。
|
|
65
|
+
*
|
|
66
|
+
* 第二参数只接受归一化后的扁平路由表;结构化 Config 必须先经 normalizeConfig。
|
|
67
|
+
* 曾尝试用对象形状嗅探让本函数同时接纳两种入参,但路由表允许任意非空白键,
|
|
68
|
+
* 含 "models"/"providers" 等键的路由表会被误判成结构化配置(整表归一化为空、
|
|
69
|
+
* 注入全部失效),反之仅含顶层 reasoningEffort 的最小结构化配置又会漏判——
|
|
70
|
+
* 两类误判都是静默失效,因此彻底拆掉形状嗅探。
|
|
71
|
+
*
|
|
72
|
+
* @param config - 待补齐的 LLM 请求或调用配置。
|
|
73
|
+
* @param defaults - normalizeConfig 产出的扁平路由表。
|
|
74
|
+
* @returns 原配置或带有 reasoningEffort 的浅复制对象。
|
|
75
|
+
*/
|
|
76
|
+
declare function applyDefaultReasoningEffort<T extends ReasoningConfig>(config: T, defaults: Readonly<Record<string, string>>): T;
|
|
77
|
+
/**
|
|
78
|
+
* 设置页 UI 专用命名空间。该命名空间由本插件注册为可写设置项,浏览器设置
|
|
79
|
+
* 面板通过宿主统一的 settings API 编辑它;生效优先级位于自动提取之上、
|
|
80
|
+
* cordis 插件配置之下(见 resolveEffectiveDefaults)。
|
|
81
|
+
*/
|
|
82
|
+
declare const UI_DEFAULTS_NAMESPACE = "model-reasoning-defaults";
|
|
83
|
+
/** 设置命名空间的用户层数据形状:与 Config.defaults 同构的扁平路由字典。 */
|
|
84
|
+
interface UiDefaultsSection {
|
|
85
|
+
/** 扁平路由字典:键为六级路由键,值为推理等级。 */
|
|
86
|
+
defaults?: Record<string, string>;
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* 从当前 Cordis 上下文的设置服务中读取各 Provider 与模型的默认推理等级。
|
|
90
|
+
*
|
|
91
|
+
* 字段约定(每个来源只读单一规范字段,不做别名兜底):
|
|
92
|
+
* - llm-pi-ai:provider 级 `reasoning` 是宿主原生声明字段;模型级
|
|
93
|
+
* `models[].reasoning` 与 `modelOverrides.<model>.reasoning` 是本插件约定
|
|
94
|
+
* 读取的扩展字段,依赖其设置解析对未声明键的透传行为。宿主在模型层另有
|
|
95
|
+
* 原生字段 `reasoningEfforts`,但那是"可选等级集合 + 线格式映射"的能力
|
|
96
|
+
* 声明而非默认值选择,语义不同,本插件不读取;若上游收紧对未声明键的
|
|
97
|
+
* 解析策略,`reasoning` 这部分提取会静默失效。
|
|
98
|
+
* - llm-deepseek:顶层 `reasoningEffort` 为宿主原生字段,映射到其注册的
|
|
99
|
+
* provider 路由 deepseek-official(见 DEEPSEEK_OFFICIAL_PROVIDER_ID)。
|
|
100
|
+
*
|
|
101
|
+
* 整个函数不包 try/catch:宿主的 settings.get 对未注册命名空间返回 undefined
|
|
102
|
+
* 且不会抛错,函数体已对全部外部数据做了形状防御,剩余可能抛错的只有代码
|
|
103
|
+
* 缺陷,应当让它暴露,而不是吞掉后以空映射继续主流程。
|
|
104
|
+
*
|
|
105
|
+
* @param ctx - Cordis 上下文。
|
|
106
|
+
* @returns 提取出的路由默认映射字典。
|
|
107
|
+
*/
|
|
108
|
+
declare function extractSettingsDefaults(ctx: Context): Record<string, string>;
|
|
109
|
+
/**
|
|
110
|
+
* 从本插件专用的设置命名空间读取设置页 UI 写入的路由表。
|
|
111
|
+
*
|
|
112
|
+
* 该命名空间由 apply() 注册、浏览器设置面板写入,是"设置里改默认推理强度"
|
|
113
|
+
* 的存储层;每次请求实时读取,改动即时生效。形状非法(非对象/缺字段)时
|
|
114
|
+
* 返回空映射——schema 校验已保证写入合法,这里的防御只覆盖外部手工编辑
|
|
115
|
+
* settings 文档的场景。
|
|
116
|
+
*
|
|
117
|
+
* @param ctx - Cordis 上下文。
|
|
118
|
+
* @returns 路由映射字典。
|
|
119
|
+
*/
|
|
120
|
+
declare function extractUiNamespaceDefaults(ctx: Context): Record<string, string>;
|
|
121
|
+
/**
|
|
122
|
+
* 安装默认推理等级注入逻辑。
|
|
123
|
+
*
|
|
124
|
+
* @param ctx - 当前插件上下文。
|
|
125
|
+
* @param config - 插件配置。
|
|
126
|
+
*/
|
|
127
|
+
declare function apply(ctx: Context, config?: Config): void;
|
|
128
|
+
//#endregion
|
|
129
|
+
export { Config, ModelConfig, ModelConfigInput, ProviderConfig, ProviderConfigInput, UI_DEFAULTS_NAMESPACE, UiDefaultsSection, apply, applyDefaultReasoningEffort, extractSettingsDefaults, extractUiNamespaceDefaults, inject, name, normalizeConfig };
|
|
130
|
+
//# sourceMappingURL=index.d.mts.map
|