mocode-ai 1.6.8 → 1.6.9

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.
@@ -254,8 +254,12 @@ export function buildGeminiRequest(messages, tools, runtime, overrides) {
254
254
  const geminiTools = encodeGeminiTools(tools);
255
255
  const effort = effectiveReasoningEffort(overrides?.reasoningEffort);
256
256
  const budget = thinkingBudget(effort);
257
+ // Gemini 的思考 token 计入 maxOutputTokens:不给思考留余量时,思考先吃光预算,
258
+ // finishReason=MAX_TOKENS 且正文为空/截断(3.8-flash 实测:maxOutputTokens=100 → 正文空,
259
+ // =2000 → 92 thoughts + "OK")。auto 档动态思考上限按 flash 系 24576 保守留量。
260
+ const thinkingAllowance = budget ?? (effort === 'auto' ? 24576 : 0);
257
261
  const generationConfig = {
258
- maxOutputTokens: runtimeConfig.maxTokens ?? 8192,
262
+ maxOutputTokens: (runtimeConfig.maxTokens ?? 8192) + thinkingAllowance,
259
263
  temperature: 0.2,
260
264
  ...(budget === null ? {} : { thinkingConfig: { thinkingBudget: budget } }),
261
265
  };
@@ -329,6 +333,7 @@ export async function vertexChatOnce(messages, handlers, signal, tools, runtime,
329
333
  let usage;
330
334
  const toolCalls = [];
331
335
  let reportedTool = false;
336
+ let finishReason = '';
332
337
  const live = { cjk: 0, other: 0 };
333
338
  const countLive = (text) => {
334
339
  for (const ch of text) {
@@ -355,6 +360,8 @@ export async function vertexChatOnce(messages, handlers, signal, tools, runtime,
355
360
  usage = usageFromGemini(usageMetadata);
356
361
  const candidates = Array.isArray(event.candidates) ? event.candidates : [];
357
362
  const candidate = isRecord(candidates[0]) ? candidates[0] : undefined;
363
+ if (typeof candidate?.finishReason === 'string')
364
+ finishReason = candidate.finishReason;
358
365
  const candidateContent = isRecord(candidate?.content) ? candidate.content : undefined;
359
366
  const parts = Array.isArray(candidateContent?.parts) ? candidateContent.parts : [];
360
367
  for (const rawPart of parts) {
@@ -393,5 +400,12 @@ export async function vertexChatOnce(messages, handlers, signal, tools, runtime,
393
400
  cachedTokens: usage.cachedTokens,
394
401
  });
395
402
  }
403
+ // MAX_TOKENS 截断曾静默返回:模型没发完工具调用就结束 turn(「没干完活就结束」)。
404
+ // 显式标注让用户与下一轮模型都看到截断事实;正常 STOP/SAFETY 等不加。
405
+ if (finishReason === 'MAX_TOKENS' && (content || toolCalls.length > 0)) {
406
+ const marker = '\n\n[mocode] Gemini finishReason=MAX_TOKENS:输出在 token 上限处被截断(思考也计入 maxOutputTokens)。可调大 MAX_TOKENS 或 /effort 降低思考强度。';
407
+ content += marker;
408
+ handlers.onText?.(marker);
409
+ }
396
410
  return { content: content || null, toolCalls, usage };
397
411
  }
@@ -34,6 +34,14 @@ export function applyPresetConfig(ctx, p) {
34
34
  CONTEXT_WINDOW_TOKENS: String(p.contextWindow),
35
35
  ANTHROPIC_PROMPT_CACHE: p.anthropicPromptCache ? 'true' : 'false',
36
36
  });
37
+ // 关键不变量:应用预设即激活——必须同步 .active 指针。否则重启时旧激活预设的优先级
38
+ // 高于刚写入的 config 文件,表现为「切了模型、重启又回到原来的」(实测的丢配置 bug)。
39
+ try {
40
+ setActivePresetName(p.name);
41
+ }
42
+ catch {
43
+ /* 指针写失败不阻断切换 */
44
+ }
37
45
  reconfigureClient();
38
46
  ctx.refreshStatusBase(ctx.history);
39
47
  layout.clearContent();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mocode-ai",
3
- "version": "1.6.8",
3
+ "version": "1.6.9",
4
4
  "description": "终端编码 agent:LLM + tool-call 循环 + 流式输出(含思考)+ 27 个工具,接任意 OpenAI 兼容后端。",
5
5
  "type": "module",
6
6
  "bin": {