@opentiny/tiny-robot-kit 0.4.0-alpha.2 → 0.4.0-alpha.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.d.mts +3 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.js +2 -2
- package/dist/index.mjs +2 -2
- package/package.json +5 -2
package/dist/index.d.mts
CHANGED
|
@@ -111,6 +111,7 @@ interface UseMessageOptions {
|
|
|
111
111
|
*/
|
|
112
112
|
onCompletionChunk?: (context: BasePluginContext & {
|
|
113
113
|
currentMessage: ChatMessage;
|
|
114
|
+
choice: CompletionChoice;
|
|
114
115
|
chunk: ChatCompletion;
|
|
115
116
|
}, runDefault: () => void) => void;
|
|
116
117
|
}
|
|
@@ -150,7 +151,7 @@ interface UseMessagePlugin {
|
|
|
150
151
|
/**
|
|
151
152
|
* 是否禁用插件。useMessage 可能会内置一些默认插件,如果需要禁用,可以设置为 true。
|
|
152
153
|
*/
|
|
153
|
-
disabled?: boolean;
|
|
154
|
+
disabled?: boolean | ((context: BasePluginContext) => boolean);
|
|
154
155
|
/**
|
|
155
156
|
* 一次对话回合(turn)开始钩子:用户消息入队后、正式发起请求之前触发。
|
|
156
157
|
* 按插件注册顺序串行执行,便于做有序初始化/校验;出错则中断流程。
|
|
@@ -195,6 +196,7 @@ interface UseMessagePlugin {
|
|
|
195
196
|
onError?: (context: BasePluginContext & {
|
|
196
197
|
error: unknown;
|
|
197
198
|
}) => void;
|
|
199
|
+
onFinally?: (context: BasePluginContext) => void;
|
|
198
200
|
}
|
|
199
201
|
|
|
200
202
|
interface ConversationInfo {
|
package/dist/index.d.ts
CHANGED
|
@@ -111,6 +111,7 @@ interface UseMessageOptions {
|
|
|
111
111
|
*/
|
|
112
112
|
onCompletionChunk?: (context: BasePluginContext & {
|
|
113
113
|
currentMessage: ChatMessage;
|
|
114
|
+
choice: CompletionChoice;
|
|
114
115
|
chunk: ChatCompletion;
|
|
115
116
|
}, runDefault: () => void) => void;
|
|
116
117
|
}
|
|
@@ -150,7 +151,7 @@ interface UseMessagePlugin {
|
|
|
150
151
|
/**
|
|
151
152
|
* 是否禁用插件。useMessage 可能会内置一些默认插件,如果需要禁用,可以设置为 true。
|
|
152
153
|
*/
|
|
153
|
-
disabled?: boolean;
|
|
154
|
+
disabled?: boolean | ((context: BasePluginContext) => boolean);
|
|
154
155
|
/**
|
|
155
156
|
* 一次对话回合(turn)开始钩子:用户消息入队后、正式发起请求之前触发。
|
|
156
157
|
* 按插件注册顺序串行执行,便于做有序初始化/校验;出错则中断流程。
|
|
@@ -195,6 +196,7 @@ interface UseMessagePlugin {
|
|
|
195
196
|
onError?: (context: BasePluginContext & {
|
|
196
197
|
error: unknown;
|
|
197
198
|
}) => void;
|
|
199
|
+
onFinally?: (context: BasePluginContext) => void;
|
|
198
200
|
}
|
|
199
201
|
|
|
200
202
|
interface ConversationInfo {
|
package/dist/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";var
|
|
2
|
-
`);a=A.pop()||"";for(let w of A)if(w.trim()!==""&&w.startsWith("data: ")){let v=w.slice(6);if(v==="[DONE]")return;try{yield JSON.parse(v)}catch(T){console.warn("Failed to parse SSE data:",v,T)}}}}finally{s?.removeEventListener("abort",i),n.releaseLock()}}var F=require("vue");var q=require("vue");var J=(e={})=>{let{fallbackRole:t="assistant",...n}=e;return{name:"fallbackRole",...n,onBeforeRequest(s){let{requestBody:o,messages:a}=s;return o.messages=a.map(i=>({...i,role:i.role||t})),n.onBeforeRequest?.(s)}}};var X=(e={})=>{let{continueContent:t="Please continue with your previous answer.",...n}=e;return{name:"length",...n,onAfterRequest:async s=>{let{lastChoice:o,appendMessage:a,requestNext:i}=s;return o?.finish_reason==="length"&&(a({role:"user",content:t}),i()),n.onAfterRequest?.(s)}}};var $=(e={})=>({name:"thinking",...e,onCompletionChunk(t){let{choice:n,currentMessage:s}=t,a=typeof(n?.message?.reasoning_content||n?.delta?.reasoning_content)=="string";return s.state?s.state.thinking=a:s.state={thinking:a},e.onCompletionChunk?.(t)},onTurnEnd(t){let n=t.currentTurn.slice(-1)[0];return n?.state&&(n.state.thinking=void 0),e.onTurnEnd?.(t)}});var se=require("vue");var B=class extends Error{constructor(t){super(t),this.name="AbortError"}};function pe(e){if(e.aborted)return{promise:Promise.reject(new B(String(e.reason??"Aborted"))),cleanup:()=>{}};let t=null;return{promise:new Promise((o,a)=>{t=()=>{a(new B(String(e.reason??"Aborted")))},e.addEventListener("abort",t,{once:!0})}),cleanup:()=>{t&&(e.removeEventListener("abort",t),t=null)}}}function te(e,t){let{promise:n,cleanup:s}=pe(t);return Promise.race([e,n]).finally(s)}function ne(e,t){let n={};for(let s of t)s in e&&(n[s]=e[s]);return n}async function*W(e){if(Z(e)){yield*e;return}let t=await e;if(Z(t)){yield*t;return}yield t}function Z(e){return e&&typeof e=="object"&&typeof e[Symbol.asyncIterator]=="function"}var Q=e=>typeof e=="object"&&e!==null,ee=e=>Q(e)&&typeof e.index=="number",G=(e,t)=>{for(let[n,s]of Object.entries(t)){let o=e[n];if(o)if(typeof o=="string"&&typeof s=="string")n==="type"&&o||(e[n]=o+s);else if(Array.isArray(o)&&Array.isArray(s))if(o.every(a=>ee(a))&&s.every(a=>ee(a))){let a=new Map(o.map(d=>[d.index,d])),i=new Map(s.map(d=>[d.index,d]));for(let[d,M]of i)if(a.has(d)){let A=a.get(d);a.set(d,G(A,M))}else a.set(d,M);let u=Math.max(...Array.from(a.keys()),-1)+1,y=u>o.length?Array.from({length:u}):o;for(let[d,M]of a)y[d]=M;e[n]=y}else e[n]=[...o,...s];else Q(o)&&Q(s)&&(e[n]=G(o,s));else e[n]=s}return e};function me(e,t){let n=[];for(let s=0;s<e.length;s++){let o=e[s];if(o.role==="assistant"&&o.tool_calls&&o.tool_calls.length>0){let a=new Set(o.tool_calls.map(y=>y.id)),i=new Set;for(let y=s+1;y<e.length;y++){let d=e[y];d.role==="tool"&&d.tool_call_id&&a.has(d.tool_call_id)&&i.add(d.tool_call_id)}let u=o.tool_calls.map(y=>y.id).filter(y=>!i.has(y));u.length>0&&n.push({insertAfterIndex:s,missingToolCallIds:u})}}for(let s=n.length-1;s>=0;s--){let{insertAfterIndex:o,missingToolCallIds:a}=n[s],i=a.map(u=>({role:"tool",tool_call_id:u,content:t}));e.splice(o+1,0,...i)}}var oe="remove";function he(e,t,n,s){let o=e.filter(i=>i[n]),a=new Set(o.flatMap(i=>i.tool_calls?.map(u=>u.id)??[]));if(t===oe)for(let i=e.length-1;i>=0;i--){let u=e[i];(u[n]||u[s]||u.tool_call_id&&a.has(u.tool_call_id))&&e.splice(i,1)}else if(t===!0)for(let i of e)(i[n]||i.tool_call_id&&a.has(i.tool_call_id))&&(i[s]=!0,delete i[n])}var ye=e=>{let{getTools:t,beforeCallTools:n,callTool:s,onToolCallStart:o,onToolCallEnd:a,toolCallCancelledContent:i="Tool call cancelled.",toolCallFailedContent:u="Tool call failed.",autoFillMissingToolMessages:y=!1,excludeToolMessagesNextTurn:d=!1,...M}=e,A=Symbol("doNotSendNextTurn"),w=Symbol("doNotSend"),v=(...C)=>{let[p,{primaryMessage:r}]=C;r.state.toolCall[p.id].status="running",o?.(...C)},T=(...C)=>{let[p,{status:r,primaryMessage:l}]=C;l.state.toolCall[p.id].status=r,a?.(...C)};return{name:"tool",...M,onTurnStart:C=>{let{messages:p}=C;return y&&me(p,i),d&&he(p,d,A,w),M.onTurnStart?.(C)},onBeforeRequest:async C=>{let{messages:p,requestBody:r}=C;d===!0&&(r.messages=p.filter(g=>!g[w]));let l=await t?.();return l&&l.length>0&&(r.tools=l),M.onBeforeRequest?.(C)},onAfterRequest:async C=>{let{currentMessage:p,lastChoice:r,appendMessage:l,abortSignal:g,setRequestState:f,requestNext:x}=C;if(r?.finish_reason!=="tool_calls"||!p.tool_calls?.length)return;d&&(p[A]=!0),f("processing","calling-tools"),await n?.(p.tool_calls,{...C,currentMessage:p});let E=p.tool_calls.map(async S=>{let D=Math.floor(Date.now()/1e3),O=(0,se.reactive)({role:"tool",tool_call_id:S.id,content:"",metadata:{createdAt:D,updatedAt:D}});l(O);let c={...C,primaryMessage:p,toolMessage:O};v(S,c);try{let h=s(S,c),b=W(h);for await(let _ of b){if(typeof _=="string")O.content+=_;else{let m={};try{m=JSON.parse(O.content||"{}")}catch(R){console.warn(R)}O.content=JSON.stringify(G(m,_))}O.metadata.updatedAt=Math.floor(Date.now()/1e3)}T(S,{...c,status:"success"})}catch(h){let b=h instanceof Error?h:new Error(String(h));if(g.aborted){T(S,{...c,status:"cancelled",error:b});return}console.error(h),O.content.length===0&&(O.content=u),T(S,{...c,status:"failed",error:b})}});return await Promise.all(E),x(),M.onAfterRequest?.(C)},onCompletionChunk:C=>{var r,l,g;let{currentMessage:p}=C;if(Array.isArray(p.tool_calls))for(let f of p.tool_calls)p.state?.toolCall?.[f.id]?.status||(p.state??(p.state={}),(r=p.state).toolCall??(r.toolCall={}),(l=p.state.toolCall)[g=f.id]??(l[g]={}));return M.onCompletionChunk?.(C)}}};var Ce=e=>{let t=[];for(let n of e){if(n.name){let s=t.findIndex(o=>o.name===n.name);s!==-1&&t.splice(s,1)}t.push(n)}return t},L=e=>{let{initialMessages:t=[],requestMessageFields:n=["role","content","tool_calls","tool_call_id"],plugins:s=[],onCompletionChunk:o}=e,a=(0,q.ref)("idle"),i=(0,q.ref)(void 0),u=(0,q.ref)(t),y=(0,q.ref)(e.responseProvider),d=null,M=[],A={},w=[J(),$(),X()],v=Ce(w.concat(s)),T=(0,q.computed)(()=>a.value==="processing"),C=async c=>{if(!c||!c.trim()){console.warn("Cannot send empty message");return}if(T.value){console.warn("Cannot send message while processing is in progress");return}let h=Math.floor(Date.now()/1e3);u.value.push({role:"user",content:c.trim(),metadata:{createdAt:h,updatedAt:h}}),M.push(u.value[u.value.length-1]),await E()},p=async(...c)=>{if(T.value){console.warn("Cannot send message while processing is in progress");return}u.value.push(...c),M.push(...c),await E()},r=c=>c.map(h=>ne(h,n)),l=(c,h)=>{a.value=c,c==="processing"?i.value=h||"requesting":i.value=void 0},g=c=>{Object.assign(A,c)},f=()=>({messages:u.value,currentTurn:M,requestState:a.value,processingState:i.value,requestMessageFields:n,plugins:v,setRequestState:l,customContext:A,setCustomContext:g}),x=async(c,h)=>{l("processing","requesting");let b=new Proxy({messages:r(u.value)},{set(k,P,I){return P==="messages"?(k.messages=r(I),!0):(k[P]=I,!0)}}),_=f();for(let k of v.filter(P=>!P.disabled))await k.onBeforeRequest?.({..._,abortSignal:h,requestBody:b});let m=(0,q.reactive)({role:"",content:"",loading:!0});O(m);let R,V=c(b,h),U=W(V);for await(let k of U){l("processing","completing"),m.loading&&(m.loading=void 0);let P=k.choices?.find(N=>N.index===0);if(P){R=P;let N=()=>{m.metadata||(m.metadata={});let{created:j,...ie}=k;m.metadata.createdAt=j,m.metadata.updatedAt=Math.floor(Date.now()/1e3),Object.assign(m.metadata,ie),G(m,P.message||P.delta)};if(o){let j=f();o({...j,abortSignal:h,chunk:k,currentMessage:m},N)}else N()}let I=f();for(let N of v.filter(j=>!j.disabled))N.onCompletionChunk?.({...I,abortSignal:h,chunk:k,choice:P,currentMessage:m})}await D(m,c,h,R)},E=async()=>{let c=new AbortController;d=c;let h=y.value;A={};try{l("processing","requesting");let b=f();for(let m of v.filter(R=>!R.disabled))await m.onTurnStart?.({...b,abortSignal:c.signal});try{await x(h,c.signal),l("completed")}catch(m){if(c.signal.aborted||m instanceof B||m instanceof Error&&m.name==="AbortError")l("aborted");else throw m}let _=f();for(let m of v.filter(R=>!R.disabled))await m.onTurnEnd?.({..._,abortSignal:c.signal})}catch(b){l("error");let _=f();for(let m of v.filter(R=>!R.disabled))m.onError?.({..._,abortSignal:c.signal,error:b});throw b}finally{d=null,M.slice(-1)[0]&&(M.slice(-1)[0].loading=void 0),M=[]}},S=async()=>{d?.abort(),T.value&&await new Promise(c=>{let h=(0,q.watch)(T,b=>{b||(h(),c())},{immediate:!0})})},D=async(c,h,b,_)=>{let m=!1,R=f(),V=v.filter(U=>!U.disabled).map(U=>{if(!U.onAfterRequest)return null;let k=I=>{O(I)},P=()=>{m=!0};return U.onAfterRequest({...R,abortSignal:b,currentMessage:c,lastChoice:_,appendMessage:k,requestNext:P})}).filter(U=>U!==null);await te(Promise.all(V),b),m&&await x(h,b)},O=c=>{let h=Array.isArray(c)?c:[c];u.value.push(...h),M.push(...h)};return{requestState:a,processingState:i,messages:u,responseProvider:y,isProcessing:T,sendMessage:C,send:p,abortRequest:S}};var H=require("vue");function ae(e,t=200,n=!1,s=!0,o=!1){return Me(ve(t,n,s,o),e)}function Me(e,t){function n(...s){return new Promise((o,a)=>{Promise.resolve(e(()=>t.apply(this,s),{fn:t,thisArg:this,args:s})).then(o).catch(a)})}return n}var re=()=>{};function ve(...e){let t=0,n,s=!0,o=re,a,i,u,y,d;!(0,H.isRef)(e[0])&&typeof e[0]=="object"?{delay:i,trailing:u=!0,leading:y=!0,rejectOnCancel:d=!1}=e[0]:[i,u=!0,y=!0,d=!1]=e;let M=()=>{n&&(clearTimeout(n),n=void 0,o(),o=re)};return w=>{let v=(0,H.toValue)(i),T=Date.now()-t,C=()=>a=w();return M(),v<=0?(t=Date.now(),C()):(T>v?(t=Date.now(),(y||!s)&&C()):u&&(a=new Promise((p,r)=>{o=d?r:p,n=setTimeout(()=>{t=Date.now(),s=!0,p(C()),M()},Math.max(0,v-T))})),!y&&!n&&(n=setTimeout(()=>s=!0,v)),s=!1,a)}}var be=e=>{let t=(0,F.ref)([]),n=new Map,s=new Map,o=(0,F.ref)(null),a=(0,F.computed)(()=>{let r=o.value;if(!r)return null;let l=t.value.find(f=>f.id===r);if(!l)return null;let g=n.get(r);return g?{...l,engine:g}:null}),i=r=>{if(!e.storage?.saveMessages)return;let l=r||o.value,g=t.value.find(x=>x.id===l);if(!g)return;g.updatedAt=Date.now(),e.storage?.saveConversation?.(g);let f=n.get(g.id);f&&e.storage.saveMessages(g.id,f.messages.value)},u=(r,l)=>{if(!e.autoSaveMessages||!e.storage?.saveMessages)return;let g=s.get(r);g&&g();let f=e.autoSaveThrottle??1e3,x=ae(()=>{i(r)},f,!0,!0),E=(0,F.watch)(l.messages,x,{deep:!0});s.set(r,E)},y=r=>{let l=s.get(r);l&&(l(),s.delete(r))};e.storage?.loadConversations&&Promise.resolve(e.storage.loadConversations()).then(r=>{t.value=r}).catch(r=>{console.error("[useConversation] loadConversations failed:",r)});let d=async(r,l)=>{let g=n.get(r);if(g)return g;let f=l?.initialMessages??e.useMessageOptions.initialMessages??[];if(e.storage?.loadMessages)try{f=await e.storage.loadMessages(r)}catch(E){console.error("[useConversation] loadMessages failed:",E)}let x=L({...e.useMessageOptions,...l,initialMessages:f});return n.set(r,x),u(r,x),x};function M(){return Date.now().toString(36)+Math.random().toString(36).substring(2,9)}let A=r=>{let{id:l=M(),title:g,metadata:f,useMessageOptions:x}=r||{},E=Date.now(),S={id:l,title:g,createdAt:E,updatedAt:E,metadata:f};t.value.unshift(S);let D=L({...e.useMessageOptions,...x});return n.set(l,D),u(l,D),e.storage?.saveConversation?.(S),e.storage?.saveMessages?.(l,D.messages.value),o.value=l,a.value},w=async r=>r?o.value===r?a.value:t.value.find(g=>g.id===r)?(await d(r),n.forEach((g,f)=>{if(f===r)return;g.isProcessing?.value||(y(f),n.delete(f))}),o.value=r,a.value):null:null;return{conversations:t,activeConversationId:o,activeConversation:a,createConversation:A,switchConversation:w,deleteConversation:async r=>{let l=t.value.findIndex(f=>f.id===r);if(l===-1)return;if(await n.get(r)?.abortRequest(),y(r),n.delete(r),t.value.splice(l,1),e.storage?.deleteConversation?.(r),o.value===r){let f=t.value[0];f?await w(f.id):o.value=null}},updateConversationTitle:(r,l)=>{let g=t.value.find(f=>f.id===r);g&&(g.title=l,g.updatedAt=Date.now(),e.storage?.saveConversation?.(g))},saveMessages:i,sendMessage:r=>{a.value?.engine.sendMessage(r)},abortActiveRequest:async()=>{await a.value?.engine.abortRequest()}}};0&&(module.exports={EXCLUDE_MODE_REMOVE,createSSEStreamGenerator,fallbackRolePlugin,lengthPlugin,thinkingPlugin,toolPlugin,useConversation,useMessage});
|
|
1
|
+
"use strict";var z=Object.defineProperty;var ce=Object.getOwnPropertyDescriptor;var ue=Object.getOwnPropertyNames;var ge=Object.prototype.hasOwnProperty;var fe=(e,t)=>{for(var n in t)z(e,n,{get:t[n],enumerable:!0})},de=(e,t,n,s)=>{if(t&&typeof t=="object"||typeof t=="function")for(let r of ue(t))!ge.call(e,r)&&r!==n&&z(e,r,{get:()=>t[r],enumerable:!(s=ce(t,r))||s.enumerable});return e};var pe=e=>de(z({},"__esModule",{value:!0}),e);var xe={};fe(xe,{EXCLUDE_MODE_REMOVE:()=>re,createSSEStreamGenerator:()=>Z,fallbackRolePlugin:()=>X,lengthPlugin:()=>$,thinkingPlugin:()=>Q,toolPlugin:()=>Ce,useConversation:()=>be,useMessage:()=>H});module.exports=pe(xe);function J(e="The operation was aborted"){let t=new Error(e);return t.name="AbortError",t}async function*Z(e,t={}){let n=e.body?.getReader();if(!n)throw new Error("ReadableStream not supported");let{signal:s}=t,r=new TextDecoder,a="",l=()=>{n.cancel()};s?.addEventListener("abort",l);try{for(;;){if(s?.aborted)throw J();let g;try{g=await n.read()}catch(R){throw s?.aborted?J():R}let{done:y,value:f}=g;if(y){if(s?.aborted)throw J();return}let M=r.decode(f,{stream:!0});a+=M;let E=a.split(`
|
|
2
|
+
`);a=E.pop()||"";for(let R of E)if(R.trim()!==""&&R.startsWith("data: ")){let T=R.slice(6);if(T==="[DONE]")return;try{yield JSON.parse(T)}catch(x){console.warn("Failed to parse SSE data:",T,x)}}}}finally{s?.removeEventListener("abort",l),n.releaseLock()}}var B=require("vue");var q=require("vue");var X=(e={})=>{let{fallbackRole:t="assistant",...n}=e;return{name:"fallbackRole",...n,onBeforeRequest(s){let{requestBody:r,messages:a}=s;return r.messages=a.map(l=>({...l,role:l.role||t})),n.onBeforeRequest?.(s)}}};var $=(e={})=>{let{continueContent:t="Please continue with your previous answer.",...n}=e;return{name:"length",...n,onAfterRequest:async s=>{let{lastChoice:r,appendMessage:a,requestNext:l}=s;return r?.finish_reason==="length"&&(a({role:"user",content:t}),l()),n.onAfterRequest?.(s)}}};var Q=(e={})=>({name:"thinking",...e,onCompletionChunk(t){let{choice:n,currentMessage:s}=t,a=typeof(n?.message?.reasoning_content||n?.delta?.reasoning_content)=="string";return s.state?s.state.thinking=a:s.state={thinking:a},e.onCompletionChunk?.(t)},onTurnEnd(t){let n=t.currentTurn.slice(-1)[0];return n?.state&&(n.state.thinking=void 0),e.onTurnEnd?.(t)}});var oe=require("vue");var G=class extends Error{constructor(t){super(t),this.name="AbortError"}};function me(e){if(e.aborted)return{promise:Promise.reject(new G(String(e.reason??"Aborted"))),cleanup:()=>{}};let t=null;return{promise:new Promise((r,a)=>{t=()=>{a(new G(String(e.reason??"Aborted")))},e.addEventListener("abort",t,{once:!0})}),cleanup:()=>{t&&(e.removeEventListener("abort",t),t=null)}}}function ne(e,t){let{promise:n,cleanup:s}=me(t);return Promise.race([e,n]).finally(s)}function se(e,t){let n={};for(let s of t)s in e&&(n[s]=e[s]);return n}async function*L(e){if(ee(e)){yield*e;return}let t=await e;if(ee(t)){yield*t;return}yield t}function ee(e){return e&&typeof e=="object"&&typeof e[Symbol.asyncIterator]=="function"}var Y=e=>typeof e=="object"&&e!==null,te=e=>Y(e)&&typeof e.index=="number",j=(e,t)=>{for(let[n,s]of Object.entries(t)){let r=e[n];if(r)if(typeof r=="string"&&typeof s=="string")n==="type"&&r||(e[n]=r+s);else if(Array.isArray(r)&&Array.isArray(s))if(r.every(a=>te(a))&&s.every(a=>te(a))){let a=new Map(r.map(f=>[f.index,f])),l=new Map(s.map(f=>[f.index,f]));for(let[f,M]of l)if(a.has(f)){let E=a.get(f);a.set(f,j(E,M))}else a.set(f,M);let g=Math.max(...Array.from(a.keys()),-1)+1,y=g>r.length?Array.from({length:g}):r;for(let[f,M]of a)y[f]=M;e[n]=y}else e[n]=[...r,...s];else Y(r)&&Y(s)&&(e[n]=j(r,s));else e[n]=s}return e};function he(e,t){let n=[];for(let s=0;s<e.length;s++){let r=e[s];if(r.role==="assistant"&&r.tool_calls&&r.tool_calls.length>0){let a=new Set(r.tool_calls.map(y=>y.id)),l=new Set;for(let y=s+1;y<e.length;y++){let f=e[y];f.role==="tool"&&f.tool_call_id&&a.has(f.tool_call_id)&&l.add(f.tool_call_id)}let g=r.tool_calls.map(y=>y.id).filter(y=>!l.has(y));g.length>0&&n.push({insertAfterIndex:s,missingToolCallIds:g})}}for(let s=n.length-1;s>=0;s--){let{insertAfterIndex:r,missingToolCallIds:a}=n[s],l=a.map(g=>({role:"tool",tool_call_id:g,content:t}));e.splice(r+1,0,...l)}}var re="remove";function ye(e,t,n,s){let r=e.filter(l=>l[n]),a=new Set(r.flatMap(l=>l.tool_calls?.map(g=>g.id)??[]));if(t===re)for(let l=e.length-1;l>=0;l--){let g=e[l];(g[n]||g[s]||g.tool_call_id&&a.has(g.tool_call_id))&&e.splice(l,1)}else if(t===!0)for(let l of e)(l[n]||l.tool_call_id&&a.has(l.tool_call_id))&&(l[s]=!0,delete l[n])}var Ce=e=>{let{getTools:t,beforeCallTools:n,callTool:s,onToolCallStart:r,onToolCallEnd:a,toolCallCancelledContent:l="Tool call cancelled.",toolCallFailedContent:g="Tool call failed.",autoFillMissingToolMessages:y=!1,excludeToolMessagesNextTurn:f=!1,...M}=e,E=Symbol("doNotSendNextTurn"),R=Symbol("doNotSend"),T=(...C)=>{let[p,{primaryMessage:b}]=C;b.state.toolCall[p.id].status="running",r?.(...C)},x=(...C)=>{let[p,{status:b,primaryMessage:o}]=C;o.state.toolCall[p.id].status=b,a?.(...C)};return{name:"tool",...M,onTurnStart:C=>{let{messages:p}=C;return y&&he(p,l),f&&ye(p,f,E,R),M.onTurnStart?.(C)},onBeforeRequest:async C=>{let{messages:p,requestBody:b}=C;f===!0&&(b.messages=p.filter(u=>!u[R]));let o=await t?.();return o&&o.length>0&&(b.tools=o),M.onBeforeRequest?.(C)},onAfterRequest:async C=>{let{currentMessage:p,lastChoice:b,appendMessage:o,abortSignal:u,setRequestState:c,requestNext:m}=C;if(b?.finish_reason!=="tool_calls"||!p.tool_calls?.length)return;f&&(p[E]=!0),c("processing","calling-tools"),await n?.(p.tool_calls,{...C,currentMessage:p});let P=p.tool_calls.map(async w=>{let F=Math.floor(Date.now()/1e3),S=(0,oe.reactive)({role:"tool",tool_call_id:w.id,content:"",metadata:{createdAt:F,updatedAt:F}});o(S);let D={...C,primaryMessage:p,toolMessage:S};T(w,D);try{let i=s(w,D),h=L(i);for await(let v of h){if(typeof v=="string")S.content+=v;else{let A={};try{A=JSON.parse(S.content||"{}")}catch(d){console.warn(d)}S.content=JSON.stringify(j(A,v))}S.metadata.updatedAt=Math.floor(Date.now()/1e3)}x(w,{...D,status:"success"})}catch(i){let h=i instanceof Error?i:new Error(String(i));if(u.aborted){x(w,{...D,status:"cancelled",error:h});return}console.error(i),S.content.length===0&&(S.content=g),x(w,{...D,status:"failed",error:h})}});return await Promise.all(P),m(),M.onAfterRequest?.(C)},onCompletionChunk:C=>{var b,o,u;let{currentMessage:p}=C;if(Array.isArray(p.tool_calls))for(let c of p.tool_calls)p.state?.toolCall?.[c.id]?.status||(p.state??(p.state={}),(b=p.state).toolCall??(b.toolCall={}),(o=p.state.toolCall)[u=c.id]??(o[u]={}));return M.onCompletionChunk?.(C)}}};var Me=e=>{let t=[];for(let n of e){if(n.name){let s=t.findIndex(r=>r.name===n.name);s!==-1&&t.splice(s,1)}t.push(n)}return t},H=e=>{let{initialMessages:t=[],requestMessageFields:n=["role","content","tool_calls","tool_call_id"],plugins:s=[],onCompletionChunk:r}=e,a=(0,q.ref)("idle"),l=(0,q.ref)(void 0),g=(0,q.ref)(t),y=(0,q.ref)(e.responseProvider),f=null,M=[],E={},R=[X(),Q(),$()],T=Me(R.concat(s)),x=(0,q.computed)(()=>a.value==="processing"),C=async i=>{if(!i||!i.trim()){console.warn("Cannot send empty message");return}if(x.value){console.warn("Cannot send message while processing is in progress");return}let h=Math.floor(Date.now()/1e3);g.value.push({role:"user",content:i.trim(),metadata:{createdAt:h,updatedAt:h}}),M.push(g.value[g.value.length-1]),await w()},p=async(...i)=>{if(x.value){console.warn("Cannot send message while processing is in progress");return}g.value.push(...i),M.push(...i),await w()},b=i=>i.map(h=>se(h,n)),o=(i,h)=>{a.value=i,i==="processing"?l.value=h||"requesting":l.value=void 0},u=i=>{Object.assign(E,i)},c=i=>({messages:g.value,currentTurn:M,requestState:a.value,processingState:l.value,requestMessageFields:n,plugins:T,abortSignal:i,setRequestState:o,customContext:E,setCustomContext:u}),m=(i,h)=>typeof i.disabled=="function"?i.disabled(h):!!i.disabled,P=async(i,h)=>{o("processing","requesting");let v=new Proxy({messages:b(g.value)},{set(k,O,I){return O==="messages"?(k.messages=b(I),!0):(k[O]=I,!0)}}),A=c(h);for(let k of T.filter(O=>!m(O,A)))await k.onBeforeRequest?.({...A,requestBody:v});let d=(0,q.reactive)({role:"",content:"",loading:!0});D(d);let _,K=i(v,h),U=L(K);for await(let k of U){o("processing","completing"),d.loading&&(d.loading=void 0);let O=k.choices?.find(N=>N.index===0);if(O){_=O;let N=()=>{d.metadata||(d.metadata={});let{created:W,...le}=k;d.metadata.createdAt=W,d.metadata.updatedAt=Math.floor(Date.now()/1e3),Object.assign(d.metadata,le),j(d,O.message||O.delta)};if(r){let W=c(h);r({...W,chunk:k,choice:O,currentMessage:d},N)}else N()}let I=c(h);for(let N of T.filter(W=>!m(W,I)))N.onCompletionChunk?.({...I,abortSignal:h,chunk:k,choice:O,currentMessage:d})}await S(d,i,h,_)},w=async()=>{let i=new AbortController;f=i;let h=y.value;E={};try{o("processing","requesting");let v=c(i.signal);for(let d of T.filter(_=>!m(_,v)))await d.onTurnStart?.(v);try{await P(h,i.signal),o("completed")}catch(d){if(i.signal.aborted||d instanceof G||d instanceof Error&&d.name==="AbortError")o("aborted");else throw d}let A=c(i.signal);for(let d of T.filter(_=>!m(_,A)))await d.onTurnEnd?.(A)}catch(v){o("error");let A=c(i.signal);for(let d of T.filter(_=>!m(_,A)))d.onError?.({...A,error:v});throw v}finally{let v=c(i.signal);for(let A of T.filter(d=>!m(d,v)))try{A.onFinally?.(v)}catch(d){console.error(`Error in onFinally hook for plugin ${A.name||"Anonymous"}:`,d)}f=null,M.slice(-1)[0]&&(M.slice(-1)[0].loading=void 0),M=[]}},F=async()=>{f?.abort(),x.value&&await new Promise(i=>{let h=(0,q.watch)(x,v=>{v||(h(),i())},{immediate:!0})})},S=async(i,h,v,A)=>{let d=!1,_=c(v),K=T.filter(U=>!m(U,_)).map(U=>{if(!U.onAfterRequest)return null;let k=I=>{D(I)},O=()=>{d=!0};return U.onAfterRequest({..._,currentMessage:i,lastChoice:A,appendMessage:k,requestNext:O})}).filter(U=>U!==null);await ne(Promise.all(K),v),d&&await P(h,v)},D=i=>{let h=Array.isArray(i)?i:[i];g.value.push(...h),M.push(...h)};return{requestState:a,processingState:l,messages:g,responseProvider:y,isProcessing:x,sendMessage:C,send:p,abortRequest:F}};var V=require("vue");function ie(e,t=200,n=!1,s=!0,r=!1){return ve(Te(t,n,s,r),e)}function ve(e,t){function n(...s){return new Promise((r,a)=>{Promise.resolve(e(()=>t.apply(this,s),{fn:t,thisArg:this,args:s})).then(r).catch(a)})}return n}var ae=()=>{};function Te(...e){let t=0,n,s=!0,r=ae,a,l,g,y,f;!(0,V.isRef)(e[0])&&typeof e[0]=="object"?{delay:l,trailing:g=!0,leading:y=!0,rejectOnCancel:f=!1}=e[0]:[l,g=!0,y=!0,f=!1]=e;let M=()=>{n&&(clearTimeout(n),n=void 0,r(),r=ae)};return R=>{let T=(0,V.toValue)(l),x=Date.now()-t,C=()=>a=R();return M(),T<=0?(t=Date.now(),C()):(x>T?(t=Date.now(),(y||!s)&&C()):g&&(a=new Promise((p,b)=>{r=f?b:p,n=setTimeout(()=>{t=Date.now(),s=!0,p(C()),M()},Math.max(0,T-x))})),!y&&!n&&(n=setTimeout(()=>s=!0,T)),s=!1,a)}}var be=e=>{let t=(0,B.ref)([]),n=new Map,s=new Map,r=(0,B.ref)(null),a=(0,B.computed)(()=>{let o=r.value;if(!o)return null;let u=t.value.find(m=>m.id===o);if(!u)return null;let c=n.get(o);return c?{...u,engine:c}:null}),l=o=>{if(!e.storage?.saveMessages)return;let u=o||r.value,c=t.value.find(P=>P.id===u);if(!c)return;c.updatedAt=Date.now(),e.storage?.saveConversation?.(c);let m=n.get(c.id);m&&e.storage.saveMessages(c.id,m.messages.value)},g=(o,u)=>{if(!e.autoSaveMessages||!e.storage?.saveMessages)return;let c=s.get(o);c&&c();let m=e.autoSaveThrottle??1e3,P=ie(()=>{l(o)},m,!0,!0),w=(0,B.watch)(u.messages,P,{deep:!0});s.set(o,w)},y=o=>{let u=s.get(o);u&&(u(),s.delete(o))};e.storage?.loadConversations&&Promise.resolve(e.storage.loadConversations()).then(o=>{t.value=o}).catch(o=>{console.error("[useConversation] loadConversations failed:",o)});let f=async(o,u)=>{let c=n.get(o);if(c)return c;let m=u?.initialMessages??e.useMessageOptions.initialMessages??[];if(e.storage?.loadMessages)try{m=await e.storage.loadMessages(o)}catch(w){console.error("[useConversation] loadMessages failed:",w)}let P=H({...e.useMessageOptions,...u,initialMessages:m});return n.set(o,P),g(o,P),P};function M(){return Date.now().toString(36)+Math.random().toString(36).substring(2,9)}let E=o=>{let{id:u=M(),title:c,metadata:m,useMessageOptions:P}=o||{},w=Date.now(),F={id:u,title:c,createdAt:w,updatedAt:w,metadata:m};t.value.unshift(F);let S=H({...e.useMessageOptions,...P});return n.set(u,S),g(u,S),e.storage?.saveConversation?.(F),e.storage?.saveMessages?.(u,S.messages.value),r.value=u,a.value},R=o=>{let{excludeId:u}=o||{};n.forEach((c,m)=>{if(u&&m===u)return;c.isProcessing?.value||(y(m),n.delete(m))})};return{conversations:t,activeConversationId:r,activeConversation:a,createConversation:E,switchConversation:async o=>o?r.value===o?a.value:t.value.find(c=>c.id===o)?(await f(o),R({excludeId:o}),r.value=o,a.value):null:null,deleteConversation:async o=>{let u=t.value.findIndex(m=>m.id===o);if(u===-1)return;await n.get(o)?.abortRequest(),y(o),n.delete(o),t.value.splice(u,1),e.storage?.deleteConversation?.(o),r.value===o&&(r.value=null,R())},updateConversationTitle:(o,u)=>{let c=t.value.find(m=>m.id===o);c&&(c.title=u,c.updatedAt=Date.now(),e.storage?.saveConversation?.(c))},saveMessages:l,sendMessage:o=>{a.value?.engine.sendMessage(o)},abortActiveRequest:async()=>{await a.value?.engine.abortRequest()}}};0&&(module.exports={EXCLUDE_MODE_REMOVE,createSSEStreamGenerator,fallbackRolePlugin,lengthPlugin,thinkingPlugin,toolPlugin,useConversation,useMessage});
|
package/dist/index.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
function
|
|
2
|
-
`);a=A.pop()||"";for(let w of A)if(w.trim()!==""&&w.startsWith("data: ")){let v=w.slice(6);if(v==="[DONE]")return;try{yield JSON.parse(v)}catch(T){console.warn("Failed to parse SSE data:",v,T)}}}}finally{s?.removeEventListener("abort",i),t.releaseLock()}}import{computed as ye,ref as te,watch as Ce}from"vue";import{computed as ce,reactive as ue,ref as j,watch as ge}from"vue";var K=(e={})=>{let{fallbackRole:n="assistant",...t}=e;return{name:"fallbackRole",...t,onBeforeRequest(s){let{requestBody:r,messages:a}=s;return r.messages=a.map(i=>({...i,role:i.role||n})),t.onBeforeRequest?.(s)}}};var z=(e={})=>{let{continueContent:n="Please continue with your previous answer.",...t}=e;return{name:"length",...t,onAfterRequest:async s=>{let{lastChoice:r,appendMessage:a,requestNext:i}=s;return r?.finish_reason==="length"&&(a({role:"user",content:n}),i()),t.onAfterRequest?.(s)}}};var J=(e={})=>({name:"thinking",...e,onCompletionChunk(n){let{choice:t,currentMessage:s}=n,a=typeof(t?.message?.reasoning_content||t?.delta?.reasoning_content)=="string";return s.state?s.state.thinking=a:s.state={thinking:a},e.onCompletionChunk?.(n)},onTurnEnd(n){let t=n.currentTurn.slice(-1)[0];return t?.state&&(t.state.thinking=void 0),e.onTurnEnd?.(n)}});import{reactive as re}from"vue";var I=class extends Error{constructor(n){super(n),this.name="AbortError"}};function oe(e){if(e.aborted)return{promise:Promise.reject(new I(String(e.reason??"Aborted"))),cleanup:()=>{}};let n=null;return{promise:new Promise((r,a)=>{n=()=>{a(new I(String(e.reason??"Aborted")))},e.addEventListener("abort",n,{once:!0})}),cleanup:()=>{n&&(e.removeEventListener("abort",n),n=null)}}}function Q(e,n){let{promise:t,cleanup:s}=oe(n);return Promise.race([e,t]).finally(s)}function Y(e,n){let t={};for(let s of n)s in e&&(t[s]=e[s]);return t}async function*G(e){if(X(e)){yield*e;return}let n=await e;if(X(n)){yield*n;return}yield n}function X(e){return e&&typeof e=="object"&&typeof e[Symbol.asyncIterator]=="function"}var H=e=>typeof e=="object"&&e!==null,$=e=>H(e)&&typeof e.index=="number",N=(e,n)=>{for(let[t,s]of Object.entries(n)){let r=e[t];if(r)if(typeof r=="string"&&typeof s=="string")t==="type"&&r||(e[t]=r+s);else if(Array.isArray(r)&&Array.isArray(s))if(r.every(a=>$(a))&&s.every(a=>$(a))){let a=new Map(r.map(d=>[d.index,d])),i=new Map(s.map(d=>[d.index,d]));for(let[d,M]of i)if(a.has(d)){let A=a.get(d);a.set(d,N(A,M))}else a.set(d,M);let u=Math.max(...Array.from(a.keys()),-1)+1,y=u>r.length?Array.from({length:u}):r;for(let[d,M]of a)y[d]=M;e[t]=y}else e[t]=[...r,...s];else H(r)&&H(s)&&(e[t]=N(r,s));else e[t]=s}return e};function ae(e,n){let t=[];for(let s=0;s<e.length;s++){let r=e[s];if(r.role==="assistant"&&r.tool_calls&&r.tool_calls.length>0){let a=new Set(r.tool_calls.map(y=>y.id)),i=new Set;for(let y=s+1;y<e.length;y++){let d=e[y];d.role==="tool"&&d.tool_call_id&&a.has(d.tool_call_id)&&i.add(d.tool_call_id)}let u=r.tool_calls.map(y=>y.id).filter(y=>!i.has(y));u.length>0&&t.push({insertAfterIndex:s,missingToolCallIds:u})}}for(let s=t.length-1;s>=0;s--){let{insertAfterIndex:r,missingToolCallIds:a}=t[s],i=a.map(u=>({role:"tool",tool_call_id:u,content:n}));e.splice(r+1,0,...i)}}var ie="remove";function le(e,n,t,s){let r=e.filter(i=>i[t]),a=new Set(r.flatMap(i=>i.tool_calls?.map(u=>u.id)??[]));if(n===ie)for(let i=e.length-1;i>=0;i--){let u=e[i];(u[t]||u[s]||u.tool_call_id&&a.has(u.tool_call_id))&&e.splice(i,1)}else if(n===!0)for(let i of e)(i[t]||i.tool_call_id&&a.has(i.tool_call_id))&&(i[s]=!0,delete i[t])}var Re=e=>{let{getTools:n,beforeCallTools:t,callTool:s,onToolCallStart:r,onToolCallEnd:a,toolCallCancelledContent:i="Tool call cancelled.",toolCallFailedContent:u="Tool call failed.",autoFillMissingToolMessages:y=!1,excludeToolMessagesNextTurn:d=!1,...M}=e,A=Symbol("doNotSendNextTurn"),w=Symbol("doNotSend"),v=(...C)=>{let[p,{primaryMessage:o}]=C;o.state.toolCall[p.id].status="running",r?.(...C)},T=(...C)=>{let[p,{status:o,primaryMessage:l}]=C;l.state.toolCall[p.id].status=o,a?.(...C)};return{name:"tool",...M,onTurnStart:C=>{let{messages:p}=C;return y&&ae(p,i),d&&le(p,d,A,w),M.onTurnStart?.(C)},onBeforeRequest:async C=>{let{messages:p,requestBody:o}=C;d===!0&&(o.messages=p.filter(g=>!g[w]));let l=await n?.();return l&&l.length>0&&(o.tools=l),M.onBeforeRequest?.(C)},onAfterRequest:async C=>{let{currentMessage:p,lastChoice:o,appendMessage:l,abortSignal:g,setRequestState:f,requestNext:x}=C;if(o?.finish_reason!=="tool_calls"||!p.tool_calls?.length)return;d&&(p[A]=!0),f("processing","calling-tools"),await t?.(p.tool_calls,{...C,currentMessage:p});let E=p.tool_calls.map(async S=>{let q=Math.floor(Date.now()/1e3),O=re({role:"tool",tool_call_id:S.id,content:"",metadata:{createdAt:q,updatedAt:q}});l(O);let c={...C,primaryMessage:p,toolMessage:O};v(S,c);try{let h=s(S,c),b=G(h);for await(let _ of b){if(typeof _=="string")O.content+=_;else{let m={};try{m=JSON.parse(O.content||"{}")}catch(R){console.warn(R)}O.content=JSON.stringify(N(m,_))}O.metadata.updatedAt=Math.floor(Date.now()/1e3)}T(S,{...c,status:"success"})}catch(h){let b=h instanceof Error?h:new Error(String(h));if(g.aborted){T(S,{...c,status:"cancelled",error:b});return}console.error(h),O.content.length===0&&(O.content=u),T(S,{...c,status:"failed",error:b})}});return await Promise.all(E),x(),M.onAfterRequest?.(C)},onCompletionChunk:C=>{var o,l,g;let{currentMessage:p}=C;if(Array.isArray(p.tool_calls))for(let f of p.tool_calls)p.state?.toolCall?.[f.id]?.status||(p.state??(p.state={}),(o=p.state).toolCall??(o.toolCall={}),(l=p.state.toolCall)[g=f.id]??(l[g]={}));return M.onCompletionChunk?.(C)}}};var fe=e=>{let n=[];for(let t of e){if(t.name){let s=n.findIndex(r=>r.name===t.name);s!==-1&&n.splice(s,1)}n.push(t)}return n},V=e=>{let{initialMessages:n=[],requestMessageFields:t=["role","content","tool_calls","tool_call_id"],plugins:s=[],onCompletionChunk:r}=e,a=j("idle"),i=j(void 0),u=j(n),y=j(e.responseProvider),d=null,M=[],A={},w=[K(),J(),z()],v=fe(w.concat(s)),T=ce(()=>a.value==="processing"),C=async c=>{if(!c||!c.trim()){console.warn("Cannot send empty message");return}if(T.value){console.warn("Cannot send message while processing is in progress");return}let h=Math.floor(Date.now()/1e3);u.value.push({role:"user",content:c.trim(),metadata:{createdAt:h,updatedAt:h}}),M.push(u.value[u.value.length-1]),await E()},p=async(...c)=>{if(T.value){console.warn("Cannot send message while processing is in progress");return}u.value.push(...c),M.push(...c),await E()},o=c=>c.map(h=>Y(h,t)),l=(c,h)=>{a.value=c,c==="processing"?i.value=h||"requesting":i.value=void 0},g=c=>{Object.assign(A,c)},f=()=>({messages:u.value,currentTurn:M,requestState:a.value,processingState:i.value,requestMessageFields:t,plugins:v,setRequestState:l,customContext:A,setCustomContext:g}),x=async(c,h)=>{l("processing","requesting");let b=new Proxy({messages:o(u.value)},{set(k,P,U){return P==="messages"?(k.messages=o(U),!0):(k[P]=U,!0)}}),_=f();for(let k of v.filter(P=>!P.disabled))await k.onBeforeRequest?.({..._,abortSignal:h,requestBody:b});let m=ue({role:"",content:"",loading:!0});O(m);let R,W=c(b,h),D=G(W);for await(let k of D){l("processing","completing"),m.loading&&(m.loading=void 0);let P=k.choices?.find(F=>F.index===0);if(P){R=P;let F=()=>{m.metadata||(m.metadata={});let{created:B,...ne}=k;m.metadata.createdAt=B,m.metadata.updatedAt=Math.floor(Date.now()/1e3),Object.assign(m.metadata,ne),N(m,P.message||P.delta)};if(r){let B=f();r({...B,abortSignal:h,chunk:k,currentMessage:m},F)}else F()}let U=f();for(let F of v.filter(B=>!B.disabled))F.onCompletionChunk?.({...U,abortSignal:h,chunk:k,choice:P,currentMessage:m})}await q(m,c,h,R)},E=async()=>{let c=new AbortController;d=c;let h=y.value;A={};try{l("processing","requesting");let b=f();for(let m of v.filter(R=>!R.disabled))await m.onTurnStart?.({...b,abortSignal:c.signal});try{await x(h,c.signal),l("completed")}catch(m){if(c.signal.aborted||m instanceof I||m instanceof Error&&m.name==="AbortError")l("aborted");else throw m}let _=f();for(let m of v.filter(R=>!R.disabled))await m.onTurnEnd?.({..._,abortSignal:c.signal})}catch(b){l("error");let _=f();for(let m of v.filter(R=>!R.disabled))m.onError?.({..._,abortSignal:c.signal,error:b});throw b}finally{d=null,M.slice(-1)[0]&&(M.slice(-1)[0].loading=void 0),M=[]}},S=async()=>{d?.abort(),T.value&&await new Promise(c=>{let h=ge(T,b=>{b||(h(),c())},{immediate:!0})})},q=async(c,h,b,_)=>{let m=!1,R=f(),W=v.filter(D=>!D.disabled).map(D=>{if(!D.onAfterRequest)return null;let k=U=>{O(U)},P=()=>{m=!0};return D.onAfterRequest({...R,abortSignal:b,currentMessage:c,lastChoice:_,appendMessage:k,requestNext:P})}).filter(D=>D!==null);await Q(Promise.all(W),b),m&&await x(h,b)},O=c=>{let h=Array.isArray(c)?c:[c];u.value.push(...h),M.push(...h)};return{requestState:a,processingState:i,messages:u,responseProvider:y,isProcessing:T,sendMessage:C,send:p,abortRequest:S}};import{isRef as de,toValue as pe}from"vue";function ee(e,n=200,t=!1,s=!0,r=!1){return me(he(n,t,s,r),e)}function me(e,n){function t(...s){return new Promise((r,a)=>{Promise.resolve(e(()=>n.apply(this,s),{fn:n,thisArg:this,args:s})).then(r).catch(a)})}return t}var Z=()=>{};function he(...e){let n=0,t,s=!0,r=Z,a,i,u,y,d;!de(e[0])&&typeof e[0]=="object"?{delay:i,trailing:u=!0,leading:y=!0,rejectOnCancel:d=!1}=e[0]:[i,u=!0,y=!0,d=!1]=e;let M=()=>{t&&(clearTimeout(t),t=void 0,r(),r=Z)};return w=>{let v=pe(i),T=Date.now()-n,C=()=>a=w();return M(),v<=0?(n=Date.now(),C()):(T>v?(n=Date.now(),(y||!s)&&C()):u&&(a=new Promise((p,o)=>{r=d?o:p,t=setTimeout(()=>{n=Date.now(),s=!0,p(C()),M()},Math.max(0,v-T))})),!y&&!t&&(t=setTimeout(()=>s=!0,v)),s=!1,a)}}var Be=e=>{let n=te([]),t=new Map,s=new Map,r=te(null),a=ye(()=>{let o=r.value;if(!o)return null;let l=n.value.find(f=>f.id===o);if(!l)return null;let g=t.get(o);return g?{...l,engine:g}:null}),i=o=>{if(!e.storage?.saveMessages)return;let l=o||r.value,g=n.value.find(x=>x.id===l);if(!g)return;g.updatedAt=Date.now(),e.storage?.saveConversation?.(g);let f=t.get(g.id);f&&e.storage.saveMessages(g.id,f.messages.value)},u=(o,l)=>{if(!e.autoSaveMessages||!e.storage?.saveMessages)return;let g=s.get(o);g&&g();let f=e.autoSaveThrottle??1e3,x=ee(()=>{i(o)},f,!0,!0),E=Ce(l.messages,x,{deep:!0});s.set(o,E)},y=o=>{let l=s.get(o);l&&(l(),s.delete(o))};e.storage?.loadConversations&&Promise.resolve(e.storage.loadConversations()).then(o=>{n.value=o}).catch(o=>{console.error("[useConversation] loadConversations failed:",o)});let d=async(o,l)=>{let g=t.get(o);if(g)return g;let f=l?.initialMessages??e.useMessageOptions.initialMessages??[];if(e.storage?.loadMessages)try{f=await e.storage.loadMessages(o)}catch(E){console.error("[useConversation] loadMessages failed:",E)}let x=V({...e.useMessageOptions,...l,initialMessages:f});return t.set(o,x),u(o,x),x};function M(){return Date.now().toString(36)+Math.random().toString(36).substring(2,9)}let A=o=>{let{id:l=M(),title:g,metadata:f,useMessageOptions:x}=o||{},E=Date.now(),S={id:l,title:g,createdAt:E,updatedAt:E,metadata:f};n.value.unshift(S);let q=V({...e.useMessageOptions,...x});return t.set(l,q),u(l,q),e.storage?.saveConversation?.(S),e.storage?.saveMessages?.(l,q.messages.value),r.value=l,a.value},w=async o=>o?r.value===o?a.value:n.value.find(g=>g.id===o)?(await d(o),t.forEach((g,f)=>{if(f===o)return;g.isProcessing?.value||(y(f),t.delete(f))}),r.value=o,a.value):null:null;return{conversations:n,activeConversationId:r,activeConversation:a,createConversation:A,switchConversation:w,deleteConversation:async o=>{let l=n.value.findIndex(f=>f.id===o);if(l===-1)return;if(await t.get(o)?.abortRequest(),y(o),t.delete(o),n.value.splice(l,1),e.storage?.deleteConversation?.(o),r.value===o){let f=n.value[0];f?await w(f.id):r.value=null}},updateConversationTitle:(o,l)=>{let g=n.value.find(f=>f.id===o);g&&(g.title=l,g.updatedAt=Date.now(),e.storage?.saveConversation?.(g))},saveMessages:i,sendMessage:o=>{a.value?.engine.sendMessage(o)},abortActiveRequest:async()=>{await a.value?.engine.abortRequest()}}};export{ie as EXCLUDE_MODE_REMOVE,se as createSSEStreamGenerator,K as fallbackRolePlugin,z as lengthPlugin,J as thinkingPlugin,Re as toolPlugin,Be as useConversation,V as useMessage};
|
|
1
|
+
function H(e="The operation was aborted"){let s=new Error(e);return s.name="AbortError",s}async function*oe(e,s={}){let t=e.body?.getReader();if(!t)throw new Error("ReadableStream not supported");let{signal:n}=s,r=new TextDecoder,a="",l=()=>{t.cancel()};n?.addEventListener("abort",l);try{for(;;){if(n?.aborted)throw H();let g;try{g=await t.read()}catch(R){throw n?.aborted?H():R}let{done:y,value:f}=g;if(y){if(n?.aborted)throw H();return}let M=r.decode(f,{stream:!0});a+=M;let E=a.split(`
|
|
2
|
+
`);a=E.pop()||"";for(let R of E)if(R.trim()!==""&&R.startsWith("data: ")){let T=R.slice(6);if(T==="[DONE]")return;try{yield JSON.parse(T)}catch(x){console.warn("Failed to parse SSE data:",T,x)}}}}finally{n?.removeEventListener("abort",l),t.releaseLock()}}import{computed as Ce,ref as ne,watch as Me}from"vue";import{computed as ue,reactive as ge,ref as W,watch as fe}from"vue";var z=(e={})=>{let{fallbackRole:s="assistant",...t}=e;return{name:"fallbackRole",...t,onBeforeRequest(n){let{requestBody:r,messages:a}=n;return r.messages=a.map(l=>({...l,role:l.role||s})),t.onBeforeRequest?.(n)}}};var J=(e={})=>{let{continueContent:s="Please continue with your previous answer.",...t}=e;return{name:"length",...t,onAfterRequest:async n=>{let{lastChoice:r,appendMessage:a,requestNext:l}=n;return r?.finish_reason==="length"&&(a({role:"user",content:s}),l()),t.onAfterRequest?.(n)}}};var X=(e={})=>({name:"thinking",...e,onCompletionChunk(s){let{choice:t,currentMessage:n}=s,a=typeof(t?.message?.reasoning_content||t?.delta?.reasoning_content)=="string";return n.state?n.state.thinking=a:n.state={thinking:a},e.onCompletionChunk?.(s)},onTurnEnd(s){let t=s.currentTurn.slice(-1)[0];return t?.state&&(t.state.thinking=void 0),e.onTurnEnd?.(s)}});import{reactive as ae}from"vue";var B=class extends Error{constructor(s){super(s),this.name="AbortError"}};function re(e){if(e.aborted)return{promise:Promise.reject(new B(String(e.reason??"Aborted"))),cleanup:()=>{}};let s=null;return{promise:new Promise((r,a)=>{s=()=>{a(new B(String(e.reason??"Aborted")))},e.addEventListener("abort",s,{once:!0})}),cleanup:()=>{s&&(e.removeEventListener("abort",s),s=null)}}}function Y(e,s){let{promise:t,cleanup:n}=re(s);return Promise.race([e,t]).finally(n)}function Z(e,s){let t={};for(let n of s)n in e&&(t[n]=e[n]);return t}async function*j(e){if($(e)){yield*e;return}let s=await e;if($(s)){yield*s;return}yield s}function $(e){return e&&typeof e=="object"&&typeof e[Symbol.asyncIterator]=="function"}var V=e=>typeof e=="object"&&e!==null,Q=e=>V(e)&&typeof e.index=="number",N=(e,s)=>{for(let[t,n]of Object.entries(s)){let r=e[t];if(r)if(typeof r=="string"&&typeof n=="string")t==="type"&&r||(e[t]=r+n);else if(Array.isArray(r)&&Array.isArray(n))if(r.every(a=>Q(a))&&n.every(a=>Q(a))){let a=new Map(r.map(f=>[f.index,f])),l=new Map(n.map(f=>[f.index,f]));for(let[f,M]of l)if(a.has(f)){let E=a.get(f);a.set(f,N(E,M))}else a.set(f,M);let g=Math.max(...Array.from(a.keys()),-1)+1,y=g>r.length?Array.from({length:g}):r;for(let[f,M]of a)y[f]=M;e[t]=y}else e[t]=[...r,...n];else V(r)&&V(n)&&(e[t]=N(r,n));else e[t]=n}return e};function ie(e,s){let t=[];for(let n=0;n<e.length;n++){let r=e[n];if(r.role==="assistant"&&r.tool_calls&&r.tool_calls.length>0){let a=new Set(r.tool_calls.map(y=>y.id)),l=new Set;for(let y=n+1;y<e.length;y++){let f=e[y];f.role==="tool"&&f.tool_call_id&&a.has(f.tool_call_id)&&l.add(f.tool_call_id)}let g=r.tool_calls.map(y=>y.id).filter(y=>!l.has(y));g.length>0&&t.push({insertAfterIndex:n,missingToolCallIds:g})}}for(let n=t.length-1;n>=0;n--){let{insertAfterIndex:r,missingToolCallIds:a}=t[n],l=a.map(g=>({role:"tool",tool_call_id:g,content:s}));e.splice(r+1,0,...l)}}var le="remove";function ce(e,s,t,n){let r=e.filter(l=>l[t]),a=new Set(r.flatMap(l=>l.tool_calls?.map(g=>g.id)??[]));if(s===le)for(let l=e.length-1;l>=0;l--){let g=e[l];(g[t]||g[n]||g.tool_call_id&&a.has(g.tool_call_id))&&e.splice(l,1)}else if(s===!0)for(let l of e)(l[t]||l.tool_call_id&&a.has(l.tool_call_id))&&(l[n]=!0,delete l[t])}var Pe=e=>{let{getTools:s,beforeCallTools:t,callTool:n,onToolCallStart:r,onToolCallEnd:a,toolCallCancelledContent:l="Tool call cancelled.",toolCallFailedContent:g="Tool call failed.",autoFillMissingToolMessages:y=!1,excludeToolMessagesNextTurn:f=!1,...M}=e,E=Symbol("doNotSendNextTurn"),R=Symbol("doNotSend"),T=(...C)=>{let[p,{primaryMessage:b}]=C;b.state.toolCall[p.id].status="running",r?.(...C)},x=(...C)=>{let[p,{status:b,primaryMessage:o}]=C;o.state.toolCall[p.id].status=b,a?.(...C)};return{name:"tool",...M,onTurnStart:C=>{let{messages:p}=C;return y&&ie(p,l),f&&ce(p,f,E,R),M.onTurnStart?.(C)},onBeforeRequest:async C=>{let{messages:p,requestBody:b}=C;f===!0&&(b.messages=p.filter(u=>!u[R]));let o=await s?.();return o&&o.length>0&&(b.tools=o),M.onBeforeRequest?.(C)},onAfterRequest:async C=>{let{currentMessage:p,lastChoice:b,appendMessage:o,abortSignal:u,setRequestState:c,requestNext:m}=C;if(b?.finish_reason!=="tool_calls"||!p.tool_calls?.length)return;f&&(p[E]=!0),c("processing","calling-tools"),await t?.(p.tool_calls,{...C,currentMessage:p});let P=p.tool_calls.map(async w=>{let U=Math.floor(Date.now()/1e3),S=ae({role:"tool",tool_call_id:w.id,content:"",metadata:{createdAt:U,updatedAt:U}});o(S);let q={...C,primaryMessage:p,toolMessage:S};T(w,q);try{let i=n(w,q),h=j(i);for await(let v of h){if(typeof v=="string")S.content+=v;else{let A={};try{A=JSON.parse(S.content||"{}")}catch(d){console.warn(d)}S.content=JSON.stringify(N(A,v))}S.metadata.updatedAt=Math.floor(Date.now()/1e3)}x(w,{...q,status:"success"})}catch(i){let h=i instanceof Error?i:new Error(String(i));if(u.aborted){x(w,{...q,status:"cancelled",error:h});return}console.error(i),S.content.length===0&&(S.content=g),x(w,{...q,status:"failed",error:h})}});return await Promise.all(P),m(),M.onAfterRequest?.(C)},onCompletionChunk:C=>{var b,o,u;let{currentMessage:p}=C;if(Array.isArray(p.tool_calls))for(let c of p.tool_calls)p.state?.toolCall?.[c.id]?.status||(p.state??(p.state={}),(b=p.state).toolCall??(b.toolCall={}),(o=p.state.toolCall)[u=c.id]??(o[u]={}));return M.onCompletionChunk?.(C)}}};var de=e=>{let s=[];for(let t of e){if(t.name){let n=s.findIndex(r=>r.name===t.name);n!==-1&&s.splice(n,1)}s.push(t)}return s},K=e=>{let{initialMessages:s=[],requestMessageFields:t=["role","content","tool_calls","tool_call_id"],plugins:n=[],onCompletionChunk:r}=e,a=W("idle"),l=W(void 0),g=W(s),y=W(e.responseProvider),f=null,M=[],E={},R=[z(),X(),J()],T=de(R.concat(n)),x=ue(()=>a.value==="processing"),C=async i=>{if(!i||!i.trim()){console.warn("Cannot send empty message");return}if(x.value){console.warn("Cannot send message while processing is in progress");return}let h=Math.floor(Date.now()/1e3);g.value.push({role:"user",content:i.trim(),metadata:{createdAt:h,updatedAt:h}}),M.push(g.value[g.value.length-1]),await w()},p=async(...i)=>{if(x.value){console.warn("Cannot send message while processing is in progress");return}g.value.push(...i),M.push(...i),await w()},b=i=>i.map(h=>Z(h,t)),o=(i,h)=>{a.value=i,i==="processing"?l.value=h||"requesting":l.value=void 0},u=i=>{Object.assign(E,i)},c=i=>({messages:g.value,currentTurn:M,requestState:a.value,processingState:l.value,requestMessageFields:t,plugins:T,abortSignal:i,setRequestState:o,customContext:E,setCustomContext:u}),m=(i,h)=>typeof i.disabled=="function"?i.disabled(h):!!i.disabled,P=async(i,h)=>{o("processing","requesting");let v=new Proxy({messages:b(g.value)},{set(k,O,F){return O==="messages"?(k.messages=b(F),!0):(k[O]=F,!0)}}),A=c(h);for(let k of T.filter(O=>!m(O,A)))await k.onBeforeRequest?.({...A,requestBody:v});let d=ge({role:"",content:"",loading:!0});q(d);let _,L=i(v,h),D=j(L);for await(let k of D){o("processing","completing"),d.loading&&(d.loading=void 0);let O=k.choices?.find(I=>I.index===0);if(O){_=O;let I=()=>{d.metadata||(d.metadata={});let{created:G,...se}=k;d.metadata.createdAt=G,d.metadata.updatedAt=Math.floor(Date.now()/1e3),Object.assign(d.metadata,se),N(d,O.message||O.delta)};if(r){let G=c(h);r({...G,chunk:k,choice:O,currentMessage:d},I)}else I()}let F=c(h);for(let I of T.filter(G=>!m(G,F)))I.onCompletionChunk?.({...F,abortSignal:h,chunk:k,choice:O,currentMessage:d})}await S(d,i,h,_)},w=async()=>{let i=new AbortController;f=i;let h=y.value;E={};try{o("processing","requesting");let v=c(i.signal);for(let d of T.filter(_=>!m(_,v)))await d.onTurnStart?.(v);try{await P(h,i.signal),o("completed")}catch(d){if(i.signal.aborted||d instanceof B||d instanceof Error&&d.name==="AbortError")o("aborted");else throw d}let A=c(i.signal);for(let d of T.filter(_=>!m(_,A)))await d.onTurnEnd?.(A)}catch(v){o("error");let A=c(i.signal);for(let d of T.filter(_=>!m(_,A)))d.onError?.({...A,error:v});throw v}finally{let v=c(i.signal);for(let A of T.filter(d=>!m(d,v)))try{A.onFinally?.(v)}catch(d){console.error(`Error in onFinally hook for plugin ${A.name||"Anonymous"}:`,d)}f=null,M.slice(-1)[0]&&(M.slice(-1)[0].loading=void 0),M=[]}},U=async()=>{f?.abort(),x.value&&await new Promise(i=>{let h=fe(x,v=>{v||(h(),i())},{immediate:!0})})},S=async(i,h,v,A)=>{let d=!1,_=c(v),L=T.filter(D=>!m(D,_)).map(D=>{if(!D.onAfterRequest)return null;let k=F=>{q(F)},O=()=>{d=!0};return D.onAfterRequest({..._,currentMessage:i,lastChoice:A,appendMessage:k,requestNext:O})}).filter(D=>D!==null);await Y(Promise.all(L),v),d&&await P(h,v)},q=i=>{let h=Array.isArray(i)?i:[i];g.value.push(...h),M.push(...h)};return{requestState:a,processingState:l,messages:g,responseProvider:y,isProcessing:x,sendMessage:C,send:p,abortRequest:U}};import{isRef as pe,toValue as me}from"vue";function te(e,s=200,t=!1,n=!0,r=!1){return he(ye(s,t,n,r),e)}function he(e,s){function t(...n){return new Promise((r,a)=>{Promise.resolve(e(()=>s.apply(this,n),{fn:s,thisArg:this,args:n})).then(r).catch(a)})}return t}var ee=()=>{};function ye(...e){let s=0,t,n=!0,r=ee,a,l,g,y,f;!pe(e[0])&&typeof e[0]=="object"?{delay:l,trailing:g=!0,leading:y=!0,rejectOnCancel:f=!1}=e[0]:[l,g=!0,y=!0,f=!1]=e;let M=()=>{t&&(clearTimeout(t),t=void 0,r(),r=ee)};return R=>{let T=me(l),x=Date.now()-s,C=()=>a=R();return M(),T<=0?(s=Date.now(),C()):(x>T?(s=Date.now(),(y||!n)&&C()):g&&(a=new Promise((p,b)=>{r=f?b:p,t=setTimeout(()=>{s=Date.now(),n=!0,p(C()),M()},Math.max(0,T-x))})),!y&&!t&&(t=setTimeout(()=>n=!0,T)),n=!1,a)}}var Ge=e=>{let s=ne([]),t=new Map,n=new Map,r=ne(null),a=Ce(()=>{let o=r.value;if(!o)return null;let u=s.value.find(m=>m.id===o);if(!u)return null;let c=t.get(o);return c?{...u,engine:c}:null}),l=o=>{if(!e.storage?.saveMessages)return;let u=o||r.value,c=s.value.find(P=>P.id===u);if(!c)return;c.updatedAt=Date.now(),e.storage?.saveConversation?.(c);let m=t.get(c.id);m&&e.storage.saveMessages(c.id,m.messages.value)},g=(o,u)=>{if(!e.autoSaveMessages||!e.storage?.saveMessages)return;let c=n.get(o);c&&c();let m=e.autoSaveThrottle??1e3,P=te(()=>{l(o)},m,!0,!0),w=Me(u.messages,P,{deep:!0});n.set(o,w)},y=o=>{let u=n.get(o);u&&(u(),n.delete(o))};e.storage?.loadConversations&&Promise.resolve(e.storage.loadConversations()).then(o=>{s.value=o}).catch(o=>{console.error("[useConversation] loadConversations failed:",o)});let f=async(o,u)=>{let c=t.get(o);if(c)return c;let m=u?.initialMessages??e.useMessageOptions.initialMessages??[];if(e.storage?.loadMessages)try{m=await e.storage.loadMessages(o)}catch(w){console.error("[useConversation] loadMessages failed:",w)}let P=K({...e.useMessageOptions,...u,initialMessages:m});return t.set(o,P),g(o,P),P};function M(){return Date.now().toString(36)+Math.random().toString(36).substring(2,9)}let E=o=>{let{id:u=M(),title:c,metadata:m,useMessageOptions:P}=o||{},w=Date.now(),U={id:u,title:c,createdAt:w,updatedAt:w,metadata:m};s.value.unshift(U);let S=K({...e.useMessageOptions,...P});return t.set(u,S),g(u,S),e.storage?.saveConversation?.(U),e.storage?.saveMessages?.(u,S.messages.value),r.value=u,a.value},R=o=>{let{excludeId:u}=o||{};t.forEach((c,m)=>{if(u&&m===u)return;c.isProcessing?.value||(y(m),t.delete(m))})};return{conversations:s,activeConversationId:r,activeConversation:a,createConversation:E,switchConversation:async o=>o?r.value===o?a.value:s.value.find(c=>c.id===o)?(await f(o),R({excludeId:o}),r.value=o,a.value):null:null,deleteConversation:async o=>{let u=s.value.findIndex(m=>m.id===o);if(u===-1)return;await t.get(o)?.abortRequest(),y(o),t.delete(o),s.value.splice(u,1),e.storage?.deleteConversation?.(o),r.value===o&&(r.value=null,R())},updateConversationTitle:(o,u)=>{let c=s.value.find(m=>m.id===o);c&&(c.title=u,c.updatedAt=Date.now(),e.storage?.saveConversation?.(c))},saveMessages:l,sendMessage:o=>{a.value?.engine.sendMessage(o)},abortActiveRequest:async()=>{await a.value?.engine.abortRequest()}}};export{le as EXCLUDE_MODE_REMOVE,oe as createSSEStreamGenerator,z as fallbackRolePlugin,J as lengthPlugin,X as thinkingPlugin,Pe as toolPlugin,Ge as useConversation,K 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.3",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"access": "public"
|
|
6
6
|
},
|
|
@@ -26,5 +26,8 @@
|
|
|
26
26
|
"peerDependencies": {
|
|
27
27
|
"vue": ">=3.0.0"
|
|
28
28
|
},
|
|
29
|
-
"
|
|
29
|
+
"dependencies": {
|
|
30
|
+
"idb": "^8.0.3"
|
|
31
|
+
},
|
|
32
|
+
"gitHead": "1cbef7678ff29993a748a1664119d53e6074f9df"
|
|
30
33
|
}
|