@dsh-plus/llm-pi 0.2.0 → 0.2.2
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 +33 -13
- package/lib/index.d.ts +2 -2
- package/lib/index.js +140 -47
- package/package.json +2 -2
- package/src/auth-inline.ts +21 -8
- package/src/client/api.ts +8 -1
- package/src/client/client.ts +2 -2
- package/src/client/i18n.ts +4 -2
- package/src/client/root-fields.tsx +29 -5
- package/src/compat.ts +2 -2
- package/src/config-api.ts +1 -1
- package/src/config.ts +6 -17
- package/src/deepseek-routes.ts +2 -2
- package/src/inherit.ts +1 -1
- package/src/ns.ts +1 -1
- package/src/official-surface.ts +45 -4
- package/src/profiles-deepseek.ts +1 -11
- package/src/profiles.ts +2 -10
- package/src/resolve-dsh.ts +110 -46
- package/src/service.ts +20 -14
package/lib/client.js
CHANGED
|
@@ -184,7 +184,7 @@ window.__ModuleLoader__.load({
|
|
|
184
184
|
unsaved: "未保存",
|
|
185
185
|
loading: "加载中…",
|
|
186
186
|
unavailable: "配置服务不可用。",
|
|
187
|
-
readOnly: "当前部署无 settings provider
|
|
187
|
+
readOnly: "当前部署无 settings provider,配置为只读;请在 profile 的 cordis.patch.yml 行级配置。",
|
|
188
188
|
invalidNumber: "请输入正整数。",
|
|
189
189
|
collapse: "收起",
|
|
190
190
|
expand: "展开",
|
|
@@ -201,7 +201,7 @@ window.__ModuleLoader__.load({
|
|
|
201
201
|
unsaved: "Unsaved",
|
|
202
202
|
loading: "Loading…",
|
|
203
203
|
unavailable: "Settings service unavailable.",
|
|
204
|
-
readOnly: "No settings provider in this deployment; config is read-only.
|
|
204
|
+
readOnly: "No settings provider in this deployment; config is read-only. Configure it at the profile row in cordis.patch.yml.",
|
|
205
205
|
invalidNumber: "Enter a positive integer.",
|
|
206
206
|
collapse: "Collapse",
|
|
207
207
|
expand: "Expand",
|
|
@@ -408,7 +408,7 @@ ${extra}
|
|
|
408
408
|
//#region src/ns.ts
|
|
409
409
|
/**
|
|
410
410
|
* settings 命名空间字面量(纯常量,零依赖,浏览器半可安全引入)。
|
|
411
|
-
* 服务端直接以字面量注册(
|
|
411
|
+
* 服务端直接以字面量注册(dsh-settings 对命名空间做编译期
|
|
412
412
|
* 语法校验,见 config.ts);浏览器半把它作为配置卡片的注册键
|
|
413
413
|
* (插件页配置卡片挂在 row/bundle config 槽位上,与命名空间解耦,
|
|
414
414
|
* 见 shared/config-slots),
|
|
@@ -1125,8 +1125,9 @@ ${extra}
|
|
|
1125
1125
|
*
|
|
1126
1126
|
* 状态行回答的是"我现在到底在跑哪一份 pi-ai"——插件按文件路径动态加载已装 dsh 树
|
|
1127
1127
|
* 里的套件(见 resolve-dsh.ts),manifest 上写的版本**不是**生效版本。这里显示
|
|
1128
|
-
* 生效版本、安装树、目录规模与数据日期、可服务协议、compat
|
|
1129
|
-
*
|
|
1128
|
+
* 生效版本、安装树、目录规模与数据日期、可服务协议、compat 表来源,以及诊断
|
|
1129
|
+
* (按「形态说明 / 降级诊断」分块,避免恒定事实淹没真实降级);版本超出验证区间
|
|
1130
|
+
* 时给出提示(提示而非阻断)。
|
|
1130
1131
|
* @module llm-pi/client/root-fields
|
|
1131
1132
|
*/
|
|
1132
1133
|
/** 时间戳 → 本地日期(秒级精度足够)。 */
|
|
@@ -1154,6 +1155,21 @@ ${extra}
|
|
|
1154
1155
|
if (copy.updatedAt === void 0) return t("officialCopyPending");
|
|
1155
1156
|
return `${copy.path} · ${copy.routes} ${t("officialCopyRoutes")} · ${formatTime(copy.updatedAt, t("runtimeVersionUnknown"))}`;
|
|
1156
1157
|
}
|
|
1158
|
+
/**
|
|
1159
|
+
* 诊断分块:形态说明与降级分开渲染——「官方 src 不随 npm 发布」这类恒定事实
|
|
1160
|
+
* 永不会消失,混在一起会把真正的降级淹掉。空块不渲染。
|
|
1161
|
+
*/
|
|
1162
|
+
function DiagnosticBlock(props) {
|
|
1163
|
+
const messages = props.items.filter((item) => item.level === props.level).map((m) => m.message);
|
|
1164
|
+
if (messages.length === 0) return null;
|
|
1165
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
1166
|
+
className: "lpc-catDetailLabel",
|
|
1167
|
+
children: props.label
|
|
1168
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("pre", {
|
|
1169
|
+
className: "lpc-catJson",
|
|
1170
|
+
children: messages.join("\n")
|
|
1171
|
+
})] });
|
|
1172
|
+
}
|
|
1157
1173
|
function RootFields(props) {
|
|
1158
1174
|
const { t, draft, disabled, kit, onEdit } = props;
|
|
1159
1175
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
|
|
@@ -1205,12 +1221,14 @@ ${extra}
|
|
|
1205
1221
|
className: "lpc-invalid",
|
|
1206
1222
|
children: `${t("runtimeNotice")}:${kit.versionNotice}`
|
|
1207
1223
|
}) : null,
|
|
1208
|
-
kit.diagnostics.length > 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1224
|
+
kit.diagnostics.length > 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(DiagnosticBlock, {
|
|
1225
|
+
label: t("runtimeFormNotes"),
|
|
1226
|
+
level: "info",
|
|
1227
|
+
items: kit.diagnostics
|
|
1228
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(DiagnosticBlock, {
|
|
1229
|
+
label: t("runtimeDiagnostics"),
|
|
1230
|
+
level: "degradation",
|
|
1231
|
+
items: kit.diagnostics
|
|
1214
1232
|
})] }) : null
|
|
1215
1233
|
] })
|
|
1216
1234
|
] });
|
|
@@ -2866,7 +2884,8 @@ ${extra}
|
|
|
2866
2884
|
officialCopyPending: "尚未生成",
|
|
2867
2885
|
officialCopyFailed: "生成失败:",
|
|
2868
2886
|
officialCopyRoutes: "个 route",
|
|
2869
|
-
|
|
2887
|
+
runtimeFormNotes: "形态说明",
|
|
2888
|
+
runtimeDiagnostics: "降级诊断",
|
|
2870
2889
|
runtimeVersionUnknown: "未知",
|
|
2871
2890
|
runtimeCatalogUnit: "个 provider /",
|
|
2872
2891
|
runtimeCatalogModels: "个模型",
|
|
@@ -3000,7 +3019,8 @@ ${extra}
|
|
|
3000
3019
|
officialCopyPending: "not generated yet",
|
|
3001
3020
|
officialCopyFailed: "generation failed: ",
|
|
3002
3021
|
officialCopyRoutes: "routes",
|
|
3003
|
-
|
|
3022
|
+
runtimeFormNotes: "Packaging notes",
|
|
3023
|
+
runtimeDiagnostics: "Degradations",
|
|
3004
3024
|
runtimeVersionUnknown: "unknown",
|
|
3005
3025
|
runtimeCatalogUnit: "providers /",
|
|
3006
3026
|
runtimeCatalogModels: "models",
|
package/lib/index.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ import z from "@deepseek-ai/schemastery";
|
|
|
2
2
|
import { VolatileFields } from "@dsh-plus/shared";
|
|
3
3
|
import { Context } from "@deepseek-ai/cordis";
|
|
4
4
|
//#region src/config.d.ts
|
|
5
|
-
/** settings
|
|
5
|
+
/** settings 命名空间(字面量即合法命名空间,编译期校验;webui 配置卡片与插件运行期读取同一份)。 */
|
|
6
6
|
declare const SETTINGS_NS = "dsh-plus-llm-pi";
|
|
7
7
|
/** 线协议标识;合法集合运行期推导,故此处是开放字符串而非字面量联合。 */
|
|
8
8
|
type ProtocolId = string;
|
|
@@ -89,7 +89,7 @@ interface LlmPiConfig {
|
|
|
89
89
|
* (2 个根字段均有 schema 默认值),解析输出仍是完整的 {@link LlmPiConfig}。
|
|
90
90
|
*/
|
|
91
91
|
type LlmPiConfigInput = Partial<LlmPiConfig>;
|
|
92
|
-
/** 活动字段形态(
|
|
92
|
+
/** 活动字段形态(loader 解析产物:volatile 字段为活动引用)。 */
|
|
93
93
|
type LlmPiConfigFields = VolatileFields<LlmPiConfig>;
|
|
94
94
|
declare const Config: z<LlmPiConfigInput, LlmPiConfigFields>;
|
|
95
95
|
//#endregion
|
package/lib/index.js
CHANGED
|
@@ -24,7 +24,7 @@ import { homedir } from "node:os";
|
|
|
24
24
|
//#region src/config.ts
|
|
25
25
|
/**
|
|
26
26
|
* 配置单一事实源:cordis 行级 Config(组合默认值)与 settings namespace
|
|
27
|
-
|
|
27
|
+
*(用户层=profile 行级覆盖层 cordis.patch.yml,热生效)共用同一
|
|
28
28
|
* schemastery schema。无密钥字段(apiKeyEnv 是凭据引用名而非密钥本身)。
|
|
29
29
|
*
|
|
30
30
|
* 与官方 llm-pi-ai 的差异:
|
|
@@ -35,10 +35,10 @@ import { homedir } from "node:os";
|
|
|
35
35
|
* 官方将来新增协议无需改本插件。
|
|
36
36
|
* @module llm-pi/config
|
|
37
37
|
*/
|
|
38
|
-
/** settings
|
|
38
|
+
/** settings 命名空间(字面量即合法命名空间,编译期校验;webui 配置卡片与插件运行期读取同一份)。 */
|
|
39
39
|
const SETTINGS_NS = "dsh-plus-llm-pi";
|
|
40
40
|
/**
|
|
41
|
-
*
|
|
41
|
+
* 官方适配器不可用/推导失败时的协议兜底三元组。
|
|
42
42
|
* 运行期生效集合来自已安装官方包的 `supportedProtocols()`(见 resolve-dsh.ts),
|
|
43
43
|
* 本常量只用于 schema 描述、浏览器半首帧兜底与推导失败回退。
|
|
44
44
|
*/
|
|
@@ -68,8 +68,6 @@ const DEEPSEEK_REASONING_EFFORTS = [
|
|
|
68
68
|
"high",
|
|
69
69
|
"max"
|
|
70
70
|
];
|
|
71
|
-
/** 旧版 imageDetail 枚举(0.1.2-alpha.1 已移除该字段;仅用于 schema 透传陷阱的取值集)。 */
|
|
72
|
-
const DEEPSEEK_IMAGE_DETAILS = ["auto", "low"];
|
|
73
71
|
/** dsh-timeout 的定时器上限(与官方 MAX_TIMER_DELAY_MS 对齐)。 */
|
|
74
72
|
const MAX_TIMER_DELAY_MS = 2 ** 31 - 1;
|
|
75
73
|
/**
|
|
@@ -103,8 +101,7 @@ const modelEntry = z.object({
|
|
|
103
101
|
reasoningEfforts: z.union([z.const(false), reasoningEfforts]).description("可选 reasoning 档位:false=非推理模型;dict=档位→线值映射;缺省继承内置目录能力"),
|
|
104
102
|
compat: compatDict.description("模型级 compat(字段级合并,压过 route 级与继承值)"),
|
|
105
103
|
imagePixelBudget: z.number().step(1).min(1).description("(仅 adapter: deepseek)单张请求图片的总像素预算;缺省继承官方目录"),
|
|
106
|
-
imageMaxBytes: z.number().step(1).min(1).description("(仅 adapter: deepseek)单张请求图片的编码字节上限;缺省继承官方目录")
|
|
107
|
-
imageDetail: z.union(DEEPSEEK_IMAGE_DETAILS).description("(已移除)图片细节档位;0.1.2-alpha.1 起请改用 imagePixelBudget/imageMaxBytes")
|
|
104
|
+
imageMaxBytes: z.number().step(1).min(1).description("(仅 adapter: deepseek)单张请求图片的编码字节上限;缺省继承官方目录")
|
|
108
105
|
});
|
|
109
106
|
const providerProfile = z.object({
|
|
110
107
|
adapter: z.union(ADAPTER_KINDS).description("路由适配器:pi=PiAiAdapter(默认,协议集合随已装官方适配器推导);deepseek=官方 DeepSeekAdapter(图片走 Files API 文件通道,失败自动降级 base64)").default("pi"),
|
|
@@ -134,7 +131,7 @@ const providerProfile = z.object({
|
|
|
134
131
|
timeoutMs: z.natural().description("HTTP/provider 超时毫秒"),
|
|
135
132
|
websocketConnectTimeoutMs: z.natural().description("WebSocket 连接超时毫秒"),
|
|
136
133
|
streamIdleTimeoutMs: z.number().min(Number.MIN_VALUE).max(MAX_TIMER_DELAY_MS).description("单支流式读取的最大空闲间隔毫秒"),
|
|
137
|
-
maxRequestImageBytes: z.natural().description("单请求 base64 图片载荷上限字节;缺省 20MiB
|
|
134
|
+
maxRequestImageBytes: z.natural().description("单请求 base64 图片载荷上限字节;缺省 20MiB(官方必需字段,旧配置免改)"),
|
|
138
135
|
requestImagePixelBudget: z.number().step(1).min(1).description("单请求每个确定性内联图片版本的像素总预算;缺省 2048x2048(官方同值)"),
|
|
139
136
|
requestImageMaxBytes: z.number().step(1).min(1).description("内联图片版本编码字节目标;缺省 1MiB(官方同值)"),
|
|
140
137
|
retryPolicy: z.any().description("provider 重试策略(dsh-llm RetryPolicy 形状,构建期校验)"),
|
|
@@ -517,7 +514,7 @@ function browseModels(kit, query = {}) {
|
|
|
517
514
|
* 3. **模型条目字段集**:Config schema 的 `providers.*.models` 键集——继承时按此
|
|
518
515
|
* 透传 pi-ai 目录的同名字段,官方将来新增模型级字段即自动跟随。
|
|
519
516
|
*
|
|
520
|
-
*
|
|
517
|
+
* 历史教训(详见 docs/repo/事故记录.md):compat 门控曾是官方的手抄镜像,官方扩容
|
|
521
518
|
* offer 字段而旧表漏收,导致官方可配字段被本插件**误拒**(静默功能缺失、无报错)。
|
|
522
519
|
* 现改为现场推导,`tests/official-surface.test.ts` 直读官方副本守门推导正确性。
|
|
523
520
|
*
|
|
@@ -652,10 +649,18 @@ const FALLBACK_MODEL_ENTRY_FIELDS = [
|
|
|
652
649
|
function fallbackProtocols() {
|
|
653
650
|
return [...FALLBACK_PROTOCOLS];
|
|
654
651
|
}
|
|
655
|
-
/**
|
|
652
|
+
/**
|
|
653
|
+
* 官方门控表不可解析时的兜底快照(0.2.1-alpha.1 现场推导值)。
|
|
654
|
+
*
|
|
655
|
+
* 只在官方改打包形态、`COMPAT_GATES` 解析失败时启用(此时未知键放行、只拦快照里
|
|
656
|
+
* 明确 withhold 的键,见 compat.ts 的「语义分两档」)。快照过期会重新引入
|
|
657
|
+
* 「误拒官方新字段」那类静默故障,故由 tests/official-surface.test.ts 的
|
|
658
|
+
* 「兜底快照不得过期」用例与现场推导逐协议比对守门。
|
|
659
|
+
*/
|
|
656
660
|
const FALLBACK_TABLE = {
|
|
657
661
|
source: "fallback",
|
|
658
662
|
gates: {
|
|
663
|
+
"mistral-conversations": { supportsMidConvoSystemMessages: "withhold" },
|
|
659
664
|
"openai-completions": {
|
|
660
665
|
supportsStore: "offer",
|
|
661
666
|
supportsDeveloperRole: "offer",
|
|
@@ -681,7 +686,8 @@ const FALLBACK_TABLE = {
|
|
|
681
686
|
zaiToolStream: "withhold",
|
|
682
687
|
supportsOpenAIGrammarTools: "withhold",
|
|
683
688
|
sendSessionAffinityHeaders: "withhold",
|
|
684
|
-
|
|
689
|
+
supportsMidConvoSystemMessages: "withhold",
|
|
690
|
+
supportsMidConvoToolAdditions: "withhold",
|
|
685
691
|
sessionAffinityFormat: "withhold"
|
|
686
692
|
},
|
|
687
693
|
"openai-responses": {
|
|
@@ -693,7 +699,32 @@ const FALLBACK_TABLE = {
|
|
|
693
699
|
supportsOpenAIGrammarTools: "withhold",
|
|
694
700
|
supportsAdditionalTools: "withhold",
|
|
695
701
|
supportsToolSearch: "withhold",
|
|
696
|
-
supportsExplicitPromptCacheMode: "withhold"
|
|
702
|
+
supportsExplicitPromptCacheMode: "withhold",
|
|
703
|
+
supportsMidConvoSystemMessages: "withhold"
|
|
704
|
+
},
|
|
705
|
+
"azure-openai-responses": {
|
|
706
|
+
supportsDeveloperRole: "offer",
|
|
707
|
+
supportsMaxOutputTokens: "offer",
|
|
708
|
+
supportsStrictMode: "offer",
|
|
709
|
+
supportsLongCacheRetention: "offer",
|
|
710
|
+
sessionAffinityFormat: "withhold",
|
|
711
|
+
supportsOpenAIGrammarTools: "withhold",
|
|
712
|
+
supportsAdditionalTools: "withhold",
|
|
713
|
+
supportsToolSearch: "withhold",
|
|
714
|
+
supportsExplicitPromptCacheMode: "withhold",
|
|
715
|
+
supportsMidConvoSystemMessages: "withhold"
|
|
716
|
+
},
|
|
717
|
+
"openai-codex-responses": {
|
|
718
|
+
supportsDeveloperRole: "offer",
|
|
719
|
+
supportsMaxOutputTokens: "offer",
|
|
720
|
+
supportsStrictMode: "offer",
|
|
721
|
+
supportsLongCacheRetention: "offer",
|
|
722
|
+
sessionAffinityFormat: "withhold",
|
|
723
|
+
supportsOpenAIGrammarTools: "withhold",
|
|
724
|
+
supportsAdditionalTools: "withhold",
|
|
725
|
+
supportsToolSearch: "withhold",
|
|
726
|
+
supportsExplicitPromptCacheMode: "withhold",
|
|
727
|
+
supportsMidConvoSystemMessages: "withhold"
|
|
697
728
|
},
|
|
698
729
|
"anthropic-messages": {
|
|
699
730
|
supportsEagerToolInputStreaming: "offer",
|
|
@@ -704,10 +735,13 @@ const FALLBACK_TABLE = {
|
|
|
704
735
|
allowEmptySignature: "offer",
|
|
705
736
|
supportsStrictTools: "offer",
|
|
706
737
|
sendSessionAffinityHeaders: "withhold",
|
|
707
|
-
|
|
738
|
+
sessionAffinityFormat: "withhold",
|
|
739
|
+
supportsMidConvoSystemMessages: "withhold",
|
|
740
|
+
supportsMidConvoToolChanges: "withhold",
|
|
708
741
|
supportsMidConvoEffort: "withhold",
|
|
709
742
|
allowedFallbackModels: "withhold"
|
|
710
|
-
}
|
|
743
|
+
},
|
|
744
|
+
"bedrock-converse-stream": { supportsStrictMode: "offer" }
|
|
711
745
|
},
|
|
712
746
|
specs: {
|
|
713
747
|
supportsStore: "boolean",
|
|
@@ -821,7 +855,7 @@ function checkValue(field, spec, value, where) {
|
|
|
821
855
|
}
|
|
822
856
|
/**
|
|
823
857
|
* 校验一份 compat 字典对指定协议合法(对齐官方门控语义 + schema 值约束):
|
|
824
|
-
* - 未知键/withhold
|
|
858
|
+
* - 未知键/withhold 字段拒绝(与官方写时拒绝同款);
|
|
825
859
|
* - 值类型/枚举按官方 schema 校验;
|
|
826
860
|
* - 无值键(null/undefined)拒绝(官方 assertOfferedCompatFields 同款)。
|
|
827
861
|
*/
|
|
@@ -1527,7 +1561,6 @@ function declaredModalities(configured) {
|
|
|
1527
1561
|
/** 物化单个模型目录条目:官方 base 在下,条目显式字段逐字段覆盖。 */
|
|
1528
1562
|
function materializeModel$1(route, entry, deps) {
|
|
1529
1563
|
if (entry.reasoningEfforts !== void 0 || nonEmptyDict(entry.compat)) invalid$1(route, `model "${entry.id}" 的 reasoningEfforts/compat 仅 adapter: pi 可用`);
|
|
1530
|
-
if (entry.imageDetail !== void 0) invalid$1(route, `model "${entry.id}" 的 imageDetail 已随 0.1.2-alpha.1 移除;请改用 imagePixelBudget/imageMaxBytes(低细节可配更小的 imagePixelBudget)并删除 imageDetail`);
|
|
1531
1564
|
const base = resolveOfficialBase(route, entry, deps);
|
|
1532
1565
|
const input = declaredModalities(entry.input) ?? base.input;
|
|
1533
1566
|
const imageFields = {
|
|
@@ -1588,7 +1621,7 @@ function rawAdapterConfig(profile, baseURL, models) {
|
|
|
1588
1621
|
/** 物化单个 deepseek route;lenient 下失败告警并返回 null(调用方跳过注册)。 */
|
|
1589
1622
|
function buildRoute(route, profile, deps) {
|
|
1590
1623
|
try {
|
|
1591
|
-
if (deps.kit.deepseek === void 0) invalid$1(route, "使用 adapter: deepseek,但当前运行时套件不含 dsh-llm-deepseek
|
|
1624
|
+
if (deps.kit.deepseek === void 0) invalid$1(route, "使用 adapter: deepseek,但当前运行时套件不含 dsh-llm-deepseek(本仓基线的必需套件)");
|
|
1592
1625
|
rejectPiOnlyFields(route, profile);
|
|
1593
1626
|
if (profile.extends !== void 0 && profile.extends !== "deepseek") invalid$1(route, `的 extends ${JSON.stringify(profile.extends)} 非法:adapter: deepseek 仅支持 "deepseek"(官方目录)`);
|
|
1594
1627
|
if (profile.apiKeyEnv === void 0 || profile.apiKeyEnv.length === 0) invalid$1(route, "需要 apiKeyEnv:DeepSeekAdapter 无环境自发现,凭据引用必须显式配置");
|
|
@@ -1625,7 +1658,7 @@ function buildDeepseekRoutes(providers, deps) {
|
|
|
1625
1658
|
//#endregion
|
|
1626
1659
|
//#region src/profiles.ts
|
|
1627
1660
|
/**
|
|
1628
|
-
* profile
|
|
1661
|
+
* profile 构建器:插件 Config → 官方 schema 形状的
|
|
1629
1662
|
* 「前置数据源归一化」→ 官方 resolveProfiles(或插件等价兜底)→
|
|
1630
1663
|
* ResolvedPiAiProviderProfile。
|
|
1631
1664
|
*
|
|
@@ -1740,7 +1773,6 @@ function reasoningEffortsFromBase(provider, entry, base) {
|
|
|
1740
1773
|
* 返回 null(调用方跳过该模型)。
|
|
1741
1774
|
*/
|
|
1742
1775
|
function materializeModel(route, profile, entry, base, routeApi, defaultInput, deps) {
|
|
1743
|
-
if (entry.imageDetail !== void 0) invalid(route, `model "${entry.id}" 的 imageDetail 已随 0.1.2-alpha.1 移除;请改用 imagePixelBudget/imageMaxBytes(仅 adapter: deepseek)并删除 imageDetail`);
|
|
1744
1776
|
const api = profile.api ?? base.api ?? routeApi;
|
|
1745
1777
|
if (api === void 0) {
|
|
1746
1778
|
if (deps.lenient) {
|
|
@@ -2434,6 +2466,20 @@ function createOfficialCopyWriter(deps) {
|
|
|
2434
2466
|
status: () => status
|
|
2435
2467
|
};
|
|
2436
2468
|
}
|
|
2469
|
+
//#endregion
|
|
2470
|
+
//#region src/auth-inline.ts
|
|
2471
|
+
/**
|
|
2472
|
+
* PiAiAdapter 认证注入的内联实现(官方 llm-pi-ai/src/auth.ts 的等价移植)。
|
|
2473
|
+
*
|
|
2474
|
+
* 官方 credentialStoreFrom/authContextFrom 仅在 @deepseek-ai/dsh-llm-pi-ai 的
|
|
2475
|
+
* src/auth.ts 子路径导出(包根只导出 recordKeyFor),而 npm 发布形态不携带
|
|
2476
|
+
* src/(lib/index.js 单 bundle)——源码布局优先经 src 子路径走官方实现
|
|
2477
|
+
* (见 resolve-dsh.ts 探测),本文件在其余形态(npm 布局的 dsh 树 /
|
|
2478
|
+
* vendored 兜底)下按官方语义逐行等价实现,并经 assertKitShape 自检兜底。
|
|
2479
|
+
* recordKeyFor 由调用方注入(与 PiAiAdapter 同源模块的包根导出,保证记录
|
|
2480
|
+
* 键格式与官方写入方一致);记录作用域不手抄,由它现场推导(见 recordScopeOf)。
|
|
2481
|
+
* @module llm-pi/auth-inline
|
|
2482
|
+
*/
|
|
2437
2483
|
/** 官方 jsonImage:pi-ai 凭据里显式 undefined 成员 JSON 序列化为缺省/数组 null。 */
|
|
2438
2484
|
function jsonImage(value) {
|
|
2439
2485
|
if (Array.isArray(value)) return value.map((entry) => entry === void 0 ? null : jsonImage(entry));
|
|
@@ -2472,12 +2518,26 @@ function writableStore(ctx) {
|
|
|
2472
2518
|
if (credentials === void 0) throw new LlmError("llm-pi: 当前组合未挂载凭据服务(dsh-credentials-local),登录产生的凭据无处存储", "NO_CREDENTIAL_STORE");
|
|
2473
2519
|
return credentials;
|
|
2474
2520
|
}
|
|
2521
|
+
/** 作用域推导的探针 provider id(合法记录段,故 recordKeyFor 给出完整键)。 */
|
|
2522
|
+
const RECORD_SCOPE_PROBE_ID = "record-scope-probe";
|
|
2523
|
+
/**
|
|
2524
|
+
* 记录作用域的现场推导(**不手抄**官方常量):`recordKeyFor` 由与 PiAiAdapter
|
|
2525
|
+
* 同源的官方包根注入,其产物 `scope/id` 的 scope 段就是官方写入方使用的作用域。
|
|
2526
|
+
* 官方改作用域时此处自动跟随——硬编码镜像一旦落后,{@link credentialStoreFrom}
|
|
2527
|
+
* 的 list() 会把本插件自己的登录记录判成他人的而凭空消失,且无任何报错
|
|
2528
|
+
* (与 compat 门控表手抄镜像同一类故障,见 docs/repo/事故记录.md)。
|
|
2529
|
+
*/
|
|
2530
|
+
function recordScopeOf(recordKeyFor) {
|
|
2531
|
+
return credentialKeyScope(recordKeyFor(RECORD_SCOPE_PROBE_ID));
|
|
2532
|
+
}
|
|
2475
2533
|
/**
|
|
2476
2534
|
* pi-ai `CredentialStore`(官方 credentialStoreFrom 等价实现)。
|
|
2477
2535
|
* 路由键任意而记录 id 受语法约束:语法外的 id 读答"未存储"、删除无事可做、
|
|
2478
|
-
* modify 拒绝(写不落地不能报成功)。
|
|
2536
|
+
* modify 拒绝(写不落地不能报成功)。list() 的归属判定用现场推导的作用域
|
|
2537
|
+
* ({@link recordScopeOf}),不比对硬编码常量。
|
|
2479
2538
|
*/
|
|
2480
2539
|
function credentialStoreFrom(ctx, recordKeyFor) {
|
|
2540
|
+
const recordScope = recordScopeOf(recordKeyFor);
|
|
2481
2541
|
return {
|
|
2482
2542
|
async read(providerId) {
|
|
2483
2543
|
const credentials = ctx.get("credentials");
|
|
@@ -2489,7 +2549,7 @@ function credentialStoreFrom(ctx, recordKeyFor) {
|
|
|
2489
2549
|
const stored = await ctx.get("credentials")?.listRecords() ?? [];
|
|
2490
2550
|
const mine = [];
|
|
2491
2551
|
for (const entry of stored) {
|
|
2492
|
-
if (credentialKeyScope(entry.key) !==
|
|
2552
|
+
if (credentialKeyScope(entry.key) !== recordScope) continue;
|
|
2493
2553
|
mine.push({
|
|
2494
2554
|
providerId: credentialKeyId(entry.key),
|
|
2495
2555
|
type: entry.kind === "api-key" ? "api_key" : "oauth"
|
|
@@ -2558,15 +2618,40 @@ function authContextFrom(ctx) {
|
|
|
2558
2618
|
* 模型条目字段集同样现场推导(official-surface.ts)。生效版本只用于状态行显示,
|
|
2559
2619
|
* 超出已验证区间也只是提示(kit-meta.ts),永不阻断。
|
|
2560
2620
|
*
|
|
2561
|
-
*
|
|
2562
|
-
* - resolveProfiles(config.ts
|
|
2621
|
+
* 仅 src 子路径导出、包根不导出的两块面:
|
|
2622
|
+
* - resolveProfiles(config.ts):官方解析链,源码布局可经 src 子路径复用;
|
|
2563
2623
|
* - credentialStoreFrom/authContextFrom(auth.ts):PiAiAdapter 必需 auth 注入。
|
|
2564
2624
|
* npm 发布形态(lib/index.js 单 bundle + 无 src/)两者都拿不到:dsh 树优先
|
|
2565
2625
|
* 探测 src/*(含 lib/* 候选),未命中时 resolveProfiles 走插件等价实现
|
|
2566
|
-
* (profiles.ts
|
|
2567
|
-
* (auth-inline.ts,recordKeyFor
|
|
2626
|
+
* (profiles.ts,语义对齐官方 config.ts:resolveProfiles)、auth 走内联等价实现
|
|
2627
|
+
* (auth-inline.ts,recordKeyFor 自包根导出同源注入、记录作用域由它现场推导)。
|
|
2628
|
+
* 这是**打包形态的恒定事实而非降级**,故按 info 档记入诊断(missingSourceNote),
|
|
2629
|
+
* 免得淹没同面板里真正的降级;等价实现由形状自检与单测兜底。
|
|
2568
2630
|
* @module llm-pi/resolve-dsh
|
|
2569
2631
|
*/
|
|
2632
|
+
/** 生成一条降级诊断(推导失败 / 加载回退)。 */
|
|
2633
|
+
function degradation(message) {
|
|
2634
|
+
return {
|
|
2635
|
+
level: "degradation",
|
|
2636
|
+
message
|
|
2637
|
+
};
|
|
2638
|
+
}
|
|
2639
|
+
/**
|
|
2640
|
+
* 官方 `src/` 子路径未随 npm 发布携带时的**形态说明**(info 档)。
|
|
2641
|
+
*
|
|
2642
|
+
* 官方 `resolveProfiles`(src/config.ts)与认证助手(src/auth.ts)只在子路径导出、
|
|
2643
|
+
* 包根不导出,而发布清单只含 `lib/index.js` + `lib/types/**`——任何 npm 安装形态都
|
|
2644
|
+
* 拿不到,故这两块常走插件等价实现。此处逐面列出实际走等价实现的部分,并点明
|
|
2645
|
+
* **仍取自官方现场推导**的部分(compat 门控 / 协议 / 模型字段集),避免被读成
|
|
2646
|
+
* "自动跟随失败"。
|
|
2647
|
+
* @param surfaces 走等价实现的官方面名称(如 `profile 解析`)。
|
|
2648
|
+
*/
|
|
2649
|
+
function missingSourceNote(surfaces) {
|
|
2650
|
+
return {
|
|
2651
|
+
level: "info",
|
|
2652
|
+
message: `官方 @deepseek-ai/dsh-llm-pi-ai 只经 src/ 子路径导出、npm 发布形态不携带 src/:${surfaces.join("、")}使用插件等价实现;compat 门控 / 协议集合 / 模型条目字段集仍取自官方安装副本现场推导`
|
|
2653
|
+
};
|
|
2654
|
+
}
|
|
2570
2655
|
/** kit 必备形状清单:缺失即视为上游不兼容。 */
|
|
2571
2656
|
function assertKitShape(kit, origin) {
|
|
2572
2657
|
const problems = [];
|
|
@@ -2592,6 +2677,7 @@ function assertKitShape(kit, origin) {
|
|
|
2592
2677
|
if (typeof kit.resolveProfiles !== "function") problems.push("resolveProfiles 缺失");
|
|
2593
2678
|
if (typeof kit.resolveImageAttachmentAccess !== "function") problems.push("resolveImageAttachmentAccess 缺失");
|
|
2594
2679
|
if (typeof kit.auth?.credentialStoreFrom !== "function" || typeof kit.auth?.authContextFrom !== "function") problems.push("auth 助手(credentialStoreFrom/authContextFrom)缺失");
|
|
2680
|
+
if (typeof kit.recordKeyFor !== "function") problems.push("recordKeyFor 缺失");
|
|
2595
2681
|
if (problems.length > 0) throw new Error(`llm-pi: ${origin} 来源的运行时套件形状不兼容:${problems.join(";")}`);
|
|
2596
2682
|
}
|
|
2597
2683
|
/** deepseek 模块形状自检;返回问题清单(空 = 可用),由调用方决定降级。 */
|
|
@@ -2696,7 +2782,7 @@ async function loadFallbackTreeFactories(root, diagnostics) {
|
|
|
2696
2782
|
if (factory !== void 0) out[api] = factory;
|
|
2697
2783
|
} catch {}
|
|
2698
2784
|
}
|
|
2699
|
-
if (Object.keys(out).length < fallbackProtocols().length) diagnostics.push(`pi-ai 协议兜底三元组未能全部加载(${Object.keys(out).join("/") || "空"});请检查 dsh 安装树里 @earendil-works/pi-ai/dist/api 的形态`);
|
|
2785
|
+
if (Object.keys(out).length < fallbackProtocols().length) diagnostics.push(degradation(`pi-ai 协议兜底三元组未能全部加载(${Object.keys(out).join("/") || "空"});请检查 dsh 安装树里 @earendil-works/pi-ai/dist/api 的形态`));
|
|
2700
2786
|
return out;
|
|
2701
2787
|
}
|
|
2702
2788
|
/**
|
|
@@ -2709,25 +2795,25 @@ async function loadTreeProtocols(root, derived, diagnostics) {
|
|
|
2709
2795
|
for (const api of derived) {
|
|
2710
2796
|
const file = join(dir, `${api}.lazy.js`);
|
|
2711
2797
|
if (!existsSync(file)) {
|
|
2712
|
-
diagnostics.push(`pi-ai 未提供协议 "${api}" 的惰性实现(缺 ${file});该协议不可用,其余协议不受影响`);
|
|
2798
|
+
diagnostics.push(degradation(`pi-ai 未提供协议 "${api}" 的惰性实现(缺 ${file});该协议不可用,其余协议不受影响`));
|
|
2713
2799
|
continue;
|
|
2714
2800
|
}
|
|
2715
2801
|
try {
|
|
2716
2802
|
const factory = protocolFactoryOf(await import(pathToFileURL(file).href));
|
|
2717
2803
|
if (factory === void 0) {
|
|
2718
|
-
diagnostics.push(`协议 "${api}" 的实现模块未导出唯一 *Api 工厂;该协议不可用`);
|
|
2804
|
+
diagnostics.push(degradation(`协议 "${api}" 的实现模块未导出唯一 *Api 工厂;该协议不可用`));
|
|
2719
2805
|
continue;
|
|
2720
2806
|
}
|
|
2721
2807
|
out[api] = factory;
|
|
2722
2808
|
} catch (error) {
|
|
2723
|
-
diagnostics.push(`协议 "${api}" 的实现加载失败(${error instanceof Error ? error.message : String(error)});该协议不可用`);
|
|
2809
|
+
diagnostics.push(degradation(`协议 "${api}" 的实现加载失败(${error instanceof Error ? error.message : String(error)});该协议不可用`));
|
|
2724
2810
|
}
|
|
2725
2811
|
}
|
|
2726
2812
|
if (Object.keys(out).length > 0) return {
|
|
2727
2813
|
protocols: derived.filter((api) => out[api] !== void 0),
|
|
2728
2814
|
protocolFactories: out
|
|
2729
2815
|
};
|
|
2730
|
-
diagnostics.push("官方声明的协议一个都加载不到;回退内置三元组");
|
|
2816
|
+
diagnostics.push(degradation("官方声明的协议一个都加载不到;回退内置三元组"));
|
|
2731
2817
|
const fallback = await loadFallbackTreeFactories(root, diagnostics);
|
|
2732
2818
|
return {
|
|
2733
2819
|
protocols: fallbackProtocols().filter((api) => fallback[api] !== void 0),
|
|
@@ -2773,7 +2859,7 @@ function installOfficialSurface(options) {
|
|
|
2773
2859
|
try {
|
|
2774
2860
|
const gates = deriveGates(readFileSync(bundlePath, "utf8"));
|
|
2775
2861
|
if (gates === void 0) {
|
|
2776
|
-
diagnostics.push(`${compatLabel}未能从官方 bundle 解析 COMPAT_GATES(${bundlePath});使用内置快照(未知字段放行、withhold 仍拒绝;请检查 dsh-llm-pi-ai 打包形态)`);
|
|
2862
|
+
diagnostics.push(degradation(`${compatLabel}未能从官方 bundle 解析 COMPAT_GATES(${bundlePath});使用内置快照(未知字段放行、withhold 仍拒绝;请检查 dsh-llm-pi-ai 打包形态)`));
|
|
2777
2863
|
installCompatTable(FALLBACK_TABLE);
|
|
2778
2864
|
} else installCompatTable({
|
|
2779
2865
|
gates,
|
|
@@ -2785,13 +2871,13 @@ function installOfficialSurface(options) {
|
|
|
2785
2871
|
});
|
|
2786
2872
|
} catch (error) {
|
|
2787
2873
|
const reason = error instanceof Error ? error.message : String(error);
|
|
2788
|
-
diagnostics.push(`${compatLabel}推导失败(${reason});使用内置快照(未知字段放行)`);
|
|
2874
|
+
diagnostics.push(degradation(`${compatLabel}推导失败(${reason});使用内置快照(未知字段放行)`));
|
|
2789
2875
|
installCompatTable(FALLBACK_TABLE);
|
|
2790
2876
|
}
|
|
2791
2877
|
const derivedProtocols = deriveProtocols(adapterModule);
|
|
2792
|
-
if (derivedProtocols === void 0) diagnostics.push(`${origin}:官方 supportedProtocols() 不可用;协议集合回退内置三元组 ${fallbackProtocols().join("/")}`);
|
|
2878
|
+
if (derivedProtocols === void 0) diagnostics.push(degradation(`${origin}:官方 supportedProtocols() 不可用;协议集合回退内置三元组 ${fallbackProtocols().join("/")}`));
|
|
2793
2879
|
const fields = deriveModelEntryFields(adapterModule);
|
|
2794
|
-
if (fields === void 0) diagnostics.push(`${origin}:官方 Config schema 的模型条目字段集不可推导;继承字段回退已知键 ${FALLBACK_MODEL_ENTRY_FIELDS.join("/")}(官方新增字段可能不被继承)`);
|
|
2880
|
+
if (fields === void 0) diagnostics.push(degradation(`${origin}:官方 Config schema 的模型条目字段集不可推导;继承字段回退已知键 ${FALLBACK_MODEL_ENTRY_FIELDS.join("/")}(官方新增字段可能不被继承)`));
|
|
2795
2881
|
const generatedAt = catalogGeneratedAtOf(options.catalogModule);
|
|
2796
2882
|
return {
|
|
2797
2883
|
protocols: derivedProtocols ?? fallbackProtocols(),
|
|
@@ -2833,7 +2919,8 @@ function kitFromTree(options) {
|
|
|
2833
2919
|
credentialStoreFrom: officialCredentialStoreFrom !== void 0 ? officialCredentialStoreFrom : (ctx) => credentialStoreFrom(ctx, recordKeyFor),
|
|
2834
2920
|
authContextFrom: officialAuthContextFrom !== void 0 ? officialAuthContextFrom : authContextFrom
|
|
2835
2921
|
},
|
|
2836
|
-
resolveImageAttachmentAccess: mods.llm["resolveImageAttachmentAccess"]
|
|
2922
|
+
resolveImageAttachmentAccess: mods.llm["resolveImageAttachmentAccess"],
|
|
2923
|
+
recordKeyFor
|
|
2837
2924
|
};
|
|
2838
2925
|
}
|
|
2839
2926
|
/** vendored 兜底副本的 deepseek 模块(形状自检不过时返回 undefined)。 */
|
|
@@ -2867,7 +2954,7 @@ function vendoredProtocolFactories() {
|
|
|
2867
2954
|
* npm 发布形态不携带 src/、lib 仅 index.js/invariant.js——resolveProfiles 与
|
|
2868
2955
|
* auth 助手在此无条件走插件等价实现(内联,见文件头说明);compat 门控表则
|
|
2869
2956
|
* 仍从 vendored 副本的 bundle + Config schema 现场推导(与 dsh 树同一推导链)。
|
|
2870
|
-
* @param diagnostics
|
|
2957
|
+
* @param diagnostics 可选诊断收集器(回退原因、形态说明与逐项降级)。
|
|
2871
2958
|
*/
|
|
2872
2959
|
function loadVendoredKit(diagnostics = []) {
|
|
2873
2960
|
const staticFactories = vendoredProtocolFactories();
|
|
@@ -2913,9 +3000,11 @@ function loadVendoredKit(diagnostics = []) {
|
|
|
2913
3000
|
authContextFrom
|
|
2914
3001
|
},
|
|
2915
3002
|
resolveImageAttachmentAccess: vendoredLlm.resolveImageAttachmentAccess,
|
|
3003
|
+
recordKeyFor: vendoredPiAiAdapter.recordKeyFor,
|
|
2916
3004
|
...deepseek === void 0 ? {} : { deepseek }
|
|
2917
3005
|
};
|
|
2918
3006
|
assertKitShape(kit, "vendored");
|
|
3007
|
+
diagnostics.push(missingSourceNote(["profile 解析", "认证助手"]));
|
|
2919
3008
|
return kit;
|
|
2920
3009
|
}
|
|
2921
3010
|
/**
|
|
@@ -2939,7 +3028,8 @@ function dshTreeAnchor(installAnchor, argvEntry = process.argv[1]) {
|
|
|
2939
3028
|
/**
|
|
2940
3029
|
* 解析运行时套件:优先 dsh 安装树(自动跟随上游),失败回退 vendored 副本;
|
|
2941
3030
|
* 两者都过不了形状自检时抛错(调用方应记日志并放弃注册 route)。
|
|
2942
|
-
* 返回的 diagnostics
|
|
3031
|
+
* 返回的 diagnostics 记录回退原因、打包形态说明(info)与逐项降级(degradation),
|
|
3032
|
+
* 供配置卡片与日志分档展示。
|
|
2943
3033
|
* @param installAnchor profile 的 dsh 安装锚点(`ctx.profileContext.installAnchor`)。
|
|
2944
3034
|
*/
|
|
2945
3035
|
async function resolveDshKit(installAnchor) {
|
|
@@ -2969,8 +3059,10 @@ async function resolveDshKit(installAnchor) {
|
|
|
2969
3059
|
versions: collectTreeVersions(anchor)
|
|
2970
3060
|
});
|
|
2971
3061
|
assertKitShape(kit, "dsh-tree");
|
|
2972
|
-
|
|
2973
|
-
if (config === void 0)
|
|
3062
|
+
const missingSeams = [];
|
|
3063
|
+
if (config === void 0) missingSeams.push("profile 解析");
|
|
3064
|
+
if (auth === void 0) missingSeams.push("认证助手");
|
|
3065
|
+
if (missingSeams.length > 0) diagnostics.push(missingSourceNote(missingSeams));
|
|
2974
3066
|
const tree = await importTreeDeepseek(anchor);
|
|
2975
3067
|
if (tree.kit !== void 0) return {
|
|
2976
3068
|
kit: {
|
|
@@ -2979,17 +3071,17 @@ async function resolveDshKit(installAnchor) {
|
|
|
2979
3071
|
},
|
|
2980
3072
|
diagnostics
|
|
2981
3073
|
};
|
|
2982
|
-
diagnostics.push(`dsh 安装树的 dsh-llm-deepseek 不可用(${tree.problem ?? "未知原因"});adapter: deepseek 的 route 不可用,pi 路由不受影响`);
|
|
3074
|
+
diagnostics.push(degradation(`dsh 安装树的 dsh-llm-deepseek 不可用(${tree.problem ?? "未知原因"});adapter: deepseek 的 route 不可用,pi 路由不受影响`));
|
|
2983
3075
|
return {
|
|
2984
3076
|
kit,
|
|
2985
3077
|
diagnostics
|
|
2986
3078
|
};
|
|
2987
3079
|
} catch (error) {
|
|
2988
|
-
diagnostics.push(`dsh 安装树套件不可用(${anchor}):${error instanceof Error ? error.message : String(error)};回退 vendored 副本`);
|
|
3080
|
+
diagnostics.push(degradation(`dsh 安装树套件不可用(${anchor}):${error instanceof Error ? error.message : String(error)};回退 vendored 副本`));
|
|
2989
3081
|
}
|
|
2990
|
-
} else diagnostics.push("未能从 profileContext.installAnchor / process.argv[1] 定位 dsh 安装树;回退 vendored 副本");
|
|
3082
|
+
} else diagnostics.push(degradation("未能从 profileContext.installAnchor / process.argv[1] 定位 dsh 安装树;回退 vendored 副本"));
|
|
2991
3083
|
const kit = loadVendoredKit(diagnostics);
|
|
2992
|
-
if (kit.deepseek === void 0) diagnostics.push("vendored 副本的 dsh-llm-deepseek 形状不兼容;adapter: deepseek 的 route 不可用");
|
|
3084
|
+
if (kit.deepseek === void 0) diagnostics.push(degradation("vendored 副本的 dsh-llm-deepseek 形状不兼容;adapter: deepseek 的 route 不可用"));
|
|
2993
3085
|
return {
|
|
2994
3086
|
kit,
|
|
2995
3087
|
diagnostics
|
|
@@ -3016,10 +3108,11 @@ function makeResolveApiKey(ctx, kit) {
|
|
|
3016
3108
|
throw new kit.LlmError(`llm-pi: provider route "${provider}" 的凭据引用 ${String(ref)} 未解析到值——请经凭据服务(web Models 页)存放或导出环境变量;仅当该 provider 应使用 pi-ai 自有环境发现时才移除 apiKeyEnv`, "MISSING_CREDENTIAL");
|
|
3017
3109
|
};
|
|
3018
3110
|
}
|
|
3019
|
-
/**
|
|
3111
|
+
/** 解析运行期套件并落启动日志(来源/生效版本/协议/形态说明与逐项降级)。 */
|
|
3020
3112
|
async function loadRuntimeKit(ctx, logger) {
|
|
3021
3113
|
const { kit, diagnostics } = await resolveDshKit(ctx.get("profileContext")?.installAnchor);
|
|
3022
|
-
for (const
|
|
3114
|
+
for (const item of diagnostics) if (item.level === "info") logger.info(item.message);
|
|
3115
|
+
else logger.warn(item.message);
|
|
3023
3116
|
logger.info(`运行时套件来源:${kit.source};pi-ai ${kit.versions.piAi ?? "?"} / dsh-llm-pi-ai ${kit.versions.piAiAdapter ?? "?"};协议 ${kit.protocols.join("/")}`);
|
|
3024
3117
|
const versionNotice = piAiVersionNotice(kit.versions.piAi);
|
|
3025
3118
|
if (versionNotice !== void 0) logger.warn(versionNotice);
|
|
@@ -3285,8 +3378,8 @@ async function startRuntime(ctx, rawConfig) {
|
|
|
3285
3378
|
officialCopy: copy,
|
|
3286
3379
|
diagnostics: [
|
|
3287
3380
|
...diagnostics,
|
|
3288
|
-
...copy.warnings.map((warning) => `应急副本:${warning}`),
|
|
3289
|
-
...copy.error === void 0 ? [] : [`应急副本:生成失败(${copy.error})`]
|
|
3381
|
+
...copy.warnings.map((warning) => degradation(`应急副本:${warning}`)),
|
|
3382
|
+
...copy.error === void 0 ? [] : [degradation(`应急副本:生成失败(${copy.error})`)]
|
|
3290
3383
|
]
|
|
3291
3384
|
};
|
|
3292
3385
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dsh-plus/llm-pi",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.2",
|
|
4
4
|
"description": "dsh-plus service+ui plugin: 基于 PiAiAdapter 的自定义 LLM 路由(全量 compat、模型继承、pi-ai 内置目录;协议/compat/字段集现场推导,自动跟随已装 dsh)",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "lib/index.js",
|
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
},
|
|
33
33
|
"dependencies": {
|
|
34
34
|
"yaml": "^2.9.0",
|
|
35
|
-
"@dsh-plus/shared": "0.1.
|
|
35
|
+
"@dsh-plus/shared": "0.1.37"
|
|
36
36
|
},
|
|
37
37
|
"peerDependencies": {
|
|
38
38
|
"@deepseek-ai/cordis": "^4.0.5-alpha.1",
|