dsh-cmtoken-oauth 1.6.0 → 1.6.1

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 CHANGED
@@ -137,12 +137,12 @@ window.__ModuleLoader__.load({
137
137
  if (phase === "loading") {
138
138
  authCard = react.createElement("div", { className: "co-card" },
139
139
  react.createElement("div", { className: "co-card-title" }, "认证"),
140
- react.createElement("p", { className: "co-hint" }, "中国移动算力豆(komect)一键认证:扫码即自动创建专属 DSH API key,长期有效,无需刷新令牌。"),
140
+ react.createElement("p", { className: "co-hint" }, "中国移动算力豆一键认证:扫码即自动创建专属 DSH API key,长期有效,无需刷新令牌。"),
141
141
  react.createElement("div", { className: "co-hint" }, "加载中…"));
142
142
  } else if (phase === "qr" && flow) {
143
143
  authCard = react.createElement("div", { className: "co-card" },
144
144
  react.createElement("div", { className: "co-card-title" }, "认证"),
145
- react.createElement("p", { className: "co-hint" }, "中国移动算力豆(komect)一键认证:扫码即自动创建专属 DSH API key,长期有效,无需刷新令牌。"),
145
+ react.createElement("p", { className: "co-hint" }, "中国移动算力豆一键认证:扫码即自动创建专属 DSH API key,长期有效,无需刷新令牌。"),
146
146
  react.createElement("div", { className: "co-qr" },
147
147
  react.createElement("div", { dangerouslySetInnerHTML: { __html: flow.qr_svg } }),
148
148
  react.createElement("div", { className: "co-hint" }, "扫码登录中国移动账号,一次扫码完成认证与用量关联,约 " + Math.round(flow.expires_in || 180) + " 秒内有效")
@@ -153,7 +153,7 @@ window.__ModuleLoader__.load({
153
153
  } else if (phase === "done") {
154
154
  authCard = react.createElement("div", { className: "co-card" },
155
155
  react.createElement("div", { className: "co-card-title" }, "认证"),
156
- react.createElement("p", { className: "co-hint" }, "中国移动算力豆(komect)一键认证:扫码即自动创建专属 DSH API key,长期有效,无需刷新令牌。"),
156
+ react.createElement("p", { className: "co-hint" }, "中国移动算力豆一键认证:扫码即自动创建专属 DSH API key,长期有效,无需刷新令牌。"),
157
157
  react.createElement("div", { className: "co-auth-ok" }, "✅ 已认证" + (models.length ? ",已接入 " + models.length + " 个模型" : "")),
158
158
  react.createElement("div", { className: "co-row" },
159
159
  react.createElement(Button, { variant: "outline", size: "md", onClick: doRefresh }, "刷新模型与用量"),
@@ -161,14 +161,14 @@ window.__ModuleLoader__.load({
161
161
  } else if (phase === "error") {
162
162
  authCard = react.createElement("div", { className: "co-card" },
163
163
  react.createElement("div", { className: "co-card-title" }, "认证"),
164
- react.createElement("p", { className: "co-hint" }, "中国移动算力豆(komect)一键认证:扫码即自动创建专属 DSH API key,长期有效,无需刷新令牌。"),
164
+ react.createElement("p", { className: "co-hint" }, "中国移动算力豆一键认证:扫码即自动创建专属 DSH API key,长期有效,无需刷新令牌。"),
165
165
  react.createElement("div", { className: "co-err" }, "❌ " + (error || "认证失败")),
166
166
  react.createElement("div", { className: "co-row" },
167
167
  react.createElement(Button, { variant: "primary", size: "md", onClick: () => { setPhase("ok"); setError(null); } }, "返回重试")));
168
168
  } else if (authenticated) {
169
169
  authCard = react.createElement("div", { className: "co-card" },
170
170
  react.createElement("div", { className: "co-card-title" }, "认证"),
171
- react.createElement("p", { className: "co-hint" }, "中国移动算力豆(komect)一键认证:扫码即自动创建专属 DSH API key,长期有效,无需刷新令牌。"),
171
+ react.createElement("p", { className: "co-hint" }, "中国移动算力豆一键认证:扫码即自动创建专属 DSH API key,长期有效,无需刷新令牌。"),
172
172
  react.createElement("div", { className: "co-auth-ok" },
173
173
  "✅ 已认证",
174
174
  status && status.sessionExpired ? react.createElement("span", { className: "co-hint" }, "(管理会话已过期,重新扫码可刷新模型列表)") : null),
@@ -178,7 +178,7 @@ window.__ModuleLoader__.load({
178
178
  } else {
179
179
  authCard = react.createElement("div", { className: "co-card" },
180
180
  react.createElement("div", { className: "co-card-title" }, "认证"),
181
- react.createElement("p", { className: "co-hint" }, "中国移动算力豆(komect)一键认证:扫码即自动创建专属 DSH API key,长期有效,无需刷新令牌。"),
181
+ react.createElement("p", { className: "co-hint" }, "中国移动算力豆一键认证:扫码即自动创建专属 DSH API key,长期有效,无需刷新令牌。"),
182
182
  react.createElement("div", { className: "co-hint" }, "准备二维码…"));
183
183
  }
184
184
 
package/lib/index.js CHANGED
@@ -22,7 +22,7 @@ export const inject = ['connection', 'settings', 'credentials', 'tools', 'llm',
22
22
  export const Config = z.object({});
23
23
 
24
24
  // ---------------- 协议常量 ----------------
25
- // 旧通道(广东移动 MaaS OAuth Device Grant)已由 komect API-key 通道取代(见下)。
25
+ // 旧通道(广东移动 MaaS OAuth Device Grant)已由 中国移动算力豆 API-key 通道取代(见下)。
26
26
 
27
27
  const API_KEY_ENV = 'CMTOKEN_API_KEY';
28
28
  const REFRESH_ENV = 'CMTOKEN_REFRESH_TOKEN';
@@ -114,10 +114,10 @@ async function komect(path, { method = 'GET', token, body, timeout = 20_000 } =
114
114
  });
115
115
  const json = await res.json().catch(() => undefined);
116
116
  if (res.status === 401 || json?.code === 3004) {
117
- throw new Error('komect 管理会话已失效,请重新扫码认证');
117
+ throw new Error('中国移动算力豆管理会话已失效,请重新扫码认证');
118
118
  }
119
119
  if (!res.ok || json?.code !== 0) {
120
- throw new Error(`komect ${path} 失败 ${res.status}: ${String(json?.message ?? '').slice(0, 200) || 'unknown'}`);
120
+ throw new Error(`算力豆 ${path} 失败 ${res.status}: ${String(json?.message ?? '').slice(0, 200) || 'unknown'}`);
121
121
  }
122
122
  return json.data;
123
123
  }
@@ -143,7 +143,7 @@ async function ensureDshApiKey(session) {
143
143
  const revealed = await komect(`/api-keys/${encodeURIComponent(item.id)}/reveal`, { method: 'POST', token: session });
144
144
  const apiKey = revealed?.api_key;
145
145
  if (typeof apiKey !== 'string' || !apiKey.startsWith('lx_sk_')) {
146
- throw new Error('komect 密钥 reveal 失败:未返回有效的 lx_sk_ 密钥');
146
+ throw new Error('算力豆密钥 reveal 失败:未返回有效的 lx_sk_ 密钥');
147
147
  }
148
148
  return apiKey;
149
149
  }
@@ -156,20 +156,34 @@ async function fetchKomectModels(session) {
156
156
  headers: { Accept: 'application/json', Authorization: `Bearer ${session}` },
157
157
  });
158
158
  const json = await res.json().catch(() => undefined);
159
- if (res.status === 401) throw new Error('komect 管理会话已失效,请重新扫码认证');
159
+ if (res.status === 401) throw new Error('中国移动算力豆管理会话已失效,请重新扫码认证');
160
160
  if (!res.ok || json?.code !== 0 || !Array.isArray(json?.data)) {
161
- throw new Error(`komect 模型发现失败 ${res.status}: ${String(json?.message ?? '').slice(0, 200) || 'unknown'}`);
161
+ throw new Error(`算力豆模型发现失败 ${res.status}: ${String(json?.message ?? '').slice(0, 200) || 'unknown'}`);
162
162
  }
163
163
  return json.data
164
164
  .filter((m) => typeof m?.modelName === 'string' && m?.modelType === 'llm')
165
- .map((m) => ({
166
- id: m.modelName,
167
- name: m.name ?? m.modelName,
168
- contextWindow: m.extInfo?.limits?.max_input_tokens ?? DEFAULT_MODEL_SPEC.contextWindow,
169
- maxTokens: m.extInfo?.limits?.max_output_tokens ?? DEFAULT_MODEL_SPEC.maxTokens,
170
- // 图片准入以服务端 supports_images 声明为准
171
- input: m.extInfo?.supports_images === true ? ['text', 'image'] : ['text'],
172
- }));
165
+ .map((m) => {
166
+ // 限时免费模型(名称/描述带「限时免费」)服务端对 max_tokens 的实际上限低于声明值,
167
+ // 超限直接网关 500。按 2026-09-18 实测的各模型最大可用值精确收口:
168
+ // flash:262144 ✓ / 512000 ✗;Qwen3.6:196608 / 262144 ✗;qwen38:256000 ✓
169
+ // 未列入映射的免费标记模型保守收口 131072;付费模型按平台声明值。
170
+ const free = /限时免费|限量免费/.test(`${m.name ?? ''}${m.desc ?? ''}`);
171
+ const maxOut = m.extInfo?.limits?.max_output_tokens ?? DEFAULT_MODEL_SPEC.maxTokens;
172
+ const FREE_MODEL_MAX_TOKENS = {
173
+ 'deepseekv4-flash-guangdong': 262_144,
174
+ 'qwen3.6-35b-guangdong': 196_608,
175
+ 'qwen38-27b-guangdong': 256_000,
176
+ };
177
+ const freeCap = FREE_MODEL_MAX_TOKENS[String(m.modelName).toLowerCase()] ?? 131_072;
178
+ return {
179
+ id: m.modelName,
180
+ name: m.name ?? m.modelName,
181
+ contextWindow: m.extInfo?.limits?.max_input_tokens ?? DEFAULT_MODEL_SPEC.contextWindow,
182
+ maxTokens: free ? Math.min(maxOut, freeCap) : maxOut,
183
+ // 图片准入以服务端 supports_images 声明为准
184
+ input: m.extInfo?.supports_images === true ? ['text', 'image'] : ['text'],
185
+ };
186
+ });
173
187
  }
174
188
 
175
189
 
@@ -354,8 +368,8 @@ function registerRpc(ctx) {
354
368
  models = await fetchKomectModels(session);
355
369
  } catch (e) {
356
370
  // 模型发现失败:密钥照存,配置给最小模型集,报错提示
357
- ctx.logger?.warn?.('[cmtoken-oauth] komect 模型发现失败: ' + String(e.message || e));
358
- models = [{ id: 'deepseekv4-flash-guangdong', name: 'DeepSeek V4 Flash', contextWindow: 512_000, maxTokens: 512_000, input: ['text'] }];
371
+ ctx.logger?.warn?.('[cmtoken-oauth] 算力豆模型发现失败: ' + String(e.message || e));
372
+ models = [{ id: 'deepseekv4-flash-guangdong', name: 'DeepSeek V4 Flash', contextWindow: 512_000, maxTokens: 262_144, input: ['text'] }];
359
373
  }
360
374
  await writeConfigAndCreds(ctx, { apiKey, session, expires }, models);
361
375
  return {
@@ -472,7 +486,7 @@ async function writeConfigAndCreds(ctx, { apiKey, session, expires }, models) {
472
486
  const section = {
473
487
  providers: {
474
488
  cmtoken: {
475
- displayName: 'komect 算力豆',
489
+ displayName: '中国移动算力豆',
476
490
  apiKeyEnv: API_KEY_ENV,
477
491
  api: 'openai-completions',
478
492
  baseURL: GW_BASE,
@@ -656,7 +670,7 @@ async function describeImage({ baseURL, apiKey, model, dataUri, focus, signal })
656
670
  }
657
671
  if (!res.ok) {
658
672
  const text = (await res.text().catch(() => '')).slice(0, 300);
659
- if (res.status === 401) throw new Error('komect API key 无效,请在设置 → cmtoken 认证里重新认证');
673
+ if (res.status === 401) throw new Error('算力豆 API key 无效,请在设置 → cmtoken 认证里重新认证');
660
674
  if (res.status === 403 && /订阅套餐|订阅已过期|余额不足/.test(text)) throw new Error('订阅错误:' + text);
661
675
  throw new Error(`视觉模型识图失败 ${res.status}: ${text}`);
662
676
  }
@@ -695,7 +709,7 @@ function registerVisionTool(ctx) {
695
709
  if (!model) throw new Error('cmtoken 未配置视觉模型:请先在 DSH 设置 → cmtoken 认证完成一键认证');
696
710
 
697
711
  const key = await ctx.credentials?.resolve(credentialRef(API_KEY_ENV));
698
- if (!key) throw new Error('komect API key 不可用:请先在 DSH 设置 → cmtoken 认证完成一键认证');
712
+ if (!key) throw new Error('算力豆 API key 不可用:请先在 DSH 设置 → cmtoken 认证完成一键认证');
699
713
 
700
714
  const bytes = await loadImageBytes(source, exec?.signal);
701
715
  if (bytes.length === 0) throw new Error('图片内容为空');
@@ -796,7 +810,7 @@ async function evidenceForBlock(ctx, block, signal, cache) {
796
810
  const model = await resolveVisionModel(ctx);
797
811
  if (!model) throw new Error('cmtoken 未配置视觉模型,请先完成一键认证');
798
812
  const keyRes = await ctx.credentials?.resolve(credentialRef(API_KEY_ENV));
799
- if (!keyRes) throw new Error('komect API key 不可用,请重新认证');
813
+ if (!keyRes) throw new Error('算力豆 API key 不可用,请重新认证');
800
814
  const baseURL = ctx.settings?.get?.(settingsNamespace('llm-pi-ai'))?.providers?.cmtoken?.baseURL || GW_BASE;
801
815
  const signals = [AbortSignal.timeout(VISION_TOOL_TIMEOUT_MS)];
802
816
  if (signal) signals.push(signal);
@@ -1156,7 +1170,7 @@ export function apply(ctx, cfg = {}) {
1156
1170
  disposeVisionAdapter();
1157
1171
  };
1158
1172
  }, 'cmtoken-oauth: host service');
1159
- ctx.logger?.info?.('[cmtoken-oauth] host 服务已启动(komect API-key 通道:密钥长期有效,无需定时刷新)');
1173
+ ctx.logger?.info?.('[cmtoken-oauth] host 服务已启动(中国移动算力豆 API-key 通道:密钥长期有效,无需定时刷新)');
1160
1174
  }
1161
1175
 
1162
1176
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-cmtoken-oauth",
3
- "version": "1.6.0",
3
+ "version": "1.6.1",
4
4
  "description": "DeepSeek Harness 插件:在 DSH 设置页一键完成中国移动算力豆平台(komect)扫码认证——一次扫码自动桥接密钥管理会话、创建专属 DSH API key(lx_sk_,长期有效)、发现模型(上下文/输出/图片支持由平台动态提供)并写入 llm-pi-ai provider 配置,同时展示算力豆用量余额;粘贴识图让纯文本模型直接收图,另有 cmtoken_read_image 工具与可选的 cmtoken-vision 包装路由。零第三方运行时依赖。",
5
5
  "type": "module",
6
6
  "main": "./lib/index.js",