@dsh-plus/llm-pi 0.1.9 → 0.1.11
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 +24 -7
- package/package.json +1 -1
- package/src/catalog/models-dev.ts +11 -0
- package/src/client/client.ts +1 -1
- package/src/client/scope.ts +3 -0
- package/src/deepseek-routes.ts +23 -7
package/lib/index.js
CHANGED
|
@@ -276,6 +276,12 @@ function fetchJson(url, proxy, timeoutMs) {
|
|
|
276
276
|
}, (response) => {
|
|
277
277
|
const chunks = [];
|
|
278
278
|
let size = 0;
|
|
279
|
+
let settled = false;
|
|
280
|
+
const fail = (error) => {
|
|
281
|
+
if (settled) return;
|
|
282
|
+
settled = true;
|
|
283
|
+
reject(error);
|
|
284
|
+
};
|
|
279
285
|
response.on("data", (chunk) => {
|
|
280
286
|
size += chunk.length;
|
|
281
287
|
if (size > MAX_RESPONSE_BYTES$1) {
|
|
@@ -285,11 +291,14 @@ function fetchJson(url, proxy, timeoutMs) {
|
|
|
285
291
|
chunks.push(chunk);
|
|
286
292
|
});
|
|
287
293
|
response.on("end", () => {
|
|
294
|
+
if (settled) return;
|
|
295
|
+
settled = true;
|
|
288
296
|
resolve({
|
|
289
297
|
status: response.statusCode ?? 0,
|
|
290
298
|
body: Buffer.concat(chunks).toString("utf8")
|
|
291
299
|
});
|
|
292
300
|
});
|
|
301
|
+
response.on("error", fail);
|
|
293
302
|
});
|
|
294
303
|
req.on("timeout", () => req.destroy(/* @__PURE__ */ new Error(`请求超时(${timeoutMs}ms)`)));
|
|
295
304
|
req.on("error", reject);
|
|
@@ -449,20 +458,23 @@ var DeepseekRouteRegistrar = class {
|
|
|
449
458
|
for (const [route, built] of target) {
|
|
450
459
|
const existing = this.registrations.get(route);
|
|
451
460
|
if (existing !== void 0) {
|
|
452
|
-
this.
|
|
461
|
+
this.refreshRegistration(route, built, existing);
|
|
453
462
|
continue;
|
|
454
463
|
}
|
|
455
464
|
this.register(route, built);
|
|
456
465
|
}
|
|
457
466
|
}
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
467
|
+
/** retryPolicy 或 displayName 变化时原地 replace(两者均为注册期捕获事实)。 */
|
|
468
|
+
refreshRegistration(route, built, registration) {
|
|
469
|
+
const policyUnchanged = deepEqualJson(built.connection.retryPolicy, registration.retryPolicy);
|
|
470
|
+
const nameUnchanged = built.displayName === registration.displayName;
|
|
471
|
+
if (policyUnchanged && nameUnchanged) return;
|
|
461
472
|
try {
|
|
462
473
|
registration.handle.replace([route]);
|
|
463
|
-
registration.retryPolicy =
|
|
474
|
+
registration.retryPolicy = built.connection.retryPolicy;
|
|
475
|
+
registration.displayName = built.displayName;
|
|
464
476
|
} catch (error) {
|
|
465
|
-
this.deps.logger.error(`llm-pi: deepseek route "${route}"
|
|
477
|
+
this.deps.logger.error(`llm-pi: deepseek route "${route}" 注册事实更新被拒,保留此前注册`);
|
|
466
478
|
this.deps.logger.error(error);
|
|
467
479
|
}
|
|
468
480
|
}
|
|
@@ -484,11 +496,16 @@ var DeepseekRouteRegistrar = class {
|
|
|
484
496
|
resolveUserId: () => this.resolveUserId(),
|
|
485
497
|
resolveAttachments: () => ctx.get("attachments")
|
|
486
498
|
});
|
|
499
|
+
adapter.providerInfo = (provider) => ({
|
|
500
|
+
id: provider,
|
|
501
|
+
name: routes().get(route)?.displayName ?? built.displayName
|
|
502
|
+
});
|
|
487
503
|
try {
|
|
488
504
|
const handle = ctx.llm.registerAdapter([route], adapter);
|
|
489
505
|
this.registrations.set(route, {
|
|
490
506
|
handle,
|
|
491
|
-
retryPolicy: built.connection.retryPolicy
|
|
507
|
+
retryPolicy: built.connection.retryPolicy,
|
|
508
|
+
displayName: built.displayName
|
|
492
509
|
});
|
|
493
510
|
} catch (error) {
|
|
494
511
|
logger.error(`llm-pi: deepseek route "${route}" 注册失败(可能与其他 adapter 重名),该 route 不可用`);
|
package/package.json
CHANGED
|
@@ -82,6 +82,12 @@ function fetchJson(url: string, proxy: string, timeoutMs: number): Promise<JsonR
|
|
|
82
82
|
(response) => {
|
|
83
83
|
const chunks: Buffer[] = []
|
|
84
84
|
let size = 0
|
|
85
|
+
let settled = false
|
|
86
|
+
const fail = (error: Error): void => {
|
|
87
|
+
if (settled) return
|
|
88
|
+
settled = true
|
|
89
|
+
reject(error)
|
|
90
|
+
}
|
|
85
91
|
response.on('data', (chunk: Buffer) => {
|
|
86
92
|
size += chunk.length
|
|
87
93
|
if (size > MAX_RESPONSE_BYTES) {
|
|
@@ -91,11 +97,16 @@ function fetchJson(url: string, proxy: string, timeoutMs: number): Promise<JsonR
|
|
|
91
97
|
chunks.push(chunk)
|
|
92
98
|
})
|
|
93
99
|
response.on('end', () => {
|
|
100
|
+
if (settled) return
|
|
101
|
+
settled = true
|
|
94
102
|
resolve({
|
|
95
103
|
status: response.statusCode ?? 0,
|
|
96
104
|
body: Buffer.concat(chunks).toString('utf8'),
|
|
97
105
|
})
|
|
98
106
|
})
|
|
107
|
+
// 响应流自身出错(中途截断的 aborted 等)不经请求转发:缺此监听时
|
|
108
|
+
// Promise 永不 settle(req timeout 只覆盖建连/空闲等待),refresh 永久挂起。
|
|
109
|
+
response.on('error', fail)
|
|
99
110
|
},
|
|
100
111
|
)
|
|
101
112
|
req.on('timeout', () => req.destroy(new Error(`请求超时(${timeoutMs}ms)`)))
|
package/src/client/client.ts
CHANGED
|
@@ -21,7 +21,7 @@ import type { Context } from '@deepseek-ai/cordis'
|
|
|
21
21
|
import { SETTINGS_NS } from '../ns.ts'
|
|
22
22
|
import { LlmPiCard } from './card.tsx'
|
|
23
23
|
import { en, NS, zh } from './i18n.ts'
|
|
24
|
-
import type { Scope, SettingsApi } from './scope.ts'
|
|
24
|
+
import type { Scope, ScopeSnapshot, SettingsApi } from './scope.ts'
|
|
25
25
|
import { injectStyle } from './styles.ts'
|
|
26
26
|
|
|
27
27
|
export const name = 'dsh-plus-llm-pi'
|
package/src/client/scope.ts
CHANGED
package/src/deepseek-routes.ts
CHANGED
|
@@ -25,6 +25,8 @@ interface RouteRegistration {
|
|
|
25
25
|
handle: AdapterRegistrationHandle
|
|
26
26
|
/** 注册期捕获的重试策略(变化才 replace)。 */
|
|
27
27
|
retryPolicy: unknown
|
|
28
|
+
/** 注册期捕获的展示名(providerInfo 是注册期捕获事实,变化才 replace)。 */
|
|
29
|
+
displayName: string
|
|
28
30
|
}
|
|
29
31
|
|
|
30
32
|
export interface DeepseekRegistrarDeps {
|
|
@@ -80,25 +82,28 @@ export class DeepseekRouteRegistrar {
|
|
|
80
82
|
for (const [route, built] of target) {
|
|
81
83
|
const existing = this.registrations.get(route)
|
|
82
84
|
if (existing !== undefined) {
|
|
83
|
-
this.
|
|
85
|
+
this.refreshRegistration(route, built, existing)
|
|
84
86
|
continue
|
|
85
87
|
}
|
|
86
88
|
this.register(route, built)
|
|
87
89
|
}
|
|
88
90
|
}
|
|
89
91
|
|
|
90
|
-
|
|
92
|
+
/** retryPolicy 或 displayName 变化时原地 replace(两者均为注册期捕获事实)。 */
|
|
93
|
+
private refreshRegistration(
|
|
91
94
|
route: string,
|
|
92
95
|
built: ResolvedDeepseekRoute,
|
|
93
96
|
registration: RouteRegistration,
|
|
94
97
|
): void {
|
|
95
|
-
const
|
|
96
|
-
|
|
98
|
+
const policyUnchanged = deepEqualJson(built.connection.retryPolicy, registration.retryPolicy)
|
|
99
|
+
const nameUnchanged = built.displayName === registration.displayName
|
|
100
|
+
if (policyUnchanged && nameUnchanged) return
|
|
97
101
|
try {
|
|
98
102
|
registration.handle.replace([route])
|
|
99
|
-
registration.retryPolicy =
|
|
103
|
+
registration.retryPolicy = built.connection.retryPolicy
|
|
104
|
+
registration.displayName = built.displayName
|
|
100
105
|
} catch (error) {
|
|
101
|
-
this.deps.logger.error(`llm-pi: deepseek route "${route}"
|
|
106
|
+
this.deps.logger.error(`llm-pi: deepseek route "${route}" 注册事实更新被拒,保留此前注册`)
|
|
102
107
|
this.deps.logger.error(error)
|
|
103
108
|
}
|
|
104
109
|
}
|
|
@@ -126,9 +131,20 @@ export class DeepseekRouteRegistrar {
|
|
|
126
131
|
resolveUserId: () => this.resolveUserId() as never,
|
|
127
132
|
resolveAttachments: () => ctx.get('attachments') as never,
|
|
128
133
|
})
|
|
134
|
+
// 官方 providerInfo 硬编码 name: "DeepSeek"——覆盖为按路由动态读取的
|
|
135
|
+
// displayName,否则自定义 deepseek 路由在模型选择器里与 deepseek-official
|
|
136
|
+
// 撞名(两个 "DeepSeek" 分组,无法区分)。
|
|
137
|
+
adapter.providerInfo = (provider: string) => ({
|
|
138
|
+
id: provider,
|
|
139
|
+
name: routes().get(route)?.displayName ?? built.displayName,
|
|
140
|
+
})
|
|
129
141
|
try {
|
|
130
142
|
const handle = ctx.llm.registerAdapter([route], adapter as never)
|
|
131
|
-
this.registrations.set(route, {
|
|
143
|
+
this.registrations.set(route, {
|
|
144
|
+
handle,
|
|
145
|
+
retryPolicy: built.connection.retryPolicy,
|
|
146
|
+
displayName: built.displayName,
|
|
147
|
+
})
|
|
132
148
|
} catch (error) {
|
|
133
149
|
logger.error(
|
|
134
150
|
`llm-pi: deepseek route "${route}" 注册失败(可能与其他 adapter 重名),该 route 不可用`,
|