magpie-gemini-web 0.1.2 → 0.1.3

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/README.md CHANGED
@@ -140,6 +140,20 @@ http://127.0.0.1:8083/admin
140
140
  | `requestTimeoutMs`| integer | `240000` | 转发单次请求的超时时间(毫秒,默认 4 分钟) |
141
141
  | `modelTimeoutMs` | integer | `10000` | 获取模型列表的超时时间(毫秒,默认 10 秒) |
142
142
 
143
+ ### 思考档位(effort)
144
+
145
+ 后端没有 effort 参数,扩展思考是单独的 `-thinking` 模型。插件把有 `-thinking` 版的模型声明为 `low` / `high` 两档,可以在 Magpie 里直接切换:
146
+
147
+ | 档位 | 实际调用 | 说明 |
148
+ | :--- | :--- | :--- |
149
+ | `low`(或不指定) | `gemini-x` | 网页端默认档:Argon 为「低」档,Flash 不输出思考链,3.1 Pro 仍会少量思考 |
150
+ | `high` | `gemini-x-thinking` | 网页端扩展思考(上游显示为 High),带 `reasoning_content` |
151
+
152
+ - 插件读取请求里的 `reasoning_effort`:`none` / `minimal` / `low` 走普通版,其他值(如 `medium`、`xhigh`)走 `-thinking` 版。经 Magpie 调用时,Magpie 会先把 Responses API 的 `reasoning.effort`、Anthropic Messages 的 `thinking.budget_tokens` 换算成最接近的已声明档位;Anthropic 的 `output_config.effort` 不会被转发。
153
+ - 直接选 `-thinking` 模型照常可用,档位设置对它不生效。
154
+ - 网页端 Argon 的「中」档上游尚未支持(见 [#5](https://github.com/BUKOWSKIREAL/magpie-gemini-web/issues/5))。
155
+ - 升级插件后,执行 `magpie provider models gemini-web` 重新拉取模型列表,档位才会出现。
156
+
143
157
  ---
144
158
 
145
159
  ## 5. 本地开发与实验性 Argon 支持 (Local Development & Argon Support)
package/lib/backend.mjs CHANGED
@@ -4,6 +4,14 @@ const MEDIA_SPECIAL = /(?:^|[-_])(image|music|canvas|video|research)(?:[-_]|$)/i
4
4
  const CONTROL_CHARS = /[\x00-\x1f\x7f]/;
5
5
  const NEWLINE_CHARS = /[\r\n]/;
6
6
 
7
+ // The backend has no effort parameter: extended thinking is a separate "<id>-thinking" model.
8
+ // A base model with such a twin offers low (itself) and high (the twin). Magpie maps any other
9
+ // level to the nearest declared one before it reaches us; direct callers get the same rule.
10
+ const THINKING_SUFFIX = '-thinking';
11
+ const LOW_EFFORTS = new Set(['none', 'minimal', 'low']);
12
+ const MODEL_CACHE_MS = 10 * 60 * 1000;
13
+ const knownModels = new Map();
14
+
7
15
  const KNOWN_OPTIONS = new Set([
8
16
  'baseURL',
9
17
  'allowTools',
@@ -253,8 +261,12 @@ export async function listModels(c, opts) {
253
261
  throw new Error('No usable Gemini models found in backend response');
254
262
  }
255
263
 
264
+ const ids = new Set(validIds);
265
+ knownModels.set(modelCacheKey(c), { ids, at: Date.now() });
266
+
256
267
  const result = Object.create(null);
257
268
  for (const id of validIds) {
269
+ const hasTwin = !id.endsWith(THINKING_SUFFIX) && ids.has(id + THINKING_SUFFIX);
258
270
  result[id] = {
259
271
  id,
260
272
  providerID: 'gemini-web',
@@ -291,7 +303,7 @@ export async function listModels(c, opts) {
291
303
  },
292
304
  options: {},
293
305
  headers: {},
294
- variants: {},
306
+ variants: hasTwin ? { low: {}, high: {} } : {},
295
307
  status: 'active'
296
308
  };
297
309
  }
@@ -299,6 +311,32 @@ export async function listModels(c, opts) {
299
311
  return result;
300
312
  }
301
313
 
314
+ function modelCacheKey(c) {
315
+ return `${c.baseURL}\n${c.key}`;
316
+ }
317
+
318
+ // thinkingTwin returns the model a chat request should run on for its reasoning_effort, or null
319
+ // to leave it alone. The twin is only used when the backend lists it; if the list can't be
320
+ // fetched the request goes out unchanged.
321
+ async function thinkingTwin(body, c, opts) {
322
+ const effort = body.reasoning_effort;
323
+ const model = body.model;
324
+ if (typeof effort !== 'string' || LOW_EFFORTS.has(effort)) return null;
325
+ if (typeof model !== 'string' || model.endsWith(THINKING_SUFFIX)) return null;
326
+
327
+ let cached = knownModels.get(modelCacheKey(c));
328
+ if (!cached || Date.now() - cached.at > MODEL_CACHE_MS) {
329
+ try {
330
+ await listModels(c, opts);
331
+ } catch {
332
+ return null;
333
+ }
334
+ cached = knownModels.get(modelCacheKey(c));
335
+ }
336
+ const twin = model + THINKING_SUFFIX;
337
+ return cached?.ids.has(twin) ? twin : null;
338
+ }
339
+
302
340
  export async function forward(input, init, getAuth, opts) {
303
341
  const req = new Request(input, init);
304
342
 
@@ -417,6 +455,12 @@ export async function forward(input, init, getAuth, opts) {
417
455
  }
418
456
  }
419
457
  }
458
+
459
+ const twin = await thinkingTwin(body, c, opts);
460
+ if (twin) {
461
+ body.model = twin;
462
+ rawBody = JSON.stringify(body);
463
+ }
420
464
  }
421
465
 
422
466
  const timeoutSignal = AbortSignal.timeout(opts.requestTimeoutMs);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "magpie-gemini-web",
3
- "version": "0.1.2",
3
+ "version": "0.1.3",
4
4
  "description": "Gemini Web provider for Magpie, backed by gemini-web2api-go",
5
5
  "type": "module",
6
6
  "main": "./index.mjs",