feat: v0.8.3 工作空间切换链路根治 · 思考强度扩档 — 启动TDZ连锁/继承丢数/回显滞后三修复 · xhigh+true档位单源 · 安全防线ready后注册 · 2217 用例全量回归 + 生产模式E2E
This commit is contained in:
@@ -82,7 +82,9 @@ describe('OpenAIAdapter — 推理模型 reasoning_effort', () => {
|
||||
['low', 'low'],
|
||||
['medium', 'medium'],
|
||||
['high', 'high'],
|
||||
['xhigh', 'high'], // v0.8.3: OpenAI 档位封顶 high,xhigh 就近降档
|
||||
['max', 'high'], // max 归一 high
|
||||
['true', 'high'], // v0.8.3: 模型默认档归一 high
|
||||
] as const)('o3-mini effort=%s → reasoning_effort=%s', async (effort, expected) => {
|
||||
const adapter = makeAdapter('o3-mini');
|
||||
mockFetch.mockResolvedValue(okResponse());
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
*
|
||||
* Ollama:
|
||||
* O1 options 映射(num_predict=numTokens、num_ctx=contextLength、stop、top_p)
|
||||
* O2 think 参数 effort 映射(low→"low"、max→true)与未配置时缺省
|
||||
* O2 think 参数 effort 映射(low→"low"、xhigh→"xhigh"、max/true→true)与未配置时缺省
|
||||
* O3 图片归一化(data URI 剥前缀;无 URL 触发下载分支时零网络请求)
|
||||
*
|
||||
* Agnes:
|
||||
@@ -286,7 +286,7 @@ describe('OllamaAdapter — 请求体契约', () => {
|
||||
expect(options.stop).toEqual(['STOP']);
|
||||
});
|
||||
|
||||
it('O2: think 参数 effort 映射(low→"low"、max→true);未开启思考时缺省', async () => {
|
||||
it('O2: think 参数 effort 映射(low→"low"、xhigh→"xhigh"、max/true→true);未开启思考时缺省', async () => {
|
||||
const adapter = makeOllama();
|
||||
const { bodies } = captureFetch();
|
||||
|
||||
@@ -316,12 +316,39 @@ describe('OllamaAdapter — 请求体契约', () => {
|
||||
);
|
||||
expect(bodies[1].think).toBe(true);
|
||||
|
||||
// v0.8.3: xhigh 原样透传(Qwen3 等思考模板原生档);true → 布尔 true(模型默认档)
|
||||
await adapter.send(
|
||||
makeRequest({
|
||||
params: {
|
||||
maxTokens: 4096,
|
||||
temperature: 0,
|
||||
stream: false,
|
||||
thinkingEnabled: true,
|
||||
thinkingEffort: 'xhigh',
|
||||
},
|
||||
}),
|
||||
);
|
||||
expect(bodies[2].think).toBe('xhigh');
|
||||
|
||||
await adapter.send(
|
||||
makeRequest({
|
||||
params: {
|
||||
maxTokens: 4096,
|
||||
temperature: 0,
|
||||
stream: false,
|
||||
thinkingEnabled: true,
|
||||
thinkingEffort: 'true',
|
||||
},
|
||||
}),
|
||||
);
|
||||
expect(bodies[3].think).toBe(true);
|
||||
|
||||
await adapter.send(
|
||||
makeRequest({
|
||||
params: { maxTokens: 4096, temperature: 0, stream: false, thinkingEnabled: false },
|
||||
}),
|
||||
);
|
||||
expect(bodies[2].think).toBeUndefined();
|
||||
expect(bodies[4].think).toBeUndefined();
|
||||
});
|
||||
|
||||
it('O3: data URI 图片剥前缀转纯 base64 数组(无网络下载路径触发)', async () => {
|
||||
@@ -516,8 +543,10 @@ describe('AnthropicAdapter — thinking budget 按 effort 映射矩阵', () => {
|
||||
['low', 1024],
|
||||
['medium', 4096],
|
||||
['high', 16384],
|
||||
['xhigh', 24576], // v0.8.3: 介于 high 与 max 之间
|
||||
// v0.8.1: max_tokens 不再按模型钳制(100_000 原样透传)→ budget = min(32768, floor(100000/2)) = 32768
|
||||
['max', 32768],
|
||||
['true', 16384], // v0.8.3: 模型默认档按 high 同档预算
|
||||
] as const)('effort=%s → budget 为该档值且 < max_tokens', async (effort, expectBudget) => {
|
||||
const adapter = makeAdapter();
|
||||
const { bodies } = captureFetch();
|
||||
@@ -723,9 +752,11 @@ describe('DeepSeekAdapter — thinking 映射矩阵', () => {
|
||||
['low', 'high'],
|
||||
['medium', 'high'],
|
||||
['high', 'high'],
|
||||
['xhigh', 'high'], // v0.8.3: DeepSeek 无 xhigh 档,就近映射 high
|
||||
['max', 'max'],
|
||||
['true', 'high'], // v0.8.3: 模型默认档映射 high
|
||||
] as const)(
|
||||
'effort=%s → reasoning_effort=%s(low/medium 归一 high)',
|
||||
'effort=%s → reasoning_effort=%s(low/medium/xhigh/true 归一 high)',
|
||||
async (effort, expected) => {
|
||||
const adapter = makeAdapter();
|
||||
const { bodies } = captureFetch();
|
||||
|
||||
@@ -730,12 +730,16 @@ export class AnthropicAdapter extends BaseAdapter {
|
||||
}
|
||||
|
||||
// Thinking 模式:budget_tokens(必须小于 max_tokens,此处钳制到一半)
|
||||
// v0.8.3: 新增 xhigh / true 档 —— xhigh 介于 high 与 max 之间取 24576;
|
||||
// true(模型默认档)按 high 同档预算
|
||||
if (thinkingRequested) {
|
||||
const budgetMap: Record<string, number> = {
|
||||
low: 1024,
|
||||
medium: 4096,
|
||||
high: 16384,
|
||||
xhigh: 24576,
|
||||
max: 32768,
|
||||
true: 16384,
|
||||
};
|
||||
const effortBudget = budgetMap[request.params.thinkingEffort ?? 'high'] ?? 16384;
|
||||
// thinking 路径 maxTokensForRequest 恒为数字(Math.max(2048, …) 兜底)
|
||||
|
||||
@@ -206,13 +206,16 @@ export class DeepSeekAdapter extends OpenAICompatibleAdapter {
|
||||
body.thinking = { type: 'disabled' };
|
||||
} else {
|
||||
body.thinking = { type: 'enabled' };
|
||||
// v0.8.3: 新增 xhigh / true 档 —— DeepSeek API 仅 high / max 两档,就近映射 high
|
||||
const effortMap: Record<string, string> = {
|
||||
low: 'high',
|
||||
medium: 'high',
|
||||
high: 'high',
|
||||
xhigh: 'high',
|
||||
max: 'max',
|
||||
true: 'high',
|
||||
};
|
||||
// DeepSeek API 仅支持 high / max 两档,low/medium 映射为 high
|
||||
// DeepSeek API 仅支持 high / max 两档,low/medium/xhigh/true 映射为 high
|
||||
body.reasoning_effort = effortMap[request.params.thinkingEffort ?? 'high'] ?? 'high';
|
||||
// 元信息标注不支持思考但用户开启 —— 告知降级兜底路径(不拦截)
|
||||
if (DeepSeekAdapter.MODEL_INFO[this.config.defaultModel]?.supportsThinking === false) {
|
||||
|
||||
@@ -698,11 +698,17 @@ export class OllamaAdapter extends BaseAdapter {
|
||||
if (request.params.thinkingEnabled) {
|
||||
const modelThinkingSupported = this.cachedThinkingSupport !== false;
|
||||
if (modelThinkingSupported) {
|
||||
// v0.8.3: 新增 xhigh / true 档 —— Qwen3 等新模型思考模板原生支持 xhigh
|
||||
//(旧版仅下发 low/medium/high 时,模板会 500 "Unexpected reasoning effort");
|
||||
// true = 不指定档位(think: true),由模型思考模板用自身默认档。
|
||||
// max 语义为"应用内最高档",Ollama 侧同样以布尔 true 放行给服务端默认。
|
||||
const effortMap: Record<string, string | boolean> = {
|
||||
low: 'low',
|
||||
medium: 'medium',
|
||||
high: 'high',
|
||||
xhigh: 'xhigh',
|
||||
max: true,
|
||||
true: true,
|
||||
};
|
||||
body.think = effortMap[request.params.thinkingEffort ?? 'high'] ?? true;
|
||||
// v0.8.0 P0-3: 思考占用 num_predict 输出预算 —— 预算过小时显式告警
|
||||
|
||||
@@ -149,12 +149,15 @@ export class OpenAIAdapter extends OpenAICompatibleAdapter {
|
||||
}
|
||||
|
||||
// Thinking 模式:推理模型映射 reasoning_effort;非推理模型忽略
|
||||
// v0.8.3: 新增 xhigh / true 档 —— OpenAI API 档位封顶 high,二者就近映射
|
||||
if (request.params.thinkingEnabled && isReasoningModel) {
|
||||
const effortMap: Record<string, string> = {
|
||||
low: 'low',
|
||||
medium: 'medium',
|
||||
high: 'high',
|
||||
xhigh: 'high',
|
||||
max: 'high',
|
||||
true: 'high',
|
||||
};
|
||||
body.reasoning_effort = effortMap[request.params.thinkingEffort ?? 'high'] ?? 'high';
|
||||
// v0.8.0 P0-3: 推理 token 计入 max_completion_tokens —— 用户配置的预算过小时告警
|
||||
|
||||
@@ -4,7 +4,12 @@
|
||||
* 用于 Agent Loop 引擎内部的状态管理和迭代记录。
|
||||
*/
|
||||
|
||||
import type { MetonaToolCall, MetonaToolResult, MetonaThinkingBlock } from '../types';
|
||||
import type {
|
||||
MetonaThinkingEffort,
|
||||
MetonaToolCall,
|
||||
MetonaToolResult,
|
||||
MetonaThinkingBlock,
|
||||
} from '../types';
|
||||
|
||||
// ===== Agent Loop 状态机 =====
|
||||
|
||||
@@ -100,8 +105,8 @@ export interface AgentLoopConfig {
|
||||
maxTokens?: number;
|
||||
/** 是否启用思考模式(默认 true) */
|
||||
thinkingEnabled: boolean;
|
||||
/** 思考强度(默认 'high') */
|
||||
thinkingEffort: 'low' | 'medium' | 'high' | 'max';
|
||||
/** 思考强度(默认 'high';v0.8.3 档位单源见 MetonaThinkingEffort) */
|
||||
thinkingEffort: MetonaThinkingEffort;
|
||||
/** Ollama num_ctx(与「上下文长度」同源:llm.contextWindow,仅 Ollama Provider 下发) */
|
||||
contextLength?: number;
|
||||
/** 工具执行兜底超时(ms,默认 120000),实际取 max(此值, tool.timeoutMs) */
|
||||
|
||||
@@ -11,6 +11,7 @@ export type {
|
||||
MetonaRequestMeta,
|
||||
MetonaSystemPrompt,
|
||||
MetonaGenerationParams,
|
||||
MetonaThinkingEffort,
|
||||
MetonaConstraints,
|
||||
MetonaMessage,
|
||||
MetonaImageContent,
|
||||
|
||||
@@ -38,6 +38,17 @@ export interface MetonaSystemPrompt {
|
||||
|
||||
// ===== 生成参数 =====
|
||||
|
||||
/**
|
||||
* 思考强度档位(v0.8.3 起单一类型源,引擎/引擎配置/UI/各 Adapter 共用)
|
||||
*
|
||||
* - low / medium / high / max:原始四档
|
||||
* - xhigh:v0.8.3 新增 —— Qwen3 等新模型思考模板原生支持 xhigh 档
|
||||
* (Ollama 下原样下发;仅支持 low/medium/high 的 Provider 就近降档映射)
|
||||
* - true:v0.8.3 新增 —— 不指定档位,`think: true` 交给模型思考模板用自身默认
|
||||
* 档(如 Qwen3 默认 xhigh);有显式档位协议的 Provider 就近映射为 high
|
||||
*/
|
||||
export type MetonaThinkingEffort = 'low' | 'medium' | 'high' | 'xhigh' | 'max' | 'true';
|
||||
|
||||
export interface MetonaGenerationParams {
|
||||
/** 最大生成 token 数 */
|
||||
maxTokens?: number;
|
||||
@@ -52,7 +63,7 @@ export interface MetonaGenerationParams {
|
||||
/** 是否启用思考模式 */
|
||||
thinkingEnabled?: boolean;
|
||||
/** 思考强度(替代 thinkingBudget,各 Provider 映射见 Adapter 规范) */
|
||||
thinkingEffort?: 'low' | 'medium' | 'high' | 'max';
|
||||
thinkingEffort?: MetonaThinkingEffort;
|
||||
/** 上下文窗口大小(仅 Ollama 支持 num_ctx) */
|
||||
contextLength?: number;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user