@dsh-plus/llm-pi 0.1.7 → 0.1.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/client.js +1 -1
- package/lib/index.js +51 -17
- package/package.json +1 -1
- package/src/client/draft.ts +1 -1
- package/src/directory.ts +73 -0
- package/src/service.ts +12 -18
package/lib/client.js
CHANGED
|
@@ -230,7 +230,7 @@ window.__ModuleLoader__.load({
|
|
|
230
230
|
compat: provider.compat,
|
|
231
231
|
defaultContextWindow: toNum(provider.defaultContextWindow),
|
|
232
232
|
defaultMaxTokens: toNum(provider.defaultMaxTokens),
|
|
233
|
-
|
|
233
|
+
defaultInput: inputToWire(provider.input),
|
|
234
234
|
reasoning: provider.reasoning,
|
|
235
235
|
thinkingBudgets: budgetToWire(provider.thinkingBudgets),
|
|
236
236
|
cacheRetention: provider.cacheRetention,
|
package/lib/index.js
CHANGED
|
@@ -497,6 +497,52 @@ var DeepseekRouteRegistrar = class {
|
|
|
497
497
|
}
|
|
498
498
|
};
|
|
499
499
|
//#endregion
|
|
500
|
+
//#region src/directory.ts
|
|
501
|
+
/**
|
|
502
|
+
* 可配置 provider 目录注册:条目组装与冲突降级。
|
|
503
|
+
*
|
|
504
|
+
* 官方 `registerConfigurableProviders`/`replace` 的拒绝语义是原子的——任一条目
|
|
505
|
+
* 与既有声明冲突(典型:route 名撞官方内置 provider 目录条目,如 anthropic)则
|
|
506
|
+
* 整批不落盘。此处按 registerAdapter 同款降级模式:逐个剔除冲突条目重试,
|
|
507
|
+
* 让其余 route 的目录条目照常生效。
|
|
508
|
+
* @module llm-pi/directory
|
|
509
|
+
*/
|
|
510
|
+
/** 组装当前全部 route 的目录条目(pi + deepseek 两族)。 */
|
|
511
|
+
function buildDirectoryEntries(kit, settingsNs, piProfiles, deepseekRoutes) {
|
|
512
|
+
const piEntries = [...piProfiles.entries()].map(([provider, profile]) => ({
|
|
513
|
+
provider,
|
|
514
|
+
displayName: profile.displayName,
|
|
515
|
+
settingsNs,
|
|
516
|
+
settingsPath: ["providers", provider],
|
|
517
|
+
declared: !hasBuiltinProvider(kit, provider)
|
|
518
|
+
}));
|
|
519
|
+
const deepseekEntries = [...deepseekRoutes.values()].map((built) => ({
|
|
520
|
+
provider: built.route,
|
|
521
|
+
displayName: built.displayName,
|
|
522
|
+
settingsNs,
|
|
523
|
+
settingsPath: ["providers", built.route],
|
|
524
|
+
declared: true
|
|
525
|
+
}));
|
|
526
|
+
return [...piEntries, ...deepseekEntries];
|
|
527
|
+
}
|
|
528
|
+
/**
|
|
529
|
+
* 提交目录条目;整批被原子拒绝时逐个剔除冲突条目重试(每轮至多剔一个,
|
|
530
|
+
* 轮数不超过条目数,必然终止)。非冲突错误原样上抛。
|
|
531
|
+
*/
|
|
532
|
+
function commitDirectory(register, entries, warn) {
|
|
533
|
+
let rest = entries;
|
|
534
|
+
for (let attempts = 0; attempts <= entries.length; attempts++) try {
|
|
535
|
+
register(rest);
|
|
536
|
+
return;
|
|
537
|
+
} catch (error) {
|
|
538
|
+
const match = /configurable provider "([^"]+)" is already declared/.exec(error instanceof Error ? error.message : String(error));
|
|
539
|
+
const next = match === null ? [] : rest.filter((entry) => entry.provider !== match[1]);
|
|
540
|
+
if (match === null || next.length === rest.length) throw error;
|
|
541
|
+
warn(`llm-pi: 目录条目 "${match[1]}" 与既有声明冲突(通常为官方内置 provider 目录),已跳过该条目`);
|
|
542
|
+
rest = next;
|
|
543
|
+
}
|
|
544
|
+
}
|
|
545
|
+
//#endregion
|
|
500
546
|
//#region src/catalog/official.ts
|
|
501
547
|
/** 按 kit 备忘(kit 实例在进程内唯一,目录随 dsh 树版本固定)。 */
|
|
502
548
|
const cache = /* @__PURE__ */ new WeakMap();
|
|
@@ -1542,28 +1588,16 @@ async function startRuntime(ctx, rawConfig) {
|
|
|
1542
1588
|
let directory;
|
|
1543
1589
|
let directoryFacts;
|
|
1544
1590
|
const ensureDirectory = () => {
|
|
1545
|
-
const
|
|
1546
|
-
provider,
|
|
1547
|
-
displayName: profile.displayName,
|
|
1548
|
-
settingsNs: SETTINGS_NS,
|
|
1549
|
-
settingsPath: ["providers", provider],
|
|
1550
|
-
declared: !hasBuiltinProvider(kit, provider)
|
|
1551
|
-
}));
|
|
1552
|
-
const deepseekEntries = [...deepseekRoutes().values()].map((built) => ({
|
|
1553
|
-
provider: built.route,
|
|
1554
|
-
displayName: built.displayName,
|
|
1555
|
-
settingsNs: SETTINGS_NS,
|
|
1556
|
-
settingsPath: ["providers", built.route],
|
|
1557
|
-
declared: true
|
|
1558
|
-
}));
|
|
1559
|
-
const entries = [...piEntries, ...deepseekEntries];
|
|
1591
|
+
const entries = buildDirectoryEntries(kit, SETTINGS_NS, profiles(), deepseekRoutes());
|
|
1560
1592
|
if (deepEqualJson(entries, directoryFacts)) return;
|
|
1561
1593
|
if (entries.length === 0) {
|
|
1562
1594
|
directoryFacts = entries;
|
|
1563
1595
|
return;
|
|
1564
1596
|
}
|
|
1565
|
-
|
|
1566
|
-
|
|
1597
|
+
commitDirectory((batch) => {
|
|
1598
|
+
if (directory === void 0) directory = ctx.llm.registerConfigurableProviders(batch);
|
|
1599
|
+
else directory.replace(batch);
|
|
1600
|
+
}, entries, (message) => logger.warn(message));
|
|
1567
1601
|
directoryFacts = entries;
|
|
1568
1602
|
};
|
|
1569
1603
|
const deepseekRegistrar = new DeepseekRouteRegistrar({
|
package/package.json
CHANGED
package/src/client/draft.ts
CHANGED
|
@@ -285,7 +285,7 @@ function providerToWire(provider: ProviderDraft): WireProvider {
|
|
|
285
285
|
compat: provider.compat,
|
|
286
286
|
defaultContextWindow: toNum(provider.defaultContextWindow),
|
|
287
287
|
defaultMaxTokens: toNum(provider.defaultMaxTokens),
|
|
288
|
-
|
|
288
|
+
defaultInput: inputToWire(provider.input),
|
|
289
289
|
reasoning: provider.reasoning,
|
|
290
290
|
thinkingBudgets: budgetToWire(provider.thinkingBudgets),
|
|
291
291
|
cacheRetention: provider.cacheRetention,
|
package/src/directory.ts
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 可配置 provider 目录注册:条目组装与冲突降级。
|
|
3
|
+
*
|
|
4
|
+
* 官方 `registerConfigurableProviders`/`replace` 的拒绝语义是原子的——任一条目
|
|
5
|
+
* 与既有声明冲突(典型:route 名撞官方内置 provider 目录条目,如 anthropic)则
|
|
6
|
+
* 整批不落盘。此处按 registerAdapter 同款降级模式:逐个剔除冲突条目重试,
|
|
7
|
+
* 让其余 route 的目录条目照常生效。
|
|
8
|
+
* @module llm-pi/directory
|
|
9
|
+
*/
|
|
10
|
+
import { hasBuiltinProvider } from './catalog/builtin.ts'
|
|
11
|
+
import type { ResolvedDeepseekRoute } from './profiles-deepseek.ts'
|
|
12
|
+
import type { DshKit } from './resolve-dsh.ts'
|
|
13
|
+
|
|
14
|
+
/** 一条可配置 provider 目录条目(registerConfigurableProviders 的入参形状)。 */
|
|
15
|
+
export interface DirectoryEntry {
|
|
16
|
+
provider: string
|
|
17
|
+
displayName: string
|
|
18
|
+
settingsNs: string
|
|
19
|
+
settingsPath: string[]
|
|
20
|
+
declared: boolean
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/** 组装当前全部 route 的目录条目(pi + deepseek 两族)。 */
|
|
24
|
+
export function buildDirectoryEntries(
|
|
25
|
+
kit: DshKit,
|
|
26
|
+
settingsNs: string,
|
|
27
|
+
piProfiles: Map<string, { displayName: string }>,
|
|
28
|
+
deepseekRoutes: Map<string, ResolvedDeepseekRoute>,
|
|
29
|
+
): DirectoryEntry[] {
|
|
30
|
+
const piEntries = [...piProfiles.entries()].map(([provider, profile]) => ({
|
|
31
|
+
provider,
|
|
32
|
+
displayName: profile.displayName,
|
|
33
|
+
settingsNs,
|
|
34
|
+
settingsPath: ['providers', provider],
|
|
35
|
+
declared: !hasBuiltinProvider(kit, provider),
|
|
36
|
+
}))
|
|
37
|
+
const deepseekEntries = [...deepseekRoutes.values()].map((built) => ({
|
|
38
|
+
provider: built.route,
|
|
39
|
+
displayName: built.displayName,
|
|
40
|
+
settingsNs,
|
|
41
|
+
settingsPath: ['providers', built.route],
|
|
42
|
+
declared: true,
|
|
43
|
+
}))
|
|
44
|
+
return [...piEntries, ...deepseekEntries]
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* 提交目录条目;整批被原子拒绝时逐个剔除冲突条目重试(每轮至多剔一个,
|
|
49
|
+
* 轮数不超过条目数,必然终止)。非冲突错误原样上抛。
|
|
50
|
+
*/
|
|
51
|
+
export function commitDirectory(
|
|
52
|
+
register: (entries: DirectoryEntry[]) => void,
|
|
53
|
+
entries: DirectoryEntry[],
|
|
54
|
+
warn: (message: string) => void,
|
|
55
|
+
): void {
|
|
56
|
+
let rest = entries
|
|
57
|
+
for (let attempts = 0; attempts <= entries.length; attempts++) {
|
|
58
|
+
try {
|
|
59
|
+
register(rest)
|
|
60
|
+
return
|
|
61
|
+
} catch (error) {
|
|
62
|
+
const match = /configurable provider "([^"]+)" is already declared/.exec(
|
|
63
|
+
error instanceof Error ? error.message : String(error),
|
|
64
|
+
)
|
|
65
|
+
const next = match === null ? [] : rest.filter((entry) => entry.provider !== match[1])
|
|
66
|
+
if (match === null || next.length === rest.length) throw error
|
|
67
|
+
warn(
|
|
68
|
+
`llm-pi: 目录条目 "${match[1]}" 与既有声明冲突(通常为官方内置 provider 目录),已跳过该条目`,
|
|
69
|
+
)
|
|
70
|
+
rest = next
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
package/src/service.ts
CHANGED
|
@@ -16,10 +16,10 @@ import { launchEnvironmentOf } from '@deepseek-ai/dsh-launch-environment'
|
|
|
16
16
|
import type { ResolvedPiAiProviderProfile } from '@deepseek-ai/dsh-llm-pi-ai'
|
|
17
17
|
import { deepEqualJson, installSettingsSection } from '@deepseek-ai/dsh-settings'
|
|
18
18
|
|
|
19
|
-
import { hasBuiltinProvider } from './catalog/builtin.ts'
|
|
20
19
|
import { ModelsDevSource } from './catalog/models-dev.ts'
|
|
21
20
|
import { Config, type LlmPiConfig, SETTINGS_NS } from './config.ts'
|
|
22
21
|
import { DeepseekRouteRegistrar } from './deepseek-routes.ts'
|
|
22
|
+
import { buildDirectoryEntries, commitDirectory, type DirectoryEntry } from './directory.ts'
|
|
23
23
|
import { discoverModels } from './discovery.ts'
|
|
24
24
|
import { assertServiceable, buildProfiles } from './profiles.ts'
|
|
25
25
|
import { buildDeepseekRoutes, type ResolvedDeepseekRoute } from './profiles-deepseek.ts'
|
|
@@ -213,29 +213,23 @@ export async function startRuntime(ctx: Context, rawConfig: LlmPiConfig): Promis
|
|
|
213
213
|
let directory: { replace: (entries: unknown[]) => void } | undefined
|
|
214
214
|
let directoryFacts: unknown
|
|
215
215
|
const ensureDirectory = (): void => {
|
|
216
|
-
const
|
|
217
|
-
|
|
218
|
-
displayName: profile.displayName,
|
|
219
|
-
settingsNs: SETTINGS_NS,
|
|
220
|
-
settingsPath: ['providers', provider],
|
|
221
|
-
declared: !hasBuiltinProvider(kit, provider),
|
|
222
|
-
}))
|
|
223
|
-
const deepseekEntries = [...deepseekRoutes().values()].map((built) => ({
|
|
224
|
-
provider: built.route,
|
|
225
|
-
displayName: built.displayName,
|
|
226
|
-
settingsNs: SETTINGS_NS,
|
|
227
|
-
settingsPath: ['providers', built.route],
|
|
228
|
-
declared: true,
|
|
229
|
-
}))
|
|
230
|
-
const entries = [...piEntries, ...deepseekEntries]
|
|
216
|
+
const entries = buildDirectoryEntries(kit, SETTINGS_NS, profiles(), deepseekRoutes())
|
|
217
|
+
// 备忘键为目标全集(含被冲突跳过的条目):目标不变不重复尝试/告警
|
|
231
218
|
if (deepEqualJson(entries, directoryFacts)) return
|
|
232
219
|
if (entries.length === 0) {
|
|
233
220
|
// 空目录不可注册(INVALID_DIRECTORY);等 settings 用户层供数后在 onChange 注册
|
|
234
221
|
directoryFacts = entries
|
|
235
222
|
return
|
|
236
223
|
}
|
|
237
|
-
|
|
238
|
-
|
|
224
|
+
commitDirectory(
|
|
225
|
+
(batch: DirectoryEntry[]) => {
|
|
226
|
+
if (directory === undefined)
|
|
227
|
+
directory = ctx.llm.registerConfigurableProviders(batch as never)
|
|
228
|
+
else directory.replace(batch)
|
|
229
|
+
},
|
|
230
|
+
entries,
|
|
231
|
+
(message) => logger.warn(message),
|
|
232
|
+
)
|
|
239
233
|
directoryFacts = entries
|
|
240
234
|
}
|
|
241
235
|
|