@huyooo/ai-chat-core 0.2.22 → 0.2.24
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +1 -1
- package/package.json +1 -1
- package/src/constants.ts +3 -0
package/dist/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{GoogleGenAI as e}from"@google/genai";import{Client as t}from"@modelcontextprotocol/sdk/client/index.js";import{StdioClientTransport as n}from"@modelcontextprotocol/sdk/client/stdio.js";import{SSEClientTransport as o}from"@modelcontextprotocol/sdk/client/sse.js";import{appendFileSync as s}from"fs";import{createGateway as i,streamText as a,tool as r}from"ai";import{z as l}from"zod";var c={id:"doubao",displayName:"豆包",supportsVision:!0,supportsThinking:!0,thinkingFormat:"reasoning",supportsNativeSearch:!1,searchStrategy:"tavily",toolCallFormat:"responses",defaultMaxTokens:32768},u={id:"deepseek",displayName:"DeepSeek",supportsVision:!1,supportsThinking:!0,thinkingFormat:"reasoning",supportsNativeSearch:!1,searchStrategy:"tavily",toolCallFormat:"responses",defaultMaxTokens:32768},p={id:"qwen",displayName:"通义千问",supportsVision:!1,supportsThinking:!0,thinkingFormat:"thinking_enabled",supportsNativeSearch:!1,searchStrategy:"tavily",toolCallFormat:"openai",defaultMaxTokens:32768},d={id:"gemini",displayName:"Gemini",supportsVision:!0,supportsThinking:!0,thinkingFormat:"thought_signature",supportsNativeSearch:!1,searchStrategy:"tavily",toolCallFormat:"gemini",defaultMaxTokens:65536,requiresSpecialHandling:["thought_signature"]},m={id:"gpt",displayName:"GPT",supportsVision:!0,supportsThinking:!0,thinkingFormat:"reasoning",supportsNativeSearch:!1,searchStrategy:"tavily",toolCallFormat:"openai",defaultMaxTokens:128e3},g={id:"claude",displayName:"Claude",supportsVision:!0,supportsThinking:!0,thinkingFormat:"reasoning",supportsNativeSearch:!1,searchStrategy:"tavily",toolCallFormat:"openai",defaultMaxTokens:2e5},h={doubao:c,deepseek:u,qwen:p,gemini:d,gpt:m,claude:g},y=[{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 f(e){return y.find(t=>t.id===e||e.includes(t.id))}function k(e){const t=f(e);if(t)return h[t.family]}function _(e){const t=f(e);return t?.protocol}function b(){return y.filter(e=>e.visible)}function T(e){return y.filter(t=>t.family===e)}function w(e){return y.filter(t=>t.protocol===e)}function C(e){const t=k(e);return t?.supportsThinking??!1}function v(e){const t=k(e);return t?.supportsNativeSearch??!1}function S(e){const t=f(e);if(!t)return!1;if("boolean"==typeof t.supportsVision)return t.supportsVision;const n=k(e);return n?.supportsVision??!1}function A(e){const t=k(e);return t?.searchStrategy??"tavily"}function x(e){const t=k(e.id),n=S(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 R=b().map(e=>{const t=k(e.id),n=t?.supportsThinking??!1,o=S(e.id);return{modelId:e.id,displayName:e.displayName,supportsThinking:n,supportsVision:o,tooltip:{features:x(e),cost:e.pricing}}});function K(e){return R.find(t=>t.modelId===e)}function N(e){return{tools:[e]}}function $(e){return{tools:e}}async function M(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 I(e){return{type:"agent_status",data:{phase:e}}}var q=["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 O(){return{type:"thinking_start",data:{startedAt:Date.now()}}}function P(e){return{type:"thinking_delta",data:{content:e}}}function D(e){const t=Date.now();return{type:"thinking_end",data:{endedAt:t,duration:t-e}}}function U(e){return{type:"search_start",data:{query:e,startedAt:Date.now()}}}function E(e,t){const n=Date.now();return{type:"search_result",data:{results:e,endedAt:n,duration:n-t}}}function j(e,t,n){const o=Date.now();return{type:"search_end",data:{success:e,error:n,endedAt:o,duration:o-t}}}function J(e,t,n){return{type:"tool_call_start",data:{id:e,name:t,args:n,startedAt:Date.now()}}}function W(e,t,n,o,s,i,a,r){const l=Date.now();return{type:"tool_call_result",data:{id:e,name:t,result:n,success:o,error:i,endedAt:l,duration:l-s,sideEffects:a,resultType:r}}}function F(e,t,n,o){return{type:"tool_call_output",data:{id:e,name:t,stream:n,chunk:o,at:Date.now()}}}function V(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 G(e,t,n){return{type:"done",data:{text:e,usage:t,duration:n}}}function z(e){return{type:"error",data:e}}function L(e,t={}){return z({category:"api",message:e,...t})}function Q(e,t,n){return z({category:"rate_limit",message:e,code:"RATE_LIMIT",statusCode:429,retryable:!0,retryAfter:t,context:n})}function H(e,t,n){return z({category:"tool",message:e,code:"TOOL_ERROR",context:t,cause:n,retryable:!1})}function Z(e,t){return z({category:"timeout",message:e,code:"TIMEOUT",retryable:!0,context:t})}function X(e,t){return z({category:"parse",message:e,code:"PARSE_ERROR",cause:t,retryable:!1})}function Y(e){return{type:"abort",data:{reason:e,abortedAt:Date.now()}}}function ee(e,t){return{type:"step_start",data:{stepNumber:e,description:t,startedAt:Date.now()}}}function te(e,t){const n=Date.now();return{type:"step_end",data:{stepNumber:e,endedAt:n,duration:n-t}}}function ne(e){return e.type.startsWith("thinking_")}function oe(e){return e.type.startsWith("search_")}function se(e){return e.type.startsWith("tool_")}function ie(e){return"text_delta"===e.type}function ae(e){return"done"===e.type||"error"===e.type||"abort"===e.type}function re(e){return"error"===e.type}function le(e){return"abort"===e.type}function ce(e){return e.type.startsWith("step_")}function ue(e){return"error"===e.type&&!0===e.data.retryable}var pe=["rm -rf /","rm -rf ~","format","mkfs","dd if=","shutdown","reboot","sudo rm","sudo format"];function de(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 pe.some(e=>t.includes(e.toLowerCase()))}(t))return{success:!1,error:"该命令被安全策略阻止"};try{const{spawn:i}=await import("child_process");return new Promise(a=>{let r="",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"),a({success:!1,error:"命令执行超时(30秒)"}))},3e4),g=()=>{c||(d("SIGTERM"),clearTimeout(m),a({success:!1,error:"操作已取消"}))};o?.addEventListener("abort",g),p.stdout?.on("data",e=>{const t=e.toString();r+=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=r.trim(),n=l.trim();if(0===e)a({success:!0,output:t||n||"执行成功"});else if(t){a({success:!0,output:t+(n?`\n[警告: ${n}]`:"")})}else a(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||a({success:!1,error:e.message})})})}catch(e){return{success:!1,error:e instanceof Error?e.message:String(e)}}}}}var me="https://ark.cn-beijing.volces.com/api/v3",ge="https://openrouter.ai/api/v1",he="doubao-seed-1-6-250615";function ye(e){return fe(e).provider}function fe(e){const t=f(e);return t?{provider:t.protocol,registryEntry:t,familyConfig:k(e),isDefault:!1}:{provider:"ark",isDefault:!0}}function ke(){return"ark"}function _e(e,t){return ye(e)===t}var be=!1,Te=null,we=class e{prefix;constructor(e){this.prefix=e}static enable(e){be=e}static isEnabled(){return be}static setLogFile(e){Te=e}static module(t){return new e(`[${t}]`)}debug(...e){be&&this.writeToFile("debug",e)}info(...e){be&&this.writeToFile("info",e)}warn(...e){be&&this.writeToFile("warn",e)}error(...e){be&&this.writeToFile("error",e)}writeToFile(e,t){if(Te)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)}})});s(Te,n+"\n")}catch{}}},Ce=we.module("MCP"),ve=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&&Ce.error(`[${s}] 连接失败:`,o.reason)}}async connect(e){const{name:s}=e;this.connections.has(s)&&await this.disconnect(s),Ce.info(`[${s}] 正在连接...`);const i=new t({name:"ai-chat-mcp-client",version:"1.0.0"});let a;if("stdio"===e.transport){if(!e.command)throw new Error(`[${s}] stdio 模式必须指定 command`);a=new n({command:e.command,args:e.args,env:e.env,cwd:e.cwd})}else{if("sse"!==e.transport)throw new Error(`[${s}] 不支持的传输方式: ${e.transport}`);if(!e.url)throw new Error(`[${s}] sse 模式必须指定 url`);a=new o(new URL(e.url))}const r={config:e,client:i,transport:a,status:"connecting",tools:[]};this.connections.set(s,r);try{await i.connect(a),r.status="connected",Ce.info(`[${s}] 已连接`);const e=await this.discoverTools(r);r.tools=e,Ce.info(`[${s}] 发现 ${e.length} 个工具:`,e.map(e=>e.name))}catch(e){throw r.status="error",r.error=e instanceof Error?e.message:String(e),Ce.error(`[${s}] 连接失败:`,r.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 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(),Ce.info(`[${e}] 已断开`)}catch(t){Ce.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)))}},Se=we.module("ContextCompressor");function Ae(e,t){const n=e.reduce((e,t)=>e+(t.content?.length??0),0);if(n<8e4)return!1;Se.info(`Context 压缩触发: ${n} 字符, ${e.length} 条消息`);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-10);if(i-s<4)return!1;const a=function(e){const t=[];let n="";for(const o of e){if("assistant"===o.role&&o.toolCalls)for(const e of o.toolCalls)t.push(e.name);"assistant"===o.role&&o.content&&(n+=o.content.slice(0,200)+"\n")}return[`[上下文压缩] 以下是之前 ${e.length} 条消息的摘要:`,t.length>0?`- 执行了 ${t.length} 次工具调用: ${[...new Set(t)].join(", ")}`:"",n?`- AI 回复摘要: ${n.slice(0,500)}`:""].filter(Boolean).join("\n")}(e.slice(s,i)),r=[...e.slice(0,s),{role:"system",content:a},...e.slice(i)],l=r.reduce((e,t)=>e+(t.content?.length??0),0);return Se.info(`Context 压缩完成: ${e.length} → ${r.length} 条消息, ${n} → ${l} 字符`),e.length=0,e.push(...r),!0}var xe="web_search_ai";var Re=we.module("Orchestrator");function Ke(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 Ne=class{config;constructor(e){this.config={maxIterations:25,...e}}async*chat(e,t,n,o){const s=Date.now(),i=this.config.maxIterations??25,a=this.buildMessages(n,t);Ae(a)&&Re.info("初始历史已压缩");let r=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(;r<i;){if(n.signal.aborted)return void(yield Y("请求已取消"));r++,r>1&&Ae(a);const i=Date.now();Re.info(`======= 第 ${r} 轮开始 =======`),yield ee(r),yield I("thinking");let f="",k=0,_=!1,b=!1;const T={};let w=!1;const C=e=>{T[e]=(T[e]||0)+1};try{const v=[];let S=!1;const A=!0===o.enableThinking,x=!0===o.enableSearch;Re.debug("调用 adapter.streamOnce",{enableThinking:A,enableSearch:x});const R=e.streamOnce(a,n.tools,{model:o.model,enableThinking:A,enableSearch:x,signal:n.signal});for await(const e of R)switch(C(e.type),e.type){case"text":e.text&&(w||(w=!0,Re.debug("首次收到 text",{thinkingStarted:_,thinkingComplete:b}),yield I(null)),A&&_&&!b&&(Re.debug("text 触发 thinking_end"),b=!0,yield D(k)),l+=e.text,yield B(e.text));break;case"thinking":if(!A)break;if(e.thinking)if(b)Re.warn("⚠️ thinkingComplete=true 但收到 thinking",e.thinking.slice(0,30)),Re.warn("当前状态",{textStarted:w,chunkCounts:T});else if(w)Re.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(),Re.debug("发送 thinking_start"),yield I(null),yield O()),f+=t,yield P(t)}break;case"thinking_done":if(!A)break;Re.info("收到 thinking_done",{thinkingStarted:_,thinkingComplete:b}),_&&!b?(b=!0,Re.debug("发送 thinking_end"),yield D(k)):_||Re.warn("⚠️ 收到 thinking_done 但 thinkingStarted=false");break;case"tool_call":if(e.toolCall){if(!n.tools||0===n.tools.length){Re.warn("收到 tool_call 但当前未注入工具,已忽略",{toolName:e.toolCall.name});break}v.push(e.toolCall),S=!0}break;case"search_result":if(!x)break;e.searchResults&&(p||(p=!0,u=Date.now(),yield I(null),yield U(t)),c=Ke(e.searchResults),yield E(c,u));break;case"done":Re.info("收到 done",{finishReason:e.finishReason,usage:e.usage}),Re.info(`第 ${r} 轮 chunk 统计`,T),"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 Re.error("收到 error",e.error),void(yield L(e.error??"未知错误"))}if(Re.info(`第 ${r} 轮 for-await 循环结束`),Re.debug("状态",{thinkingStarted:_,thinkingComplete:b}),A&&_&&!b&&(Re.debug("补发 thinking_end"),b=!0,yield D(k)),S&&v.length>0){const e=v.map(e=>`${e.name}:${e.arguments}`).sort().join("|");if(e===m?g++:(g=0,m=e),g>=2){Re.warn("检测到重复工具调用,注入终止提示",{signature:e.slice(0,200),count:g+1});v.map(e=>e.name).join(", ");a.push({role:"assistant",content:l,toolCalls:v});for(const e of v)a.push({role:"tool",content:`[系统提示] 你已经连续 ${g+1} 次使用相同参数调用 ${e.name},任务应已完成。请直接回复用户执行结果,不要再调用工具。`,toolCallId:e.id,toolName:e.name});yield te(r,i),l="";continue}const h=n.clientToolNames||this.config.clientToolNames,y=h?v.filter(e=>h.has(e.name)):[];if(y.length>0){Re.info("检测到客户端工具调用,透传给客户端",y.map(e=>e.name));for(const e of y){let t;try{t=JSON.parse(e.arguments||"{}")}catch{t={}}yield V(e.id,e.name,t)}const e=Date.now()-s;return void(yield G(l,void 0,e))}yield I(null);const f={role:"assistant",content:l,toolCalls:v};a.push(f);for(const e of v){const s=Date.now();let i;try{i=JSON.parse(e.arguments||"{}")}catch{a.push({role:"tool",content:"参数解析错误",toolCallId:e.id});continue}if(e.name===xe){("string"==typeof i.query?i.query:"").trim()||(i.query=t)}const r=this.config.getAutoRunConfig?await this.config.getAutoRunConfig():o.autoRunConfig||this.config.autoRunConfig;if(Re.debug("检查工具批准",{toolName:e.name,autoRunConfigMode:r?.mode,hasCallback:!!this.config.onToolApprovalRequest}),"manual"===r?.mode&&this.config.onToolApprovalRequest){Re.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===xe&&x){if(!p){p=!0,u=Date.now();const e="string"==typeof i.query?i.query:t;yield U(e)}d=!0,yield j(!1,u,`用户跳过了 ${xe}`)}else yield W(e.id,e.name,n,!1,s);a.push({role:"tool",content:n,toolCallId:e.id,toolName:e.name});continue}}const l=e.name===xe;if(l){if(x&&!p){p=!0,u=Date.now();const e="string"==typeof i.query?i.query:t;yield U(e)}}else yield J(e.id,e.name,i);let m,g,h=!0;try{const t=[];let o=null;const s=()=>o?.(),a=e=>{t.push(e),s()};let r,l,c=!1;const u={toolCallId:e.id,toolName:e.name,onStdout:t=>{t&&a(F(e.id,e.name,"stdout",t))},onStderr:t=>{t&&a(F(e.id,e.name,"stderr",t))}};for(this.config.executeTool(e.name,i,n.signal,u).then(e=>{r=e,c=!0,s()}).catch(e=>{l=e,c=!0,s()});!c||t.length>0;){for(;t.length>0;){const e=t.shift();e&&(yield e)}if(c)break;await new Promise(e=>o=e),o=null}if(l)throw l;const p=r;"string"==typeof p?m=p:(m=p.result,g=p.sideEffects)}catch(e){h=!1;m=`错误: ${e instanceof Error?e.message:String(e)}`}const y=this.config.tools?.get(e.name),f=g??y?.sideEffects,k=h?y?.resultType:void 0;if(l){if(x){let e,t=[];try{const n=JSON.parse(m||"{}");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,h=!1)}catch{e=`${xe} 返回结果解析失败`,h=!1}t.length>0&&(c=Ke(t),yield E(c,u)),d=!0,yield j(h,u,e)}}else yield W(e.id,e.name,m,h,s,void 0,f,k);if(a.push({role:"tool",content:m,toolCallId:e.id,toolName:e.name}),n.signal.aborted)return void(yield Y("请求已取消"))}yield te(r,i),l="";continue}yield te(r,i);break}catch(e){return yield te(r,i),void(n.signal.aborted?yield Y("请求已取消"):yield L(e instanceof Error?e.message:String(e)))}}r>=i&&Re.warn(`达到最大迭代次数 ${i},强制结束工具调用循环`),p&&!d&&(yield j(!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 G(l,k,f)}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}};function $e(e){return new Ne(e)}var Me={400:"请求参数错误",401:"API 认证失败,请检查 API Key 配置",402:"账户余额不足,请充值后重试",403:"没有权限访问此模型",404:"请求的模型或接口不存在",429:"请求过于频繁,请稍后重试",500:"API 服务器内部错误,请稍后重试",502:"API 网关错误,请稍后重试",503:"API 服务暂时不可用,请稍后重试",504:"API 请求超时,请稍后重试"};function Ie(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=Me[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 qe=we.module("ArkProtocol"),Oe=class{name="ark";apiKey;apiUrl;constructor(e){this.apiKey=e.apiKey,this.apiUrl=e.apiUrl??me}async*stream(e,t,n){const o=this.buildRequestBody(e,t,n);qe.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 qe.error("ARK API 错误",{status:s.status,body:e.slice(0,500)}),void(yield{type:"error",error:Ie(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??32768,input:o},i=[],a=t.some(e=>e.name===xe);n.enableSearch&&!a&&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 a,r=!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(r)continue;if(!e.startsWith("data:"))continue;const t=e.slice(5).trim();if("[DONE]"===t){if(r=!0,o.size>0){for(const e of o.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(t),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||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(!r)if(o.size>0){for(const e of o.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 Pe(e){return new Oe(e)}var De=we.module("DeepSeekProtocol"),Ue=class{name="deepseek";apiKey;apiUrl;constructor(e){this.apiKey=e.apiKey,this.apiUrl=e.apiUrl??me}async*stream(e,t,n){const o=this.buildRequestBody(e,t,n),s=`${this.apiUrl}/responses`;De.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 De.error("DeepSeek API 错误",{status:i.status,body:e.slice(0,500)}),void(yield{type:"error",error:Ie(i.status,e,"DeepSeek")})}const a=i.body?.getReader();a?yield*this.parseSSE(a,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=[],a=t.some(e=>e.name===xe);n.enableSearch&&!a&&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 a=[];let r,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:r}}else yield{type:"done",finishReason:"stop",usage:r};return}try{const e=JSON.parse(n),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||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){a.some(e=>e.url===t.url)||(a.push({title:t.title||t.text||"",url:t.url,snippet:t.summary||t.snippet||""}),yield{type:"search_result",searchResults:[...a]})}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:r}}else yield{type:"done",finishReason:"stop",usage:r}}};function Ee(e){return new Ue(e)}var je=we.module("QwenProtocol"),Je=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`;je.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 je.error("Qwen API 错误",{status:i.status,body:e.slice(0,500)}),void(yield{type:"error",error:Ie(i.status,e,"Qwen")})}const a=i.body?.getReader();a?yield*this.parseSSE(a,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,a=!1,r=!1;for(;;){const{done:l,value:c}=await e.read();if(l)break;o+=n.decode(c,{stream:!0});const u=o.split("\n");o=u.pop()||"";for(const e of u){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 l=o.delta;if(!l)continue;if(t&&l.reasoning_content&&!r&&(yield{type:"thinking_delta",delta:l.reasoning_content}),l.content&&(!t||a||r||(r=!0,yield{type:"thinking_done"}),a=!0,yield{type:"text_delta",delta:l.content}),l.tool_calls?.length)for(const e of l.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||""}})}if(o.finish_reason){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 yield{type:"done",finishReason:o.finish_reason,usage:i};return}}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 yield{type:"done",finishReason:"stop",usage:i};return}}}const l=Array.from(s.values());if(l.length>0){for(const e of l)yield{type:"tool_call_done",toolCall:e};yield{type:"done",finishReason:"tool_calls",usage:i}}else yield{type:"done",finishReason:"stop",usage:i}}};function We(e){return new Je(e)}var Fe=we.module("GeminiProtocol"),Ve=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`;Fe.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 Fe.error("Gemini API 错误",{status:i.status,body:e.slice(0,500)}),void(yield{type:"error",error:Ie(i.status,e,"Gemini")})}const a=i.body?.getReader();a?yield*this.parseSSE(a):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 a=[];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);a.push({functionDeclarations:Array.from(n.values())})}else n.enableSearch&&a.push({googleSearch:{}});return a.length>0&&(i.tools=a),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:a,value:r}=await e.read();if(a)break;n+=t.decode(r,{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 a=n.groundingMetadata;if(a?.groundingChunks?.length){const e=[];for(const t of a.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 Be(e){return new Ve(e)}var Ge=we.module("OpenAIProtocol"),ze=class{name="openai";apiKey;apiUrl;constructor(e){this.apiKey=e.apiKey,this.apiUrl=e.apiUrl??ge}async*stream(e,t,n){const o=this.buildRequestBody(e,t,n),s=`${this.apiUrl}/responses`;Ge.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 Ge.error("OpenAI API 错误",{status:i.status,body:e.slice(0,500)}),void(yield{type:"error",error:Ie(i.status,e,"OpenAI")})}const a=i.body?.getReader();a?yield*this.parseSSE(a,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 a=[];let r,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:r}}else yield{type:"done",finishReason:"stop",usage:r};return}try{const e=JSON.parse(n);Ge.debug("SSE 事件",{type:e.type,event:JSON.stringify(e).slice(0,200)});const 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??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}),Ge.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{Ge.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}),Ge.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){a.some(e=>e.url===t.url)||(a.push({title:t.title||t.text||"",url:t.url,snippet:t.summary||t.snippet||""}),yield{type:"search_result",searchResults:[...a]})}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}),Ge.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(r=o,l=!0,s.size>0){for(const e of s.values())Ge.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){Ge.warn("SSE 解析错误",{line:e.slice(0,100),error:String(t)})}}}if(!l)if(Ge.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:r}}else yield{type:"done",finishReason:"stop",usage:r}}};function Le(e){return new ze(e)}var Qe=we.module("AnthropicProtocol"),He=class{name="anthropic";gateway;constructor(e){this.gateway=i({apiKey:e.apiKey})}async*stream(e,t,n){Qe.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}}}),Qe.debug("发送请求到 Vercel AI Gateway",{model:n.model,messagesCount:o.length,toolsCount:t.length,enableThinking:n.enableThinking});const i=a(s);yield*this.parseStream(i)}catch(e){const t=Ze(e);Qe.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?l.enum(o.enum):l.string();break;case"number":case"integer":s=l.number();break;case"boolean":s=l.boolean();break;case"array":s=l.array(l.string());break;default:s=l.unknown()}o.description&&(s=s.describe(o.description)),e.required?.includes(n)||(s=s.optional()),t[n]=s}return l.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?Ze(e):"模型请求失败";return Qe.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,a=n?{promptTokens:o,completionTokens:i,totalTokens:n.totalTokens??o+i}:void 0;return void(yield{type:"done",finishReason:e,usage:a})}}yield{type:"done",finishReason:"stop"}}};function Ze(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 Xe(e){return new He(e)}var Ye=we.module("UnifiedAdapter"),et=class{name="unified";get supportedModels(){return b().map(e=>e.id)}protocols=new Map;constructor(e){e.arkApiKey&&(this.protocols.set("ark",Pe({apiKey:e.arkApiKey,apiUrl:e.arkApiUrl})),this.protocols.set("deepseek",Ee({apiKey:e.arkApiKey,apiUrl:e.arkApiUrl}))),e.qwenApiKey&&this.protocols.set("qwen",We({apiKey:e.qwenApiKey,apiUrl:e.qwenApiUrl})),e.geminiApiKey&&this.protocols.set("gemini",Be({apiKey:e.geminiApiKey,apiUrl:e.geminiApiUrl})),e.openrouterApiKey&&this.protocols.set("openai",Le({apiKey:e.openrouterApiKey,apiUrl:e.openrouterApiUrl})),e.vercelApiKey&&this.protocols.set("anthropic",Xe({apiKey:e.vercelApiKey}))}supportsModel(e){const t=_(e);return!!t&&this.protocols.has(t)}getModelFamilyConfig(e){return k(e)}async*streamOnce(e,t,n){const{model:o,enableThinking:s=!1,enableSearch:i=!1,signal:a}=n,r=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(r,l,{model:o,enableThinking:s,enableSearch:i,signal:a})}async*stream(e,t,n){const{model:o,enableThinking:s=!1,enableSearch:i=!1,signal:a}=n,r=_(o),l=k(o);if(!r)return void(yield{type:"error",error:`未知模型: ${o}`});if(!l)return void(yield{type:"error",error:`模型 ${o} 缺少家族配置`});const c=this.protocols.get(r);if(!c)return void(yield{type:"error",error:`Protocol ${r} 未配置`});Ye.debug("开始流式调用",{model:o,protocol:r,family:l.id,enableThinking:s,enableSearch:i});const u=c.stream(e,t,{model:o,familyConfig:l,enableThinking:s,enableSearch:i,signal:a});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 tt(e){return new et(e)}var nt=class{config;adapter;orchestrator;geminiClient;toolExecutor;abortController=null;tools=new Map;toolConfig;mcpManager=null;mcpConfigs;constructor(t,n){this.config={arkApiKey:t.arkApiKey,arkApiUrl:t.arkApiUrl||me,qwenApiKey:t.qwenApiKey||"",qwenApiUrl:t.qwenApiUrl||"https://dashscope.aliyuncs.com/compatible-mode/v1",openrouterApiKey:t.openrouterApiKey||"",openrouterApiUrl:t.openrouterApiUrl||ge,vercelApiKey:t.vercelApiKey||"",tavilyApiKey:t.tavilyApiKey||"",geminiApiKey:t.geminiApiKey,cwd:t.cwd||process.cwd()},this.geminiClient=new e({apiKey:this.config.geminiApiKey}),this.toolExecutor=n||de(this.config.cwd),this.toolConfig=t.tools,this.mcpConfigs=t.mcpServers,this.tools=new Map,this.adapter=new et({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 Ne({executeTool:this.executeTool.bind(this),tools:this.tools,onToolApprovalRequest:t.onToolApprovalRequest,getAutoRunConfig:t.getAutoRunConfig})}async asyncInit(){if(this.toolConfig&&0===this.tools.size){const e=await M(this.toolConfig);for(const t of e)this.tools.set(t.name,t)}var e;if(this.config.tavilyApiKey&&!this.tools.has(xe)&&this.tools.set(xe,(e=this.config.tavilyApiKey,{name:xe,description:"联网搜索工具。输入 query(搜索关键词/问题),返回搜索结果列表(title/url/snippet)。用于获取实时信息与可引用来源。",parameters:{type:"object",properties:{query:{type:"string",description:"搜索关键词或问题(必填)"},max_results:{type:"number",description:"最大返回结果数(可选,默认 5)"}},required:["query"]},resultType:"search_results",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 JSON.stringify({query:"",results:[],error:"缺少 query"});if(!e)return JSON.stringify({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 JSON.stringify({query:o,results:[],error:`Tavily /search 错误: ${i.status} ${e}`.trim()})}const a=await i.json().catch(()=>null),r=[],l=a&&"object"==typeof a&&Array.isArray(a.results)?a.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:"";r.push({title:n,url:t,snippet:o})}return JSON.stringify({query:o,results:r})}})),this.mcpConfigs?.length&&!this.mcpManager){this.mcpManager=new ve,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 k(e)}getModelProvider(e){return ye(e)}getModelRouteInfo(e){return{...fe(e),available:this.adapter.supportsModel(e),familyConfig:k(e)}}buildSystemPrompt(e){const t=e.model||he,n=k(t);let o="你是一个专业的 AI 助手,具备自主执行复杂任务的能力。\n\n## 工作方式\n1. **分析任务**:理解用户需求,拆解为可执行的步骤\n2. **逐步执行**:按步骤依次调用工具,检查每步结果\n3. **自我验证**:工具执行后检查结果是否符合预期\n4. **自动纠正**:发现问题时尝试替代方案,不要停下来问用户\n5. **总结汇报**:所有步骤完成后,给出简洁的结果总结\n\n## 输出规范\n- 不使用表情符号(emoji),除非用户要求\n- 使用 Markdown 格式组织内容\n- 代码块使用正确的语言标识";return e.skillContents?.length&&(o+="\n\n【用户指令】\n"+e.skillContents.join("\n\n")),e.enableWebSearch&&n&&!v(t)&&(o+=`\n\n【联网搜索】当用户问题需要实时信息/最新事实/可引用来源时,请先调用 ${xe} 工具获取结果,然后基于返回的 title/url/snippet 作答,并在回答中给出来源链接。`),o}getDefaultThinkingMode(){return"disabled"}createToolContext(e,t){return{cwd:this.config.cwd,geminiClient:this.geminiClient,executeCommand:(n,o)=>this.toolExecutor.executeCommand(n,o||this.config.cwd,e,{onStdout:t?.onStdout,onStderr:t?.onStderr}),signal:e}}async executeTool(e,t,n,o){const s=this.tools.get(e);return s?await s.execute(t,this.createToolContext(n,o)):`未知工具: ${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||he;if(!this.adapter.supportsModel(s)){return void(k(s)?yield L(`模型 ${s} 缺少 API Key 配置`,{code:"MISSING_API_KEY"}):yield L(`未知模型: ${s}`,{code:"MODEL_NOT_SUPPORTED"}))}const i=k(s),a="enabled"===(t.thinkingMode??this.getDefaultThinkingMode())?"enabled":"disabled",r=this.buildSystemPrompt(t),l="ask"===t.mode,c=!l&&!!t.enableWebSearch,u=c&&i&&!v(s)?[xe]: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"===a&&(i?.supportsThinking??!1),y={systemPrompt:r,history:t.history||[],tools:m,signal:o,images:n,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 R}getMcpConnections(){return this.mcpManager?.getConnectionInfos()??[]}async destroy(){this.mcpManager&&(await this.mcpManager.disconnectAll(),this.mcpManager=null)}};export{He as AnthropicProtocol,Oe as ArkProtocol,q as CHAT_EVENT_TYPES,g as CLAUDE_FAMILY,Ne as ChatOrchestrator,u as DEEPSEEK_FAMILY,he as DEFAULT_MODEL,c as DOUBAO_FAMILY,we as DebugLogger,Ue as DeepSeekProtocol,d as GEMINI_FAMILY,m as GPT_FAMILY,Ve as GeminiProtocol,nt as HybridAgent,R as MODELS,h as MODEL_FAMILIES,y as MODEL_REGISTRY,ze as OpenAIProtocol,p as QWEN_FAMILY,Je as QwenProtocol,et as UnifiedAdapter,Y as createAbort,Xe as createAnthropicProtocol,L as createApiError,Pe as createArkProtocol,Ee as createDeepSeekProtocol,de as createDefaultToolExecutor,G as createDone,z as createError,Be as createGeminiProtocol,Le as createOpenAIProtocol,$e as createOrchestrator,X as createParseError,We as createQwenProtocol,Q as createRateLimitError,j as createSearchEnd,E as createSearchResult,U as createSearchStart,te as createStepEnd,ee as createStepStart,B as createTextDelta,P as createThinkingDelta,D as createThinkingEnd,O as createThinkingStart,Z as createTimeoutError,F as createToolCallOutput,V as createToolCallRequest,W as createToolCallResult,J as createToolCallStart,H as createToolError,tt as createUnifiedAdapter,ke as getDefaultProvider,K as getModelByModelId,f as getModelEntry,k as getModelFamily,_ as getModelProtocol,A as getModelSearchStrategy,T as getModelsByFamily,w as getModelsByProtocol,b as getVisibleModels,le as isAbortEvent,re as isErrorEvent,_e as isModelForProvider,ue as isRetryableError,oe as isSearchEvent,ae as isStatusEvent,ce as isStepEvent,ie as isTextEvent,ne as isThinkingEvent,se as isToolEvent,v as modelSupportsNativeSearch,C as modelSupportsThinking,M as resolveTools,ye as routeModelToProvider,fe as routeModelWithDetails,N as tool,$ as tools};
|
|
1
|
+
import{GoogleGenAI as e}from"@google/genai";import{Client as t}from"@modelcontextprotocol/sdk/client/index.js";import{StdioClientTransport as n}from"@modelcontextprotocol/sdk/client/stdio.js";import{SSEClientTransport as o}from"@modelcontextprotocol/sdk/client/sse.js";import{appendFileSync as s}from"fs";import{createGateway as i,streamText as a,tool as r}from"ai";import{z as l}from"zod";var c={id:"doubao",displayName:"豆包",supportsVision:!0,supportsThinking:!0,thinkingFormat:"reasoning",supportsNativeSearch:!1,searchStrategy:"tavily",toolCallFormat:"responses",defaultMaxTokens:32768},u={id:"deepseek",displayName:"DeepSeek",supportsVision:!1,supportsThinking:!0,thinkingFormat:"reasoning",supportsNativeSearch:!1,searchStrategy:"tavily",toolCallFormat:"responses",defaultMaxTokens:32768},p={id:"qwen",displayName:"通义千问",supportsVision:!1,supportsThinking:!0,thinkingFormat:"thinking_enabled",supportsNativeSearch:!1,searchStrategy:"tavily",toolCallFormat:"openai",defaultMaxTokens:32768},d={id:"gemini",displayName:"Gemini",supportsVision:!0,supportsThinking:!0,thinkingFormat:"thought_signature",supportsNativeSearch:!1,searchStrategy:"tavily",toolCallFormat:"gemini",defaultMaxTokens:65536,requiresSpecialHandling:["thought_signature"]},m={id:"gpt",displayName:"GPT",supportsVision:!0,supportsThinking:!0,thinkingFormat:"reasoning",supportsNativeSearch:!1,searchStrategy:"tavily",toolCallFormat:"openai",defaultMaxTokens:128e3},g={id:"claude",displayName:"Claude",supportsVision:!0,supportsThinking:!0,thinkingFormat:"reasoning",supportsNativeSearch:!1,searchStrategy:"tavily",toolCallFormat:"openai",defaultMaxTokens:2e5},h={doubao:c,deepseek:u,qwen:p,gemini:d,gpt:m,claude:g},y=[{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 f(e){return y.find(t=>t.id===e||e.includes(t.id))}function k(e){const t=f(e);if(t)return h[t.family]}function _(e){const t=f(e);return t?.protocol}function b(){return y.filter(e=>e.visible)}function T(e){return y.filter(t=>t.family===e)}function w(e){return y.filter(t=>t.protocol===e)}function C(e){const t=k(e);return t?.supportsThinking??!1}function v(e){const t=k(e);return t?.supportsNativeSearch??!1}function S(e){const t=f(e);if(!t)return!1;if("boolean"==typeof t.supportsVision)return t.supportsVision;const n=k(e);return n?.supportsVision??!1}function A(e){const t=k(e);return t?.searchStrategy??"tavily"}function x(e){const t=k(e.id),n=S(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 R=b().map(e=>{const t=k(e.id),n=t?.supportsThinking??!1,o=S(e.id);return{modelId:e.id,displayName:e.displayName,supportsThinking:n,supportsVision:o,tooltip:{features:x(e),cost:e.pricing}}});function K(e){return R.find(t=>t.modelId===e)}function N(e){return{tools:[e]}}function $(e){return{tools:e}}async function M(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 I(e){return{type:"agent_status",data:{phase:e}}}var q=["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 O(){return{type:"thinking_start",data:{startedAt:Date.now()}}}function P(e){return{type:"thinking_delta",data:{content:e}}}function D(e){const t=Date.now();return{type:"thinking_end",data:{endedAt:t,duration:t-e}}}function U(e){return{type:"search_start",data:{query:e,startedAt:Date.now()}}}function E(e,t){const n=Date.now();return{type:"search_result",data:{results:e,endedAt:n,duration:n-t}}}function j(e,t,n){const o=Date.now();return{type:"search_end",data:{success:e,error:n,endedAt:o,duration:o-t}}}function J(e,t,n){return{type:"tool_call_start",data:{id:e,name:t,args:n,startedAt:Date.now()}}}function W(e,t,n,o,s,i,a,r){const l=Date.now();return{type:"tool_call_result",data:{id:e,name:t,result:n,success:o,error:i,endedAt:l,duration:l-s,sideEffects:a,resultType:r}}}function F(e,t,n,o){return{type:"tool_call_output",data:{id:e,name:t,stream:n,chunk:o,at:Date.now()}}}function V(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 G(e,t,n){return{type:"done",data:{text:e,usage:t,duration:n}}}function z(e){return{type:"error",data:e}}function L(e,t={}){return z({category:"api",message:e,...t})}function Q(e,t,n){return z({category:"rate_limit",message:e,code:"RATE_LIMIT",statusCode:429,retryable:!0,retryAfter:t,context:n})}function H(e,t,n){return z({category:"tool",message:e,code:"TOOL_ERROR",context:t,cause:n,retryable:!1})}function Z(e,t){return z({category:"timeout",message:e,code:"TIMEOUT",retryable:!0,context:t})}function X(e,t){return z({category:"parse",message:e,code:"PARSE_ERROR",cause:t,retryable:!1})}function Y(e){return{type:"abort",data:{reason:e,abortedAt:Date.now()}}}function ee(e,t){return{type:"step_start",data:{stepNumber:e,description:t,startedAt:Date.now()}}}function te(e,t){const n=Date.now();return{type:"step_end",data:{stepNumber:e,endedAt:n,duration:n-t}}}function ne(e){return e.type.startsWith("thinking_")}function oe(e){return e.type.startsWith("search_")}function se(e){return e.type.startsWith("tool_")}function ie(e){return"text_delta"===e.type}function ae(e){return"done"===e.type||"error"===e.type||"abort"===e.type}function re(e){return"error"===e.type}function le(e){return"abort"===e.type}function ce(e){return e.type.startsWith("step_")}function ue(e){return"error"===e.type&&!0===e.data.retryable}var pe=["rm -rf /","rm -rf ~","format","mkfs","dd if=","shutdown","reboot","sudo rm","sudo format"];function de(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 pe.some(e=>t.includes(e.toLowerCase()))}(t))return{success:!1,error:"该命令被安全策略阻止"};try{const{spawn:i}=await import("child_process");return new Promise(a=>{let r="",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"),a({success:!1,error:"命令执行超时(30秒)"}))},3e4),g=()=>{c||(d("SIGTERM"),clearTimeout(m),a({success:!1,error:"操作已取消"}))};o?.addEventListener("abort",g),p.stdout?.on("data",e=>{const t=e.toString();r+=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=r.trim(),n=l.trim();if(0===e)a({success:!0,output:t||n||"执行成功"});else if(t){a({success:!0,output:t+(n?`\n[警告: ${n}]`:"")})}else a(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||a({success:!1,error:e.message})})})}catch(e){return{success:!1,error:e instanceof Error?e.message:String(e)}}}}}var me="https://ark.cn-beijing.volces.com/api/v3",ge="https://openrouter.ai/api/v1",he="doubao-seed-1-6-250615";function ye(e){return fe(e).provider}function fe(e){const t=f(e);return t?{provider:t.protocol,registryEntry:t,familyConfig:k(e),isDefault:!1}:{provider:"ark",isDefault:!0}}function ke(){return"ark"}function _e(e,t){return ye(e)===t}var be=!1,Te=null,we=class e{prefix;constructor(e){this.prefix=e}static enable(e){be=e}static isEnabled(){return be}static setLogFile(e){Te=e}static module(t){return new e(`[${t}]`)}debug(...e){be&&this.writeToFile("debug",e)}info(...e){be&&this.writeToFile("info",e)}warn(...e){be&&this.writeToFile("warn",e)}error(...e){be&&this.writeToFile("error",e)}writeToFile(e,t){if(Te)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)}})});s(Te,n+"\n")}catch{}}},Ce=we.module("MCP"),ve=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&&Ce.error(`[${s}] 连接失败:`,o.reason)}}async connect(e){const{name:s}=e;this.connections.has(s)&&await this.disconnect(s),Ce.info(`[${s}] 正在连接...`);const i=new t({name:"ai-chat-mcp-client",version:"1.0.0"});let a;if("stdio"===e.transport){if(!e.command)throw new Error(`[${s}] stdio 模式必须指定 command`);a=new n({command:e.command,args:e.args,env:e.env,cwd:e.cwd})}else{if("sse"!==e.transport)throw new Error(`[${s}] 不支持的传输方式: ${e.transport}`);if(!e.url)throw new Error(`[${s}] sse 模式必须指定 url`);a=new o(new URL(e.url))}const r={config:e,client:i,transport:a,status:"connecting",tools:[]};this.connections.set(s,r);try{await i.connect(a),r.status="connected",Ce.info(`[${s}] 已连接`);const e=await this.discoverTools(r);r.tools=e,Ce.info(`[${s}] 发现 ${e.length} 个工具:`,e.map(e=>e.name))}catch(e){throw r.status="error",r.error=e instanceof Error?e.message:String(e),Ce.error(`[${s}] 连接失败:`,r.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 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(),Ce.info(`[${e}] 已断开`)}catch(t){Ce.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)))}},Se=we.module("ContextCompressor");function Ae(e,t){const n=e.reduce((e,t)=>e+(t.content?.length??0),0);if(n<8e4)return!1;Se.info(`Context 压缩触发: ${n} 字符, ${e.length} 条消息`);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-10);if(i-s<4)return!1;const a=function(e){const t=[];let n="";for(const o of e){if("assistant"===o.role&&o.toolCalls)for(const e of o.toolCalls)t.push(e.name);"assistant"===o.role&&o.content&&(n+=o.content.slice(0,200)+"\n")}return[`[上下文压缩] 以下是之前 ${e.length} 条消息的摘要:`,t.length>0?`- 执行了 ${t.length} 次工具调用: ${[...new Set(t)].join(", ")}`:"",n?`- AI 回复摘要: ${n.slice(0,500)}`:""].filter(Boolean).join("\n")}(e.slice(s,i)),r=[...e.slice(0,s),{role:"system",content:a},...e.slice(i)],l=r.reduce((e,t)=>e+(t.content?.length??0),0);return Se.info(`Context 压缩完成: ${e.length} → ${r.length} 条消息, ${n} → ${l} 字符`),e.length=0,e.push(...r),!0}var xe="web_search_ai";var Re=we.module("Orchestrator");function Ke(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 Ne=class{config;constructor(e){this.config={maxIterations:25,...e}}async*chat(e,t,n,o){const s=Date.now(),i=this.config.maxIterations??25,a=this.buildMessages(n,t);Ae(a)&&Re.info("初始历史已压缩");let r=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(;r<i;){if(n.signal.aborted)return void(yield Y("请求已取消"));r++,r>1&&Ae(a);const i=Date.now();Re.info(`======= 第 ${r} 轮开始 =======`),yield ee(r),yield I("thinking");let f="",k=0,_=!1,b=!1;const T={};let w=!1;const C=e=>{T[e]=(T[e]||0)+1};try{const v=[];let S=!1;const A=!0===o.enableThinking,x=!0===o.enableSearch;Re.debug("调用 adapter.streamOnce",{enableThinking:A,enableSearch:x});const R=e.streamOnce(a,n.tools,{model:o.model,enableThinking:A,enableSearch:x,signal:n.signal});for await(const e of R)switch(C(e.type),e.type){case"text":e.text&&(w||(w=!0,Re.debug("首次收到 text",{thinkingStarted:_,thinkingComplete:b}),yield I(null)),A&&_&&!b&&(Re.debug("text 触发 thinking_end"),b=!0,yield D(k)),l+=e.text,yield B(e.text));break;case"thinking":if(!A)break;if(e.thinking)if(b)Re.warn("⚠️ thinkingComplete=true 但收到 thinking",e.thinking.slice(0,30)),Re.warn("当前状态",{textStarted:w,chunkCounts:T});else if(w)Re.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(),Re.debug("发送 thinking_start"),yield I(null),yield O()),f+=t,yield P(t)}break;case"thinking_done":if(!A)break;Re.info("收到 thinking_done",{thinkingStarted:_,thinkingComplete:b}),_&&!b?(b=!0,Re.debug("发送 thinking_end"),yield D(k)):_||Re.warn("⚠️ 收到 thinking_done 但 thinkingStarted=false");break;case"tool_call":if(e.toolCall){if(!n.tools||0===n.tools.length){Re.warn("收到 tool_call 但当前未注入工具,已忽略",{toolName:e.toolCall.name});break}v.push(e.toolCall),S=!0}break;case"search_result":if(!x)break;e.searchResults&&(p||(p=!0,u=Date.now(),yield I(null),yield U(t)),c=Ke(e.searchResults),yield E(c,u));break;case"done":Re.info("收到 done",{finishReason:e.finishReason,usage:e.usage}),Re.info(`第 ${r} 轮 chunk 统计`,T),"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 Re.error("收到 error",e.error),void(yield L(e.error??"未知错误"))}if(Re.info(`第 ${r} 轮 for-await 循环结束`),Re.debug("状态",{thinkingStarted:_,thinkingComplete:b}),A&&_&&!b&&(Re.debug("补发 thinking_end"),b=!0,yield D(k)),S&&v.length>0){const e=v.map(e=>`${e.name}:${e.arguments}`).sort().join("|");if(e===m?g++:(g=0,m=e),g>=2){Re.warn("检测到重复工具调用,注入终止提示",{signature:e.slice(0,200),count:g+1});v.map(e=>e.name).join(", ");a.push({role:"assistant",content:l,toolCalls:v});for(const e of v)a.push({role:"tool",content:`[系统提示] 你已经连续 ${g+1} 次使用相同参数调用 ${e.name},任务应已完成。请直接回复用户执行结果,不要再调用工具。`,toolCallId:e.id,toolName:e.name});yield te(r,i),l="";continue}const h=n.clientToolNames||this.config.clientToolNames,y=h?v.filter(e=>h.has(e.name)):[];if(y.length>0){Re.info("检测到客户端工具调用,透传给客户端",y.map(e=>e.name));for(const e of y){let t;try{t=JSON.parse(e.arguments||"{}")}catch{t={}}yield V(e.id,e.name,t)}const e=Date.now()-s;return void(yield G(l,void 0,e))}yield I(null);const f={role:"assistant",content:l,toolCalls:v};a.push(f);for(const e of v){const s=Date.now();let i;try{i=JSON.parse(e.arguments||"{}")}catch{a.push({role:"tool",content:"参数解析错误",toolCallId:e.id});continue}if(e.name===xe){("string"==typeof i.query?i.query:"").trim()||(i.query=t)}const r=this.config.getAutoRunConfig?await this.config.getAutoRunConfig():o.autoRunConfig||this.config.autoRunConfig;if(Re.debug("检查工具批准",{toolName:e.name,autoRunConfigMode:r?.mode,hasCallback:!!this.config.onToolApprovalRequest}),"manual"===r?.mode&&this.config.onToolApprovalRequest){Re.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===xe&&x){if(!p){p=!0,u=Date.now();const e="string"==typeof i.query?i.query:t;yield U(e)}d=!0,yield j(!1,u,`用户跳过了 ${xe}`)}else yield W(e.id,e.name,n,!1,s);a.push({role:"tool",content:n,toolCallId:e.id,toolName:e.name});continue}}const l=e.name===xe;if(l){if(x&&!p){p=!0,u=Date.now();const e="string"==typeof i.query?i.query:t;yield U(e)}}else yield J(e.id,e.name,i);let m,g,h=!0;try{const t=[];let o=null;const s=()=>o?.(),a=e=>{t.push(e),s()};let r,l,c=!1;const u={toolCallId:e.id,toolName:e.name,onStdout:t=>{t&&a(F(e.id,e.name,"stdout",t))},onStderr:t=>{t&&a(F(e.id,e.name,"stderr",t))}};for(this.config.executeTool(e.name,i,n.signal,u).then(e=>{r=e,c=!0,s()}).catch(e=>{l=e,c=!0,s()});!c||t.length>0;){for(;t.length>0;){const e=t.shift();e&&(yield e)}if(c)break;await new Promise(e=>o=e),o=null}if(l)throw l;const p=r;"string"==typeof p?m=p:(m=p.result,g=p.sideEffects)}catch(e){h=!1;m=`错误: ${e instanceof Error?e.message:String(e)}`}const y=this.config.tools?.get(e.name),f=g??y?.sideEffects,k=h?y?.resultType:void 0;if(l){if(x){let e,t=[];try{const n=JSON.parse(m||"{}");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,h=!1)}catch{e=`${xe} 返回结果解析失败`,h=!1}t.length>0&&(c=Ke(t),yield E(c,u)),d=!0,yield j(h,u,e)}}else yield W(e.id,e.name,m,h,s,void 0,f,k);if(a.push({role:"tool",content:m,toolCallId:e.id,toolName:e.name}),n.signal.aborted)return void(yield Y("请求已取消"))}yield te(r,i),l="";continue}yield te(r,i);break}catch(e){return yield te(r,i),void(n.signal.aborted?yield Y("请求已取消"):yield L(e instanceof Error?e.message:String(e)))}}r>=i&&Re.warn(`达到最大迭代次数 ${i},强制结束工具调用循环`),p&&!d&&(yield j(!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 G(l,k,f)}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}};function $e(e){return new Ne(e)}var Me={400:"请求参数错误",401:"API 认证失败,请检查 API Key 配置",402:"账户余额不足,请充值后重试",403:"没有权限访问此模型",404:"请求的模型或接口不存在",429:"请求过于频繁,请稍后重试",500:"API 服务器内部错误,请稍后重试",502:"API 网关错误,请稍后重试",503:"API 服务暂时不可用,请稍后重试",504:"API 请求超时,请稍后重试"};function Ie(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=Me[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 qe=we.module("ArkProtocol"),Oe=class{name="ark";apiKey;apiUrl;constructor(e){this.apiKey=e.apiKey,this.apiUrl=e.apiUrl??me}async*stream(e,t,n){const o=this.buildRequestBody(e,t,n);qe.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 qe.error("ARK API 错误",{status:s.status,body:e.slice(0,500)}),void(yield{type:"error",error:Ie(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??32768,input:o},i=[],a=t.some(e=>e.name===xe);n.enableSearch&&!a&&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 a,r=!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(r)continue;if(!e.startsWith("data:"))continue;const t=e.slice(5).trim();if("[DONE]"===t){if(r=!0,o.size>0){for(const e of o.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(t),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||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(!r)if(o.size>0){for(const e of o.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 Pe(e){return new Oe(e)}var De=we.module("DeepSeekProtocol"),Ue=class{name="deepseek";apiKey;apiUrl;constructor(e){this.apiKey=e.apiKey,this.apiUrl=e.apiUrl??me}async*stream(e,t,n){const o=this.buildRequestBody(e,t,n),s=`${this.apiUrl}/responses`;De.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 De.error("DeepSeek API 错误",{status:i.status,body:e.slice(0,500)}),void(yield{type:"error",error:Ie(i.status,e,"DeepSeek")})}const a=i.body?.getReader();a?yield*this.parseSSE(a,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=[],a=t.some(e=>e.name===xe);n.enableSearch&&!a&&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 a=[];let r,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:r}}else yield{type:"done",finishReason:"stop",usage:r};return}try{const e=JSON.parse(n),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||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){a.some(e=>e.url===t.url)||(a.push({title:t.title||t.text||"",url:t.url,snippet:t.summary||t.snippet||""}),yield{type:"search_result",searchResults:[...a]})}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:r}}else yield{type:"done",finishReason:"stop",usage:r}}};function Ee(e){return new Ue(e)}var je=we.module("QwenProtocol"),Je=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`;je.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 je.error("Qwen API 错误",{status:i.status,body:e.slice(0,500)}),void(yield{type:"error",error:Ie(i.status,e,"Qwen")})}const a=i.body?.getReader();a?yield*this.parseSSE(a,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,a=!1,r=!1;for(;;){const{done:l,value:c}=await e.read();if(l)break;o+=n.decode(c,{stream:!0});const u=o.split("\n");o=u.pop()||"";for(const e of u){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 l=o.delta;if(!l)continue;if(t&&l.reasoning_content&&!r&&(yield{type:"thinking_delta",delta:l.reasoning_content}),l.content&&(!t||a||r||(r=!0,yield{type:"thinking_done"}),a=!0,yield{type:"text_delta",delta:l.content}),l.tool_calls?.length)for(const e of l.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||""}})}if(o.finish_reason){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 yield{type:"done",finishReason:o.finish_reason,usage:i};return}}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 yield{type:"done",finishReason:"stop",usage:i};return}}}const l=Array.from(s.values());if(l.length>0){for(const e of l)yield{type:"tool_call_done",toolCall:e};yield{type:"done",finishReason:"tool_calls",usage:i}}else yield{type:"done",finishReason:"stop",usage:i}}};function We(e){return new Je(e)}var Fe=we.module("GeminiProtocol"),Ve=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`;Fe.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 Fe.error("Gemini API 错误",{status:i.status,body:e.slice(0,500)}),void(yield{type:"error",error:Ie(i.status,e,"Gemini")})}const a=i.body?.getReader();a?yield*this.parseSSE(a):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 a=[];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);a.push({functionDeclarations:Array.from(n.values())})}else n.enableSearch&&a.push({googleSearch:{}});return a.length>0&&(i.tools=a),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:a,value:r}=await e.read();if(a)break;n+=t.decode(r,{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 a=n.groundingMetadata;if(a?.groundingChunks?.length){const e=[];for(const t of a.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 Be(e){return new Ve(e)}var Ge=we.module("OpenAIProtocol"),ze=class{name="openai";apiKey;apiUrl;constructor(e){this.apiKey=e.apiKey,this.apiUrl=e.apiUrl??ge}async*stream(e,t,n){const o=this.buildRequestBody(e,t,n),s=`${this.apiUrl}/responses`;Ge.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 Ge.error("OpenAI API 错误",{status:i.status,body:e.slice(0,500)}),void(yield{type:"error",error:Ie(i.status,e,"OpenAI")})}const a=i.body?.getReader();a?yield*this.parseSSE(a,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 a=[];let r,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:r}}else yield{type:"done",finishReason:"stop",usage:r};return}try{const e=JSON.parse(n);Ge.debug("SSE 事件",{type:e.type,event:JSON.stringify(e).slice(0,200)});const 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??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}),Ge.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{Ge.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}),Ge.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){a.some(e=>e.url===t.url)||(a.push({title:t.title||t.text||"",url:t.url,snippet:t.summary||t.snippet||""}),yield{type:"search_result",searchResults:[...a]})}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}),Ge.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(r=o,l=!0,s.size>0){for(const e of s.values())Ge.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){Ge.warn("SSE 解析错误",{line:e.slice(0,100),error:String(t)})}}}if(!l)if(Ge.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:r}}else yield{type:"done",finishReason:"stop",usage:r}}};function Le(e){return new ze(e)}var Qe=we.module("AnthropicProtocol"),He=class{name="anthropic";gateway;constructor(e){this.gateway=i({apiKey:e.apiKey})}async*stream(e,t,n){Qe.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}}}),Qe.debug("发送请求到 Vercel AI Gateway",{model:n.model,messagesCount:o.length,toolsCount:t.length,enableThinking:n.enableThinking});const i=a(s);yield*this.parseStream(i)}catch(e){const t=Ze(e);Qe.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?l.enum(o.enum):l.string();break;case"number":case"integer":s=l.number();break;case"boolean":s=l.boolean();break;case"array":s=l.array(l.string());break;default:s=l.unknown()}o.description&&(s=s.describe(o.description)),e.required?.includes(n)||(s=s.optional()),t[n]=s}return l.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?Ze(e):"模型请求失败";return Qe.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,a=n?{promptTokens:o,completionTokens:i,totalTokens:n.totalTokens??o+i}:void 0;return void(yield{type:"done",finishReason:e,usage:a})}}yield{type:"done",finishReason:"stop"}}};function Ze(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 Xe(e){return new He(e)}var Ye=we.module("UnifiedAdapter"),et=class{name="unified";get supportedModels(){return b().map(e=>e.id)}protocols=new Map;constructor(e){e.arkApiKey&&(this.protocols.set("ark",Pe({apiKey:e.arkApiKey,apiUrl:e.arkApiUrl})),this.protocols.set("deepseek",Ee({apiKey:e.arkApiKey,apiUrl:e.arkApiUrl}))),e.qwenApiKey&&this.protocols.set("qwen",We({apiKey:e.qwenApiKey,apiUrl:e.qwenApiUrl})),e.geminiApiKey&&this.protocols.set("gemini",Be({apiKey:e.geminiApiKey,apiUrl:e.geminiApiUrl})),e.openrouterApiKey&&this.protocols.set("openai",Le({apiKey:e.openrouterApiKey,apiUrl:e.openrouterApiUrl})),e.vercelApiKey&&this.protocols.set("anthropic",Xe({apiKey:e.vercelApiKey}))}supportsModel(e){const t=_(e);return!!t&&this.protocols.has(t)}getModelFamilyConfig(e){return k(e)}async*streamOnce(e,t,n){const{model:o,enableThinking:s=!1,enableSearch:i=!1,signal:a}=n,r=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(r,l,{model:o,enableThinking:s,enableSearch:i,signal:a})}async*stream(e,t,n){const{model:o,enableThinking:s=!1,enableSearch:i=!1,signal:a}=n,r=_(o),l=k(o);if(!r)return void(yield{type:"error",error:`未知模型: ${o}`});if(!l)return void(yield{type:"error",error:`模型 ${o} 缺少家族配置`});const c=this.protocols.get(r);if(!c)return void(yield{type:"error",error:`Protocol ${r} 未配置`});Ye.debug("开始流式调用",{model:o,protocol:r,family:l.id,enableThinking:s,enableSearch:i});const u=c.stream(e,t,{model:o,familyConfig:l,enableThinking:s,enableSearch:i,signal:a});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 tt(e){return new et(e)}var nt=class{config;adapter;orchestrator;geminiClient;toolExecutor;abortController=null;tools=new Map;toolConfig;mcpManager=null;mcpConfigs;constructor(t,n){this.config={arkApiKey:t.arkApiKey,arkApiUrl:t.arkApiUrl||me,qwenApiKey:t.qwenApiKey||"",qwenApiUrl:t.qwenApiUrl||"https://dashscope.aliyuncs.com/compatible-mode/v1",openrouterApiKey:t.openrouterApiKey||"",openrouterApiUrl:t.openrouterApiUrl||ge,vercelApiKey:t.vercelApiKey||"",tavilyApiKey:t.tavilyApiKey||"",geminiApiKey:t.geminiApiKey,cwd:t.cwd||process.cwd()},this.geminiClient=new e({apiKey:this.config.geminiApiKey}),this.toolExecutor=n||de(this.config.cwd),this.toolConfig=t.tools,this.mcpConfigs=t.mcpServers,this.tools=new Map,this.adapter=new et({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 Ne({executeTool:this.executeTool.bind(this),tools:this.tools,onToolApprovalRequest:t.onToolApprovalRequest,getAutoRunConfig:t.getAutoRunConfig})}async asyncInit(){if(this.toolConfig&&0===this.tools.size){const e=await M(this.toolConfig);for(const t of e)this.tools.set(t.name,t)}var e;if(this.config.tavilyApiKey&&!this.tools.has(xe)&&this.tools.set(xe,(e=this.config.tavilyApiKey,{name:xe,description:"联网搜索工具。输入 query(搜索关键词/问题),返回搜索结果列表(title/url/snippet)。用于获取实时信息与可引用来源。",parameters:{type:"object",properties:{query:{type:"string",description:"搜索关键词或问题(必填)"},max_results:{type:"number",description:"最大返回结果数(可选,默认 5)"}},required:["query"]},resultType:"search_results",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 JSON.stringify({query:"",results:[],error:"缺少 query"});if(!e)return JSON.stringify({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 JSON.stringify({query:o,results:[],error:`Tavily /search 错误: ${i.status} ${e}`.trim()})}const a=await i.json().catch(()=>null),r=[],l=a&&"object"==typeof a&&Array.isArray(a.results)?a.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:"";r.push({title:n,url:t,snippet:o})}return JSON.stringify({query:o,results:r})}})),this.mcpConfigs?.length&&!this.mcpManager){this.mcpManager=new ve,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 k(e)}getModelProvider(e){return ye(e)}getModelRouteInfo(e){return{...fe(e),available:this.adapter.supportsModel(e),familyConfig:k(e)}}buildSystemPrompt(e){const t=e.model||he,n=k(t);let o="你是一个专业的 AI 助手,具备自主执行复杂任务的能力。\n\n## 工作方式\n1. **分析任务**:理解用户需求,拆解为可执行的步骤\n2. **逐步执行**:按步骤依次调用工具,检查每步结果\n3. **自我验证**:工具执行后检查结果是否符合预期\n4. **自动纠正**:发现问题时尝试替代方案,不要停下来问用户\n5. **总结汇报**:所有步骤完成后,给出简洁的结果总结\n\n## 技能库\n你可以通过 search_skills 工具搜索专业技能指令库。当用户请求涉及特定领域(如文档摘要、翻译、代码审查、数据分析、写作润色等)时,建议先搜索是否有专门的技能指令可参考,用 load_skill 加载后按技能指令执行,以获得更高质量的结果。\n\n## 输出规范\n- 不使用表情符号(emoji),除非用户要求\n- 使用 Markdown 格式组织内容\n- 代码块使用正确的语言标识";return e.skillContents?.length&&(o+="\n\n【用户指令】\n"+e.skillContents.join("\n\n")),e.enableWebSearch&&n&&!v(t)&&(o+=`\n\n【联网搜索】当用户问题需要实时信息/最新事实/可引用来源时,请先调用 ${xe} 工具获取结果,然后基于返回的 title/url/snippet 作答,并在回答中给出来源链接。`),o}getDefaultThinkingMode(){return"disabled"}createToolContext(e,t){return{cwd:this.config.cwd,geminiClient:this.geminiClient,executeCommand:(n,o)=>this.toolExecutor.executeCommand(n,o||this.config.cwd,e,{onStdout:t?.onStdout,onStderr:t?.onStderr}),signal:e}}async executeTool(e,t,n,o){const s=this.tools.get(e);return s?await s.execute(t,this.createToolContext(n,o)):`未知工具: ${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||he;if(!this.adapter.supportsModel(s)){return void(k(s)?yield L(`模型 ${s} 缺少 API Key 配置`,{code:"MISSING_API_KEY"}):yield L(`未知模型: ${s}`,{code:"MODEL_NOT_SUPPORTED"}))}const i=k(s),a="enabled"===(t.thinkingMode??this.getDefaultThinkingMode())?"enabled":"disabled",r=this.buildSystemPrompt(t),l="ask"===t.mode,c=!l&&!!t.enableWebSearch,u=c&&i&&!v(s)?[xe]: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"===a&&(i?.supportsThinking??!1),y={systemPrompt:r,history:t.history||[],tools:m,signal:o,images:n,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 R}getMcpConnections(){return this.mcpManager?.getConnectionInfos()??[]}async destroy(){this.mcpManager&&(await this.mcpManager.disconnectAll(),this.mcpManager=null)}};export{He as AnthropicProtocol,Oe as ArkProtocol,q as CHAT_EVENT_TYPES,g as CLAUDE_FAMILY,Ne as ChatOrchestrator,u as DEEPSEEK_FAMILY,he as DEFAULT_MODEL,c as DOUBAO_FAMILY,we as DebugLogger,Ue as DeepSeekProtocol,d as GEMINI_FAMILY,m as GPT_FAMILY,Ve as GeminiProtocol,nt as HybridAgent,R as MODELS,h as MODEL_FAMILIES,y as MODEL_REGISTRY,ze as OpenAIProtocol,p as QWEN_FAMILY,Je as QwenProtocol,et as UnifiedAdapter,Y as createAbort,Xe as createAnthropicProtocol,L as createApiError,Pe as createArkProtocol,Ee as createDeepSeekProtocol,de as createDefaultToolExecutor,G as createDone,z as createError,Be as createGeminiProtocol,Le as createOpenAIProtocol,$e as createOrchestrator,X as createParseError,We as createQwenProtocol,Q as createRateLimitError,j as createSearchEnd,E as createSearchResult,U as createSearchStart,te as createStepEnd,ee as createStepStart,B as createTextDelta,P as createThinkingDelta,D as createThinkingEnd,O as createThinkingStart,Z as createTimeoutError,F as createToolCallOutput,V as createToolCallRequest,W as createToolCallResult,J as createToolCallStart,H as createToolError,tt as createUnifiedAdapter,ke as getDefaultProvider,K as getModelByModelId,f as getModelEntry,k as getModelFamily,_ as getModelProtocol,A as getModelSearchStrategy,T as getModelsByFamily,w as getModelsByProtocol,b as getVisibleModels,le as isAbortEvent,re as isErrorEvent,_e as isModelForProvider,ue as isRetryableError,oe as isSearchEvent,ae as isStatusEvent,ce as isStepEvent,ie as isTextEvent,ne as isThinkingEvent,se as isToolEvent,v as modelSupportsNativeSearch,C as modelSupportsThinking,M as resolveTools,ye as routeModelToProvider,fe as routeModelWithDetails,N as tool,$ as tools};
|
package/package.json
CHANGED
package/src/constants.ts
CHANGED
|
@@ -118,6 +118,9 @@ export const AGENT_MODE_PROMPT = `你是一个专业的 AI 助手,具备自主
|
|
|
118
118
|
4. **自动纠正**:发现问题时尝试替代方案,不要停下来问用户
|
|
119
119
|
5. **总结汇报**:所有步骤完成后,给出简洁的结果总结
|
|
120
120
|
|
|
121
|
+
## 技能库
|
|
122
|
+
你可以通过 search_skills 工具搜索专业技能指令库。当用户请求涉及特定领域(如文档摘要、翻译、代码审查、数据分析、写作润色等)时,建议先搜索是否有专门的技能指令可参考,用 load_skill 加载后按技能指令执行,以获得更高质量的结果。
|
|
123
|
+
|
|
121
124
|
## 输出规范
|
|
122
125
|
- 不使用表情符号(emoji),除非用户要求
|
|
123
126
|
- 使用 Markdown 格式组织内容
|