@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.
@@ -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 benefitModels = await getBenefitModels(providerId)
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
- const retryState = { cooldownUntil: 0 }
66
-
67
- // ---- benefit 模型判断 ----
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: isBenefitModel(bundle.benefitModels, id) ? `${providerId}-benefit` : providerId,
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
- // 全局冷却:acquireUpstream cooldownUntil
124
- await waitForCooldown(retryState)
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: retryState,
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
- log(`[${id}] 鉴权就绪 AK=${cred.accessKeyId?.slice(0, 4)}****${cred.accessKeyId?.slice(-3)} expires=${new Date(cred.expiresAt).toISOString()}`)
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
  }