@opentiny/tiny-robot-kit 0.4.0-alpha.3 → 0.4.0-alpha.5

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
@@ -7,7 +7,18 @@ type MaybePromise<T> = T | Promise<T>;
7
7
  * 提供一些实用的辅助函数
8
8
  */
9
9
 
10
- declare function createSSEStreamGenerator<T = any>(response: Response, options?: {
10
+ /**
11
+ * 将 SSE 流转换为异步生成器。
12
+ * 将服务器发送事件(SSE)流式响应转换为异步生成器,逐个产出解析后的数据
13
+ *
14
+ * 当取消信号被触发时,会抛出 name 为 'AbortError' 的错误
15
+ * @param response fetch 响应对象
16
+ * @param options 配置选项
17
+ * @param options.signal 可选的取消信号,用于中断流处理
18
+ * @returns 异步生成器,产出类型为 T 的数据
19
+ * @template T 生成器产出的数据类型,默认为 any
20
+ */
21
+ declare function sseStreamToGenerator<T = any>(response: Response, options?: {
11
22
  signal?: AbortSignal;
12
23
  }): AsyncGenerator<T, void, unknown>;
13
24
 
@@ -33,6 +44,7 @@ interface MessageMetadata {
33
44
  interface ChatMessage {
34
45
  role: string;
35
46
  content: string;
47
+ reasoning_content?: string;
36
48
  metadata?: MessageMetadata;
37
49
  tool_calls?: ToolCall[];
38
50
  tool_call_id?: string;
@@ -101,7 +113,16 @@ interface ChatCompletion {
101
113
  }
102
114
  interface UseMessageOptions {
103
115
  initialMessages?: ChatMessage[];
104
- requestMessageFields?: (keyof ChatMessage)[];
116
+ /**
117
+ * 请求消息时,要包含的字段(白名单)。默认包含所有字段。
118
+ * 如果 `requestMessageFieldsExclude` 存在,会先取 `requestMessageFields` 中的字段,再排除 `requestMessageFieldsExclude` 中的字段
119
+ */
120
+ requestMessageFields?: string[];
121
+ /**
122
+ * 请求消息时,要排除的字段(黑名单)。默认会排除 `state`、`metadata`、`loading` 字段(这几个字段是给UI展示用的)。
123
+ * 如果 `requestMessageFields` 存在,会先取 `requestMessageFields` 中的字段,再排除 `requestMessageFieldsExclude` 中的字段
124
+ */
125
+ requestMessageFieldsExclude?: string[];
105
126
  plugins?: UseMessagePlugin[];
106
127
  responseProvider: <T = ChatCompletion>(requestBody: MessageRequestBody, abortSignal: AbortSignal) => Promise<T> | AsyncGenerator<T> | Promise<AsyncGenerator<T>>;
107
128
  /**
@@ -130,7 +151,6 @@ interface BasePluginContext {
130
151
  currentTurn: ChatMessage[];
131
152
  requestState: RequestState;
132
153
  processingState?: RequestProcessingState;
133
- requestMessageFields: (keyof ChatMessage)[];
134
154
  plugins: UseMessagePlugin[];
135
155
  setRequestState: (state: RequestState, processingState?: RequestProcessingState) => void;
136
156
  abortSignal: AbortSignal;
@@ -368,4 +388,4 @@ declare const toolPlugin: (options: UseMessagePlugin & {
368
388
 
369
389
  declare const useMessage: (options: UseMessageOptions) => UseMessageReturn;
370
390
 
371
- export { type BasePluginContext, type ChatCompletion, type ChatMessage, type Choice, type CompletionChoice, type Conversation, type ConversationInfo, type ConversationStorageStrategy, type DeltaChoice, EXCLUDE_MODE_REMOVE, type MessageMetadata, type MessageRequestBody, type RequestProcessingState, type RequestState, type Tool, type ToolCall, type Usage, type UseConversationOptions, type UseConversationReturn, type UseMessageOptions, type UseMessagePlugin, type UseMessageReturn, createSSEStreamGenerator, fallbackRolePlugin, lengthPlugin, thinkingPlugin, toolPlugin, useConversation, useMessage };
391
+ export { type BasePluginContext, type ChatCompletion, type ChatMessage, type Choice, type CompletionChoice, type Conversation, type ConversationInfo, type ConversationStorageStrategy, type DeltaChoice, EXCLUDE_MODE_REMOVE, type MessageMetadata, type MessageRequestBody, type RequestProcessingState, type RequestState, type Tool, type ToolCall, type Usage, type UseConversationOptions, type UseConversationReturn, type UseMessageOptions, type UseMessagePlugin, type UseMessageReturn, fallbackRolePlugin, lengthPlugin, sseStreamToGenerator, thinkingPlugin, toolPlugin, useConversation, useMessage };
package/dist/index.d.ts CHANGED
@@ -7,7 +7,18 @@ type MaybePromise<T> = T | Promise<T>;
7
7
  * 提供一些实用的辅助函数
8
8
  */
9
9
 
10
- declare function createSSEStreamGenerator<T = any>(response: Response, options?: {
10
+ /**
11
+ * 将 SSE 流转换为异步生成器。
12
+ * 将服务器发送事件(SSE)流式响应转换为异步生成器,逐个产出解析后的数据
13
+ *
14
+ * 当取消信号被触发时,会抛出 name 为 'AbortError' 的错误
15
+ * @param response fetch 响应对象
16
+ * @param options 配置选项
17
+ * @param options.signal 可选的取消信号,用于中断流处理
18
+ * @returns 异步生成器,产出类型为 T 的数据
19
+ * @template T 生成器产出的数据类型,默认为 any
20
+ */
21
+ declare function sseStreamToGenerator<T = any>(response: Response, options?: {
11
22
  signal?: AbortSignal;
12
23
  }): AsyncGenerator<T, void, unknown>;
13
24
 
@@ -33,6 +44,7 @@ interface MessageMetadata {
33
44
  interface ChatMessage {
34
45
  role: string;
35
46
  content: string;
47
+ reasoning_content?: string;
36
48
  metadata?: MessageMetadata;
37
49
  tool_calls?: ToolCall[];
38
50
  tool_call_id?: string;
@@ -101,7 +113,16 @@ interface ChatCompletion {
101
113
  }
102
114
  interface UseMessageOptions {
103
115
  initialMessages?: ChatMessage[];
104
- requestMessageFields?: (keyof ChatMessage)[];
116
+ /**
117
+ * 请求消息时,要包含的字段(白名单)。默认包含所有字段。
118
+ * 如果 `requestMessageFieldsExclude` 存在,会先取 `requestMessageFields` 中的字段,再排除 `requestMessageFieldsExclude` 中的字段
119
+ */
120
+ requestMessageFields?: string[];
121
+ /**
122
+ * 请求消息时,要排除的字段(黑名单)。默认会排除 `state`、`metadata`、`loading` 字段(这几个字段是给UI展示用的)。
123
+ * 如果 `requestMessageFields` 存在,会先取 `requestMessageFields` 中的字段,再排除 `requestMessageFieldsExclude` 中的字段
124
+ */
125
+ requestMessageFieldsExclude?: string[];
105
126
  plugins?: UseMessagePlugin[];
106
127
  responseProvider: <T = ChatCompletion>(requestBody: MessageRequestBody, abortSignal: AbortSignal) => Promise<T> | AsyncGenerator<T> | Promise<AsyncGenerator<T>>;
107
128
  /**
@@ -130,7 +151,6 @@ interface BasePluginContext {
130
151
  currentTurn: ChatMessage[];
131
152
  requestState: RequestState;
132
153
  processingState?: RequestProcessingState;
133
- requestMessageFields: (keyof ChatMessage)[];
134
154
  plugins: UseMessagePlugin[];
135
155
  setRequestState: (state: RequestState, processingState?: RequestProcessingState) => void;
136
156
  abortSignal: AbortSignal;
@@ -368,4 +388,4 @@ declare const toolPlugin: (options: UseMessagePlugin & {
368
388
 
369
389
  declare const useMessage: (options: UseMessageOptions) => UseMessageReturn;
370
390
 
371
- export { type BasePluginContext, type ChatCompletion, type ChatMessage, type Choice, type CompletionChoice, type Conversation, type ConversationInfo, type ConversationStorageStrategy, type DeltaChoice, EXCLUDE_MODE_REMOVE, type MessageMetadata, type MessageRequestBody, type RequestProcessingState, type RequestState, type Tool, type ToolCall, type Usage, type UseConversationOptions, type UseConversationReturn, type UseMessageOptions, type UseMessagePlugin, type UseMessageReturn, createSSEStreamGenerator, fallbackRolePlugin, lengthPlugin, thinkingPlugin, toolPlugin, useConversation, useMessage };
391
+ export { type BasePluginContext, type ChatCompletion, type ChatMessage, type Choice, type CompletionChoice, type Conversation, type ConversationInfo, type ConversationStorageStrategy, type DeltaChoice, EXCLUDE_MODE_REMOVE, type MessageMetadata, type MessageRequestBody, type RequestProcessingState, type RequestState, type Tool, type ToolCall, type Usage, type UseConversationOptions, type UseConversationReturn, type UseMessageOptions, type UseMessagePlugin, type UseMessageReturn, fallbackRolePlugin, lengthPlugin, sseStreamToGenerator, thinkingPlugin, toolPlugin, useConversation, useMessage };
package/dist/index.js CHANGED
@@ -1,2 +1,2 @@
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});
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,fallbackRolePlugin:()=>$,lengthPlugin:()=>Q,sseStreamToGenerator:()=>ee,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 O=x.slice(6);if(O==="[DONE]")return;try{yield JSON.parse(O)}catch(b){console.warn("Failed to parse SSE data:",O,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"),O=(...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};O(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={},O=[$(),Y(),Q()],b=Te(O.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(_,S,B){return S==="messages"?(_.messages=r(B),!0):(_[S]=B,!0)}}),P=y(u);for(let _ of b.filter(S=>!T(S,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 S=_.choices?.find(G=>G.index===0);if(S){k=S;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,S.message||S.delta)};if(a){let K=y(u);a({...K,chunk:_,choice:S,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:S,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)},S=()=>{C=!0};return U.onAfterRequest({...k,currentMessage:l,lastChoice:P,appendMessage:_,requestNext:S})}).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 O=(0,V.toValue)(i),b=Date.now()-t,m=()=>a=x();return v(),O<=0?(t=Date.now(),m()):(b>O?(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,O-b))})),!g&&!n&&(n=setTimeout(()=>s=!0,O)),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,fallbackRolePlugin,lengthPlugin,sseStreamToGenerator,thinkingPlugin,toolPlugin,useConversation,useMessage});
package/dist/index.mjs CHANGED
@@ -1,2 +1,2 @@
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};
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 O=x.slice(6);if(O==="[DONE]")return;try{yield JSON.parse(O)}catch(b){console.warn("Failed to parse SSE data:",O,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 Oe=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"),O=(...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};O(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={},O=[J(),$(),X()],b=me(O.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(_,S,I){return S==="messages"?(_.messages=o(I),!0):(_[S]=I,!0)}}),P=y(u);for(let _ of b.filter(S=>!T(S,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 S=_.choices?.find(B=>B.index===0);if(S){k=S;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,S.message||S.delta)};if(a){let j=y(u);a({...j,chunk:_,choice:S,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:S,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)},S=()=>{C=!0};return D.onAfterRequest({...k,currentMessage:l,lastChoice:P,appendMessage:_,requestNext:S})}).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 O=ye(i),b=Date.now()-s,m=()=>a=x();return v(),O<=0?(s=Date.now(),m()):(b>O?(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,O-b))})),!g&&!t&&(t=setTimeout(()=>n=!0,O)),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,J as fallbackRolePlugin,X as lengthPlugin,ae as sseStreamToGenerator,$ as thinkingPlugin,Oe 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.3",
3
+ "version": "0.4.0-alpha.5",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
@@ -29,5 +29,5 @@
29
29
  "dependencies": {
30
30
  "idb": "^8.0.3"
31
31
  },
32
- "gitHead": "1cbef7678ff29993a748a1664119d53e6074f9df"
32
+ "gitHead": "b93984b6f54974da260d45fcd7556606f2018319"
33
33
  }