@opentiny/tiny-robot-kit 0.4.0-alpha.2 → 0.4.0-alpha.4

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 CHANGED
@@ -33,6 +33,7 @@ interface MessageMetadata {
33
33
  interface ChatMessage {
34
34
  role: string;
35
35
  content: string;
36
+ reasoning_content?: string;
36
37
  metadata?: MessageMetadata;
37
38
  tool_calls?: ToolCall[];
38
39
  tool_call_id?: string;
@@ -101,7 +102,16 @@ interface ChatCompletion {
101
102
  }
102
103
  interface UseMessageOptions {
103
104
  initialMessages?: ChatMessage[];
104
- requestMessageFields?: (keyof ChatMessage)[];
105
+ /**
106
+ * 请求消息时,要包含的字段(白名单)。默认包含所有字段。
107
+ * 如果 `requestMessageFieldsExclude` 存在,会先取 `requestMessageFields` 中的字段,再排除 `requestMessageFieldsExclude` 中的字段
108
+ */
109
+ requestMessageFields?: string[];
110
+ /**
111
+ * 请求消息时,要排除的字段(黑名单)。默认会排除 `state`、`metadata`、`loading` 字段(这几个字段是给UI展示用的)。
112
+ * 如果 `requestMessageFields` 存在,会先取 `requestMessageFields` 中的字段,再排除 `requestMessageFieldsExclude` 中的字段
113
+ */
114
+ requestMessageFieldsExclude?: string[];
105
115
  plugins?: UseMessagePlugin[];
106
116
  responseProvider: <T = ChatCompletion>(requestBody: MessageRequestBody, abortSignal: AbortSignal) => Promise<T> | AsyncGenerator<T> | Promise<AsyncGenerator<T>>;
107
117
  /**
@@ -111,6 +121,7 @@ interface UseMessageOptions {
111
121
  */
112
122
  onCompletionChunk?: (context: BasePluginContext & {
113
123
  currentMessage: ChatMessage;
124
+ choice: CompletionChoice;
114
125
  chunk: ChatCompletion;
115
126
  }, runDefault: () => void) => void;
116
127
  }
@@ -129,7 +140,6 @@ interface BasePluginContext {
129
140
  currentTurn: ChatMessage[];
130
141
  requestState: RequestState;
131
142
  processingState?: RequestProcessingState;
132
- requestMessageFields: (keyof ChatMessage)[];
133
143
  plugins: UseMessagePlugin[];
134
144
  setRequestState: (state: RequestState, processingState?: RequestProcessingState) => void;
135
145
  abortSignal: AbortSignal;
@@ -150,7 +160,7 @@ interface UseMessagePlugin {
150
160
  /**
151
161
  * 是否禁用插件。useMessage 可能会内置一些默认插件,如果需要禁用,可以设置为 true。
152
162
  */
153
- disabled?: boolean;
163
+ disabled?: boolean | ((context: BasePluginContext) => boolean);
154
164
  /**
155
165
  * 一次对话回合(turn)开始钩子:用户消息入队后、正式发起请求之前触发。
156
166
  * 按插件注册顺序串行执行,便于做有序初始化/校验;出错则中断流程。
@@ -195,6 +205,7 @@ interface UseMessagePlugin {
195
205
  onError?: (context: BasePluginContext & {
196
206
  error: unknown;
197
207
  }) => void;
208
+ onFinally?: (context: BasePluginContext) => void;
198
209
  }
199
210
 
200
211
  interface ConversationInfo {
package/dist/index.d.ts CHANGED
@@ -33,6 +33,7 @@ interface MessageMetadata {
33
33
  interface ChatMessage {
34
34
  role: string;
35
35
  content: string;
36
+ reasoning_content?: string;
36
37
  metadata?: MessageMetadata;
37
38
  tool_calls?: ToolCall[];
38
39
  tool_call_id?: string;
@@ -101,7 +102,16 @@ interface ChatCompletion {
101
102
  }
102
103
  interface UseMessageOptions {
103
104
  initialMessages?: ChatMessage[];
104
- requestMessageFields?: (keyof ChatMessage)[];
105
+ /**
106
+ * 请求消息时,要包含的字段(白名单)。默认包含所有字段。
107
+ * 如果 `requestMessageFieldsExclude` 存在,会先取 `requestMessageFields` 中的字段,再排除 `requestMessageFieldsExclude` 中的字段
108
+ */
109
+ requestMessageFields?: string[];
110
+ /**
111
+ * 请求消息时,要排除的字段(黑名单)。默认会排除 `state`、`metadata`、`loading` 字段(这几个字段是给UI展示用的)。
112
+ * 如果 `requestMessageFields` 存在,会先取 `requestMessageFields` 中的字段,再排除 `requestMessageFieldsExclude` 中的字段
113
+ */
114
+ requestMessageFieldsExclude?: string[];
105
115
  plugins?: UseMessagePlugin[];
106
116
  responseProvider: <T = ChatCompletion>(requestBody: MessageRequestBody, abortSignal: AbortSignal) => Promise<T> | AsyncGenerator<T> | Promise<AsyncGenerator<T>>;
107
117
  /**
@@ -111,6 +121,7 @@ interface UseMessageOptions {
111
121
  */
112
122
  onCompletionChunk?: (context: BasePluginContext & {
113
123
  currentMessage: ChatMessage;
124
+ choice: CompletionChoice;
114
125
  chunk: ChatCompletion;
115
126
  }, runDefault: () => void) => void;
116
127
  }
@@ -129,7 +140,6 @@ interface BasePluginContext {
129
140
  currentTurn: ChatMessage[];
130
141
  requestState: RequestState;
131
142
  processingState?: RequestProcessingState;
132
- requestMessageFields: (keyof ChatMessage)[];
133
143
  plugins: UseMessagePlugin[];
134
144
  setRequestState: (state: RequestState, processingState?: RequestProcessingState) => void;
135
145
  abortSignal: AbortSignal;
@@ -150,7 +160,7 @@ interface UseMessagePlugin {
150
160
  /**
151
161
  * 是否禁用插件。useMessage 可能会内置一些默认插件,如果需要禁用,可以设置为 true。
152
162
  */
153
- disabled?: boolean;
163
+ disabled?: boolean | ((context: BasePluginContext) => boolean);
154
164
  /**
155
165
  * 一次对话回合(turn)开始钩子:用户消息入队后、正式发起请求之前触发。
156
166
  * 按插件注册顺序串行执行,便于做有序初始化/校验;出错则中断流程。
@@ -195,6 +205,7 @@ interface UseMessagePlugin {
195
205
  onError?: (context: BasePluginContext & {
196
206
  error: unknown;
197
207
  }) => void;
208
+ onFinally?: (context: BasePluginContext) => void;
198
209
  }
199
210
 
200
211
  interface ConversationInfo {
package/dist/index.js CHANGED
@@ -1,2 +1,2 @@
1
- "use strict";var K=Object.defineProperty;var le=Object.getOwnPropertyDescriptor;var ce=Object.getOwnPropertyNames;var ue=Object.prototype.hasOwnProperty;var ge=(e,t)=>{for(var n in t)K(e,n,{get:t[n],enumerable:!0})},fe=(e,t,n,s)=>{if(t&&typeof t=="object"||typeof t=="function")for(let o of ce(t))!ue.call(e,o)&&o!==n&&K(e,o,{get:()=>t[o],enumerable:!(s=le(t,o))||s.enumerable});return e};var de=e=>fe(K({},"__esModule",{value:!0}),e);var Te={};ge(Te,{EXCLUDE_MODE_REMOVE:()=>oe,createSSEStreamGenerator:()=>Y,fallbackRolePlugin:()=>J,lengthPlugin:()=>X,thinkingPlugin:()=>$,toolPlugin:()=>ye,useConversation:()=>be,useMessage:()=>L});module.exports=de(Te);function z(e="The operation was aborted"){let t=new Error(e);return t.name="AbortError",t}async function*Y(e,t={}){let n=e.body?.getReader();if(!n)throw new Error("ReadableStream not supported");let{signal:s}=t,o=new TextDecoder,a="",i=()=>{n.cancel()};s?.addEventListener("abort",i);try{for(;;){if(s?.aborted)throw z();let u;try{u=await n.read()}catch(w){throw s?.aborted?z():w}let{done:y,value:d}=u;if(y){if(s?.aborted)throw z();return}let M=o.decode(d,{stream:!0});a+=M;let A=a.split(`
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 J=Object.defineProperty;var ge=Object.getOwnPropertyDescriptor;var fe=Object.getOwnPropertyNames;var de=Object.prototype.hasOwnProperty;var pe=(e,t)=>{for(var n in t)J(e,n,{get:t[n],enumerable:!0})},me=(e,t,n,s)=>{if(t&&typeof t=="object"||typeof t=="function")for(let o of fe(t))!de.call(e,o)&&o!==n&&J(e,o,{get:()=>t[o],enumerable:!(s=ge(t,o))||s.enumerable});return e};var he=e=>me(J({},"__esModule",{value:!0}),e);var Ae={};pe(Ae,{EXCLUDE_MODE_REMOVE:()=>ie,createSSEStreamGenerator:()=>ee,fallbackRolePlugin:()=>$,lengthPlugin:()=>Q,thinkingPlugin:()=>Y,toolPlugin:()=>ve,useConversation:()=>xe,useMessage:()=>H});module.exports=he(Ae);function X(e="The operation was aborted"){let t=new Error(e);return t.name="AbortError",t}async function*ee(e,t={}){let n=e.body?.getReader();if(!n)throw new Error("ReadableStream not supported");let{signal:s}=t,o=new TextDecoder,a="",i=()=>{n.cancel()};s?.addEventListener("abort",i);try{for(;;){if(s?.aborted)throw X();let p;try{p=await n.read()}catch(x){throw s?.aborted?X():x}let{done:g,value:f}=p;if(g){if(s?.aborted)throw X();return}let v=o.decode(f,{stream:!0});a+=v;let w=a.split(`
2
+ `);a=w.pop()||"";for(let x of w)if(x.trim()!==""&&x.startsWith("data: ")){let S=x.slice(6);if(S==="[DONE]")return;try{yield JSON.parse(S)}catch(b){console.warn("Failed to parse SSE data:",S,b)}}}}finally{s?.removeEventListener("abort",i),n.releaseLock()}}var N=require("vue");var q=require("vue");var $=(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 Q=(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 Y=(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 ae=require("vue");var j=class extends Error{constructor(t){super(t),this.name="AbortError"}};function ye(e){if(e.aborted)return{promise:Promise.reject(new j(String(e.reason??"Aborted"))),cleanup:()=>{}};let t=null;return{promise:new Promise((o,a)=>{t=()=>{a(new j(String(e.reason??"Aborted")))},e.addEventListener("abort",t,{once:!0})}),cleanup:()=>{t&&(e.removeEventListener("abort",t),t=null)}}}function se(e,t){let{promise:n,cleanup:s}=ye(t);return Promise.race([e,n]).finally(s)}function oe(e,t){let n={};for(let s in e)t.includes(s)&&(n[s]=e[s]);return n}function re(e,t){let n={};for(let s in e)t.includes(s)||(n[s]=e[s]);return n}async function*L(e){if(te(e)){yield*e;return}let t=await e;if(te(t)){yield*t;return}yield t}function te(e){return e&&typeof e=="object"&&typeof e[Symbol.asyncIterator]=="function"}var Z=e=>typeof e=="object"&&e!==null,ne=e=>Z(e)&&typeof e.index=="number",W=(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=>ne(a))&&s.every(a=>ne(a))){let a=new Map(o.map(f=>[f.index,f])),i=new Map(s.map(f=>[f.index,f]));for(let[f,v]of i)if(a.has(f)){let w=a.get(f);a.set(f,W(w,v))}else a.set(f,v);let p=Math.max(...Array.from(a.keys()),-1)+1,g=p>o.length?Array.from({length:p}):o;for(let[f,v]of a)g[f]=v;e[n]=g}else e[n]=[...o,...s];else Z(o)&&Z(s)&&(e[n]=W(o,s));else e[n]=s}return e};function Ce(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(g=>g.id)),i=new Set;for(let g=s+1;g<e.length;g++){let f=e[g];f.role==="tool"&&f.tool_call_id&&a.has(f.tool_call_id)&&i.add(f.tool_call_id)}let p=o.tool_calls.map(g=>g.id).filter(g=>!i.has(g));p.length>0&&n.push({insertAfterIndex:s,missingToolCallIds:p})}}for(let s=n.length-1;s>=0;s--){let{insertAfterIndex:o,missingToolCallIds:a}=n[s],i=a.map(p=>({role:"tool",tool_call_id:p,content:t}));e.splice(o+1,0,...i)}}var ie="remove";function Me(e,t,n,s){let o=e.filter(i=>i[n]),a=new Set(o.flatMap(i=>i.tool_calls?.map(p=>p.id)??[]));if(t===ie)for(let i=e.length-1;i>=0;i--){let p=e[i];(p[n]||p[s]||p.tool_call_id&&a.has(p.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 ve=e=>{let{getTools:t,beforeCallTools:n,callTool:s,onToolCallStart:o,onToolCallEnd:a,toolCallCancelledContent:i="Tool call cancelled.",toolCallFailedContent:p="Tool call failed.",autoFillMissingToolMessages:g=!1,excludeToolMessagesNextTurn:f=!1,...v}=e,w=Symbol("doNotSendNextTurn"),x=Symbol("doNotSend"),S=(...m)=>{let[h,{primaryMessage:A}]=m;A.state.toolCall[h.id].status="running",o?.(...m)},b=(...m)=>{let[h,{status:A,primaryMessage:r}]=m;r.state.toolCall[h.id].status=A,a?.(...m)};return{name:"tool",...v,onTurnStart:m=>{let{messages:h}=m;return g&&Ce(h,i),f&&Me(h,f,w,x),v.onTurnStart?.(m)},onBeforeRequest:async m=>{let{messages:h,requestBody:A}=m;f===!0&&(A.messages=h.filter(c=>!c[x]));let r=await t?.();return r&&r.length>0&&(A.tools=r),v.onBeforeRequest?.(m)},onAfterRequest:async m=>{let{currentMessage:h,lastChoice:A,appendMessage:r,abortSignal:c,setRequestState:d,requestNext:y}=m;if(A?.finish_reason!=="tool_calls"||!h.tool_calls?.length)return;f&&(h[w]=!0),d("processing","calling-tools"),await n?.(h.tool_calls,{...m,currentMessage:h});let T=h.tool_calls.map(async R=>{let D=Math.floor(Date.now()/1e3),E=(0,ae.reactive)({role:"tool",tool_call_id:R.id,content:"",metadata:{createdAt:D,updatedAt:D}});r(E);let I={...m,primaryMessage:h,toolMessage:E};S(R,I);try{let F=s(R,I),l=L(F);for await(let u of l){if(typeof u=="string")E.content+=u;else{let M={};try{M=JSON.parse(E.content||"{}")}catch(P){console.warn(P)}E.content=JSON.stringify(W(M,u))}E.metadata.updatedAt=Math.floor(Date.now()/1e3)}b(R,{...I,status:"success"})}catch(F){let l=F instanceof Error?F:new Error(String(F));if(c.aborted){b(R,{...I,status:"cancelled",error:l});return}console.error(F),E.content.length===0&&(E.content=p),b(R,{...I,status:"failed",error:l})}});return await Promise.all(T),y(),v.onAfterRequest?.(m)},onCompletionChunk:m=>{var A,r,c;let{currentMessage:h}=m;if(Array.isArray(h.tool_calls))for(let d of h.tool_calls)h.state?.toolCall?.[d.id]?.status||(h.state??(h.state={}),(A=h.state).toolCall??(A.toolCall={}),(r=h.state.toolCall)[c=d.id]??(r[c]={}));return v.onCompletionChunk?.(m)}}};var Te=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},H=e=>{let{initialMessages:t=[],requestMessageFields:n=[],requestMessageFieldsExclude:s=["state","metadata","loading"],plugins:o=[],onCompletionChunk:a}=e,i=(0,q.ref)("idle"),p=(0,q.ref)(void 0),g=(0,q.ref)(t),f=(0,q.ref)(e.responseProvider),v=null,w=[],x={},S=[$(),Y(),Q()],b=Te(S.concat(o)),m=(0,q.computed)(()=>i.value==="processing"),h=async l=>{if(!l||!l.trim()){console.warn("Cannot send empty message");return}if(m.value){console.warn("Cannot send message while processing is in progress");return}let u=Math.floor(Date.now()/1e3);g.value.push({role:"user",content:l.trim(),metadata:{createdAt:u,updatedAt:u}}),w.push(g.value[g.value.length-1]),await D()},A=async(...l)=>{if(m.value){console.warn("Cannot send message while processing is in progress");return}g.value.push(...l),w.push(...l),await D()},r=l=>{let u=l;return n.length&&(u=u.map(M=>oe(M,n))),s.length&&(u=u.map(M=>re(M,s))),u},c=(l,u)=>{i.value=l,l==="processing"?p.value=u||"requesting":p.value=void 0},d=l=>{Object.assign(x,l)},y=l=>({messages:g.value,currentTurn:w,requestState:i.value,processingState:p.value,plugins:b,abortSignal:l,setRequestState:c,customContext:x,setCustomContext:d}),T=(l,u)=>typeof l.disabled=="function"?l.disabled(u):!!l.disabled,R=async(l,u)=>{c("processing","requesting");let M=new Proxy({messages:r(g.value)},{set(_,O,B){return O==="messages"?(_.messages=r(B),!0):(_[O]=B,!0)}}),P=y(u);for(let _ of b.filter(O=>!T(O,P)))await _.onBeforeRequest?.({...P,requestBody:M});let C=(0,q.reactive)({role:"",content:"",loading:!0});F(C);let k,z=l(M,u),U=L(z);for await(let _ of U){c("processing","completing"),C.loading&&(C.loading=void 0);let O=_.choices?.find(G=>G.index===0);if(O){k=O;let G=()=>{C.metadata||(C.metadata={});let{created:K,...ue}=_;C.metadata.createdAt=K,C.metadata.updatedAt=Math.floor(Date.now()/1e3),Object.assign(C.metadata,ue),W(C,O.message||O.delta)};if(a){let K=y(u);a({...K,chunk:_,choice:O,currentMessage:C},G)}else G()}let B=y(u);for(let G of b.filter(K=>!T(K,B)))G.onCompletionChunk?.({...B,abortSignal:u,chunk:_,choice:O,currentMessage:C})}await I(C,l,u,k)},D=async()=>{let l=new AbortController;v=l,x={};try{c("processing","requesting");let u=y(l.signal);for(let C of b.filter(k=>!T(k,u)))await C.onTurnStart?.(u);let M=f.value;try{await R(M,l.signal),c("completed")}catch(C){if(l.signal.aborted||C instanceof j||C instanceof Error&&C.name==="AbortError")c("aborted");else throw C}let P=y(l.signal);for(let C of b.filter(k=>!T(k,P)))await C.onTurnEnd?.(P)}catch(u){c("error");let M=!1,P=y(l.signal);for(let C of b.filter(k=>!T(k,P)))M=!0,C.onError?.({...P,error:u});if(!M)throw u}finally{let u=y(l.signal);for(let M of b.filter(P=>!T(P,u)))try{M.onFinally?.(u)}catch(P){console.error(`Error in onFinally hook for plugin ${M.name||"Anonymous"}:`,P)}v=null,w.slice(-1)[0]&&(w.slice(-1)[0].loading=void 0),w=[]}},E=async()=>{v?.abort(),m.value&&await new Promise(l=>{let u=(0,q.watch)(m,M=>{M||(u(),l())},{immediate:!0})})},I=async(l,u,M,P)=>{let C=!1,k=y(M),z=b.filter(U=>!T(U,k)).map(U=>{if(!U.onAfterRequest)return null;let _=B=>{F(B)},O=()=>{C=!0};return U.onAfterRequest({...k,currentMessage:l,lastChoice:P,appendMessage:_,requestNext:O})}).filter(U=>U!==null);await se(Promise.all(z),M),C&&await R(u,M)},F=l=>{let u=Array.isArray(l)?l:[l];g.value.push(...u),w.push(...u)};return{requestState:i,processingState:p,messages:g,responseProvider:f,isProcessing:m,sendMessage:h,send:A,abortRequest:E}};var V=require("vue");function ce(e,t=200,n=!1,s=!0,o=!1){return be(we(t,n,s,o),e)}function be(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 le=()=>{};function we(...e){let t=0,n,s=!0,o=le,a,i,p,g,f;!(0,V.isRef)(e[0])&&typeof e[0]=="object"?{delay:i,trailing:p=!0,leading:g=!0,rejectOnCancel:f=!1}=e[0]:[i,p=!0,g=!0,f=!1]=e;let v=()=>{n&&(clearTimeout(n),n=void 0,o(),o=le)};return x=>{let S=(0,V.toValue)(i),b=Date.now()-t,m=()=>a=x();return v(),S<=0?(t=Date.now(),m()):(b>S?(t=Date.now(),(g||!s)&&m()):p&&(a=new Promise((h,A)=>{o=f?A:h,n=setTimeout(()=>{t=Date.now(),s=!0,h(m()),v()},Math.max(0,S-b))})),!g&&!n&&(n=setTimeout(()=>s=!0,S)),s=!1,a)}}var xe=e=>{let t=(0,N.ref)([]),n=new Map,s=new Map,o=(0,N.ref)(null),a=(0,N.computed)(()=>{let r=o.value;if(!r)return null;let c=t.value.find(y=>y.id===r);if(!c)return null;let d=n.get(r);return d?{...c,engine:d}:null}),i=r=>{if(!e.storage?.saveMessages)return;let c=r||o.value,d=t.value.find(T=>T.id===c);if(!d)return;d.updatedAt=Date.now(),e.storage?.saveConversation?.(d);let y=n.get(d.id);y&&e.storage.saveMessages(d.id,y.messages.value)},p=(r,c)=>{if(!e.autoSaveMessages||!e.storage?.saveMessages)return;let d=s.get(r);d&&d();let y=e.autoSaveThrottle??1e3,T=ce(()=>{i(r)},y,!0,!0),R=(0,N.watch)(c.messages,T,{deep:!0});s.set(r,R)},g=r=>{let c=s.get(r);c&&(c(),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 f=async(r,c)=>{let d=n.get(r);if(d)return d;let y=c?.initialMessages??e.useMessageOptions.initialMessages??[];if(e.storage?.loadMessages)try{y=await e.storage.loadMessages(r)}catch(R){console.error("[useConversation] loadMessages failed:",R)}let T=H({...e.useMessageOptions,...c,initialMessages:y});return n.set(r,T),p(r,T),T};function v(){return Date.now().toString(36)+Math.random().toString(36).substring(2,9)}let w=r=>{let{id:c=v(),title:d,metadata:y,useMessageOptions:T}=r||{},R=Date.now(),D={id:c,title:d,createdAt:R,updatedAt:R,metadata:y};t.value.unshift(D);let E=H({...e.useMessageOptions,...T});return n.set(c,E),p(c,E),e.storage?.saveConversation?.(D),e.storage?.saveMessages?.(c,E.messages.value),o.value=c,a.value},x=r=>{let{excludeId:c}=r||{};n.forEach((d,y)=>{if(c&&y===c)return;d.isProcessing?.value||(g(y),n.delete(y))})};return{conversations:t,activeConversationId:o,activeConversation:a,createConversation:w,switchConversation:async r=>r?o.value===r?a.value:t.value.find(d=>d.id===r)?(await f(r),x({excludeId:r}),o.value=r,a.value):null:null,deleteConversation:async r=>{let c=t.value.findIndex(y=>y.id===r);if(c===-1)return;await n.get(r)?.abortRequest(),g(r),n.delete(r),t.value.splice(c,1),e.storage?.deleteConversation?.(r),o.value===r&&(o.value=null,x())},updateConversationTitle:(r,c)=>{let d=t.value.find(y=>y.id===r);d&&(d.title=c,d.updatedAt=Date.now(),e.storage?.saveConversation?.(d))},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});
package/dist/index.mjs CHANGED
@@ -1,2 +1,2 @@
1
- function L(e="The operation was aborted"){let n=new Error(e);return n.name="AbortError",n}async function*se(e,n={}){let t=e.body?.getReader();if(!t)throw new Error("ReadableStream not supported");let{signal:s}=n,r=new TextDecoder,a="",i=()=>{t.cancel()};s?.addEventListener("abort",i);try{for(;;){if(s?.aborted)throw L();let u;try{u=await t.read()}catch(w){throw s?.aborted?L():w}let{done:y,value:d}=u;if(y){if(s?.aborted)throw L();return}let M=r.decode(d,{stream:!0});a+=M;let A=a.split(`
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*ae(e,s={}){let t=e.body?.getReader();if(!t)throw new Error("ReadableStream not supported");let{signal:n}=s,r=new TextDecoder,a="",i=()=>{t.cancel()};n?.addEventListener("abort",i);try{for(;;){if(n?.aborted)throw H();let p;try{p=await t.read()}catch(x){throw n?.aborted?H():x}let{done:g,value:f}=p;if(g){if(n?.aborted)throw H();return}let v=r.decode(f,{stream:!0});a+=v;let w=a.split(`
2
+ `);a=w.pop()||"";for(let x of w)if(x.trim()!==""&&x.startsWith("data: ")){let S=x.slice(6);if(S==="[DONE]")return;try{yield JSON.parse(S)}catch(b){console.warn("Failed to parse SSE data:",S,b)}}}}finally{n?.removeEventListener("abort",i),t.releaseLock()}}import{computed as ve,ref as oe,watch as Te}from"vue";import{computed as fe,reactive as de,ref as K,watch as pe}from"vue";var J=(e={})=>{let{fallbackRole:s="assistant",...t}=e;return{name:"fallbackRole",...t,onBeforeRequest(n){let{requestBody:r,messages:a}=n;return r.messages=a.map(i=>({...i,role:i.role||s})),t.onBeforeRequest?.(n)}}};var X=(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:i}=n;return r?.finish_reason==="length"&&(a({role:"user",content:s}),i()),t.onAfterRequest?.(n)}}};var $=(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 le}from"vue";var N=class extends Error{constructor(s){super(s),this.name="AbortError"}};function ie(e){if(e.aborted)return{promise:Promise.reject(new N(String(e.reason??"Aborted"))),cleanup:()=>{}};let s=null;return{promise:new Promise((r,a)=>{s=()=>{a(new N(String(e.reason??"Aborted")))},e.addEventListener("abort",s,{once:!0})}),cleanup:()=>{s&&(e.removeEventListener("abort",s),s=null)}}}function Z(e,s){let{promise:t,cleanup:n}=ie(s);return Promise.race([e,t]).finally(n)}function ee(e,s){let t={};for(let n in e)s.includes(n)&&(t[n]=e[n]);return t}function te(e,s){let t={};for(let n in e)s.includes(n)||(t[n]=e[n]);return t}async function*W(e){if(Q(e)){yield*e;return}let s=await e;if(Q(s)){yield*s;return}yield s}function Q(e){return e&&typeof e=="object"&&typeof e[Symbol.asyncIterator]=="function"}var V=e=>typeof e=="object"&&e!==null,Y=e=>V(e)&&typeof e.index=="number",G=(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=>Y(a))&&n.every(a=>Y(a))){let a=new Map(r.map(f=>[f.index,f])),i=new Map(n.map(f=>[f.index,f]));for(let[f,v]of i)if(a.has(f)){let w=a.get(f);a.set(f,G(w,v))}else a.set(f,v);let p=Math.max(...Array.from(a.keys()),-1)+1,g=p>r.length?Array.from({length:p}):r;for(let[f,v]of a)g[f]=v;e[t]=g}else e[t]=[...r,...n];else V(r)&&V(n)&&(e[t]=G(r,n));else e[t]=n}return e};function ce(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(g=>g.id)),i=new Set;for(let g=n+1;g<e.length;g++){let f=e[g];f.role==="tool"&&f.tool_call_id&&a.has(f.tool_call_id)&&i.add(f.tool_call_id)}let p=r.tool_calls.map(g=>g.id).filter(g=>!i.has(g));p.length>0&&t.push({insertAfterIndex:n,missingToolCallIds:p})}}for(let n=t.length-1;n>=0;n--){let{insertAfterIndex:r,missingToolCallIds:a}=t[n],i=a.map(p=>({role:"tool",tool_call_id:p,content:s}));e.splice(r+1,0,...i)}}var ue="remove";function ge(e,s,t,n){let r=e.filter(i=>i[t]),a=new Set(r.flatMap(i=>i.tool_calls?.map(p=>p.id)??[]));if(s===ue)for(let i=e.length-1;i>=0;i--){let p=e[i];(p[t]||p[n]||p.tool_call_id&&a.has(p.tool_call_id))&&e.splice(i,1)}else if(s===!0)for(let i of e)(i[t]||i.tool_call_id&&a.has(i.tool_call_id))&&(i[n]=!0,delete i[t])}var Se=e=>{let{getTools:s,beforeCallTools:t,callTool:n,onToolCallStart:r,onToolCallEnd:a,toolCallCancelledContent:i="Tool call cancelled.",toolCallFailedContent:p="Tool call failed.",autoFillMissingToolMessages:g=!1,excludeToolMessagesNextTurn:f=!1,...v}=e,w=Symbol("doNotSendNextTurn"),x=Symbol("doNotSend"),S=(...m)=>{let[h,{primaryMessage:A}]=m;A.state.toolCall[h.id].status="running",r?.(...m)},b=(...m)=>{let[h,{status:A,primaryMessage:o}]=m;o.state.toolCall[h.id].status=A,a?.(...m)};return{name:"tool",...v,onTurnStart:m=>{let{messages:h}=m;return g&&ce(h,i),f&&ge(h,f,w,x),v.onTurnStart?.(m)},onBeforeRequest:async m=>{let{messages:h,requestBody:A}=m;f===!0&&(A.messages=h.filter(c=>!c[x]));let o=await s?.();return o&&o.length>0&&(A.tools=o),v.onBeforeRequest?.(m)},onAfterRequest:async m=>{let{currentMessage:h,lastChoice:A,appendMessage:o,abortSignal:c,setRequestState:d,requestNext:y}=m;if(A?.finish_reason!=="tool_calls"||!h.tool_calls?.length)return;f&&(h[w]=!0),d("processing","calling-tools"),await t?.(h.tool_calls,{...m,currentMessage:h});let T=h.tool_calls.map(async R=>{let F=Math.floor(Date.now()/1e3),E=le({role:"tool",tool_call_id:R.id,content:"",metadata:{createdAt:F,updatedAt:F}});o(E);let U={...m,primaryMessage:h,toolMessage:E};S(R,U);try{let q=n(R,U),l=W(q);for await(let u of l){if(typeof u=="string")E.content+=u;else{let M={};try{M=JSON.parse(E.content||"{}")}catch(P){console.warn(P)}E.content=JSON.stringify(G(M,u))}E.metadata.updatedAt=Math.floor(Date.now()/1e3)}b(R,{...U,status:"success"})}catch(q){let l=q instanceof Error?q:new Error(String(q));if(c.aborted){b(R,{...U,status:"cancelled",error:l});return}console.error(q),E.content.length===0&&(E.content=p),b(R,{...U,status:"failed",error:l})}});return await Promise.all(T),y(),v.onAfterRequest?.(m)},onCompletionChunk:m=>{var A,o,c;let{currentMessage:h}=m;if(Array.isArray(h.tool_calls))for(let d of h.tool_calls)h.state?.toolCall?.[d.id]?.status||(h.state??(h.state={}),(A=h.state).toolCall??(A.toolCall={}),(o=h.state.toolCall)[c=d.id]??(o[c]={}));return v.onCompletionChunk?.(m)}}};var me=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},z=e=>{let{initialMessages:s=[],requestMessageFields:t=[],requestMessageFieldsExclude:n=["state","metadata","loading"],plugins:r=[],onCompletionChunk:a}=e,i=K("idle"),p=K(void 0),g=K(s),f=K(e.responseProvider),v=null,w=[],x={},S=[J(),$(),X()],b=me(S.concat(r)),m=fe(()=>i.value==="processing"),h=async l=>{if(!l||!l.trim()){console.warn("Cannot send empty message");return}if(m.value){console.warn("Cannot send message while processing is in progress");return}let u=Math.floor(Date.now()/1e3);g.value.push({role:"user",content:l.trim(),metadata:{createdAt:u,updatedAt:u}}),w.push(g.value[g.value.length-1]),await F()},A=async(...l)=>{if(m.value){console.warn("Cannot send message while processing is in progress");return}g.value.push(...l),w.push(...l),await F()},o=l=>{let u=l;return t.length&&(u=u.map(M=>ee(M,t))),n.length&&(u=u.map(M=>te(M,n))),u},c=(l,u)=>{i.value=l,l==="processing"?p.value=u||"requesting":p.value=void 0},d=l=>{Object.assign(x,l)},y=l=>({messages:g.value,currentTurn:w,requestState:i.value,processingState:p.value,plugins:b,abortSignal:l,setRequestState:c,customContext:x,setCustomContext:d}),T=(l,u)=>typeof l.disabled=="function"?l.disabled(u):!!l.disabled,R=async(l,u)=>{c("processing","requesting");let M=new Proxy({messages:o(g.value)},{set(_,O,I){return O==="messages"?(_.messages=o(I),!0):(_[O]=I,!0)}}),P=y(u);for(let _ of b.filter(O=>!T(O,P)))await _.onBeforeRequest?.({...P,requestBody:M});let C=de({role:"",content:"",loading:!0});q(C);let k,L=l(M,u),D=W(L);for await(let _ of D){c("processing","completing"),C.loading&&(C.loading=void 0);let O=_.choices?.find(B=>B.index===0);if(O){k=O;let B=()=>{C.metadata||(C.metadata={});let{created:j,...re}=_;C.metadata.createdAt=j,C.metadata.updatedAt=Math.floor(Date.now()/1e3),Object.assign(C.metadata,re),G(C,O.message||O.delta)};if(a){let j=y(u);a({...j,chunk:_,choice:O,currentMessage:C},B)}else B()}let I=y(u);for(let B of b.filter(j=>!T(j,I)))B.onCompletionChunk?.({...I,abortSignal:u,chunk:_,choice:O,currentMessage:C})}await U(C,l,u,k)},F=async()=>{let l=new AbortController;v=l,x={};try{c("processing","requesting");let u=y(l.signal);for(let C of b.filter(k=>!T(k,u)))await C.onTurnStart?.(u);let M=f.value;try{await R(M,l.signal),c("completed")}catch(C){if(l.signal.aborted||C instanceof N||C instanceof Error&&C.name==="AbortError")c("aborted");else throw C}let P=y(l.signal);for(let C of b.filter(k=>!T(k,P)))await C.onTurnEnd?.(P)}catch(u){c("error");let M=!1,P=y(l.signal);for(let C of b.filter(k=>!T(k,P)))M=!0,C.onError?.({...P,error:u});if(!M)throw u}finally{let u=y(l.signal);for(let M of b.filter(P=>!T(P,u)))try{M.onFinally?.(u)}catch(P){console.error(`Error in onFinally hook for plugin ${M.name||"Anonymous"}:`,P)}v=null,w.slice(-1)[0]&&(w.slice(-1)[0].loading=void 0),w=[]}},E=async()=>{v?.abort(),m.value&&await new Promise(l=>{let u=pe(m,M=>{M||(u(),l())},{immediate:!0})})},U=async(l,u,M,P)=>{let C=!1,k=y(M),L=b.filter(D=>!T(D,k)).map(D=>{if(!D.onAfterRequest)return null;let _=I=>{q(I)},O=()=>{C=!0};return D.onAfterRequest({...k,currentMessage:l,lastChoice:P,appendMessage:_,requestNext:O})}).filter(D=>D!==null);await Z(Promise.all(L),M),C&&await R(u,M)},q=l=>{let u=Array.isArray(l)?l:[l];g.value.push(...u),w.push(...u)};return{requestState:i,processingState:p,messages:g,responseProvider:f,isProcessing:m,sendMessage:h,send:A,abortRequest:E}};import{isRef as he,toValue as ye}from"vue";function se(e,s=200,t=!1,n=!0,r=!1){return Ce(Me(s,t,n,r),e)}function Ce(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 ne=()=>{};function Me(...e){let s=0,t,n=!0,r=ne,a,i,p,g,f;!he(e[0])&&typeof e[0]=="object"?{delay:i,trailing:p=!0,leading:g=!0,rejectOnCancel:f=!1}=e[0]:[i,p=!0,g=!0,f=!1]=e;let v=()=>{t&&(clearTimeout(t),t=void 0,r(),r=ne)};return x=>{let S=ye(i),b=Date.now()-s,m=()=>a=x();return v(),S<=0?(s=Date.now(),m()):(b>S?(s=Date.now(),(g||!n)&&m()):p&&(a=new Promise((h,A)=>{r=f?A:h,t=setTimeout(()=>{s=Date.now(),n=!0,h(m()),v()},Math.max(0,S-b))})),!g&&!t&&(t=setTimeout(()=>n=!0,S)),n=!1,a)}}var We=e=>{let s=oe([]),t=new Map,n=new Map,r=oe(null),a=ve(()=>{let o=r.value;if(!o)return null;let c=s.value.find(y=>y.id===o);if(!c)return null;let d=t.get(o);return d?{...c,engine:d}:null}),i=o=>{if(!e.storage?.saveMessages)return;let c=o||r.value,d=s.value.find(T=>T.id===c);if(!d)return;d.updatedAt=Date.now(),e.storage?.saveConversation?.(d);let y=t.get(d.id);y&&e.storage.saveMessages(d.id,y.messages.value)},p=(o,c)=>{if(!e.autoSaveMessages||!e.storage?.saveMessages)return;let d=n.get(o);d&&d();let y=e.autoSaveThrottle??1e3,T=se(()=>{i(o)},y,!0,!0),R=Te(c.messages,T,{deep:!0});n.set(o,R)},g=o=>{let c=n.get(o);c&&(c(),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,c)=>{let d=t.get(o);if(d)return d;let y=c?.initialMessages??e.useMessageOptions.initialMessages??[];if(e.storage?.loadMessages)try{y=await e.storage.loadMessages(o)}catch(R){console.error("[useConversation] loadMessages failed:",R)}let T=z({...e.useMessageOptions,...c,initialMessages:y});return t.set(o,T),p(o,T),T};function v(){return Date.now().toString(36)+Math.random().toString(36).substring(2,9)}let w=o=>{let{id:c=v(),title:d,metadata:y,useMessageOptions:T}=o||{},R=Date.now(),F={id:c,title:d,createdAt:R,updatedAt:R,metadata:y};s.value.unshift(F);let E=z({...e.useMessageOptions,...T});return t.set(c,E),p(c,E),e.storage?.saveConversation?.(F),e.storage?.saveMessages?.(c,E.messages.value),r.value=c,a.value},x=o=>{let{excludeId:c}=o||{};t.forEach((d,y)=>{if(c&&y===c)return;d.isProcessing?.value||(g(y),t.delete(y))})};return{conversations:s,activeConversationId:r,activeConversation:a,createConversation:w,switchConversation:async o=>o?r.value===o?a.value:s.value.find(d=>d.id===o)?(await f(o),x({excludeId:o}),r.value=o,a.value):null:null,deleteConversation:async o=>{let c=s.value.findIndex(y=>y.id===o);if(c===-1)return;await t.get(o)?.abortRequest(),g(o),t.delete(o),s.value.splice(c,1),e.storage?.deleteConversation?.(o),r.value===o&&(r.value=null,x())},updateConversationTitle:(o,c)=>{let d=s.value.find(y=>y.id===o);d&&(d.title=c,d.updatedAt=Date.now(),e.storage?.saveConversation?.(d))},saveMessages:i,sendMessage:o=>{a.value?.engine.sendMessage(o)},abortActiveRequest:async()=>{await a.value?.engine.abortRequest()}}};export{ue as EXCLUDE_MODE_REMOVE,ae as createSSEStreamGenerator,J as fallbackRolePlugin,X as lengthPlugin,$ as thinkingPlugin,Se as toolPlugin,We as useConversation,z 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.2",
3
+ "version": "0.4.0-alpha.4",
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
- "gitHead": "f61a3ba7f8eef7dd364354ebf71a3475c509930e"
29
+ "dependencies": {
30
+ "idb": "^8.0.3"
31
+ },
32
+ "gitHead": "a25e92bf59065712e7814abb5d31c19ccfd342e0"
30
33
  }