@huyooo/ai-chat-core 0.2.41 → 0.2.44

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.
@@ -119,8 +119,10 @@ interface ModelRegistryEntry {
119
119
  visible?: boolean;
120
120
  /** 是否支持图片理解(优先级高于 family.supportsVision) */
121
121
  supportsVision?: boolean;
122
- /** 上下文窗口大小(如 "256K" */
122
+ /** 上下文窗口大小(如 "256K"),用于展示 */
123
123
  contextWindow?: string;
124
+ /** 上下文窗口精确 token 数(用于压缩器计算) */
125
+ contextWindowTokens?: number;
124
126
  /** 价格信息(数组,分行显示) */
125
127
  pricing?: string[];
126
128
  }
@@ -305,6 +307,17 @@ interface AgentConfig {
305
307
  * ```
306
308
  */
307
309
  mcpServers?: McpServerConfig[];
310
+ /**
311
+ * 上下文总结回调(走 ai-server 等外部服务)
312
+ *
313
+ * 当对话历史超过模型 context window 时,orchestrator 调用此函数执行 AI 总结。
314
+ * 宿主提供实现(如 smart-finder 的 toolAI),ai-chat-core 不关心具体调用方式。
315
+ *
316
+ * @param systemPrompt 总结指令
317
+ * @param userPrompt 格式化后的中间对话历史
318
+ * @returns 总结后的文本
319
+ */
320
+ summarize?: (systemPrompt: string, userPrompt: string) => Promise<string>;
308
321
  }
309
322
  /** 深度思考模式 */
310
323
  type ThinkingMode = 'enabled' | 'disabled';
@@ -934,6 +947,38 @@ interface StepEndEvent {
934
947
  }
935
948
  /** 步骤相关事件联合类型 */
936
949
  type StepEvent = StepStartEvent | StepEndEvent;
950
+ /** 上下文压缩开始事件 */
951
+ interface CompactStartEvent {
952
+ type: 'compact_start';
953
+ data: {
954
+ /** 压缩前估算 token 数 */
955
+ estimatedTokens: number;
956
+ /** 可用 prompt token 预算 */
957
+ budget: number;
958
+ /** 开始时间戳 */
959
+ startedAt: number;
960
+ };
961
+ }
962
+ /** 上下文压缩完成事件 */
963
+ interface CompactEndEvent {
964
+ type: 'compact_end';
965
+ data: {
966
+ /** 是否成功 */
967
+ success: boolean;
968
+ /** 压缩后估算 token 数 */
969
+ compressedTokens: number;
970
+ /** 压缩前消息数 */
971
+ originalMessageCount: number;
972
+ /** 压缩后消息数 */
973
+ compressedMessageCount: number;
974
+ /** 结束时间戳 */
975
+ endedAt: number;
976
+ /** 耗时(毫秒) */
977
+ duration: number;
978
+ };
979
+ }
980
+ /** 上下文压缩相关事件联合类型 */
981
+ type CompactEvent = CompactStartEvent | CompactEndEvent;
937
982
  /**
938
983
  * Agent 当前阶段:前端根据此字段直接渲染 loading 状态,不需要「猜」。
939
984
  *
@@ -952,7 +997,7 @@ interface AgentStatusEvent {
952
997
  /** 创建 agent_status 事件 */
953
998
  declare function createAgentStatus(phase: AgentPhase): AgentStatusEvent;
954
999
  /** 所有事件类型 */
955
- type ChatEvent = ThinkingEvent | SearchEvent | ToolEvent | TextEvent | StatusEvent | StepEvent | AgentStatusEvent;
1000
+ type ChatEvent = ThinkingEvent | SearchEvent | ToolEvent | TextEvent | StatusEvent | StepEvent | CompactEvent | AgentStatusEvent;
956
1001
  /** 事件类型字符串 */
957
1002
  type ChatEventType = ChatEvent['type'];
958
1003
  /** 所有合法事件类型(用于契约测试:Orchestrator/适配器产出必须在此集合内) */
@@ -1051,6 +1096,14 @@ declare function createStepStart(stepNumber: number, description?: string): Step
1051
1096
  * 创建步骤结束事件
1052
1097
  */
1053
1098
  declare function createStepEnd(stepNumber: number, startedAt: number): StepEndEvent;
1099
+ /**
1100
+ * 创建上下文压缩开始事件
1101
+ */
1102
+ declare function createCompactStart(estimatedTokens: number, budget: number): CompactStartEvent;
1103
+ /**
1104
+ * 创建上下文压缩完成事件
1105
+ */
1106
+ declare function createCompactEnd(success: boolean, compressedTokens: number, originalMessageCount: number, compressedMessageCount: number, startedAt: number): CompactEndEvent;
1054
1107
  /** 检查是否为思考事件 */
1055
1108
  declare function isThinkingEvent(event: ChatEvent): event is ThinkingEvent;
1056
1109
  /** 检查是否为搜索事件 */
@@ -1067,7 +1120,9 @@ declare function isErrorEvent(event: ChatEvent): event is ErrorEvent;
1067
1120
  declare function isAbortEvent(event: ChatEvent): event is AbortEvent;
1068
1121
  /** 检查是否为步骤事件 */
1069
1122
  declare function isStepEvent(event: ChatEvent): event is StepEvent;
1123
+ /** 检查是否为上下文压缩事件 */
1124
+ declare function isCompactEvent(event: ChatEvent): event is CompactEvent;
1070
1125
  /** 检查错误是否可重试 */
1071
1126
  declare function isRetryableError(event: ChatEvent): boolean;
1072
1127
 
1073
- export { resolveTools as $, type AgentConfig as A, type AutoRunConfig as B, type ChatOptions as C, DOUBAO_FAMILY as D, type ToolDefinition as E, type ResponsesApiTool as F, GEMINI_FAMILY as G, type ProviderType as H, type ToolContext as I, type JsonSchemaObject as J, type ToolUI as K, type RenderType as L, type ModelFamilyConfig as M, type ActionType as N, type ExecResult as O, type ProtocolId as P, QWEN_FAMILY as Q, type RouteResult as R, type SearchStrategy as S, type ToolExecutor as T, type ToolError as U, type ToolErrorCode as V, type ToolPlugin as W, type ToolConfigItem as X, type UserToolDefinition as Y, MODELS as Z, getModelByModelId as _, type ChatEvent as a, isTextEvent as a$, tool as a0, tools as a1, throwToolError as a2, rethrowToolError as a3, isToolError as a4, getArg as a5, type SearchResult as a6, type ToolCallStatus as a7, type ToolCallInfo as a8, type TokenUsage as a9, type StepEndEvent as aA, type StepEvent as aB, type ChatEventType as aC, createThinkingStart as aD, createThinkingDelta as aE, createThinkingEnd as aF, createSearchStart as aG, createSearchResult as aH, createSearchEnd as aI, createToolCallStart as aJ, createToolCallResult as aK, createToolCallOutput as aL, createToolCallRequest as aM, createTextDelta as aN, createDone as aO, createError as aP, createApiError as aQ, createRateLimitError as aR, createToolError as aS, createTimeoutError as aT, createParseError as aU, createAbort as aV, createStepStart as aW, createStepEnd as aX, isThinkingEvent as aY, isSearchEvent as aZ, isToolEvent as a_, type ErrorCategory as aa, type ErrorDetails as ab, type ToolUIShape as ac, type ThinkingStartEvent as ad, type ThinkingDeltaEvent as ae, type ThinkingEndEvent as af, type ThinkingEvent as ag, type SearchStartEvent as ah, type SearchResultEvent as ai, type SearchEndEvent as aj, type SearchEvent as ak, type ToolCallStartEvent as al, type ToolCallResultEvent as am, type ToolCallOutputEvent as an, type ToolApprovalRequestEvent as ao, type ToolCallRequestEvent as ap, type ToolEvent as aq, type TextDeltaEvent as ar, type TextEvent as as, type PlanStep as at, type PlanStepStatus as au, type DoneEvent as av, type ErrorEvent as aw, type AbortEvent as ax, type StatusEvent as ay, type StepStartEvent as az, type ModelOption as b, isStatusEvent as b0, isErrorEvent as b1, isAbortEvent as b2, isStepEvent as b3, isRetryableError as b4, CHAT_EVENT_TYPES as b5, routeModelToProvider as b6, routeModelWithDetails as b7, getDefaultProvider as b8, isModelForProvider as b9, type McpServerConfig as ba, type McpConnectionStatus as bb, type AgentPhase as bc, type AgentStatusEvent as bd, createAgentStatus as be, type McpConnectionInfo as c, type Tool as d, type ChatMessage as e, MODEL_FAMILIES as f, DEEPSEEK_FAMILY as g, GPT_FAMILY as h, CLAUDE_FAMILY as i, MODEL_REGISTRY as j, getModelEntry as k, getModelFamily as l, getModelProtocol as m, getVisibleModels as n, getModelsByFamily as o, getModelsByProtocol as p, modelSupportsThinking as q, modelSupportsNativeSearch as r, getModelSearchStrategy as s, type ModelFamilyId as t, type ThinkingFormat as u, type ToolCallFormat as v, type ModelRegistryEntry as w, type ChatMode as x, type ThinkingMode as y, type AutoRunMode as z };
1128
+ export { resolveTools as $, type AgentConfig as A, type AutoRunConfig as B, type ChatOptions as C, DOUBAO_FAMILY as D, type ToolDefinition as E, type ResponsesApiTool as F, GEMINI_FAMILY as G, type ProviderType as H, type ToolContext as I, type JsonSchemaObject as J, type ToolUI as K, type RenderType as L, type ModelFamilyConfig as M, type ActionType as N, type ExecResult as O, type ProtocolId as P, QWEN_FAMILY as Q, type RouteResult as R, type SearchStrategy as S, type ToolExecutor as T, type ToolError as U, type ToolErrorCode as V, type ToolPlugin as W, type ToolConfigItem as X, type UserToolDefinition as Y, MODELS as Z, getModelByModelId as _, type ChatEvent as a, isTextEvent as a$, tool as a0, tools as a1, throwToolError as a2, rethrowToolError as a3, isToolError as a4, getArg as a5, type SearchResult as a6, type ToolCallStatus as a7, type ToolCallInfo as a8, type TokenUsage as a9, type StepEndEvent as aA, type StepEvent as aB, type ChatEventType as aC, createThinkingStart as aD, createThinkingDelta as aE, createThinkingEnd as aF, createSearchStart as aG, createSearchResult as aH, createSearchEnd as aI, createToolCallStart as aJ, createToolCallResult as aK, createToolCallOutput as aL, createToolCallRequest as aM, createTextDelta as aN, createDone as aO, createError as aP, createApiError as aQ, createRateLimitError as aR, createToolError as aS, createTimeoutError as aT, createParseError as aU, createAbort as aV, createStepStart as aW, createStepEnd as aX, isThinkingEvent as aY, isSearchEvent as aZ, isToolEvent as a_, type ErrorCategory as aa, type ErrorDetails as ab, type ToolUIShape as ac, type ThinkingStartEvent as ad, type ThinkingDeltaEvent as ae, type ThinkingEndEvent as af, type ThinkingEvent as ag, type SearchStartEvent as ah, type SearchResultEvent as ai, type SearchEndEvent as aj, type SearchEvent as ak, type ToolCallStartEvent as al, type ToolCallResultEvent as am, type ToolCallOutputEvent as an, type ToolApprovalRequestEvent as ao, type ToolCallRequestEvent as ap, type ToolEvent as aq, type TextDeltaEvent as ar, type TextEvent as as, type PlanStep as at, type PlanStepStatus as au, type DoneEvent as av, type ErrorEvent as aw, type AbortEvent as ax, type StatusEvent as ay, type StepStartEvent as az, type ModelOption as b, isStatusEvent as b0, isErrorEvent as b1, isAbortEvent as b2, isStepEvent as b3, isRetryableError as b4, CHAT_EVENT_TYPES as b5, routeModelToProvider as b6, routeModelWithDetails as b7, getDefaultProvider as b8, isModelForProvider as b9, type McpServerConfig as ba, type McpConnectionStatus as bb, type CompactStartEvent as bc, type CompactEndEvent as bd, type CompactEvent as be, type AgentPhase as bf, type AgentStatusEvent as bg, createAgentStatus as bh, createCompactStart as bi, createCompactEnd as bj, isCompactEvent as bk, type McpConnectionInfo as c, type Tool as d, type ChatMessage as e, MODEL_FAMILIES as f, DEEPSEEK_FAMILY as g, GPT_FAMILY as h, CLAUDE_FAMILY as i, MODEL_REGISTRY as j, getModelEntry as k, getModelFamily as l, getModelProtocol as m, getVisibleModels as n, getModelsByFamily as o, getModelsByProtocol as p, modelSupportsThinking as q, modelSupportsNativeSearch as r, getModelSearchStrategy as s, type ModelFamilyId as t, type ThinkingFormat as u, type ToolCallFormat as v, type ModelRegistryEntry as w, type ChatMode as x, type ThinkingMode as y, type AutoRunMode as z };
package/dist/events.d.ts CHANGED
@@ -1 +1 @@
1
- export { ax as AbortEvent, bc as AgentPhase, bd as AgentStatusEvent, b5 as CHAT_EVENT_TYPES, a as ChatEvent, aC as ChatEventType, av as DoneEvent, aa as ErrorCategory, ab as ErrorDetails, aw as ErrorEvent, at as PlanStep, au as PlanStepStatus, aj as SearchEndEvent, ak as SearchEvent, a6 as SearchResult, ai as SearchResultEvent, ah as SearchStartEvent, ay as StatusEvent, aA as StepEndEvent, aB as StepEvent, az as StepStartEvent, ar as TextDeltaEvent, as as TextEvent, ae as ThinkingDeltaEvent, af as ThinkingEndEvent, ag as ThinkingEvent, ad as ThinkingStartEvent, a9 as TokenUsage, ao as ToolApprovalRequestEvent, a8 as ToolCallInfo, an as ToolCallOutputEvent, ap as ToolCallRequestEvent, am as ToolCallResultEvent, al as ToolCallStartEvent, a7 as ToolCallStatus, U as ToolErrorShape, aq as ToolEvent, ac as ToolUIShape, aV as createAbort, be as createAgentStatus, aQ as createApiError, aO as createDone, aP as createError, aU as createParseError, aR as createRateLimitError, aI as createSearchEnd, aH as createSearchResult, aG as createSearchStart, aX as createStepEnd, aW as createStepStart, aN as createTextDelta, aE as createThinkingDelta, aF as createThinkingEnd, aD as createThinkingStart, aT as createTimeoutError, aL as createToolCallOutput, aM as createToolCallRequest, aK as createToolCallResult, aJ as createToolCallStart, aS as createToolError, b2 as isAbortEvent, b1 as isErrorEvent, b4 as isRetryableError, aZ as isSearchEvent, b0 as isStatusEvent, b3 as isStepEvent, a$ as isTextEvent, aY as isThinkingEvent, a4 as isThrowableToolError, a_ as isToolEvent } from './events-GWl1-vbT.js';
1
+ export { ax as AbortEvent, bf as AgentPhase, bg as AgentStatusEvent, b5 as CHAT_EVENT_TYPES, a as ChatEvent, aC as ChatEventType, bd as CompactEndEvent, be as CompactEvent, bc as CompactStartEvent, av as DoneEvent, aa as ErrorCategory, ab as ErrorDetails, aw as ErrorEvent, at as PlanStep, au as PlanStepStatus, aj as SearchEndEvent, ak as SearchEvent, a6 as SearchResult, ai as SearchResultEvent, ah as SearchStartEvent, ay as StatusEvent, aA as StepEndEvent, aB as StepEvent, az as StepStartEvent, ar as TextDeltaEvent, as as TextEvent, ae as ThinkingDeltaEvent, af as ThinkingEndEvent, ag as ThinkingEvent, ad as ThinkingStartEvent, a9 as TokenUsage, ao as ToolApprovalRequestEvent, a8 as ToolCallInfo, an as ToolCallOutputEvent, ap as ToolCallRequestEvent, am as ToolCallResultEvent, al as ToolCallStartEvent, a7 as ToolCallStatus, U as ToolErrorShape, aq as ToolEvent, ac as ToolUIShape, aV as createAbort, bh as createAgentStatus, aQ as createApiError, bj as createCompactEnd, bi as createCompactStart, aO as createDone, aP as createError, aU as createParseError, aR as createRateLimitError, aI as createSearchEnd, aH as createSearchResult, aG as createSearchStart, aX as createStepEnd, aW as createStepStart, aN as createTextDelta, aE as createThinkingDelta, aF as createThinkingEnd, aD as createThinkingStart, aT as createTimeoutError, aL as createToolCallOutput, aM as createToolCallRequest, aK as createToolCallResult, aJ as createToolCallStart, aS as createToolError, b2 as isAbortEvent, bk as isCompactEvent, b1 as isErrorEvent, b4 as isRetryableError, aZ as isSearchEvent, b0 as isStatusEvent, b3 as isStepEvent, a$ as isTextEvent, aY as isThinkingEvent, a4 as isThrowableToolError, a_ as isToolEvent } from './events-CU5D5ray.js';
package/dist/events.js CHANGED
@@ -1 +1 @@
1
- var t={doubao:{id:"doubao",displayName:"豆包",supportsVision:!0,supportsThinking:!0,thinkingFormat:"reasoning",supportsNativeSearch:!1,searchStrategy:"tavily",toolCallFormat:"responses",defaultMaxTokens:32768},deepseek:{id:"deepseek",displayName:"DeepSeek",supportsVision:!1,supportsThinking:!0,thinkingFormat:"reasoning",supportsNativeSearch:!1,searchStrategy:"tavily",toolCallFormat:"responses",defaultMaxTokens:32768},qwen:{id:"qwen",displayName:"通义千问",supportsVision:!1,supportsThinking:!0,thinkingFormat:"thinking_enabled",supportsNativeSearch:!1,searchStrategy:"tavily",toolCallFormat:"openai",defaultMaxTokens:32768},gemini:{id:"gemini",displayName:"Gemini",supportsVision:!0,supportsThinking:!0,thinkingFormat:"thought_signature",supportsNativeSearch:!1,searchStrategy:"tavily",toolCallFormat:"gemini",defaultMaxTokens:65536,requiresSpecialHandling:["thought_signature"]},gpt:{id:"gpt",displayName:"GPT",supportsVision:!0,supportsThinking:!0,thinkingFormat:"reasoning",supportsNativeSearch:!1,searchStrategy:"tavily",toolCallFormat:"openai",defaultMaxTokens:128e3},claude:{id:"claude",displayName:"Claude",supportsVision:!0,supportsThinking:!0,thinkingFormat:"reasoning",supportsNativeSearch:!1,searchStrategy:"tavily",toolCallFormat:"openai",defaultMaxTokens:2e5}},e=[{id:"doubao-seed-1-6-250615",displayName:"豆包 Seed 1.6",family:"doubao",protocol:"ark",visible:!0,supportsVision:!0,contextWindow:"256K",pricing:["输入 0.8 元/百万tokens","输出 2-8 元/百万tokens"]},{id:"doubao-seed-1-8-251215",displayName:"豆包 Seed 1.8",family:"doubao",protocol:"ark",contextWindow:"256K",pricing:["输入 0.8 元/百万tokens","输出 2-8 元/百万tokens"]},{id:"deepseek-v3-2-251201",displayName:"DeepSeek V3.2",family:"deepseek",protocol:"deepseek",visible:!0,supportsVision:!1,contextWindow:"128K",pricing:["输入 2 元/百万tokens","输出 3 元/百万tokens"]},{id:"qwen3-vl-plus",displayName:"通义千问 3 VL",family:"qwen",protocol:"qwen",visible:!0,supportsVision:!0,contextWindow:"128K",pricing:["输入 1 元/百万tokens","输出 10 元/百万tokens"]},{id:"gemini-3-pro-preview",displayName:"Gemini 3 Pro",family:"gemini",protocol:"gemini",visible:!0,supportsVision:!0,contextWindow:"1M",pricing:["输入 1.25 元/百万tokens","输出 10 元/百万tokens"]},{id:"gemini-2.5-flash-preview-05-20",displayName:"Gemini 2.5 Flash",family:"gemini",protocol:"gemini",contextWindow:"1M",pricing:["输入 0.15 元/百万tokens","输出 0.6 元/百万tokens"]},{id:"gemini-2.5-pro-preview-05-06",displayName:"Gemini 2.5 Pro",family:"gemini",protocol:"gemini",contextWindow:"1M",pricing:["输入 1.25 元/百万tokens","输出 10 元/百万tokens"]},{id:"openai/gpt-5.2",displayName:"GPT-5.2",family:"gpt",protocol:"openai",visible:!0,supportsVision:!0,contextWindow:"400K",pricing:["输入 12.6 元/百万tokens","输出 100.8 元/百万tokens"]},{id:"anthropic/claude-opus-4.5",displayName:"Claude Opus 4.5",family:"claude",protocol:"anthropic",visible:!0,supportsVision:!0,contextWindow:"200K",pricing:["输入 36 元/百万tokens","输出 180 元/百万tokens"]}];function n(t){return e.find(e=>e.id===t||t.includes(e.id))}function o(e){const o=n(e);if(o)return t[o.family]}function i(t){const e=n(t);if(!e)return!1;if("boolean"==typeof e.supportsVision)return e.supportsVision;const i=o(t);return i?.supportsVision??!1}function r(t){const e=o(t.id),n=i(t.id),r=e?.supportsThinking??!1,a=e?.supportsNativeSearch??!1,s=[];return n&&s.push("多模态"),r&&s.push("深度思考"),t.contextWindow&&s.push(`长上下文(${t.contextWindow})`),a&&s.push("联网搜索"),s}function a(t){return t instanceof Error&&"object"==typeof t.toolError&&null!==t.toolError&&"string"==typeof t.toolError.message}function s(t){return{type:"agent_status",data:{phase:t}}}e.filter(t=>t.visible).map(t=>{const e=o(t.id),n=e?.supportsThinking??!1,a=i(t.id);return{modelId:t.id,displayName:t.displayName,supportsThinking:n,supportsVision:a,tooltip:{features:r(t),cost:t.pricing}}});var p=["thinking_start","thinking_delta","thinking_end","search_start","search_result","search_end","tool_call_start","tool_call_result","tool_call_output","tool_approval_request","tool_call_request","text_delta","done","error","abort","step_start","step_end","agent_status"];function u(){return{type:"thinking_start",data:{startedAt:Date.now()}}}function d(t){return{type:"thinking_delta",data:{content:t}}}function l(t){const e=Date.now();return{type:"thinking_end",data:{endedAt:e,duration:e-t}}}function c(t){return{type:"search_start",data:{query:t,startedAt:Date.now()}}}function y(t,e){const n=Date.now();return{type:"search_result",data:{results:t,endedAt:n,duration:n-e}}}function g(t,e,n){const o=Date.now();return{type:"search_end",data:{success:t,error:n,endedAt:o,duration:o-e}}}function m(t,e,n){return{type:"tool_call_start",data:{id:t,name:e,args:n,startedAt:Date.now()}}}function f(t,e,n,o,i,r,a){const s=Date.now();return{type:"tool_call_result",data:{id:t,name:e,result:n,success:o,error:r,endedAt:s,duration:s-i,ui:a}}}function h(t,e,n,o){return{type:"tool_call_output",data:{id:t,name:e,stream:n,chunk:o,at:Date.now()}}}function k(t,e,n){return{type:"tool_call_request",data:{id:t,name:e,args:n,requestedAt:Date.now()}}}function _(t){return{type:"text_delta",data:{content:t}}}function w(t,e,n){return{type:"done",data:{text:t,usage:e,duration:n}}}function b(t){return{type:"error",data:t}}function v(t,e={}){return b({category:"api",message:t,...e})}function N(t,e,n){return b({category:"rate_limit",message:t,code:"RATE_LIMIT",statusCode:429,retryable:!0,retryAfter:e,context:n})}function x(t,e,n){return b({category:"tool",message:t,code:"TOOL_ERROR",context:e,cause:n,retryable:!1})}function T(t,e){return b({category:"timeout",message:t,code:"TIMEOUT",retryable:!0,context:e})}function S(t,e){return b({category:"parse",message:t,code:"PARSE_ERROR",cause:e,retryable:!1})}function V(t){return{type:"abort",data:{reason:t,abortedAt:Date.now()}}}function W(t,e){return{type:"step_start",data:{stepNumber:t,description:e,startedAt:Date.now()}}}function A(t,e){const n=Date.now();return{type:"step_end",data:{stepNumber:t,endedAt:n,duration:n-e}}}function D(t){return t.type.startsWith("thinking_")}function F(t){return t.type.startsWith("search_")}function q(t){return t.type.startsWith("tool_")}function M(t){return"text_delta"===t.type}function E(t){return"done"===t.type||"error"===t.type||"abort"===t.type}function C(t){return"error"===t.type}function R(t){return"abort"===t.type}function G(t){return t.type.startsWith("step_")}function K(t){return"error"===t.type&&!0===t.data.retryable}export{p as CHAT_EVENT_TYPES,V as createAbort,s as createAgentStatus,v as createApiError,w as createDone,b as createError,S as createParseError,N as createRateLimitError,g as createSearchEnd,y as createSearchResult,c as createSearchStart,A as createStepEnd,W as createStepStart,_ as createTextDelta,d as createThinkingDelta,l as createThinkingEnd,u as createThinkingStart,T as createTimeoutError,h as createToolCallOutput,k as createToolCallRequest,f as createToolCallResult,m as createToolCallStart,x as createToolError,R as isAbortEvent,C as isErrorEvent,K as isRetryableError,F as isSearchEvent,E as isStatusEvent,G as isStepEvent,M as isTextEvent,D as isThinkingEvent,a as isThrowableToolError,q as isToolEvent};
1
+ var t={doubao:{id:"doubao",displayName:"豆包",supportsVision:!0,supportsThinking:!0,thinkingFormat:"reasoning",supportsNativeSearch:!1,searchStrategy:"tavily",toolCallFormat:"responses",defaultMaxTokens:16384},deepseek:{id:"deepseek",displayName:"DeepSeek",supportsVision:!1,supportsThinking:!0,thinkingFormat:"reasoning",supportsNativeSearch:!1,searchStrategy:"tavily",toolCallFormat:"responses",defaultMaxTokens:32768},qwen:{id:"qwen",displayName:"通义千问",supportsVision:!1,supportsThinking:!0,thinkingFormat:"thinking_enabled",supportsNativeSearch:!1,searchStrategy:"tavily",toolCallFormat:"openai",defaultMaxTokens:32768},gemini:{id:"gemini",displayName:"Gemini",supportsVision:!0,supportsThinking:!0,thinkingFormat:"thought_signature",supportsNativeSearch:!1,searchStrategy:"tavily",toolCallFormat:"gemini",defaultMaxTokens:65536,requiresSpecialHandling:["thought_signature"]},gpt:{id:"gpt",displayName:"GPT",supportsVision:!0,supportsThinking:!0,thinkingFormat:"reasoning",supportsNativeSearch:!1,searchStrategy:"tavily",toolCallFormat:"openai",defaultMaxTokens:128e3},claude:{id:"claude",displayName:"Claude",supportsVision:!0,supportsThinking:!0,thinkingFormat:"reasoning",supportsNativeSearch:!1,searchStrategy:"tavily",toolCallFormat:"openai",defaultMaxTokens:64e3}},e=[{id:"doubao-seed-1-6-250615",displayName:"豆包 Seed 1.6",family:"doubao",protocol:"ark",visible:!0,supportsVision:!0,contextWindow:"256K",contextWindowTokens:256e3,pricing:["输入 0.8 元/百万tokens","输出 2-8 元/百万tokens"]},{id:"doubao-seed-1-8-251215",displayName:"豆包 Seed 1.8",family:"doubao",protocol:"ark",contextWindow:"256K",contextWindowTokens:256e3,pricing:["输入 0.8 元/百万tokens","输出 2-8 元/百万tokens"]},{id:"deepseek-v3-2-251201",displayName:"DeepSeek V3.2",family:"deepseek",protocol:"deepseek",visible:!0,supportsVision:!1,contextWindow:"128K",contextWindowTokens:128e3,pricing:["输入 2 元/百万tokens","输出 3 元/百万tokens"]},{id:"qwen3-vl-plus",displayName:"通义千问 3 VL",family:"qwen",protocol:"qwen",visible:!0,supportsVision:!0,contextWindow:"262K",contextWindowTokens:262144,pricing:["输入 1 元/百万tokens","输出 10 元/百万tokens"]},{id:"qwen3.5-plus",displayName:"通义千问 3.5 Plus",family:"qwen",protocol:"qwen",contextWindow:"1M",contextWindowTokens:1e6,pricing:["输入 0.8 元/百万tokens","输出 4.8 元/百万tokens"]},{id:"qwen-long",displayName:"通义千问 Long",family:"qwen",protocol:"qwen",contextWindow:"10M",contextWindowTokens:1e7,pricing:["输入 0.5 元/百万tokens","输出 2 元/百万tokens"]},{id:"gemini-3-pro-preview",displayName:"Gemini 3 Pro",family:"gemini",protocol:"gemini",visible:!0,supportsVision:!0,contextWindow:"1M",contextWindowTokens:1e6,pricing:["输入 1.25 元/百万tokens","输出 10 元/百万tokens"]},{id:"gemini-2.5-flash-preview-05-20",displayName:"Gemini 2.5 Flash",family:"gemini",protocol:"gemini",contextWindow:"1M",contextWindowTokens:1e6,pricing:["输入 0.15 元/百万tokens","输出 0.6 元/百万tokens"]},{id:"gemini-2.5-pro-preview-05-06",displayName:"Gemini 2.5 Pro",family:"gemini",protocol:"gemini",contextWindow:"1M",contextWindowTokens:1e6,pricing:["输入 1.25 元/百万tokens","输出 10 元/百万tokens"]},{id:"openai/gpt-5.2",displayName:"GPT-5.2",family:"gpt",protocol:"openai",visible:!0,supportsVision:!0,contextWindow:"400K",contextWindowTokens:4e5,pricing:["输入 12.6 元/百万tokens","输出 100.8 元/百万tokens"]},{id:"anthropic/claude-opus-4.5",displayName:"Claude Opus 4.5",family:"claude",protocol:"anthropic",visible:!0,supportsVision:!0,contextWindow:"200K",contextWindowTokens:2e5,pricing:["输入 36 元/百万tokens","输出 180 元/百万tokens"]}];function n(t){return e.find(e=>e.id===t||t.includes(e.id))}function o(e){const o=n(e);if(o)return t[o.family]}function i(t){const e=n(t);if(!e)return!1;if("boolean"==typeof e.supportsVision)return e.supportsVision;const i=o(t);return i?.supportsVision??!1}function r(t){const e=o(t.id),n=i(t.id),r=e?.supportsThinking??!1,a=e?.supportsNativeSearch??!1,s=[];return n&&s.push("多模态"),r&&s.push("深度思考"),t.contextWindow&&s.push(`长上下文(${t.contextWindow})`),a&&s.push("联网搜索"),s}function a(t){return t instanceof Error&&"object"==typeof t.toolError&&null!==t.toolError&&"string"==typeof t.toolError.message}function s(t){return{type:"agent_status",data:{phase:t}}}e.filter(t=>t.visible).map(t=>{const e=o(t.id),n=e?.supportsThinking??!1,a=i(t.id);return{modelId:t.id,displayName:t.displayName,supportsThinking:n,supportsVision:a,tooltip:{features:r(t),cost:t.pricing}}});var p=["thinking_start","thinking_delta","thinking_end","search_start","search_result","search_end","tool_call_start","tool_call_result","tool_call_output","tool_approval_request","tool_call_request","text_delta","done","error","abort","step_start","step_end","compact_start","compact_end","agent_status"];function u(){return{type:"thinking_start",data:{startedAt:Date.now()}}}function d(t){return{type:"thinking_delta",data:{content:t}}}function c(t){const e=Date.now();return{type:"thinking_end",data:{endedAt:e,duration:e-t}}}function l(t){return{type:"search_start",data:{query:t,startedAt:Date.now()}}}function g(t,e){const n=Date.now();return{type:"search_result",data:{results:t,endedAt:n,duration:n-e}}}function y(t,e,n){const o=Date.now();return{type:"search_end",data:{success:t,error:n,endedAt:o,duration:o-e}}}function m(t,e,n){return{type:"tool_call_start",data:{id:t,name:e,args:n,startedAt:Date.now()}}}function k(t,e,n,o,i,r,a){const s=Date.now();return{type:"tool_call_result",data:{id:t,name:e,result:n,success:o,error:r,endedAt:s,duration:s-i,ui:a}}}function f(t,e,n,o){return{type:"tool_call_output",data:{id:t,name:e,stream:n,chunk:o,at:Date.now()}}}function h(t,e,n){return{type:"tool_call_request",data:{id:t,name:e,args:n,requestedAt:Date.now()}}}function _(t){return{type:"text_delta",data:{content:t}}}function w(t,e,n){return{type:"done",data:{text:t,usage:e,duration:n}}}function x(t){return{type:"error",data:t}}function T(t,e={}){return x({category:"api",message:t,...e})}function b(t,e,n){return x({category:"rate_limit",message:t,code:"RATE_LIMIT",statusCode:429,retryable:!0,retryAfter:e,context:n})}function W(t,e,n){return x({category:"tool",message:t,code:"TOOL_ERROR",context:e,cause:n,retryable:!1})}function v(t,e){return x({category:"timeout",message:t,code:"TIMEOUT",retryable:!0,context:e})}function N(t,e){return x({category:"parse",message:t,code:"PARSE_ERROR",cause:e,retryable:!1})}function S(t){return{type:"abort",data:{reason:t,abortedAt:Date.now()}}}function V(t,e){return{type:"step_start",data:{stepNumber:t,description:e,startedAt:Date.now()}}}function q(t,e){const n=Date.now();return{type:"step_end",data:{stepNumber:t,endedAt:n,duration:n-e}}}function A(t,e){return{type:"compact_start",data:{estimatedTokens:t,budget:e,startedAt:Date.now()}}}function D(t,e,n,o,i){const r=Date.now();return{type:"compact_end",data:{success:t,compressedTokens:e,originalMessageCount:n,compressedMessageCount:o,endedAt:r,duration:r-i}}}function M(t){return t.type.startsWith("thinking_")}function F(t){return t.type.startsWith("search_")}function C(t){return t.type.startsWith("tool_")}function E(t){return"text_delta"===t.type}function R(t){return"done"===t.type||"error"===t.type||"abort"===t.type}function G(t){return"error"===t.type}function K(t){return"abort"===t.type}function O(t){return t.type.startsWith("step_")}function P(t){return t.type.startsWith("compact_")}function I(t){return"error"===t.type&&!0===t.data.retryable}export{p as CHAT_EVENT_TYPES,S as createAbort,s as createAgentStatus,T as createApiError,D as createCompactEnd,A as createCompactStart,w as createDone,x as createError,N as createParseError,b as createRateLimitError,y as createSearchEnd,g as createSearchResult,l as createSearchStart,q as createStepEnd,V as createStepStart,_ as createTextDelta,d as createThinkingDelta,c as createThinkingEnd,u as createThinkingStart,v as createTimeoutError,f as createToolCallOutput,h as createToolCallRequest,k as createToolCallResult,m as createToolCallStart,W as createToolError,K as isAbortEvent,P as isCompactEvent,G as isErrorEvent,I as isRetryableError,F as isSearchEvent,R as isStatusEvent,O as isStepEvent,E as isTextEvent,M as isThinkingEvent,a as isThrowableToolError,C as isToolEvent};
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { A as AgentConfig, T as ToolExecutor$1, M as ModelFamilyConfig, R as RouteResult, C as ChatOptions, a as ChatEvent, b as ModelOption, c as McpConnectionInfo, J as JsonSchemaObject, d as Tool, e as ChatMessage } from './events-GWl1-vbT.js';
2
- export { ax as AbortEvent, N as ActionType, B as AutoRunConfig, z as AutoRunMode, b5 as CHAT_EVENT_TYPES, i as CLAUDE_FAMILY, aC as ChatEventType, x as ChatMode, g as DEEPSEEK_FAMILY, D as DOUBAO_FAMILY, av as DoneEvent, aa as ErrorCategory, ab as ErrorDetails, aw as ErrorEvent, O as ExecResult, G as GEMINI_FAMILY, h as GPT_FAMILY, Z as MODELS, f as MODEL_FAMILIES, j as MODEL_REGISTRY, bb as McpConnectionStatus, ba as McpServerConfig, t as ModelFamilyId, w as ModelRegistryEntry, at as PlanStep, au as PlanStepStatus, P as ProtocolId, H as ProviderType, Q as QWEN_FAMILY, L as RenderType, F as ResponsesApiTool, aj as SearchEndEvent, ak as SearchEvent, a6 as SearchResult, ai as SearchResultEvent, ah as SearchStartEvent, S as SearchStrategy, ay as StatusEvent, aA as StepEndEvent, aB as StepEvent, az as StepStartEvent, ar as TextDeltaEvent, as as TextEvent, ae as ThinkingDeltaEvent, af as ThinkingEndEvent, ag as ThinkingEvent, u as ThinkingFormat, y as ThinkingMode, ad as ThinkingStartEvent, a9 as TokenUsage, ao as ToolApprovalRequestEvent, v as ToolCallFormat, a8 as ToolCallInfo, an as ToolCallOutputEvent, ap as ToolCallRequestEvent, am as ToolCallResultEvent, al as ToolCallStartEvent, a7 as ToolCallStatus, X as ToolConfigItem, I as ToolContext, E as ToolDefinition, U as ToolError, V as ToolErrorCode, U as ToolErrorShape, aq as ToolEvent, W as ToolPlugin, K as ToolUI, ac as ToolUIShape, Y as UserToolDefinition, aV as createAbort, aQ as createApiError, aO as createDone, aP as createError, aU as createParseError, aR as createRateLimitError, aI as createSearchEnd, aH as createSearchResult, aG as createSearchStart, aX as createStepEnd, aW as createStepStart, aN as createTextDelta, aE as createThinkingDelta, aF as createThinkingEnd, aD as createThinkingStart, aT as createTimeoutError, aL as createToolCallOutput, aM as createToolCallRequest, aK as createToolCallResult, aJ as createToolCallStart, aS as createToolError, a5 as getArg, b8 as getDefaultProvider, _ as getModelByModelId, k as getModelEntry, l as getModelFamily, m as getModelProtocol, s as getModelSearchStrategy, o as getModelsByFamily, p as getModelsByProtocol, n as getVisibleModels, b2 as isAbortEvent, b1 as isErrorEvent, b9 as isModelForProvider, b4 as isRetryableError, aZ as isSearchEvent, b0 as isStatusEvent, b3 as isStepEvent, a$ as isTextEvent, aY as isThinkingEvent, a4 as isThrowableToolError, a4 as isToolError, a_ as isToolEvent, r as modelSupportsNativeSearch, q as modelSupportsThinking, $ as resolveTools, a3 as rethrowToolError, b6 as routeModelToProvider, b7 as routeModelWithDetails, a2 as throwToolError, a0 as tool, a1 as tools } from './events-GWl1-vbT.js';
1
+ import { A as AgentConfig, T as ToolExecutor$1, M as ModelFamilyConfig, R as RouteResult, C as ChatOptions, a as ChatEvent, b as ModelOption, c as McpConnectionInfo, J as JsonSchemaObject, d as Tool, e as ChatMessage } from './events-CU5D5ray.js';
2
+ export { ax as AbortEvent, N as ActionType, B as AutoRunConfig, z as AutoRunMode, b5 as CHAT_EVENT_TYPES, i as CLAUDE_FAMILY, aC as ChatEventType, x as ChatMode, g as DEEPSEEK_FAMILY, D as DOUBAO_FAMILY, av as DoneEvent, aa as ErrorCategory, ab as ErrorDetails, aw as ErrorEvent, O as ExecResult, G as GEMINI_FAMILY, h as GPT_FAMILY, Z as MODELS, f as MODEL_FAMILIES, j as MODEL_REGISTRY, bb as McpConnectionStatus, ba as McpServerConfig, t as ModelFamilyId, w as ModelRegistryEntry, at as PlanStep, au as PlanStepStatus, P as ProtocolId, H as ProviderType, Q as QWEN_FAMILY, L as RenderType, F as ResponsesApiTool, aj as SearchEndEvent, ak as SearchEvent, a6 as SearchResult, ai as SearchResultEvent, ah as SearchStartEvent, S as SearchStrategy, ay as StatusEvent, aA as StepEndEvent, aB as StepEvent, az as StepStartEvent, ar as TextDeltaEvent, as as TextEvent, ae as ThinkingDeltaEvent, af as ThinkingEndEvent, ag as ThinkingEvent, u as ThinkingFormat, y as ThinkingMode, ad as ThinkingStartEvent, a9 as TokenUsage, ao as ToolApprovalRequestEvent, v as ToolCallFormat, a8 as ToolCallInfo, an as ToolCallOutputEvent, ap as ToolCallRequestEvent, am as ToolCallResultEvent, al as ToolCallStartEvent, a7 as ToolCallStatus, X as ToolConfigItem, I as ToolContext, E as ToolDefinition, U as ToolError, V as ToolErrorCode, U as ToolErrorShape, aq as ToolEvent, W as ToolPlugin, K as ToolUI, ac as ToolUIShape, Y as UserToolDefinition, aV as createAbort, aQ as createApiError, aO as createDone, aP as createError, aU as createParseError, aR as createRateLimitError, aI as createSearchEnd, aH as createSearchResult, aG as createSearchStart, aX as createStepEnd, aW as createStepStart, aN as createTextDelta, aE as createThinkingDelta, aF as createThinkingEnd, aD as createThinkingStart, aT as createTimeoutError, aL as createToolCallOutput, aM as createToolCallRequest, aK as createToolCallResult, aJ as createToolCallStart, aS as createToolError, a5 as getArg, b8 as getDefaultProvider, _ as getModelByModelId, k as getModelEntry, l as getModelFamily, m as getModelProtocol, s as getModelSearchStrategy, o as getModelsByFamily, p as getModelsByProtocol, n as getVisibleModels, b2 as isAbortEvent, b1 as isErrorEvent, b9 as isModelForProvider, b4 as isRetryableError, aZ as isSearchEvent, b0 as isStatusEvent, b3 as isStepEvent, a$ as isTextEvent, aY as isThinkingEvent, a4 as isThrowableToolError, a4 as isToolError, a_ as isToolEvent, r as modelSupportsNativeSearch, q as modelSupportsThinking, $ as resolveTools, a3 as rethrowToolError, b6 as routeModelToProvider, b7 as routeModelWithDetails, a2 as throwToolError, a0 as tool, a1 as tools } from './events-CU5D5ray.js';
3
3
 
4
4
  /** 运行时配置(API Keys 和 URLs) */
5
5
  interface RuntimeConfig {
@@ -252,6 +252,8 @@ interface OrchestratorConfig {
252
252
  * 3. 客户端执行后,发新请求继续对话
253
253
  */
254
254
  clientToolNames?: Set<string>;
255
+ /** 上下文总结回调(走 ai-server 等外部服务) */
256
+ summarize?: (systemPrompt: string, userPrompt: string) => Promise<string>;
255
257
  }
256
258
  /** Orchestrator 上下文 */
257
259
  interface OrchestratorContext {
@@ -753,6 +755,8 @@ declare class ChatOrchestrator {
753
755
  * 构建标准化消息列表
754
756
  */
755
757
  private buildMessages;
758
+ /** 检测并执行上下文压缩,通过注入的 summarize 回调走 ai-server */
759
+ private compactIfNeeded;
756
760
  }
757
761
  /**
758
762
  * 创建 Orchestrator 实例
package/dist/index.js CHANGED
@@ -1 +1 @@
1
- import{Client as e}from"@modelcontextprotocol/sdk/client/index.js";import{StdioClientTransport as t}from"@modelcontextprotocol/sdk/client/stdio.js";import{SSEClientTransport as o}from"@modelcontextprotocol/sdk/client/sse.js";import{appendFileSync as n}from"fs";import{createGateway as s,streamText as i,tool as r}from"ai";import{z as a}from"zod";var l={id:"doubao",displayName:"豆包",supportsVision:!0,supportsThinking:!0,thinkingFormat:"reasoning",supportsNativeSearch:!1,searchStrategy:"tavily",toolCallFormat:"responses",defaultMaxTokens:32768},c={id:"deepseek",displayName:"DeepSeek",supportsVision:!1,supportsThinking:!0,thinkingFormat:"reasoning",supportsNativeSearch:!1,searchStrategy:"tavily",toolCallFormat:"responses",defaultMaxTokens:32768},u={id:"qwen",displayName:"通义千问",supportsVision:!1,supportsThinking:!0,thinkingFormat:"thinking_enabled",supportsNativeSearch:!1,searchStrategy:"tavily",toolCallFormat:"openai",defaultMaxTokens:32768},p={id:"gemini",displayName:"Gemini",supportsVision:!0,supportsThinking:!0,thinkingFormat:"thought_signature",supportsNativeSearch:!1,searchStrategy:"tavily",toolCallFormat:"gemini",defaultMaxTokens:65536,requiresSpecialHandling:["thought_signature"]},d={id:"gpt",displayName:"GPT",supportsVision:!0,supportsThinking:!0,thinkingFormat:"reasoning",supportsNativeSearch:!1,searchStrategy:"tavily",toolCallFormat:"openai",defaultMaxTokens:128e3},m={id:"claude",displayName:"Claude",supportsVision:!0,supportsThinking:!0,thinkingFormat:"reasoning",supportsNativeSearch:!1,searchStrategy:"tavily",toolCallFormat:"openai",defaultMaxTokens:2e5},g={doubao:l,deepseek:c,qwen:u,gemini:p,gpt:d,claude:m},h=[{id:"doubao-seed-1-6-250615",displayName:"豆包 Seed 1.6",family:"doubao",protocol:"ark",visible:!0,supportsVision:!0,contextWindow:"256K",pricing:["输入 0.8 元/百万tokens","输出 2-8 元/百万tokens"]},{id:"doubao-seed-1-8-251215",displayName:"豆包 Seed 1.8",family:"doubao",protocol:"ark",contextWindow:"256K",pricing:["输入 0.8 元/百万tokens","输出 2-8 元/百万tokens"]},{id:"deepseek-v3-2-251201",displayName:"DeepSeek V3.2",family:"deepseek",protocol:"deepseek",visible:!0,supportsVision:!1,contextWindow:"128K",pricing:["输入 2 元/百万tokens","输出 3 元/百万tokens"]},{id:"qwen3-vl-plus",displayName:"通义千问 3 VL",family:"qwen",protocol:"qwen",visible:!0,supportsVision:!0,contextWindow:"128K",pricing:["输入 1 元/百万tokens","输出 10 元/百万tokens"]},{id:"gemini-3-pro-preview",displayName:"Gemini 3 Pro",family:"gemini",protocol:"gemini",visible:!0,supportsVision:!0,contextWindow:"1M",pricing:["输入 1.25 元/百万tokens","输出 10 元/百万tokens"]},{id:"gemini-2.5-flash-preview-05-20",displayName:"Gemini 2.5 Flash",family:"gemini",protocol:"gemini",contextWindow:"1M",pricing:["输入 0.15 元/百万tokens","输出 0.6 元/百万tokens"]},{id:"gemini-2.5-pro-preview-05-06",displayName:"Gemini 2.5 Pro",family:"gemini",protocol:"gemini",contextWindow:"1M",pricing:["输入 1.25 元/百万tokens","输出 10 元/百万tokens"]},{id:"openai/gpt-5.2",displayName:"GPT-5.2",family:"gpt",protocol:"openai",visible:!0,supportsVision:!0,contextWindow:"400K",pricing:["输入 12.6 元/百万tokens","输出 100.8 元/百万tokens"]},{id:"anthropic/claude-opus-4.5",displayName:"Claude Opus 4.5",family:"claude",protocol:"anthropic",visible:!0,supportsVision:!0,contextWindow:"200K",pricing:["输入 36 元/百万tokens","输出 180 元/百万tokens"]}];function y(e){return h.find(t=>t.id===e||e.includes(t.id))}function f(e){const t=y(e);if(t)return g[t.family]}function k(e){const t=y(e);return t?.protocol}function _(){return h.filter(e=>e.visible)}function b(e){return h.filter(t=>t.family===e)}function w(e){return h.filter(t=>t.protocol===e)}function T(e){const t=f(e);return t?.supportsThinking??!1}function v(e){const t=f(e);return t?.supportsNativeSearch??!1}function C(e){const t=y(e);if(!t)return!1;if("boolean"==typeof t.supportsVision)return t.supportsVision;const o=f(e);return o?.supportsVision??!1}function S(e){const t=f(e);return t?.searchStrategy??"tavily"}function A(e){const t=f(e.id),o=C(e.id),n=t?.supportsThinking??!1,s=t?.supportsNativeSearch??!1,i=[];return o&&i.push("多模态"),n&&i.push("深度思考"),e.contextWindow&&i.push(`长上下文(${e.contextWindow})`),s&&i.push("联网搜索"),i}var x=_().map(e=>{const t=f(e.id),o=t?.supportsThinking??!1,n=C(e.id);return{modelId:e.id,displayName:e.displayName,supportsThinking:o,supportsVision:n,tooltip:{features:A(e),cost:e.pricing}}});function R(e){return x.find(t=>t.modelId===e)}function $(e){return e instanceof Error&&"object"==typeof e.toolError&&null!==e.toolError&&"string"==typeof e.toolError.message}function N(e,t,o){const n={message:e,code:t,...o},s=new Error(e);throw Object.defineProperty(s,"toolError",{value:n,enumerable:!0}),s}function K(e,t,o){if($(e))throw e;N(e instanceof Error?e.message:String(e),t,o)}function M(e,t){return e[t]}function q(e){return{tools:[e]}}function I(e){return{tools:e}}async function O(e){const t=[];for(const o of e){const e=await o;"tools"in e&&Array.isArray(e.tools)?t.push(...e.tools):"name"in e&&"execute"in e&&t.push(e)}return t}function P(e){return{type:"agent_status",data:{phase:e}}}var E=["thinking_start","thinking_delta","thinking_end","search_start","search_result","search_end","tool_call_start","tool_call_result","tool_call_output","tool_approval_request","tool_call_request","text_delta","done","error","abort","step_start","step_end","agent_status"];function D(){return{type:"thinking_start",data:{startedAt:Date.now()}}}function U(e){return{type:"thinking_delta",data:{content:e}}}function j(e){const t=Date.now();return{type:"thinking_end",data:{endedAt:t,duration:t-e}}}function J(e){return{type:"search_start",data:{query:e,startedAt:Date.now()}}}function W(e,t){const o=Date.now();return{type:"search_result",data:{results:e,endedAt:o,duration:o-t}}}function F(e,t,o){const n=Date.now();return{type:"search_end",data:{success:e,error:o,endedAt:n,duration:n-t}}}function V(e,t,o){return{type:"tool_call_start",data:{id:e,name:t,args:o,startedAt:Date.now()}}}function B(e,t,o,n,s,i,r){const a=Date.now();return{type:"tool_call_result",data:{id:e,name:t,result:o,success:n,error:i,endedAt:a,duration:a-s,ui:r}}}function G(e,t,o,n){return{type:"tool_call_output",data:{id:e,name:t,stream:o,chunk:n,at:Date.now()}}}function z(e,t,o){return{type:"tool_call_request",data:{id:e,name:t,args:o,requestedAt:Date.now()}}}function L(e){return{type:"text_delta",data:{content:e}}}function Q(e,t,o){return{type:"done",data:{text:e,usage:t,duration:o}}}function H(e){return{type:"error",data:e}}function Z(e,t={}){return H({category:"api",message:e,...t})}function X(e,t,o){return H({category:"rate_limit",message:e,code:"RATE_LIMIT",statusCode:429,retryable:!0,retryAfter:t,context:o})}function Y(e,t,o){return H({category:"tool",message:e,code:"TOOL_ERROR",context:t,cause:o,retryable:!1})}function ee(e,t){return H({category:"timeout",message:e,code:"TIMEOUT",retryable:!0,context:t})}function te(e,t){return H({category:"parse",message:e,code:"PARSE_ERROR",cause:t,retryable:!1})}function oe(e){return{type:"abort",data:{reason:e,abortedAt:Date.now()}}}function ne(e,t){return{type:"step_start",data:{stepNumber:e,description:t,startedAt:Date.now()}}}function se(e,t){const o=Date.now();return{type:"step_end",data:{stepNumber:e,endedAt:o,duration:o-t}}}function ie(e){return e.type.startsWith("thinking_")}function re(e){return e.type.startsWith("search_")}function ae(e){return e.type.startsWith("tool_")}function le(e){return"text_delta"===e.type}function ce(e){return"done"===e.type||"error"===e.type||"abort"===e.type}function ue(e){return"error"===e.type}function pe(e){return"abort"===e.type}function de(e){return e.type.startsWith("step_")}function me(e){return"error"===e.type&&!0===e.data.retryable}var ge=["rm -rf /","rm -rf ~","format","mkfs","dd if=","shutdown","reboot","sudo rm","sudo format"];function he(e=process.cwd()){return{async executeCommand(t,o,n,s){if(n?.aborted)return{success:!1,error:"操作已取消"};if(function(e){const t=e.toLowerCase().trim();return ge.some(e=>t.includes(e.toLowerCase()))}(t))return{success:!1,error:"该命令被安全策略阻止"};try{const{spawn:i}=await import("child_process");return new Promise(r=>{let a="",l="",c=!1,u=null;const p=i("sh",["-c",t],{cwd:o||e,env:process.env,detached:"win32"!==process.platform}),d=e=>{if(!c){c=!0;try{"win32"!==process.platform&&"number"==typeof p.pid?process.kill(-p.pid,e):p.kill(e)}catch{try{p.kill(e)}catch{}}u&&clearTimeout(u),u=setTimeout(()=>{try{"win32"!==process.platform&&"number"==typeof p.pid?process.kill(-p.pid,"SIGKILL"):p.kill("SIGKILL")}catch{}},1500)}},m=setTimeout(()=>{c||(d("SIGTERM"),r({success:!1,error:"命令执行超时(30秒)"}))},3e4),g=()=>{c||(d("SIGTERM"),clearTimeout(m),r({success:!1,error:"操作已取消"}))};n?.addEventListener("abort",g),p.stdout?.on("data",e=>{const t=e.toString();a+=t,s?.onStdout?.(t)}),p.stderr?.on("data",e=>{const t=e.toString();l+=t,s?.onStderr?.(t)}),p.on("close",e=>{if(clearTimeout(m),n?.removeEventListener("abort",g),u&&(clearTimeout(u),u=null),c)return;const t=a.trim(),o=l.trim();if(0===e)r({success:!0,output:t||o||"执行成功"});else if(t){r({success:!0,output:t+(o?`\n[警告: ${o}]`:"")})}else r(o?{success:!1,error:o}:{success:!1,error:`命令退出码: ${e}`})}),p.on("error",e=>{clearTimeout(m),n?.removeEventListener("abort",g),u&&(clearTimeout(u),u=null),c||r({success:!1,error:e.message})})})}catch(e){return{success:!1,error:e instanceof Error?e.message:String(e)}}}}}var ye="https://ark.cn-beijing.volces.com/api/v3",fe="https://openrouter.ai/api/v1",ke="doubao-seed-1-6-250615";function _e(e){return be(e).provider}function be(e){const t=y(e);return t?{provider:t.protocol,registryEntry:t,familyConfig:f(e),isDefault:!1}:{provider:"ark",isDefault:!0}}function we(){return"ark"}function Te(e,t){return _e(e)===t}var ve=!1,Ce=null,Se=class e{prefix;constructor(e){this.prefix=e}static enable(e){ve=e}static isEnabled(){return ve}static setLogFile(e){Ce=e}static module(t){return new e(`[${t}]`)}debug(...e){ve&&this.writeToFile("debug",e)}info(...e){ve&&this.writeToFile("info",e)}warn(...e){ve&&this.writeToFile("warn",e)}error(...e){ve&&this.writeToFile("error",e)}writeToFile(e,t){if(Ce)try{const o=JSON.stringify({t:Date.now(),level:e,module:this.prefix,args:t.map(e=>{try{return"string"==typeof e?e:JSON.parse(JSON.stringify(e))}catch{return String(e)}})});n(Ce,o+"\n")}catch{}}},Ae=Se.module("MCP"),xe=class{connections=new Map;async connectAll(e){const t=await Promise.allSettled(e.map(e=>this.connect(e)));for(let o=0;o<t.length;o++){const n=t[o],s=e[o].name;"rejected"===n.status&&Ae.error(`[${s}] 连接失败:`,n.reason)}}async connect(n){const{name:s}=n;this.connections.has(s)&&await this.disconnect(s),Ae.info(`[${s}] 正在连接...`);const i=new e({name:"ai-chat-mcp-client",version:"1.0.0"});let r;if("stdio"===n.transport){if(!n.command)throw new Error(`[${s}] stdio 模式必须指定 command`);r=new t({command:n.command,args:n.args,env:n.env,cwd:n.cwd})}else{if("sse"!==n.transport)throw new Error(`[${s}] 不支持的传输方式: ${n.transport}`);if(!n.url)throw new Error(`[${s}] sse 模式必须指定 url`);r=new o(new URL(n.url))}const a={config:n,client:i,transport:r,status:"connecting",tools:[]};this.connections.set(s,a);try{await i.connect(r),a.status="connected",Ae.info(`[${s}] 已连接`);const e=await this.discoverTools(a);a.tools=e,Ae.info(`[${s}] 发现 ${e.length} 个工具:`,e.map(e=>e.name))}catch(e){throw a.status="error",a.error=e instanceof Error?e.message:String(e),Ae.error(`[${s}] 连接失败:`,a.error),e}}async discoverTools(e){const{client:t,config:o}=e,{tools:n}=await t.listTools();return n.map(e=>this.adaptTool(e,o.name,t))}adaptTool(e,t,o){const n=this.convertSchema(e.inputSchema);return{name:e.name,description:e.description||`MCP tool from ${t}`,parameters:n,execute:async t=>{const n=await o.callTool({name:e.name,arguments:t}),s=[];if(Array.isArray(n.content))for(const e of n.content)if("object"==typeof e&&null!==e){const t=e;"text"===t.type&&"string"==typeof t.text?s.push(t.text):"image"===t.type?s.push(`[image: ${t.mimeType||"unknown"}]`):"resource"===t.type&&s.push(JSON.stringify(t))}return{text:s.join("\n")||JSON.stringify(n.content)}}}}convertSchema(e){const t={},o=[],n=e.properties;if(n)for(const[e,o]of Object.entries(n))t[e]=this.convertProperty(o);return Array.isArray(e.required)&&o.push(...e.required.filter(e=>"string"==typeof e)),{type:"object",properties:t,required:o.length>0?o:void 0}}convertProperty(e){const t={type:"string"==typeof e.type?e.type:"string"};if("string"==typeof e.description&&(t.description=e.description),Array.isArray(e.enum)&&(t.enum=e.enum),e.items&&"object"==typeof e.items&&(t.items=this.convertProperty(e.items)),e.properties&&"object"==typeof e.properties){t.properties={};for(const[o,n]of Object.entries(e.properties))t.properties[o]=this.convertProperty(n)}return Array.isArray(e.required)&&(t.required=e.required.filter(e=>"string"==typeof e)),t}getAllTools(){const e=[];for(const t of this.connections.values())"connected"===t.status&&e.push(...t.tools);return e}getConnectionInfos(){return Array.from(this.connections.values()).map(e=>({name:e.config.name,status:e.status,toolCount:e.tools.length,error:e.error}))}async disconnect(e){const t=this.connections.get(e);if(t)try{await t.client.close(),Ae.info(`[${e}] 已断开`)}catch(t){Ae.error(`[${e}] 断开失败:`,t)}finally{t.status="disconnected",t.tools=[],this.connections.delete(e)}}async disconnectAll(){const e=Array.from(this.connections.keys());await Promise.allSettled(e.map(e=>this.disconnect(e)))}},Re=Se.module("ContextCompressor");function $e(e,t){const o=e.reduce((e,t)=>e+(t.content?.length??0),0);if(o<8e4)return!1;Re.info(`Context 压缩触发: ${o} 字符, ${e.length} 条消息`);let n=0;"system"===e[0]?.role&&(n=1);let s=n;for(let t=n;t<e.length;t++)if("user"===e[t].role){s=t+1;break}const i=Math.max(s,e.length-10);if(i-s<4)return!1;const r=function(e){const t=[];let o="";for(const n of e){if("assistant"===n.role&&n.toolCalls)for(const e of n.toolCalls)t.push(e.name);"assistant"===n.role&&n.content&&(o+=n.content.slice(0,200)+"\n")}return[`[上下文压缩] 以下是之前 ${e.length} 条消息的摘要:`,t.length>0?`- 执行了 ${t.length} 次工具调用: ${[...new Set(t)].join(", ")}`:"",o?`- AI 回复摘要: ${o.slice(0,500)}`:""].filter(Boolean).join("\n")}(e.slice(s,i)),a=[...e.slice(0,s),{role:"system",content:r},...e.slice(i)],l=a.reduce((e,t)=>e+(t.content?.length??0),0);return Re.info(`Context 压缩完成: ${e.length} → ${a.length} 条消息, ${o} → ${l} 字符`),e.length=0,e.push(...a),!0}var Ne="web_search_ai";var Ke=Se.module("Orchestrator");function Me(e){const t=new Map;for(const o of e){const e=String(o?.url??"").trim();if(!e)continue;const n=String(o?.snippet??"").trim();let s=String(o?.title??"").trim();if(!s)try{s=new URL(e).hostname}catch{s=e}const i=t.get(e);i?(!i.snippet&&n&&(i.snippet=n),!i.title&&s&&(i.title=s)):t.set(e,{title:s,url:e,snippet:n})}return Array.from(t.values())}var qe=class{config;constructor(e){this.config={maxIterations:25,...e}}async*chat(e,t,o,n){const s=Date.now(),i=this.config.maxIterations??25,r=this.buildMessages(o,t);$e(r)&&Ke.info("初始历史已压缩");let a=0,l="",c=[],u=0,p=!1,d=!1,m="",g=0,h={promptTokens:0,completionTokens:0,totalTokens:0,reasoningTokens:0,cachedTokens:0},y=!1;for(;a<i;){if(o.signal.aborted)return void(yield oe("请求已取消"));a++,a>1&&$e(r);const i=Date.now();Ke.info(`======= 第 ${a} 轮开始 =======`),yield ne(a),yield P("thinking");let f="",k=0,_=!1,b=!1;const w={};let T=!1;const v=e=>{w[e]=(w[e]||0)+1};try{const C=[];let S=!1;const A=!0===n.enableThinking,x=!0===n.enableSearch;Ke.debug("调用 adapter.streamOnce",{enableThinking:A,enableSearch:x});const R=e.streamOnce(r,o.tools,{model:n.model,enableThinking:A,enableSearch:x,signal:o.signal});for await(const e of R)switch(v(e.type),e.type){case"text":e.text&&(T||(T=!0,Ke.debug("首次收到 text",{thinkingStarted:_,thinkingComplete:b}),yield P(null)),A&&_&&!b&&(Ke.debug("text 触发 thinking_end"),b=!0,yield j(k)),l+=e.text,yield L(e.text));break;case"thinking":if(!A)break;if(e.thinking)if(b)Ke.warn("⚠️ thinkingComplete=true 但收到 thinking",e.thinking.slice(0,30)),Ke.warn("当前状态",{textStarted:T,chunkCounts:w});else if(T)Ke.warn("⚠️ text 开始后收到 thinking",e.thinking.slice(0,30));else{let t=e.thinking;if(!_&&(t=t.replace(/^(?:\r?\n)+/,""),!t))break;_||(_=!0,k=Date.now(),Ke.debug("发送 thinking_start"),yield P(null),yield D()),f+=t,yield U(t)}break;case"thinking_done":if(!A)break;Ke.info("收到 thinking_done",{thinkingStarted:_,thinkingComplete:b}),_&&!b?(b=!0,Ke.debug("发送 thinking_end"),yield j(k)):_||Ke.warn("⚠️ 收到 thinking_done 但 thinkingStarted=false");break;case"tool_call":if(e.toolCall){if(!o.tools||0===o.tools.length){Ke.warn("收到 tool_call 但当前未注入工具,已忽略",{toolName:e.toolCall.name});break}C.push(e.toolCall),S=!0}break;case"search_result":if(!x)break;e.searchResults&&(p||(p=!0,u=Date.now(),yield P(null),yield J(t)),c=Me(e.searchResults),yield W(c,u));break;case"done":Ke.info("收到 done",{finishReason:e.finishReason,usage:e.usage}),Ke.info(`第 ${a} 轮 chunk 统计`,w),"tool_calls"===e.finishReason&&(S=!0),e.usage&&(y=!0,h.promptTokens+=e.usage.promptTokens||0,h.completionTokens+=e.usage.completionTokens||0,h.totalTokens+=e.usage.totalTokens||0,h.reasoningTokens+=e.usage.reasoningTokens||0,h.cachedTokens+=e.usage.cachedTokens||0);break;case"error":return Ke.error("收到 error",e.error),void(yield Z(e.error??"未知错误"))}if(Ke.info(`第 ${a} 轮 for-await 循环结束`),Ke.debug("状态",{thinkingStarted:_,thinkingComplete:b}),A&&_&&!b&&(Ke.debug("补发 thinking_end"),b=!0,yield j(k)),S&&C.length>0){const e=C.map(e=>`${e.name}:${e.arguments}`).sort().join("|");if(e===m?g++:(g=0,m=e),g>=2){Ke.warn("检测到重复工具调用,注入终止提示",{signature:e.slice(0,200),count:g+1});C.map(e=>e.name).join(", ");r.push({role:"assistant",content:l,toolCalls:C});for(const e of C)r.push({role:"tool",content:`[系统提示] 你已经连续 ${g+1} 次使用相同参数调用 ${e.name},任务应已完成。请直接回复用户执行结果,不要再调用工具。`,toolCallId:e.id,toolName:e.name});yield se(a,i),l="";continue}const h=o.clientToolNames||this.config.clientToolNames,y=h?C.filter(e=>h.has(e.name)):[];if(y.length>0){Ke.info("检测到客户端工具调用,透传给客户端",y.map(e=>e.name));for(const e of y){let t;try{t=JSON.parse(e.arguments||"{}")}catch{t={}}yield z(e.id,e.name,t)}const e=Date.now()-s;return void(yield Q(l,void 0,e))}yield P(null);const f={role:"assistant",content:l,toolCalls:C};r.push(f);for(const e of C){const s=Date.now();let i;try{i=JSON.parse(e.arguments||"{}")}catch{r.push({role:"tool",content:"参数解析错误",toolCallId:e.id});continue}if(e.name===Ne){("string"==typeof i.query?i.query:"").trim()||(i.query=t)}const a=this.config.getAutoRunConfig?await this.config.getAutoRunConfig():n.autoRunConfig||this.config.autoRunConfig,l=this.config.tools?.get(e.name),m="manual"===a?.mode||!0===l?.requiresApproval;if(Ke.debug("检查工具批准",{toolName:e.name,autoRunConfigMode:a?.mode,requiresApproval:l?.requiresApproval,hasCallback:!!this.config.onToolApprovalRequest}),m&&this.config.onToolApprovalRequest){Ke.info("发送工具批准请求",e.name);const o={type:"tool_approval_request",data:{id:e.id,name:e.name,args:i,requestedAt:Date.now()}};yield o;if(!await this.config.onToolApprovalRequest({id:e.id,name:e.name,args:i})){const o=JSON.stringify({skipped:!0,message:"用户跳过了此工具"});if(e.name===Ne&&x){if(!p){p=!0,u=Date.now();const e="string"==typeof i.query?i.query:t;yield J(e)}d=!0,yield F(!1,u,`用户跳过了 ${Ne}`)}else yield B(e.id,e.name,o,!1,s);r.push({role:"tool",content:o,toolCallId:e.id,toolName:e.name});continue}}const g=e.name===Ne;if(g){if(x&&!p){p=!0,u=Date.now();const e="string"==typeof i.query?i.query:t;yield J(e)}}else yield V(e.id,e.name,i);const h=this.config.tools?.get(e.name);let y,f,k,_=o.signal;if(h?.timeout){const e=new AbortController;y=setTimeout(()=>e.abort(),h.timeout),o.signal.addEventListener("abort",()=>e.abort(),{once:!0}),_=e.signal}let b=!0;try{const t=[];let o=null;const n=()=>o?.(),s=e=>{t.push(e),n()};let r,a,l=!1;const c={toolCallId:e.id,toolName:e.name,onStdout:t=>{t&&s(G(e.id,e.name,"stdout",t))},onStderr:t=>{t&&s(G(e.id,e.name,"stderr",t))}};for(this.config.executeTool(e.name,i,_,c).then(e=>{r=e,l=!0,n()}).catch(e=>{a=e,l=!0,n()});!l||t.length>0;){for(;t.length>0;){const e=t.shift();e&&(yield e)}if(l)break;await new Promise(e=>o=e),o=null}if(a)throw a;f=JSON.stringify(r??{})}catch(e){if(b=!1,$(e))k=e.toolError,f=JSON.stringify({error:e.toolError.message});else{const t=e instanceof Error?e.message:String(e);k={message:t},f=JSON.stringify({error:t})}}void 0!==y&&clearTimeout(y);const w=this.config.tools?.get(e.name),T=b?w?.ui:void 0;if(g){if(x){let e,t=[];try{const o=JSON.parse(f||"{}");t=(Array.isArray(o?.results)?o.results:[]).map(e=>({title:"string"==typeof e?.title?e.title:"",url:"string"==typeof e?.url?e.url:"",snippet:"string"==typeof e?.snippet?e.snippet:""})).filter(e=>!!e.url),"string"==typeof o?.error&&o.error&&(e=o.error,b=!1)}catch{e=`${Ne} 返回结果解析失败`,b=!1}t.length>0&&(c=Me(t),yield W(c,u)),d=!0,yield F(b,u,e)}}else yield B(e.id,e.name,f,b,s,k,T);if(r.push({role:"tool",content:f,toolCallId:e.id,toolName:e.name}),o.signal.aborted)return void(yield oe("请求已取消"))}yield se(a,i),l="";continue}yield se(a,i);break}catch(e){return yield se(a,i),void(o.signal.aborted?yield oe("请求已取消"):yield Z(e instanceof Error?e.message:String(e)))}}a>=i&&Ke.warn(`达到最大迭代次数 ${i},强制结束工具调用循环`),p&&!d&&(yield F(!0,u));const f=Date.now()-s,k=y?{promptTokens:h.promptTokens,completionTokens:h.completionTokens,totalTokens:h.totalTokens,...h.reasoningTokens>0?{reasoningTokens:h.reasoningTokens}:{},...h.cachedTokens>0?{cachedTokens:h.cachedTokens}:{}}:void 0;yield Q(l,k,f)}buildMessages(e,t){const o=[];e.systemPrompt&&o.push({role:"system",content:e.systemPrompt});for(const t of e.history){const e={role:t.role,content:t.content};t.tool_calls&&(e.toolCalls=t.tool_calls.map(e=>({id:e.id,name:e.function.name,arguments:e.function.arguments,thought_signature:e.thought_signature}))),"tool"===t.role&&t.tool_call_id&&(e.toolCallId=t.tool_call_id),o.push(e)}return t&&o.push({role:"user",content:t,images:e.images}),o}};function Ie(e){return new qe(e)}var Oe={400:"请求参数错误",401:"API 认证失败,请检查 API Key 配置",402:"账户余额不足,请充值后重试",403:"没有权限访问此模型",404:"请求的模型或接口不存在",429:"请求过于频繁,请稍后重试",500:"API 服务器内部错误,请稍后重试",502:"API 网关错误,请稍后重试",503:"API 服务暂时不可用,请稍后重试",504:"API 请求超时,请稍后重试"};function Pe(e,t,o){const n=function(e){try{const t=JSON.parse(e);if(t?.error?.message)return{message:t.error.message,type:t.error.type};if("string"==typeof t?.error_msg)return{message:t.error_msg};if("string"==typeof t?.message)return{message:t.message}}catch{}return null}(t),s=n?.message,i=Oe[e];if(i)return s&&s.length<=100?`${i}(${s})`:i;if(s){return`${o} 错误 (${e}): ${s.length>200?s.slice(0,200)+"...":s}`}return`${o} 错误 (${e})`}var Ee=Se.module("ArkProtocol"),De=class{name="ark";apiKey;apiUrl;constructor(e){this.apiKey=e.apiKey,this.apiUrl=e.apiUrl??ye}async*stream(e,t,o){const n=this.buildRequestBody(e,t,o);Ee.debug("发送 ARK 请求",{url:`${this.apiUrl}/responses`,model:o.model,enableSearch:o.enableSearch,enableThinking:o.enableThinking,toolsCount:t.length});const s=await fetch(`${this.apiUrl}/responses`,{method:"POST",headers:{Authorization:`Bearer ${this.apiKey}`,"Content-Type":"application/json"},body:JSON.stringify(n),signal:o.signal});if(!s.ok){const e=await s.text();return Ee.error("ARK API 错误",{status:s.status,body:e.slice(0,500)}),void(yield{type:"error",error:Pe(s.status,e,"ARK")})}const i=s.body?.getReader();i?yield*this.parseSSE(i):yield{type:"error",error:"无法获取响应流"}}buildRequestBody(e,t,o){const n=this.convertMessages(e),s={model:o.model,stream:!0,max_output_tokens:o.familyConfig.defaultMaxTokens??32768,input:n},i=[],r=t.some(e=>e.name===Ne);o.enableSearch&&!r&&i.push({type:"web_search",max_keyword:5,limit:20});for(const e of t)i.push({type:"function",name:e.name,description:e.description,parameters:e.parameters});return i.length>0&&(s.tools=i),o.enableThinking&&(s.thinking={type:"enabled"}),s}convertMessages(e){const t=[];for(const o of e)switch(o.role){case"system":t.push({role:"system",content:o.content});break;case"user":{const e=[{type:"input_text",text:o.content||(o.images?.length?"请分析这张图片":"")}];if(o.images?.length)for(const t of o.images)e.push({type:"input_image",image_url:t.startsWith("data:")?t:`data:image/jpeg;base64,${t}`});t.push({role:"user",content:e});break}case"assistant":if(o.toolCalls?.length){o.content&&t.push({type:"message",role:"assistant",content:[{type:"output_text",text:o.content}]});for(const e of o.toolCalls)t.push({type:"function_call",call_id:e.id,name:e.name,arguments:e.arguments})}else t.push({role:"developer",content:`[上一轮AI回复]: ${o.content}`});break;case"tool":t.push({type:"function_call_output",call_id:o.toolCallId,output:o.content})}return t}async*parseSSE(e){const t=new TextDecoder;let o="";const n=new Map;let s=null;const i=[];let r,a=!1,l=!1,c=!1;for(;;){const{done:u,value:p}=await e.read();if(u)break;o+=t.decode(p,{stream:!0});const d=o.split("\n");o=d.pop()||"";for(const e of d){if(a)continue;if(!e.startsWith("data:"))continue;const t=e.slice(5).trim();if("[DONE]"===t){if(a=!0,n.size>0){for(const e of n.values())yield{type:"tool_call_done",toolCall:e};yield{type:"done",finishReason:"tool_calls",usage:r}}else yield{type:"done",finishReason:"stop",usage:r};return}try{const e=JSON.parse(t),o=e.response?.usage||e.usage;switch(o&&(r={promptTokens:o.input_tokens||o.prompt_tokens||0,completionTokens:o.output_tokens||o.completion_tokens||0,totalTokens:(o.input_tokens||o.prompt_tokens||0)+(o.output_tokens||o.completion_tokens||0),reasoningTokens:o.output_tokens_details?.reasoning_tokens||0,cachedTokens:o.input_tokens_details?.cached_tokens||0}),e.type){case"response.output_item.added":{const t=e.item;"function_call"===t?.type&&t.call_id&&(s=t.call_id,n.set(t.call_id,{id:t.call_id,name:t.name||"",arguments:t.arguments||""}),yield{type:"tool_call_start",toolCall:{id:t.call_id,name:t.name||""}});break}case"response.function_call_arguments.delta":if(s){const t=n.get(s);t&&(t.arguments+=e.delta||"",yield{type:"tool_call_delta",toolCall:{id:s,arguments:e.delta||""}})}break;case"response.function_call_arguments.done":case"response.output_item.done":{const t=e.item;if("function_call"===t?.type&&t.call_id){const e=n.get(t.call_id);n.set(t.call_id,{id:t.call_id,name:t.name||e?.name||"",arguments:t.arguments||e?.arguments||"{}"})}break}case"response.output_text.annotation.added":{const t=e.annotation;if(t?.url){i.some(e=>e.url===t.url)||(i.push({title:t.title||t.text||"",url:t.url,snippet:t.summary||t.snippet||""}),yield{type:"search_result",searchResults:[...i]})}break}case"response.output_text.delta":e.delta&&(c||(c=!0,l||(l=!0,yield{type:"thinking_done"})),yield{type:"text_delta",delta:e.delta});break;case"response.reasoning_summary_text.delta":e.delta&&!l&&(yield{type:"thinking_delta",delta:e.delta})}}catch{}}}if(!a)if(n.size>0){for(const e of n.values())yield{type:"tool_call_done",toolCall:e};yield{type:"done",finishReason:"tool_calls",usage:r}}else yield{type:"done",finishReason:"stop",usage:r}}};function Ue(e){return new De(e)}var je=Se.module("DeepSeekProtocol"),Je=class{name="deepseek";apiKey;apiUrl;constructor(e){this.apiKey=e.apiKey,this.apiUrl=e.apiUrl??ye}async*stream(e,t,o){const n=this.buildRequestBody(e,t,o),s=`${this.apiUrl}/responses`;je.debug("发送 DeepSeek 请求",{url:s,model:o.model,enableSearch:o.enableSearch,enableThinking:o.enableThinking,toolsCount:t.length});const i=await fetch(s,{method:"POST",headers:{Authorization:`Bearer ${this.apiKey}`,"Content-Type":"application/json"},body:JSON.stringify(n),signal:o.signal});if(!i.ok){const e=await i.text();return je.error("DeepSeek API 错误",{status:i.status,body:e.slice(0,500)}),void(yield{type:"error",error:Pe(i.status,e,"DeepSeek")})}const r=i.body?.getReader();r?yield*this.parseSSE(r,o.enableThinking):yield{type:"error",error:"无法获取响应流"}}buildRequestBody(e,t,o){const n=this.convertMessages(e),s={model:o.model,stream:!0,max_output_tokens:o.familyConfig.defaultMaxTokens??32768,input:n},i=[],r=t.some(e=>e.name===Ne);o.enableSearch&&!r&&i.push({type:"web_search",max_keyword:5,limit:20});for(const e of t)i.push({type:"function",name:e.name,description:e.description,parameters:e.parameters});return i.length>0&&(s.tools=i),o.enableThinking&&(s.thinking={type:"enabled"}),s}convertMessages(e){const t=[];for(const o of e)switch(o.role){case"system":t.push({role:"system",content:o.content});break;case"user":{const e=[{type:"input_text",text:o.content||(o.images?.length?"请分析这张图片":"")}];if(o.images?.length)for(const t of o.images)e.push({type:"input_image",image_url:t.startsWith("data:")?t:`data:image/jpeg;base64,${t}`});t.push({role:"user",content:e});break}case"assistant":if(o.toolCalls?.length)for(const e of o.toolCalls)t.push({type:"function_call",call_id:e.id,name:e.name,arguments:e.arguments});else t.push({role:"developer",content:`[上一轮AI回复]: ${o.content}`});break;case"tool":t.push({type:"function_call_output",call_id:o.toolCallId,output:o.content})}return t}async*parseSSE(e,t){const o=new TextDecoder;let n="";const s=new Map;let i=null;const r=[];let a,l=!1,c=!1,u=!1;for(;;){const{done:p,value:d}=await e.read();if(p)break;n+=o.decode(d,{stream:!0});const m=n.split("\n");n=m.pop()||"";for(const e of m){if(l)continue;if(!e.startsWith("data:"))continue;const o=e.slice(5).trim();if("[DONE]"===o){if(l=!0,s.size>0){for(const e of s.values())yield{type:"tool_call_done",toolCall:e};yield{type:"done",finishReason:"tool_calls",usage:a}}else yield{type:"done",finishReason:"stop",usage:a};return}try{const e=JSON.parse(o),n=e.response?.usage||e.usage;switch(n&&(a={promptTokens:n.input_tokens||n.prompt_tokens||0,completionTokens:n.output_tokens||n.completion_tokens||0,totalTokens:(n.input_tokens||n.prompt_tokens||0)+(n.output_tokens||n.completion_tokens||0),reasoningTokens:n.output_tokens_details?.reasoning_tokens||n.completion_tokens_details?.reasoning_tokens||0}),e.type){case"response.output_item.added":{const t=e.item;"function_call"===t?.type&&t.call_id&&(i=t.call_id,s.set(t.call_id,{id:t.call_id,name:t.name||"",arguments:t.arguments||""}),yield{type:"tool_call_start",toolCall:{id:t.call_id,name:t.name||""}});break}case"response.function_call_arguments.delta":if(i){const t=s.get(i);t&&(t.arguments+=e.delta||"",yield{type:"tool_call_delta",toolCall:{id:i,arguments:e.delta||""}})}break;case"response.function_call_arguments.done":case"response.output_item.done":{const t=e.item;if("function_call"===t?.type&&t.call_id){const e=s.get(t.call_id);s.set(t.call_id,{id:t.call_id,name:t.name||e?.name||"",arguments:t.arguments||e?.arguments||"{}"})}break}case"response.output_text.annotation.added":{const t=e.annotation;if(t?.url){r.some(e=>e.url===t.url)||(r.push({title:t.title||t.text||"",url:t.url,snippet:t.summary||t.snippet||""}),yield{type:"search_result",searchResults:[...r]})}break}case"response.output_text.delta":e.delta&&(u||(u=!0,t&&!c&&(c=!0,yield{type:"thinking_done"})),yield{type:"text_delta",delta:e.delta});break;case"response.reasoning_summary_text.delta":t&&e.delta&&!c&&(yield{type:"thinking_delta",delta:e.delta})}}catch{}}}if(!l)if(s.size>0){for(const e of s.values())yield{type:"tool_call_done",toolCall:e};yield{type:"done",finishReason:"tool_calls",usage:a}}else yield{type:"done",finishReason:"stop",usage:a}}};function We(e){return new Je(e)}var Fe=Se.module("QwenProtocol"),Ve=class{name="qwen";apiKey;apiUrl;constructor(e){this.apiKey=e.apiKey,this.apiUrl=e.apiUrl??"https://dashscope.aliyuncs.com/compatible-mode/v1"}async*stream(e,t,o){const n=this.buildRequestBody(e,t,o),s=`${this.apiUrl}/chat/completions`;Fe.debug("发送 Qwen 请求(兼容模式)",{url:s,model:o.model,enableThinking:o.enableThinking,toolsCount:t.length});const i=await fetch(s,{method:"POST",headers:{Authorization:`Bearer ${this.apiKey}`,"Content-Type":"application/json"},body:JSON.stringify(n),signal:o.signal});if(!i.ok){const e=await i.text();return Fe.error("Qwen API 错误",{status:i.status,body:e.slice(0,500)}),void(yield{type:"error",error:Pe(i.status,e,"Qwen")})}const r=i.body?.getReader();r?yield*this.parseSSE(r,o.enableThinking):yield{type:"error",error:"无法获取响应流"}}buildRequestBody(e,t,o){const n=this.convertMessages(e),s={model:o.model,messages:n,stream:!0,stream_options:{include_usage:!0}};return o.enableThinking&&(s.enable_thinking=!0,s.thinking_budget=38400),t.length>0&&(s.tools=t.map(e=>({type:"function",function:{name:e.name,description:e.description,parameters:e.parameters}}))),s}convertMessages(e){const t=[];for(const o of e)switch(o.role){case"system":t.push({role:"system",content:o.content});break;case"user":{const e=o.content||(o.images?.length?"请分析这张图片":"");if(o.images?.length){const n=[{type:"text",text:e}];for(const e of o.images)n.push({type:"image_url",image_url:{url:e.startsWith("data:")?e:`data:image/jpeg;base64,${e}`}});t.push({role:"user",content:n})}else t.push({role:"user",content:e});break}case"assistant":o.toolCalls?.length?t.push({role:"assistant",content:o.content||null,tool_calls:o.toolCalls.map(e=>({id:e.id,type:"function",function:{name:e.name,arguments:e.arguments}}))}):t.push({role:"assistant",content:o.content});break;case"tool":t.push({role:"tool",tool_call_id:o.toolCallId,content:o.content})}return t}async*parseSSE(e,t){const o=new TextDecoder;let n="";const s=new Map;let i,r,a=!1,l=!1;for(;;){const{done:c,value:u}=await e.read();if(c)break;n+=o.decode(u,{stream:!0});const p=n.split("\n");n=p.pop()||"";for(const e of p){if(!e.startsWith("data:"))continue;const o=e.slice(5).trim();if(o&&"[DONE]"!==o)try{const e=JSON.parse(o);e.usage&&(i={promptTokens:e.usage.prompt_tokens||0,completionTokens:e.usage.completion_tokens||0,totalTokens:e.usage.total_tokens||(e.usage.prompt_tokens||0)+(e.usage.completion_tokens||0)});const n=e.choices?.[0];if(!n)continue;const c=n.delta;if(!c)continue;if(t&&c.reasoning_content&&!l&&(yield{type:"thinking_delta",delta:c.reasoning_content}),c.content&&(!t||a||l||(l=!0,yield{type:"thinking_done"}),a=!0,yield{type:"text_delta",delta:c.content}),c.tool_calls?.length)for(const e of c.tool_calls){const t=e.index??0,o=s.get(t);o?e.function?.arguments&&(o.arguments+=e.function.arguments):(s.set(t,{id:e.id||`call_${t}`,name:e.function?.name||"",arguments:e.function?.arguments||""}),yield{type:"tool_call_start",toolCall:{id:e.id||`call_${t}`,name:e.function?.name||""}})}n.finish_reason&&(r=n.finish_reason)}catch{}else if("[DONE]"===o){const e=Array.from(s.values());if(e.length>0){for(const t of e)yield{type:"tool_call_done",toolCall:t};yield{type:"done",finishReason:"tool_calls",usage:i}}else{const e="tool_calls"===r||"length"===r||"error"===r?r:"stop";yield{type:"done",finishReason:e,usage:i}}return}}}const c=Array.from(s.values());if(c.length>0){for(const e of c)yield{type:"tool_call_done",toolCall:e};yield{type:"done",finishReason:"tool_calls",usage:i}}else{const e="tool_calls"===r||"length"===r||"error"===r?r:"stop";yield{type:"done",finishReason:e,usage:i}}}};function Be(e){return new Ve(e)}var Ge=Se.module("GeminiProtocol"),ze=class{name="gemini";apiKey;apiUrl;constructor(e){this.apiKey=e.apiKey,this.apiUrl=e.apiUrl??"https://generativelanguage.googleapis.com/v1beta"}async*stream(e,t,o){const n=this.buildRequestBody(e,t,o),s=`${this.apiUrl}/models/${o.model}:streamGenerateContent?key=${this.apiKey}&alt=sse`;Ge.debug("发送 Gemini 请求",{url:s.replace(this.apiKey,"***"),model:o.model,enableSearch:o.enableSearch,enableThinking:o.enableThinking,toolsCount:t.length});const i=await fetch(s,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(n),signal:o.signal});if(!i.ok){const e=await i.text();return Ge.error("Gemini API 错误",{status:i.status,body:e.slice(0,500)}),void(yield{type:"error",error:Pe(i.status,e,"Gemini")})}const r=i.body?.getReader();r?yield*this.parseSSE(r):yield{type:"error",error:"无法获取响应流"}}buildRequestBody(e,t,o){const{systemInstruction:n,contents:s}=this.convertMessages(e),i={contents:s,generationConfig:{maxOutputTokens:o.familyConfig.defaultMaxTokens??65536}};n&&(i.systemInstruction=n),o.enableThinking&&(i.generationConfig.thinkingConfig={thinkingBudget:24576,includeThoughts:!0});const r=[];if(t.length>0){const e=t.map(e=>({name:e.name,description:e.description,parameters:e.parameters})),o=new Map;for(const t of e)o.has(t.name)||o.set(t.name,t);r.push({functionDeclarations:Array.from(o.values())})}else o.enableSearch&&r.push({googleSearch:{}});return r.length>0&&(i.tools=r),i}convertMessages(e){let t;const o=[];for(const n of e)switch(n.role){case"system":t={parts:[{text:n.content}]};break;case"user":{const e=[{text:n.content||(n.images?.length?"请分析这张图片":"")}];if(n.images?.length)for(const t of n.images)if(t.startsWith("data:")){const o=t.match(/^data:([^;]+);base64,(.+)$/);o&&e.push({inlineData:{mimeType:o[1],data:o[2]}})}else e.push({inlineData:{mimeType:"image/jpeg",data:t}});o.push({role:"user",parts:e});break}case"assistant":if(n.toolCalls?.length){const e=[];for(const t of n.toolCalls){const o={functionCall:{name:t.name,args:JSON.parse(t.arguments||"{}")}};o.thoughtSignature=t.thoughtSignature??"skip_thought_signature_validator",e.push(o)}o.push({role:"model",parts:e})}else o.push({role:"model",parts:[{text:n.content}]});break;case"tool":o.push({role:"user",parts:[{functionResponse:{name:n.toolName||"unknown",response:{result:n.content}}}]})}return{systemInstruction:t,contents:o}}async*parseSSE(e){const t=new TextDecoder;let o="";const n=new Map;let s=!1,i=0;for(;;){const{done:r,value:a}=await e.read();if(r)break;o+=t.decode(a,{stream:!0});const l=o.split("\n");o=l.pop()||"";for(const e of l){if(!e.startsWith("data:"))continue;const t=e.slice(5).trim();if(t)try{const e=JSON.parse(t),o=e.candidates?.[0];if(!o?.content?.parts)continue;for(const e of o.content.parts)if(e.text&&(!0===e.thought?yield{type:"thinking_delta",delta:e.text}:(s||(s=!0,yield{type:"thinking_done"}),yield{type:"text_delta",delta:e.text})),e.functionCall){const t="gemini-"+i++,o={id:t,name:e.functionCall.name,arguments:JSON.stringify(e.functionCall.args||{})};e.thoughtSignature&&(o.thoughtSignature=e.thoughtSignature),n.set(t,o),yield{type:"tool_call_start",toolCall:{id:t,name:o.name}},yield{type:"tool_call_done",toolCall:o}}const r=o.groundingMetadata;if(r?.groundingChunks?.length){const e=[];for(const t of r.groundingChunks)t.web?.uri&&e.push({title:t.web.title||"",url:t.web.uri,snippet:""});e.length>0&&(yield{type:"search_result",searchResults:e})}if(o.finishReason){const t=e.usageMetadata,o=t?{promptTokens:t.promptTokenCount||0,completionTokens:t.candidatesTokenCount||0,totalTokens:t.totalTokenCount||0,reasoningTokens:t.thoughtsTokenCount||0,cachedTokens:t.cachedContentTokenCount||0}:void 0;return void(n.size>0?yield{type:"done",finishReason:"tool_calls",usage:o}:yield{type:"done",finishReason:"stop",usage:o})}}catch{}}}n.size>0?yield{type:"done",finishReason:"tool_calls"}:yield{type:"done",finishReason:"stop"}}};function Le(e){return new ze(e)}var Qe=Se.module("OpenAIProtocol"),He=class{name="openai";apiKey;apiUrl;constructor(e){this.apiKey=e.apiKey,this.apiUrl=e.apiUrl??fe}async*stream(e,t,o){const n=this.buildRequestBody(e,t,o),s=`${this.apiUrl}/responses`;Qe.debug("发送 OpenAI 请求",{url:s,model:o.model,toolsCount:t.length});const i=await fetch(s,{method:"POST",headers:{Authorization:`Bearer ${this.apiKey}`,"Content-Type":"application/json","HTTP-Referer":"https://ai-chat.local","X-Title":"AI Chat"},body:JSON.stringify(n),signal:o.signal});if(!i.ok){const e=await i.text();return Qe.error("OpenAI API 错误",{status:i.status,body:e.slice(0,500)}),void(yield{type:"error",error:Pe(i.status,e,"OpenAI")})}const r=i.body?.getReader();r?yield*this.parseSSE(r,o.enableThinking):yield{type:"error",error:"无法获取响应流"}}buildRequestBody(e,t,o){const n=this.convertMessages(e),s={model:o.model,stream:!0,input:n};return o.enableThinking&&(s.reasoning={effort:"high"}),t.length>0&&(s.tools=t.map(e=>({type:"function",name:e.name,description:e.description,parameters:e.parameters}))),s}convertMessages(e){const t=[];for(const o of e)switch(o.role){case"system":t.push({role:"system",content:o.content});break;case"user":{const e=[{type:"input_text",text:o.content||(o.images?.length?"请分析这张图片":"")}];if(o.images?.length)for(const t of o.images)e.push({type:"input_image",image_url:t.startsWith("data:")?t:`data:image/jpeg;base64,${t}`,detail:"auto"});t.push({role:"user",content:e});break}case"assistant":if(o.toolCalls?.length)for(const e of o.toolCalls)t.push({type:"function_call",call_id:e.id,name:e.name,arguments:e.arguments});else t.push({role:"developer",content:`[上一轮AI回复]: ${o.content}`});break;case"tool":t.push({type:"function_call_output",call_id:o.toolCallId,output:o.content})}return t}async*parseSSE(e,t){const o=new TextDecoder;let n="";const s=new Map;let i=null;const r=[];let a,l=!1,c=!1,u=!1;for(;;){const{done:p,value:d}=await e.read();if(p)break;n+=o.decode(d,{stream:!0});const m=n.split("\n");n=m.pop()||"";for(const e of m){if(l)continue;if(!e.startsWith("data:"))continue;const o=e.slice(5).trim();if("[DONE]"===o){if(l=!0,s.size>0){for(const e of s.values())yield{type:"tool_call_done",toolCall:e};yield{type:"done",finishReason:"tool_calls",usage:a}}else yield{type:"done",finishReason:"stop",usage:a};return}try{const e=JSON.parse(o);Qe.debug("SSE 事件",{type:e.type,event:JSON.stringify(e).slice(0,200)});const n=e.response?.usage||e.usage;switch(n&&(a={promptTokens:n.input_tokens??n.prompt_tokens??0,completionTokens:n.output_tokens??n.completion_tokens??0,totalTokens:(n.input_tokens??n.prompt_tokens??0)+(n.output_tokens??n.completion_tokens??0),reasoningTokens:n.output_tokens_details?.reasoning_tokens??0,cachedTokens:n.input_tokens_details?.cached_tokens??n.prompt_tokens_details?.cached_tokens??0}),e.type){case"response.output_item.added":{const t=e.item,o=t?.call_id||t?.id;if("function_call"===t?.type&&o){i=o;let e=t.arguments||t.input||"";"object"==typeof e&&(e=JSON.stringify(e)),s.set(o,{id:o,name:t.name||t.function?.name||"",arguments:e}),Qe.debug("工具调用开始",{id:o,name:t.name,args:e.slice(0,100)}),yield{type:"tool_call_start",toolCall:{id:o,name:t.name||t.function?.name||""}}}break}case"response.function_call_arguments.delta":{const t=e.delta;if(i&&t){const e=s.get(i);e&&(e.arguments+=t,yield{type:"tool_call_delta",toolCall:{id:i,arguments:t}})}break}case"response.function_call_arguments.done":{const t=e.item_id||e.call_id||i;if(t){const o=s.get(t);if(o){e.arguments&&(o.arguments=e.arguments);try{JSON.parse(o.arguments)}catch{Qe.warn("工具参数解析失败,使用空对象",{args:o.arguments.slice(0,100)}),o.arguments="{}"}}}break}case"response.output_item.done":{const t=e.item,o=t?.call_id||t?.id;if("function_call"===t?.type&&o){const e=s.get(o);let n=t.arguments||t.input||e?.arguments||"{}";"object"==typeof n&&(n=JSON.stringify(n)),s.set(o,{id:o,name:t.name||t.function?.name||e?.name||"",arguments:n}),Qe.debug("工具调用完成",{id:o,name:t.name,args:n.slice(0,100)})}break}case"response.output_text.annotation.added":{const t=e.annotation;if(t?.url){r.some(e=>e.url===t.url)||(r.push({title:t.title||t.text||"",url:t.url,snippet:t.summary||t.snippet||""}),yield{type:"search_result",searchResults:[...r]})}break}case"response.output_text.delta":e.delta&&(u||(u=!0,t&&!c&&(c=!0,yield{type:"thinking_done"})),yield{type:"text_delta",delta:e.delta});break;case"response.reasoning_summary_text.delta":t&&e.delta&&!c&&(yield{type:"thinking_delta",delta:e.delta});break;case"response.done":case"response.completed":{const t=e.response;if(t?.output?.length)for(const e of t.output)if("function_call"===e.type&&e.call_id){const t=s.get(e.call_id);let o=e.arguments||t?.arguments||"{}";"object"==typeof o&&(o=JSON.stringify(o)),s.set(e.call_id,{id:e.call_id,name:e.name||t?.name||"",arguments:o}),Qe.debug("response.completed: 更新工具参数",{id:e.call_id,args:o.slice(0,100)})}const o=t?.usage,n=o?{promptTokens:o.input_tokens||o.prompt_tokens||0,completionTokens:o.output_tokens||o.completion_tokens||0,totalTokens:(o.input_tokens||o.prompt_tokens||0)+(o.output_tokens||o.completion_tokens||0),reasoningTokens:o.output_tokens_details?.reasoning_tokens||0,cachedTokens:o.input_tokens_details?.cached_tokens||o.prompt_tokens_details?.cached_tokens||0}:void 0;if(a=n,l=!0,s.size>0){for(const e of s.values())Qe.debug("response.completed: 发出 tool_call_done",e),yield{type:"tool_call_done",toolCall:e};yield{type:"done",finishReason:"tool_calls",usage:n}}else yield{type:"done",finishReason:"stop",usage:n};return}}}catch(t){Qe.warn("SSE 解析错误",{line:e.slice(0,100),error:String(t)})}}}if(!l)if(Qe.debug("流结束,执行兜底逻辑",{pendingToolCalls:s.size}),s.size>0){for(const e of s.values())yield{type:"tool_call_done",toolCall:e};yield{type:"done",finishReason:"tool_calls",usage:a}}else yield{type:"done",finishReason:"stop",usage:a}}};function Ze(e){return new He(e)}var Xe=Se.module("AnthropicProtocol"),Ye=class{name="anthropic";gateway;constructor(e){this.gateway=s({apiKey:e.apiKey})}async*stream(e,t,o){Xe.debug("使用 Vercel AI Gateway 调用 Claude",{model:o.model,enableThinking:o.enableThinking,toolsCount:t.length});try{const n=this.convertMessages(e),s={model:this.gateway(o.model),messages:n,maxOutputTokens:o.familyConfig.defaultMaxTokens,abortSignal:o.signal};t.length>0&&(s.tools=this.convertTools(t)),o.enableThinking&&(s.providerOptions={anthropic:{thinking:{type:"enabled",budgetTokens:1e4}}}),Xe.debug("发送请求到 Vercel AI Gateway",{model:o.model,messagesCount:n.length,toolsCount:t.length,enableThinking:o.enableThinking});const r=i(s);yield*this.parseStream(r)}catch(e){const t=et(e);Xe.error("Vercel AI Gateway 错误",{error:t}),yield{type:"error",error:t}}}convertMessages(e){const t=[];for(const o of e)switch(o.role){case"system":t.push({role:"system",content:o.content});break;case"user":{const e=o.content||(o.images?.length?"请分析这张图片":"");if(o.images?.length){const n=[{type:"text",text:e}];for(const e of o.images)n.push({type:"image",image:e.startsWith("data:")?e:`data:image/jpeg;base64,${e}`});t.push({role:"user",content:n})}else t.push({role:"user",content:e});break}case"assistant":o.content&&t.push({role:"assistant",content:o.content});break;case"tool":t.push({role:"user",content:`[工具 ${o.toolName||"unknown"} 返回结果]: ${o.content}`})}return t}convertTools(e){const t={};for(const o of e){const e=this.jsonSchemaToZod(o.parameters);t[o.name]=r({description:o.description,inputSchema:e})}return t}jsonSchemaToZod(e){const t={};for(const[o,n]of Object.entries(e.properties)){let s;switch(n.type){case"string":s=n.enum?a.enum(n.enum):a.string();break;case"number":case"integer":s=a.number();break;case"boolean":s=a.boolean();break;case"array":s=a.array(a.string());break;default:s=a.unknown()}n.description&&(s=s.describe(n.description)),e.required?.includes(o)||(s=s.optional()),t[o]=s}return a.object(t)}async*parseStream(e){const t=new Map;let o=!1,n=!1;for await(const s of e.fullStream)switch(s.type){case"reasoning-delta":"text"in s&&s.text&&(o=!0,yield{type:"thinking_delta",delta:s.text});break;case"reasoning-end":o&&!n&&(n=!0,yield{type:"thinking_done"});break;case"text-delta":o&&!n&&(n=!0,yield{type:"thinking_done"}),"text"in s&&s.text&&(yield{type:"text_delta",delta:s.text});break;case"tool-call":if("toolCallId"in s&&"toolName"in s){const e=s.toolCallId,o=s.toolName,n="input"in s?s.input:null,i=n?"string"==typeof n?n:JSON.stringify(n):"{}";yield{type:"tool_call_start",toolCall:{id:e,name:o}},t.set(e,{id:e,name:o,arguments:i}),yield{type:"tool_call_done",toolCall:{id:e,name:o,arguments:i}}}break;case"error":{const e="error"in s?s.error:void 0,t=e?et(e):"模型请求失败";return Xe.error("AI SDK stream error 事件",{error:t}),void(yield{type:"error",error:t})}case"finish":{const e=t.size>0?"tool_calls":"finishReason"in s&&"stop"===s.finishReason?"stop":"finishReason"in s&&"length"===s.finishReason?"length":"stop",o="totalUsage"in s?s.totalUsage:"usage"in s?s.usage:void 0,n=o?.promptTokens??o?.inputTokens??0,i=o?.completionTokens??o?.outputTokens??0,r=o?{promptTokens:n,completionTokens:i,totalTokens:o.totalTokens??n+i}:void 0;return void(yield{type:"done",finishReason:e,usage:r})}}yield{type:"done",finishReason:"stop"}}};function et(e){if(!e||"object"!=typeof e)return"未知错误";const t=e,o=t.cause?.data?.error;if(o?.message){const e=t.cause?.statusCode||t.statusCode;return"insufficient_funds"===o.type||402===e?"账户余额不足,请充值后重试":401===e?"API 认证失败,请检查 API Key 配置":429===e?"请求过于频繁,请稍后重试":`API 错误: ${o.message}`}if(t.cause?.responseBody)try{const e=JSON.parse(t.cause.responseBody);if(e?.error?.message){const o=t.cause?.statusCode||t.statusCode;return"insufficient_funds"===e.error.type||402===o?"账户余额不足,请充值后重试":`API 错误: ${e.error.message}`}}catch{}const n=t.statusCode||t.cause?.statusCode;if(402===n)return"账户余额不足,请充值后重试";if(401===n)return"API 认证失败,请检查 API Key 配置";if(429===n)return"请求过于频繁,请稍后重试";if(503===n)return"服务暂时不可用,请稍后重试";const s=t.message||"未知错误";return s.length>200?s.slice(0,200)+"...":s}function tt(e){return new Ye(e)}var ot=Se.module("UnifiedAdapter"),nt=class{name="unified";get supportedModels(){return _().map(e=>e.id)}protocols=new Map;constructor(e){e.arkApiKey&&(this.protocols.set("ark",Ue({apiKey:e.arkApiKey,apiUrl:e.arkApiUrl})),this.protocols.set("deepseek",We({apiKey:e.arkApiKey,apiUrl:e.arkApiUrl}))),e.qwenApiKey&&this.protocols.set("qwen",Be({apiKey:e.qwenApiKey,apiUrl:e.qwenApiUrl})),e.geminiApiKey&&this.protocols.set("gemini",Le({apiKey:e.geminiApiKey,apiUrl:e.geminiApiUrl})),e.openrouterApiKey&&this.protocols.set("openai",Ze({apiKey:e.openrouterApiKey,apiUrl:e.openrouterApiUrl})),e.vercelApiKey&&this.protocols.set("anthropic",tt({apiKey:e.vercelApiKey}))}supportsModel(e){const t=k(e);return!!t&&this.protocols.has(t)}getModelFamilyConfig(e){return f(e)}async*streamOnce(e,t,o){const{model:n,enableThinking:s=!1,enableSearch:i=!1,signal:r}=o,a=e.map(e=>({role:e.role,content:e.content,images:e.images,toolCalls:e.toolCalls?.map(e=>({id:e.id,name:e.name,arguments:e.arguments,thoughtSignature:e.thought_signature})),toolCallId:e.toolCallId,toolName:e.toolName})),l=t;yield*this.stream(a,l,{model:n,enableThinking:s,enableSearch:i,signal:r})}async*stream(e,t,o){const{model:n,enableThinking:s=!1,enableSearch:i=!1,signal:r}=o,a=k(n),l=f(n);if(!a)return void(yield{type:"error",error:`未知模型: ${n}`});if(!l)return void(yield{type:"error",error:`模型 ${n} 缺少家族配置`});const c=this.protocols.get(a);if(!c)return void(yield{type:"error",error:`Protocol ${a} 未配置`});ot.debug("开始流式调用",{model:n,protocol:a,family:l.id,enableThinking:s,enableSearch:i});const u=c.stream(e,t,{model:n,familyConfig:l,enableThinking:s,enableSearch:i,signal:r});yield*this.transformEvents(u,l,s,i)}async*transformEvents(e,t,o,n){let s=!1;for await(const i of e)switch(i.type){case"thinking_delta":if(o&&t.supportsThinking&&i.delta){let e=i.delta;s||(e=e.replace(/^\n+/,""),e&&(s=!0)),e&&(yield{type:"thinking",thinking:e})}break;case"thinking_done":o&&t.supportsThinking&&(yield{type:"thinking_done"});break;case"text_delta":i.delta&&(yield{type:"text",text:i.delta});break;case"tool_call_done":if(i.toolCall){const e={id:i.toolCall.id||"",name:i.toolCall.name||"",arguments:i.toolCall.arguments||"{}"};i.toolCall.thoughtSignature&&(e.thought_signature=i.toolCall.thoughtSignature),yield{type:"tool_call",toolCall:e}}break;case"search_result":if(n&&i.searchResults){const e=i.searchResults.map(e=>({title:e.title,url:e.url,snippet:e.snippet}));yield{type:"search_result",searchResults:e}}break;case"done":yield{type:"done",finishReason:i.finishReason||"stop",usage:i.usage?{promptTokens:i.usage.promptTokens,completionTokens:i.usage.completionTokens,totalTokens:i.usage.totalTokens,reasoningTokens:i.usage.reasoningTokens,cachedTokens:i.usage.cachedTokens}:void 0};break;case"error":yield{type:"error",error:i.error||"未知错误"}}}};function st(e){return new nt(e)}var it=class{config;adapter;orchestrator;toolExecutor;abortController=null;tools=new Map;toolConfig;mcpManager=null;mcpConfigs;constructor(e,t){this.config={arkApiKey:e.arkApiKey,arkApiUrl:e.arkApiUrl||ye,qwenApiKey:e.qwenApiKey||"",qwenApiUrl:e.qwenApiUrl||"https://dashscope.aliyuncs.com/compatible-mode/v1",openrouterApiKey:e.openrouterApiKey||"",openrouterApiUrl:e.openrouterApiUrl||fe,vercelApiKey:e.vercelApiKey||"",tavilyApiKey:e.tavilyApiKey||"",geminiApiKey:e.geminiApiKey,cwd:e.cwd||process.cwd()},this.toolExecutor=t||he(this.config.cwd),this.toolConfig=e.tools,this.mcpConfigs=e.mcpServers,this.tools=new Map,this.adapter=new nt({arkApiKey:this.config.arkApiKey,arkApiUrl:this.config.arkApiUrl,qwenApiKey:this.config.qwenApiKey,qwenApiUrl:this.config.qwenApiUrl,geminiApiKey:this.config.geminiApiKey,openrouterApiKey:this.config.openrouterApiKey,openrouterApiUrl:this.config.openrouterApiUrl,vercelApiKey:this.config.vercelApiKey}),this.orchestrator=new qe({executeTool:this.executeTool.bind(this),tools:this.tools,onToolApprovalRequest:e.onToolApprovalRequest,getAutoRunConfig:e.getAutoRunConfig})}async asyncInit(){if(this.toolConfig&&0===this.tools.size){const e=await O(this.toolConfig);for(const t of e)this.tools.set(t.name,t)}var e;if(this.config.tavilyApiKey&&!this.tools.has(Ne)&&this.tools.set(Ne,(e=this.config.tavilyApiKey,{name:Ne,description:"联网搜索工具。输入 query(搜索关键词/问题),返回搜索结果列表(title/url/snippet)。用于获取实时信息与可引用来源。",parameters:{type:"object",properties:{query:{type:"string",description:"搜索关键词或问题(必填)"},max_results:{type:"number",description:"最大返回结果数(可选,默认 5)"}},required:["query"]},execute:async(t,o)=>{const n="string"==typeof t.query?t.query:"",s="number"==typeof t.max_results&&Number.isFinite(t.max_results)?Math.max(1,Math.min(10,Math.floor(t.max_results))):5;if(!n.trim())return{query:"",results:[],error:"缺少 query"};if(!e)return{query:n,results:[],error:"缺少 Tavily API Key"};const i=await fetch("https://api.tavily.com/search",{method:"POST",headers:{Authorization:`Bearer ${e}`,"Content-Type":"application/json"},body:JSON.stringify({query:n,max_results:s,search_depth:"basic",include_answer:!1,include_raw_content:!1}),signal:o.signal});if(!i.ok){const e=await i.text().catch(()=>"");return{query:n,results:[],error:`Tavily /search 错误: ${i.status} ${e}`.trim()}}const r=await i.json().catch(()=>null),a=[],l=r&&"object"==typeof r&&Array.isArray(r.results)?r.results:[];for(const e of l){const t="string"==typeof e?.url?e.url:"";if(!t)continue;const o="string"==typeof e?.title?e.title:"",n="string"==typeof e?.content?e.content:"";a.push({title:o,url:t,snippet:n})}return{query:n,results:a}}})),this.mcpConfigs?.length&&!this.mcpManager){this.mcpManager=new xe,await this.mcpManager.connectAll(this.mcpConfigs);for(const e of this.mcpManager.getAllTools())this.tools.has(e.name)||this.tools.set(e.name,e)}}getModelFamilyConfig(e){return f(e)}getModelProvider(e){return _e(e)}getModelRouteInfo(e){return{...be(e),available:this.adapter.supportsModel(e),familyConfig:f(e)}}buildSystemPrompt(e){const t=e.model||ke,o=f(t);let n="你是一个专业的 AI 助手,具备自主执行复杂任务的能力。\n\n## 工作方式\n1. **分析任务**:理解用户需求,拆解为可执行的步骤\n2. **逐步执行**:按步骤依次调用工具,检查每步结果\n3. **自我验证**:工具执行后检查结果是否符合预期\n4. **自动纠正**:发现问题时尝试替代方案,不要停下来问用户\n5. **总结汇报**:所有步骤完成后,给出简洁的结果总结\n\n## 输出规范\n- 不使用表情符号(emoji),除非用户要求\n- 使用 Markdown 格式组织内容\n- 代码块使用正确的语言标识";return e.platformPrompt&&(n+="\n\n"+e.platformPrompt),e.skillContents?.length&&(n+="\n\n【用户指令】\n"+e.skillContents.join("\n\n")),e.enableWebSearch&&o&&!v(t)&&(n+=`\n\n【联网搜索】当用户问题需要实时信息/最新事实/可引用来源时,请先调用 ${Ne} 工具获取结果,然后基于返回的 title/url/snippet 作答,并在回答中给出来源链接。`),n}getDefaultThinkingMode(){return"disabled"}createToolContext(e,t){const o=this.config.cwd,n=this.toolExecutor;return{cwd:o,exec:async(s,i)=>{const r=i?.length?`${s} ${i.join(" ")}`:s,a=await n.executeCommand(r,o,e,{onStdout:t?.onStdout,onStderr:t?.onStderr});return{stdout:a.output??"",stderr:a.error??"",exitCode:a.success?0:1}},signal:e}}async executeTool(e,t,o,n){const s=this.tools.get(e);return s?await s.execute(t,this.createToolContext(o,n)):{error:`未知工具: ${e}`}}getToolDefinitions(e,t){const o=Array.from(this.tools.values());let n=void 0!==e?o.filter(t=>e.includes(t.name)):o;if(t?.length)for(const e of t)if(!n.some(t=>t.name===e)){const t=this.tools.get(e);t&&(n=[...n,t])}return n.map(e=>({name:e.name,description:e.description,parameters:e.parameters}))}getAllTools(){return Array.from(this.tools.values()).map(e=>({name:e.name,description:e.description}))}async*chat(e,t={},o){await this.asyncInit(),this.abortController=new AbortController;const n=this.abortController.signal,s=t.model||ke;if(!this.adapter.supportsModel(s)){return void(f(s)?yield Z(`模型 ${s} 缺少 API Key 配置`,{code:"MISSING_API_KEY"}):yield Z(`未知模型: ${s}`,{code:"MODEL_NOT_SUPPORTED"}))}const i=f(s),r="enabled"===(t.thinkingMode??this.getDefaultThinkingMode())?"enabled":"disabled",a=this.buildSystemPrompt(t),l="ask"===t.mode,c=!l&&!!t.enableWebSearch,u=c&&i&&!v(s)?[Ne]:void 0,p=l?[]:this.getToolDefinitions(t.enabledTools,u),d=t.userTools||[],m=[...p,...d.map(e=>({name:e.name,description:e.description,parameters:{...e.parameters,required:e.parameters.required||[]}}))],g=d.length>0?new Set(d.map(e=>e.name)):void 0,h=!l&&"enabled"===r&&(i?.supportsThinking??!1),y={systemPrompt:a,history:t.history||[],tools:m,signal:n,images:o,clientToolNames:g};try{yield*this.orchestrator.chat(this.adapter,e,y,{model:s,enableThinking:h,enableSearch:c,autoRunConfig:t.autoRunConfig})}finally{this.abortController=null}}abort(){this.abortController&&this.abortController.abort()}setCwd(e){this.config.cwd=e}getConfig(){return{...this.config}}getSupportedModels(){return x}getMcpConnections(){return this.mcpManager?.getConnectionInfos()??[]}async destroy(){this.mcpManager&&(await this.mcpManager.disconnectAll(),this.mcpManager=null)}};export{Ye as AnthropicProtocol,De as ArkProtocol,E as CHAT_EVENT_TYPES,m as CLAUDE_FAMILY,qe as ChatOrchestrator,c as DEEPSEEK_FAMILY,ke as DEFAULT_MODEL,l as DOUBAO_FAMILY,Se as DebugLogger,Je as DeepSeekProtocol,p as GEMINI_FAMILY,d as GPT_FAMILY,ze as GeminiProtocol,it as HybridAgent,x as MODELS,g as MODEL_FAMILIES,h as MODEL_REGISTRY,He as OpenAIProtocol,u as QWEN_FAMILY,Ve as QwenProtocol,nt as UnifiedAdapter,oe as createAbort,tt as createAnthropicProtocol,Z as createApiError,Ue as createArkProtocol,We as createDeepSeekProtocol,he as createDefaultToolExecutor,Q as createDone,H as createError,Le as createGeminiProtocol,Ze as createOpenAIProtocol,Ie as createOrchestrator,te as createParseError,Be as createQwenProtocol,X as createRateLimitError,F as createSearchEnd,W as createSearchResult,J as createSearchStart,se as createStepEnd,ne as createStepStart,L as createTextDelta,U as createThinkingDelta,j as createThinkingEnd,D as createThinkingStart,ee as createTimeoutError,G as createToolCallOutput,z as createToolCallRequest,B as createToolCallResult,V as createToolCallStart,Y as createToolError,st as createUnifiedAdapter,M as getArg,we as getDefaultProvider,R as getModelByModelId,y as getModelEntry,f as getModelFamily,k as getModelProtocol,S as getModelSearchStrategy,b as getModelsByFamily,w as getModelsByProtocol,_ as getVisibleModels,pe as isAbortEvent,ue as isErrorEvent,Te as isModelForProvider,me as isRetryableError,re as isSearchEvent,ce as isStatusEvent,de as isStepEvent,le as isTextEvent,ie as isThinkingEvent,$ as isThrowableToolError,$ as isToolError,ae as isToolEvent,v as modelSupportsNativeSearch,T as modelSupportsThinking,O as resolveTools,K as rethrowToolError,_e as routeModelToProvider,be as routeModelWithDetails,N as throwToolError,q as tool,I as tools};
1
+ import{Client as e}from"@modelcontextprotocol/sdk/client/index.js";import{StdioClientTransport as t}from"@modelcontextprotocol/sdk/client/stdio.js";import{SSEClientTransport as n}from"@modelcontextprotocol/sdk/client/sse.js";import{appendFileSync as o}from"fs";import{createGateway as s,streamText as i,tool as r}from"ai";import{z as a}from"zod";var l={id:"doubao",displayName:"豆包",supportsVision:!0,supportsThinking:!0,thinkingFormat:"reasoning",supportsNativeSearch:!1,searchStrategy:"tavily",toolCallFormat:"responses",defaultMaxTokens:16384},c={id:"deepseek",displayName:"DeepSeek",supportsVision:!1,supportsThinking:!0,thinkingFormat:"reasoning",supportsNativeSearch:!1,searchStrategy:"tavily",toolCallFormat:"responses",defaultMaxTokens:32768},u={id:"qwen",displayName:"通义千问",supportsVision:!1,supportsThinking:!0,thinkingFormat:"thinking_enabled",supportsNativeSearch:!1,searchStrategy:"tavily",toolCallFormat:"openai",defaultMaxTokens:32768},p={id:"gemini",displayName:"Gemini",supportsVision:!0,supportsThinking:!0,thinkingFormat:"thought_signature",supportsNativeSearch:!1,searchStrategy:"tavily",toolCallFormat:"gemini",defaultMaxTokens:65536,requiresSpecialHandling:["thought_signature"]},d={id:"gpt",displayName:"GPT",supportsVision:!0,supportsThinking:!0,thinkingFormat:"reasoning",supportsNativeSearch:!1,searchStrategy:"tavily",toolCallFormat:"openai",defaultMaxTokens:128e3},m={id:"claude",displayName:"Claude",supportsVision:!0,supportsThinking:!0,thinkingFormat:"reasoning",supportsNativeSearch:!1,searchStrategy:"tavily",toolCallFormat:"openai",defaultMaxTokens:64e3},g={doubao:l,deepseek:c,qwen:u,gemini:p,gpt:d,claude:m},h=[{id:"doubao-seed-1-6-250615",displayName:"豆包 Seed 1.6",family:"doubao",protocol:"ark",visible:!0,supportsVision:!0,contextWindow:"256K",contextWindowTokens:256e3,pricing:["输入 0.8 元/百万tokens","输出 2-8 元/百万tokens"]},{id:"doubao-seed-1-8-251215",displayName:"豆包 Seed 1.8",family:"doubao",protocol:"ark",contextWindow:"256K",contextWindowTokens:256e3,pricing:["输入 0.8 元/百万tokens","输出 2-8 元/百万tokens"]},{id:"deepseek-v3-2-251201",displayName:"DeepSeek V3.2",family:"deepseek",protocol:"deepseek",visible:!0,supportsVision:!1,contextWindow:"128K",contextWindowTokens:128e3,pricing:["输入 2 元/百万tokens","输出 3 元/百万tokens"]},{id:"qwen3-vl-plus",displayName:"通义千问 3 VL",family:"qwen",protocol:"qwen",visible:!0,supportsVision:!0,contextWindow:"262K",contextWindowTokens:262144,pricing:["输入 1 元/百万tokens","输出 10 元/百万tokens"]},{id:"qwen3.5-plus",displayName:"通义千问 3.5 Plus",family:"qwen",protocol:"qwen",contextWindow:"1M",contextWindowTokens:1e6,pricing:["输入 0.8 元/百万tokens","输出 4.8 元/百万tokens"]},{id:"qwen-long",displayName:"通义千问 Long",family:"qwen",protocol:"qwen",contextWindow:"10M",contextWindowTokens:1e7,pricing:["输入 0.5 元/百万tokens","输出 2 元/百万tokens"]},{id:"gemini-3-pro-preview",displayName:"Gemini 3 Pro",family:"gemini",protocol:"gemini",visible:!0,supportsVision:!0,contextWindow:"1M",contextWindowTokens:1e6,pricing:["输入 1.25 元/百万tokens","输出 10 元/百万tokens"]},{id:"gemini-2.5-flash-preview-05-20",displayName:"Gemini 2.5 Flash",family:"gemini",protocol:"gemini",contextWindow:"1M",contextWindowTokens:1e6,pricing:["输入 0.15 元/百万tokens","输出 0.6 元/百万tokens"]},{id:"gemini-2.5-pro-preview-05-06",displayName:"Gemini 2.5 Pro",family:"gemini",protocol:"gemini",contextWindow:"1M",contextWindowTokens:1e6,pricing:["输入 1.25 元/百万tokens","输出 10 元/百万tokens"]},{id:"openai/gpt-5.2",displayName:"GPT-5.2",family:"gpt",protocol:"openai",visible:!0,supportsVision:!0,contextWindow:"400K",contextWindowTokens:4e5,pricing:["输入 12.6 元/百万tokens","输出 100.8 元/百万tokens"]},{id:"anthropic/claude-opus-4.5",displayName:"Claude Opus 4.5",family:"claude",protocol:"anthropic",visible:!0,supportsVision:!0,contextWindow:"200K",contextWindowTokens:2e5,pricing:["输入 36 元/百万tokens","输出 180 元/百万tokens"]}];function f(e){return h.find(t=>t.id===e||e.includes(t.id))}function y(e){const t=f(e);if(t)return g[t.family]}function k(e){const t=f(e);return t?.protocol}function _(){return h.filter(e=>e.visible)}function b(e){return h.filter(t=>t.family===e)}function w(e){return h.filter(t=>t.protocol===e)}function T(e){const t=y(e);return t?.supportsThinking??!1}function v(e){const t=y(e);return t?.supportsNativeSearch??!1}function C(e){const t=f(e);if(!t)return!1;if("boolean"==typeof t.supportsVision)return t.supportsVision;const n=y(e);return n?.supportsVision??!1}function x(e){const t=y(e);return t?.searchStrategy??"tavily"}function S(e){const t=y(e.id),n=C(e.id),o=t?.supportsThinking??!1,s=t?.supportsNativeSearch??!1,i=[];return n&&i.push("多模态"),o&&i.push("深度思考"),e.contextWindow&&i.push(`长上下文(${e.contextWindow})`),s&&i.push("联网搜索"),i}var A=_().map(e=>{const t=y(e.id),n=t?.supportsThinking??!1,o=C(e.id);return{modelId:e.id,displayName:e.displayName,supportsThinking:n,supportsVision:o,tooltip:{features:S(e),cost:e.pricing}}});function $(e){return A.find(t=>t.modelId===e)}function R(e){return e instanceof Error&&"object"==typeof e.toolError&&null!==e.toolError&&"string"==typeof e.toolError.message}function M(e,t,n){const o={message:e,code:t,...n},s=new Error(e);throw Object.defineProperty(s,"toolError",{value:o,enumerable:!0}),s}function N(e,t,n){if(R(e))throw e;M(e instanceof Error?e.message:String(e),t,n)}function I(e,t){return e[t]}function K(e){return{tools:[e]}}function q(e){return{tools:e}}async function O(e){const t=[];for(const n of e){const e=await n;"tools"in e&&Array.isArray(e.tools)?t.push(...e.tools):"name"in e&&"execute"in e&&t.push(e)}return t}function E(e){return{type:"agent_status",data:{phase:e}}}var P=["thinking_start","thinking_delta","thinking_end","search_start","search_result","search_end","tool_call_start","tool_call_result","tool_call_output","tool_approval_request","tool_call_request","text_delta","done","error","abort","step_start","step_end","compact_start","compact_end","agent_status"];function D(){return{type:"thinking_start",data:{startedAt:Date.now()}}}function U(e){return{type:"thinking_delta",data:{content:e}}}function W(e){const t=Date.now();return{type:"thinking_end",data:{endedAt:t,duration:t-e}}}function j(e){return{type:"search_start",data:{query:e,startedAt:Date.now()}}}function J(e,t){const n=Date.now();return{type:"search_result",data:{results:e,endedAt:n,duration:n-t}}}function z(e,t,n){const o=Date.now();return{type:"search_end",data:{success:e,error:n,endedAt:o,duration:o-t}}}function F(e,t,n){return{type:"tool_call_start",data:{id:e,name:t,args:n,startedAt:Date.now()}}}function V(e,t,n,o,s,i,r){const a=Date.now();return{type:"tool_call_result",data:{id:e,name:t,result:n,success:o,error:i,endedAt:a,duration:a-s,ui:r}}}function G(e,t,n,o){return{type:"tool_call_output",data:{id:e,name:t,stream:n,chunk:o,at:Date.now()}}}function L(e,t,n){return{type:"tool_call_request",data:{id:e,name:t,args:n,requestedAt:Date.now()}}}function B(e){return{type:"text_delta",data:{content:e}}}function Q(e,t,n){return{type:"done",data:{text:e,usage:t,duration:n}}}function H(e){return{type:"error",data:e}}function Y(e,t={}){return H({category:"api",message:e,...t})}function Z(e,t,n){return H({category:"rate_limit",message:e,code:"RATE_LIMIT",statusCode:429,retryable:!0,retryAfter:t,context:n})}function X(e,t,n){return H({category:"tool",message:e,code:"TOOL_ERROR",context:t,cause:n,retryable:!1})}function ee(e,t){return H({category:"timeout",message:e,code:"TIMEOUT",retryable:!0,context:t})}function te(e,t){return H({category:"parse",message:e,code:"PARSE_ERROR",cause:t,retryable:!1})}function ne(e){return{type:"abort",data:{reason:e,abortedAt:Date.now()}}}function oe(e,t){return{type:"step_start",data:{stepNumber:e,description:t,startedAt:Date.now()}}}function se(e,t){const n=Date.now();return{type:"step_end",data:{stepNumber:e,endedAt:n,duration:n-t}}}function ie(e){return e.type.startsWith("thinking_")}function re(e){return e.type.startsWith("search_")}function ae(e){return e.type.startsWith("tool_")}function le(e){return"text_delta"===e.type}function ce(e){return"done"===e.type||"error"===e.type||"abort"===e.type}function ue(e){return"error"===e.type}function pe(e){return"abort"===e.type}function de(e){return e.type.startsWith("step_")}function me(e){return"error"===e.type&&!0===e.data.retryable}var ge=["rm -rf /","rm -rf ~","format","mkfs","dd if=","shutdown","reboot","sudo rm","sudo format"];function he(e=process.cwd()){return{async executeCommand(t,n,o,s){if(o?.aborted)return{success:!1,error:"操作已取消"};if(function(e){const t=e.toLowerCase().trim();return ge.some(e=>t.includes(e.toLowerCase()))}(t))return{success:!1,error:"该命令被安全策略阻止"};try{const{spawn:i}=await import("child_process");return new Promise(r=>{let a="",l="",c=!1,u=null;const p=i("sh",["-c",t],{cwd:n||e,env:process.env,detached:"win32"!==process.platform}),d=e=>{if(!c){c=!0;try{"win32"!==process.platform&&"number"==typeof p.pid?process.kill(-p.pid,e):p.kill(e)}catch{try{p.kill(e)}catch{}}u&&clearTimeout(u),u=setTimeout(()=>{try{"win32"!==process.platform&&"number"==typeof p.pid?process.kill(-p.pid,"SIGKILL"):p.kill("SIGKILL")}catch{}},1500)}},m=setTimeout(()=>{c||(d("SIGTERM"),r({success:!1,error:"命令执行超时(30秒)"}))},3e4),g=()=>{c||(d("SIGTERM"),clearTimeout(m),r({success:!1,error:"操作已取消"}))};o?.addEventListener("abort",g),p.stdout?.on("data",e=>{const t=e.toString();a+=t,s?.onStdout?.(t)}),p.stderr?.on("data",e=>{const t=e.toString();l+=t,s?.onStderr?.(t)}),p.on("close",e=>{if(clearTimeout(m),o?.removeEventListener("abort",g),u&&(clearTimeout(u),u=null),c)return;const t=a.trim(),n=l.trim();if(0===e)r({success:!0,output:t||n||"执行成功"});else if(t){r({success:!0,output:t+(n?`\n[警告: ${n}]`:"")})}else r(n?{success:!1,error:n}:{success:!1,error:`命令退出码: ${e}`})}),p.on("error",e=>{clearTimeout(m),o?.removeEventListener("abort",g),u&&(clearTimeout(u),u=null),c||r({success:!1,error:e.message})})})}catch(e){return{success:!1,error:e instanceof Error?e.message:String(e)}}}}}var fe="https://ark.cn-beijing.volces.com/api/v3",ye="https://openrouter.ai/api/v1",ke="doubao-seed-1-6-250615";function _e(e){return be(e).provider}function be(e){const t=f(e);return t?{provider:t.protocol,registryEntry:t,familyConfig:y(e),isDefault:!1}:{provider:"ark",isDefault:!0}}function we(){return"ark"}function Te(e,t){return _e(e)===t}var ve=!1,Ce=null,xe=class e{prefix;constructor(e){this.prefix=e}static enable(e){ve=e}static isEnabled(){return ve}static setLogFile(e){Ce=e}static module(t){return new e(`[${t}]`)}debug(...e){ve&&this.writeToFile("debug",e)}info(...e){ve&&this.writeToFile("info",e)}warn(...e){ve&&this.writeToFile("warn",e)}error(...e){ve&&this.writeToFile("error",e)}writeToFile(e,t){if(Ce)try{const n=JSON.stringify({t:Date.now(),level:e,module:this.prefix,args:t.map(e=>{try{return"string"==typeof e?e:JSON.parse(JSON.stringify(e))}catch{return String(e)}})});o(Ce,n+"\n")}catch{}}},Se=xe.module("MCP"),Ae=class{connections=new Map;async connectAll(e){const t=await Promise.allSettled(e.map(e=>this.connect(e)));for(let n=0;n<t.length;n++){const o=t[n],s=e[n].name;"rejected"===o.status&&Se.error(`[${s}] 连接失败:`,o.reason)}}async connect(o){const{name:s}=o;this.connections.has(s)&&await this.disconnect(s),Se.info(`[${s}] 正在连接...`);const i=new e({name:"ai-chat-mcp-client",version:"1.0.0"});let r;if("stdio"===o.transport){if(!o.command)throw new Error(`[${s}] stdio 模式必须指定 command`);r=new t({command:o.command,args:o.args,env:o.env,cwd:o.cwd})}else{if("sse"!==o.transport)throw new Error(`[${s}] 不支持的传输方式: ${o.transport}`);if(!o.url)throw new Error(`[${s}] sse 模式必须指定 url`);r=new n(new URL(o.url))}const a={config:o,client:i,transport:r,status:"connecting",tools:[]};this.connections.set(s,a);try{await i.connect(r),a.status="connected",Se.info(`[${s}] 已连接`);const e=await this.discoverTools(a);a.tools=e,Se.info(`[${s}] 发现 ${e.length} 个工具:`,e.map(e=>e.name))}catch(e){throw a.status="error",a.error=e instanceof Error?e.message:String(e),Se.error(`[${s}] 连接失败:`,a.error),e}}async discoverTools(e){const{client:t,config:n}=e,{tools:o}=await t.listTools();return o.map(e=>this.adaptTool(e,n.name,t))}adaptTool(e,t,n){const o=this.convertSchema(e.inputSchema);return{name:e.name,description:e.description||`MCP tool from ${t}`,parameters:o,execute:async t=>{const o=await n.callTool({name:e.name,arguments:t}),s=[];if(Array.isArray(o.content))for(const e of o.content)if("object"==typeof e&&null!==e){const t=e;"text"===t.type&&"string"==typeof t.text?s.push(t.text):"image"===t.type?s.push(`[image: ${t.mimeType||"unknown"}]`):"resource"===t.type&&s.push(JSON.stringify(t))}return{text:s.join("\n")||JSON.stringify(o.content)}}}}convertSchema(e){const t={},n=[],o=e.properties;if(o)for(const[e,n]of Object.entries(o))t[e]=this.convertProperty(n);return Array.isArray(e.required)&&n.push(...e.required.filter(e=>"string"==typeof e)),{type:"object",properties:t,required:n.length>0?n:void 0}}convertProperty(e){const t={type:"string"==typeof e.type?e.type:"string"};if("string"==typeof e.description&&(t.description=e.description),Array.isArray(e.enum)&&(t.enum=e.enum),e.items&&"object"==typeof e.items&&(t.items=this.convertProperty(e.items)),e.properties&&"object"==typeof e.properties){t.properties={};for(const[n,o]of Object.entries(e.properties))t.properties[n]=this.convertProperty(o)}return Array.isArray(e.required)&&(t.required=e.required.filter(e=>"string"==typeof e)),t}getAllTools(){const e=[];for(const t of this.connections.values())"connected"===t.status&&e.push(...t.tools);return e}getConnectionInfos(){return Array.from(this.connections.values()).map(e=>({name:e.config.name,status:e.status,toolCount:e.tools.length,error:e.error}))}async disconnect(e){const t=this.connections.get(e);if(t)try{await t.client.close(),Se.info(`[${e}] 已断开`)}catch(t){Se.error(`[${e}] 断开失败:`,t)}finally{t.status="disconnected",t.tools=[],this.connections.delete(e)}}async disconnectAll(){const e=Array.from(this.connections.keys());await Promise.allSettled(e.map(e=>this.disconnect(e)))}},$e=xe.module("ContextCompressor");function Re(e){return e?Math.ceil(e.length/3.2):0}function Me(e){let t=4;if(t+=Re(e.content),e.toolCalls)for(const n of e.toolCalls)t+=Re(n.name),t+=Re(n.arguments),t+=10;return e.images&&(t+=85*e.images.length),t}function Ne(e){let t=3;for(const n of e)t+=Me(n);return t}function Ie(e){const t=e.compactThresholdRatio??.8;return Math.floor(e.contextWindowTokens*t)-e.maxOutputTokens}var Ke='你是一个对话历史压缩助手。请总结以下对话历史,保留所有关键信息:\n\n要求:\n1. 保留所有文件修改记录(哪些文件被创建/修改/删除了,具体改了什么)\n2. 保留所有关键决策和结论\n3. 保留错误信息和解决方案\n4. 保留用户的明确要求和偏好\n5. 用简洁的条目列表格式输出\n6. 不要遗漏任何可能影响后续工作的信息\n\n直接输出摘要,不要开头说"以下是摘要"之类的话。';function qe(e){const t=[];for(const n of e){const e="assistant"===n.role?"AI":"user"===n.role?"用户":"工具";if("assistant"===n.role&&n.toolCalls&&n.toolCalls.length>0){const o=n.toolCalls.map(e=>{const t=e.arguments.length>200?e.arguments.slice(0,200)+"...":e.arguments;return` 调用 ${e.name}(${t})`}).join("\n"),s=n.content?`${n.content}\n${o}`:o;t.push(`[${e}]\n${s}`)}else if("tool"===n.role){const o=n.content.length>1e3?n.content.slice(0,1e3)+`... (共 ${n.content.length} 字符)`:n.content;t.push(`[${e}: ${n.toolName??"unknown"}]\n${o}`)}else n.content&&t.push(`[${e}]\n${n.content}`)}return t.join("\n\n---\n\n")}var Oe=xe.module("ContextSummarizer");async function Ee(e,t,n){const{summarizeMessages:o,keepMessages:s}=function(e,t){const n=t.keepRecentMessages??6;let o=0;"system"===e[0]?.role&&(o=1);let s=o;for(let t=o;t<e.length;t++)if("user"===e[t].role){s=t+1;break}const i=Math.max(s,e.length-n),r=e.slice(i),a=e.slice(s,i);if(a.length<2)return{summarizeMessages:[],keepMessages:e.slice(o)};const l=Ne(e),c=Ie(t);return $e.info(`准备 AI 总结: ~${l} tokens > budget ${c}, 总结 ${a.length} 条中间消息, 保留最近 ${r.length} 条`),{summarizeMessages:[{role:"system",content:Ke},{role:"user",content:qe(a)}],keepMessages:r}}(t,n);if(0===o.length)return Oe.info("中间历史太短,跳过 AI 总结"),{messages:t,success:!0};const i=o[0].content,r=o[1].content;Oe.info(`开始 AI 总结: ~${Ne(o)} tokens, ${t.length} 条消息`);try{const n=await e(i,r);if(!n.trim())return Oe.warn("AI 总结返回空内容"),{messages:t,success:!1};const o=function(e,t,n){const o="system"===e[0]?.role?e[0]:null;let s=null;for(let t=o?1:0;t<e.length;t++)if("user"===e[t].role){s=e[t];break}const i=[];o&&i.push(o),s&&i.push(s),i.push({role:"system",content:`[对话历史摘要]\n${t}`}),i.push(...n);const r=Ne(i);return $e.info(`AI 总结应用完成: ${e.length} → ${i.length} 条消息, ~${r} tokens`),i}(t,n,s);return Oe.info(`AI 总结完成: ${t.length} → ${o.length} 条消息, ~${Ne(o)} tokens`),{messages:o,success:!0}}catch(e){return Oe.error("AI 总结异常:",e),{messages:t,success:!1}}}var Pe="web_search_ai";var De=xe.module("Orchestrator");function Ue(e){const t=new Map;for(const n of e){const e=String(n?.url??"").trim();if(!e)continue;const o=String(n?.snippet??"").trim();let s=String(n?.title??"").trim();if(!s)try{s=new URL(e).hostname}catch{s=e}const i=t.get(e);i?(!i.snippet&&o&&(i.snippet=o),!i.title&&s&&(i.title=s)):t.set(e,{title:s,url:e,snippet:o})}return Array.from(t.values())}var We=class{config;constructor(e){this.config={maxIterations:25,...e}}async*chat(e,t,n,o){const s=Date.now(),i=this.config.maxIterations??25;let r=this.buildMessages(n,t);const{contextWindowTokens:a,maxOutputTokens:l}=function(e){const t=f(e);if(!t)throw new Error(`模型 ${e} 未在 MODEL_REGISTRY 中注册`);const n=g[t.family];if(!n)throw new Error(`模型 ${e} 的家族 ${t.family} 未定义`);if(!t.contextWindowTokens)throw new Error(`模型 ${e} 缺少 contextWindowTokens 配置`);if(!n.defaultMaxTokens)throw new Error(`模型家族 ${t.family} 缺少 defaultMaxTokens 配置`);return{contextWindowTokens:t.contextWindowTokens,maxOutputTokens:n.defaultMaxTokens}}(o.model),c={contextWindowTokens:a,maxOutputTokens:l};{const e=this.compactIfNeeded(r,c);let t=await e.next();for(;!t.done;)yield t.value,t=await e.next();r=t.value}let u=0,p="",d=[],m=0,h=!1,y=!1,k="",_=0,b={promptTokens:0,completionTokens:0,totalTokens:0,reasoningTokens:0,cachedTokens:0},w=!1;for(;u<i;){if(n.signal.aborted)return void(yield ne("请求已取消"));if(u++,u>1){const e=this.compactIfNeeded(r,c);let t=await e.next();for(;!t.done;)yield t.value,t=await e.next();r=t.value}const i=Date.now();De.info(`======= 第 ${u} 轮开始 =======`),yield oe(u),yield E("thinking");let a="",l=0,g=!1,f=!1;const T={};let v=!1;const C=e=>{T[e]=(T[e]||0)+1};try{const c=[];let x=!1;const S=!0===o.enableThinking,A=!0===o.enableSearch;De.debug("调用 adapter.streamOnce",{enableThinking:S,enableSearch:A});const $=e.streamOnce(r,n.tools,{model:o.model,enableThinking:S,enableSearch:A,signal:n.signal});for await(const e of $)switch(C(e.type),e.type){case"text":e.text&&(v||(v=!0,De.debug("首次收到 text",{thinkingStarted:g,thinkingComplete:f}),yield E(null)),S&&g&&!f&&(De.debug("text 触发 thinking_end"),f=!0,yield W(l)),p+=e.text,yield B(e.text));break;case"thinking":if(!S)break;if(e.thinking)if(f)De.warn("⚠️ thinkingComplete=true 但收到 thinking",e.thinking.slice(0,30)),De.warn("当前状态",{textStarted:v,chunkCounts:T});else if(v)De.warn("⚠️ text 开始后收到 thinking",e.thinking.slice(0,30));else{let t=e.thinking;if(!g&&(t=t.replace(/^(?:\r?\n)+/,""),!t))break;g||(g=!0,l=Date.now(),De.debug("发送 thinking_start"),yield E(null),yield D()),a+=t,yield U(t)}break;case"thinking_done":if(!S)break;De.info("收到 thinking_done",{thinkingStarted:g,thinkingComplete:f}),g&&!f?(f=!0,De.debug("发送 thinking_end"),yield W(l)):g||De.warn("⚠️ 收到 thinking_done 但 thinkingStarted=false");break;case"tool_call":if(e.toolCall){if(!n.tools||0===n.tools.length){De.warn("收到 tool_call 但当前未注入工具,已忽略",{toolName:e.toolCall.name});break}c.push(e.toolCall),x=!0}break;case"search_result":if(!A)break;e.searchResults&&(h||(h=!0,m=Date.now(),yield E(null),yield j(t)),d=Ue(e.searchResults),yield J(d,m));break;case"done":De.info("收到 done",{finishReason:e.finishReason,usage:e.usage}),De.info(`第 ${u} 轮 chunk 统计`,T),"tool_calls"===e.finishReason&&(x=!0),e.usage&&(w=!0,b.promptTokens+=e.usage.promptTokens||0,b.completionTokens+=e.usage.completionTokens||0,b.totalTokens+=e.usage.totalTokens||0,b.reasoningTokens+=e.usage.reasoningTokens||0,b.cachedTokens+=e.usage.cachedTokens||0);break;case"error":return De.error("收到 error",e.error),void(yield Y(e.error??"未知错误"))}if(De.info(`第 ${u} 轮 for-await 循环结束`),De.debug("状态",{thinkingStarted:g,thinkingComplete:f}),S&&g&&!f&&(De.debug("补发 thinking_end"),f=!0,yield W(l)),x&&c.length>0){const e=c.map(e=>`${e.name}:${e.arguments}`).sort().join("|");if(e===k?_++:(_=0,k=e),_>=2){De.warn("检测到重复工具调用,注入终止提示",{signature:e.slice(0,200),count:_+1});c.map(e=>e.name).join(", ");r.push({role:"assistant",content:p,toolCalls:c});for(const e of c)r.push({role:"tool",content:`[系统提示] 你已经连续 ${_+1} 次使用相同参数调用 ${e.name},任务应已完成。请直接回复用户执行结果,不要再调用工具。`,toolCallId:e.id,toolName:e.name});yield se(u,i),p="";continue}const a=n.clientToolNames||this.config.clientToolNames,l=a?c.filter(e=>a.has(e.name)):[];if(l.length>0){De.info("检测到客户端工具调用,透传给客户端",l.map(e=>e.name));for(const e of l){let t;try{t=JSON.parse(e.arguments||"{}")}catch{t={}}yield L(e.id,e.name,t)}const e=Date.now()-s;return void(yield Q(p,void 0,e))}yield E(null);const g={role:"assistant",content:p,toolCalls:c};r.push(g);for(const e of c){const s=Date.now();let i;try{i=JSON.parse(e.arguments||"{}")}catch{r.push({role:"tool",content:"参数解析错误",toolCallId:e.id});continue}if(e.name===Pe){("string"==typeof i.query?i.query:"").trim()||(i.query=t)}const a=this.config.getAutoRunConfig?await this.config.getAutoRunConfig():o.autoRunConfig||this.config.autoRunConfig,l=this.config.tools?.get(e.name),c="manual"===a?.mode||!0===l?.requiresApproval;if(De.debug("检查工具批准",{toolName:e.name,autoRunConfigMode:a?.mode,requiresApproval:l?.requiresApproval,hasCallback:!!this.config.onToolApprovalRequest}),c&&this.config.onToolApprovalRequest){De.info("发送工具批准请求",e.name);const n={type:"tool_approval_request",data:{id:e.id,name:e.name,args:i,requestedAt:Date.now()}};yield n;if(!await this.config.onToolApprovalRequest({id:e.id,name:e.name,args:i})){const n=JSON.stringify({skipped:!0,message:"用户跳过了此工具"});if(e.name===Pe&&A){if(!h){h=!0,m=Date.now();const e="string"==typeof i.query?i.query:t;yield j(e)}y=!0,yield z(!1,m,`用户跳过了 ${Pe}`)}else yield V(e.id,e.name,n,!1,s);r.push({role:"tool",content:n,toolCallId:e.id,toolName:e.name});continue}}const u=e.name===Pe;if(u){if(A&&!h){h=!0,m=Date.now();const e="string"==typeof i.query?i.query:t;yield j(e)}}else yield F(e.id,e.name,i);const p=this.config.tools?.get(e.name);let g,f,k,_=n.signal;if(p?.timeout){const e=new AbortController;g=setTimeout(()=>e.abort(),p.timeout),n.signal.addEventListener("abort",()=>e.abort(),{once:!0}),_=e.signal}let b=!0;try{const t=[];let n=null;const o=()=>n?.(),s=e=>{t.push(e),o()};let r,a,l=!1;const c={toolCallId:e.id,toolName:e.name,onStdout:t=>{t&&s(G(e.id,e.name,"stdout",t))},onStderr:t=>{t&&s(G(e.id,e.name,"stderr",t))}};for(this.config.executeTool(e.name,i,_,c).then(e=>{r=e,l=!0,o()}).catch(e=>{a=e,l=!0,o()});!l||t.length>0;){for(;t.length>0;){const e=t.shift();e&&(yield e)}if(l)break;await new Promise(e=>n=e),n=null}if(a)throw a;f=JSON.stringify(r??{})}catch(e){if(b=!1,R(e))k=e.toolError,f=JSON.stringify({error:e.toolError.message});else{const t=e instanceof Error?e.message:String(e);k={message:t},f=JSON.stringify({error:t})}}void 0!==g&&clearTimeout(g);const w=this.config.tools?.get(e.name),T=b?w?.ui:void 0;if(u){if(A){let e,t=[];try{const n=JSON.parse(f||"{}");t=(Array.isArray(n?.results)?n.results:[]).map(e=>({title:"string"==typeof e?.title?e.title:"",url:"string"==typeof e?.url?e.url:"",snippet:"string"==typeof e?.snippet?e.snippet:""})).filter(e=>!!e.url),"string"==typeof n?.error&&n.error&&(e=n.error,b=!1)}catch{e=`${Pe} 返回结果解析失败`,b=!1}t.length>0&&(d=Ue(t),yield J(d,m)),y=!0,yield z(b,m,e)}}else yield V(e.id,e.name,f,b,s,k,T);if(r.push({role:"tool",content:f,toolCallId:e.id,toolName:e.name}),n.signal.aborted)return void(yield ne("请求已取消"))}yield se(u,i),p="";continue}yield se(u,i);break}catch(e){return yield se(u,i),void(n.signal.aborted?yield ne("请求已取消"):yield Y(e instanceof Error?e.message:String(e)))}}u>=i&&De.warn(`达到最大迭代次数 ${i},强制结束工具调用循环`),h&&!y&&(yield z(!0,m));const T=Date.now()-s,v=w?{promptTokens:b.promptTokens,completionTokens:b.completionTokens,totalTokens:b.totalTokens,...b.reasoningTokens>0?{reasoningTokens:b.reasoningTokens}:{},...b.cachedTokens>0?{cachedTokens:b.cachedTokens}:{}}:void 0;yield Q(p,v,T)}buildMessages(e,t){const n=[];e.systemPrompt&&n.push({role:"system",content:e.systemPrompt});for(const t of e.history){const e={role:t.role,content:t.content};t.tool_calls&&(e.toolCalls=t.tool_calls.map(e=>({id:e.id,name:e.function.name,arguments:e.function.arguments,thought_signature:e.thought_signature}))),"tool"===t.role&&t.tool_call_id&&(e.toolCallId=t.tool_call_id),n.push(e)}return t&&n.push({role:"user",content:t,images:e.images}),n}async*compactIfNeeded(e,t){if(!function(e,t){return Ne(e)>Ie(t)}(e,t))return e;const n=this.config.summarize;if(!n)return De.warn("上下文超限但未配置 summarize 回调,跳过压缩"),e;const o=Date.now(),s=Ne(e),i=Ie(t),r=e.length;yield function(e,t){return{type:"compact_start",data:{estimatedTokens:e,budget:t,startedAt:Date.now()}}}(s,i);const{messages:a,success:l}=await Ee(n,e,t);return yield function(e,t,n,o,s){const i=Date.now();return{type:"compact_end",data:{success:e,compressedTokens:t,originalMessageCount:n,compressedMessageCount:o,endedAt:i,duration:i-s}}}(l,Ne(a),r,a.length,o),a}};function je(e){return new We(e)}var Je={400:"请求参数错误",401:"API 认证失败,请检查 API Key 配置",402:"账户余额不足,请充值后重试",403:"没有权限访问此模型",404:"请求的模型或接口不存在",429:"请求过于频繁,请稍后重试",500:"API 服务器内部错误,请稍后重试",502:"API 网关错误,请稍后重试",503:"API 服务暂时不可用,请稍后重试",504:"API 请求超时,请稍后重试"};function ze(e,t,n){const o=function(e){try{const t=JSON.parse(e);if(t?.error?.message)return{message:t.error.message,type:t.error.type};if("string"==typeof t?.error_msg)return{message:t.error_msg};if("string"==typeof t?.message)return{message:t.message}}catch{}return null}(t),s=o?.message,i=Je[e];if(i)return s&&s.length<=100?`${i}(${s})`:i;if(s){return`${n} 错误 (${e}): ${s.length>200?s.slice(0,200)+"...":s}`}return`${n} 错误 (${e})`}var Fe=xe.module("ArkProtocol"),Ve=class{name="ark";apiKey;apiUrl;constructor(e){this.apiKey=e.apiKey,this.apiUrl=e.apiUrl??fe}async*stream(e,t,n){const o=this.buildRequestBody(e,t,n);Fe.debug("发送 ARK 请求",{url:`${this.apiUrl}/responses`,model:n.model,enableSearch:n.enableSearch,enableThinking:n.enableThinking,toolsCount:t.length});const s=await fetch(`${this.apiUrl}/responses`,{method:"POST",headers:{Authorization:`Bearer ${this.apiKey}`,"Content-Type":"application/json"},body:JSON.stringify(o),signal:n.signal});if(!s.ok){const e=await s.text();return Fe.error("ARK API 错误",{status:s.status,body:e.slice(0,500)}),void(yield{type:"error",error:ze(s.status,e,"ARK")})}const i=s.body?.getReader();i?yield*this.parseSSE(i):yield{type:"error",error:"无法获取响应流"}}buildRequestBody(e,t,n){const o=this.convertMessages(e),s={model:n.model,stream:!0,max_output_tokens:n.familyConfig.defaultMaxTokens??16384,input:o},i=[],r=t.some(e=>e.name===Pe);n.enableSearch&&!r&&i.push({type:"web_search",max_keyword:5,limit:20});for(const e of t)i.push({type:"function",name:e.name,description:e.description,parameters:e.parameters});return i.length>0&&(s.tools=i),n.enableThinking&&(s.thinking={type:"enabled"}),s}convertMessages(e){const t=[];for(const n of e)switch(n.role){case"system":t.push({role:"system",content:n.content});break;case"user":{const e=[{type:"input_text",text:n.content||(n.images?.length?"请分析这张图片":"")}];if(n.images?.length)for(const t of n.images)e.push({type:"input_image",image_url:t.startsWith("data:")?t:`data:image/jpeg;base64,${t}`});t.push({role:"user",content:e});break}case"assistant":if(n.toolCalls?.length){n.content&&t.push({type:"message",role:"assistant",content:[{type:"output_text",text:n.content}]});for(const e of n.toolCalls)t.push({type:"function_call",call_id:e.id,name:e.name,arguments:e.arguments})}else t.push({role:"developer",content:`[上一轮AI回复]: ${n.content}`});break;case"tool":t.push({type:"function_call_output",call_id:n.toolCallId,output:n.content})}return t}async*parseSSE(e){const t=new TextDecoder;let n="";const o=new Map;let s=null;const i=[];let r,a=!1,l=!1,c=!1;for(;;){const{done:u,value:p}=await e.read();if(u)break;n+=t.decode(p,{stream:!0});const d=n.split("\n");n=d.pop()||"";for(const e of d){if(a)continue;if(!e.startsWith("data:"))continue;const t=e.slice(5).trim();if("[DONE]"===t){if(a=!0,o.size>0){for(const e of o.values())yield{type:"tool_call_done",toolCall:e};yield{type:"done",finishReason:"tool_calls",usage:r}}else yield{type:"done",finishReason:"stop",usage:r};return}try{const e=JSON.parse(t),n=e.response?.usage||e.usage;switch(n&&(r={promptTokens:n.input_tokens||n.prompt_tokens||0,completionTokens:n.output_tokens||n.completion_tokens||0,totalTokens:(n.input_tokens||n.prompt_tokens||0)+(n.output_tokens||n.completion_tokens||0),reasoningTokens:n.output_tokens_details?.reasoning_tokens||0,cachedTokens:n.input_tokens_details?.cached_tokens||0}),e.type){case"response.output_item.added":{const t=e.item;"function_call"===t?.type&&t.call_id&&(s=t.call_id,o.set(t.call_id,{id:t.call_id,name:t.name||"",arguments:t.arguments||""}),yield{type:"tool_call_start",toolCall:{id:t.call_id,name:t.name||""}});break}case"response.function_call_arguments.delta":if(s){const t=o.get(s);t&&(t.arguments+=e.delta||"",yield{type:"tool_call_delta",toolCall:{id:s,arguments:e.delta||""}})}break;case"response.function_call_arguments.done":case"response.output_item.done":{const t=e.item;if("function_call"===t?.type&&t.call_id){const e=o.get(t.call_id);o.set(t.call_id,{id:t.call_id,name:t.name||e?.name||"",arguments:t.arguments||e?.arguments||"{}"})}break}case"response.output_text.annotation.added":{const t=e.annotation;if(t?.url){i.some(e=>e.url===t.url)||(i.push({title:t.title||t.text||"",url:t.url,snippet:t.summary||t.snippet||""}),yield{type:"search_result",searchResults:[...i]})}break}case"response.output_text.delta":e.delta&&(c||(c=!0,l||(l=!0,yield{type:"thinking_done"})),yield{type:"text_delta",delta:e.delta});break;case"response.reasoning_summary_text.delta":e.delta&&!l&&(yield{type:"thinking_delta",delta:e.delta})}}catch{}}}if(!a)if(o.size>0){for(const e of o.values())yield{type:"tool_call_done",toolCall:e};yield{type:"done",finishReason:"tool_calls",usage:r}}else yield{type:"done",finishReason:"stop",usage:r}}};function Ge(e){return new Ve(e)}var Le=xe.module("DeepSeekProtocol"),Be=class{name="deepseek";apiKey;apiUrl;constructor(e){this.apiKey=e.apiKey,this.apiUrl=e.apiUrl??fe}async*stream(e,t,n){const o=this.buildRequestBody(e,t,n),s=`${this.apiUrl}/responses`;Le.debug("发送 DeepSeek 请求",{url:s,model:n.model,enableSearch:n.enableSearch,enableThinking:n.enableThinking,toolsCount:t.length});const i=await fetch(s,{method:"POST",headers:{Authorization:`Bearer ${this.apiKey}`,"Content-Type":"application/json"},body:JSON.stringify(o),signal:n.signal});if(!i.ok){const e=await i.text();return Le.error("DeepSeek API 错误",{status:i.status,body:e.slice(0,500)}),void(yield{type:"error",error:ze(i.status,e,"DeepSeek")})}const r=i.body?.getReader();r?yield*this.parseSSE(r,n.enableThinking):yield{type:"error",error:"无法获取响应流"}}buildRequestBody(e,t,n){const o=this.convertMessages(e),s={model:n.model,stream:!0,max_output_tokens:n.familyConfig.defaultMaxTokens??32768,input:o},i=[],r=t.some(e=>e.name===Pe);n.enableSearch&&!r&&i.push({type:"web_search",max_keyword:5,limit:20});for(const e of t)i.push({type:"function",name:e.name,description:e.description,parameters:e.parameters});return i.length>0&&(s.tools=i),n.enableThinking&&(s.thinking={type:"enabled"}),s}convertMessages(e){const t=[];for(const n of e)switch(n.role){case"system":t.push({role:"system",content:n.content});break;case"user":{const e=[{type:"input_text",text:n.content||(n.images?.length?"请分析这张图片":"")}];if(n.images?.length)for(const t of n.images)e.push({type:"input_image",image_url:t.startsWith("data:")?t:`data:image/jpeg;base64,${t}`});t.push({role:"user",content:e});break}case"assistant":if(n.toolCalls?.length)for(const e of n.toolCalls)t.push({type:"function_call",call_id:e.id,name:e.name,arguments:e.arguments});else t.push({role:"developer",content:`[上一轮AI回复]: ${n.content}`});break;case"tool":t.push({type:"function_call_output",call_id:n.toolCallId,output:n.content})}return t}async*parseSSE(e,t){const n=new TextDecoder;let o="";const s=new Map;let i=null;const r=[];let a,l=!1,c=!1,u=!1;for(;;){const{done:p,value:d}=await e.read();if(p)break;o+=n.decode(d,{stream:!0});const m=o.split("\n");o=m.pop()||"";for(const e of m){if(l)continue;if(!e.startsWith("data:"))continue;const n=e.slice(5).trim();if("[DONE]"===n){if(l=!0,s.size>0){for(const e of s.values())yield{type:"tool_call_done",toolCall:e};yield{type:"done",finishReason:"tool_calls",usage:a}}else yield{type:"done",finishReason:"stop",usage:a};return}try{const e=JSON.parse(n),o=e.response?.usage||e.usage;switch(o&&(a={promptTokens:o.input_tokens||o.prompt_tokens||0,completionTokens:o.output_tokens||o.completion_tokens||0,totalTokens:(o.input_tokens||o.prompt_tokens||0)+(o.output_tokens||o.completion_tokens||0),reasoningTokens:o.output_tokens_details?.reasoning_tokens||o.completion_tokens_details?.reasoning_tokens||0}),e.type){case"response.output_item.added":{const t=e.item;"function_call"===t?.type&&t.call_id&&(i=t.call_id,s.set(t.call_id,{id:t.call_id,name:t.name||"",arguments:t.arguments||""}),yield{type:"tool_call_start",toolCall:{id:t.call_id,name:t.name||""}});break}case"response.function_call_arguments.delta":if(i){const t=s.get(i);t&&(t.arguments+=e.delta||"",yield{type:"tool_call_delta",toolCall:{id:i,arguments:e.delta||""}})}break;case"response.function_call_arguments.done":case"response.output_item.done":{const t=e.item;if("function_call"===t?.type&&t.call_id){const e=s.get(t.call_id);s.set(t.call_id,{id:t.call_id,name:t.name||e?.name||"",arguments:t.arguments||e?.arguments||"{}"})}break}case"response.output_text.annotation.added":{const t=e.annotation;if(t?.url){r.some(e=>e.url===t.url)||(r.push({title:t.title||t.text||"",url:t.url,snippet:t.summary||t.snippet||""}),yield{type:"search_result",searchResults:[...r]})}break}case"response.output_text.delta":e.delta&&(u||(u=!0,t&&!c&&(c=!0,yield{type:"thinking_done"})),yield{type:"text_delta",delta:e.delta});break;case"response.reasoning_summary_text.delta":t&&e.delta&&!c&&(yield{type:"thinking_delta",delta:e.delta})}}catch{}}}if(!l)if(s.size>0){for(const e of s.values())yield{type:"tool_call_done",toolCall:e};yield{type:"done",finishReason:"tool_calls",usage:a}}else yield{type:"done",finishReason:"stop",usage:a}}};function Qe(e){return new Be(e)}var He=xe.module("QwenProtocol"),Ye=class{name="qwen";apiKey;apiUrl;constructor(e){this.apiKey=e.apiKey,this.apiUrl=e.apiUrl??"https://dashscope.aliyuncs.com/compatible-mode/v1"}async*stream(e,t,n){const o=this.buildRequestBody(e,t,n),s=`${this.apiUrl}/chat/completions`;He.debug("发送 Qwen 请求(兼容模式)",{url:s,model:n.model,enableThinking:n.enableThinking,toolsCount:t.length});const i=await fetch(s,{method:"POST",headers:{Authorization:`Bearer ${this.apiKey}`,"Content-Type":"application/json"},body:JSON.stringify(o),signal:n.signal});if(!i.ok){const e=await i.text();return He.error("Qwen API 错误",{status:i.status,body:e.slice(0,500)}),void(yield{type:"error",error:ze(i.status,e,"Qwen")})}const r=i.body?.getReader();r?yield*this.parseSSE(r,n.enableThinking):yield{type:"error",error:"无法获取响应流"}}buildRequestBody(e,t,n){const o=this.convertMessages(e),s={model:n.model,messages:o,stream:!0,stream_options:{include_usage:!0}};return n.enableThinking&&(s.enable_thinking=!0,s.thinking_budget=38400),t.length>0&&(s.tools=t.map(e=>({type:"function",function:{name:e.name,description:e.description,parameters:e.parameters}}))),s}convertMessages(e){const t=[];for(const n of e)switch(n.role){case"system":t.push({role:"system",content:n.content});break;case"user":{const e=n.content||(n.images?.length?"请分析这张图片":"");if(n.images?.length){const o=[{type:"text",text:e}];for(const e of n.images)o.push({type:"image_url",image_url:{url:e.startsWith("data:")?e:`data:image/jpeg;base64,${e}`}});t.push({role:"user",content:o})}else t.push({role:"user",content:e});break}case"assistant":n.toolCalls?.length?t.push({role:"assistant",content:n.content||null,tool_calls:n.toolCalls.map(e=>({id:e.id,type:"function",function:{name:e.name,arguments:e.arguments}}))}):t.push({role:"assistant",content:n.content});break;case"tool":t.push({role:"tool",tool_call_id:n.toolCallId,content:n.content})}return t}async*parseSSE(e,t){const n=new TextDecoder;let o="";const s=new Map;let i,r,a=!1,l=!1;for(;;){const{done:c,value:u}=await e.read();if(c)break;o+=n.decode(u,{stream:!0});const p=o.split("\n");o=p.pop()||"";for(const e of p){if(!e.startsWith("data:"))continue;const n=e.slice(5).trim();if(n&&"[DONE]"!==n)try{const e=JSON.parse(n);e.usage&&(i={promptTokens:e.usage.prompt_tokens||0,completionTokens:e.usage.completion_tokens||0,totalTokens:e.usage.total_tokens||(e.usage.prompt_tokens||0)+(e.usage.completion_tokens||0)});const o=e.choices?.[0];if(!o)continue;const c=o.delta;if(!c)continue;if(t&&c.reasoning_content&&!l&&(yield{type:"thinking_delta",delta:c.reasoning_content}),c.content&&(!t||a||l||(l=!0,yield{type:"thinking_done"}),a=!0,yield{type:"text_delta",delta:c.content}),c.tool_calls?.length)for(const e of c.tool_calls){const t=e.index??0,n=s.get(t);n?e.function?.arguments&&(n.arguments+=e.function.arguments):(s.set(t,{id:e.id||`call_${t}`,name:e.function?.name||"",arguments:e.function?.arguments||""}),yield{type:"tool_call_start",toolCall:{id:e.id||`call_${t}`,name:e.function?.name||""}})}o.finish_reason&&(r=o.finish_reason)}catch{}else if("[DONE]"===n){const e=Array.from(s.values());if(e.length>0){for(const t of e)yield{type:"tool_call_done",toolCall:t};yield{type:"done",finishReason:"tool_calls",usage:i}}else{const e="tool_calls"===r||"length"===r||"error"===r?r:"stop";yield{type:"done",finishReason:e,usage:i}}return}}}const c=Array.from(s.values());if(c.length>0){for(const e of c)yield{type:"tool_call_done",toolCall:e};yield{type:"done",finishReason:"tool_calls",usage:i}}else{const e="tool_calls"===r||"length"===r||"error"===r?r:"stop";yield{type:"done",finishReason:e,usage:i}}}};function Ze(e){return new Ye(e)}var Xe=xe.module("GeminiProtocol"),et=class{name="gemini";apiKey;apiUrl;constructor(e){this.apiKey=e.apiKey,this.apiUrl=e.apiUrl??"https://generativelanguage.googleapis.com/v1beta"}async*stream(e,t,n){const o=this.buildRequestBody(e,t,n),s=`${this.apiUrl}/models/${n.model}:streamGenerateContent?key=${this.apiKey}&alt=sse`;Xe.debug("发送 Gemini 请求",{url:s.replace(this.apiKey,"***"),model:n.model,enableSearch:n.enableSearch,enableThinking:n.enableThinking,toolsCount:t.length});const i=await fetch(s,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(o),signal:n.signal});if(!i.ok){const e=await i.text();return Xe.error("Gemini API 错误",{status:i.status,body:e.slice(0,500)}),void(yield{type:"error",error:ze(i.status,e,"Gemini")})}const r=i.body?.getReader();r?yield*this.parseSSE(r):yield{type:"error",error:"无法获取响应流"}}buildRequestBody(e,t,n){const{systemInstruction:o,contents:s}=this.convertMessages(e),i={contents:s,generationConfig:{maxOutputTokens:n.familyConfig.defaultMaxTokens??65536}};o&&(i.systemInstruction=o),n.enableThinking&&(i.generationConfig.thinkingConfig={thinkingBudget:24576,includeThoughts:!0});const r=[];if(t.length>0){const e=t.map(e=>({name:e.name,description:e.description,parameters:e.parameters})),n=new Map;for(const t of e)n.has(t.name)||n.set(t.name,t);r.push({functionDeclarations:Array.from(n.values())})}else n.enableSearch&&r.push({googleSearch:{}});return r.length>0&&(i.tools=r),i}convertMessages(e){let t;const n=[];for(const o of e)switch(o.role){case"system":t={parts:[{text:o.content}]};break;case"user":{const e=[{text:o.content||(o.images?.length?"请分析这张图片":"")}];if(o.images?.length)for(const t of o.images)if(t.startsWith("data:")){const n=t.match(/^data:([^;]+);base64,(.+)$/);n&&e.push({inlineData:{mimeType:n[1],data:n[2]}})}else e.push({inlineData:{mimeType:"image/jpeg",data:t}});n.push({role:"user",parts:e});break}case"assistant":if(o.toolCalls?.length){const e=[];for(const t of o.toolCalls){const n={functionCall:{name:t.name,args:JSON.parse(t.arguments||"{}")}};n.thoughtSignature=t.thoughtSignature??"skip_thought_signature_validator",e.push(n)}n.push({role:"model",parts:e})}else n.push({role:"model",parts:[{text:o.content}]});break;case"tool":n.push({role:"user",parts:[{functionResponse:{name:o.toolName||"unknown",response:{result:o.content}}}]})}return{systemInstruction:t,contents:n}}async*parseSSE(e){const t=new TextDecoder;let n="";const o=new Map;let s=!1,i=0;for(;;){const{done:r,value:a}=await e.read();if(r)break;n+=t.decode(a,{stream:!0});const l=n.split("\n");n=l.pop()||"";for(const e of l){if(!e.startsWith("data:"))continue;const t=e.slice(5).trim();if(t)try{const e=JSON.parse(t),n=e.candidates?.[0];if(!n?.content?.parts)continue;for(const e of n.content.parts)if(e.text&&(!0===e.thought?yield{type:"thinking_delta",delta:e.text}:(s||(s=!0,yield{type:"thinking_done"}),yield{type:"text_delta",delta:e.text})),e.functionCall){const t="gemini-"+i++,n={id:t,name:e.functionCall.name,arguments:JSON.stringify(e.functionCall.args||{})};e.thoughtSignature&&(n.thoughtSignature=e.thoughtSignature),o.set(t,n),yield{type:"tool_call_start",toolCall:{id:t,name:n.name}},yield{type:"tool_call_done",toolCall:n}}const r=n.groundingMetadata;if(r?.groundingChunks?.length){const e=[];for(const t of r.groundingChunks)t.web?.uri&&e.push({title:t.web.title||"",url:t.web.uri,snippet:""});e.length>0&&(yield{type:"search_result",searchResults:e})}if(n.finishReason){const t=e.usageMetadata,n=t?{promptTokens:t.promptTokenCount||0,completionTokens:t.candidatesTokenCount||0,totalTokens:t.totalTokenCount||0,reasoningTokens:t.thoughtsTokenCount||0,cachedTokens:t.cachedContentTokenCount||0}:void 0;return void(o.size>0?yield{type:"done",finishReason:"tool_calls",usage:n}:yield{type:"done",finishReason:"stop",usage:n})}}catch{}}}o.size>0?yield{type:"done",finishReason:"tool_calls"}:yield{type:"done",finishReason:"stop"}}};function tt(e){return new et(e)}var nt=xe.module("OpenAIProtocol"),ot=class{name="openai";apiKey;apiUrl;constructor(e){this.apiKey=e.apiKey,this.apiUrl=e.apiUrl??ye}async*stream(e,t,n){const o=this.buildRequestBody(e,t,n),s=`${this.apiUrl}/responses`;nt.debug("发送 OpenAI 请求",{url:s,model:n.model,toolsCount:t.length});const i=await fetch(s,{method:"POST",headers:{Authorization:`Bearer ${this.apiKey}`,"Content-Type":"application/json","HTTP-Referer":"https://ai-chat.local","X-Title":"AI Chat"},body:JSON.stringify(o),signal:n.signal});if(!i.ok){const e=await i.text();return nt.error("OpenAI API 错误",{status:i.status,body:e.slice(0,500)}),void(yield{type:"error",error:ze(i.status,e,"OpenAI")})}const r=i.body?.getReader();r?yield*this.parseSSE(r,n.enableThinking):yield{type:"error",error:"无法获取响应流"}}buildRequestBody(e,t,n){const o=this.convertMessages(e),s={model:n.model,stream:!0,input:o};return n.enableThinking&&(s.reasoning={effort:"high"}),t.length>0&&(s.tools=t.map(e=>({type:"function",name:e.name,description:e.description,parameters:e.parameters}))),s}convertMessages(e){const t=[];for(const n of e)switch(n.role){case"system":t.push({role:"system",content:n.content});break;case"user":{const e=[{type:"input_text",text:n.content||(n.images?.length?"请分析这张图片":"")}];if(n.images?.length)for(const t of n.images)e.push({type:"input_image",image_url:t.startsWith("data:")?t:`data:image/jpeg;base64,${t}`,detail:"auto"});t.push({role:"user",content:e});break}case"assistant":if(n.toolCalls?.length)for(const e of n.toolCalls)t.push({type:"function_call",call_id:e.id,name:e.name,arguments:e.arguments});else t.push({role:"developer",content:`[上一轮AI回复]: ${n.content}`});break;case"tool":t.push({type:"function_call_output",call_id:n.toolCallId,output:n.content})}return t}async*parseSSE(e,t){const n=new TextDecoder;let o="";const s=new Map;let i=null;const r=[];let a,l=!1,c=!1,u=!1;for(;;){const{done:p,value:d}=await e.read();if(p)break;o+=n.decode(d,{stream:!0});const m=o.split("\n");o=m.pop()||"";for(const e of m){if(l)continue;if(!e.startsWith("data:"))continue;const n=e.slice(5).trim();if("[DONE]"===n){if(l=!0,s.size>0){for(const e of s.values())yield{type:"tool_call_done",toolCall:e};yield{type:"done",finishReason:"tool_calls",usage:a}}else yield{type:"done",finishReason:"stop",usage:a};return}try{const e=JSON.parse(n);nt.debug("SSE 事件",{type:e.type,event:JSON.stringify(e).slice(0,200)});const o=e.response?.usage||e.usage;switch(o&&(a={promptTokens:o.input_tokens??o.prompt_tokens??0,completionTokens:o.output_tokens??o.completion_tokens??0,totalTokens:(o.input_tokens??o.prompt_tokens??0)+(o.output_tokens??o.completion_tokens??0),reasoningTokens:o.output_tokens_details?.reasoning_tokens??0,cachedTokens:o.input_tokens_details?.cached_tokens??o.prompt_tokens_details?.cached_tokens??0}),e.type){case"response.output_item.added":{const t=e.item,n=t?.call_id||t?.id;if("function_call"===t?.type&&n){i=n;let e=t.arguments||t.input||"";"object"==typeof e&&(e=JSON.stringify(e)),s.set(n,{id:n,name:t.name||t.function?.name||"",arguments:e}),nt.debug("工具调用开始",{id:n,name:t.name,args:e.slice(0,100)}),yield{type:"tool_call_start",toolCall:{id:n,name:t.name||t.function?.name||""}}}break}case"response.function_call_arguments.delta":{const t=e.delta;if(i&&t){const e=s.get(i);e&&(e.arguments+=t,yield{type:"tool_call_delta",toolCall:{id:i,arguments:t}})}break}case"response.function_call_arguments.done":{const t=e.item_id||e.call_id||i;if(t){const n=s.get(t);if(n){e.arguments&&(n.arguments=e.arguments);try{JSON.parse(n.arguments)}catch{nt.warn("工具参数解析失败,使用空对象",{args:n.arguments.slice(0,100)}),n.arguments="{}"}}}break}case"response.output_item.done":{const t=e.item,n=t?.call_id||t?.id;if("function_call"===t?.type&&n){const e=s.get(n);let o=t.arguments||t.input||e?.arguments||"{}";"object"==typeof o&&(o=JSON.stringify(o)),s.set(n,{id:n,name:t.name||t.function?.name||e?.name||"",arguments:o}),nt.debug("工具调用完成",{id:n,name:t.name,args:o.slice(0,100)})}break}case"response.output_text.annotation.added":{const t=e.annotation;if(t?.url){r.some(e=>e.url===t.url)||(r.push({title:t.title||t.text||"",url:t.url,snippet:t.summary||t.snippet||""}),yield{type:"search_result",searchResults:[...r]})}break}case"response.output_text.delta":e.delta&&(u||(u=!0,t&&!c&&(c=!0,yield{type:"thinking_done"})),yield{type:"text_delta",delta:e.delta});break;case"response.reasoning_summary_text.delta":t&&e.delta&&!c&&(yield{type:"thinking_delta",delta:e.delta});break;case"response.done":case"response.completed":{const t=e.response;if(t?.output?.length)for(const e of t.output)if("function_call"===e.type&&e.call_id){const t=s.get(e.call_id);let n=e.arguments||t?.arguments||"{}";"object"==typeof n&&(n=JSON.stringify(n)),s.set(e.call_id,{id:e.call_id,name:e.name||t?.name||"",arguments:n}),nt.debug("response.completed: 更新工具参数",{id:e.call_id,args:n.slice(0,100)})}const n=t?.usage,o=n?{promptTokens:n.input_tokens||n.prompt_tokens||0,completionTokens:n.output_tokens||n.completion_tokens||0,totalTokens:(n.input_tokens||n.prompt_tokens||0)+(n.output_tokens||n.completion_tokens||0),reasoningTokens:n.output_tokens_details?.reasoning_tokens||0,cachedTokens:n.input_tokens_details?.cached_tokens||n.prompt_tokens_details?.cached_tokens||0}:void 0;if(a=o,l=!0,s.size>0){for(const e of s.values())nt.debug("response.completed: 发出 tool_call_done",e),yield{type:"tool_call_done",toolCall:e};yield{type:"done",finishReason:"tool_calls",usage:o}}else yield{type:"done",finishReason:"stop",usage:o};return}}}catch(t){nt.warn("SSE 解析错误",{line:e.slice(0,100),error:String(t)})}}}if(!l)if(nt.debug("流结束,执行兜底逻辑",{pendingToolCalls:s.size}),s.size>0){for(const e of s.values())yield{type:"tool_call_done",toolCall:e};yield{type:"done",finishReason:"tool_calls",usage:a}}else yield{type:"done",finishReason:"stop",usage:a}}};function st(e){return new ot(e)}var it=xe.module("AnthropicProtocol"),rt=class{name="anthropic";gateway;constructor(e){this.gateway=s({apiKey:e.apiKey})}async*stream(e,t,n){it.debug("使用 Vercel AI Gateway 调用 Claude",{model:n.model,enableThinking:n.enableThinking,toolsCount:t.length});try{const o=this.convertMessages(e),s={model:this.gateway(n.model),messages:o,maxOutputTokens:n.familyConfig.defaultMaxTokens,abortSignal:n.signal};t.length>0&&(s.tools=this.convertTools(t)),n.enableThinking&&(s.providerOptions={anthropic:{thinking:{type:"enabled",budgetTokens:1e4}}}),it.debug("发送请求到 Vercel AI Gateway",{model:n.model,messagesCount:o.length,toolsCount:t.length,enableThinking:n.enableThinking});const r=i(s);yield*this.parseStream(r)}catch(e){const t=at(e);it.error("Vercel AI Gateway 错误",{error:t}),yield{type:"error",error:t}}}convertMessages(e){const t=[];for(const n of e)switch(n.role){case"system":t.push({role:"system",content:n.content});break;case"user":{const e=n.content||(n.images?.length?"请分析这张图片":"");if(n.images?.length){const o=[{type:"text",text:e}];for(const e of n.images)o.push({type:"image",image:e.startsWith("data:")?e:`data:image/jpeg;base64,${e}`});t.push({role:"user",content:o})}else t.push({role:"user",content:e});break}case"assistant":n.content&&t.push({role:"assistant",content:n.content});break;case"tool":t.push({role:"user",content:`[工具 ${n.toolName||"unknown"} 返回结果]: ${n.content}`})}return t}convertTools(e){const t={};for(const n of e){const e=this.jsonSchemaToZod(n.parameters);t[n.name]=r({description:n.description,inputSchema:e})}return t}jsonSchemaToZod(e){const t={};for(const[n,o]of Object.entries(e.properties)){let s;switch(o.type){case"string":s=o.enum?a.enum(o.enum):a.string();break;case"number":case"integer":s=a.number();break;case"boolean":s=a.boolean();break;case"array":s=a.array(a.string());break;default:s=a.unknown()}o.description&&(s=s.describe(o.description)),e.required?.includes(n)||(s=s.optional()),t[n]=s}return a.object(t)}async*parseStream(e){const t=new Map;let n=!1,o=!1;for await(const s of e.fullStream)switch(s.type){case"reasoning-delta":"text"in s&&s.text&&(n=!0,yield{type:"thinking_delta",delta:s.text});break;case"reasoning-end":n&&!o&&(o=!0,yield{type:"thinking_done"});break;case"text-delta":n&&!o&&(o=!0,yield{type:"thinking_done"}),"text"in s&&s.text&&(yield{type:"text_delta",delta:s.text});break;case"tool-call":if("toolCallId"in s&&"toolName"in s){const e=s.toolCallId,n=s.toolName,o="input"in s?s.input:null,i=o?"string"==typeof o?o:JSON.stringify(o):"{}";yield{type:"tool_call_start",toolCall:{id:e,name:n}},t.set(e,{id:e,name:n,arguments:i}),yield{type:"tool_call_done",toolCall:{id:e,name:n,arguments:i}}}break;case"error":{const e="error"in s?s.error:void 0,t=e?at(e):"模型请求失败";return it.error("AI SDK stream error 事件",{error:t}),void(yield{type:"error",error:t})}case"finish":{const e=t.size>0?"tool_calls":"finishReason"in s&&"stop"===s.finishReason?"stop":"finishReason"in s&&"length"===s.finishReason?"length":"stop",n="totalUsage"in s?s.totalUsage:"usage"in s?s.usage:void 0,o=n?.promptTokens??n?.inputTokens??0,i=n?.completionTokens??n?.outputTokens??0,r=n?{promptTokens:o,completionTokens:i,totalTokens:n.totalTokens??o+i}:void 0;return void(yield{type:"done",finishReason:e,usage:r})}}yield{type:"done",finishReason:"stop"}}};function at(e){if(!e||"object"!=typeof e)return"未知错误";const t=e,n=t.cause?.data?.error;if(n?.message){const e=t.cause?.statusCode||t.statusCode;return"insufficient_funds"===n.type||402===e?"账户余额不足,请充值后重试":401===e?"API 认证失败,请检查 API Key 配置":429===e?"请求过于频繁,请稍后重试":`API 错误: ${n.message}`}if(t.cause?.responseBody)try{const e=JSON.parse(t.cause.responseBody);if(e?.error?.message){const n=t.cause?.statusCode||t.statusCode;return"insufficient_funds"===e.error.type||402===n?"账户余额不足,请充值后重试":`API 错误: ${e.error.message}`}}catch{}const o=t.statusCode||t.cause?.statusCode;if(402===o)return"账户余额不足,请充值后重试";if(401===o)return"API 认证失败,请检查 API Key 配置";if(429===o)return"请求过于频繁,请稍后重试";if(503===o)return"服务暂时不可用,请稍后重试";const s=t.message||"未知错误";return s.length>200?s.slice(0,200)+"...":s}function lt(e){return new rt(e)}var ct=xe.module("UnifiedAdapter"),ut=class{name="unified";get supportedModels(){return _().map(e=>e.id)}protocols=new Map;constructor(e){e.arkApiKey&&(this.protocols.set("ark",Ge({apiKey:e.arkApiKey,apiUrl:e.arkApiUrl})),this.protocols.set("deepseek",Qe({apiKey:e.arkApiKey,apiUrl:e.arkApiUrl}))),e.qwenApiKey&&this.protocols.set("qwen",Ze({apiKey:e.qwenApiKey,apiUrl:e.qwenApiUrl})),e.geminiApiKey&&this.protocols.set("gemini",tt({apiKey:e.geminiApiKey,apiUrl:e.geminiApiUrl})),e.openrouterApiKey&&this.protocols.set("openai",st({apiKey:e.openrouterApiKey,apiUrl:e.openrouterApiUrl})),e.vercelApiKey&&this.protocols.set("anthropic",lt({apiKey:e.vercelApiKey}))}supportsModel(e){const t=k(e);return!!t&&this.protocols.has(t)}getModelFamilyConfig(e){return y(e)}async*streamOnce(e,t,n){const{model:o,enableThinking:s=!1,enableSearch:i=!1,signal:r}=n,a=e.map(e=>({role:e.role,content:e.content,images:e.images,toolCalls:e.toolCalls?.map(e=>({id:e.id,name:e.name,arguments:e.arguments,thoughtSignature:e.thought_signature})),toolCallId:e.toolCallId,toolName:e.toolName})),l=t;yield*this.stream(a,l,{model:o,enableThinking:s,enableSearch:i,signal:r})}async*stream(e,t,n){const{model:o,enableThinking:s=!1,enableSearch:i=!1,signal:r}=n,a=k(o),l=y(o);if(!a)return void(yield{type:"error",error:`未知模型: ${o}`});if(!l)return void(yield{type:"error",error:`模型 ${o} 缺少家族配置`});const c=this.protocols.get(a);if(!c)return void(yield{type:"error",error:`Protocol ${a} 未配置`});ct.debug("开始流式调用",{model:o,protocol:a,family:l.id,enableThinking:s,enableSearch:i});const u=c.stream(e,t,{model:o,familyConfig:l,enableThinking:s,enableSearch:i,signal:r});yield*this.transformEvents(u,l,s,i)}async*transformEvents(e,t,n,o){let s=!1;for await(const i of e)switch(i.type){case"thinking_delta":if(n&&t.supportsThinking&&i.delta){let e=i.delta;s||(e=e.replace(/^\n+/,""),e&&(s=!0)),e&&(yield{type:"thinking",thinking:e})}break;case"thinking_done":n&&t.supportsThinking&&(yield{type:"thinking_done"});break;case"text_delta":i.delta&&(yield{type:"text",text:i.delta});break;case"tool_call_done":if(i.toolCall){const e={id:i.toolCall.id||"",name:i.toolCall.name||"",arguments:i.toolCall.arguments||"{}"};i.toolCall.thoughtSignature&&(e.thought_signature=i.toolCall.thoughtSignature),yield{type:"tool_call",toolCall:e}}break;case"search_result":if(o&&i.searchResults){const e=i.searchResults.map(e=>({title:e.title,url:e.url,snippet:e.snippet}));yield{type:"search_result",searchResults:e}}break;case"done":yield{type:"done",finishReason:i.finishReason||"stop",usage:i.usage?{promptTokens:i.usage.promptTokens,completionTokens:i.usage.completionTokens,totalTokens:i.usage.totalTokens,reasoningTokens:i.usage.reasoningTokens,cachedTokens:i.usage.cachedTokens}:void 0};break;case"error":yield{type:"error",error:i.error||"未知错误"}}}};function pt(e){return new ut(e)}var dt=class{config;adapter;orchestrator;toolExecutor;abortController=null;tools=new Map;toolConfig;mcpManager=null;mcpConfigs;constructor(e,t){this.config={arkApiKey:e.arkApiKey,arkApiUrl:e.arkApiUrl||fe,qwenApiKey:e.qwenApiKey||"",qwenApiUrl:e.qwenApiUrl||"https://dashscope.aliyuncs.com/compatible-mode/v1",openrouterApiKey:e.openrouterApiKey||"",openrouterApiUrl:e.openrouterApiUrl||ye,vercelApiKey:e.vercelApiKey||"",tavilyApiKey:e.tavilyApiKey||"",geminiApiKey:e.geminiApiKey,cwd:e.cwd||process.cwd()},this.toolExecutor=t||he(this.config.cwd),this.toolConfig=e.tools,this.mcpConfigs=e.mcpServers,this.tools=new Map,this.adapter=new ut({arkApiKey:this.config.arkApiKey,arkApiUrl:this.config.arkApiUrl,qwenApiKey:this.config.qwenApiKey,qwenApiUrl:this.config.qwenApiUrl,geminiApiKey:this.config.geminiApiKey,openrouterApiKey:this.config.openrouterApiKey,openrouterApiUrl:this.config.openrouterApiUrl,vercelApiKey:this.config.vercelApiKey}),this.orchestrator=new We({executeTool:this.executeTool.bind(this),tools:this.tools,onToolApprovalRequest:e.onToolApprovalRequest,getAutoRunConfig:e.getAutoRunConfig,summarize:e.summarize})}async asyncInit(){if(this.toolConfig&&0===this.tools.size){const e=await O(this.toolConfig);for(const t of e)this.tools.set(t.name,t)}var e;if(this.config.tavilyApiKey&&!this.tools.has(Pe)&&this.tools.set(Pe,(e=this.config.tavilyApiKey,{name:Pe,description:"联网搜索工具。输入 query(搜索关键词/问题),返回搜索结果列表(title/url/snippet)。用于获取实时信息与可引用来源。",parameters:{type:"object",properties:{query:{type:"string",description:"搜索关键词或问题(必填)"},max_results:{type:"number",description:"最大返回结果数(可选,默认 5)"}},required:["query"]},execute:async(t,n)=>{const o="string"==typeof t.query?t.query:"",s="number"==typeof t.max_results&&Number.isFinite(t.max_results)?Math.max(1,Math.min(10,Math.floor(t.max_results))):5;if(!o.trim())return{query:"",results:[],error:"缺少 query"};if(!e)return{query:o,results:[],error:"缺少 Tavily API Key"};const i=await fetch("https://api.tavily.com/search",{method:"POST",headers:{Authorization:`Bearer ${e}`,"Content-Type":"application/json"},body:JSON.stringify({query:o,max_results:s,search_depth:"basic",include_answer:!1,include_raw_content:!1}),signal:n.signal});if(!i.ok){const e=await i.text().catch(()=>"");return{query:o,results:[],error:`Tavily /search 错误: ${i.status} ${e}`.trim()}}const r=await i.json().catch(()=>null),a=[],l=r&&"object"==typeof r&&Array.isArray(r.results)?r.results:[];for(const e of l){const t="string"==typeof e?.url?e.url:"";if(!t)continue;const n="string"==typeof e?.title?e.title:"",o="string"==typeof e?.content?e.content:"";a.push({title:n,url:t,snippet:o})}return{query:o,results:a}}})),this.mcpConfigs?.length&&!this.mcpManager){this.mcpManager=new Ae,await this.mcpManager.connectAll(this.mcpConfigs);for(const e of this.mcpManager.getAllTools())this.tools.has(e.name)||this.tools.set(e.name,e)}}getModelFamilyConfig(e){return y(e)}getModelProvider(e){return _e(e)}getModelRouteInfo(e){return{...be(e),available:this.adapter.supportsModel(e),familyConfig:y(e)}}buildSystemPrompt(e){const t=e.model||ke,n=y(t);let o="你是一个专业的 AI 助手,具备自主执行复杂任务的能力。\n\n## 工作方式\n1. **分析任务**:理解用户需求,拆解为可执行的步骤\n2. **逐步执行**:按步骤依次调用工具,检查每步结果\n3. **自我验证**:工具执行后检查结果是否符合预期\n4. **自动纠正**:发现问题时尝试替代方案,不要停下来问用户\n5. **总结汇报**:所有步骤完成后,给出简洁的结果总结\n\n## 输出规范\n- 不使用表情符号(emoji),除非用户要求\n- 使用 Markdown 格式组织内容\n- 代码块使用正确的语言标识";return e.platformPrompt&&(o+="\n\n"+e.platformPrompt),e.skillContents?.length&&(o+="\n\n【用户指令】\n"+e.skillContents.join("\n\n")),e.enableWebSearch&&n&&!v(t)&&(o+=`\n\n【联网搜索】当用户问题需要实时信息/最新事实/可引用来源时,请先调用 ${Pe} 工具获取结果,然后基于返回的 title/url/snippet 作答,并在回答中给出来源链接。`),o}getDefaultThinkingMode(){return"disabled"}createToolContext(e,t){const n=this.config.cwd,o=this.toolExecutor;return{cwd:n,exec:async(s,i)=>{const r=i?.length?`${s} ${i.join(" ")}`:s,a=await o.executeCommand(r,n,e,{onStdout:t?.onStdout,onStderr:t?.onStderr});return{stdout:a.output??"",stderr:a.error??"",exitCode:a.success?0:1}},signal:e}}async executeTool(e,t,n,o){const s=this.tools.get(e);return s?await s.execute(t,this.createToolContext(n,o)):{error:`未知工具: ${e}`}}getToolDefinitions(e,t){const n=Array.from(this.tools.values());let o=void 0!==e?n.filter(t=>e.includes(t.name)):n;if(t?.length)for(const e of t)if(!o.some(t=>t.name===e)){const t=this.tools.get(e);t&&(o=[...o,t])}return o.map(e=>({name:e.name,description:e.description,parameters:e.parameters}))}getAllTools(){return Array.from(this.tools.values()).map(e=>({name:e.name,description:e.description}))}async*chat(e,t={},n){await this.asyncInit(),this.abortController=new AbortController;const o=this.abortController.signal,s=t.model||ke;if(!this.adapter.supportsModel(s)){return void(y(s)?yield Y(`模型 ${s} 缺少 API Key 配置`,{code:"MISSING_API_KEY"}):yield Y(`未知模型: ${s}`,{code:"MODEL_NOT_SUPPORTED"}))}const i=y(s),r="enabled"===(t.thinkingMode??this.getDefaultThinkingMode())?"enabled":"disabled",a=this.buildSystemPrompt(t),l="ask"===t.mode,c=!l&&!!t.enableWebSearch,u=c&&i&&!v(s)?[Pe]:void 0,p=l?[]:this.getToolDefinitions(t.enabledTools,u),d=t.userTools||[],m=[...p,...d.map(e=>({name:e.name,description:e.description,parameters:{...e.parameters,required:e.parameters.required||[]}}))],g=d.length>0?new Set(d.map(e=>e.name)):void 0,h=!l&&"enabled"===r&&(i?.supportsThinking??!1),f={systemPrompt:a,history:t.history||[],tools:m,signal:o,images:n,clientToolNames:g};try{yield*this.orchestrator.chat(this.adapter,e,f,{model:s,enableThinking:h,enableSearch:c,autoRunConfig:t.autoRunConfig})}finally{this.abortController=null}}abort(){this.abortController&&this.abortController.abort()}setCwd(e){this.config.cwd=e}getConfig(){return{...this.config}}getSupportedModels(){return A}getMcpConnections(){return this.mcpManager?.getConnectionInfos()??[]}async destroy(){this.mcpManager&&(await this.mcpManager.disconnectAll(),this.mcpManager=null)}};export{rt as AnthropicProtocol,Ve as ArkProtocol,P as CHAT_EVENT_TYPES,m as CLAUDE_FAMILY,We as ChatOrchestrator,c as DEEPSEEK_FAMILY,ke as DEFAULT_MODEL,l as DOUBAO_FAMILY,xe as DebugLogger,Be as DeepSeekProtocol,p as GEMINI_FAMILY,d as GPT_FAMILY,et as GeminiProtocol,dt as HybridAgent,A as MODELS,g as MODEL_FAMILIES,h as MODEL_REGISTRY,ot as OpenAIProtocol,u as QWEN_FAMILY,Ye as QwenProtocol,ut as UnifiedAdapter,ne as createAbort,lt as createAnthropicProtocol,Y as createApiError,Ge as createArkProtocol,Qe as createDeepSeekProtocol,he as createDefaultToolExecutor,Q as createDone,H as createError,tt as createGeminiProtocol,st as createOpenAIProtocol,je as createOrchestrator,te as createParseError,Ze as createQwenProtocol,Z as createRateLimitError,z as createSearchEnd,J as createSearchResult,j as createSearchStart,se as createStepEnd,oe as createStepStart,B as createTextDelta,U as createThinkingDelta,W as createThinkingEnd,D as createThinkingStart,ee as createTimeoutError,G as createToolCallOutput,L as createToolCallRequest,V as createToolCallResult,F as createToolCallStart,X as createToolError,pt as createUnifiedAdapter,I as getArg,we as getDefaultProvider,$ as getModelByModelId,f as getModelEntry,y as getModelFamily,k as getModelProtocol,x as getModelSearchStrategy,b as getModelsByFamily,w as getModelsByProtocol,_ as getVisibleModels,pe as isAbortEvent,ue as isErrorEvent,Te as isModelForProvider,me as isRetryableError,re as isSearchEvent,ce as isStatusEvent,de as isStepEvent,le as isTextEvent,ie as isThinkingEvent,R as isThrowableToolError,R as isToolError,ae as isToolEvent,v as modelSupportsNativeSearch,T as modelSupportsThinking,O as resolveTools,N as rethrowToolError,_e as routeModelToProvider,be as routeModelWithDetails,M as throwToolError,K as tool,q as tools};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@huyooo/ai-chat-core",
3
- "version": "0.2.41",
3
+ "version": "0.2.44",
4
4
  "description": "AI Chat Core - HybridAgent with Doubao + Gemini",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
package/src/agent.ts CHANGED
@@ -116,6 +116,7 @@ export class HybridAgent {
116
116
  tools: this.tools,
117
117
  onToolApprovalRequest: config.onToolApprovalRequest,
118
118
  getAutoRunConfig: config.getAutoRunConfig,
119
+ summarize: config.summarize,
119
120
  });
120
121
  }
121
122