@wwkit/llmproxy 1.0.4 → 1.0.5
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/package.json +3 -3
- package/src/config.json5 +34 -0
- package/src/core/factory.js +1 -15
- package/src/core/transport.js +5 -49
- package/src/ctl-impl.js +122 -1
- package/src/ctl.js +35 -4
- package/src/providers/codearts/auth.js +3 -21
- package/src/providers/codearts/client.js +88 -3
- package/src/providers/deepseek-web/auth.js +278 -0
- package/src/providers/deepseek-web/client.js +171 -0
- package/src/providers/deepseek-web/config.js +22 -0
- package/src/providers/deepseek-web/error.js +28 -0
- package/src/providers/deepseek-web/pow.js +279 -0
- package/src/providers/deepseek-web/sign.js +10 -0
- package/src/providers/deepseek-web/sse.js +202 -0
- package/src/providers/deepseek-web/tools.js +53 -0
- package/src/providers/qianwen-web/auth.js +258 -0
- package/src/providers/qianwen-web/client.js +159 -0
- package/src/providers/qianwen-web/config.js +22 -0
- package/src/providers/qianwen-web/error.js +10 -0
- package/src/providers/qianwen-web/sign.js +86 -0
- package/src/providers/qianwen-web/sse.js +157 -0
- package/src/providers/qianwen-web/tools.js +36 -0
- package/src/server.js +11 -18
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
// providers/qianwen-web/tools.js — 千问 Web 消息格式化
|
|
2
|
+
//
|
|
3
|
+
// 将 OpenAI 消息数组转为千问请求体的 messages 格式。
|
|
4
|
+
// Tool 注入/解析由 openai-tool-bridge 通用层处理。
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* 构建千问 messages 数组(从 OpenAI messages 转换)
|
|
8
|
+
* 千问格式:{ mime_type, content, meta_data, status }
|
|
9
|
+
*/
|
|
10
|
+
export function buildMessages(messages) {
|
|
11
|
+
if (!Array.isArray(messages) || messages.length === 0) return [];
|
|
12
|
+
|
|
13
|
+
return messages
|
|
14
|
+
.filter((m) => m.role === "user" || m.role === "assistant" || m.role === "system")
|
|
15
|
+
.map((m) => {
|
|
16
|
+
const content = extractContent(m.content);
|
|
17
|
+
if (!content) return null;
|
|
18
|
+
return {
|
|
19
|
+
mime_type: "text/plain",
|
|
20
|
+
content,
|
|
21
|
+
meta_data: { ori_query: content },
|
|
22
|
+
status: "complete",
|
|
23
|
+
};
|
|
24
|
+
})
|
|
25
|
+
.filter(Boolean);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function extractContent(content) {
|
|
29
|
+
if (typeof content === "string") return content;
|
|
30
|
+
if (Array.isArray(content)) {
|
|
31
|
+
return content
|
|
32
|
+
.map((p) => (typeof p === "string" ? p : p?.text || ""))
|
|
33
|
+
.join("\n");
|
|
34
|
+
}
|
|
35
|
+
return "";
|
|
36
|
+
}
|
package/src/server.js
CHANGED
|
@@ -29,7 +29,6 @@ import {
|
|
|
29
29
|
buildSignProvider,
|
|
30
30
|
buildErrorPatterns,
|
|
31
31
|
buildClient,
|
|
32
|
-
getBenefitModels,
|
|
33
32
|
} from './core/factory.js'
|
|
34
33
|
import {
|
|
35
34
|
streamSSE,
|
|
@@ -53,8 +52,7 @@ async function getProviderBundle(providerId) {
|
|
|
53
52
|
const signProvider = await buildSignProvider(providerId, null) // 从模块 SIGN_CONFIG 加载
|
|
54
53
|
const errorPatterns = await buildErrorPatterns(providerId, null) // 从模块 ERROR_CONFIG 加载
|
|
55
54
|
const client = await buildClient(providerId, providerConfig, { authProvider, signProvider })
|
|
56
|
-
const
|
|
57
|
-
const bundle = { providerConfig, authProvider, signProvider, errorPatterns, client, benefitModels }
|
|
55
|
+
const bundle = { providerConfig, authProvider, signProvider, errorPatterns, client }
|
|
58
56
|
providerRegistry.set(providerId, bundle)
|
|
59
57
|
return bundle
|
|
60
58
|
}
|
|
@@ -62,19 +60,16 @@ async function getProviderBundle(providerId) {
|
|
|
62
60
|
// ---- 全局状态 ----
|
|
63
61
|
let inflight = 0
|
|
64
62
|
let reqSeq = 0
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
function isBenefitModel(benefitModels, modelId) {
|
|
69
|
-
return benefitModels.map(m => m.toLowerCase()).includes(String(modelId).toLowerCase())
|
|
70
|
-
}
|
|
63
|
+
// 每个 provider 独立的冷却状态(避免一个 provider 失败阻塞其它 provider)
|
|
64
|
+
const retryState = {} // providerId -> { cooldownUntil }
|
|
65
|
+
const getRetryState = (id) => (retryState[id] ??= { cooldownUntil: 0 })
|
|
71
66
|
|
|
72
67
|
async function handleProviderModels(res, providerId) {
|
|
73
68
|
const bundle = await getProviderBundle(providerId)
|
|
74
69
|
const data = bundle.providerConfig.models.map((id, i) => ({
|
|
75
70
|
id,
|
|
76
71
|
object: 'model',
|
|
77
|
-
owned_by:
|
|
72
|
+
owned_by: providerId,
|
|
78
73
|
sort: i,
|
|
79
74
|
}))
|
|
80
75
|
json(res, 200, { object: 'list', data })
|
|
@@ -114,24 +109,21 @@ async function handleChat(req, res, providerId) {
|
|
|
114
109
|
// 客户端断开信号
|
|
115
110
|
const clientGone = clientGoneSignal(res)
|
|
116
111
|
|
|
117
|
-
// benefit 头
|
|
118
|
-
const extraHeaders = isBenefitModel(bundle.benefitModels, model) ? { 'maas_type': 'benefit' } : {}
|
|
119
|
-
|
|
120
112
|
body.stream = stream
|
|
121
113
|
|
|
122
114
|
try {
|
|
123
|
-
//
|
|
124
|
-
|
|
115
|
+
// 冷却等待:仅当前 provider 的冷却(互不阻塞)
|
|
116
|
+
const state = getRetryState(providerId)
|
|
117
|
+
await waitForCooldown(state)
|
|
125
118
|
|
|
126
119
|
// 重试循环
|
|
127
120
|
const result = await retryLoop({
|
|
128
121
|
attemptFn: () => bundle.client.chatCompletions(body, {
|
|
129
|
-
headers: extraHeaders,
|
|
130
122
|
signal: clientGone.signal,
|
|
131
123
|
}),
|
|
132
124
|
errorPatterns: bundle.errorPatterns,
|
|
133
125
|
config: config.retry,
|
|
134
|
-
state
|
|
126
|
+
state,
|
|
135
127
|
clientGone,
|
|
136
128
|
chatId: id,
|
|
137
129
|
})
|
|
@@ -238,7 +230,8 @@ async function warmupProvider(id) {
|
|
|
238
230
|
const shouldAutoLogin = process.env.LLMPROXY_LOGIN === id
|
|
239
231
|
try {
|
|
240
232
|
const cred = await bundle.authProvider.getCredentials({ autoLogin: shouldAutoLogin })
|
|
241
|
-
|
|
233
|
+
const label = cred.accessKeyId || cred.token || cred.cookie ? '凭证就绪' : '凭证就绪'
|
|
234
|
+
log(`[${id}] ${label} expires=${cred.expiresAt ? new Date(cred.expiresAt).toISOString() : 'N/A'}`)
|
|
242
235
|
} catch (e) {
|
|
243
236
|
log(`[${id}] 鉴权未就绪: ${e.message}(请执行 llmproxy login --provider ${id})`)
|
|
244
237
|
}
|