agent-tool-chat 1.1.2 → 1.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -1,7 +1,7 @@
1
1
  "use strict";var ci=Object.defineProperty;var ui=(e,t,n)=>t in e?ci(e,t,{enumerable:!0,configurable:!0,writable:!0,value:n}):e[t]=n;var L=(e,t,n)=>ui(e,typeof t!="symbol"?t+"":t,n);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const r=require("vue"),ft=require("element-plus");function hi(e){let t="";return typeof e.content=="string"?t=e.content:e.content!=null&&(t=JSON.stringify(e.content)),e.tool_calls&&(t+=JSON.stringify(e.tool_calls)),e.name&&(t+=e.name),Math.ceil(t.length/2)||1}function di(e,t){const n=e.length;if(n===0)return e;let i=0,o=n-1;for(let s=n-1;s>=0;s--)if(i+=hi(e[s]),o=s,i>t){o=Math.min(s+1,n-1);break}return o>0&&e[o].role==="tool"&&(o-=1),e.slice(o)}class Zo{constructor(t){L(this,"messages",[]);L(this,"config");L(this,"listeners",new Set);L(this,"abortController",null);L(this,"_loading",!1);this.config={...t,maxToolRounds:t.maxToolRounds??6}}get loading(){return this._loading}updateProviderConfig(t){this.config.providerConfig={...this.config.providerConfig,...t}}initialize(t){this.messages.length=0,this.messages.push(...t)}clear(){var t;this.stop(),this.messages.length=0,(t=this.config.storage)==null||t.save([])}on(t){return this.listeners.add(t),()=>this.listeners.delete(t)}emit(t){this.listeners.forEach(n=>n(t))}async sendMessage(t){var o;const n=t.trim();if(!n||this._loading)return;this._loading=!0,this.abortController=new AbortController,this.emit({type:"status",loading:!0});const i={role:"user",content:n};this.messages.push(i),this.emit({type:"message",message:i});try{let s=0;const l=this.config.maxToolRounds;for(;s<l;){s++;const A={role:"assistant",content:""};this.messages.push(A),this.emit({type:"message",message:A});const a=this.buildApiMessages(),u=await this.config.provider.streamChat({config:this.config.providerConfig,messages:a,tools:this.config.tools.getDefinitions(),signal:this.abortController.signal,onContent:d=>{A.content+=d,this.emit({type:"stream:delta",delta:{content:d}})},onReasoning:d=>{this.emit({type:"stream:delta",delta:{reasoning:d}})}});if(A.content=u.content,this.emit({type:"stream:end",content:u.content,reasoning:u.reasoning}),u.tool_calls.length>0){A.tool_calls=u.tool_calls;for(const d of u.tool_calls){this.emit({type:"tool:start",call:d});const f=await this.config.tools.execute(d.function.name,d.function.arguments);this.emit({type:"tool:end",call:d,output:f}),this.messages.push({role:"tool",tool_call_id:d.id,content:f.result,name:d.function.name})}continue}break}await((o=this.config.storage)==null?void 0:o.save(this.messages))}catch(s){if((s==null?void 0:s.name)!=="AbortError")this.emit({type:"error",error:(s==null?void 0:s.message)||"请求出错"});else{const l=this.messages[this.messages.length-1];(l==null?void 0:l.role)==="assistant"&&!l.content&&(l.content="(已停止生成)")}}finally{this._loading=!1,this.abortController=null,this.emit({type:"status",loading:!1})}}stop(){var t;(t=this.abortController)==null||t.abort()}buildApiMessages(){const t=this.messages;let i=t.length>0&&t[t.length-1].role==="assistant"&&t[t.length-1].content===""&&!t[t.length-1].tool_calls?t.slice(0,-1):t;const o=this.config.maxHistoryMessages??0;o>0&&i.length>o&&(i=i.slice(i.length-o));const s=this.config.maxContextTokens??0;for(s>0&&(i=di(i,s));i.length&&i[0].role==="tool";)i=i.slice(1);return this.config.systemPrompt?[{role:"system",content:this.config.systemPrompt},...i]:[...i]}}class Po{constructor(){L(this,"_definitions",[]);L(this,"_handlers",new Map)}register(t,n){const i=t.function.name,o=this._definitions.findIndex(s=>s.function.name===i);return o!==-1&&this._definitions.splice(o,1),this._definitions.push(t),this._handlers.set(i,n),this}registerBatch(t){for(const n of t)this.register(n.definition,n.handler);return this}getDefinitions(){return[...this._definitions]}async execute(t,n){const i=this._handlers.get(t);if(!i)return{success:!1,result:`未知工具:${t}`};try{const o=n?JSON.parse(n):{};return await i(o)}catch(o){return{success:!1,result:`工具执行异常:${(o==null?void 0:o.message)||String(o)}`}}}}function fi(e){let t=e.trim().replace(/\/+$/,"");return t=t.replace(/\/v1$/,""),t}function zo(){return{async streamChat(e){var w;const{config:{baseUrl:t,apiKey:n,model:i,temperature:o,thinking:s},messages:l,tools:A,signal:a,onContent:u,onReasoning:d}=e;if(!n)throw new Error("未配置 API Key");const f=`${fi(t)}/chat/completions`,_={model:i,messages:l,stream:!0};typeof o=="number"&&(_.temperature=o),_.thinking={type:(s==null?void 0:s.type)==="enabled"?"enabled":"disabled"},(s==null?void 0:s.type)==="enabled"&&s.effort&&(_.reasoning_effort=s.effort),A!=null&&A.length&&(_.tools=A,_.tool_choice="auto");const m=await fetch(f,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${n}`},body:JSON.stringify(_),signal:a});if(!m.ok||!m.body){let E=`请求失败(HTTP ${m.status})`;try{const x=await m.json();(w=x==null?void 0:x.error)!=null&&w.message&&(E=x.error.message)}catch{}throw new Error(E)}const h=m.body.getReader(),k=new TextDecoder("utf-8");let b="",g="",I="",S="stop";const C=new Map,B=E=>{if(!E)return;const x=E.index??0;C.has(x)||C.set(x,{id:"",type:"function",function:{name:"",arguments:""}});const R=C.get(x);E.id&&(R.id=E.id),E.type&&(R.type=E.type),E.function&&(E.function.name&&(R.function.name+=E.function.name),E.function.arguments&&(R.function.arguments+=E.function.arguments))},K=E=>{var J;const x=(J=E==null?void 0:E.choices)==null?void 0:J[0];if(!x)return;const R=x.delta||{};typeof R.content=="string"&&R.content&&(g+=R.content,u==null||u(R.content)),typeof R.reasoning_content=="string"&&R.reasoning_content&&(I+=R.reasoning_content,d==null||d(R.reasoning_content)),Array.isArray(R.tool_calls)&&R.tool_calls.forEach(z=>B(z)),x.finish_reason&&(S=x.finish_reason)};for(;;){const{done:E,value:x}=await h.read();if(E)break;b+=k.decode(x,{stream:!0});let R;for(;(R=b.indexOf(`
2
2
  `))!==-1;){const J=b.slice(0,R).replace(/\r$/,"").trim();if(b=b.slice(R+1),!J||J.startsWith(":")||!J.startsWith("data:"))continue;const z=J.slice(5).trim();if(z==="[DONE]")return N();try{K(JSON.parse(z))}catch{}}}return N();function N(){const E=Array.from(C.values()).filter(x=>x.function.name);return{content:g,reasoning:I,tool_calls:E,finish_reason:S}}}}}function jo(){return{async streamChat(e){var N;const{config:{baseUrl:t,model:n,temperature:i,thinking:o},messages:s,tools:l,signal:A,onContent:a,onReasoning:u}=e,d=`${t.trim().replace(/\/+$/,"")}`,f={model:n,messages:s,stream:!0};typeof i=="number"&&(f.temperature=i),f.thinking={type:(o==null?void 0:o.type)==="enabled"?"enabled":"disabled"},(o==null?void 0:o.type)==="enabled"&&o.effort&&(f.reasoning_effort=o.effort),l!=null&&l.length&&(f.tools=l,f.tool_choice="auto");const _=await fetch(d,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(f),signal:A});if(!_.ok||!_.body){let w=`请求失败(HTTP ${_.status})`;try{const E=await _.json();(N=E==null?void 0:E.error)!=null&&N.message&&(w=E.error.message)}catch{}throw new Error(w)}const m=_.body.getReader(),h=new TextDecoder("utf-8");let k="",b="",g="",I="stop";const S=new Map,C=w=>{if(!w)return;const E=w.index??0;S.has(E)||S.set(E,{id:"",type:"function",function:{name:"",arguments:""}});const x=S.get(E);w.id&&(x.id=w.id),w.type&&(x.type=w.type),w.function&&(w.function.name&&(x.function.name+=w.function.name),w.function.arguments&&(x.function.arguments+=w.function.arguments))},B=w=>{var R;const E=(R=w==null?void 0:w.choices)==null?void 0:R[0];if(!E)return;const x=E.delta||{};typeof x.content=="string"&&x.content&&(b+=x.content,a==null||a(x.content)),typeof x.reasoning_content=="string"&&x.reasoning_content&&(g+=x.reasoning_content,u==null||u(x.reasoning_content)),Array.isArray(x.tool_calls)&&x.tool_calls.forEach(J=>C(J)),E.finish_reason&&(I=E.finish_reason)};for(;;){const{done:w,value:E}=await m.read();if(w)break;k+=h.decode(E,{stream:!0});let x;for(;(x=k.indexOf(`
3
3
  `))!==-1;){const R=k.slice(0,x).replace(/\r$/,"").trim();if(k=k.slice(x+1),!R||R.startsWith(":")||!R.startsWith("data:"))continue;const J=R.slice(5).trim();if(J==="[DONE]")return K();try{B(JSON.parse(J))}catch{}}}return K();function K(){const w=Array.from(S.values()).filter(E=>E.function.name);return{content:b,reasoning:g,tool_calls:w,finish_reason:I}}}}}function pi(e){var n,i,o,s,l;const t=[];return(n=e.displayHints)!=null&&n.suggestComponent&&t.push(`展示建议: 使用 ${e.displayHints.suggestComponent} 组件`),(i=e.displayHints)!=null&&i.resultFormat&&t.push(`格式: ${e.displayHints.resultFormat}`),(s=(o=e.displayHints)==null?void 0:o.previewFields)!=null&&s.length&&t.push(`预览字段: ${e.displayHints.previewFields.join(", ")}`),(l=e.displayHints)!=null&&l.summaryTemplate&&t.push(`概要模板: ${e.displayHints.summaryTemplate}`),t.length?t.join(" | "):""}function Xo(e){const t=[`【${e.name}】${e.description}`];for(const n of e.tools){const i=pi(n);t.push(` - ${n.name}: ${n.description}`),i&&t.push(` ${i}`)}return t.join(`
4
- `)}function $o(e){const t=["你是一个 AI 助手,可以帮助用户完成各种操作。","","你可以使用以下工具包:",""];for(const n of e)t.push(Xo(n)),t.push("");return t.push("注意:"),t.push("1. 所有回复与思考/推理过程(reasoning / thinking)一律使用中文(禁止使用英文),保持简洁清晰;除非用户明确要求使用其他语言,此时思考与回复也相应使用该语言。"),t.push("2. 当你需要查询或操作数据时,调用对应工具包中的函数。"),t.push("3. 工具函数由宿主系统执行,你只需要传递正确的参数。"),t.push("4. 获取到工具结果后,回复用户并告知结果。"),t.push("5. 如果工具返回了结构化数据(如订单信息、系统状态等),在回复中清晰地展示给用户。"),t.push("6. 根据结果动态建议用户接下来可以做什么。要求分条目,结构清晰,每个条目占一行。"),t.push("7. 如果用户上传了文件,文件格式为(.txt、.json、.geojson等格式),你必须调用 open_mapview_file 工具在地图上展示,不要只回复文字。"),t.push(""),t.push("--- 文件上传规则 ---"),t.push("用户可能上传文件,文件以如下格式出现在消息中:"),t.push("已上传文件:"),t.push("1. **文件名**(类型,大小KB),文件ID:`fileId`"),t.push("你无法查看文件内容,只能看到文件名和类型。"),t.push("你必须根据文件名、扩展名和用户的文字指令,调用对应的工具来处理文件。"),t.push("如果某个工具需要处理该文件,在工具参数中传入 fileId。"),t.push('不要回复假性成功消息(如"已在地图上显示"),如果不调用工具,文件不会被实际处理。'),t.push("不要编造文件内容,不要假装你看到了文件数据。"),t.join(`
4
+ `)}function $o(e){const t=["你是一个 AI 助手,可以帮助用户完成各种操作。","","你可以使用以下工具包:",""];for(const n of e)t.push(Xo(n)),t.push("");return t.push("注意:"),t.push("1. 所有回复与思考/推理过程(reasoning / thinking)一律使用中文(禁止使用英文),保持简洁清晰;除非用户明确要求使用其他语言,此时思考与回复也相应使用该语言。"),t.push("2. 当你需要查询或操作数据时,调用对应工具包中的函数。"),t.push("3. 工具函数由宿主系统执行,你只需要传递正确的参数。"),t.push("4. 获取到工具结果后,回复用户并告知结果。"),t.push("5. 如果工具返回了结构化数据(如订单信息、系统状态等),在回复中清晰地展示给用户。"),t.push("6. 根据结果动态建议用户接下来可以做什么。"),t.push("7. 如果用户上传了文件,文件格式为(.txt、.json、.geojson等格式),你必须调用 open_mapview_file 工具在地图上展示,不要只回复文字。"),t.push(""),t.push("--- 文件上传规则 ---"),t.push("用户可能上传文件,文件以如下格式出现在消息中:"),t.push("已上传文件:"),t.push("1. **文件名**(类型,大小KB),文件ID:`fileId`"),t.push("你无法查看文件内容,只能看到文件名和类型。"),t.push("你必须根据文件名、扩展名和用户的文字指令,调用对应的工具来处理文件。"),t.push("如果某个工具需要处理该文件,在工具参数中传入 fileId。"),t.push('不要回复假性成功消息(如"已在地图上显示"),如果不调用工具,文件不会被实际处理。'),t.push("不要编造文件内容,不要假装你看到了文件数据。"),t.join(`
5
5
  `)}const mi=`--- 重复指令处理规则 ---
6
6
  如果用户再次发送相同或类似的指令(即使之前已经执行过),必须重新调用对应的工具再次执行。
7
7
  不得以"已经执行过""之前做过"等理由拒绝,也不能用历史中的工具结果代替重新执行。`;function gi(e){const t=String(e).replace(/\s+/g,"");if(!t||!/^[\d+\-*/%().]+$/.test(t))throw new Error("表达式含非法字符");return Ci(t)}function Ci(e){let t=0;function n(){return e[t]??""}function i(u){return e[t]===u?(t++,!0):!1}function o(){const u=t;for(;/[\d.]/.test(n());)t++;const d=e.slice(u,t);if(!d)throw new Error("预期数字");const f=Number(d);if(Number.isNaN(f))throw new Error("无效数字");return f}function s(){if(i("-"))return-s();if(i("+"))return s();if(i("(")){const u=A();if(!i(")"))throw new Error("括号不匹配");return u}return o()}function l(){let u=s();for(;;)if(i("*"))u*=s();else if(i("/"))u/=s();else if(i("%"))u=(u%s()+s())%s();else break;return u}function A(){let u=l();for(;;)if(i("+"))u+=l();else if(i("-"))u-=l();else break;return u}const a=A();if(t!==e.length)throw new Error("无法解析的表达式");return a}const wt={id:"__builtin",name:"内置工具",description:"开箱即用的通用工具(时间、计算、UUID、客户端信息)",tools:[{name:"get_current_time",description:"获取用户当前的时间、日期、时区与星期",parameters:{type:"object",properties:{}},displayHints:{resultFormat:"card"}},{name:"calculate_expression",description:"安全计算数学表达式(支持 + - * / % 和括号)",parameters:{type:"object",properties:{expression:{type:"string",description:"数学表达式,如 (1+2)*3"}},required:["expression"]},displayHints:{resultFormat:"text"}},{name:"generate_uuid",description:"生成一个 UUID v4 随机标识符",parameters:{type:"object",properties:{}},displayHints:{resultFormat:"text"}},{name:"get_client_info",description:"获取用户浏览器的基本信息(UA、平台、语言、屏幕尺寸)",parameters:{type:"object",properties:{}},displayHints:{resultFormat:"card"}}]};function _i(){return{get_current_time:()=>{const e=new Date;return{time:e.toLocaleTimeString(),date:e.toLocaleDateString(),timezone:Intl.DateTimeFormat().resolvedOptions().timeZone,weekday:e.toLocaleDateString("zh-CN",{weekday:"long"})}},calculate_expression:e=>{if(!(e!=null&&e.expression))throw new Error("缺少 expression 参数");const t=gi(String(e.expression));return{expression:e.expression,result:t}},generate_uuid:()=>{let e=[];const t="0123456789abcdef";for(let n=0;n<36;n++)e[n]=t.charAt(Math.floor(Math.random()*16));return e[14]="4",e[19]=t.charAt(parseInt(e[19],16)&3|8),e[8]=e[13]=e[18]=e[23]="-",{uuid:e.join("")}},get_client_info:()=>{var e;return{userAgent:navigator.userAgent,platform:navigator.platform,language:navigator.language,languages:(e=navigator.languages)==null?void 0:e.join(", "),screen:`${window.screen.width}×${window.screen.height}`}}}}const ki=_i();function qo(e,t){const n=ki[e];if(!n)throw new Error(`未知内置工具:${e}`);return n(t)}function yi(e,t,n){var s;let i=null;if(e.type==="auto"&&(e={...e,type:Qn(e.data)}),e.type==="component"&&e.componentName){let l;e.packageId&&(l=t.find(A=>A.id===e.packageId)),!l&&n&&(l=t.find(A=>A.id===n)),(s=l==null?void 0:l.components)!=null&&s[e.componentName]&&(i=l.components[e.componentName])}const o=Ei(e);return{component:i,block:e,fallbackText:o}}function Qn(e){const t=Qt(e);return t&&t.length===1?"none":"table"}function Ei(e){switch(e.type){case"table":return bi(e);case"card":return Di(e);case"list":return Ii(e);case"none":return"";default:return JSON.stringify(e.data,null,2)}}function Qt(e){return e==null?null:Array.isArray(e)?e:typeof e!="object"?null:Array.isArray(e.data)?e.data:Array.isArray(e.list)?e.list:Array.isArray(e.items)?e.items:[e]}function bi(e){const t=Qt(e.data);if(!(t!=null&&t.length))return"(无数据)";const n=e.title?`**${e.title}**
package/dist/index.js CHANGED
@@ -312,7 +312,7 @@ function Qs(e) {
312
312
  t.push(di(n)), t.push("");
313
313
  return t.push("注意:"), t.push(
314
314
  "1. 所有回复与思考/推理过程(reasoning / thinking)一律使用中文(禁止使用英文),保持简洁清晰;除非用户明确要求使用其他语言,此时思考与回复也相应使用该语言。"
315
- ), t.push("2. 当你需要查询或操作数据时,调用对应工具包中的函数。"), t.push("3. 工具函数由宿主系统执行,你只需要传递正确的参数。"), t.push("4. 获取到工具结果后,回复用户并告知结果。"), t.push("5. 如果工具返回了结构化数据(如订单信息、系统状态等),在回复中清晰地展示给用户。"), t.push("6. 根据结果动态建议用户接下来可以做什么。要求分条目,结构清晰,每个条目占一行。"), t.push("7. 如果用户上传了文件,文件格式为(.txt、.json、.geojson等格式),你必须调用 open_mapview_file 工具在地图上展示,不要只回复文字。"), t.push(""), t.push("--- 文件上传规则 ---"), t.push("用户可能上传文件,文件以如下格式出现在消息中:"), t.push("已上传文件:"), t.push("1. **文件名**(类型,大小KB),文件ID:`fileId`"), t.push("你无法查看文件内容,只能看到文件名和类型。"), t.push("你必须根据文件名、扩展名和用户的文字指令,调用对应的工具来处理文件。"), t.push("如果某个工具需要处理该文件,在工具参数中传入 fileId。"), t.push('不要回复假性成功消息(如"已在地图上显示"),如果不调用工具,文件不会被实际处理。'), t.push("不要编造文件内容,不要假装你看到了文件数据。"), t.join(`
315
+ ), t.push("2. 当你需要查询或操作数据时,调用对应工具包中的函数。"), t.push("3. 工具函数由宿主系统执行,你只需要传递正确的参数。"), t.push("4. 获取到工具结果后,回复用户并告知结果。"), t.push("5. 如果工具返回了结构化数据(如订单信息、系统状态等),在回复中清晰地展示给用户。"), t.push("6. 根据结果动态建议用户接下来可以做什么。"), t.push("7. 如果用户上传了文件,文件格式为(.txt、.json、.geojson等格式),你必须调用 open_mapview_file 工具在地图上展示,不要只回复文字。"), t.push(""), t.push("--- 文件上传规则 ---"), t.push("用户可能上传文件,文件以如下格式出现在消息中:"), t.push("已上传文件:"), t.push("1. **文件名**(类型,大小KB),文件ID:`fileId`"), t.push("你无法查看文件内容,只能看到文件名和类型。"), t.push("你必须根据文件名、扩展名和用户的文字指令,调用对应的工具来处理文件。"), t.push("如果某个工具需要处理该文件,在工具参数中传入 fileId。"), t.push('不要回复假性成功消息(如"已在地图上显示"),如果不调用工具,文件不会被实际处理。'), t.push("不要编造文件内容,不要假装你看到了文件数据。"), t.join(`
316
316
  `);
317
317
  }
318
318
  const Ms = `--- 重复指令处理规则 ---
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "agent-tool-chat",
3
3
  "description": "An agent-driven chat plugin with ToolPackage architecture and host-controlled execution",
4
4
  "author": "kangjinrui <1092014304@qq.com>",
5
- "version": "1.1.2",
5
+ "version": "1.1.3",
6
6
  "license": "MIT",
7
7
  "private": false,
8
8
  "type": "module",