@dsh-plus/llm-pi 0.1.35 → 0.1.37
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/index.js +33 -15
- package/package.json +28 -27
- package/src/deepseek-routes.ts +13 -1
- package/src/resolve-dsh.ts +31 -11
- package/src/service.ts +4 -1
package/lib/index.js
CHANGED
|
@@ -815,7 +815,13 @@ var DeepseekRouteRegistrar = class {
|
|
|
815
815
|
if (current === void 0) throw new kit.LlmError(`llm-pi: deepseek route "${route}" 已注销`, "INVALID_REQUEST");
|
|
816
816
|
return current.connection;
|
|
817
817
|
},
|
|
818
|
-
|
|
818
|
+
resolveAuth: (async (connection) => ({ headers: { "x-api-key": await this.resolveApiKey(connection) } })),
|
|
819
|
+
discoverModels: (provider) => {
|
|
820
|
+
const connection = routes().get(route)?.connection ?? built.connection;
|
|
821
|
+
const catalogModelInfo = kit.deepseek?.catalogModelInfo;
|
|
822
|
+
if (catalogModelInfo === void 0) return Promise.resolve([]);
|
|
823
|
+
return Promise.resolve(connection.models.map((model) => catalogModelInfo(provider, model)));
|
|
824
|
+
},
|
|
819
825
|
resolveUserId: () => this.resolveUserId(),
|
|
820
826
|
resolveAttachments: () => ctx.get("attachments"),
|
|
821
827
|
resolveImageAccess: (attachments, ref) => kit.resolveImageAttachmentAccess(attachments, (hostPath) => ctx.get("fs")?.processPathFromHostPath(hostPath), ref),
|
|
@@ -1803,9 +1809,9 @@ function authContextFrom(ctx) {
|
|
|
1803
1809
|
* dsh-llm-pi-ai / dsh-llm / pi-ai 之上,从而 dsh 升级即自动跟随上游。
|
|
1804
1810
|
*
|
|
1805
1811
|
* 解析策略(全部模块同源地整体成功或整体回退,杜绝跨源混用):
|
|
1806
|
-
* 1. dsh-tree
|
|
1807
|
-
*
|
|
1808
|
-
* node_modules/@deepseek-ai/dsh-llm-pi-ai 与 node_modules/@earendil-works/pi-ai
|
|
1812
|
+
* 1. dsh-tree:锚点链 = profileContext.installAnchor(CLI/桌面端同一事实,
|
|
1813
|
+
* 桌面端 Electron 下 argv[1] 探测走不通)→ realpath(argv[1]) 向上找到同时
|
|
1814
|
+
* 含 node_modules/@deepseek-ai/dsh-llm-pi-ai 与 node_modules/@earendil-works/pi-ai
|
|
1809
1815
|
* 的目录,按文件路径动态 import——与 dsh 官方插件共享同一模块实例;
|
|
1810
1816
|
* 2. vendored:回退到本插件 dependencies 里的固定版本副本(裸 import)。
|
|
1811
1817
|
*
|
|
@@ -1851,6 +1857,7 @@ function checkDeepseekShape(kit) {
|
|
|
1851
1857
|
if (typeof kit.DeepSeekAdapter !== "function") problems.push("DeepSeekAdapter 不是类");
|
|
1852
1858
|
else if (typeof kit.DeepSeekAdapter.prototype["stream"] !== "function") problems.push("DeepSeekAdapter.prototype.stream 缺失");
|
|
1853
1859
|
if (typeof kit.resolveAdapterOptions !== "function") problems.push("resolveAdapterOptions 缺失");
|
|
1860
|
+
if (typeof kit.catalogModelInfo !== "function") problems.push("catalogModelInfo 缺失");
|
|
1854
1861
|
if (typeof kit.getOrCreateAnonymousUserId !== "function") problems.push("getOrCreateAnonymousUserId 缺失");
|
|
1855
1862
|
return problems;
|
|
1856
1863
|
}
|
|
@@ -1915,7 +1922,8 @@ async function importTreeDeepseek(root) {
|
|
|
1915
1922
|
const kit = {
|
|
1916
1923
|
DeepSeekAdapter: deepseek["DeepSeekAdapter"],
|
|
1917
1924
|
resolveAdapterOptions: deepseek["resolveAdapterOptions"],
|
|
1918
|
-
getOrCreateAnonymousUserId: anonId["getOrCreateAnonymousUserId"]
|
|
1925
|
+
getOrCreateAnonymousUserId: anonId["getOrCreateAnonymousUserId"],
|
|
1926
|
+
catalogModelInfo: deepseek["catalogModelInfo"]
|
|
1919
1927
|
};
|
|
1920
1928
|
const problems = checkDeepseekShape(kit);
|
|
1921
1929
|
if (problems.length > 0) return { problem: `形状不兼容:${problems.join(";")}` };
|
|
@@ -2001,7 +2009,8 @@ function loadVendoredDeepseek() {
|
|
|
2001
2009
|
const kit = {
|
|
2002
2010
|
DeepSeekAdapter: vendoredDeepseek.DeepSeekAdapter,
|
|
2003
2011
|
resolveAdapterOptions: vendoredDeepseek.resolveAdapterOptions,
|
|
2004
|
-
getOrCreateAnonymousUserId: vendoredAnonId.getOrCreateAnonymousUserId
|
|
2012
|
+
getOrCreateAnonymousUserId: vendoredAnonId.getOrCreateAnonymousUserId,
|
|
2013
|
+
catalogModelInfo: vendoredDeepseek.catalogModelInfo
|
|
2005
2014
|
};
|
|
2006
2015
|
return checkDeepseekShape(kit).length === 0 ? kit : void 0;
|
|
2007
2016
|
}
|
|
@@ -2055,12 +2064,20 @@ function loadVendoredKit() {
|
|
|
2055
2064
|
assertKitShape(kit, "vendored");
|
|
2056
2065
|
return kit;
|
|
2057
2066
|
}
|
|
2058
|
-
/**
|
|
2059
|
-
|
|
2060
|
-
|
|
2061
|
-
|
|
2067
|
+
/**
|
|
2068
|
+
* 定位 dsh 安装树根:优先 `profileContext.installAnchor`(CLI 与桌面端同一
|
|
2069
|
+
* 事实——桌面端 Electron 启动时 argv[1] 是 Electron 自身、走不通 argv 探测,
|
|
2070
|
+
* 锚点是唯一可靠来源),其次 realpath(argv[1]) 向上查找;均失败返回 undefined。
|
|
2071
|
+
* argvEntry 参数仅测试注入(缺省 process.argv[1])。
|
|
2072
|
+
*/
|
|
2073
|
+
function dshTreeAnchor(installAnchor, argvEntry = process.argv[1]) {
|
|
2074
|
+
if (installAnchor !== void 0 && installAnchor.length > 0) {
|
|
2075
|
+
const anchored = findDshTreeRoot(dirname(installAnchor));
|
|
2076
|
+
if (anchored !== void 0) return anchored;
|
|
2077
|
+
}
|
|
2078
|
+
if (argvEntry === void 0) return void 0;
|
|
2062
2079
|
try {
|
|
2063
|
-
return findDshTreeRoot(dirname(realpathSync(
|
|
2080
|
+
return findDshTreeRoot(dirname(realpathSync(argvEntry)));
|
|
2064
2081
|
} catch {
|
|
2065
2082
|
return;
|
|
2066
2083
|
}
|
|
@@ -2069,10 +2086,11 @@ function dshTreeAnchor() {
|
|
|
2069
2086
|
* 解析运行时套件:优先 dsh 安装树(自动跟随上游),失败回退 vendored 副本;
|
|
2070
2087
|
* 两者都过不了形状自检时抛错(调用方应记日志并放弃注册 route)。
|
|
2071
2088
|
* 返回的 diagnostics 记录回退原因,供配置卡片与日志展示。
|
|
2089
|
+
* @param installAnchor profile 的 dsh 安装锚点(`ctx.profileContext.installAnchor`)。
|
|
2072
2090
|
*/
|
|
2073
|
-
async function resolveDshKit() {
|
|
2091
|
+
async function resolveDshKit(installAnchor) {
|
|
2074
2092
|
const diagnostics = [];
|
|
2075
|
-
const anchor = dshTreeAnchor();
|
|
2093
|
+
const anchor = dshTreeAnchor(installAnchor);
|
|
2076
2094
|
if (anchor !== void 0) {
|
|
2077
2095
|
const treePkgDir = join(anchor, "node_modules", "@deepseek-ai", "dsh-llm-pi-ai");
|
|
2078
2096
|
try {
|
|
@@ -2099,7 +2117,7 @@ async function resolveDshKit() {
|
|
|
2099
2117
|
} catch (error) {
|
|
2100
2118
|
diagnostics.push(`dsh 安装树套件不可用(${anchor}):${error instanceof Error ? error.message : String(error)};回退 vendored 副本`);
|
|
2101
2119
|
}
|
|
2102
|
-
} else diagnostics.push("未能从 process.argv[1] 定位 dsh 安装树;回退 vendored 副本");
|
|
2120
|
+
} else diagnostics.push("未能从 profileContext.installAnchor / process.argv[1] 定位 dsh 安装树;回退 vendored 副本");
|
|
2103
2121
|
const kit = loadVendoredKit();
|
|
2104
2122
|
if (kit.deepseek === void 0) diagnostics.push("vendored 副本的 dsh-llm-deepseek 形状不兼容;adapter: deepseek 的 route 不可用");
|
|
2105
2123
|
return {
|
|
@@ -2132,7 +2150,7 @@ function makeResolveApiKey(ctx, kit) {
|
|
|
2132
2150
|
async function startRuntime(ctx, rawConfig) {
|
|
2133
2151
|
const logger = ctx.logger("llm-pi");
|
|
2134
2152
|
const fields = hasVolatileRefs(rawConfig) ? rawConfig : Config(rawConfig ?? {});
|
|
2135
|
-
const { kit, diagnostics } = await resolveDshKit();
|
|
2153
|
+
const { kit, diagnostics } = await resolveDshKit(ctx.get("profileContext")?.installAnchor);
|
|
2136
2154
|
for (const line of diagnostics) logger.warn(line);
|
|
2137
2155
|
logger.info(`运行时套件来源:${kit.source}`);
|
|
2138
2156
|
let snapshot = unwrapVolatile(fields);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dsh-plus/llm-pi",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.37",
|
|
4
4
|
"description": "dsh-plus service+ui plugin: 基于 PiAiAdapter 的自定义 LLM 路由(全量 compat、模型继承、models.dev 目录兜底)",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "lib/index.js",
|
|
@@ -32,40 +32,41 @@
|
|
|
32
32
|
},
|
|
33
33
|
"dependencies": {
|
|
34
34
|
"https-proxy-agent": "^9.1.0",
|
|
35
|
-
"@dsh-plus/shared": "0.1.
|
|
35
|
+
"@dsh-plus/shared": "0.1.27"
|
|
36
36
|
},
|
|
37
37
|
"peerDependencies": {
|
|
38
38
|
"@deepseek-ai/cordis": "^4.0.4",
|
|
39
|
-
"@deepseek-ai/dsh-anonymous-user-id": "^0.
|
|
40
|
-
"@deepseek-ai/dsh-credentials": "^0.
|
|
41
|
-
"@deepseek-ai/dsh-home-paths": "^0.
|
|
42
|
-
"@deepseek-ai/dsh-host-webserver": "^0.
|
|
43
|
-
"@deepseek-ai/dsh-launch-environment": "^0.
|
|
44
|
-
"@deepseek-ai/dsh-llm": "^0.
|
|
45
|
-
"@deepseek-ai/dsh-llm-deepseek": "^0.
|
|
46
|
-
"@deepseek-ai/dsh-llm-pi-ai": "^0.
|
|
47
|
-
"@deepseek-ai/dsh-settings": "^0.
|
|
48
|
-
"@deepseek-ai/dsh-util-values": "^0.
|
|
39
|
+
"@deepseek-ai/dsh-anonymous-user-id": "^0.2.0-rc.1",
|
|
40
|
+
"@deepseek-ai/dsh-credentials": "^0.2.0-rc.1",
|
|
41
|
+
"@deepseek-ai/dsh-home-paths": "^0.2.0-rc.1",
|
|
42
|
+
"@deepseek-ai/dsh-host-webserver": "^0.2.0-rc.1",
|
|
43
|
+
"@deepseek-ai/dsh-launch-environment": "^0.2.0-rc.1",
|
|
44
|
+
"@deepseek-ai/dsh-llm": "^0.2.0-rc.1",
|
|
45
|
+
"@deepseek-ai/dsh-llm-deepseek": "^0.2.0-rc.1",
|
|
46
|
+
"@deepseek-ai/dsh-llm-pi-ai": "^0.2.0-rc.1",
|
|
47
|
+
"@deepseek-ai/dsh-settings": "^0.2.0-rc.1",
|
|
48
|
+
"@deepseek-ai/dsh-util-values": "^0.2.0-rc.1",
|
|
49
49
|
"@deepseek-ai/schemastery": "^3.18.4",
|
|
50
50
|
"@earendil-works/pi-ai": "^0.85.1"
|
|
51
51
|
},
|
|
52
52
|
"devDependencies": {
|
|
53
53
|
"@deepseek-ai/cordis": "4.0.4",
|
|
54
|
-
"@deepseek-ai/dsh-anonymous-user-id": "0.
|
|
55
|
-
"@deepseek-ai/dsh-
|
|
56
|
-
"@deepseek-ai/dsh-
|
|
57
|
-
"@deepseek-ai/dsh-
|
|
58
|
-
"@deepseek-ai/dsh-
|
|
59
|
-
"@deepseek-ai/dsh-
|
|
60
|
-
"@deepseek-ai/dsh-
|
|
61
|
-
"@deepseek-ai/dsh-
|
|
62
|
-
"@deepseek-ai/dsh-llm
|
|
63
|
-
"@deepseek-ai/dsh-llm-
|
|
64
|
-
"@deepseek-ai/dsh-
|
|
65
|
-
"@deepseek-ai/dsh-
|
|
66
|
-
"@deepseek-ai/dsh-
|
|
67
|
-
"@deepseek-ai/dsh-
|
|
68
|
-
"@deepseek-ai/dsh-util-
|
|
54
|
+
"@deepseek-ai/dsh-anonymous-user-id": "0.2.0-rc.1",
|
|
55
|
+
"@deepseek-ai/dsh-app-boot": "0.2.0-rc.1",
|
|
56
|
+
"@deepseek-ai/dsh-atomic-write": "0.2.0-rc.1",
|
|
57
|
+
"@deepseek-ai/dsh-attachment": "0.2.0-rc.1",
|
|
58
|
+
"@deepseek-ai/dsh-credentials": "0.2.0-rc.1",
|
|
59
|
+
"@deepseek-ai/dsh-home-paths": "0.2.0-rc.1",
|
|
60
|
+
"@deepseek-ai/dsh-host-webserver": "0.2.0-rc.1",
|
|
61
|
+
"@deepseek-ai/dsh-launch-environment": "0.2.0-rc.1",
|
|
62
|
+
"@deepseek-ai/dsh-llm": "0.2.0-rc.1",
|
|
63
|
+
"@deepseek-ai/dsh-llm-deepseek": "0.2.0-rc.1",
|
|
64
|
+
"@deepseek-ai/dsh-llm-pi-ai": "0.2.0-rc.1",
|
|
65
|
+
"@deepseek-ai/dsh-settings": "0.2.0-rc.1",
|
|
66
|
+
"@deepseek-ai/dsh-timeout": "0.2.0-rc.1",
|
|
67
|
+
"@deepseek-ai/dsh-typert-protocol": "0.2.0-rc.1",
|
|
68
|
+
"@deepseek-ai/dsh-util-crypto": "0.2.0-rc.1",
|
|
69
|
+
"@deepseek-ai/dsh-util-values": "0.2.0-rc.1",
|
|
69
70
|
"@deepseek-ai/schemastery": "3.18.4",
|
|
70
71
|
"@earendil-works/pi-ai": "0.85.1",
|
|
71
72
|
"@types/react": "~18.3.31",
|
package/src/deepseek-routes.ts
CHANGED
|
@@ -130,7 +130,19 @@ export class DeepseekRouteRegistrar {
|
|
|
130
130
|
}
|
|
131
131
|
return current.connection
|
|
132
132
|
},
|
|
133
|
-
|
|
133
|
+
// 0.2.0 起认证由 resolveAuth 一次性给出请求头(resolveApiKey 已删),
|
|
134
|
+
// 头形与官方 llm-deepseek-api-key 接线一致(x-api-key)。
|
|
135
|
+
resolveAuth: (async (connection: { apiKeyEnv: unknown }) => ({
|
|
136
|
+
headers: { 'x-api-key': await this.resolveApiKey(connection) },
|
|
137
|
+
})) as never,
|
|
138
|
+
// 0.2.0 起 listModels 改读 discoverModels(缺省即空目录,模型选择器无项):
|
|
139
|
+
// 与官方 llm-deepseek-api-key 同款——现取当前物化 connection 的 models。
|
|
140
|
+
discoverModels: (provider: string) => {
|
|
141
|
+
const connection = routes().get(route)?.connection ?? built.connection
|
|
142
|
+
const catalogModelInfo = kit.deepseek?.catalogModelInfo
|
|
143
|
+
if (catalogModelInfo === undefined) return Promise.resolve([])
|
|
144
|
+
return Promise.resolve(connection.models.map((model) => catalogModelInfo(provider, model)))
|
|
145
|
+
},
|
|
134
146
|
resolveUserId: () => this.resolveUserId() as never,
|
|
135
147
|
resolveAttachments: () => ctx.get('attachments') as never,
|
|
136
148
|
// 附件宿主路径 → 模型工具执行世界只读路径桥(官方接线同款,见
|
package/src/resolve-dsh.ts
CHANGED
|
@@ -3,9 +3,9 @@
|
|
|
3
3
|
* dsh-llm-pi-ai / dsh-llm / pi-ai 之上,从而 dsh 升级即自动跟随上游。
|
|
4
4
|
*
|
|
5
5
|
* 解析策略(全部模块同源地整体成功或整体回退,杜绝跨源混用):
|
|
6
|
-
* 1. dsh-tree
|
|
7
|
-
*
|
|
8
|
-
* node_modules/@deepseek-ai/dsh-llm-pi-ai 与 node_modules/@earendil-works/pi-ai
|
|
6
|
+
* 1. dsh-tree:锚点链 = profileContext.installAnchor(CLI/桌面端同一事实,
|
|
7
|
+
* 桌面端 Electron 下 argv[1] 探测走不通)→ realpath(argv[1]) 向上找到同时
|
|
8
|
+
* 含 node_modules/@deepseek-ai/dsh-llm-pi-ai 与 node_modules/@earendil-works/pi-ai
|
|
9
9
|
* 的目录,按文件路径动态 import——与 dsh 官方插件共享同一模块实例;
|
|
10
10
|
* 2. vendored:回退到本插件 dependencies 里的固定版本副本(裸 import)。
|
|
11
11
|
*
|
|
@@ -31,6 +31,7 @@ import type { CredentialKey } from '@deepseek-ai/dsh-credentials'
|
|
|
31
31
|
import type * as DshLlm from '@deepseek-ai/dsh-llm'
|
|
32
32
|
import * as vendoredLlm from '@deepseek-ai/dsh-llm'
|
|
33
33
|
import type {
|
|
34
|
+
catalogModelInfo as catalogModelInfoType,
|
|
34
35
|
DeepSeekAdapter as DeepSeekAdapterType,
|
|
35
36
|
resolveAdapterOptions as resolveDeepSeekOptionsType,
|
|
36
37
|
} from '@deepseek-ai/dsh-llm-deepseek'
|
|
@@ -68,6 +69,8 @@ export interface DeepSeekKit {
|
|
|
68
69
|
DeepSeekAdapter: typeof DeepSeekAdapterType
|
|
69
70
|
resolveAdapterOptions: typeof resolveDeepSeekOptionsType
|
|
70
71
|
getOrCreateAnonymousUserId: typeof getAnonIdType
|
|
72
|
+
/** 目录项 → LlmModelInfo(0.2.0 起 listModels 经 discoverModels 消费)。 */
|
|
73
|
+
catalogModelInfo: typeof catalogModelInfoType
|
|
71
74
|
}
|
|
72
75
|
|
|
73
76
|
/** profile 解析面(官方 config.ts resolveProfiles 的签名;包根未导出,见文件头)。 */
|
|
@@ -178,6 +181,7 @@ function checkDeepseekShape(kit: DeepSeekKit): string[] {
|
|
|
178
181
|
problems.push('DeepSeekAdapter.prototype.stream 缺失')
|
|
179
182
|
}
|
|
180
183
|
if (typeof kit.resolveAdapterOptions !== 'function') problems.push('resolveAdapterOptions 缺失')
|
|
184
|
+
if (typeof kit.catalogModelInfo !== 'function') problems.push('catalogModelInfo 缺失')
|
|
181
185
|
if (typeof kit.getOrCreateAnonymousUserId !== 'function') {
|
|
182
186
|
problems.push('getOrCreateAnonymousUserId 缺失')
|
|
183
187
|
}
|
|
@@ -268,6 +272,7 @@ async function importTreeDeepseek(root: string): Promise<{ kit?: DeepSeekKit; pr
|
|
|
268
272
|
getOrCreateAnonymousUserId: anonId[
|
|
269
273
|
'getOrCreateAnonymousUserId'
|
|
270
274
|
] as DeepSeekKit['getOrCreateAnonymousUserId'],
|
|
275
|
+
catalogModelInfo: deepseek['catalogModelInfo'] as DeepSeekKit['catalogModelInfo'],
|
|
271
276
|
}
|
|
272
277
|
const problems = checkDeepseekShape(kit)
|
|
273
278
|
if (problems.length > 0) return { problem: `形状不兼容:${problems.join(';')}` }
|
|
@@ -381,6 +386,7 @@ function loadVendoredDeepseek(): DeepSeekKit | undefined {
|
|
|
381
386
|
DeepSeekAdapter: vendoredDeepseek.DeepSeekAdapter,
|
|
382
387
|
resolveAdapterOptions: vendoredDeepseek.resolveAdapterOptions,
|
|
383
388
|
getOrCreateAnonymousUserId: vendoredAnonId.getOrCreateAnonymousUserId,
|
|
389
|
+
catalogModelInfo: vendoredDeepseek.catalogModelInfo,
|
|
384
390
|
}
|
|
385
391
|
return checkDeepseekShape(kit).length === 0 ? kit : undefined
|
|
386
392
|
}
|
|
@@ -444,12 +450,23 @@ export function loadVendoredKit(): DshKit {
|
|
|
444
450
|
return kit
|
|
445
451
|
}
|
|
446
452
|
|
|
447
|
-
/**
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
453
|
+
/**
|
|
454
|
+
* 定位 dsh 安装树根:优先 `profileContext.installAnchor`(CLI 与桌面端同一
|
|
455
|
+
* 事实——桌面端 Electron 启动时 argv[1] 是 Electron 自身、走不通 argv 探测,
|
|
456
|
+
* 锚点是唯一可靠来源),其次 realpath(argv[1]) 向上查找;均失败返回 undefined。
|
|
457
|
+
* argvEntry 参数仅测试注入(缺省 process.argv[1])。
|
|
458
|
+
*/
|
|
459
|
+
export function dshTreeAnchor(
|
|
460
|
+
installAnchor?: string | undefined,
|
|
461
|
+
argvEntry: string | undefined = process.argv[1],
|
|
462
|
+
): string | undefined {
|
|
463
|
+
if (installAnchor !== undefined && installAnchor.length > 0) {
|
|
464
|
+
const anchored = findDshTreeRoot(dirname(installAnchor))
|
|
465
|
+
if (anchored !== undefined) return anchored
|
|
466
|
+
}
|
|
467
|
+
if (argvEntry === undefined) return undefined
|
|
451
468
|
try {
|
|
452
|
-
return findDshTreeRoot(dirname(realpathSync(
|
|
469
|
+
return findDshTreeRoot(dirname(realpathSync(argvEntry)))
|
|
453
470
|
} catch {
|
|
454
471
|
return undefined
|
|
455
472
|
}
|
|
@@ -459,13 +476,14 @@ function dshTreeAnchor(): string | undefined {
|
|
|
459
476
|
* 解析运行时套件:优先 dsh 安装树(自动跟随上游),失败回退 vendored 副本;
|
|
460
477
|
* 两者都过不了形状自检时抛错(调用方应记日志并放弃注册 route)。
|
|
461
478
|
* 返回的 diagnostics 记录回退原因,供配置卡片与日志展示。
|
|
479
|
+
* @param installAnchor profile 的 dsh 安装锚点(`ctx.profileContext.installAnchor`)。
|
|
462
480
|
*/
|
|
463
|
-
export async function resolveDshKit(): Promise<{
|
|
481
|
+
export async function resolveDshKit(installAnchor?: string | undefined): Promise<{
|
|
464
482
|
kit: DshKit
|
|
465
483
|
diagnostics: string[]
|
|
466
484
|
}> {
|
|
467
485
|
const diagnostics: string[] = []
|
|
468
|
-
const anchor = dshTreeAnchor()
|
|
486
|
+
const anchor = dshTreeAnchor(installAnchor)
|
|
469
487
|
if (anchor !== undefined) {
|
|
470
488
|
const treePkgDir = join(anchor, 'node_modules', '@deepseek-ai', 'dsh-llm-pi-ai')
|
|
471
489
|
try {
|
|
@@ -502,7 +520,9 @@ export async function resolveDshKit(): Promise<{
|
|
|
502
520
|
)
|
|
503
521
|
}
|
|
504
522
|
} else {
|
|
505
|
-
diagnostics.push(
|
|
523
|
+
diagnostics.push(
|
|
524
|
+
'未能从 profileContext.installAnchor / process.argv[1] 定位 dsh 安装树;回退 vendored 副本',
|
|
525
|
+
)
|
|
506
526
|
}
|
|
507
527
|
const kit = loadVendoredKit()
|
|
508
528
|
if (kit.deepseek === undefined) {
|
package/src/service.ts
CHANGED
|
@@ -11,6 +11,9 @@
|
|
|
11
11
|
* @module llm-pi/service
|
|
12
12
|
*/
|
|
13
13
|
import type { Context } from '@deepseek-ai/cordis'
|
|
14
|
+
// 平台类型面:profileContext.installAnchor(dsh 安装锚点,桌面端关键来源)。
|
|
15
|
+
// 纯类型导入,按开发规范仅需 devDeps。
|
|
16
|
+
import type {} from '@deepseek-ai/dsh-app-boot'
|
|
14
17
|
import type { CredentialRef } from '@deepseek-ai/dsh-credentials'
|
|
15
18
|
import { launchEnvironmentOf } from '@deepseek-ai/dsh-launch-environment'
|
|
16
19
|
import type { DirectoryRegistrationHandle } from '@deepseek-ai/dsh-llm'
|
|
@@ -90,7 +93,7 @@ export async function startRuntime(
|
|
|
90
93
|
const fields: LlmPiConfigFields = hasVolatileRefs(rawConfig)
|
|
91
94
|
? (rawConfig as LlmPiConfigFields)
|
|
92
95
|
: Config((rawConfig ?? {}) as LlmPiConfigInput)
|
|
93
|
-
const { kit, diagnostics } = await resolveDshKit()
|
|
96
|
+
const { kit, diagnostics } = await resolveDshKit(ctx.get('profileContext')?.installAnchor)
|
|
94
97
|
for (const line of diagnostics) logger.warn(line)
|
|
95
98
|
logger.info(`运行时套件来源:${kit.source}`)
|
|
96
99
|
|