@opentiny/tiny-robot-kit 0.4.0-alpha.7 → 0.4.0-alpha.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +3 -3
- package/dist/index.mjs +3 -3
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"use strict";var
|
|
1
|
+
"use strict";var ae=Object.defineProperty;var Oe=Object.getOwnPropertyDescriptor;var Ie=Object.getOwnPropertyNames;var ke=Object.prototype.hasOwnProperty;var _e=(o,t)=>{for(var e in t)ae(o,e,{get:t[e],enumerable:!0})},De=(o,t,e,n)=>{if(t&&typeof t=="object"||typeof t=="function")for(let s of Ie(t))!ke.call(o,s)&&s!==e&&ae(o,s,{get:()=>t[s],enumerable:!(n=Oe(t,s))||n.enumerable});return o};var Ue=o=>De(ae({},"__esModule",{value:!0}),o);var He={};_e(He,{AIClient:()=>Y,EXCLUDE_MODE_REMOVE:()=>Te,ErrorType:()=>pe,IndexedDBStrategy:()=>H,LocalStorageStrategy:()=>W,StreamEventType:()=>fe,fallbackRolePlugin:()=>ce,indexedDBStorageStrategyFactory:()=>ve,lengthPlugin:()=>ue,localStorageStrategyFactory:()=>ee,sseStreamToGenerator:()=>he,thinkingPlugin:()=>de,toolPlugin:()=>Fe,useConversation:()=>We,useMessage:()=>oe});module.exports=Ue(He);var Q=class{constructor(t){this.config=t}updateConfig(t){this.config={...this.config,...t}}getConfig(){return{...this.config}}validateRequest(t){if(!t.messages||!Array.isArray(t.messages)||t.messages.length===0)throw new Error("\u8BF7\u6C42\u5FC5\u987B\u5305\u542B\u81F3\u5C11\u4E00\u6761\u6D88\u606F");for(let e of t.messages)if(!e.role||!e.content)throw new Error("\u6BCF\u6761\u6D88\u606F\u5FC5\u987B\u5305\u542B\u89D2\u8272\u548C\u5185\u5BB9")}};var pe=(l=>(l.NETWORK_ERROR="network_error",l.AUTHENTICATION_ERROR="authentication_error",l.RATE_LIMIT_ERROR="rate_limit_error",l.SERVER_ERROR="server_error",l.MODEL_ERROR="model_error",l.TIMEOUT_ERROR="timeout_error",l.UNKNOWN_ERROR="unknown_error",l))(pe||{}),fe=(n=>(n.DATA="data",n.ERROR="error",n.DONE="done",n))(fe||{});function K(o){return{type:o.type||"unknown_error",message:o.message||"\u672A\u77E5\u9519\u8BEF",statusCode:o.statusCode,originalError:o.originalError}}function ie(o){if(!o.response)return K({type:"network_error",message:"\u7F51\u7EDC\u8FDE\u63A5\u9519\u8BEF\uFF0C\u8BF7\u68C0\u67E5\u60A8\u7684\u7F51\u7EDC\u8FDE\u63A5",originalError:o});if(o.response){let{status:t,data:e}=o.response;return t===401||t===403?K({type:"authentication_error",message:"\u8EAB\u4EFD\u9A8C\u8BC1\u5931\u8D25\uFF0C\u8BF7\u68C0\u67E5\u60A8\u7684API\u5BC6\u94A5",statusCode:t,originalError:o}):t===429?K({type:"rate_limit_error",message:"\u8D85\u51FAAPI\u8C03\u7528\u9650\u5236\uFF0C\u8BF7\u7A0D\u540E\u518D\u8BD5",statusCode:t,originalError:o}):t>=500?K({type:"server_error",message:"\u670D\u52A1\u5668\u9519\u8BEF\uFF0C\u8BF7\u7A0D\u540E\u518D\u8BD5",statusCode:t,originalError:o}):K({type:"unknown_error",message:e?.error?.message||`\u8BF7\u6C42\u5931\u8D25\uFF0C\u72B6\u6001\u7801: ${t}`,statusCode:t,originalError:o})}return o.code==="ECONNABORTED"?K({type:"timeout_error",message:"\u8BF7\u6C42\u8D85\u65F6\uFF0C\u8BF7\u7A0D\u540E\u518D\u8BD5",originalError:o}):K({type:"unknown_error",message:o.message||"\u53D1\u751F\u672A\u77E5\u9519\u8BEF",originalError:o})}async function me(o,t,e){let n=o.body?.getReader();if(!n)throw new Error("Response body is null");let s=new TextDecoder,r="",a,l;e&&e.addEventListener("abort",()=>{n.cancel().catch(d=>console.error("Error cancelling reader:",d))},{once:!0});try{for(;;){if(e?.aborted){await n.cancel();break}let{done:d,value:p}=await n.read();if(d)break;let v=s.decode(p,{stream:!0});r+=v;let R=r.split(`
|
|
2
2
|
|
|
3
|
-
`);r=R.pop()||"";for(let x of R)if(x.trim()!==""){if(x.trim()==="data: [DONE]"){l&&(a=l),t.onDone(a);continue}try{let A=x.match(/^data: (.+)$/m);if(!A)continue;let
|
|
4
|
-
`);r=R.pop()||"";for(let x of R)if(x.trim()!==""&&x.startsWith("data: ")){let A=x.slice(6);if(A==="[DONE]")return;try{yield JSON.parse(A)}catch(b){console.warn("Failed to parse SSE data:",A,b)}}}}finally{s?.removeEventListener("abort",a),e.releaseLock()}}var $=class extends X{constructor(e){super(e);this.defaultModel="gpt-3.5-turbo";this.baseURL=e.apiUrl||"https://api.openai.com/v1",this.apiKey=e.apiKey||"",e.defaultModel&&(this.defaultModel=e.defaultModel),this.apiKey||console.warn("API key is not provided. Authentication will likely fail.")}async chat(e){try{this.validateRequest(e);let s={model:e.options?.model||this.config.defaultModel||this.defaultModel,messages:e.messages,...e.options,stream:!1},n={method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(s)};this.apiKey&&Object.assign(n.headers,{Authorization:`Bearer ${this.apiKey}`});let r=await fetch(`${this.baseURL}/chat/completions`,n);if(!r.ok){let a=await r.text();throw new Error(`HTTP error! status: ${r.status}, details: ${a}`)}return await r.json()}catch(s){throw re(s)}}async chatStream(e,s){let{signal:n,...r}=e.options||{};try{this.validateRequest(e);let a={model:e.options?.model||this.config.defaultModel||this.defaultModel,messages:e.messages,...r,stream:!0},l={method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${this.apiKey}`,Accept:"text/event-stream"},body:JSON.stringify(a),signal:n};this.apiKey&&Object.assign(l.headers,{Authorization:`Bearer ${this.apiKey}`});let u=await fetch(`${this.baseURL}/chat/completions`,l);if(!u.ok){let p=await u.text();throw new Error(`HTTP error! status: ${u.status}, details: ${p}`)}await pe(u,s,n)}catch(a){if(n?.aborted)return;s.onError(re(a))}}updateConfig(e){super.updateConfig(e),e.apiUrl&&(this.baseURL=e.apiUrl),e.apiKey&&(this.apiKey=e.apiKey),e.defaultModel&&(this.defaultModel=e.defaultModel)}};var Q=class{constructor(t){this.config=t,this.provider=this.createProvider(t)}createProvider(t){if(t.provider==="custom"&&"providerImplementation"in t)return t.providerImplementation;if(t.provider==="deepseek"){let e={defaultModel:"deepseek-chat",apiUrl:"https://api.deepseek.com/v1"};return new $({...e,...t})}else return new $(t)}async chat(t){return this.provider.chat(t)}async chatStream(t,e){let s={...t,options:{...t.options,stream:!0}};return this.provider.chatStream(s,e)}getConfig(){return{...this.config}}updateConfig(t){this.config={...this.config,...t},t.provider&&t.provider!==this.config.provider?this.provider=this.createProvider(this.config):this.provider.updateConfig(this.config)}};var me=require("vue");function J(o,t=new WeakSet){if(o==null||typeof o!="object")return o;if(t.has(o))return Array.isArray(o)?[]:{};t.add(o);try{let e=(0,me.toRaw)(o);if(Array.isArray(e))return e.map(n=>J(n,t));if(e instanceof Date||e instanceof RegExp||e instanceof ArrayBuffer||e instanceof Blob)return e;let s={};for(let n in e){if(typeof n=="symbol")continue;let r=Object.getOwnPropertyDescriptor(e,n);if(!r||r.get||r.set)continue;let a=e[n];typeof a!="function"&&typeof a!="symbol"&&(s[n]=J(a,t))}return s}catch(e){return console.warn("unwrapProxy error:",e),Array.isArray(o)?[]:{}}}var Y=o=>o.map(t=>{let{renderContent:e,...s}=t;if(!Array.isArray(e))return t;let n=e.filter(a=>a.type==="collapsible-text"),r=e.filter(a=>a.type==="markdown"||a.type==="text");return n.length>0&&(s.reasoning_content=n.map(a=>a.content).join("")),r.length>0&&(s.content=r.map(a=>a.content).join("")),s});var z=o=>{let t=localStorage.getItem(o);return t?JSON.parse(t):[]},L=class{constructor(t="tiny-robot-ai-conversations"){this.storageKey=t}saveConversation(t){try{let e=z(this.storageKey),s=e.findIndex(n=>n.id===t.id);s!==-1?Object.assign(e[s],t):e.unshift({...t,messages:[]}),localStorage.setItem(this.storageKey,JSON.stringify(e))}catch(e){console.error("\u4FDD\u5B58\u4F1A\u8BDD\u5931\u8D25:",e)}}loadConversations(){try{return z(this.storageKey).map(e=>({id:e.id,title:e.title,createdAt:e.createdAt,updatedAt:e.updatedAt,metadata:e.metadata}))}catch(t){return console.error("\u52A0\u8F7D\u4F1A\u8BDD\u5931\u8D25:",t),[]}}saveMessages(t,e){try{let s=z(this.storageKey),n=s.findIndex(r=>r.id===t);n!==-1&&(s[n].messages=e),localStorage.setItem(this.storageKey,JSON.stringify(s))}catch(s){console.error("\u4FDD\u5B58\u4F1A\u8BDD\u6D88\u606F\u5931\u8D25:",s)}}loadMessages(t){try{let s=z(this.storageKey).find(r=>r.id===t);return Y(s?.messages||[])}catch(e){return console.error("\u52A0\u8F7D\u4F1A\u8BDD\u6D88\u606F\u5931\u8D25:",e),[]}}deleteConversation(t){let e=z(this.storageKey),s=e.findIndex(n=>n.id===t);s!==-1&&e.splice(s,1),localStorage.setItem(this.storageKey,JSON.stringify(e))}};var he=require("idb");var W=class{constructor(t="tiny-robot-ai-db",e=3){this.db=null;this.dbName=t,this.dbVersion=e}async getDB(){return this.db||(this.db=await(0,he.openDB)(this.dbName,this.dbVersion,{upgrade(t){t.objectStoreNames.contains("conversations")||t.createObjectStore("conversations",{keyPath:"id"}).createIndex("by-updated","updatedAt"),t.objectStoreNames.contains("messages")||t.createObjectStore("messages",{keyPath:"conversationId"})}})),this.db}async loadConversations(){try{return(await(await this.getDB()).getAllFromIndex("conversations","by-updated")).reverse()}catch(t){return console.error("\u52A0\u8F7D\u4F1A\u8BDD\u5931\u8D25:",t),[]}}async loadMessages(t){try{let s=await(await this.getDB()).get("messages",t);return s?Y(s.messages):[]}catch(e){return console.error("\u52A0\u8F7D\u4F1A\u8BDD\u6D88\u606F\u5931\u8D25:",e),[]}}async saveConversation(t){try{let e=await this.getDB(),s=J(t);await e.put("conversations",s)}catch(e){throw console.error("\u4FDD\u5B58\u4F1A\u8BDD\u5931\u8D25:",e),e}}async saveMessages(t,e){try{let s=await this.getDB(),n=J(e);await s.put("messages",{conversationId:t,messages:n})}catch(s){throw console.error("\u4FDD\u5B58\u4F1A\u8BDD\u6D88\u606F\u5931\u8D25:",s),s}}async deleteConversation(t){try{let e=await this.getDB();await e.delete("conversations",t),await e.delete("messages",t)}catch(e){throw console.error("\u5220\u9664\u4F1A\u8BDD\u5931\u8D25:",e),e}}};function Z(o={}){return new L(o.key||"tiny-robot-ai-conversations")}function ye(o={}){return new W(o.dbName||"tiny-robot-ai-db",o.dbVersion||1)}var K=require("vue");var U=require("vue");var ie=(o={})=>{let{fallbackRole:t="assistant",...e}=o;return{name:"fallbackRole",...e,onBeforeRequest(s){let{requestBody:n,messages:r}=s;return n.messages=r.map(a=>({...a,role:a.role||t})),e.onBeforeRequest?.(s)}}};var le=(o={})=>{let{continueContent:t="Please continue with your previous answer.",...e}=o;return{name:"length",...e,onAfterRequest:async s=>{let{lastChoice:n,appendMessage:r,requestNext:a}=s;return n?.finish_reason==="length"&&(r({role:"user",content:t}),a()),e.onAfterRequest?.(s)}}};var ce=(o={})=>({name:"thinking",...o,onCompletionChunk(t){let{choice:e,currentMessage:s}=t,r=typeof(e?.message?.reasoning_content||e?.delta?.reasoning_content)=="string";return s.state?s.state.thinking=r:s.state={thinking:r},o.onCompletionChunk?.(t)},onTurnEnd(t){let e=t.currentTurn.slice(-1)[0];return e?.state&&(e.state.thinking=void 0),o.onTurnEnd?.(t)}});var xe=require("vue");var H=class extends Error{constructor(t){super(t),this.name="AbortError"}};function De(o){if(o.aborted)return{promise:Promise.reject(new H(String(o.reason??"Aborted"))),cleanup:()=>{}};let t=null;return{promise:new Promise((n,r)=>{t=()=>{r(new H(String(o.reason??"Aborted")))},o.addEventListener("abort",t,{once:!0})}),cleanup:()=>{t&&(o.removeEventListener("abort",t),t=null)}}}function Me(o,t){let{promise:e,cleanup:s}=De(t);return Promise.race([o,e]).finally(s)}function be(o,t){let e={};for(let s in o)t.includes(s)&&(e[s]=o[s]);return e}function Re(o,t){let e={};for(let s in o)t.includes(s)||(e[s]=o[s]);return e}async function*ee(o){if(Ce(o)){yield*o;return}let t=await o;if(Ce(t)){yield*t;return}yield t}function Ce(o){return o&&typeof o=="object"&&typeof o[Symbol.asyncIterator]=="function"}var ue=o=>typeof o=="object"&&o!==null,ve=o=>ue(o)&&typeof o.index=="number",G=(o,t)=>{for(let[e,s]of Object.entries(t)){let n=o[e];if(n)if(typeof n=="string"&&typeof s=="string")e==="type"&&n||(o[e]=n+s);else if(Array.isArray(n)&&Array.isArray(s))if(n.every(r=>ve(r))&&s.every(r=>ve(r))){let r=new Map(n.map(p=>[p.index,p])),a=new Map(s.map(p=>[p.index,p]));for(let[p,v]of a)if(r.has(p)){let R=r.get(p);r.set(p,G(R,v))}else r.set(p,v);let l=Math.max(...Array.from(r.keys()),-1)+1,u=l>n.length?Array.from({length:l}):n;for(let[p,v]of r)u[p]=v;o[e]=u}else o[e]=[...n,...s];else ue(n)&&ue(s)&&(o[e]=G(n,s));else o[e]=s}return o};function Ue(o,t){let e=[];for(let s=0;s<o.length;s++){let n=o[s];if(n.role==="assistant"&&n.tool_calls&&n.tool_calls.length>0){let r=new Set(n.tool_calls.map(u=>u.id)),a=new Set;for(let u=s+1;u<o.length;u++){let p=o[u];p.role==="tool"&&p.tool_call_id&&r.has(p.tool_call_id)&&a.add(p.tool_call_id)}let l=n.tool_calls.map(u=>u.id).filter(u=>!a.has(u));l.length>0&&e.push({insertAfterIndex:s,missingToolCallIds:l})}}for(let s=e.length-1;s>=0;s--){let{insertAfterIndex:n,missingToolCallIds:r}=e[s],a=r.map(l=>({role:"tool",tool_call_id:l,content:t}));o.splice(n+1,0,...a)}}var Ae="remove";function qe(o,t,e,s){let n=o.filter(a=>a[e]),r=new Set(n.flatMap(a=>a.tool_calls?.map(l=>l.id)??[]));if(t===Ae)for(let a=o.length-1;a>=0;a--){let l=o[a];(l[e]||l[s]||l.tool_call_id&&r.has(l.tool_call_id))&&o.splice(a,1)}else if(t===!0)for(let a of o)(a[e]||a.tool_call_id&&r.has(a.tool_call_id))&&(a[s]=!0,delete a[e])}var Be=o=>{let{getTools:t,beforeCallTools:e,callTool:s,onToolCallStart:n,onToolCallEnd:r,toolCallCancelledContent:a="Tool call cancelled.",toolCallFailedContent:l="Tool call failed.",autoFillMissingToolMessages:u=!1,excludeToolMessagesNextTurn:p=!1,...v}=o,R=Symbol("doNotSendNextTurn"),x=Symbol("doNotSend"),A=(...m)=>{let[h,{primaryMessage:T}]=m;T.state.toolCall[h.id].status="running",n?.(...m)},b=(...m)=>{let[h,{status:T,primaryMessage:O}]=m;O.state.toolCall[h.id].status=T,r?.(...m)};return{name:"tool",...v,onTurnStart:m=>{let{messages:h}=m;return u&&Ue(h,a),p&&qe(h,p,R,x),v.onTurnStart?.(m)},onBeforeRequest:async m=>{let{messages:h,requestBody:T}=m;p===!0&&(T.messages=h.filter(E=>!E[x]));let O=await t?.();return O&&O.length>0&&(T.tools=O),v.onBeforeRequest?.(m)},onAfterRequest:async m=>{let{currentMessage:h,lastChoice:T,appendMessage:O,abortSignal:E,setRequestState:i,requestNext:c}=m;if(T?.finish_reason!=="tool_calls"||!h.tool_calls?.length)return;p&&(h[R]=!0),i("processing","calling-tools"),await e?.(h.tool_calls,{...m,currentMessage:h});let f=h.tool_calls.map(async y=>{let S=Math.floor(Date.now()/1e3),w=(0,xe.reactive)({role:"tool",tool_call_id:y.id,content:"",metadata:{createdAt:S,updatedAt:S}});O(w);let q={...m,primaryMessage:h,toolMessage:w};A(y,q);try{let I=s(y,q),d=ee(I);for await(let g of d){if(typeof g=="string")w.content+=g;else{let M={};try{M=JSON.parse(w.content||"{}")}catch(P){console.warn(P)}w.content=JSON.stringify(G(M,g))}w.metadata.updatedAt=Math.floor(Date.now()/1e3)}b(y,{...q,status:"success"})}catch(I){let d=I instanceof Error?I:new Error(String(I));if(E.aborted){b(y,{...q,status:"cancelled",error:d});return}console.error(I),w.content.length===0&&(w.content=l),b(y,{...q,status:"failed",error:d})}});return await Promise.all(f),c(),v.onAfterRequest?.(m)},onCompletionChunk:m=>{var T,O,E;let{currentMessage:h}=m;if(Array.isArray(h.tool_calls))for(let i of h.tool_calls)h.state?.toolCall?.[i.id]?.status||(h.state??(h.state={}),(T=h.state).toolCall??(T.toolCall={}),(O=h.state.toolCall)[E=i.id]??(O[E]={}));return v.onCompletionChunk?.(m)}}};var Ne=o=>{let t=[];for(let e of o){if(e.name){let s=t.findIndex(n=>n.name===e.name);s!==-1&&t.splice(s,1)}t.push(e)}return t},te=o=>{let{initialMessages:t=[],requestMessageFields:e=[],requestMessageFieldsExclude:s=["state","metadata","loading"],plugins:n=[],onCompletionChunk:r}=o,a=(0,U.ref)("idle"),l=(0,U.ref)(void 0),u=(0,U.ref)(t),p=(0,U.ref)(o.responseProvider),v=null,R=[],x={},A=[ie(),ce(),le()],b=Ne(A.concat(n)),m=(0,U.computed)(()=>a.value==="processing"),h=async d=>{if(!d||!d.trim()){console.warn("Cannot send empty message");return}if(m.value){console.warn("Cannot send message while processing is in progress");return}let g=Math.floor(Date.now()/1e3);u.value.push({role:"user",content:d.trim(),metadata:{createdAt:g,updatedAt:g}}),R.push(u.value[u.value.length-1]),await S()},T=async(...d)=>{if(m.value){console.warn("Cannot send message while processing is in progress");return}u.value.push(...d),R.push(...d),await S()},O=d=>{let g=d;return e.length&&(g=g.map(M=>be(M,e))),s.length&&(g=g.map(M=>Re(M,s))),g},E=(d,g)=>{a.value=d,d==="processing"?l.value=g||"requesting":l.value=void 0},i=d=>{Object.assign(x,d)},c=d=>({messages:u.value,currentTurn:R,requestState:a.value,processingState:l.value,plugins:b,abortSignal:d,setRequestState:E,customContext:x,setCustomContext:i}),f=(d,g)=>typeof d.disabled=="function"?d.disabled(g):!!d.disabled,y=async(d,g)=>{E("processing","requesting");let M=new Proxy({messages:O(u.value)},{set(D,k,N){return k==="messages"?(D.messages=O(N),!0):(D[k]=N,!0)}}),P=c(g);for(let D of b.filter(k=>!f(k,P)))await D.onBeforeRequest?.({...P,requestBody:M});let C=(0,U.reactive)({role:"",content:"",loading:!0});I(C);let _,se=d(M,g),B=ee(se);for await(let D of B){E("processing","completing"),C.loading&&(C.loading=void 0);let k=D.choices?.find(j=>j.index===0);if(k){_=k;let j=()=>{C.metadata||(C.metadata={});let{created:V,...Se}=D;C.metadata.createdAt=V,C.metadata.updatedAt=Math.floor(Date.now()/1e3),Object.assign(C.metadata,Se),G(C,k.message||k.delta)};if(r){let V=c(g);r({...V,chunk:D,choice:k,currentMessage:C},j)}else j()}let N=c(g);for(let j of b.filter(V=>!f(V,N)))j.onCompletionChunk?.({...N,abortSignal:g,chunk:D,choice:k,currentMessage:C})}await q(C,d,g,_)},S=async()=>{let d=new AbortController;v=d,x={};try{E("processing","requesting");let g=c(d.signal);for(let C of b.filter(_=>!f(_,g)))await C.onTurnStart?.(g);let M=p.value;try{await y(M,d.signal),E("completed")}catch(C){if(d.signal.aborted||C instanceof H||C instanceof Error&&C.name==="AbortError")E("aborted");else throw C}let P=c(d.signal);for(let C of b.filter(_=>!f(_,P)))await C.onTurnEnd?.(P)}catch(g){E("error");let M=!1,P=c(d.signal);for(let C of b.filter(_=>!f(_,P)))M=!0,C.onError?.({...P,error:g});if(!M)throw g}finally{let g=c(d.signal);for(let M of b.filter(P=>!f(P,g)))try{M.onFinally?.(g)}catch(P){console.error(`Error in onFinally hook for plugin ${M.name||"Anonymous"}:`,P)}v=null,R.slice(-1)[0]&&(R.slice(-1)[0].loading=void 0),R=[]}},w=async()=>{v?.abort(),m.value&&await new Promise(d=>{let g=(0,U.watch)(m,M=>{M||(g(),d())},{immediate:!0})})},q=async(d,g,M,P)=>{let C=!1,_=c(M),se=b.filter(B=>!f(B,_)).map(B=>{if(!B.onAfterRequest)return null;let D=N=>{I(N)},k=()=>{C=!0};return B.onAfterRequest({..._,currentMessage:d,lastChoice:P,appendMessage:D,requestNext:k})}).filter(B=>B!==null);await Me(Promise.all(se),M),C&&await y(g,M)},I=d=>{let g=Array.isArray(d)?d:[d];u.value.push(...g),R.push(...g)};return{requestState:a,processingState:l,messages:u,responseProvider:p,isProcessing:m,sendMessage:h,send:T,abortRequest:w}};var oe=require("vue");function Te(o,t=200,e=!1,s=!0,n=!1){return Fe(Ke(t,e,s,n),o)}function Fe(o,t){function e(...s){return new Promise((n,r)=>{Promise.resolve(o(()=>t.apply(this,s),{fn:t,thisArg:this,args:s})).then(n).catch(r)})}return e}var we=()=>{};function Ke(...o){let t=0,e,s=!0,n=we,r,a,l,u,p;!(0,oe.isRef)(o[0])&&typeof o[0]=="object"?{delay:a,trailing:l=!0,leading:u=!0,rejectOnCancel:p=!1}=o[0]:[a,l=!0,u=!0,p=!1]=o;let v=()=>{e&&(clearTimeout(e),e=void 0,n(),n=we)};return x=>{let A=(0,oe.toValue)(a),b=Date.now()-t,m=()=>r=x();return v(),A<=0?(t=Date.now(),m()):(b>A?(t=Date.now(),(u||!s)&&m()):l&&(r=new Promise((h,T)=>{n=p?T:h,e=setTimeout(()=>{t=Date.now(),s=!0,h(m()),v()},Math.max(0,A-b))})),!u&&!e&&(e=setTimeout(()=>s=!0,A)),s=!1,r)}}var je=o=>{let t=o.storage||Z(),e=(0,K.ref)([]),s=new Map,n=new Map,r=(0,K.ref)(null),a=(0,K.computed)(()=>{let i=r.value;if(!i)return null;let c=e.value.find(y=>y.id===i);if(!c)return null;let f=s.get(i);return f?{...c,engine:f}:null}),l=i=>{if(!t?.saveMessages)return;let c=i||r.value,f=e.value.find(S=>S.id===c);if(!f)return;f.updatedAt=Date.now(),t?.saveConversation?.(f);let y=s.get(f.id);y&&t.saveMessages(f.id,y.messages.value)},u=(i,c)=>{if(!o.autoSaveMessages||!t?.saveMessages)return;let f=n.get(i);f&&f();let y=o.autoSaveThrottle??1e3,S=Te(()=>{l(i)},y,!0,!0),w=(0,K.watch)(c.messages,S,{deep:!0});n.set(i,w)},p=i=>{let c=n.get(i);c&&(c(),n.delete(i))};t?.loadConversations&&Promise.resolve(t.loadConversations()).then(i=>{e.value=i}).catch(i=>{console.error("[useConversation] loadConversations failed:",i)});let v=async(i,c)=>{let f=s.get(i);if(f)return f;let y=c?.initialMessages??o.useMessageOptions.initialMessages??[];if(t?.loadMessages)try{y=await t.loadMessages(i)}catch(w){console.error("[useConversation] loadMessages failed:",w)}let S=te({...o.useMessageOptions,...c,initialMessages:y});return s.set(i,S),u(i,S),S};function R(){return Date.now().toString(36)+Math.random().toString(36).substring(2,9)}let x=i=>{let{id:c=R(),title:f,metadata:y,useMessageOptions:S}=i||{},w=Date.now(),q={id:c,title:f,createdAt:w,updatedAt:w,metadata:y};e.value.unshift(q);let I=te({...o.useMessageOptions,...S});return s.set(c,I),u(c,I),t?.saveConversation?.(q),t?.saveMessages?.(c,I.messages.value),r.value=c,a.value},A=i=>{let{excludeId:c}=i||{};s.forEach((f,y)=>{if(c&&y===c)return;f.isProcessing?.value||(p(y),s.delete(y))})};return{conversations:e,activeConversationId:r,activeConversation:a,createConversation:x,switchConversation:async i=>i?r.value===i?a.value:e.value.find(f=>f.id===i)?(await v(i),A({excludeId:i}),r.value=i,a.value):null:null,deleteConversation:async i=>{let c=e.value.findIndex(y=>y.id===i);if(c===-1)return;await s.get(i)?.abortRequest(),p(i),s.delete(i),e.value.splice(c,1),t?.deleteConversation?.(i),r.value===i&&(r.value=null,A())},clear:()=>{e.value.map(c=>c.id).forEach(c=>{t?.deleteConversation?.(c)}),s.forEach(c=>{c.abortRequest()}),n.forEach(c=>{c()}),e.value=[],s.clear(),n.clear(),r.value=null},updateConversationTitle:(i,c)=>{let f=e.value.find(y=>y.id===i);f&&(f.title=c,f.updatedAt=Date.now(),t?.saveConversation?.(f))},saveMessages:l,sendMessage:i=>{a.value?.engine.sendMessage(i)},abortActiveRequest:async()=>{await a.value?.engine.abortRequest()}}};0&&(module.exports={AIClient,EXCLUDE_MODE_REMOVE,ErrorType,IndexedDBStrategy,LocalStorageStrategy,StreamEventType,fallbackRolePlugin,indexedDBStorageStrategyFactory,lengthPlugin,localStorageStrategyFactory,sseStreamToGenerator,thinkingPlugin,toolPlugin,useConversation,useMessage});
|
|
3
|
+
`);r=R.pop()||"";for(let x of R)if(x.trim()!==""){if(x.trim()==="data: [DONE]"){l&&(a=l),t.onDone(a);continue}try{let A=x.match(/^data: (.+)$/m);if(!A)continue;let M=JSON.parse(A[1]);t.onData(M),l=M.choices?.[0]?.finish_reason||void 0}catch(A){console.error("Error parsing SSE message:",A)}}}(r.trim()==="data: [DONE]"||e?.aborted)&&(e?.aborted&&(a="aborted"),t.onDone(a))}catch(d){if(e?.aborted)return;throw d}}function le(o="The operation was aborted"){let t=new Error(o);return t.name="AbortError",t}async function*he(o,t={}){let e=o.body?.getReader();if(!e)throw new Error("ReadableStream not supported");let{signal:n}=t,s=new TextDecoder,r="",a=()=>{e.cancel()};n?.addEventListener("abort",a);try{for(;;){if(n?.aborted)throw le();let l;try{l=await e.read()}catch(x){throw n?.aborted?le():x}let{done:d,value:p}=l;if(d){if(n?.aborted)throw le();return}let v=s.decode(p,{stream:!0});r+=v;let R=r.split(`
|
|
4
|
+
`);r=R.pop()||"";for(let x of R)if(x.trim()!==""&&x.startsWith("data: ")){let A=x.slice(6);if(A==="[DONE]")return;try{yield JSON.parse(A)}catch(M){console.warn("Failed to parse SSE data:",A,M)}}}}finally{n?.removeEventListener("abort",a),e.releaseLock()}}var J=class extends Q{constructor(e){super(e);this.defaultModel="gpt-3.5-turbo";this.baseURL=e.apiUrl||"https://api.openai.com/v1",this.apiKey=e.apiKey||"",e.defaultModel&&(this.defaultModel=e.defaultModel),this.apiKey||console.warn("API key is not provided. Authentication will likely fail.")}async chat(e){try{this.validateRequest(e);let n={model:e.options?.model||this.config.defaultModel||this.defaultModel,messages:e.messages,...e.options,stream:!1},s={method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(n)};this.apiKey&&Object.assign(s.headers,{Authorization:`Bearer ${this.apiKey}`});let r=await fetch(`${this.baseURL}/chat/completions`,s);if(!r.ok){let a=await r.text();throw new Error(`HTTP error! status: ${r.status}, details: ${a}`)}return await r.json()}catch(n){throw ie(n)}}async chatStream(e,n){let{signal:s,...r}=e.options||{};try{this.validateRequest(e);let a={model:e.options?.model||this.config.defaultModel||this.defaultModel,messages:e.messages,...r,stream:!0},l={method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${this.apiKey}`,Accept:"text/event-stream"},body:JSON.stringify(a),signal:s};this.apiKey&&Object.assign(l.headers,{Authorization:`Bearer ${this.apiKey}`});let d=await fetch(`${this.baseURL}/chat/completions`,l);if(!d.ok){let p=await d.text();throw new Error(`HTTP error! status: ${d.status}, details: ${p}`)}await me(d,n,s)}catch(a){if(s?.aborted)return;n.onError(ie(a))}}updateConfig(e){super.updateConfig(e),e.apiUrl&&(this.baseURL=e.apiUrl),e.apiKey&&(this.apiKey=e.apiKey),e.defaultModel&&(this.defaultModel=e.defaultModel)}};var Y=class{constructor(t){this.config=t,this.provider=this.createProvider(t)}createProvider(t){if(t.provider==="custom"&&"providerImplementation"in t)return t.providerImplementation;if(t.provider==="deepseek"){let e={defaultModel:"deepseek-chat",apiUrl:"https://api.deepseek.com/v1"};return new J({...e,...t})}else return new J(t)}async chat(t){return this.provider.chat(t)}async chatStream(t,e){let n={...t,options:{...t.options,stream:!0}};return this.provider.chatStream(n,e)}getConfig(){return{...this.config}}updateConfig(t){this.config={...this.config,...t},t.provider&&t.provider!==this.config.provider?this.provider=this.createProvider(this.config):this.provider.updateConfig(this.config)}};var ye=require("vue");function z(o,t=new WeakSet){if(o==null||typeof o!="object")return o;if(t.has(o))return Array.isArray(o)?[]:{};t.add(o);try{let e=(0,ye.toRaw)(o);if(Array.isArray(e))return e.map(s=>z(s,t));if(e instanceof Date||e instanceof RegExp||e instanceof ArrayBuffer||e instanceof Blob)return e;let n={};for(let s in e){if(typeof s=="symbol")continue;let r=Object.getOwnPropertyDescriptor(e,s);if(!r||r.get||r.set)continue;let a=e[s];typeof a!="function"&&typeof a!="symbol"&&(n[s]=z(a,t))}return n}catch(e){return console.warn("unwrapProxy error:",e),Array.isArray(o)?[]:{}}}var Z=o=>o.map(t=>{let{renderContent:e,...n}=t;if(!Array.isArray(e))return t;let s=e.filter(a=>a.type==="collapsible-text"),r=e.filter(a=>a.type==="markdown"||a.type==="text");return s.length>0&&(n.reasoning_content=s.map(a=>a.content).join("")),r.length>0&&(n.content=r.map(a=>a.content).join("")),n});var X=o=>{let t=localStorage.getItem(o);return t?JSON.parse(t):[]},W=class{constructor(t="tiny-robot-ai-conversations"){this.storageKey=t}saveConversation(t){try{let e=X(this.storageKey),n=e.findIndex(s=>s.id===t.id);n!==-1?Object.assign(e[n],t):e.unshift({...t,messages:[]}),localStorage.setItem(this.storageKey,JSON.stringify(e))}catch(e){console.error("\u4FDD\u5B58\u4F1A\u8BDD\u5931\u8D25:",e)}}loadConversations(){try{return X(this.storageKey).map(e=>({id:e.id,title:e.title,createdAt:e.createdAt,updatedAt:e.updatedAt,metadata:e.metadata}))}catch(t){return console.error("\u52A0\u8F7D\u4F1A\u8BDD\u5931\u8D25:",t),[]}}saveMessages(t,e){try{let n=X(this.storageKey),s=n.findIndex(r=>r.id===t);s!==-1&&(n[s].messages=e),localStorage.setItem(this.storageKey,JSON.stringify(n))}catch(n){console.error("\u4FDD\u5B58\u4F1A\u8BDD\u6D88\u606F\u5931\u8D25:",n)}}loadMessages(t){try{let n=X(this.storageKey).find(r=>r.id===t);return Z(n?.messages||[])}catch(e){return console.error("\u52A0\u8F7D\u4F1A\u8BDD\u6D88\u606F\u5931\u8D25:",e),[]}}deleteConversation(t){let e=X(this.storageKey),n=e.findIndex(s=>s.id===t);n!==-1&&e.splice(n,1),localStorage.setItem(this.storageKey,JSON.stringify(e))}};var Ce=require("idb");var H=class{constructor(t="tiny-robot-ai-db",e=3){this.db=null;this.dbName=t,this.dbVersion=e}async getDB(){return this.db||(this.db=await(0,Ce.openDB)(this.dbName,this.dbVersion,{upgrade(t){t.objectStoreNames.contains("conversations")||t.createObjectStore("conversations",{keyPath:"id"}).createIndex("by-updated","updatedAt"),t.objectStoreNames.contains("messages")||t.createObjectStore("messages",{keyPath:"conversationId"})}})),this.db}async loadConversations(){try{return(await(await this.getDB()).getAllFromIndex("conversations","by-updated")).reverse()}catch(t){return console.error("\u52A0\u8F7D\u4F1A\u8BDD\u5931\u8D25:",t),[]}}async loadMessages(t){try{let n=await(await this.getDB()).get("messages",t);return n?Z(n.messages):[]}catch(e){return console.error("\u52A0\u8F7D\u4F1A\u8BDD\u6D88\u606F\u5931\u8D25:",e),[]}}async saveConversation(t){try{let e=await this.getDB(),n=z(t);await e.put("conversations",n)}catch(e){throw console.error("\u4FDD\u5B58\u4F1A\u8BDD\u5931\u8D25:",e),e}}async saveMessages(t,e){try{let n=await this.getDB(),s=z(e);await n.put("messages",{conversationId:t,messages:s})}catch(n){throw console.error("\u4FDD\u5B58\u4F1A\u8BDD\u6D88\u606F\u5931\u8D25:",n),n}}async deleteConversation(t){try{let e=await this.getDB();await e.delete("conversations",t),await e.delete("messages",t)}catch(e){throw console.error("\u5220\u9664\u4F1A\u8BDD\u5931\u8D25:",e),e}}};function ee(o={}){return new W(o.key||"tiny-robot-ai-conversations")}function ve(o={}){return new H(o.dbName||"tiny-robot-ai-db",o.dbVersion||1)}var j=require("vue");var U=require("vue");var ce=(o={})=>{let{fallbackRole:t="assistant",...e}=o;return{name:"fallbackRole",...e,onBeforeRequest(n){let{requestBody:s,messages:r}=n;return s.messages=r.map(a=>({...a,role:a.role||t})),e.onBeforeRequest?.(n)}}};var ue=(o={})=>{let{continueContent:t="Please continue with your previous answer.",...e}=o;return{name:"length",...e,onAfterRequest:async n=>{let{lastChoice:s,appendMessage:r,requestNext:a}=n;return s?.finish_reason==="length"&&(r({role:"user",content:t}),a()),e.onAfterRequest?.(n)}}};var de=(o={})=>({name:"thinking",...o,onCompletionChunk(t){let{choice:e,currentMessage:n}=t,r=typeof(e?.message?.reasoning_content||e?.delta?.reasoning_content)=="string";return n.state?n.state.thinking=r:n.state={thinking:r},o.onCompletionChunk?.(t)},onTurnEnd(t){let e=t.currentTurn.slice(-1)[0];return e?.state&&(e.state.thinking=void 0),o.onTurnEnd?.(t)}});var we=require("vue");var G=class extends Error{constructor(t){super(t),this.name="AbortError"}};function qe(o){if(o.aborted)return{promise:Promise.reject(new G(String(o.reason??"Aborted"))),cleanup:()=>{}};let t=null;return{promise:new Promise((s,r)=>{t=()=>{r(new G(String(o.reason??"Aborted")))},o.addEventListener("abort",t,{once:!0})}),cleanup:()=>{t&&(o.removeEventListener("abort",t),t=null)}}}function Re(o,t){let{promise:e,cleanup:n}=qe(t);return Promise.race([o,e]).finally(n)}function xe(o,t){let e={};for(let n in o)t.includes(n)&&(e[n]=o[n]);return e}function Ae(o,t){let e={};for(let n in o)t.includes(n)||(e[n]=o[n]);return e}async function*te(o){if(Me(o)){yield*o;return}let t=await o;if(Me(t)){yield*t;return}yield t}function Me(o){return o&&typeof o=="object"&&typeof o[Symbol.asyncIterator]=="function"}var ge=o=>typeof o=="object"&&o!==null,be=o=>ge(o)&&typeof o.index=="number",V=(o,t)=>{for(let[e,n]of Object.entries(t)){let s=o[e];if(s)if(typeof s=="string"&&typeof n=="string")e==="type"&&s||(o[e]=s+n);else if(Array.isArray(s)&&Array.isArray(n))if(s.every(r=>be(r))&&n.every(r=>be(r))){let r=new Map(s.map(p=>[p.index,p])),a=new Map(n.map(p=>[p.index,p]));for(let[p,v]of a)if(r.has(p)){let R=r.get(p);r.set(p,V(R,v))}else r.set(p,v);let l=Math.max(...Array.from(r.keys()),-1)+1,d=l>s.length?Array.from({length:l}):s;for(let[p,v]of r)d[p]=v;o[e]=d}else o[e]=[...s,...n];else ge(s)&&ge(n)&&(o[e]=V(s,n));else o[e]=n}return o};function Be(o,t){let e=[];for(let n=0;n<o.length;n++){let s=o[n];if(s.role==="assistant"&&s.tool_calls&&s.tool_calls.length>0){let r=new Set(s.tool_calls.map(d=>d.id)),a=new Set;for(let d=n+1;d<o.length;d++){let p=o[d];p.role==="tool"&&p.tool_call_id&&r.has(p.tool_call_id)&&a.add(p.tool_call_id)}let l=s.tool_calls.map(d=>d.id).filter(d=>!a.has(d));l.length>0&&e.push({insertAfterIndex:n,missingToolCallIds:l})}}for(let n=e.length-1;n>=0;n--){let{insertAfterIndex:s,missingToolCallIds:r}=e[n],a=r.map(l=>({role:"tool",tool_call_id:l,content:t}));o.splice(s+1,0,...a)}}var Te="remove";function Ne(o,t,e,n){let s=o.filter(a=>a[e]),r=new Set(s.flatMap(a=>a.tool_calls?.map(l=>l.id)??[]));if(t===Te)for(let a=o.length-1;a>=0;a--){let l=o[a];(l[e]||l[n]||l.tool_call_id&&r.has(l.tool_call_id))&&o.splice(a,1)}else if(t===!0)for(let a of o)(a[e]||a.tool_call_id&&r.has(a.tool_call_id))&&(a[n]=!0,delete a[e])}var Fe=o=>{let{getTools:t,beforeCallTools:e,callTool:n,onToolCallStart:s,onToolCallEnd:r,toolCallCancelledContent:a="Tool call cancelled.",toolCallFailedContent:l="Tool call failed.",autoFillMissingToolMessages:d=!1,excludeToolMessagesNextTurn:p=!1,...v}=o,R=Symbol("doNotSendNextTurn"),x=Symbol("doNotSend"),A=(...m)=>{let[h,{primaryMessage:T}]=m;T.state.toolCall[h.id].status="running",s?.(...m)},M=(...m)=>{let[h,{status:T,primaryMessage:O}]=m;O.state.toolCall[h.id].status=T,r?.(...m)};return{name:"tool",...v,onTurnStart:m=>{let{messages:h}=m;return d&&Be(h,a),p&&Ne(h,p,R,x),v.onTurnStart?.(m)},onBeforeRequest:async m=>{let{messages:h,requestBody:T}=m;p===!0&&(T.messages=h.filter(E=>!E[x]));let O=await t?.();return O&&O.length>0&&(T.tools=O),v.onBeforeRequest?.(m)},onAfterRequest:async m=>{let{currentMessage:h,lastChoice:T,appendMessage:O,abortSignal:E,setRequestState:i,requestNext:c}=m;if(T?.finish_reason!=="tool_calls"||!h.tool_calls?.length)return;p&&(h[R]=!0),i("processing","calling-tools"),await e?.(h.tool_calls,{...m,currentMessage:h});let f=h.tool_calls.map(async y=>{let S=Math.floor(Date.now()/1e3),w=(0,we.reactive)({role:"tool",tool_call_id:y.id,content:"",metadata:{createdAt:S,updatedAt:S}});O(w);let q={...m,primaryMessage:h,toolMessage:w};A(y,q);try{let k=n(y,q),N=te(k);for await(let u of N){if(typeof u=="string")w.content+=u;else{let g={};try{g=JSON.parse(w.content||"{}")}catch(b){console.warn(b)}w.content=JSON.stringify(V(g,u))}w.metadata.updatedAt=Math.floor(Date.now()/1e3)}M(y,{...q,status:"success"})}catch(k){let N=k instanceof Error?k:new Error(String(k));if(E.aborted){M(y,{...q,status:"cancelled",error:N});return}console.error(k),w.content.length===0&&(w.content=l),M(y,{...q,status:"failed",error:N})}});return await Promise.all(f),c(),v.onAfterRequest?.(m)},onCompletionChunk:m=>{var T,O,E;let{currentMessage:h}=m;if(Array.isArray(h.tool_calls))for(let i of h.tool_calls)h.state?.toolCall?.[i.id]?.status||(h.state??(h.state={}),(T=h.state).toolCall??(T.toolCall={}),(O=h.state.toolCall)[E=i.id]??(O[E]={}));return v.onCompletionChunk?.(m)}}};var Ke=o=>{let t=[];for(let e of o){if(e.name){let n=t.findIndex(s=>s.name===e.name);n!==-1&&t.splice(n,1)}t.push(e)}return t},oe=o=>{let{initialMessages:t=[],requestMessageFields:e=[],requestMessageFieldsExclude:n=["state","metadata","loading"],plugins:s=[],onCompletionChunk:r}=o,a=(0,U.ref)("idle"),l=(0,U.ref)(void 0),d=(0,U.ref)(t),p=(0,U.ref)(o.responseProvider),v=null,R=[],x={},A=[ce(),de(),ue()],M=Ke(A.concat(s)),m=(0,U.computed)(()=>a.value==="processing"),h=async u=>{if(!u||!u.trim()){console.warn("Cannot send empty message");return}if(m.value){console.warn("Cannot send message while processing is in progress");return}let g=Math.floor(Date.now()/1e3);d.value.push({role:"user",content:u.trim(),metadata:{createdAt:g,updatedAt:g}}),R.push(d.value[d.value.length-1]),await w()},T=async(...u)=>{if(m.value){console.warn("Cannot send message while processing is in progress");return}d.value.push(...u),R.push(...u),await w()},O=u=>{let g=u;return e.length&&(g=g.map(b=>xe(b,e))),n.length&&(g=g.map(b=>Ae(b,n))),g},E=(u,g)=>{a.value=u,u==="processing"?l.value=g||"requesting":l.value=void 0},i=u=>{Object.assign(x,u)},c=u=>({messages:d.value,currentTurn:R,requestState:a.value,processingState:l.value,plugins:M,abortSignal:u,setRequestState:E,customContext:x,setCustomContext:i}),f=(u,g)=>typeof u.disabled=="function"?u.disabled(g):!!u.disabled,y=u=>!u||Object.keys(u).length===0?!1:Object.values(u).some(g=>!!g),S=async(u,g)=>{E("processing","requesting");let b=new Proxy({messages:O(d.value)},{set(D,P,F){return P==="messages"?(D.messages=O(F),!0):(D[P]=F,!0)}}),I=c(g);for(let D of M.filter(P=>!f(P,I)))await D.onBeforeRequest?.({...I,requestBody:b});let C=(0,U.reactive)({role:"",content:"",loading:!0});N(C);let _,se=u(b,g),B=te(se);for await(let D of B){E("processing","completing"),C.loading&&(C.loading=void 0);let P=D.choices?.find(L=>L.index===0);if(P){_=P;let L=()=>{C.metadata||(C.metadata={});let{created:$,...Ee}=D;C.metadata.createdAt=$,C.metadata.updatedAt=Math.floor(Date.now()/1e3),Object.assign(C.metadata,Ee);let re=y(P.delta)?P.delta:P.message;re||(re=P.delta||P.message||{}),V(C,re)};if(r){let $=c(g);r({...$,chunk:D,choice:P,currentMessage:C},L)}else L()}let F=c(g);for(let L of M.filter($=>!f($,F)))L.onCompletionChunk?.({...F,abortSignal:g,chunk:D,choice:P,currentMessage:C})}await k(C,u,g,_)},w=async()=>{let u=new AbortController;v=u,x={};try{E("processing","requesting");let g=c(u.signal);for(let C of M.filter(_=>!f(_,g)))await C.onTurnStart?.(g);let b=p.value;try{await S(b,u.signal),E("completed")}catch(C){if(u.signal.aborted||C instanceof G||C instanceof Error&&C.name==="AbortError")E("aborted");else throw C}let I=c(u.signal);for(let C of M.filter(_=>!f(_,I)))await C.onTurnEnd?.(I)}catch(g){E("error");let b=!1,I=c(u.signal);for(let C of M.filter(_=>!f(_,I)))b=!0,C.onError?.({...I,error:g});if(!b)throw g}finally{let g=c(u.signal);for(let b of M.filter(I=>!f(I,g)))try{b.onFinally?.(g)}catch(I){console.error(`Error in onFinally hook for plugin ${b.name||"Anonymous"}:`,I)}v=null,R.slice(-1)[0]&&(R.slice(-1)[0].loading=void 0),R=[]}},q=async()=>{v?.abort(),m.value&&await new Promise(u=>{let g=(0,U.watch)(m,b=>{b||(g(),u())},{immediate:!0})})},k=async(u,g,b,I)=>{let C=!1,_=c(b),se=M.filter(B=>!f(B,_)).map(B=>{if(!B.onAfterRequest)return null;let D=F=>{N(F)},P=()=>{C=!0};return B.onAfterRequest({..._,currentMessage:u,lastChoice:I,appendMessage:D,requestNext:P})}).filter(B=>B!==null);await Re(Promise.all(se),b),C&&await S(g,b)},N=u=>{let g=Array.isArray(u)?u:[u];d.value.push(...g),R.push(...g)};return{requestState:a,processingState:l,messages:d,responseProvider:p,isProcessing:m,sendMessage:h,send:T,abortRequest:q}};var ne=require("vue");function Pe(o,t=200,e=!1,n=!0,s=!1){return je(Le(t,e,n,s),o)}function je(o,t){function e(...n){return new Promise((s,r)=>{Promise.resolve(o(()=>t.apply(this,n),{fn:t,thisArg:this,args:n})).then(s).catch(r)})}return e}var Se=()=>{};function Le(...o){let t=0,e,n=!0,s=Se,r,a,l,d,p;!(0,ne.isRef)(o[0])&&typeof o[0]=="object"?{delay:a,trailing:l=!0,leading:d=!0,rejectOnCancel:p=!1}=o[0]:[a,l=!0,d=!0,p=!1]=o;let v=()=>{e&&(clearTimeout(e),e=void 0,s(),s=Se)};return x=>{let A=(0,ne.toValue)(a),M=Date.now()-t,m=()=>r=x();return v(),A<=0?(t=Date.now(),m()):(M>A?(t=Date.now(),(d||!n)&&m()):l&&(r=new Promise((h,T)=>{s=p?T:h,e=setTimeout(()=>{t=Date.now(),n=!0,h(m()),v()},Math.max(0,A-M))})),!d&&!e&&(e=setTimeout(()=>n=!0,A)),n=!1,r)}}var We=o=>{let t=o.storage||ee(),e=(0,j.ref)([]),n=new Map,s=new Map,r=(0,j.ref)(null),a=(0,j.computed)(()=>{let i=r.value;if(!i)return null;let c=e.value.find(y=>y.id===i);if(!c)return null;let f=n.get(i);return f?{...c,engine:f}:null}),l=i=>{if(!t?.saveMessages)return;let c=i||r.value,f=e.value.find(S=>S.id===c);if(!f)return;f.updatedAt=Date.now(),t?.saveConversation?.(f);let y=n.get(f.id);y&&t.saveMessages(f.id,y.messages.value)},d=(i,c)=>{if(!o.autoSaveMessages||!t?.saveMessages)return;let f=s.get(i);f&&f();let y=o.autoSaveThrottle??1e3,S=Pe(()=>{l(i)},y,!0,!0),w=(0,j.watch)(c.messages,S,{deep:!0});s.set(i,w)},p=i=>{let c=s.get(i);c&&(c(),s.delete(i))};t?.loadConversations&&Promise.resolve(t.loadConversations()).then(i=>{e.value=i}).catch(i=>{console.error("[useConversation] loadConversations failed:",i)});let v=async(i,c)=>{let f=n.get(i);if(f)return f;let y=c?.initialMessages??o.useMessageOptions.initialMessages??[];if(t?.loadMessages)try{y=await t.loadMessages(i)}catch(w){console.error("[useConversation] loadMessages failed:",w)}let S=oe({...o.useMessageOptions,...c,initialMessages:y});return n.set(i,S),d(i,S),S};function R(){return Date.now().toString(36)+Math.random().toString(36).substring(2,9)}let x=i=>{let{id:c=R(),title:f,metadata:y,useMessageOptions:S}=i||{},w=Date.now(),q={id:c,title:f,createdAt:w,updatedAt:w,metadata:y};e.value.unshift(q);let k=oe({...o.useMessageOptions,...S});return n.set(c,k),d(c,k),t?.saveConversation?.(q),t?.saveMessages?.(c,k.messages.value),r.value=c,a.value},A=i=>{let{excludeId:c}=i||{};n.forEach((f,y)=>{if(c&&y===c)return;f.isProcessing?.value||(p(y),n.delete(y))})};return{conversations:e,activeConversationId:r,activeConversation:a,createConversation:x,switchConversation:async i=>i?r.value===i?a.value:e.value.find(f=>f.id===i)?(await v(i),A({excludeId:i}),r.value=i,a.value):null:null,deleteConversation:async i=>{let c=e.value.findIndex(y=>y.id===i);if(c===-1)return;await n.get(i)?.abortRequest(),p(i),n.delete(i),e.value.splice(c,1),t?.deleteConversation?.(i),r.value===i&&(r.value=null,A())},clear:()=>{e.value.map(c=>c.id).forEach(c=>{t?.deleteConversation?.(c)}),n.forEach(c=>{c.abortRequest()}),s.forEach(c=>{c()}),e.value=[],n.clear(),s.clear(),r.value=null},updateConversationTitle:(i,c)=>{let f=e.value.find(y=>y.id===i);f&&(f.title=c,f.updatedAt=Date.now(),t?.saveConversation?.(f))},saveMessages:l,sendMessage:i=>{a.value?.engine.sendMessage(i)},abortActiveRequest:async()=>{await a.value?.engine.abortRequest()}}};0&&(module.exports={AIClient,EXCLUDE_MODE_REMOVE,ErrorType,IndexedDBStrategy,LocalStorageStrategy,StreamEventType,fallbackRolePlugin,indexedDBStorageStrategyFactory,lengthPlugin,localStorageStrategyFactory,sseStreamToGenerator,thinkingPlugin,toolPlugin,useConversation,useMessage});
|
package/dist/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
var
|
|
1
|
+
var z=class{constructor(t){this.config=t}updateConfig(t){this.config={...this.config,...t}}getConfig(){return{...this.config}}validateRequest(t){if(!t.messages||!Array.isArray(t.messages)||t.messages.length===0)throw new Error("\u8BF7\u6C42\u5FC5\u987B\u5305\u542B\u81F3\u5C11\u4E00\u6761\u6D88\u606F");for(let e of t.messages)if(!e.role||!e.content)throw new Error("\u6BCF\u6761\u6D88\u606F\u5FC5\u987B\u5305\u542B\u89D2\u8272\u548C\u5185\u5BB9")}};var Me=(l=>(l.NETWORK_ERROR="network_error",l.AUTHENTICATION_ERROR="authentication_error",l.RATE_LIMIT_ERROR="rate_limit_error",l.SERVER_ERROR="server_error",l.MODEL_ERROR="model_error",l.TIMEOUT_ERROR="timeout_error",l.UNKNOWN_ERROR="unknown_error",l))(Me||{}),be=(n=>(n.DATA="data",n.ERROR="error",n.DONE="done",n))(be||{});function F(o){return{type:o.type||"unknown_error",message:o.message||"\u672A\u77E5\u9519\u8BEF",statusCode:o.statusCode,originalError:o.originalError}}function te(o){if(!o.response)return F({type:"network_error",message:"\u7F51\u7EDC\u8FDE\u63A5\u9519\u8BEF\uFF0C\u8BF7\u68C0\u67E5\u60A8\u7684\u7F51\u7EDC\u8FDE\u63A5",originalError:o});if(o.response){let{status:t,data:e}=o.response;return t===401||t===403?F({type:"authentication_error",message:"\u8EAB\u4EFD\u9A8C\u8BC1\u5931\u8D25\uFF0C\u8BF7\u68C0\u67E5\u60A8\u7684API\u5BC6\u94A5",statusCode:t,originalError:o}):t===429?F({type:"rate_limit_error",message:"\u8D85\u51FAAPI\u8C03\u7528\u9650\u5236\uFF0C\u8BF7\u7A0D\u540E\u518D\u8BD5",statusCode:t,originalError:o}):t>=500?F({type:"server_error",message:"\u670D\u52A1\u5668\u9519\u8BEF\uFF0C\u8BF7\u7A0D\u540E\u518D\u8BD5",statusCode:t,originalError:o}):F({type:"unknown_error",message:e?.error?.message||`\u8BF7\u6C42\u5931\u8D25\uFF0C\u72B6\u6001\u7801: ${t}`,statusCode:t,originalError:o})}return o.code==="ECONNABORTED"?F({type:"timeout_error",message:"\u8BF7\u6C42\u8D85\u65F6\uFF0C\u8BF7\u7A0D\u540E\u518D\u8BD5",originalError:o}):F({type:"unknown_error",message:o.message||"\u53D1\u751F\u672A\u77E5\u9519\u8BEF",originalError:o})}async function ie(o,t,e){let n=o.body?.getReader();if(!n)throw new Error("Response body is null");let s=new TextDecoder,r="",a,l;e&&e.addEventListener("abort",()=>{n.cancel().catch(d=>console.error("Error cancelling reader:",d))},{once:!0});try{for(;;){if(e?.aborted){await n.cancel();break}let{done:d,value:p}=await n.read();if(d)break;let v=s.decode(p,{stream:!0});r+=v;let R=r.split(`
|
|
2
2
|
|
|
3
|
-
`);r=R.pop()||"";for(let x of R)if(x.trim()!==""){if(x.trim()==="data: [DONE]"){l&&(a=l),t.onDone(a);continue}try{let A=x.match(/^data: (.+)$/m);if(!A)continue;let
|
|
4
|
-
`);r=R.pop()||"";for(let x of R)if(x.trim()!==""&&x.startsWith("data: ")){let A=x.slice(6);if(A==="[DONE]")return;try{yield JSON.parse(A)}catch(b){console.warn("Failed to parse SSE data:",A,b)}}}}finally{s?.removeEventListener("abort",a),e.releaseLock()}}var W=class extends J{constructor(e){super(e);this.defaultModel="gpt-3.5-turbo";this.baseURL=e.apiUrl||"https://api.openai.com/v1",this.apiKey=e.apiKey||"",e.defaultModel&&(this.defaultModel=e.defaultModel),this.apiKey||console.warn("API key is not provided. Authentication will likely fail.")}async chat(e){try{this.validateRequest(e);let s={model:e.options?.model||this.config.defaultModel||this.defaultModel,messages:e.messages,...e.options,stream:!1},n={method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(s)};this.apiKey&&Object.assign(n.headers,{Authorization:`Bearer ${this.apiKey}`});let r=await fetch(`${this.baseURL}/chat/completions`,n);if(!r.ok){let a=await r.text();throw new Error(`HTTP error! status: ${r.status}, details: ${a}`)}return await r.json()}catch(s){throw Z(s)}}async chatStream(e,s){let{signal:n,...r}=e.options||{};try{this.validateRequest(e);let a={model:e.options?.model||this.config.defaultModel||this.defaultModel,messages:e.messages,...r,stream:!0},l={method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${this.apiKey}`,Accept:"text/event-stream"},body:JSON.stringify(a),signal:n};this.apiKey&&Object.assign(l.headers,{Authorization:`Bearer ${this.apiKey}`});let u=await fetch(`${this.baseURL}/chat/completions`,l);if(!u.ok){let p=await u.text();throw new Error(`HTTP error! status: ${u.status}, details: ${p}`)}await re(u,s,n)}catch(a){if(n?.aborted)return;s.onError(Z(a))}}updateConfig(e){super.updateConfig(e),e.apiUrl&&(this.baseURL=e.apiUrl),e.apiKey&&(this.apiKey=e.apiKey),e.defaultModel&&(this.defaultModel=e.defaultModel)}};var te=class{constructor(t){this.config=t,this.provider=this.createProvider(t)}createProvider(t){if(t.provider==="custom"&&"providerImplementation"in t)return t.providerImplementation;if(t.provider==="deepseek"){let e={defaultModel:"deepseek-chat",apiUrl:"https://api.deepseek.com/v1"};return new W({...e,...t})}else return new W(t)}async chat(t){return this.provider.chat(t)}async chatStream(t,e){let s={...t,options:{...t.options,stream:!0}};return this.provider.chatStream(s,e)}getConfig(){return{...this.config}}updateConfig(t){this.config={...this.config,...t},t.provider&&t.provider!==this.config.provider?this.provider=this.createProvider(this.config):this.provider.updateConfig(this.config)}};import{toRaw as be}from"vue";function H(o,t=new WeakSet){if(o==null||typeof o!="object")return o;if(t.has(o))return Array.isArray(o)?[]:{};t.add(o);try{let e=be(o);if(Array.isArray(e))return e.map(n=>H(n,t));if(e instanceof Date||e instanceof RegExp||e instanceof ArrayBuffer||e instanceof Blob)return e;let s={};for(let n in e){if(typeof n=="symbol")continue;let r=Object.getOwnPropertyDescriptor(e,n);if(!r||r.get||r.set)continue;let a=e[n];typeof a!="function"&&typeof a!="symbol"&&(s[n]=H(a,t))}return s}catch(e){return console.warn("unwrapProxy error:",e),Array.isArray(o)?[]:{}}}var z=o=>o.map(t=>{let{renderContent:e,...s}=t;if(!Array.isArray(e))return t;let n=e.filter(a=>a.type==="collapsible-text"),r=e.filter(a=>a.type==="markdown"||a.type==="text");return n.length>0&&(s.reasoning_content=n.map(a=>a.content).join("")),r.length>0&&(s.content=r.map(a=>a.content).join("")),s});var G=o=>{let t=localStorage.getItem(o);return t?JSON.parse(t):[]},V=class{constructor(t="tiny-robot-ai-conversations"){this.storageKey=t}saveConversation(t){try{let e=G(this.storageKey),s=e.findIndex(n=>n.id===t.id);s!==-1?Object.assign(e[s],t):e.unshift({...t,messages:[]}),localStorage.setItem(this.storageKey,JSON.stringify(e))}catch(e){console.error("\u4FDD\u5B58\u4F1A\u8BDD\u5931\u8D25:",e)}}loadConversations(){try{return G(this.storageKey).map(e=>({id:e.id,title:e.title,createdAt:e.createdAt,updatedAt:e.updatedAt,metadata:e.metadata}))}catch(t){return console.error("\u52A0\u8F7D\u4F1A\u8BDD\u5931\u8D25:",t),[]}}saveMessages(t,e){try{let s=G(this.storageKey),n=s.findIndex(r=>r.id===t);n!==-1&&(s[n].messages=e),localStorage.setItem(this.storageKey,JSON.stringify(s))}catch(s){console.error("\u4FDD\u5B58\u4F1A\u8BDD\u6D88\u606F\u5931\u8D25:",s)}}loadMessages(t){try{let s=G(this.storageKey).find(r=>r.id===t);return z(s?.messages||[])}catch(e){return console.error("\u52A0\u8F7D\u4F1A\u8BDD\u6D88\u606F\u5931\u8D25:",e),[]}}deleteConversation(t){let e=G(this.storageKey),s=e.findIndex(n=>n.id===t);s!==-1&&e.splice(s,1),localStorage.setItem(this.storageKey,JSON.stringify(e))}};import{openDB as Re}from"idb";var $=class{constructor(t="tiny-robot-ai-db",e=3){this.db=null;this.dbName=t,this.dbVersion=e}async getDB(){return this.db||(this.db=await Re(this.dbName,this.dbVersion,{upgrade(t){t.objectStoreNames.contains("conversations")||t.createObjectStore("conversations",{keyPath:"id"}).createIndex("by-updated","updatedAt"),t.objectStoreNames.contains("messages")||t.createObjectStore("messages",{keyPath:"conversationId"})}})),this.db}async loadConversations(){try{return(await(await this.getDB()).getAllFromIndex("conversations","by-updated")).reverse()}catch(t){return console.error("\u52A0\u8F7D\u4F1A\u8BDD\u5931\u8D25:",t),[]}}async loadMessages(t){try{let s=await(await this.getDB()).get("messages",t);return s?z(s.messages):[]}catch(e){return console.error("\u52A0\u8F7D\u4F1A\u8BDD\u6D88\u606F\u5931\u8D25:",e),[]}}async saveConversation(t){try{let e=await this.getDB(),s=H(t);await e.put("conversations",s)}catch(e){throw console.error("\u4FDD\u5B58\u4F1A\u8BDD\u5931\u8D25:",e),e}}async saveMessages(t,e){try{let s=await this.getDB(),n=H(e);await s.put("messages",{conversationId:t,messages:n})}catch(s){throw console.error("\u4FDD\u5B58\u4F1A\u8BDD\u6D88\u606F\u5931\u8D25:",s),s}}async deleteConversation(t){try{let e=await this.getDB();await e.delete("conversations",t),await e.delete("messages",t)}catch(e){throw console.error("\u5220\u9664\u4F1A\u8BDD\u5931\u8D25:",e),e}}};function oe(o={}){return new V(o.key||"tiny-robot-ai-conversations")}function xe(o={}){return new $(o.dbName||"tiny-robot-ai-db",o.dbVersion||1)}import{computed as Be,ref as he,watch as Ne}from"vue";import{computed as Ee,reactive as Oe,ref as Q,watch as Ie}from"vue";var ae=(o={})=>{let{fallbackRole:t="assistant",...e}=o;return{name:"fallbackRole",...e,onBeforeRequest(s){let{requestBody:n,messages:r}=s;return n.messages=r.map(a=>({...a,role:a.role||t})),e.onBeforeRequest?.(s)}}};var ie=(o={})=>{let{continueContent:t="Please continue with your previous answer.",...e}=o;return{name:"length",...e,onAfterRequest:async s=>{let{lastChoice:n,appendMessage:r,requestNext:a}=s;return n?.finish_reason==="length"&&(r({role:"user",content:t}),a()),e.onAfterRequest?.(s)}}};var le=(o={})=>({name:"thinking",...o,onCompletionChunk(t){let{choice:e,currentMessage:s}=t,r=typeof(e?.message?.reasoning_content||e?.delta?.reasoning_content)=="string";return s.state?s.state.thinking=r:s.state={thinking:r},o.onCompletionChunk?.(t)},onTurnEnd(t){let e=t.currentTurn.slice(-1)[0];return e?.state&&(e.state.thinking=void 0),o.onTurnEnd?.(t)}});import{reactive as we}from"vue";var K=class extends Error{constructor(t){super(t),this.name="AbortError"}};function Ae(o){if(o.aborted)return{promise:Promise.reject(new K(String(o.reason??"Aborted"))),cleanup:()=>{}};let t=null;return{promise:new Promise((n,r)=>{t=()=>{r(new K(String(o.reason??"Aborted")))},o.addEventListener("abort",t,{once:!0})}),cleanup:()=>{t&&(o.removeEventListener("abort",t),t=null)}}}function de(o,t){let{promise:e,cleanup:s}=Ae(t);return Promise.race([o,e]).finally(s)}function ge(o,t){let e={};for(let s in o)t.includes(s)&&(e[s]=o[s]);return e}function pe(o,t){let e={};for(let s in o)t.includes(s)||(e[s]=o[s]);return e}async function*X(o){if(ce(o)){yield*o;return}let t=await o;if(ce(t)){yield*t;return}yield t}function ce(o){return o&&typeof o=="object"&&typeof o[Symbol.asyncIterator]=="function"}var se=o=>typeof o=="object"&&o!==null,ue=o=>se(o)&&typeof o.index=="number",j=(o,t)=>{for(let[e,s]of Object.entries(t)){let n=o[e];if(n)if(typeof n=="string"&&typeof s=="string")e==="type"&&n||(o[e]=n+s);else if(Array.isArray(n)&&Array.isArray(s))if(n.every(r=>ue(r))&&s.every(r=>ue(r))){let r=new Map(n.map(p=>[p.index,p])),a=new Map(s.map(p=>[p.index,p]));for(let[p,v]of a)if(r.has(p)){let R=r.get(p);r.set(p,j(R,v))}else r.set(p,v);let l=Math.max(...Array.from(r.keys()),-1)+1,u=l>n.length?Array.from({length:l}):n;for(let[p,v]of r)u[p]=v;o[e]=u}else o[e]=[...n,...s];else se(n)&&se(s)&&(o[e]=j(n,s));else o[e]=s}return o};function Te(o,t){let e=[];for(let s=0;s<o.length;s++){let n=o[s];if(n.role==="assistant"&&n.tool_calls&&n.tool_calls.length>0){let r=new Set(n.tool_calls.map(u=>u.id)),a=new Set;for(let u=s+1;u<o.length;u++){let p=o[u];p.role==="tool"&&p.tool_call_id&&r.has(p.tool_call_id)&&a.add(p.tool_call_id)}let l=n.tool_calls.map(u=>u.id).filter(u=>!a.has(u));l.length>0&&e.push({insertAfterIndex:s,missingToolCallIds:l})}}for(let s=e.length-1;s>=0;s--){let{insertAfterIndex:n,missingToolCallIds:r}=e[s],a=r.map(l=>({role:"tool",tool_call_id:l,content:t}));o.splice(n+1,0,...a)}}var Se="remove";function Pe(o,t,e,s){let n=o.filter(a=>a[e]),r=new Set(n.flatMap(a=>a.tool_calls?.map(l=>l.id)??[]));if(t===Se)for(let a=o.length-1;a>=0;a--){let l=o[a];(l[e]||l[s]||l.tool_call_id&&r.has(l.tool_call_id))&&o.splice(a,1)}else if(t===!0)for(let a of o)(a[e]||a.tool_call_id&&r.has(a.tool_call_id))&&(a[s]=!0,delete a[e])}var mt=o=>{let{getTools:t,beforeCallTools:e,callTool:s,onToolCallStart:n,onToolCallEnd:r,toolCallCancelledContent:a="Tool call cancelled.",toolCallFailedContent:l="Tool call failed.",autoFillMissingToolMessages:u=!1,excludeToolMessagesNextTurn:p=!1,...v}=o,R=Symbol("doNotSendNextTurn"),x=Symbol("doNotSend"),A=(...m)=>{let[h,{primaryMessage:T}]=m;T.state.toolCall[h.id].status="running",n?.(...m)},b=(...m)=>{let[h,{status:T,primaryMessage:O}]=m;O.state.toolCall[h.id].status=T,r?.(...m)};return{name:"tool",...v,onTurnStart:m=>{let{messages:h}=m;return u&&Te(h,a),p&&Pe(h,p,R,x),v.onTurnStart?.(m)},onBeforeRequest:async m=>{let{messages:h,requestBody:T}=m;p===!0&&(T.messages=h.filter(E=>!E[x]));let O=await t?.();return O&&O.length>0&&(T.tools=O),v.onBeforeRequest?.(m)},onAfterRequest:async m=>{let{currentMessage:h,lastChoice:T,appendMessage:O,abortSignal:E,setRequestState:i,requestNext:c}=m;if(T?.finish_reason!=="tool_calls"||!h.tool_calls?.length)return;p&&(h[R]=!0),i("processing","calling-tools"),await e?.(h.tool_calls,{...m,currentMessage:h});let f=h.tool_calls.map(async y=>{let S=Math.floor(Date.now()/1e3),w=we({role:"tool",tool_call_id:y.id,content:"",metadata:{createdAt:S,updatedAt:S}});O(w);let U={...m,primaryMessage:h,toolMessage:w};A(y,U);try{let I=s(y,U),d=X(I);for await(let g of d){if(typeof g=="string")w.content+=g;else{let M={};try{M=JSON.parse(w.content||"{}")}catch(P){console.warn(P)}w.content=JSON.stringify(j(M,g))}w.metadata.updatedAt=Math.floor(Date.now()/1e3)}b(y,{...U,status:"success"})}catch(I){let d=I instanceof Error?I:new Error(String(I));if(E.aborted){b(y,{...U,status:"cancelled",error:d});return}console.error(I),w.content.length===0&&(w.content=l),b(y,{...U,status:"failed",error:d})}});return await Promise.all(f),c(),v.onAfterRequest?.(m)},onCompletionChunk:m=>{var T,O,E;let{currentMessage:h}=m;if(Array.isArray(h.tool_calls))for(let i of h.tool_calls)h.state?.toolCall?.[i.id]?.status||(h.state??(h.state={}),(T=h.state).toolCall??(T.toolCall={}),(O=h.state.toolCall)[E=i.id]??(O[E]={}));return v.onCompletionChunk?.(m)}}};var ke=o=>{let t=[];for(let e of o){if(e.name){let s=t.findIndex(n=>n.name===e.name);s!==-1&&t.splice(s,1)}t.push(e)}return t},ne=o=>{let{initialMessages:t=[],requestMessageFields:e=[],requestMessageFieldsExclude:s=["state","metadata","loading"],plugins:n=[],onCompletionChunk:r}=o,a=Q("idle"),l=Q(void 0),u=Q(t),p=Q(o.responseProvider),v=null,R=[],x={},A=[ae(),le(),ie()],b=ke(A.concat(n)),m=Ee(()=>a.value==="processing"),h=async d=>{if(!d||!d.trim()){console.warn("Cannot send empty message");return}if(m.value){console.warn("Cannot send message while processing is in progress");return}let g=Math.floor(Date.now()/1e3);u.value.push({role:"user",content:d.trim(),metadata:{createdAt:g,updatedAt:g}}),R.push(u.value[u.value.length-1]),await S()},T=async(...d)=>{if(m.value){console.warn("Cannot send message while processing is in progress");return}u.value.push(...d),R.push(...d),await S()},O=d=>{let g=d;return e.length&&(g=g.map(M=>ge(M,e))),s.length&&(g=g.map(M=>pe(M,s))),g},E=(d,g)=>{a.value=d,d==="processing"?l.value=g||"requesting":l.value=void 0},i=d=>{Object.assign(x,d)},c=d=>({messages:u.value,currentTurn:R,requestState:a.value,processingState:l.value,plugins:b,abortSignal:d,setRequestState:E,customContext:x,setCustomContext:i}),f=(d,g)=>typeof d.disabled=="function"?d.disabled(g):!!d.disabled,y=async(d,g)=>{E("processing","requesting");let M=new Proxy({messages:O(u.value)},{set(D,k,B){return k==="messages"?(D.messages=O(B),!0):(D[k]=B,!0)}}),P=c(g);for(let D of b.filter(k=>!f(k,P)))await D.onBeforeRequest?.({...P,requestBody:M});let C=Oe({role:"",content:"",loading:!0});I(C);let _,Y=d(M,g),q=X(Y);for await(let D of q){E("processing","completing"),C.loading&&(C.loading=void 0);let k=D.choices?.find(F=>F.index===0);if(k){_=k;let F=()=>{C.metadata||(C.metadata={});let{created:L,...ye}=D;C.metadata.createdAt=L,C.metadata.updatedAt=Math.floor(Date.now()/1e3),Object.assign(C.metadata,ye),j(C,k.message||k.delta)};if(r){let L=c(g);r({...L,chunk:D,choice:k,currentMessage:C},F)}else F()}let B=c(g);for(let F of b.filter(L=>!f(L,B)))F.onCompletionChunk?.({...B,abortSignal:g,chunk:D,choice:k,currentMessage:C})}await U(C,d,g,_)},S=async()=>{let d=new AbortController;v=d,x={};try{E("processing","requesting");let g=c(d.signal);for(let C of b.filter(_=>!f(_,g)))await C.onTurnStart?.(g);let M=p.value;try{await y(M,d.signal),E("completed")}catch(C){if(d.signal.aborted||C instanceof K||C instanceof Error&&C.name==="AbortError")E("aborted");else throw C}let P=c(d.signal);for(let C of b.filter(_=>!f(_,P)))await C.onTurnEnd?.(P)}catch(g){E("error");let M=!1,P=c(d.signal);for(let C of b.filter(_=>!f(_,P)))M=!0,C.onError?.({...P,error:g});if(!M)throw g}finally{let g=c(d.signal);for(let M of b.filter(P=>!f(P,g)))try{M.onFinally?.(g)}catch(P){console.error(`Error in onFinally hook for plugin ${M.name||"Anonymous"}:`,P)}v=null,R.slice(-1)[0]&&(R.slice(-1)[0].loading=void 0),R=[]}},w=async()=>{v?.abort(),m.value&&await new Promise(d=>{let g=Ie(m,M=>{M||(g(),d())},{immediate:!0})})},U=async(d,g,M,P)=>{let C=!1,_=c(M),Y=b.filter(q=>!f(q,_)).map(q=>{if(!q.onAfterRequest)return null;let D=B=>{I(B)},k=()=>{C=!0};return q.onAfterRequest({..._,currentMessage:d,lastChoice:P,appendMessage:D,requestNext:k})}).filter(q=>q!==null);await de(Promise.all(Y),M),C&&await y(g,M)},I=d=>{let g=Array.isArray(d)?d:[d];u.value.push(...g),R.push(...g)};return{requestState:a,processingState:l,messages:u,responseProvider:p,isProcessing:m,sendMessage:h,send:T,abortRequest:w}};import{isRef as _e,toValue as De}from"vue";function me(o,t=200,e=!1,s=!0,n=!1){return Ue(qe(t,e,s,n),o)}function Ue(o,t){function e(...s){return new Promise((n,r)=>{Promise.resolve(o(()=>t.apply(this,s),{fn:t,thisArg:this,args:s})).then(n).catch(r)})}return e}var fe=()=>{};function qe(...o){let t=0,e,s=!0,n=fe,r,a,l,u,p;!_e(o[0])&&typeof o[0]=="object"?{delay:a,trailing:l=!0,leading:u=!0,rejectOnCancel:p=!1}=o[0]:[a,l=!0,u=!0,p=!1]=o;let v=()=>{e&&(clearTimeout(e),e=void 0,n(),n=fe)};return x=>{let A=De(a),b=Date.now()-t,m=()=>r=x();return v(),A<=0?(t=Date.now(),m()):(b>A?(t=Date.now(),(u||!s)&&m()):l&&(r=new Promise((h,T)=>{n=p?T:h,e=setTimeout(()=>{t=Date.now(),s=!0,h(m()),v()},Math.max(0,A-b))})),!u&&!e&&(e=setTimeout(()=>s=!0,A)),s=!1,r)}}var Et=o=>{let t=o.storage||oe(),e=he([]),s=new Map,n=new Map,r=he(null),a=Be(()=>{let i=r.value;if(!i)return null;let c=e.value.find(y=>y.id===i);if(!c)return null;let f=s.get(i);return f?{...c,engine:f}:null}),l=i=>{if(!t?.saveMessages)return;let c=i||r.value,f=e.value.find(S=>S.id===c);if(!f)return;f.updatedAt=Date.now(),t?.saveConversation?.(f);let y=s.get(f.id);y&&t.saveMessages(f.id,y.messages.value)},u=(i,c)=>{if(!o.autoSaveMessages||!t?.saveMessages)return;let f=n.get(i);f&&f();let y=o.autoSaveThrottle??1e3,S=me(()=>{l(i)},y,!0,!0),w=Ne(c.messages,S,{deep:!0});n.set(i,w)},p=i=>{let c=n.get(i);c&&(c(),n.delete(i))};t?.loadConversations&&Promise.resolve(t.loadConversations()).then(i=>{e.value=i}).catch(i=>{console.error("[useConversation] loadConversations failed:",i)});let v=async(i,c)=>{let f=s.get(i);if(f)return f;let y=c?.initialMessages??o.useMessageOptions.initialMessages??[];if(t?.loadMessages)try{y=await t.loadMessages(i)}catch(w){console.error("[useConversation] loadMessages failed:",w)}let S=ne({...o.useMessageOptions,...c,initialMessages:y});return s.set(i,S),u(i,S),S};function R(){return Date.now().toString(36)+Math.random().toString(36).substring(2,9)}let x=i=>{let{id:c=R(),title:f,metadata:y,useMessageOptions:S}=i||{},w=Date.now(),U={id:c,title:f,createdAt:w,updatedAt:w,metadata:y};e.value.unshift(U);let I=ne({...o.useMessageOptions,...S});return s.set(c,I),u(c,I),t?.saveConversation?.(U),t?.saveMessages?.(c,I.messages.value),r.value=c,a.value},A=i=>{let{excludeId:c}=i||{};s.forEach((f,y)=>{if(c&&y===c)return;f.isProcessing?.value||(p(y),s.delete(y))})};return{conversations:e,activeConversationId:r,activeConversation:a,createConversation:x,switchConversation:async i=>i?r.value===i?a.value:e.value.find(f=>f.id===i)?(await v(i),A({excludeId:i}),r.value=i,a.value):null:null,deleteConversation:async i=>{let c=e.value.findIndex(y=>y.id===i);if(c===-1)return;await s.get(i)?.abortRequest(),p(i),s.delete(i),e.value.splice(c,1),t?.deleteConversation?.(i),r.value===i&&(r.value=null,A())},clear:()=>{e.value.map(c=>c.id).forEach(c=>{t?.deleteConversation?.(c)}),s.forEach(c=>{c.abortRequest()}),n.forEach(c=>{c()}),e.value=[],s.clear(),n.clear(),r.value=null},updateConversationTitle:(i,c)=>{let f=e.value.find(y=>y.id===i);f&&(f.title=c,f.updatedAt=Date.now(),t?.saveConversation?.(f))},saveMessages:l,sendMessage:i=>{a.value?.engine.sendMessage(i)},abortActiveRequest:async()=>{await a.value?.engine.abortRequest()}}};export{te as AIClient,Se as EXCLUDE_MODE_REMOVE,Ce as ErrorType,$ as IndexedDBStrategy,V as LocalStorageStrategy,ve as StreamEventType,ae as fallbackRolePlugin,xe as indexedDBStorageStrategyFactory,ie as lengthPlugin,oe as localStorageStrategyFactory,Me as sseStreamToGenerator,le as thinkingPlugin,mt as toolPlugin,Et as useConversation,ne as useMessage};
|
|
3
|
+
`);r=R.pop()||"";for(let x of R)if(x.trim()!==""){if(x.trim()==="data: [DONE]"){l&&(a=l),t.onDone(a);continue}try{let A=x.match(/^data: (.+)$/m);if(!A)continue;let M=JSON.parse(A[1]);t.onData(M),l=M.choices?.[0]?.finish_reason||void 0}catch(A){console.error("Error parsing SSE message:",A)}}}(r.trim()==="data: [DONE]"||e?.aborted)&&(e?.aborted&&(a="aborted"),t.onDone(a))}catch(d){if(e?.aborted)return;throw d}}function oe(o="The operation was aborted"){let t=new Error(o);return t.name="AbortError",t}async function*Re(o,t={}){let e=o.body?.getReader();if(!e)throw new Error("ReadableStream not supported");let{signal:n}=t,s=new TextDecoder,r="",a=()=>{e.cancel()};n?.addEventListener("abort",a);try{for(;;){if(n?.aborted)throw oe();let l;try{l=await e.read()}catch(x){throw n?.aborted?oe():x}let{done:d,value:p}=l;if(d){if(n?.aborted)throw oe();return}let v=s.decode(p,{stream:!0});r+=v;let R=r.split(`
|
|
4
|
+
`);r=R.pop()||"";for(let x of R)if(x.trim()!==""&&x.startsWith("data: ")){let A=x.slice(6);if(A==="[DONE]")return;try{yield JSON.parse(A)}catch(M){console.warn("Failed to parse SSE data:",A,M)}}}}finally{n?.removeEventListener("abort",a),e.releaseLock()}}var H=class extends z{constructor(e){super(e);this.defaultModel="gpt-3.5-turbo";this.baseURL=e.apiUrl||"https://api.openai.com/v1",this.apiKey=e.apiKey||"",e.defaultModel&&(this.defaultModel=e.defaultModel),this.apiKey||console.warn("API key is not provided. Authentication will likely fail.")}async chat(e){try{this.validateRequest(e);let n={model:e.options?.model||this.config.defaultModel||this.defaultModel,messages:e.messages,...e.options,stream:!1},s={method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(n)};this.apiKey&&Object.assign(s.headers,{Authorization:`Bearer ${this.apiKey}`});let r=await fetch(`${this.baseURL}/chat/completions`,s);if(!r.ok){let a=await r.text();throw new Error(`HTTP error! status: ${r.status}, details: ${a}`)}return await r.json()}catch(n){throw te(n)}}async chatStream(e,n){let{signal:s,...r}=e.options||{};try{this.validateRequest(e);let a={model:e.options?.model||this.config.defaultModel||this.defaultModel,messages:e.messages,...r,stream:!0},l={method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${this.apiKey}`,Accept:"text/event-stream"},body:JSON.stringify(a),signal:s};this.apiKey&&Object.assign(l.headers,{Authorization:`Bearer ${this.apiKey}`});let d=await fetch(`${this.baseURL}/chat/completions`,l);if(!d.ok){let p=await d.text();throw new Error(`HTTP error! status: ${d.status}, details: ${p}`)}await ie(d,n,s)}catch(a){if(s?.aborted)return;n.onError(te(a))}}updateConfig(e){super.updateConfig(e),e.apiUrl&&(this.baseURL=e.apiUrl),e.apiKey&&(this.apiKey=e.apiKey),e.defaultModel&&(this.defaultModel=e.defaultModel)}};var ne=class{constructor(t){this.config=t,this.provider=this.createProvider(t)}createProvider(t){if(t.provider==="custom"&&"providerImplementation"in t)return t.providerImplementation;if(t.provider==="deepseek"){let e={defaultModel:"deepseek-chat",apiUrl:"https://api.deepseek.com/v1"};return new H({...e,...t})}else return new H(t)}async chat(t){return this.provider.chat(t)}async chatStream(t,e){let n={...t,options:{...t.options,stream:!0}};return this.provider.chatStream(n,e)}getConfig(){return{...this.config}}updateConfig(t){this.config={...this.config,...t},t.provider&&t.provider!==this.config.provider?this.provider=this.createProvider(this.config):this.provider.updateConfig(this.config)}};import{toRaw as xe}from"vue";function G(o,t=new WeakSet){if(o==null||typeof o!="object")return o;if(t.has(o))return Array.isArray(o)?[]:{};t.add(o);try{let e=xe(o);if(Array.isArray(e))return e.map(s=>G(s,t));if(e instanceof Date||e instanceof RegExp||e instanceof ArrayBuffer||e instanceof Blob)return e;let n={};for(let s in e){if(typeof s=="symbol")continue;let r=Object.getOwnPropertyDescriptor(e,s);if(!r||r.get||r.set)continue;let a=e[s];typeof a!="function"&&typeof a!="symbol"&&(n[s]=G(a,t))}return n}catch(e){return console.warn("unwrapProxy error:",e),Array.isArray(o)?[]:{}}}var X=o=>o.map(t=>{let{renderContent:e,...n}=t;if(!Array.isArray(e))return t;let s=e.filter(a=>a.type==="collapsible-text"),r=e.filter(a=>a.type==="markdown"||a.type==="text");return s.length>0&&(n.reasoning_content=s.map(a=>a.content).join("")),r.length>0&&(n.content=r.map(a=>a.content).join("")),n});var V=o=>{let t=localStorage.getItem(o);return t?JSON.parse(t):[]},$=class{constructor(t="tiny-robot-ai-conversations"){this.storageKey=t}saveConversation(t){try{let e=V(this.storageKey),n=e.findIndex(s=>s.id===t.id);n!==-1?Object.assign(e[n],t):e.unshift({...t,messages:[]}),localStorage.setItem(this.storageKey,JSON.stringify(e))}catch(e){console.error("\u4FDD\u5B58\u4F1A\u8BDD\u5931\u8D25:",e)}}loadConversations(){try{return V(this.storageKey).map(e=>({id:e.id,title:e.title,createdAt:e.createdAt,updatedAt:e.updatedAt,metadata:e.metadata}))}catch(t){return console.error("\u52A0\u8F7D\u4F1A\u8BDD\u5931\u8D25:",t),[]}}saveMessages(t,e){try{let n=V(this.storageKey),s=n.findIndex(r=>r.id===t);s!==-1&&(n[s].messages=e),localStorage.setItem(this.storageKey,JSON.stringify(n))}catch(n){console.error("\u4FDD\u5B58\u4F1A\u8BDD\u6D88\u606F\u5931\u8D25:",n)}}loadMessages(t){try{let n=V(this.storageKey).find(r=>r.id===t);return X(n?.messages||[])}catch(e){return console.error("\u52A0\u8F7D\u4F1A\u8BDD\u6D88\u606F\u5931\u8D25:",e),[]}}deleteConversation(t){let e=V(this.storageKey),n=e.findIndex(s=>s.id===t);n!==-1&&e.splice(n,1),localStorage.setItem(this.storageKey,JSON.stringify(e))}};import{openDB as Ae}from"idb";var J=class{constructor(t="tiny-robot-ai-db",e=3){this.db=null;this.dbName=t,this.dbVersion=e}async getDB(){return this.db||(this.db=await Ae(this.dbName,this.dbVersion,{upgrade(t){t.objectStoreNames.contains("conversations")||t.createObjectStore("conversations",{keyPath:"id"}).createIndex("by-updated","updatedAt"),t.objectStoreNames.contains("messages")||t.createObjectStore("messages",{keyPath:"conversationId"})}})),this.db}async loadConversations(){try{return(await(await this.getDB()).getAllFromIndex("conversations","by-updated")).reverse()}catch(t){return console.error("\u52A0\u8F7D\u4F1A\u8BDD\u5931\u8D25:",t),[]}}async loadMessages(t){try{let n=await(await this.getDB()).get("messages",t);return n?X(n.messages):[]}catch(e){return console.error("\u52A0\u8F7D\u4F1A\u8BDD\u6D88\u606F\u5931\u8D25:",e),[]}}async saveConversation(t){try{let e=await this.getDB(),n=G(t);await e.put("conversations",n)}catch(e){throw console.error("\u4FDD\u5B58\u4F1A\u8BDD\u5931\u8D25:",e),e}}async saveMessages(t,e){try{let n=await this.getDB(),s=G(e);await n.put("messages",{conversationId:t,messages:s})}catch(n){throw console.error("\u4FDD\u5B58\u4F1A\u8BDD\u6D88\u606F\u5931\u8D25:",n),n}}async deleteConversation(t){try{let e=await this.getDB();await e.delete("conversations",t),await e.delete("messages",t)}catch(e){throw console.error("\u5220\u9664\u4F1A\u8BDD\u5931\u8D25:",e),e}}};function se(o={}){return new $(o.key||"tiny-robot-ai-conversations")}function we(o={}){return new J(o.dbName||"tiny-robot-ai-db",o.dbVersion||1)}import{computed as Fe,ref as Ce,watch as Ke}from"vue";import{computed as Ie,reactive as ke,ref as Y,watch as _e}from"vue";var le=(o={})=>{let{fallbackRole:t="assistant",...e}=o;return{name:"fallbackRole",...e,onBeforeRequest(n){let{requestBody:s,messages:r}=n;return s.messages=r.map(a=>({...a,role:a.role||t})),e.onBeforeRequest?.(n)}}};var ce=(o={})=>{let{continueContent:t="Please continue with your previous answer.",...e}=o;return{name:"length",...e,onAfterRequest:async n=>{let{lastChoice:s,appendMessage:r,requestNext:a}=n;return s?.finish_reason==="length"&&(r({role:"user",content:t}),a()),e.onAfterRequest?.(n)}}};var ue=(o={})=>({name:"thinking",...o,onCompletionChunk(t){let{choice:e,currentMessage:n}=t,r=typeof(e?.message?.reasoning_content||e?.delta?.reasoning_content)=="string";return n.state?n.state.thinking=r:n.state={thinking:r},o.onCompletionChunk?.(t)},onTurnEnd(t){let e=t.currentTurn.slice(-1)[0];return e?.state&&(e.state.thinking=void 0),o.onTurnEnd?.(t)}});import{reactive as Se}from"vue";var j=class extends Error{constructor(t){super(t),this.name="AbortError"}};function Te(o){if(o.aborted)return{promise:Promise.reject(new j(String(o.reason??"Aborted"))),cleanup:()=>{}};let t=null;return{promise:new Promise((s,r)=>{t=()=>{r(new j(String(o.reason??"Aborted")))},o.addEventListener("abort",t,{once:!0})}),cleanup:()=>{t&&(o.removeEventListener("abort",t),t=null)}}}function pe(o,t){let{promise:e,cleanup:n}=Te(t);return Promise.race([o,e]).finally(n)}function fe(o,t){let e={};for(let n in o)t.includes(n)&&(e[n]=o[n]);return e}function me(o,t){let e={};for(let n in o)t.includes(n)||(e[n]=o[n]);return e}async function*Q(o){if(de(o)){yield*o;return}let t=await o;if(de(t)){yield*t;return}yield t}function de(o){return o&&typeof o=="object"&&typeof o[Symbol.asyncIterator]=="function"}var re=o=>typeof o=="object"&&o!==null,ge=o=>re(o)&&typeof o.index=="number",L=(o,t)=>{for(let[e,n]of Object.entries(t)){let s=o[e];if(s)if(typeof s=="string"&&typeof n=="string")e==="type"&&s||(o[e]=s+n);else if(Array.isArray(s)&&Array.isArray(n))if(s.every(r=>ge(r))&&n.every(r=>ge(r))){let r=new Map(s.map(p=>[p.index,p])),a=new Map(n.map(p=>[p.index,p]));for(let[p,v]of a)if(r.has(p)){let R=r.get(p);r.set(p,L(R,v))}else r.set(p,v);let l=Math.max(...Array.from(r.keys()),-1)+1,d=l>s.length?Array.from({length:l}):s;for(let[p,v]of r)d[p]=v;o[e]=d}else o[e]=[...s,...n];else re(s)&&re(n)&&(o[e]=L(s,n));else o[e]=n}return o};function Pe(o,t){let e=[];for(let n=0;n<o.length;n++){let s=o[n];if(s.role==="assistant"&&s.tool_calls&&s.tool_calls.length>0){let r=new Set(s.tool_calls.map(d=>d.id)),a=new Set;for(let d=n+1;d<o.length;d++){let p=o[d];p.role==="tool"&&p.tool_call_id&&r.has(p.tool_call_id)&&a.add(p.tool_call_id)}let l=s.tool_calls.map(d=>d.id).filter(d=>!a.has(d));l.length>0&&e.push({insertAfterIndex:n,missingToolCallIds:l})}}for(let n=e.length-1;n>=0;n--){let{insertAfterIndex:s,missingToolCallIds:r}=e[n],a=r.map(l=>({role:"tool",tool_call_id:l,content:t}));o.splice(s+1,0,...a)}}var Ee="remove";function Oe(o,t,e,n){let s=o.filter(a=>a[e]),r=new Set(s.flatMap(a=>a.tool_calls?.map(l=>l.id)??[]));if(t===Ee)for(let a=o.length-1;a>=0;a--){let l=o[a];(l[e]||l[n]||l.tool_call_id&&r.has(l.tool_call_id))&&o.splice(a,1)}else if(t===!0)for(let a of o)(a[e]||a.tool_call_id&&r.has(a.tool_call_id))&&(a[n]=!0,delete a[e])}var yt=o=>{let{getTools:t,beforeCallTools:e,callTool:n,onToolCallStart:s,onToolCallEnd:r,toolCallCancelledContent:a="Tool call cancelled.",toolCallFailedContent:l="Tool call failed.",autoFillMissingToolMessages:d=!1,excludeToolMessagesNextTurn:p=!1,...v}=o,R=Symbol("doNotSendNextTurn"),x=Symbol("doNotSend"),A=(...m)=>{let[h,{primaryMessage:T}]=m;T.state.toolCall[h.id].status="running",s?.(...m)},M=(...m)=>{let[h,{status:T,primaryMessage:O}]=m;O.state.toolCall[h.id].status=T,r?.(...m)};return{name:"tool",...v,onTurnStart:m=>{let{messages:h}=m;return d&&Pe(h,a),p&&Oe(h,p,R,x),v.onTurnStart?.(m)},onBeforeRequest:async m=>{let{messages:h,requestBody:T}=m;p===!0&&(T.messages=h.filter(E=>!E[x]));let O=await t?.();return O&&O.length>0&&(T.tools=O),v.onBeforeRequest?.(m)},onAfterRequest:async m=>{let{currentMessage:h,lastChoice:T,appendMessage:O,abortSignal:E,setRequestState:i,requestNext:c}=m;if(T?.finish_reason!=="tool_calls"||!h.tool_calls?.length)return;p&&(h[R]=!0),i("processing","calling-tools"),await e?.(h.tool_calls,{...m,currentMessage:h});let f=h.tool_calls.map(async y=>{let S=Math.floor(Date.now()/1e3),w=Se({role:"tool",tool_call_id:y.id,content:"",metadata:{createdAt:S,updatedAt:S}});O(w);let U={...m,primaryMessage:h,toolMessage:w};A(y,U);try{let k=n(y,U),B=Q(k);for await(let u of B){if(typeof u=="string")w.content+=u;else{let g={};try{g=JSON.parse(w.content||"{}")}catch(b){console.warn(b)}w.content=JSON.stringify(L(g,u))}w.metadata.updatedAt=Math.floor(Date.now()/1e3)}M(y,{...U,status:"success"})}catch(k){let B=k instanceof Error?k:new Error(String(k));if(E.aborted){M(y,{...U,status:"cancelled",error:B});return}console.error(k),w.content.length===0&&(w.content=l),M(y,{...U,status:"failed",error:B})}});return await Promise.all(f),c(),v.onAfterRequest?.(m)},onCompletionChunk:m=>{var T,O,E;let{currentMessage:h}=m;if(Array.isArray(h.tool_calls))for(let i of h.tool_calls)h.state?.toolCall?.[i.id]?.status||(h.state??(h.state={}),(T=h.state).toolCall??(T.toolCall={}),(O=h.state.toolCall)[E=i.id]??(O[E]={}));return v.onCompletionChunk?.(m)}}};var De=o=>{let t=[];for(let e of o){if(e.name){let n=t.findIndex(s=>s.name===e.name);n!==-1&&t.splice(n,1)}t.push(e)}return t},ae=o=>{let{initialMessages:t=[],requestMessageFields:e=[],requestMessageFieldsExclude:n=["state","metadata","loading"],plugins:s=[],onCompletionChunk:r}=o,a=Y("idle"),l=Y(void 0),d=Y(t),p=Y(o.responseProvider),v=null,R=[],x={},A=[le(),ue(),ce()],M=De(A.concat(s)),m=Ie(()=>a.value==="processing"),h=async u=>{if(!u||!u.trim()){console.warn("Cannot send empty message");return}if(m.value){console.warn("Cannot send message while processing is in progress");return}let g=Math.floor(Date.now()/1e3);d.value.push({role:"user",content:u.trim(),metadata:{createdAt:g,updatedAt:g}}),R.push(d.value[d.value.length-1]),await w()},T=async(...u)=>{if(m.value){console.warn("Cannot send message while processing is in progress");return}d.value.push(...u),R.push(...u),await w()},O=u=>{let g=u;return e.length&&(g=g.map(b=>fe(b,e))),n.length&&(g=g.map(b=>me(b,n))),g},E=(u,g)=>{a.value=u,u==="processing"?l.value=g||"requesting":l.value=void 0},i=u=>{Object.assign(x,u)},c=u=>({messages:d.value,currentTurn:R,requestState:a.value,processingState:l.value,plugins:M,abortSignal:u,setRequestState:E,customContext:x,setCustomContext:i}),f=(u,g)=>typeof u.disabled=="function"?u.disabled(g):!!u.disabled,y=u=>!u||Object.keys(u).length===0?!1:Object.values(u).some(g=>!!g),S=async(u,g)=>{E("processing","requesting");let b=new Proxy({messages:O(d.value)},{set(D,P,N){return P==="messages"?(D.messages=O(N),!0):(D[P]=N,!0)}}),I=c(g);for(let D of M.filter(P=>!f(P,I)))await D.onBeforeRequest?.({...I,requestBody:b});let C=ke({role:"",content:"",loading:!0});B(C);let _,Z=u(b,g),q=Q(Z);for await(let D of q){E("processing","completing"),C.loading&&(C.loading=void 0);let P=D.choices?.find(K=>K.index===0);if(P){_=P;let K=()=>{C.metadata||(C.metadata={});let{created:W,...ve}=D;C.metadata.createdAt=W,C.metadata.updatedAt=Math.floor(Date.now()/1e3),Object.assign(C.metadata,ve);let ee=y(P.delta)?P.delta:P.message;ee||(ee=P.delta||P.message||{}),L(C,ee)};if(r){let W=c(g);r({...W,chunk:D,choice:P,currentMessage:C},K)}else K()}let N=c(g);for(let K of M.filter(W=>!f(W,N)))K.onCompletionChunk?.({...N,abortSignal:g,chunk:D,choice:P,currentMessage:C})}await k(C,u,g,_)},w=async()=>{let u=new AbortController;v=u,x={};try{E("processing","requesting");let g=c(u.signal);for(let C of M.filter(_=>!f(_,g)))await C.onTurnStart?.(g);let b=p.value;try{await S(b,u.signal),E("completed")}catch(C){if(u.signal.aborted||C instanceof j||C instanceof Error&&C.name==="AbortError")E("aborted");else throw C}let I=c(u.signal);for(let C of M.filter(_=>!f(_,I)))await C.onTurnEnd?.(I)}catch(g){E("error");let b=!1,I=c(u.signal);for(let C of M.filter(_=>!f(_,I)))b=!0,C.onError?.({...I,error:g});if(!b)throw g}finally{let g=c(u.signal);for(let b of M.filter(I=>!f(I,g)))try{b.onFinally?.(g)}catch(I){console.error(`Error in onFinally hook for plugin ${b.name||"Anonymous"}:`,I)}v=null,R.slice(-1)[0]&&(R.slice(-1)[0].loading=void 0),R=[]}},U=async()=>{v?.abort(),m.value&&await new Promise(u=>{let g=_e(m,b=>{b||(g(),u())},{immediate:!0})})},k=async(u,g,b,I)=>{let C=!1,_=c(b),Z=M.filter(q=>!f(q,_)).map(q=>{if(!q.onAfterRequest)return null;let D=N=>{B(N)},P=()=>{C=!0};return q.onAfterRequest({..._,currentMessage:u,lastChoice:I,appendMessage:D,requestNext:P})}).filter(q=>q!==null);await pe(Promise.all(Z),b),C&&await S(g,b)},B=u=>{let g=Array.isArray(u)?u:[u];d.value.push(...g),R.push(...g)};return{requestState:a,processingState:l,messages:d,responseProvider:p,isProcessing:m,sendMessage:h,send:T,abortRequest:U}};import{isRef as Ue,toValue as qe}from"vue";function ye(o,t=200,e=!1,n=!0,s=!1){return Be(Ne(t,e,n,s),o)}function Be(o,t){function e(...n){return new Promise((s,r)=>{Promise.resolve(o(()=>t.apply(this,n),{fn:t,thisArg:this,args:n})).then(s).catch(r)})}return e}var he=()=>{};function Ne(...o){let t=0,e,n=!0,s=he,r,a,l,d,p;!Ue(o[0])&&typeof o[0]=="object"?{delay:a,trailing:l=!0,leading:d=!0,rejectOnCancel:p=!1}=o[0]:[a,l=!0,d=!0,p=!1]=o;let v=()=>{e&&(clearTimeout(e),e=void 0,s(),s=he)};return x=>{let A=qe(a),M=Date.now()-t,m=()=>r=x();return v(),A<=0?(t=Date.now(),m()):(M>A?(t=Date.now(),(d||!n)&&m()):l&&(r=new Promise((h,T)=>{s=p?T:h,e=setTimeout(()=>{t=Date.now(),n=!0,h(m()),v()},Math.max(0,A-M))})),!d&&!e&&(e=setTimeout(()=>n=!0,A)),n=!1,r)}}var It=o=>{let t=o.storage||se(),e=Ce([]),n=new Map,s=new Map,r=Ce(null),a=Fe(()=>{let i=r.value;if(!i)return null;let c=e.value.find(y=>y.id===i);if(!c)return null;let f=n.get(i);return f?{...c,engine:f}:null}),l=i=>{if(!t?.saveMessages)return;let c=i||r.value,f=e.value.find(S=>S.id===c);if(!f)return;f.updatedAt=Date.now(),t?.saveConversation?.(f);let y=n.get(f.id);y&&t.saveMessages(f.id,y.messages.value)},d=(i,c)=>{if(!o.autoSaveMessages||!t?.saveMessages)return;let f=s.get(i);f&&f();let y=o.autoSaveThrottle??1e3,S=ye(()=>{l(i)},y,!0,!0),w=Ke(c.messages,S,{deep:!0});s.set(i,w)},p=i=>{let c=s.get(i);c&&(c(),s.delete(i))};t?.loadConversations&&Promise.resolve(t.loadConversations()).then(i=>{e.value=i}).catch(i=>{console.error("[useConversation] loadConversations failed:",i)});let v=async(i,c)=>{let f=n.get(i);if(f)return f;let y=c?.initialMessages??o.useMessageOptions.initialMessages??[];if(t?.loadMessages)try{y=await t.loadMessages(i)}catch(w){console.error("[useConversation] loadMessages failed:",w)}let S=ae({...o.useMessageOptions,...c,initialMessages:y});return n.set(i,S),d(i,S),S};function R(){return Date.now().toString(36)+Math.random().toString(36).substring(2,9)}let x=i=>{let{id:c=R(),title:f,metadata:y,useMessageOptions:S}=i||{},w=Date.now(),U={id:c,title:f,createdAt:w,updatedAt:w,metadata:y};e.value.unshift(U);let k=ae({...o.useMessageOptions,...S});return n.set(c,k),d(c,k),t?.saveConversation?.(U),t?.saveMessages?.(c,k.messages.value),r.value=c,a.value},A=i=>{let{excludeId:c}=i||{};n.forEach((f,y)=>{if(c&&y===c)return;f.isProcessing?.value||(p(y),n.delete(y))})};return{conversations:e,activeConversationId:r,activeConversation:a,createConversation:x,switchConversation:async i=>i?r.value===i?a.value:e.value.find(f=>f.id===i)?(await v(i),A({excludeId:i}),r.value=i,a.value):null:null,deleteConversation:async i=>{let c=e.value.findIndex(y=>y.id===i);if(c===-1)return;await n.get(i)?.abortRequest(),p(i),n.delete(i),e.value.splice(c,1),t?.deleteConversation?.(i),r.value===i&&(r.value=null,A())},clear:()=>{e.value.map(c=>c.id).forEach(c=>{t?.deleteConversation?.(c)}),n.forEach(c=>{c.abortRequest()}),s.forEach(c=>{c()}),e.value=[],n.clear(),s.clear(),r.value=null},updateConversationTitle:(i,c)=>{let f=e.value.find(y=>y.id===i);f&&(f.title=c,f.updatedAt=Date.now(),t?.saveConversation?.(f))},saveMessages:l,sendMessage:i=>{a.value?.engine.sendMessage(i)},abortActiveRequest:async()=>{await a.value?.engine.abortRequest()}}};export{ne as AIClient,Ee as EXCLUDE_MODE_REMOVE,Me as ErrorType,J as IndexedDBStrategy,$ as LocalStorageStrategy,be as StreamEventType,le as fallbackRolePlugin,we as indexedDBStorageStrategyFactory,ce as lengthPlugin,se as localStorageStrategyFactory,Re as sseStreamToGenerator,ue as thinkingPlugin,yt as toolPlugin,It as useConversation,ae as useMessage};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@opentiny/tiny-robot-kit",
|
|
3
|
-
"version": "0.4.0-alpha.
|
|
3
|
+
"version": "0.4.0-alpha.9",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"access": "public"
|
|
6
6
|
},
|
|
@@ -29,5 +29,5 @@
|
|
|
29
29
|
"dependencies": {
|
|
30
30
|
"idb": "^8.0.3"
|
|
31
31
|
},
|
|
32
|
-
"gitHead": "
|
|
32
|
+
"gitHead": "99e502b3ffef2265335b6318fb482287ba0e4080"
|
|
33
33
|
}
|