@dsh-plus/llm-pi 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/lib/client.js +92 -70
- package/lib/index.d.ts +3 -2
- package/lib/index.js +634 -222
- package/package.json +28 -24
- package/src/auth-inline.ts +177 -0
- package/src/catalog/official.ts +0 -2
- package/src/client/api.ts +4 -3
- package/src/client/card.tsx +5 -13
- package/src/client/client.ts +16 -18
- package/src/client/constants.ts +11 -16
- package/src/client/fields.tsx +3 -1
- package/src/client/styles.ts +1 -1
- package/src/client/views/providers.tsx +3 -1
- package/src/compat.ts +136 -62
- package/src/config-api.ts +3 -3
- package/src/config.ts +25 -4
- package/src/deepseek-routes.ts +25 -0
- package/src/ns.ts +1 -1
- package/src/profiles-deepseek.ts +12 -6
- package/src/profiles.ts +439 -171
- package/src/resolve-dsh.ts +170 -13
- package/src/service.ts +26 -0
package/lib/client.js
CHANGED
|
@@ -6,6 +6,25 @@ window.__ModuleLoader__.load({
|
|
|
6
6
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
7
7
|
let react_jsx_runtime = require("react/jsx-runtime");
|
|
8
8
|
let react = require("react");
|
|
9
|
+
//#region ../shared/src/client/icons.tsx
|
|
10
|
+
/** 官方 IconChevronDownOutline14 的同构实现(path 数据逐字一致)。 */
|
|
11
|
+
function ChevronDownIcon(props) {
|
|
12
|
+
const size = props.size ?? 14;
|
|
13
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("svg", {
|
|
14
|
+
width: size,
|
|
15
|
+
height: size,
|
|
16
|
+
className: props.className,
|
|
17
|
+
viewBox: "0 0 14 14",
|
|
18
|
+
fill: "none",
|
|
19
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
20
|
+
"aria-hidden": "true",
|
|
21
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", {
|
|
22
|
+
d: "M11.8486 5.5L11.4238 5.92383L8.69727 8.65137C8.44157 8.90706 8.21562 9.13382 8.01172 9.29785C7.79912 9.46883 7.55595 9.61756 7.25 9.66602C7.08435 9.69222 6.91565 9.69222 6.75 9.66602C6.44405 9.61756 6.20088 9.46883 5.98828 9.29785C5.78438 9.13382 5.55843 8.90706 5.30273 8.65137L2.57617 5.92383L2.15137 5.5L3 4.65137L3.42383 5.07617L6.15137 7.80273C6.42595 8.07732 6.59876 8.24849 6.74023 8.3623C6.87291 8.46904 6.92272 8.47813 6.9375 8.48047C6.97895 8.48703 7.02105 8.48703 7.0625 8.48047C7.07728 8.47813 7.12709 8.46904 7.25977 8.3623C7.40124 8.24849 7.57405 8.07732 7.84863 7.80273L10.5762 5.07617L11 4.65137L11.8486 5.5Z",
|
|
23
|
+
fill: "currentColor"
|
|
24
|
+
})
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
//#endregion
|
|
9
28
|
//#region ../shared/src/client/card.tsx
|
|
10
29
|
const IDLE_STATUS = {
|
|
11
30
|
kind: "idle",
|
|
@@ -41,10 +60,7 @@ window.__ModuleLoader__.load({
|
|
|
41
60
|
className: `${p}-pending`,
|
|
42
61
|
children: props.dirtyLabel
|
|
43
62
|
}) : null,
|
|
44
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("
|
|
45
|
-
className: `${p}-chevron${props.open ? ` ${p}-chevronOpen` : ""}`,
|
|
46
|
-
children: "▾"
|
|
47
|
-
})
|
|
63
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(ChevronDownIcon, { className: `${p}-chevron${props.open ? ` ${p}-chevronOpen` : ""}` })
|
|
48
64
|
]
|
|
49
65
|
}), props.open ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
50
66
|
className: `${p}-body`,
|
|
@@ -110,6 +126,11 @@ window.__ModuleLoader__.load({
|
|
|
110
126
|
]
|
|
111
127
|
});
|
|
112
128
|
}
|
|
129
|
+
/**
|
|
130
|
+
* 勾选行:自绘圆角扁平开关(switch),对齐官方 WebUI 无原生 checkbox 的
|
|
131
|
+
* 设计语言(官方选择类控件全走胶囊/菜单,见 cardCss 的 -switch 规则)。
|
|
132
|
+
* 语义保持 checkbox(无障碍树与表单语义不变),视觉自绘。
|
|
133
|
+
*/
|
|
113
134
|
function CheckRow(props) {
|
|
114
135
|
const p = props.prefix ?? "dshp";
|
|
115
136
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
@@ -117,6 +138,8 @@ window.__ModuleLoader__.load({
|
|
|
117
138
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
118
139
|
id: props.id,
|
|
119
140
|
type: "checkbox",
|
|
141
|
+
role: "switch",
|
|
142
|
+
"aria-checked": props.checked,
|
|
120
143
|
checked: props.checked,
|
|
121
144
|
disabled: props.disabled === true,
|
|
122
145
|
onChange: (event) => props.onEdit(event.target.checked)
|
|
@@ -173,14 +196,15 @@ window.__ModuleLoader__.load({
|
|
|
173
196
|
//#endregion
|
|
174
197
|
//#region ../shared/src/client/scope.ts
|
|
175
198
|
/**
|
|
176
|
-
*
|
|
199
|
+
* remote.settings 直连实现的命名空间 scope(官方配置页 tab 同款模式)。
|
|
177
200
|
* 读:describe 取命名空间视图(脱敏 value/revision + 顶层 writable);
|
|
178
201
|
* 刷新:remote `settings/document-updated`(按命名空间过滤)与
|
|
179
202
|
* `connection/reset`;generation 防旧读覆盖新发布。任何页面 origin
|
|
180
203
|
* (loopback 或 tailnet 信任域名)下行为一致。
|
|
181
204
|
* effect 归属调用方 fiber(label 需含插件名以便诊断)。
|
|
182
205
|
*/
|
|
183
|
-
function
|
|
206
|
+
function createSettingsScope(c, ns, label) {
|
|
207
|
+
const remote = c.get("remote");
|
|
184
208
|
let state = {
|
|
185
209
|
status: "loading",
|
|
186
210
|
value: void 0,
|
|
@@ -195,36 +219,37 @@ window.__ModuleLoader__.load({
|
|
|
195
219
|
};
|
|
196
220
|
const load = async () => {
|
|
197
221
|
const gen = ++generation;
|
|
198
|
-
let
|
|
222
|
+
let view;
|
|
199
223
|
try {
|
|
200
|
-
response = await
|
|
224
|
+
const response = await remote.settings.describe();
|
|
225
|
+
if (!response.ok) return;
|
|
226
|
+
view = response.value;
|
|
201
227
|
} catch {
|
|
202
228
|
return;
|
|
203
229
|
}
|
|
204
|
-
if (gen !== generation
|
|
205
|
-
const
|
|
206
|
-
|
|
207
|
-
if (view === void 0) {
|
|
230
|
+
if (gen !== generation) return;
|
|
231
|
+
const namespace = view.namespaces.find((candidate) => candidate.ns === ns);
|
|
232
|
+
if (namespace === void 0) {
|
|
208
233
|
publish({
|
|
209
234
|
status: "unavailable",
|
|
210
235
|
value: void 0,
|
|
211
236
|
revision: void 0,
|
|
212
|
-
writable
|
|
237
|
+
writable: view.writable
|
|
213
238
|
});
|
|
214
239
|
return;
|
|
215
240
|
}
|
|
216
241
|
publish({
|
|
217
242
|
status: "ready",
|
|
218
|
-
value:
|
|
219
|
-
revision:
|
|
220
|
-
writable
|
|
243
|
+
value: namespace.value,
|
|
244
|
+
revision: namespace.revision,
|
|
245
|
+
writable: view.writable
|
|
221
246
|
});
|
|
222
247
|
};
|
|
223
248
|
const refresh = (namespace) => {
|
|
224
249
|
if (namespace !== void 0 && namespace !== ns) return;
|
|
225
250
|
load();
|
|
226
251
|
};
|
|
227
|
-
const disposers = [
|
|
252
|
+
const disposers = [remote.$on("settings/document-updated", refresh), c.on("connection/reset", () => {
|
|
228
253
|
load();
|
|
229
254
|
})];
|
|
230
255
|
c.effect(() => () => {
|
|
@@ -242,6 +267,20 @@ window.__ModuleLoader__.load({
|
|
|
242
267
|
load
|
|
243
268
|
};
|
|
244
269
|
}
|
|
270
|
+
/** 以 remote.settings 构造命名空间绑定的 api 面。 */
|
|
271
|
+
function createNamespaceApi(remote, ns) {
|
|
272
|
+
return {
|
|
273
|
+
update: async (patch, expectedRevision) => {
|
|
274
|
+
const response = await remote.update(ns, patch, expectedRevision);
|
|
275
|
+
if (!response.ok) throw new Error(response.error.message ?? "settings update failed");
|
|
276
|
+
},
|
|
277
|
+
describe: async () => {
|
|
278
|
+
const response = await remote.describe();
|
|
279
|
+
if (!response.ok) throw new Error(response.error.message ?? "settings describe failed");
|
|
280
|
+
return response.value;
|
|
281
|
+
}
|
|
282
|
+
};
|
|
283
|
+
}
|
|
245
284
|
//#endregion
|
|
246
285
|
//#region ../shared/src/client/styles.ts
|
|
247
286
|
/**
|
|
@@ -265,7 +304,7 @@ window.__ModuleLoader__.load({
|
|
|
265
304
|
.${prefix}-headText{flex-direction:column;flex:1;gap:4px;min-width:0;display:flex}
|
|
266
305
|
.${prefix}-name{color:var(--dsw-alias-label-primary);font-size:15px;font-weight:600;line-height:1.4}
|
|
267
306
|
.${prefix}-description{color:var(--dsw-alias-label-tertiary);font-size:13px;line-height:1.5}
|
|
268
|
-
.${prefix}-chevron{color:var(--dsw-alias-label-tertiary);flex:none;transition:transform .16s;
|
|
307
|
+
.${prefix}-chevron{color:var(--dsw-alias-label-tertiary);flex:none;transition:transform .16s;display:inline-flex}
|
|
269
308
|
.${prefix}-chevronOpen{transform:rotate(180deg)}
|
|
270
309
|
.${prefix}-pending{white-space:nowrap;background:var(--dsw-alias-bg-module-platform);color:var(--dsw-alias-label-secondary);border-radius:999px;flex:none;padding:1px 8px;font-size:11px;font-weight:500;line-height:17px}
|
|
271
310
|
.${prefix}-statusBadge{white-space:nowrap;border-radius:999px;flex:none;padding:1px 8px;font-size:11px;font-weight:500;line-height:17px}
|
|
@@ -279,16 +318,24 @@ window.__ModuleLoader__.load({
|
|
|
279
318
|
.${prefix}-badge{white-space:nowrap;border-radius:999px;padding:1px 8px;font-size:11px;font-weight:500;line-height:17px}
|
|
280
319
|
.${prefix}-badgeSet{background:var(--dsw-alias-bg-module-platform);color:var(--dsw-alias-label-secondary)}
|
|
281
320
|
.${prefix}-badgeUnset{color:var(--dsw-alias-label-tertiary)}
|
|
282
|
-
.${prefix}-input{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-3);height:34px;font:inherit;color:var(--dsw-alias-label-primary);border-radius:8px;padding:0 12px;font-size:13px}
|
|
321
|
+
.${prefix}-input{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-3);height:34px;font:inherit;color:var(--dsw-alias-label-primary);border-radius:8px;padding:0 12px;font-size:13px;transition:border-color .18s,background .18s}
|
|
322
|
+
.${prefix}-input:hover:not(:disabled):not(:focus-visible){border-color:var(--dsw-alias-label-dimmed)}
|
|
283
323
|
.${prefix}-input:focus-visible{border-color:var(--dsw-alias-brand-primary);outline:none}
|
|
284
324
|
.${prefix}-input:disabled{color:var(--dsw-alias-label-tertiary);cursor:default}
|
|
285
325
|
.${prefix}-inputInvalid{border-color:var(--dsw-alias-label-error)}
|
|
286
|
-
.${prefix}-select{appearance:none;background-image:linear-gradient(45deg,transparent 50%,var(--dsw-alias-label-
|
|
326
|
+
.${prefix}-select{appearance:none;background:var(--dsw-alias-bg-module-platform);border:none;cursor:pointer;background-image:linear-gradient(45deg,transparent 50%,var(--dsw-alias-label-secondary) 50%),linear-gradient(135deg,var(--dsw-alias-label-secondary) 50%,transparent 50%);background-position:calc(100% - 16px) 50%,calc(100% - 11px) 50%;background-size:5px 5px;background-repeat:no-repeat;color:var(--dsw-alias-label-primary);font:inherit;font-size:13px;height:34px;box-sizing:border-box;border-radius:8px;padding:0 30px 0 12px;transition:background-color .18s}
|
|
327
|
+
.${prefix}-select:hover:not(:disabled){background-color:var(--dsw-alias-interactive-bg-hover)}
|
|
287
328
|
.${prefix}-hint{color:var(--dsw-alias-label-tertiary);margin:0;font-size:12px;line-height:1.5}
|
|
288
329
|
.${prefix}-invalid{color:var(--dsw-alias-label-error);margin:0;font-size:12px;line-height:1.5}
|
|
289
|
-
.${prefix}-checkRow{align-items:center;gap:
|
|
290
|
-
.${prefix}-checkRow
|
|
291
|
-
|
|
330
|
+
.${prefix}-checkRow{align-items:center;gap:10px;display:flex;padding:6px 0}
|
|
331
|
+
.${prefix}-checkRow label{color:var(--dsw-alias-label-primary);font-size:13px;line-height:1.5;cursor:pointer;flex:1;min-width:0}
|
|
332
|
+
/* 自绘圆角扁平开关(官方 UI 无可见原生 checkbox,选择类全走胶囊/菜单) */
|
|
333
|
+
.${prefix}-checkRow input{appearance:none;-webkit-appearance:none;position:relative;box-sizing:border-box;background:var(--dsw-alias-bg-module-platform);border:none;border-radius:999px;width:34px;height:20px;flex:none;cursor:pointer;transition:background .18s;margin:0}
|
|
334
|
+
.${prefix}-checkRow input::after{content:"";position:absolute;top:2px;left:2px;background:var(--dsw-alias-label-primary);border-radius:999px;width:16px;height:16px;transition:left .18s cubic-bezier(.4,0,.2,1)}
|
|
335
|
+
.${prefix}-checkRow input:checked{background:var(--dsw-alias-brand-primary)}
|
|
336
|
+
.${prefix}-checkRow input:checked::after{left:16px;background:var(--dsw-alias-bg-base)}
|
|
337
|
+
.${prefix}-checkRow input:disabled{opacity:.4;cursor:default}
|
|
338
|
+
.${prefix}-checkRow input:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:2px}
|
|
292
339
|
.${prefix}-groupLabel{color:var(--dsw-alias-label-secondary);font-size:12px;font-weight:600;padding:12px 0 2px;margin:0}
|
|
293
340
|
.${prefix}-readOnly{color:var(--dsw-alias-label-tertiary);margin:12px 0 0;font-size:12px;line-height:1.5}
|
|
294
341
|
.${prefix}-warn{color:var(--dsw-alias-label-error);margin:12px 0 0;font-size:12px;line-height:1.5}
|
|
@@ -306,7 +353,6 @@ window.__ModuleLoader__.load({
|
|
|
306
353
|
.${prefix}-header{padding:12px 12px}
|
|
307
354
|
.${prefix}-input,.${prefix}-select{font-size:16px;height:40px}
|
|
308
355
|
.${prefix}-checkRow{min-height:44px;padding:8px 0}
|
|
309
|
-
.${prefix}-checkRow input{width:18px;height:18px;flex:none}
|
|
310
356
|
.${prefix}-footer{position:sticky;bottom:0;background:var(--dsw-alias-bg-layer-2);margin:0 -10px;padding:10px 10px 6px;border-top:1px solid var(--dsw-alias-border-l2);border-bottom-left-radius:12px;border-bottom-right-radius:12px}
|
|
311
357
|
.${prefix}-status{flex-basis:100%;flex:none}
|
|
312
358
|
.${prefix}-btn{min-height:44px;flex:1;min-width:96px}
|
|
@@ -341,7 +387,7 @@ ${extra}
|
|
|
341
387
|
* settings 命名空间字面量(纯常量,零依赖,浏览器半可安全引入)。
|
|
342
388
|
* 服务端经 settingsNamespace() 品牌化后使用(config.ts),浏览器半将其作为
|
|
343
389
|
* settings.plugin.item keyed 槽位的 key —— 同一字面量两处共用,防止漂移。
|
|
344
|
-
* 契约:
|
|
390
|
+
* 契约:0.1.2-alpha.1 起该槽位按「卡片编辑的 settings 命名空间」作 key 分发,
|
|
345
391
|
* 官方配置页只渲染 key 命中 Host 已注册命名空间的卡片。
|
|
346
392
|
* @module llm-pi/ns
|
|
347
393
|
*/
|
|
@@ -663,10 +709,7 @@ ${extra}
|
|
|
663
709
|
id: props.id,
|
|
664
710
|
"aria-expanded": open,
|
|
665
711
|
onClick: () => setOpen(!open),
|
|
666
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
667
|
-
className: `lpc-chevron${open ? " lpc-chevronOpen" : ""}`,
|
|
668
|
-
children: "▾"
|
|
669
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
712
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(ChevronDownIcon, { className: `lpc-chevron${open ? " lpc-chevronOpen" : ""}` }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
670
713
|
className: "lpc-collapseTitle",
|
|
671
714
|
children: props.title
|
|
672
715
|
})]
|
|
@@ -909,13 +952,18 @@ ${extra}
|
|
|
909
952
|
"medium",
|
|
910
953
|
"high"
|
|
911
954
|
];
|
|
912
|
-
/**
|
|
955
|
+
/**
|
|
956
|
+
* 逐协议 compat 字段表(来源:compat.ts,逐字段镜像官方 catalog.ts COMPAT_GATES)。
|
|
957
|
+
* 只列 offer 字段(withhold 字段官方写时拒绝,UI 不提供);取值约束对齐官方
|
|
958
|
+
* config.ts compatProfile schema。
|
|
959
|
+
*/
|
|
913
960
|
const COMPAT_FIELDS = {
|
|
914
961
|
"openai-completions": {
|
|
915
962
|
supportsStore: "boolean",
|
|
916
963
|
supportsDeveloperRole: "boolean",
|
|
917
964
|
supportsReasoningEffort: "boolean",
|
|
918
965
|
supportsUsageInStreaming: "boolean",
|
|
966
|
+
supportsFinishReason: "boolean",
|
|
919
967
|
maxTokensField: ["max_completion_tokens", "max_tokens"],
|
|
920
968
|
requiresToolResultName: "boolean",
|
|
921
969
|
requiresAssistantAfterToolResult: "boolean",
|
|
@@ -923,9 +971,10 @@ ${extra}
|
|
|
923
971
|
requiresReasoningContentOnAssistantMessages: "boolean",
|
|
924
972
|
thinkingFormat: [
|
|
925
973
|
"openai",
|
|
926
|
-
"openrouter",
|
|
927
974
|
"deepseek",
|
|
975
|
+
"openrouter",
|
|
928
976
|
"together",
|
|
977
|
+
"baseten",
|
|
929
978
|
"zai",
|
|
930
979
|
"qwen",
|
|
931
980
|
"chat-template",
|
|
@@ -934,44 +983,25 @@ ${extra}
|
|
|
934
983
|
"ant-ling"
|
|
935
984
|
],
|
|
936
985
|
chatTemplateKwargs: "object",
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
zaiToolStream: "boolean",
|
|
940
|
-
supportsOpenAIGrammarTools: "boolean",
|
|
986
|
+
chatTemplateArgs: "object",
|
|
987
|
+
supportsThinkingTokenBudget: "boolean",
|
|
941
988
|
supportsStrictMode: "boolean",
|
|
942
989
|
cacheControlFormat: ["anthropic"],
|
|
943
|
-
sendSessionAffinityHeaders: "boolean",
|
|
944
|
-
deferredToolsMode: ["kimi"],
|
|
945
|
-
sessionAffinityFormat: [
|
|
946
|
-
"openai",
|
|
947
|
-
"openai-nosession",
|
|
948
|
-
"openrouter"
|
|
949
|
-
],
|
|
950
990
|
supportsLongCacheRetention: "boolean"
|
|
951
991
|
},
|
|
952
992
|
"openai-responses": {
|
|
953
993
|
supportsDeveloperRole: "boolean",
|
|
954
|
-
sessionAffinityFormat: [
|
|
955
|
-
"openai",
|
|
956
|
-
"openai-nosession",
|
|
957
|
-
"openrouter"
|
|
958
|
-
],
|
|
959
|
-
supportsLongCacheRetention: "boolean",
|
|
960
994
|
supportsStrictMode: "boolean",
|
|
961
|
-
|
|
962
|
-
supportsToolSearch: "boolean",
|
|
963
|
-
supportsExplicitPromptCacheMode: "boolean"
|
|
995
|
+
supportsLongCacheRetention: "boolean"
|
|
964
996
|
},
|
|
965
997
|
"anthropic-messages": {
|
|
966
998
|
supportsEagerToolInputStreaming: "boolean",
|
|
967
999
|
supportsLongCacheRetention: "boolean",
|
|
968
|
-
sendSessionAffinityHeaders: "boolean",
|
|
969
1000
|
supportsCacheControlOnTools: "boolean",
|
|
970
1001
|
supportsTemperature: "boolean",
|
|
971
1002
|
forceAdaptiveThinking: "boolean",
|
|
972
1003
|
allowEmptySignature: "boolean",
|
|
973
|
-
supportsStrictTools: "boolean"
|
|
974
|
-
supportsToolReferences: "boolean"
|
|
1004
|
+
supportsStrictTools: "boolean"
|
|
975
1005
|
}
|
|
976
1006
|
};
|
|
977
1007
|
/** 某协议的全部合法 compat 键(与服务端 compatFieldsOf 一致)。 */
|
|
@@ -1612,10 +1642,7 @@ ${extra}
|
|
|
1612
1642
|
"aria-expanded": open,
|
|
1613
1643
|
onClick: () => setOpen(!open),
|
|
1614
1644
|
children: [
|
|
1615
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("
|
|
1616
|
-
className: `lpc-chevron${open ? " lpc-chevronOpen" : ""}`,
|
|
1617
|
-
children: "▾"
|
|
1618
|
-
}),
|
|
1645
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(ChevronDownIcon, { className: `lpc-chevron${open ? " lpc-chevronOpen" : ""}` }),
|
|
1619
1646
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
1620
1647
|
className: "lpc-routeKey",
|
|
1621
1648
|
children: route
|
|
@@ -1697,7 +1724,7 @@ ${extra}
|
|
|
1697
1724
|
/**
|
|
1698
1725
|
* 「LLM 路由」配置卡片:注册进 settings.plugin.item 插槽(官方插件配置页)。
|
|
1699
1726
|
* 顶部:enabled / catalogUrl / catalogRefreshHours / 只读状态行(kitSource、
|
|
1700
|
-
* modelsDevStatus,来自模型目录端点)+ 保存(settings.
|
|
1727
|
+
* modelsDevStatus,来自模型目录端点)+ 保存(settings.update 全量深合并)与
|
|
1701
1728
|
* 错误/成功提示;下方为 providers 路由列表(新增/删除/字段编辑/compat/模型
|
|
1702
1729
|
* 目录,见 views/)。外壳与基础控件走 @dsh-plus/shared/client 套件。
|
|
1703
1730
|
* @module llm-pi/client/card
|
|
@@ -1783,12 +1810,7 @@ ${extra}
|
|
|
1783
1810
|
const onSave = () => {
|
|
1784
1811
|
setSaving(true);
|
|
1785
1812
|
const revision = scope.getSnapshot().revision;
|
|
1786
|
-
api.
|
|
1787
|
-
ns: SETTINGS_NS,
|
|
1788
|
-
section: toPatch(draft),
|
|
1789
|
-
...revision !== void 0 ? { expectedRevision: revision } : {}
|
|
1790
|
-
}).then(async (response) => {
|
|
1791
|
-
if (!response.result.ok) throw new Error(response.result.error?.message ?? t("saveFailed"));
|
|
1813
|
+
api.update(toPatch(draft), revision).then(async () => {
|
|
1792
1814
|
await scope.load();
|
|
1793
1815
|
const next = scope.getSnapshot().value;
|
|
1794
1816
|
if (next !== void 0) setDraft(draftFromValue(next));
|
|
@@ -2136,7 +2158,7 @@ ${extra}
|
|
|
2136
2158
|
const PLUGIN_ID = "@dsh-plus/llm-pi";
|
|
2137
2159
|
const cardCssAll = cardCss("lpc", `
|
|
2138
2160
|
.lpc-input{width:100%;box-sizing:border-box}
|
|
2139
|
-
.lpc-select{appearance:none}
|
|
2161
|
+
.lpc-select{appearance:none;cursor:pointer;background-image:linear-gradient(45deg,transparent 50%,var(--dsw-alias-label-secondary) 50%),linear-gradient(135deg,var(--dsw-alias-label-secondary) 50%,transparent 50%);background-position:calc(100% - 16px) 50%,calc(100% - 11px) 50%;background-size:5px 5px;background-repeat:no-repeat;padding-right:30px}
|
|
2140
2162
|
.lpc-textarea{height:auto;min-height:72px;padding:8px 12px;line-height:1.5;font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:12px;resize:vertical}
|
|
2141
2163
|
.lpc-checkRow{padding:3px 0}
|
|
2142
2164
|
.lpc-statusRow{color:var(--dsw-alias-label-tertiary);margin:6px 0 0;font-size:12px;line-height:1.6;word-break:break-all}
|
|
@@ -2194,8 +2216,8 @@ ${extra}
|
|
|
2194
2216
|
const inject = [
|
|
2195
2217
|
"slots",
|
|
2196
2218
|
"locale",
|
|
2197
|
-
"
|
|
2198
|
-
"remote"
|
|
2219
|
+
"remote",
|
|
2220
|
+
"remote.settings"
|
|
2199
2221
|
];
|
|
2200
2222
|
function apply(ctx) {
|
|
2201
2223
|
const c = ctx;
|
|
@@ -2207,8 +2229,8 @@ ${extra}
|
|
|
2207
2229
|
zh,
|
|
2208
2230
|
en
|
|
2209
2231
|
}), "llm-pi: locale");
|
|
2210
|
-
const
|
|
2211
|
-
const
|
|
2232
|
+
const scope = createSettingsScope(c, SETTINGS_NS, "llm-pi: settings scope");
|
|
2233
|
+
const api = createNamespaceApi(c.get("remote").settings, SETTINGS_NS);
|
|
2212
2234
|
c.slots.inject("settings.plugin.item", () => c.slots.register({
|
|
2213
2235
|
name: "settings.plugin.item",
|
|
2214
2236
|
key: SETTINGS_NS,
|
package/lib/index.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ import z from "@deepseek-ai/schemastery";
|
|
|
2
2
|
import { Context } from "@deepseek-ai/cordis";
|
|
3
3
|
//#region src/config.d.ts
|
|
4
4
|
/** settings 命名空间;webui 配置卡片与插件运行期读取同一份(字面量见 ./ns.ts)。 */
|
|
5
|
-
declare const SETTINGS_NS:
|
|
5
|
+
declare const SETTINGS_NS: Branded<"SettingsNamespace">;
|
|
6
6
|
/** 本插件可为手写 route 提供的协议实现(与官方 PROTOCOLS 表一致)。 */
|
|
7
7
|
declare const PROTOCOL_IDS: readonly ["openai-completions", "openai-responses", "anthropic-messages"];
|
|
8
8
|
type ProtocolId = (typeof PROTOCOL_IDS)[number];
|
|
@@ -28,7 +28,6 @@ interface ModelEntryConfig {
|
|
|
28
28
|
/** 以下仅 adapter: deepseek 的 route 有效(官方 llm-deepseek 目录字段)。 */
|
|
29
29
|
imagePixelBudget?: number;
|
|
30
30
|
imageMaxBytes?: number;
|
|
31
|
-
imageDetail?: 'auto' | 'low';
|
|
32
31
|
}
|
|
33
32
|
/** 单个 provider route 配置(providers 字典的值)。 */
|
|
34
33
|
interface ProviderProfileConfig {
|
|
@@ -56,6 +55,8 @@ interface ProviderProfileConfig {
|
|
|
56
55
|
websocketConnectTimeoutMs?: number;
|
|
57
56
|
streamIdleTimeoutMs?: number;
|
|
58
57
|
maxRequestImageBytes?: number;
|
|
58
|
+
requestImagePixelBudget?: number;
|
|
59
|
+
requestImageMaxBytes?: number;
|
|
59
60
|
retryPolicy?: unknown;
|
|
60
61
|
models?: ModelEntryConfig[];
|
|
61
62
|
/** 以下仅 adapter: deepseek 的 route 有效(透传官方 llm-deepseek 同名策略)。 */
|