@opentiny/tiny-robot-kit 0.4.0-alpha.7 → 0.4.0-beta.0

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/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 - present OpenTiny Authors.
4
+ Copyright (c) 2025 - present Huawei Cloud Computing Technologies Co., Ltd.
5
+
6
+ Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ of this software and associated documentation files (the "Software"), to deal
8
+ in the Software without restriction, including without limitation the rights
9
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ copies of the Software, and to permit persons to whom the Software is
11
+ furnished to do so, subject to the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be included in all
14
+ copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22
+ SOFTWARE.
package/dist/index.d.mts CHANGED
@@ -258,6 +258,38 @@ declare class AIClient {
258
258
  updateConfig(config: Partial<AIModelConfig>): void;
259
259
  }
260
260
 
261
+ /**
262
+ * OpenAI提供商
263
+ * 用于与OpenAI API进行交互
264
+ */
265
+
266
+ declare class OpenAIProvider extends BaseModelProvider {
267
+ private baseURL;
268
+ private apiKey;
269
+ private defaultModel;
270
+ /**
271
+ * @param config AI模型配置
272
+ */
273
+ constructor(config: AIModelConfig);
274
+ /**
275
+ * 发送聊天请求并获取响应
276
+ * @param request 聊天请求参数
277
+ * @returns 聊天响应
278
+ */
279
+ chat(request: ChatCompletionRequest): Promise<ChatCompletionResponse>;
280
+ /**
281
+ * 发送流式聊天请求并通过处理器处理响应
282
+ * @param request 聊天请求参数
283
+ * @param handler 流式响应处理器
284
+ */
285
+ chatStream(request: ChatCompletionRequest, handler: StreamHandler): Promise<void>;
286
+ /**
287
+ * 更新配置
288
+ * @param config 新的AI模型配置
289
+ */
290
+ updateConfig(config: AIModelConfig): void;
291
+ }
292
+
261
293
  interface Tool {
262
294
  type: 'function';
263
295
  function: {
@@ -590,6 +622,25 @@ declare function indexedDBStorageStrategyFactory(config?: IndexedDBConfig): Conv
590
622
  * 提供一些实用的辅助函数
591
623
  */
592
624
 
625
+ /**
626
+ * 处理SSE流式响应
627
+ * @param response fetch响应对象
628
+ * @param handler 流处理器
629
+ */
630
+ declare function handleSSEStream(response: Response, handler: StreamHandler, signal?: AbortSignal): Promise<void>;
631
+ /**
632
+ * 格式化消息
633
+ * 将各种格式的消息转换为标准的ChatMessage格式
634
+ * @param messages 消息数组
635
+ * @returns 标准格式的消息数组
636
+ */
637
+ declare function formatMessages(messages: Array<ChatMessage | string>): ChatMessage[];
638
+ /**
639
+ * 从响应中提取文本内容
640
+ * @param response 聊天完成响应
641
+ * @returns 文本内容
642
+ */
643
+ declare function extractTextFromResponse(response: ChatCompletionResponse): string;
593
644
  /**
594
645
  * 将 SSE 流转换为异步生成器。
595
646
  * 将服务器发送事件(SSE)流式响应转换为异步生成器,逐个产出解析后的数据
@@ -688,4 +739,4 @@ declare const toolPlugin: (options: UseMessagePlugin & {
688
739
 
689
740
  declare const useMessage: (options: UseMessageOptions) => UseMessageReturn;
690
741
 
691
- export { type AIAdapterError, AIClient, type AIModelConfig, type AIProvider, type BasePluginContext, type ChatCompletion, type ChatCompletionOptions, type ChatCompletionRequest, type ChatCompletionResponse, type ChatCompletionResponseChoice, type ChatCompletionResponseMessage, type ChatCompletionResponseUsage, type ChatCompletionStreamResponse, type ChatCompletionStreamResponseChoice, type ChatCompletionStreamResponseDelta, type ChatHistory, type ChatMessage, type Choice, type CompletionChoice, type Conversation, type ConversationInfo, type ConversationStorageStrategy, type DeltaChoice, EXCLUDE_MODE_REMOVE, ErrorType, type IndexedDBConfig, IndexedDBStrategy, type LocalStorageConfig, LocalStorageStrategy, type MaybePromise, type MessageMetadata, type MessageRequestBody, type MessageRole, type RequestProcessingState, type RequestState, StreamEventType, type StreamHandler, type Tool, type ToolCall, type Usage, type UseConversationOptions, type UseConversationReturn, type UseMessageOptions, type UseMessagePlugin, type UseMessageReturn, fallbackRolePlugin, indexedDBStorageStrategyFactory, lengthPlugin, localStorageStrategyFactory, sseStreamToGenerator, thinkingPlugin, toolPlugin, useConversation, useMessage };
742
+ export { type AIAdapterError, AIClient, type AIModelConfig, type AIProvider, BaseModelProvider, type BasePluginContext, type ChatCompletion, type ChatCompletionOptions, type ChatCompletionRequest, type ChatCompletionResponse, type ChatCompletionResponseChoice, type ChatCompletionResponseMessage, type ChatCompletionResponseUsage, type ChatCompletionStreamResponse, type ChatCompletionStreamResponseChoice, type ChatCompletionStreamResponseDelta, type ChatHistory, type ChatMessage, type Choice, type CompletionChoice, type Conversation, type ConversationInfo, type ConversationStorageStrategy, type DeltaChoice, EXCLUDE_MODE_REMOVE, ErrorType, type IndexedDBConfig, IndexedDBStrategy, type LocalStorageConfig, LocalStorageStrategy, type MaybePromise, type MessageMetadata, type MessageRequestBody, type MessageRole, OpenAIProvider, type RequestProcessingState, type RequestState, StreamEventType, type StreamHandler, type Tool, type ToolCall, type Usage, type UseConversationOptions, type UseConversationReturn, type UseMessageOptions, type UseMessagePlugin, type UseMessageReturn, extractTextFromResponse, fallbackRolePlugin, formatMessages, handleSSEStream, indexedDBStorageStrategyFactory, lengthPlugin, localStorageStrategyFactory, sseStreamToGenerator, thinkingPlugin, toolPlugin, useConversation, useMessage };
package/dist/index.d.ts CHANGED
@@ -258,6 +258,38 @@ declare class AIClient {
258
258
  updateConfig(config: Partial<AIModelConfig>): void;
259
259
  }
260
260
 
261
+ /**
262
+ * OpenAI提供商
263
+ * 用于与OpenAI API进行交互
264
+ */
265
+
266
+ declare class OpenAIProvider extends BaseModelProvider {
267
+ private baseURL;
268
+ private apiKey;
269
+ private defaultModel;
270
+ /**
271
+ * @param config AI模型配置
272
+ */
273
+ constructor(config: AIModelConfig);
274
+ /**
275
+ * 发送聊天请求并获取响应
276
+ * @param request 聊天请求参数
277
+ * @returns 聊天响应
278
+ */
279
+ chat(request: ChatCompletionRequest): Promise<ChatCompletionResponse>;
280
+ /**
281
+ * 发送流式聊天请求并通过处理器处理响应
282
+ * @param request 聊天请求参数
283
+ * @param handler 流式响应处理器
284
+ */
285
+ chatStream(request: ChatCompletionRequest, handler: StreamHandler): Promise<void>;
286
+ /**
287
+ * 更新配置
288
+ * @param config 新的AI模型配置
289
+ */
290
+ updateConfig(config: AIModelConfig): void;
291
+ }
292
+
261
293
  interface Tool {
262
294
  type: 'function';
263
295
  function: {
@@ -590,6 +622,25 @@ declare function indexedDBStorageStrategyFactory(config?: IndexedDBConfig): Conv
590
622
  * 提供一些实用的辅助函数
591
623
  */
592
624
 
625
+ /**
626
+ * 处理SSE流式响应
627
+ * @param response fetch响应对象
628
+ * @param handler 流处理器
629
+ */
630
+ declare function handleSSEStream(response: Response, handler: StreamHandler, signal?: AbortSignal): Promise<void>;
631
+ /**
632
+ * 格式化消息
633
+ * 将各种格式的消息转换为标准的ChatMessage格式
634
+ * @param messages 消息数组
635
+ * @returns 标准格式的消息数组
636
+ */
637
+ declare function formatMessages(messages: Array<ChatMessage | string>): ChatMessage[];
638
+ /**
639
+ * 从响应中提取文本内容
640
+ * @param response 聊天完成响应
641
+ * @returns 文本内容
642
+ */
643
+ declare function extractTextFromResponse(response: ChatCompletionResponse): string;
593
644
  /**
594
645
  * 将 SSE 流转换为异步生成器。
595
646
  * 将服务器发送事件(SSE)流式响应转换为异步生成器,逐个产出解析后的数据
@@ -688,4 +739,4 @@ declare const toolPlugin: (options: UseMessagePlugin & {
688
739
 
689
740
  declare const useMessage: (options: UseMessageOptions) => UseMessageReturn;
690
741
 
691
- export { type AIAdapterError, AIClient, type AIModelConfig, type AIProvider, type BasePluginContext, type ChatCompletion, type ChatCompletionOptions, type ChatCompletionRequest, type ChatCompletionResponse, type ChatCompletionResponseChoice, type ChatCompletionResponseMessage, type ChatCompletionResponseUsage, type ChatCompletionStreamResponse, type ChatCompletionStreamResponseChoice, type ChatCompletionStreamResponseDelta, type ChatHistory, type ChatMessage, type Choice, type CompletionChoice, type Conversation, type ConversationInfo, type ConversationStorageStrategy, type DeltaChoice, EXCLUDE_MODE_REMOVE, ErrorType, type IndexedDBConfig, IndexedDBStrategy, type LocalStorageConfig, LocalStorageStrategy, type MaybePromise, type MessageMetadata, type MessageRequestBody, type MessageRole, type RequestProcessingState, type RequestState, StreamEventType, type StreamHandler, type Tool, type ToolCall, type Usage, type UseConversationOptions, type UseConversationReturn, type UseMessageOptions, type UseMessagePlugin, type UseMessageReturn, fallbackRolePlugin, indexedDBStorageStrategyFactory, lengthPlugin, localStorageStrategyFactory, sseStreamToGenerator, thinkingPlugin, toolPlugin, useConversation, useMessage };
742
+ export { type AIAdapterError, AIClient, type AIModelConfig, type AIProvider, BaseModelProvider, type BasePluginContext, type ChatCompletion, type ChatCompletionOptions, type ChatCompletionRequest, type ChatCompletionResponse, type ChatCompletionResponseChoice, type ChatCompletionResponseMessage, type ChatCompletionResponseUsage, type ChatCompletionStreamResponse, type ChatCompletionStreamResponseChoice, type ChatCompletionStreamResponseDelta, type ChatHistory, type ChatMessage, type Choice, type CompletionChoice, type Conversation, type ConversationInfo, type ConversationStorageStrategy, type DeltaChoice, EXCLUDE_MODE_REMOVE, ErrorType, type IndexedDBConfig, IndexedDBStrategy, type LocalStorageConfig, LocalStorageStrategy, type MaybePromise, type MessageMetadata, type MessageRequestBody, type MessageRole, OpenAIProvider, type RequestProcessingState, type RequestState, StreamEventType, type StreamHandler, type Tool, type ToolCall, type Usage, type UseConversationOptions, type UseConversationReturn, type UseMessageOptions, type UseMessagePlugin, type UseMessageReturn, extractTextFromResponse, fallbackRolePlugin, formatMessages, handleSSEStream, indexedDBStorageStrategyFactory, lengthPlugin, localStorageStrategyFactory, sseStreamToGenerator, thinkingPlugin, toolPlugin, useConversation, useMessage };
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- "use strict";var ne=Object.defineProperty;var Pe=Object.getOwnPropertyDescriptor;var Ee=Object.getOwnPropertyNames;var Oe=Object.prototype.hasOwnProperty;var Ie=(o,t)=>{for(var e in t)ne(o,e,{get:t[e],enumerable:!0})},ke=(o,t,e,s)=>{if(t&&typeof t=="object"||typeof t=="function")for(let n of Ee(t))!Oe.call(o,n)&&n!==e&&ne(o,n,{get:()=>t[n],enumerable:!(s=Pe(t,n))||s.enumerable});return o};var _e=o=>ke(ne({},"__esModule",{value:!0}),o);var Le={};Ie(Le,{AIClient:()=>Q,EXCLUDE_MODE_REMOVE:()=>Ae,ErrorType:()=>de,IndexedDBStrategy:()=>W,LocalStorageStrategy:()=>L,StreamEventType:()=>ge,fallbackRolePlugin:()=>ie,indexedDBStorageStrategyFactory:()=>ye,lengthPlugin:()=>le,localStorageStrategyFactory:()=>Z,sseStreamToGenerator:()=>fe,thinkingPlugin:()=>ce,toolPlugin:()=>Be,useConversation:()=>je,useMessage:()=>te});module.exports=_e(Le);var X=class{constructor(t){this.config=t}updateConfig(t){this.config={...this.config,...t}}getConfig(){return{...this.config}}validateRequest(t){if(!t.messages||!Array.isArray(t.messages)||t.messages.length===0)throw new Error("\u8BF7\u6C42\u5FC5\u987B\u5305\u542B\u81F3\u5C11\u4E00\u6761\u6D88\u606F");for(let e of t.messages)if(!e.role||!e.content)throw new Error("\u6BCF\u6761\u6D88\u606F\u5FC5\u987B\u5305\u542B\u89D2\u8272\u548C\u5185\u5BB9")}};var de=(l=>(l.NETWORK_ERROR="network_error",l.AUTHENTICATION_ERROR="authentication_error",l.RATE_LIMIT_ERROR="rate_limit_error",l.SERVER_ERROR="server_error",l.MODEL_ERROR="model_error",l.TIMEOUT_ERROR="timeout_error",l.UNKNOWN_ERROR="unknown_error",l))(de||{}),ge=(s=>(s.DATA="data",s.ERROR="error",s.DONE="done",s))(ge||{});function F(o){return{type:o.type||"unknown_error",message:o.message||"\u672A\u77E5\u9519\u8BEF",statusCode:o.statusCode,originalError:o.originalError}}function re(o){if(!o.response)return F({type:"network_error",message:"\u7F51\u7EDC\u8FDE\u63A5\u9519\u8BEF\uFF0C\u8BF7\u68C0\u67E5\u60A8\u7684\u7F51\u7EDC\u8FDE\u63A5",originalError:o});if(o.response){let{status:t,data:e}=o.response;return t===401||t===403?F({type:"authentication_error",message:"\u8EAB\u4EFD\u9A8C\u8BC1\u5931\u8D25\uFF0C\u8BF7\u68C0\u67E5\u60A8\u7684API\u5BC6\u94A5",statusCode:t,originalError:o}):t===429?F({type:"rate_limit_error",message:"\u8D85\u51FAAPI\u8C03\u7528\u9650\u5236\uFF0C\u8BF7\u7A0D\u540E\u518D\u8BD5",statusCode:t,originalError:o}):t>=500?F({type:"server_error",message:"\u670D\u52A1\u5668\u9519\u8BEF\uFF0C\u8BF7\u7A0D\u540E\u518D\u8BD5",statusCode:t,originalError:o}):F({type:"unknown_error",message:e?.error?.message||`\u8BF7\u6C42\u5931\u8D25\uFF0C\u72B6\u6001\u7801: ${t}`,statusCode:t,originalError:o})}return o.code==="ECONNABORTED"?F({type:"timeout_error",message:"\u8BF7\u6C42\u8D85\u65F6\uFF0C\u8BF7\u7A0D\u540E\u518D\u8BD5",originalError:o}):F({type:"unknown_error",message:o.message||"\u53D1\u751F\u672A\u77E5\u9519\u8BEF",originalError:o})}async function pe(o,t,e){let s=o.body?.getReader();if(!s)throw new Error("Response body is null");let n=new TextDecoder,r="",a,l;e&&e.addEventListener("abort",()=>{s.cancel().catch(u=>console.error("Error cancelling reader:",u))},{once:!0});try{for(;;){if(e?.aborted){await s.cancel();break}let{done:u,value:p}=await s.read();if(u)break;let v=n.decode(p,{stream:!0});r+=v;let R=r.split(`
1
+ "use strict";var re=Object.defineProperty;var Oe=Object.getOwnPropertyDescriptor;var Ie=Object.getOwnPropertyNames;var ke=Object.prototype.hasOwnProperty;var _e=(o,t)=>{for(var e in t)re(o,e,{get:t[e],enumerable:!0})},De=(o,t,e,n)=>{if(t&&typeof t=="object"||typeof t=="function")for(let s of Ie(t))!ke.call(o,s)&&s!==e&&re(o,s,{get:()=>t[s],enumerable:!(n=Oe(t,s))||n.enumerable});return o};var Ue=o=>De(re({},"__esModule",{value:!0}),o);var He={};_e(He,{AIClient:()=>Y,BaseModelProvider:()=>W,EXCLUDE_MODE_REMOVE:()=>Te,ErrorType:()=>ge,IndexedDBStrategy:()=>G,LocalStorageStrategy:()=>H,OpenAIProvider:()=>K,StreamEventType:()=>pe,extractTextFromResponse:()=>me,fallbackRolePlugin:()=>le,formatMessages:()=>fe,handleSSEStream:()=>Q,indexedDBStorageStrategyFactory:()=>ve,lengthPlugin:()=>ce,localStorageStrategyFactory:()=>ee,sseStreamToGenerator:()=>he,thinkingPlugin:()=>ue,toolPlugin:()=>Fe,useConversation:()=>We,useMessage:()=>oe});module.exports=Ue(He);var W=class{constructor(t){this.config=t}updateConfig(t){this.config={...this.config,...t}}getConfig(){return{...this.config}}validateRequest(t){if(!t.messages||!Array.isArray(t.messages)||t.messages.length===0)throw new Error("\u8BF7\u6C42\u5FC5\u987B\u5305\u542B\u81F3\u5C11\u4E00\u6761\u6D88\u606F");for(let e of t.messages)if(!e.role||!e.content)throw new Error("\u6BCF\u6761\u6D88\u606F\u5FC5\u987B\u5305\u542B\u89D2\u8272\u548C\u5185\u5BB9")}};var ge=(c=>(c.NETWORK_ERROR="network_error",c.AUTHENTICATION_ERROR="authentication_error",c.RATE_LIMIT_ERROR="rate_limit_error",c.SERVER_ERROR="server_error",c.MODEL_ERROR="model_error",c.TIMEOUT_ERROR="timeout_error",c.UNKNOWN_ERROR="unknown_error",c))(ge||{}),pe=(n=>(n.DATA="data",n.ERROR="error",n.DONE="done",n))(pe||{});function F(o){return{type:o.type||"unknown_error",message:o.message||"\u672A\u77E5\u9519\u8BEF",statusCode:o.statusCode,originalError:o.originalError}}function ae(o){if(!o.response)return F({type:"network_error",message:"\u7F51\u7EDC\u8FDE\u63A5\u9519\u8BEF\uFF0C\u8BF7\u68C0\u67E5\u60A8\u7684\u7F51\u7EDC\u8FDE\u63A5",originalError:o});if(o.response){let{status:t,data:e}=o.response;return t===401||t===403?F({type:"authentication_error",message:"\u8EAB\u4EFD\u9A8C\u8BC1\u5931\u8D25\uFF0C\u8BF7\u68C0\u67E5\u60A8\u7684API\u5BC6\u94A5",statusCode:t,originalError:o}):t===429?F({type:"rate_limit_error",message:"\u8D85\u51FAAPI\u8C03\u7528\u9650\u5236\uFF0C\u8BF7\u7A0D\u540E\u518D\u8BD5",statusCode:t,originalError:o}):t>=500?F({type:"server_error",message:"\u670D\u52A1\u5668\u9519\u8BEF\uFF0C\u8BF7\u7A0D\u540E\u518D\u8BD5",statusCode:t,originalError:o}):F({type:"unknown_error",message:e?.error?.message||`\u8BF7\u6C42\u5931\u8D25\uFF0C\u72B6\u6001\u7801: ${t}`,statusCode:t,originalError:o})}return o.code==="ECONNABORTED"?F({type:"timeout_error",message:"\u8BF7\u6C42\u8D85\u65F6\uFF0C\u8BF7\u7A0D\u540E\u518D\u8BD5",originalError:o}):F({type:"unknown_error",message:o.message||"\u53D1\u751F\u672A\u77E5\u9519\u8BEF",originalError:o})}async function Q(o,t,e){let n=o.body?.getReader();if(!n)throw new Error("Response body is null");let s=new TextDecoder,r="",a,c;e&&e.addEventListener("abort",()=>{n.cancel().catch(u=>console.error("Error cancelling reader:",u))},{once:!0});try{for(;;){if(e?.aborted){await n.cancel();break}let{done:u,value:f}=await n.read();if(u)break;let v=s.decode(f,{stream:!0});r+=v;let R=r.split(`
2
2
 
3
- `);r=R.pop()||"";for(let x of R)if(x.trim()!==""){if(x.trim()==="data: [DONE]"){l&&(a=l),t.onDone(a);continue}try{let A=x.match(/^data: (.+)$/m);if(!A)continue;let b=JSON.parse(A[1]);t.onData(b),l=b.choices?.[0]?.finish_reason||void 0}catch(A){console.error("Error parsing SSE message:",A)}}}(r.trim()==="data: [DONE]"||e?.aborted)&&(e?.aborted&&(a="aborted"),t.onDone(a))}catch(u){if(e?.aborted)return;throw u}}function ae(o="The operation was aborted"){let t=new Error(o);return t.name="AbortError",t}async function*fe(o,t={}){let e=o.body?.getReader();if(!e)throw new Error("ReadableStream not supported");let{signal:s}=t,n=new TextDecoder,r="",a=()=>{e.cancel()};s?.addEventListener("abort",a);try{for(;;){if(s?.aborted)throw ae();let l;try{l=await e.read()}catch(x){throw s?.aborted?ae():x}let{done:u,value:p}=l;if(u){if(s?.aborted)throw ae();return}let v=n.decode(p,{stream:!0});r+=v;let R=r.split(`
4
- `);r=R.pop()||"";for(let x of R)if(x.trim()!==""&&x.startsWith("data: ")){let A=x.slice(6);if(A==="[DONE]")return;try{yield JSON.parse(A)}catch(b){console.warn("Failed to parse SSE data:",A,b)}}}}finally{s?.removeEventListener("abort",a),e.releaseLock()}}var $=class extends X{constructor(e){super(e);this.defaultModel="gpt-3.5-turbo";this.baseURL=e.apiUrl||"https://api.openai.com/v1",this.apiKey=e.apiKey||"",e.defaultModel&&(this.defaultModel=e.defaultModel),this.apiKey||console.warn("API key is not provided. Authentication will likely fail.")}async chat(e){try{this.validateRequest(e);let s={model:e.options?.model||this.config.defaultModel||this.defaultModel,messages:e.messages,...e.options,stream:!1},n={method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(s)};this.apiKey&&Object.assign(n.headers,{Authorization:`Bearer ${this.apiKey}`});let r=await fetch(`${this.baseURL}/chat/completions`,n);if(!r.ok){let a=await r.text();throw new Error(`HTTP error! status: ${r.status}, details: ${a}`)}return await r.json()}catch(s){throw re(s)}}async chatStream(e,s){let{signal:n,...r}=e.options||{};try{this.validateRequest(e);let a={model:e.options?.model||this.config.defaultModel||this.defaultModel,messages:e.messages,...r,stream:!0},l={method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${this.apiKey}`,Accept:"text/event-stream"},body:JSON.stringify(a),signal:n};this.apiKey&&Object.assign(l.headers,{Authorization:`Bearer ${this.apiKey}`});let u=await fetch(`${this.baseURL}/chat/completions`,l);if(!u.ok){let p=await u.text();throw new Error(`HTTP error! status: ${u.status}, details: ${p}`)}await pe(u,s,n)}catch(a){if(n?.aborted)return;s.onError(re(a))}}updateConfig(e){super.updateConfig(e),e.apiUrl&&(this.baseURL=e.apiUrl),e.apiKey&&(this.apiKey=e.apiKey),e.defaultModel&&(this.defaultModel=e.defaultModel)}};var Q=class{constructor(t){this.config=t,this.provider=this.createProvider(t)}createProvider(t){if(t.provider==="custom"&&"providerImplementation"in t)return t.providerImplementation;if(t.provider==="deepseek"){let e={defaultModel:"deepseek-chat",apiUrl:"https://api.deepseek.com/v1"};return new $({...e,...t})}else return new $(t)}async chat(t){return this.provider.chat(t)}async chatStream(t,e){let s={...t,options:{...t.options,stream:!0}};return this.provider.chatStream(s,e)}getConfig(){return{...this.config}}updateConfig(t){this.config={...this.config,...t},t.provider&&t.provider!==this.config.provider?this.provider=this.createProvider(this.config):this.provider.updateConfig(this.config)}};var me=require("vue");function J(o,t=new WeakSet){if(o==null||typeof o!="object")return o;if(t.has(o))return Array.isArray(o)?[]:{};t.add(o);try{let e=(0,me.toRaw)(o);if(Array.isArray(e))return e.map(n=>J(n,t));if(e instanceof Date||e instanceof RegExp||e instanceof ArrayBuffer||e instanceof Blob)return e;let s={};for(let n in e){if(typeof n=="symbol")continue;let r=Object.getOwnPropertyDescriptor(e,n);if(!r||r.get||r.set)continue;let a=e[n];typeof a!="function"&&typeof a!="symbol"&&(s[n]=J(a,t))}return s}catch(e){return console.warn("unwrapProxy error:",e),Array.isArray(o)?[]:{}}}var Y=o=>o.map(t=>{let{renderContent:e,...s}=t;if(!Array.isArray(e))return t;let n=e.filter(a=>a.type==="collapsible-text"),r=e.filter(a=>a.type==="markdown"||a.type==="text");return n.length>0&&(s.reasoning_content=n.map(a=>a.content).join("")),r.length>0&&(s.content=r.map(a=>a.content).join("")),s});var z=o=>{let t=localStorage.getItem(o);return t?JSON.parse(t):[]},L=class{constructor(t="tiny-robot-ai-conversations"){this.storageKey=t}saveConversation(t){try{let e=z(this.storageKey),s=e.findIndex(n=>n.id===t.id);s!==-1?Object.assign(e[s],t):e.unshift({...t,messages:[]}),localStorage.setItem(this.storageKey,JSON.stringify(e))}catch(e){console.error("\u4FDD\u5B58\u4F1A\u8BDD\u5931\u8D25:",e)}}loadConversations(){try{return z(this.storageKey).map(e=>({id:e.id,title:e.title,createdAt:e.createdAt,updatedAt:e.updatedAt,metadata:e.metadata}))}catch(t){return console.error("\u52A0\u8F7D\u4F1A\u8BDD\u5931\u8D25:",t),[]}}saveMessages(t,e){try{let s=z(this.storageKey),n=s.findIndex(r=>r.id===t);n!==-1&&(s[n].messages=e),localStorage.setItem(this.storageKey,JSON.stringify(s))}catch(s){console.error("\u4FDD\u5B58\u4F1A\u8BDD\u6D88\u606F\u5931\u8D25:",s)}}loadMessages(t){try{let s=z(this.storageKey).find(r=>r.id===t);return Y(s?.messages||[])}catch(e){return console.error("\u52A0\u8F7D\u4F1A\u8BDD\u6D88\u606F\u5931\u8D25:",e),[]}}deleteConversation(t){let e=z(this.storageKey),s=e.findIndex(n=>n.id===t);s!==-1&&e.splice(s,1),localStorage.setItem(this.storageKey,JSON.stringify(e))}};var he=require("idb");var W=class{constructor(t="tiny-robot-ai-db",e=3){this.db=null;this.dbName=t,this.dbVersion=e}async getDB(){return this.db||(this.db=await(0,he.openDB)(this.dbName,this.dbVersion,{upgrade(t){t.objectStoreNames.contains("conversations")||t.createObjectStore("conversations",{keyPath:"id"}).createIndex("by-updated","updatedAt"),t.objectStoreNames.contains("messages")||t.createObjectStore("messages",{keyPath:"conversationId"})}})),this.db}async loadConversations(){try{return(await(await this.getDB()).getAllFromIndex("conversations","by-updated")).reverse()}catch(t){return console.error("\u52A0\u8F7D\u4F1A\u8BDD\u5931\u8D25:",t),[]}}async loadMessages(t){try{let s=await(await this.getDB()).get("messages",t);return s?Y(s.messages):[]}catch(e){return console.error("\u52A0\u8F7D\u4F1A\u8BDD\u6D88\u606F\u5931\u8D25:",e),[]}}async saveConversation(t){try{let e=await this.getDB(),s=J(t);await e.put("conversations",s)}catch(e){throw console.error("\u4FDD\u5B58\u4F1A\u8BDD\u5931\u8D25:",e),e}}async saveMessages(t,e){try{let s=await this.getDB(),n=J(e);await s.put("messages",{conversationId:t,messages:n})}catch(s){throw console.error("\u4FDD\u5B58\u4F1A\u8BDD\u6D88\u606F\u5931\u8D25:",s),s}}async deleteConversation(t){try{let e=await this.getDB();await e.delete("conversations",t),await e.delete("messages",t)}catch(e){throw console.error("\u5220\u9664\u4F1A\u8BDD\u5931\u8D25:",e),e}}};function Z(o={}){return new L(o.key||"tiny-robot-ai-conversations")}function ye(o={}){return new W(o.dbName||"tiny-robot-ai-db",o.dbVersion||1)}var K=require("vue");var U=require("vue");var ie=(o={})=>{let{fallbackRole:t="assistant",...e}=o;return{name:"fallbackRole",...e,onBeforeRequest(s){let{requestBody:n,messages:r}=s;return n.messages=r.map(a=>({...a,role:a.role||t})),e.onBeforeRequest?.(s)}}};var le=(o={})=>{let{continueContent:t="Please continue with your previous answer.",...e}=o;return{name:"length",...e,onAfterRequest:async s=>{let{lastChoice:n,appendMessage:r,requestNext:a}=s;return n?.finish_reason==="length"&&(r({role:"user",content:t}),a()),e.onAfterRequest?.(s)}}};var ce=(o={})=>({name:"thinking",...o,onCompletionChunk(t){let{choice:e,currentMessage:s}=t,r=typeof(e?.message?.reasoning_content||e?.delta?.reasoning_content)=="string";return s.state?s.state.thinking=r:s.state={thinking:r},o.onCompletionChunk?.(t)},onTurnEnd(t){let e=t.currentTurn.slice(-1)[0];return e?.state&&(e.state.thinking=void 0),o.onTurnEnd?.(t)}});var xe=require("vue");var H=class extends Error{constructor(t){super(t),this.name="AbortError"}};function De(o){if(o.aborted)return{promise:Promise.reject(new H(String(o.reason??"Aborted"))),cleanup:()=>{}};let t=null;return{promise:new Promise((n,r)=>{t=()=>{r(new H(String(o.reason??"Aborted")))},o.addEventListener("abort",t,{once:!0})}),cleanup:()=>{t&&(o.removeEventListener("abort",t),t=null)}}}function Me(o,t){let{promise:e,cleanup:s}=De(t);return Promise.race([o,e]).finally(s)}function be(o,t){let e={};for(let s in o)t.includes(s)&&(e[s]=o[s]);return e}function Re(o,t){let e={};for(let s in o)t.includes(s)||(e[s]=o[s]);return e}async function*ee(o){if(Ce(o)){yield*o;return}let t=await o;if(Ce(t)){yield*t;return}yield t}function Ce(o){return o&&typeof o=="object"&&typeof o[Symbol.asyncIterator]=="function"}var ue=o=>typeof o=="object"&&o!==null,ve=o=>ue(o)&&typeof o.index=="number",G=(o,t)=>{for(let[e,s]of Object.entries(t)){let n=o[e];if(n)if(typeof n=="string"&&typeof s=="string")e==="type"&&n||(o[e]=n+s);else if(Array.isArray(n)&&Array.isArray(s))if(n.every(r=>ve(r))&&s.every(r=>ve(r))){let r=new Map(n.map(p=>[p.index,p])),a=new Map(s.map(p=>[p.index,p]));for(let[p,v]of a)if(r.has(p)){let R=r.get(p);r.set(p,G(R,v))}else r.set(p,v);let l=Math.max(...Array.from(r.keys()),-1)+1,u=l>n.length?Array.from({length:l}):n;for(let[p,v]of r)u[p]=v;o[e]=u}else o[e]=[...n,...s];else ue(n)&&ue(s)&&(o[e]=G(n,s));else o[e]=s}return o};function Ue(o,t){let e=[];for(let s=0;s<o.length;s++){let n=o[s];if(n.role==="assistant"&&n.tool_calls&&n.tool_calls.length>0){let r=new Set(n.tool_calls.map(u=>u.id)),a=new Set;for(let u=s+1;u<o.length;u++){let p=o[u];p.role==="tool"&&p.tool_call_id&&r.has(p.tool_call_id)&&a.add(p.tool_call_id)}let l=n.tool_calls.map(u=>u.id).filter(u=>!a.has(u));l.length>0&&e.push({insertAfterIndex:s,missingToolCallIds:l})}}for(let s=e.length-1;s>=0;s--){let{insertAfterIndex:n,missingToolCallIds:r}=e[s],a=r.map(l=>({role:"tool",tool_call_id:l,content:t}));o.splice(n+1,0,...a)}}var Ae="remove";function qe(o,t,e,s){let n=o.filter(a=>a[e]),r=new Set(n.flatMap(a=>a.tool_calls?.map(l=>l.id)??[]));if(t===Ae)for(let a=o.length-1;a>=0;a--){let l=o[a];(l[e]||l[s]||l.tool_call_id&&r.has(l.tool_call_id))&&o.splice(a,1)}else if(t===!0)for(let a of o)(a[e]||a.tool_call_id&&r.has(a.tool_call_id))&&(a[s]=!0,delete a[e])}var Be=o=>{let{getTools:t,beforeCallTools:e,callTool:s,onToolCallStart:n,onToolCallEnd:r,toolCallCancelledContent:a="Tool call cancelled.",toolCallFailedContent:l="Tool call failed.",autoFillMissingToolMessages:u=!1,excludeToolMessagesNextTurn:p=!1,...v}=o,R=Symbol("doNotSendNextTurn"),x=Symbol("doNotSend"),A=(...m)=>{let[h,{primaryMessage:T}]=m;T.state.toolCall[h.id].status="running",n?.(...m)},b=(...m)=>{let[h,{status:T,primaryMessage:O}]=m;O.state.toolCall[h.id].status=T,r?.(...m)};return{name:"tool",...v,onTurnStart:m=>{let{messages:h}=m;return u&&Ue(h,a),p&&qe(h,p,R,x),v.onTurnStart?.(m)},onBeforeRequest:async m=>{let{messages:h,requestBody:T}=m;p===!0&&(T.messages=h.filter(E=>!E[x]));let O=await t?.();return O&&O.length>0&&(T.tools=O),v.onBeforeRequest?.(m)},onAfterRequest:async m=>{let{currentMessage:h,lastChoice:T,appendMessage:O,abortSignal:E,setRequestState:i,requestNext:c}=m;if(T?.finish_reason!=="tool_calls"||!h.tool_calls?.length)return;p&&(h[R]=!0),i("processing","calling-tools"),await e?.(h.tool_calls,{...m,currentMessage:h});let f=h.tool_calls.map(async y=>{let S=Math.floor(Date.now()/1e3),w=(0,xe.reactive)({role:"tool",tool_call_id:y.id,content:"",metadata:{createdAt:S,updatedAt:S}});O(w);let q={...m,primaryMessage:h,toolMessage:w};A(y,q);try{let I=s(y,q),d=ee(I);for await(let g of d){if(typeof g=="string")w.content+=g;else{let M={};try{M=JSON.parse(w.content||"{}")}catch(P){console.warn(P)}w.content=JSON.stringify(G(M,g))}w.metadata.updatedAt=Math.floor(Date.now()/1e3)}b(y,{...q,status:"success"})}catch(I){let d=I instanceof Error?I:new Error(String(I));if(E.aborted){b(y,{...q,status:"cancelled",error:d});return}console.error(I),w.content.length===0&&(w.content=l),b(y,{...q,status:"failed",error:d})}});return await Promise.all(f),c(),v.onAfterRequest?.(m)},onCompletionChunk:m=>{var T,O,E;let{currentMessage:h}=m;if(Array.isArray(h.tool_calls))for(let i of h.tool_calls)h.state?.toolCall?.[i.id]?.status||(h.state??(h.state={}),(T=h.state).toolCall??(T.toolCall={}),(O=h.state.toolCall)[E=i.id]??(O[E]={}));return v.onCompletionChunk?.(m)}}};var Ne=o=>{let t=[];for(let e of o){if(e.name){let s=t.findIndex(n=>n.name===e.name);s!==-1&&t.splice(s,1)}t.push(e)}return t},te=o=>{let{initialMessages:t=[],requestMessageFields:e=[],requestMessageFieldsExclude:s=["state","metadata","loading"],plugins:n=[],onCompletionChunk:r}=o,a=(0,U.ref)("idle"),l=(0,U.ref)(void 0),u=(0,U.ref)(t),p=(0,U.ref)(o.responseProvider),v=null,R=[],x={},A=[ie(),ce(),le()],b=Ne(A.concat(n)),m=(0,U.computed)(()=>a.value==="processing"),h=async d=>{if(!d||!d.trim()){console.warn("Cannot send empty message");return}if(m.value){console.warn("Cannot send message while processing is in progress");return}let g=Math.floor(Date.now()/1e3);u.value.push({role:"user",content:d.trim(),metadata:{createdAt:g,updatedAt:g}}),R.push(u.value[u.value.length-1]),await S()},T=async(...d)=>{if(m.value){console.warn("Cannot send message while processing is in progress");return}u.value.push(...d),R.push(...d),await S()},O=d=>{let g=d;return e.length&&(g=g.map(M=>be(M,e))),s.length&&(g=g.map(M=>Re(M,s))),g},E=(d,g)=>{a.value=d,d==="processing"?l.value=g||"requesting":l.value=void 0},i=d=>{Object.assign(x,d)},c=d=>({messages:u.value,currentTurn:R,requestState:a.value,processingState:l.value,plugins:b,abortSignal:d,setRequestState:E,customContext:x,setCustomContext:i}),f=(d,g)=>typeof d.disabled=="function"?d.disabled(g):!!d.disabled,y=async(d,g)=>{E("processing","requesting");let M=new Proxy({messages:O(u.value)},{set(D,k,N){return k==="messages"?(D.messages=O(N),!0):(D[k]=N,!0)}}),P=c(g);for(let D of b.filter(k=>!f(k,P)))await D.onBeforeRequest?.({...P,requestBody:M});let C=(0,U.reactive)({role:"",content:"",loading:!0});I(C);let _,se=d(M,g),B=ee(se);for await(let D of B){E("processing","completing"),C.loading&&(C.loading=void 0);let k=D.choices?.find(j=>j.index===0);if(k){_=k;let j=()=>{C.metadata||(C.metadata={});let{created:V,...Se}=D;C.metadata.createdAt=V,C.metadata.updatedAt=Math.floor(Date.now()/1e3),Object.assign(C.metadata,Se),G(C,k.message||k.delta)};if(r){let V=c(g);r({...V,chunk:D,choice:k,currentMessage:C},j)}else j()}let N=c(g);for(let j of b.filter(V=>!f(V,N)))j.onCompletionChunk?.({...N,abortSignal:g,chunk:D,choice:k,currentMessage:C})}await q(C,d,g,_)},S=async()=>{let d=new AbortController;v=d,x={};try{E("processing","requesting");let g=c(d.signal);for(let C of b.filter(_=>!f(_,g)))await C.onTurnStart?.(g);let M=p.value;try{await y(M,d.signal),E("completed")}catch(C){if(d.signal.aborted||C instanceof H||C instanceof Error&&C.name==="AbortError")E("aborted");else throw C}let P=c(d.signal);for(let C of b.filter(_=>!f(_,P)))await C.onTurnEnd?.(P)}catch(g){E("error");let M=!1,P=c(d.signal);for(let C of b.filter(_=>!f(_,P)))M=!0,C.onError?.({...P,error:g});if(!M)throw g}finally{let g=c(d.signal);for(let M of b.filter(P=>!f(P,g)))try{M.onFinally?.(g)}catch(P){console.error(`Error in onFinally hook for plugin ${M.name||"Anonymous"}:`,P)}v=null,R.slice(-1)[0]&&(R.slice(-1)[0].loading=void 0),R=[]}},w=async()=>{v?.abort(),m.value&&await new Promise(d=>{let g=(0,U.watch)(m,M=>{M||(g(),d())},{immediate:!0})})},q=async(d,g,M,P)=>{let C=!1,_=c(M),se=b.filter(B=>!f(B,_)).map(B=>{if(!B.onAfterRequest)return null;let D=N=>{I(N)},k=()=>{C=!0};return B.onAfterRequest({..._,currentMessage:d,lastChoice:P,appendMessage:D,requestNext:k})}).filter(B=>B!==null);await Me(Promise.all(se),M),C&&await y(g,M)},I=d=>{let g=Array.isArray(d)?d:[d];u.value.push(...g),R.push(...g)};return{requestState:a,processingState:l,messages:u,responseProvider:p,isProcessing:m,sendMessage:h,send:T,abortRequest:w}};var oe=require("vue");function Te(o,t=200,e=!1,s=!0,n=!1){return Fe(Ke(t,e,s,n),o)}function Fe(o,t){function e(...s){return new Promise((n,r)=>{Promise.resolve(o(()=>t.apply(this,s),{fn:t,thisArg:this,args:s})).then(n).catch(r)})}return e}var we=()=>{};function Ke(...o){let t=0,e,s=!0,n=we,r,a,l,u,p;!(0,oe.isRef)(o[0])&&typeof o[0]=="object"?{delay:a,trailing:l=!0,leading:u=!0,rejectOnCancel:p=!1}=o[0]:[a,l=!0,u=!0,p=!1]=o;let v=()=>{e&&(clearTimeout(e),e=void 0,n(),n=we)};return x=>{let A=(0,oe.toValue)(a),b=Date.now()-t,m=()=>r=x();return v(),A<=0?(t=Date.now(),m()):(b>A?(t=Date.now(),(u||!s)&&m()):l&&(r=new Promise((h,T)=>{n=p?T:h,e=setTimeout(()=>{t=Date.now(),s=!0,h(m()),v()},Math.max(0,A-b))})),!u&&!e&&(e=setTimeout(()=>s=!0,A)),s=!1,r)}}var je=o=>{let t=o.storage||Z(),e=(0,K.ref)([]),s=new Map,n=new Map,r=(0,K.ref)(null),a=(0,K.computed)(()=>{let i=r.value;if(!i)return null;let c=e.value.find(y=>y.id===i);if(!c)return null;let f=s.get(i);return f?{...c,engine:f}:null}),l=i=>{if(!t?.saveMessages)return;let c=i||r.value,f=e.value.find(S=>S.id===c);if(!f)return;f.updatedAt=Date.now(),t?.saveConversation?.(f);let y=s.get(f.id);y&&t.saveMessages(f.id,y.messages.value)},u=(i,c)=>{if(!o.autoSaveMessages||!t?.saveMessages)return;let f=n.get(i);f&&f();let y=o.autoSaveThrottle??1e3,S=Te(()=>{l(i)},y,!0,!0),w=(0,K.watch)(c.messages,S,{deep:!0});n.set(i,w)},p=i=>{let c=n.get(i);c&&(c(),n.delete(i))};t?.loadConversations&&Promise.resolve(t.loadConversations()).then(i=>{e.value=i}).catch(i=>{console.error("[useConversation] loadConversations failed:",i)});let v=async(i,c)=>{let f=s.get(i);if(f)return f;let y=c?.initialMessages??o.useMessageOptions.initialMessages??[];if(t?.loadMessages)try{y=await t.loadMessages(i)}catch(w){console.error("[useConversation] loadMessages failed:",w)}let S=te({...o.useMessageOptions,...c,initialMessages:y});return s.set(i,S),u(i,S),S};function R(){return Date.now().toString(36)+Math.random().toString(36).substring(2,9)}let x=i=>{let{id:c=R(),title:f,metadata:y,useMessageOptions:S}=i||{},w=Date.now(),q={id:c,title:f,createdAt:w,updatedAt:w,metadata:y};e.value.unshift(q);let I=te({...o.useMessageOptions,...S});return s.set(c,I),u(c,I),t?.saveConversation?.(q),t?.saveMessages?.(c,I.messages.value),r.value=c,a.value},A=i=>{let{excludeId:c}=i||{};s.forEach((f,y)=>{if(c&&y===c)return;f.isProcessing?.value||(p(y),s.delete(y))})};return{conversations:e,activeConversationId:r,activeConversation:a,createConversation:x,switchConversation:async i=>i?r.value===i?a.value:e.value.find(f=>f.id===i)?(await v(i),A({excludeId:i}),r.value=i,a.value):null:null,deleteConversation:async i=>{let c=e.value.findIndex(y=>y.id===i);if(c===-1)return;await s.get(i)?.abortRequest(),p(i),s.delete(i),e.value.splice(c,1),t?.deleteConversation?.(i),r.value===i&&(r.value=null,A())},clear:()=>{e.value.map(c=>c.id).forEach(c=>{t?.deleteConversation?.(c)}),s.forEach(c=>{c.abortRequest()}),n.forEach(c=>{c()}),e.value=[],s.clear(),n.clear(),r.value=null},updateConversationTitle:(i,c)=>{let f=e.value.find(y=>y.id===i);f&&(f.title=c,f.updatedAt=Date.now(),t?.saveConversation?.(f))},saveMessages:l,sendMessage:i=>{a.value?.engine.sendMessage(i)},abortActiveRequest:async()=>{await a.value?.engine.abortRequest()}}};0&&(module.exports={AIClient,EXCLUDE_MODE_REMOVE,ErrorType,IndexedDBStrategy,LocalStorageStrategy,StreamEventType,fallbackRolePlugin,indexedDBStorageStrategyFactory,lengthPlugin,localStorageStrategyFactory,sseStreamToGenerator,thinkingPlugin,toolPlugin,useConversation,useMessage});
3
+ `);r=R.pop()||"";for(let x of R)if(x.trim()!==""){if(x.trim()==="data: [DONE]"){c&&(a=c),t.onDone(a);continue}try{let A=x.match(/^data: (.+)$/m);if(!A)continue;let b=JSON.parse(A[1]);t.onData(b),c=b.choices?.[0]?.finish_reason||void 0}catch(A){console.error("Error parsing SSE message:",A)}}}(r.trim()==="data: [DONE]"||e?.aborted)&&(e?.aborted&&(a="aborted"),t.onDone(a))}catch(u){if(e?.aborted)return;throw u}}function fe(o){return o.map(t=>typeof t=="object"&&"role"in t&&"content"in t?{role:t.role,content:String(t.content),...t.name?{name:t.name}:{}}:typeof t=="string"?{role:"user",content:t}:{role:"user",content:String(t)})}function me(o){return!o.choices||!o.choices.length?"":o.choices[0].message?.content||""}function ie(o="The operation was aborted"){let t=new Error(o);return t.name="AbortError",t}async function*he(o,t={}){let e=o.body?.getReader();if(!e)throw new Error("ReadableStream not supported");let{signal:n}=t,s=new TextDecoder,r="",a=()=>{e.cancel()};n?.addEventListener("abort",a);try{for(;;){if(n?.aborted)throw ie();let c;try{c=await e.read()}catch(x){throw n?.aborted?ie():x}let{done:u,value:f}=c;if(u){if(n?.aborted)throw ie();return}let v=s.decode(f,{stream:!0});r+=v;let R=r.split(`
4
+ `);r=R.pop()||"";for(let x of R)if(x.trim()!==""&&x.startsWith("data: ")){let A=x.slice(6);if(A==="[DONE]")return;try{yield JSON.parse(A)}catch(b){console.warn("Failed to parse SSE data:",A,b)}}}}finally{n?.removeEventListener("abort",a),e.releaseLock()}}var K=class extends W{constructor(e){super(e);this.defaultModel="gpt-3.5-turbo";this.baseURL=e.apiUrl||"https://api.openai.com/v1",this.apiKey=e.apiKey||"",e.defaultModel&&(this.defaultModel=e.defaultModel),this.apiKey||console.warn("API key is not provided. Authentication will likely fail.")}async chat(e){try{this.validateRequest(e);let n={model:e.options?.model||this.config.defaultModel||this.defaultModel,messages:e.messages,...e.options,stream:!1},s={method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(n)};this.apiKey&&Object.assign(s.headers,{Authorization:`Bearer ${this.apiKey}`});let r=await fetch(`${this.baseURL}/chat/completions`,s);if(!r.ok){let a=await r.text();throw new Error(`HTTP error! status: ${r.status}, details: ${a}`)}return await r.json()}catch(n){throw ae(n)}}async chatStream(e,n){let{signal:s,...r}=e.options||{};try{this.validateRequest(e);let a={model:e.options?.model||this.config.defaultModel||this.defaultModel,messages:e.messages,...r,stream:!0},c={method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${this.apiKey}`,Accept:"text/event-stream"},body:JSON.stringify(a),signal:s};this.apiKey&&Object.assign(c.headers,{Authorization:`Bearer ${this.apiKey}`});let u=await fetch(`${this.baseURL}/chat/completions`,c);if(!u.ok){let f=await u.text();throw new Error(`HTTP error! status: ${u.status}, details: ${f}`)}await Q(u,n,s)}catch(a){if(s?.aborted)return;n.onError(ae(a))}}updateConfig(e){super.updateConfig(e),e.apiUrl&&(this.baseURL=e.apiUrl),e.apiKey&&(this.apiKey=e.apiKey),e.defaultModel&&(this.defaultModel=e.defaultModel)}};var Y=class{constructor(t){this.config=t,this.provider=this.createProvider(t)}createProvider(t){if(t.provider==="custom"&&"providerImplementation"in t)return t.providerImplementation;if(t.provider==="deepseek"){let e={defaultModel:"deepseek-chat",apiUrl:"https://api.deepseek.com/v1"};return new K({...e,...t})}else return new K(t)}async chat(t){return this.provider.chat(t)}async chatStream(t,e){let n={...t,options:{...t.options,stream:!0}};return this.provider.chatStream(n,e)}getConfig(){return{...this.config}}updateConfig(t){this.config={...this.config,...t},t.provider&&t.provider!==this.config.provider?this.provider=this.createProvider(this.config):this.provider.updateConfig(this.config)}};var ye=require("vue");function z(o,t=new WeakMap){if(o==null||typeof o!="object")return o;try{let e=(0,ye.toRaw)(o);if(t.has(e))return t.get(e);if(Array.isArray(e)){let s=[];return t.set(e,s),s.push(...e.map(r=>z(r,t))),s}if(e instanceof Date||e instanceof RegExp||e instanceof ArrayBuffer||e instanceof Blob)return e;let n={};t.set(e,n);for(let s of Object.keys(e)){let r=Object.getOwnPropertyDescriptor(e,s);if(!r||r.get||r.set)continue;let a=e[s];typeof a!="function"&&typeof a!="symbol"&&(n[s]=z(a,t))}return n}catch(e){return console.warn("unwrapProxy error:",e),Array.isArray(o)?[]:{}}}var Z=o=>o.map(t=>{let{renderContent:e,...n}=t;if(!Array.isArray(e))return t;let s=e.filter(a=>a.type==="collapsible-text"),r=e.filter(a=>a.type==="markdown"||a.type==="text");return s.length>0&&(n.reasoning_content=s.map(a=>a.content).join("")),r.length>0&&(n.content=r.map(a=>a.content).join("")),n});var X=o=>{let t=localStorage.getItem(o);return t?JSON.parse(t):[]},H=class{constructor(t="tiny-robot-ai-conversations"){this.storageKey=t}saveConversation(t){try{let e=X(this.storageKey),n=e.findIndex(s=>s.id===t.id);n!==-1?Object.assign(e[n],t):e.unshift({...t,messages:[]}),localStorage.setItem(this.storageKey,JSON.stringify(e))}catch(e){console.error("\u4FDD\u5B58\u4F1A\u8BDD\u5931\u8D25:",e)}}loadConversations(){try{return X(this.storageKey).map(e=>({id:e.id,title:e.title,createdAt:e.createdAt,updatedAt:e.updatedAt,metadata:e.metadata}))}catch(t){return console.error("\u52A0\u8F7D\u4F1A\u8BDD\u5931\u8D25:",t),[]}}saveMessages(t,e){try{let n=X(this.storageKey),s=n.findIndex(r=>r.id===t);s!==-1&&(n[s].messages=e),localStorage.setItem(this.storageKey,JSON.stringify(n))}catch(n){console.error("\u4FDD\u5B58\u4F1A\u8BDD\u6D88\u606F\u5931\u8D25:",n)}}loadMessages(t){try{let n=X(this.storageKey).find(r=>r.id===t);return Z(n?.messages||[])}catch(e){return console.error("\u52A0\u8F7D\u4F1A\u8BDD\u6D88\u606F\u5931\u8D25:",e),[]}}deleteConversation(t){let e=X(this.storageKey),n=e.findIndex(s=>s.id===t);n!==-1&&e.splice(n,1),localStorage.setItem(this.storageKey,JSON.stringify(e))}};var Ce=require("idb");var G=class{constructor(t="tiny-robot-ai-db",e=3){this.db=null;this.dbName=t,this.dbVersion=e}async getDB(){return this.db||(this.db=await(0,Ce.openDB)(this.dbName,this.dbVersion,{upgrade(t){t.objectStoreNames.contains("conversations")||t.createObjectStore("conversations",{keyPath:"id"}).createIndex("by-updated","updatedAt"),t.objectStoreNames.contains("messages")||t.createObjectStore("messages",{keyPath:"conversationId"})}})),this.db}async loadConversations(){try{return(await(await this.getDB()).getAllFromIndex("conversations","by-updated")).reverse()}catch(t){return console.error("\u52A0\u8F7D\u4F1A\u8BDD\u5931\u8D25:",t),[]}}async loadMessages(t){try{let n=await(await this.getDB()).get("messages",t);return n?Z(n.messages):[]}catch(e){return console.error("\u52A0\u8F7D\u4F1A\u8BDD\u6D88\u606F\u5931\u8D25:",e),[]}}async saveConversation(t){try{let e=await this.getDB(),n=z(t);await e.put("conversations",n)}catch(e){throw console.error("\u4FDD\u5B58\u4F1A\u8BDD\u5931\u8D25:",e),e}}async saveMessages(t,e){try{let n=await this.getDB(),s=z(e);await n.put("messages",{conversationId:t,messages:s})}catch(n){throw console.error("\u4FDD\u5B58\u4F1A\u8BDD\u6D88\u606F\u5931\u8D25:",n),n}}async deleteConversation(t){try{let e=await this.getDB();await e.delete("conversations",t),await e.delete("messages",t)}catch(e){throw console.error("\u5220\u9664\u4F1A\u8BDD\u5931\u8D25:",e),e}}};function ee(o={}){return new H(o.key||"tiny-robot-ai-conversations")}function ve(o={}){return new G(o.dbName||"tiny-robot-ai-db",o.dbVersion||1)}var j=require("vue");var U=require("vue");var le=(o={})=>{let{fallbackRole:t="assistant",...e}=o;return{name:"fallbackRole",...e,onBeforeRequest(n){let{requestBody:s}=n;return s.messages=s.messages.map(r=>({...r,role:r.role||t})),e.onBeforeRequest?.(n)}}};var ce=(o={})=>{let{continueContent:t="Please continue with your previous answer.",...e}=o;return{name:"length",...e,onAfterRequest:async n=>{let{lastChoice:s,appendMessage:r,requestNext:a}=n;return s?.finish_reason==="length"&&(r({role:"user",content:t}),a()),e.onAfterRequest?.(n)}}};var ue=(o={})=>({name:"thinking",...o,onCompletionChunk(t){let{choice:e,currentMessage:n}=t,r=typeof(e?.message?.reasoning_content||e?.delta?.reasoning_content)=="string";return n.state?n.state.thinking=r:n.state={thinking:r},o.onCompletionChunk?.(t)},onTurnEnd(t){let e=t.currentTurn.slice(-1)[0];return e?.state&&(e.state.thinking=void 0),o.onTurnEnd?.(t)}});var we=require("vue");var V=class extends Error{constructor(t){super(t),this.name="AbortError"}};function qe(o){if(o.aborted)return{promise:Promise.reject(new V(String(o.reason??"Aborted"))),cleanup:()=>{}};let t=null;return{promise:new Promise((s,r)=>{t=()=>{r(new V(String(o.reason??"Aborted")))},o.addEventListener("abort",t,{once:!0})}),cleanup:()=>{t&&(o.removeEventListener("abort",t),t=null)}}}function Re(o,t){let{promise:e,cleanup:n}=qe(t);return Promise.race([o,e]).finally(n)}function xe(o,t){let e={};for(let n in o)t.includes(n)&&(e[n]=o[n]);return e}function Ae(o,t){let e={};for(let n in o)t.includes(n)||(e[n]=o[n]);return e}async function*te(o){if(Me(o)){yield*o;return}let t=await o;if(Me(t)){yield*t;return}yield t}function Me(o){return o&&typeof o=="object"&&typeof o[Symbol.asyncIterator]=="function"}var de=o=>typeof o=="object"&&o!==null,be=o=>de(o)&&typeof o.index=="number",$=(o,t)=>{for(let[e,n]of Object.entries(t)){let s=o[e];if(s)if(typeof s=="string"&&typeof n=="string")e==="type"&&s||(o[e]=s+n);else if(Array.isArray(s)&&Array.isArray(n))if(s.every(r=>be(r))&&n.every(r=>be(r))){let r=new Map(s.map(f=>[f.index,f])),a=new Map(n.map(f=>[f.index,f]));for(let[f,v]of a)if(r.has(f)){let R=r.get(f);r.set(f,$(R,v))}else r.set(f,v);let c=Math.max(...Array.from(r.keys()),-1)+1,u=c>s.length?Array.from({length:c}):s;for(let[f,v]of r)u[f]=v;o[e]=u}else o[e]=[...s,...n];else de(s)&&de(n)&&(o[e]=$(s,n));else o[e]=n}return o};function Be(o,t){let e=[];for(let n=0;n<o.length;n++){let s=o[n];if(s.role==="assistant"&&s.tool_calls&&s.tool_calls.length>0){let r=new Set(s.tool_calls.map(u=>u.id)),a=new Set;for(let u=n+1;u<o.length;u++){let f=o[u];f.role==="tool"&&f.tool_call_id&&r.has(f.tool_call_id)&&a.add(f.tool_call_id)}let c=s.tool_calls.map(u=>u.id).filter(u=>!a.has(u));c.length>0&&e.push({insertAfterIndex:n,missingToolCallIds:c})}}for(let n=e.length-1;n>=0;n--){let{insertAfterIndex:s,missingToolCallIds:r}=e[n],a=r.map(c=>({role:"tool",tool_call_id:c,content:t}));o.splice(s+1,0,...a)}}var Te="remove";function Ne(o,t,e,n){let s=o.filter(a=>a[e]),r=new Set(s.flatMap(a=>a.tool_calls?.map(c=>c.id)??[]));if(t===Te)for(let a=o.length-1;a>=0;a--){let c=o[a];(c[e]||c[n]||c.tool_call_id&&r.has(c.tool_call_id))&&o.splice(a,1)}else if(t===!0)for(let a of o)(a[e]||a.tool_call_id&&r.has(a.tool_call_id))&&(a[n]=!0,delete a[e])}var Fe=o=>{let{getTools:t,beforeCallTools:e,callTool:n,onToolCallStart:s,onToolCallEnd:r,toolCallCancelledContent:a="Tool call cancelled.",toolCallFailedContent:c="Tool call failed.",autoFillMissingToolMessages:u=!1,excludeToolMessagesNextTurn:f=!1,...v}=o,R=Symbol("doNotSendNextTurn"),x=Symbol("doNotSend"),A=(...m)=>{let[h,{primaryMessage:T}]=m;T.state.toolCall[h.id].status="running",s?.(...m)},b=(...m)=>{let[h,{status:T,primaryMessage:O}]=m;O.state.toolCall[h.id].status=T,r?.(...m)};return{name:"tool",...v,onTurnStart:m=>{let{messages:h}=m;return u&&Be(h,a),f&&Ne(h,f,R,x),v.onTurnStart?.(m)},onBeforeRequest:async m=>{let{messages:h,requestBody:T}=m;f===!0&&(T.messages=h.filter(E=>!E[x]));let O=await t?.();return O&&O.length>0&&(T.tools=O),v.onBeforeRequest?.(m)},onAfterRequest:async m=>{let{currentMessage:h,lastChoice:T,appendMessage:O,abortSignal:E,setRequestState:i,requestNext:l}=m;if(T?.finish_reason!=="tool_calls"||!h.tool_calls?.length)return;f&&(h[R]=!0),i("processing","calling-tools"),await e?.(h.tool_calls,{...m,currentMessage:h});let d=h.tool_calls.map(async y=>{let S=Math.floor(Date.now()/1e3),w=(0,we.reactive)({role:"tool",tool_call_id:y.id,content:"",metadata:{createdAt:S,updatedAt:S}});O(w);let q={...m,primaryMessage:h,toolMessage:w};A(y,q);try{let I=n(y,q),g=te(I);for await(let p of g){if(typeof p=="string")w.content+=p;else{let M={};try{M=JSON.parse(w.content||"{}")}catch(P){console.warn(P)}w.content=JSON.stringify($(M,p))}w.metadata.updatedAt=Math.floor(Date.now()/1e3)}b(y,{...q,status:"success"})}catch(I){let g=I instanceof Error?I:new Error(String(I));if(E.aborted){b(y,{...q,status:"cancelled",error:g});return}console.error(I),w.content.length===0&&(w.content=c),b(y,{...q,status:"failed",error:g})}});return await Promise.all(d),l(),v.onAfterRequest?.(m)},onCompletionChunk:m=>{var T,O,E;let{currentMessage:h}=m;if(Array.isArray(h.tool_calls))for(let i of h.tool_calls)h.state?.toolCall?.[i.id]?.status||(h.state??(h.state={}),(T=h.state).toolCall??(T.toolCall={}),(O=h.state.toolCall)[E=i.id]??(O[E]={}));return v.onCompletionChunk?.(m)}}};var Ke=o=>{let t=[];for(let e of o){if(e.name){let n=t.findIndex(s=>s.name===e.name);n!==-1&&t.splice(n,1)}t.push(e)}return t},oe=o=>{let{initialMessages:t=[],requestMessageFields:e=[],requestMessageFieldsExclude:n=["state","metadata","loading"],plugins:s=[],onCompletionChunk:r}=o,a=(0,U.ref)("idle"),c=(0,U.ref)(void 0),u=(0,U.ref)(t),f=(0,U.ref)(o.responseProvider),v=null,R=[],x={},A=[le(),ue(),ce()],b=Ke(A.concat(s)),m=(0,U.computed)(()=>a.value==="processing"),h=async g=>{if(!g||!g.trim()){console.warn("Cannot send empty message");return}if(m.value){console.warn("Cannot send message while processing is in progress");return}let p=Math.floor(Date.now()/1e3);u.value.push({role:"user",content:g.trim(),metadata:{createdAt:p,updatedAt:p}}),R.push(u.value[u.value.length-1]),await S()},T=async(...g)=>{if(m.value){console.warn("Cannot send message while processing is in progress");return}u.value.push(...g),R.push(...g),await S()},O=g=>{let p=g;return e.length&&(p=p.map(M=>xe(M,e))),n.length&&(p=p.map(M=>Ae(M,n))),p},E=(g,p)=>{a.value=g,g==="processing"?c.value=p||"requesting":c.value=void 0},i=g=>{Object.assign(x,g)},l=g=>({messages:u.value,currentTurn:R,requestState:a.value,processingState:c.value,plugins:b,abortSignal:g,setRequestState:E,customContext:x,setCustomContext:i}),d=(g,p)=>typeof g.disabled=="function"?g.disabled(p):!!g.disabled,y=async(g,p)=>{E("processing","requesting");let M=new Proxy({messages:O(u.value)},{set(D,k,N){return k==="messages"?(D.messages=O(N),!0):(D[k]=N,!0)}}),P=l(p);for(let D of b.filter(k=>!d(k,P)))await D.onBeforeRequest?.({...P,requestBody:M});let C=(0,U.reactive)({role:"",content:"",loading:!0});I(C);let _,se=g(M,p),B=te(se);for await(let D of B){E("processing","completing"),C.loading&&(C.loading=void 0);let k=D.choices?.find(L=>L.index===0);if(k){_=k;let L=()=>{C.metadata||(C.metadata={});let{created:J,...Ee}=D;C.metadata.createdAt=J,C.metadata.updatedAt=Math.floor(Date.now()/1e3),Object.assign(C.metadata,Ee),$(C,k.message||k.delta)};if(r){let J=l(p);r({...J,chunk:D,choice:k,currentMessage:C},L)}else L()}let N=l(p);for(let L of b.filter(J=>!d(J,N)))L.onCompletionChunk?.({...N,abortSignal:p,chunk:D,choice:k,currentMessage:C})}await q(C,g,p,_)},S=async()=>{let g=new AbortController;v=g,x={};try{E("processing","requesting");let p=l(g.signal);for(let C of b.filter(_=>!d(_,p)))await C.onTurnStart?.(p);let M=f.value;try{await y(M,g.signal),E("completed")}catch(C){if(g.signal.aborted||C instanceof V||C instanceof Error&&C.name==="AbortError")E("aborted");else throw C}let P=l(g.signal);for(let C of b.filter(_=>!d(_,P)))await C.onTurnEnd?.(P)}catch(p){E("error");let M=!1,P=l(g.signal);for(let C of b.filter(_=>!d(_,P)))C.onError&&(M=!0,C.onError({...P,error:p}));if(!M)throw p}finally{let p=l(g.signal);for(let M of b.filter(P=>!d(P,p)))try{M.onFinally?.(p)}catch(P){console.error(`Error in onFinally hook for plugin ${M.name||"Anonymous"}:`,P)}v=null,R.slice(-1)[0]&&(R.slice(-1)[0].loading=void 0),R=[]}},w=async()=>{v?.abort(),m.value&&await new Promise(g=>{let p=(0,U.watch)(m,M=>{M||(p(),g())},{immediate:!0})})},q=async(g,p,M,P)=>{let C=!1,_=l(M),se=b.filter(B=>!d(B,_)).map(B=>{if(!B.onAfterRequest)return null;let D=N=>{I(N)},k=()=>{C=!0};return B.onAfterRequest({..._,currentMessage:g,lastChoice:P,appendMessage:D,requestNext:k})}).filter(B=>B!==null);await Re(Promise.all(se),M),C&&await y(p,M)},I=g=>{let p=Array.isArray(g)?g:[g];u.value.push(...p),R.push(...p)};return{requestState:a,processingState:c,messages:u,responseProvider:f,isProcessing:m,sendMessage:h,send:T,abortRequest:w}};var ne=require("vue");function Pe(o,t=200,e=!1,n=!0,s=!1){return je(Le(t,e,n,s),o)}function je(o,t){function e(...n){return new Promise((s,r)=>{Promise.resolve(o(()=>t.apply(this,n),{fn:t,thisArg:this,args:n})).then(s).catch(r)})}return e}var Se=()=>{};function Le(...o){let t=0,e,n=!0,s=Se,r,a,c,u,f;!(0,ne.isRef)(o[0])&&typeof o[0]=="object"?{delay:a,trailing:c=!0,leading:u=!0,rejectOnCancel:f=!1}=o[0]:[a,c=!0,u=!0,f=!1]=o;let v=()=>{e&&(clearTimeout(e),e=void 0,s(),s=Se)};return x=>{let A=(0,ne.toValue)(a),b=Date.now()-t,m=()=>r=x();return v(),A<=0?(t=Date.now(),m()):(b>A?(t=Date.now(),(u||!n)&&m()):c&&(r=new Promise((h,T)=>{s=f?T:h,e=setTimeout(()=>{t=Date.now(),n=!0,h(m()),v()},Math.max(0,A-b))})),!u&&!e&&(e=setTimeout(()=>n=!0,A)),n=!1,r)}}var We=o=>{let t=o.storage||ee(),e=(0,j.ref)([]),n=new Map,s=new Map,r=(0,j.ref)(null),a=(0,j.computed)(()=>{let i=r.value;if(!i)return null;let l=e.value.find(y=>y.id===i);if(!l)return null;let d=n.get(i);return d?{...l,engine:d}:null}),c=i=>{if(!t?.saveMessages)return;let l=i||r.value,d=e.value.find(S=>S.id===l);if(!d)return;d.updatedAt=Date.now(),t?.saveConversation?.(d);let y=n.get(d.id);y&&t.saveMessages(d.id,y.messages.value)},u=(i,l)=>{if(!o.autoSaveMessages||!t?.saveMessages)return;let d=s.get(i);d&&d();let y=o.autoSaveThrottle??1e3,S=Pe(()=>{c(i)},y,!0,!0),w=(0,j.watch)(l.messages,S,{deep:!0});s.set(i,w)},f=i=>{let l=s.get(i);l&&(l(),s.delete(i))};t?.loadConversations&&Promise.resolve(t.loadConversations()).then(i=>{if(!i?.length)return;if(e.value.length===0){e.value=i;return}let l=new Map(e.value.map(d=>[d.id,d]));i.forEach(d=>{l.has(d.id)||l.set(d.id,d)}),e.value=Array.from(l.values())}).catch(i=>{console.error("[useConversation] loadConversations failed:",i)});let v=async(i,l)=>{let d=n.get(i);if(d)return d;let y=l?.initialMessages??o.useMessageOptions.initialMessages??[];if(t?.loadMessages)try{y=await t.loadMessages(i)}catch(w){console.error("[useConversation] loadMessages failed:",w)}let S=oe({...o.useMessageOptions,...l,initialMessages:y});return n.set(i,S),u(i,S),S};function R(){return Date.now().toString(36)+Math.random().toString(36).substring(2,9)}let x=i=>{let{id:l=R(),title:d,metadata:y,useMessageOptions:S}=i||{},w=Date.now(),q={id:l,title:d,createdAt:w,updatedAt:w,metadata:y};e.value.unshift(q);let I=oe({...o.useMessageOptions,...S});return n.set(l,I),u(l,I),t?.saveConversation?.(q),t?.saveMessages?.(l,I.messages.value),r.value=l,a.value},A=i=>{let{excludeId:l}=i||{};n.forEach((d,y)=>{if(l&&y===l)return;d.isProcessing?.value||(f(y),n.delete(y))})};return{conversations:e,activeConversationId:r,activeConversation:a,createConversation:x,switchConversation:async i=>i?r.value===i?a.value:e.value.find(d=>d.id===i)?(await v(i),A({excludeId:i}),r.value=i,a.value):null:null,deleteConversation:async i=>{let l=e.value.findIndex(y=>y.id===i);if(l===-1)return;await n.get(i)?.abortRequest(),f(i),n.delete(i),e.value.splice(l,1),t?.deleteConversation?.(i),r.value===i&&(r.value=null,A())},clear:()=>{e.value.map(l=>l.id).forEach(l=>{t?.deleteConversation?.(l)}),n.forEach(l=>{l.abortRequest()}),s.forEach(l=>{l()}),e.value=[],n.clear(),s.clear(),r.value=null},updateConversationTitle:(i,l)=>{let d=e.value.find(y=>y.id===i);d&&(d.title=l,d.updatedAt=Date.now(),t?.saveConversation?.(d))},saveMessages:c,sendMessage:i=>{a.value?.engine.sendMessage(i)},abortActiveRequest:async()=>{await a.value?.engine.abortRequest()}}};0&&(module.exports={AIClient,BaseModelProvider,EXCLUDE_MODE_REMOVE,ErrorType,IndexedDBStrategy,LocalStorageStrategy,OpenAIProvider,StreamEventType,extractTextFromResponse,fallbackRolePlugin,formatMessages,handleSSEStream,indexedDBStorageStrategyFactory,lengthPlugin,localStorageStrategyFactory,sseStreamToGenerator,thinkingPlugin,toolPlugin,useConversation,useMessage});
package/dist/index.mjs CHANGED
@@ -1,4 +1,4 @@
1
- var J=class{constructor(t){this.config=t}updateConfig(t){this.config={...this.config,...t}}getConfig(){return{...this.config}}validateRequest(t){if(!t.messages||!Array.isArray(t.messages)||t.messages.length===0)throw new Error("\u8BF7\u6C42\u5FC5\u987B\u5305\u542B\u81F3\u5C11\u4E00\u6761\u6D88\u606F");for(let e of t.messages)if(!e.role||!e.content)throw new Error("\u6BCF\u6761\u6D88\u606F\u5FC5\u987B\u5305\u542B\u89D2\u8272\u548C\u5185\u5BB9")}};var Ce=(l=>(l.NETWORK_ERROR="network_error",l.AUTHENTICATION_ERROR="authentication_error",l.RATE_LIMIT_ERROR="rate_limit_error",l.SERVER_ERROR="server_error",l.MODEL_ERROR="model_error",l.TIMEOUT_ERROR="timeout_error",l.UNKNOWN_ERROR="unknown_error",l))(Ce||{}),ve=(s=>(s.DATA="data",s.ERROR="error",s.DONE="done",s))(ve||{});function N(o){return{type:o.type||"unknown_error",message:o.message||"\u672A\u77E5\u9519\u8BEF",statusCode:o.statusCode,originalError:o.originalError}}function Z(o){if(!o.response)return N({type:"network_error",message:"\u7F51\u7EDC\u8FDE\u63A5\u9519\u8BEF\uFF0C\u8BF7\u68C0\u67E5\u60A8\u7684\u7F51\u7EDC\u8FDE\u63A5",originalError:o});if(o.response){let{status:t,data:e}=o.response;return t===401||t===403?N({type:"authentication_error",message:"\u8EAB\u4EFD\u9A8C\u8BC1\u5931\u8D25\uFF0C\u8BF7\u68C0\u67E5\u60A8\u7684API\u5BC6\u94A5",statusCode:t,originalError:o}):t===429?N({type:"rate_limit_error",message:"\u8D85\u51FAAPI\u8C03\u7528\u9650\u5236\uFF0C\u8BF7\u7A0D\u540E\u518D\u8BD5",statusCode:t,originalError:o}):t>=500?N({type:"server_error",message:"\u670D\u52A1\u5668\u9519\u8BEF\uFF0C\u8BF7\u7A0D\u540E\u518D\u8BD5",statusCode:t,originalError:o}):N({type:"unknown_error",message:e?.error?.message||`\u8BF7\u6C42\u5931\u8D25\uFF0C\u72B6\u6001\u7801: ${t}`,statusCode:t,originalError:o})}return o.code==="ECONNABORTED"?N({type:"timeout_error",message:"\u8BF7\u6C42\u8D85\u65F6\uFF0C\u8BF7\u7A0D\u540E\u518D\u8BD5",originalError:o}):N({type:"unknown_error",message:o.message||"\u53D1\u751F\u672A\u77E5\u9519\u8BEF",originalError:o})}async function re(o,t,e){let s=o.body?.getReader();if(!s)throw new Error("Response body is null");let n=new TextDecoder,r="",a,l;e&&e.addEventListener("abort",()=>{s.cancel().catch(u=>console.error("Error cancelling reader:",u))},{once:!0});try{for(;;){if(e?.aborted){await s.cancel();break}let{done:u,value:p}=await s.read();if(u)break;let v=n.decode(p,{stream:!0});r+=v;let R=r.split(`
1
+ var H=class{constructor(t){this.config=t}updateConfig(t){this.config={...this.config,...t}}getConfig(){return{...this.config}}validateRequest(t){if(!t.messages||!Array.isArray(t.messages)||t.messages.length===0)throw new Error("\u8BF7\u6C42\u5FC5\u987B\u5305\u542B\u81F3\u5C11\u4E00\u6761\u6D88\u606F");for(let e of t.messages)if(!e.role||!e.content)throw new Error("\u6BCF\u6761\u6D88\u606F\u5FC5\u987B\u5305\u542B\u89D2\u8272\u548C\u5185\u5BB9")}};var Ce=(c=>(c.NETWORK_ERROR="network_error",c.AUTHENTICATION_ERROR="authentication_error",c.RATE_LIMIT_ERROR="rate_limit_error",c.SERVER_ERROR="server_error",c.MODEL_ERROR="model_error",c.TIMEOUT_ERROR="timeout_error",c.UNKNOWN_ERROR="unknown_error",c))(Ce||{}),ve=(n=>(n.DATA="data",n.ERROR="error",n.DONE="done",n))(ve||{});function N(o){return{type:o.type||"unknown_error",message:o.message||"\u672A\u77E5\u9519\u8BEF",statusCode:o.statusCode,originalError:o.originalError}}function Z(o){if(!o.response)return N({type:"network_error",message:"\u7F51\u7EDC\u8FDE\u63A5\u9519\u8BEF\uFF0C\u8BF7\u68C0\u67E5\u60A8\u7684\u7F51\u7EDC\u8FDE\u63A5",originalError:o});if(o.response){let{status:t,data:e}=o.response;return t===401||t===403?N({type:"authentication_error",message:"\u8EAB\u4EFD\u9A8C\u8BC1\u5931\u8D25\uFF0C\u8BF7\u68C0\u67E5\u60A8\u7684API\u5BC6\u94A5",statusCode:t,originalError:o}):t===429?N({type:"rate_limit_error",message:"\u8D85\u51FAAPI\u8C03\u7528\u9650\u5236\uFF0C\u8BF7\u7A0D\u540E\u518D\u8BD5",statusCode:t,originalError:o}):t>=500?N({type:"server_error",message:"\u670D\u52A1\u5668\u9519\u8BEF\uFF0C\u8BF7\u7A0D\u540E\u518D\u8BD5",statusCode:t,originalError:o}):N({type:"unknown_error",message:e?.error?.message||`\u8BF7\u6C42\u5931\u8D25\uFF0C\u72B6\u6001\u7801: ${t}`,statusCode:t,originalError:o})}return o.code==="ECONNABORTED"?N({type:"timeout_error",message:"\u8BF7\u6C42\u8D85\u65F6\uFF0C\u8BF7\u7A0D\u540E\u518D\u8BD5",originalError:o}):N({type:"unknown_error",message:o.message||"\u53D1\u751F\u672A\u77E5\u9519\u8BEF",originalError:o})}async function te(o,t,e){let n=o.body?.getReader();if(!n)throw new Error("Response body is null");let s=new TextDecoder,r="",a,c;e&&e.addEventListener("abort",()=>{n.cancel().catch(u=>console.error("Error cancelling reader:",u))},{once:!0});try{for(;;){if(e?.aborted){await n.cancel();break}let{done:u,value:f}=await n.read();if(u)break;let v=s.decode(f,{stream:!0});r+=v;let R=r.split(`
2
2
 
3
- `);r=R.pop()||"";for(let x of R)if(x.trim()!==""){if(x.trim()==="data: [DONE]"){l&&(a=l),t.onDone(a);continue}try{let A=x.match(/^data: (.+)$/m);if(!A)continue;let b=JSON.parse(A[1]);t.onData(b),l=b.choices?.[0]?.finish_reason||void 0}catch(A){console.error("Error parsing SSE message:",A)}}}(r.trim()==="data: [DONE]"||e?.aborted)&&(e?.aborted&&(a="aborted"),t.onDone(a))}catch(u){if(e?.aborted)return;throw u}}function ee(o="The operation was aborted"){let t=new Error(o);return t.name="AbortError",t}async function*Me(o,t={}){let e=o.body?.getReader();if(!e)throw new Error("ReadableStream not supported");let{signal:s}=t,n=new TextDecoder,r="",a=()=>{e.cancel()};s?.addEventListener("abort",a);try{for(;;){if(s?.aborted)throw ee();let l;try{l=await e.read()}catch(x){throw s?.aborted?ee():x}let{done:u,value:p}=l;if(u){if(s?.aborted)throw ee();return}let v=n.decode(p,{stream:!0});r+=v;let R=r.split(`
4
- `);r=R.pop()||"";for(let x of R)if(x.trim()!==""&&x.startsWith("data: ")){let A=x.slice(6);if(A==="[DONE]")return;try{yield JSON.parse(A)}catch(b){console.warn("Failed to parse SSE data:",A,b)}}}}finally{s?.removeEventListener("abort",a),e.releaseLock()}}var W=class extends J{constructor(e){super(e);this.defaultModel="gpt-3.5-turbo";this.baseURL=e.apiUrl||"https://api.openai.com/v1",this.apiKey=e.apiKey||"",e.defaultModel&&(this.defaultModel=e.defaultModel),this.apiKey||console.warn("API key is not provided. Authentication will likely fail.")}async chat(e){try{this.validateRequest(e);let s={model:e.options?.model||this.config.defaultModel||this.defaultModel,messages:e.messages,...e.options,stream:!1},n={method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(s)};this.apiKey&&Object.assign(n.headers,{Authorization:`Bearer ${this.apiKey}`});let r=await fetch(`${this.baseURL}/chat/completions`,n);if(!r.ok){let a=await r.text();throw new Error(`HTTP error! status: ${r.status}, details: ${a}`)}return await r.json()}catch(s){throw Z(s)}}async chatStream(e,s){let{signal:n,...r}=e.options||{};try{this.validateRequest(e);let a={model:e.options?.model||this.config.defaultModel||this.defaultModel,messages:e.messages,...r,stream:!0},l={method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${this.apiKey}`,Accept:"text/event-stream"},body:JSON.stringify(a),signal:n};this.apiKey&&Object.assign(l.headers,{Authorization:`Bearer ${this.apiKey}`});let u=await fetch(`${this.baseURL}/chat/completions`,l);if(!u.ok){let p=await u.text();throw new Error(`HTTP error! status: ${u.status}, details: ${p}`)}await re(u,s,n)}catch(a){if(n?.aborted)return;s.onError(Z(a))}}updateConfig(e){super.updateConfig(e),e.apiUrl&&(this.baseURL=e.apiUrl),e.apiKey&&(this.apiKey=e.apiKey),e.defaultModel&&(this.defaultModel=e.defaultModel)}};var te=class{constructor(t){this.config=t,this.provider=this.createProvider(t)}createProvider(t){if(t.provider==="custom"&&"providerImplementation"in t)return t.providerImplementation;if(t.provider==="deepseek"){let e={defaultModel:"deepseek-chat",apiUrl:"https://api.deepseek.com/v1"};return new W({...e,...t})}else return new W(t)}async chat(t){return this.provider.chat(t)}async chatStream(t,e){let s={...t,options:{...t.options,stream:!0}};return this.provider.chatStream(s,e)}getConfig(){return{...this.config}}updateConfig(t){this.config={...this.config,...t},t.provider&&t.provider!==this.config.provider?this.provider=this.createProvider(this.config):this.provider.updateConfig(this.config)}};import{toRaw as be}from"vue";function H(o,t=new WeakSet){if(o==null||typeof o!="object")return o;if(t.has(o))return Array.isArray(o)?[]:{};t.add(o);try{let e=be(o);if(Array.isArray(e))return e.map(n=>H(n,t));if(e instanceof Date||e instanceof RegExp||e instanceof ArrayBuffer||e instanceof Blob)return e;let s={};for(let n in e){if(typeof n=="symbol")continue;let r=Object.getOwnPropertyDescriptor(e,n);if(!r||r.get||r.set)continue;let a=e[n];typeof a!="function"&&typeof a!="symbol"&&(s[n]=H(a,t))}return s}catch(e){return console.warn("unwrapProxy error:",e),Array.isArray(o)?[]:{}}}var z=o=>o.map(t=>{let{renderContent:e,...s}=t;if(!Array.isArray(e))return t;let n=e.filter(a=>a.type==="collapsible-text"),r=e.filter(a=>a.type==="markdown"||a.type==="text");return n.length>0&&(s.reasoning_content=n.map(a=>a.content).join("")),r.length>0&&(s.content=r.map(a=>a.content).join("")),s});var G=o=>{let t=localStorage.getItem(o);return t?JSON.parse(t):[]},V=class{constructor(t="tiny-robot-ai-conversations"){this.storageKey=t}saveConversation(t){try{let e=G(this.storageKey),s=e.findIndex(n=>n.id===t.id);s!==-1?Object.assign(e[s],t):e.unshift({...t,messages:[]}),localStorage.setItem(this.storageKey,JSON.stringify(e))}catch(e){console.error("\u4FDD\u5B58\u4F1A\u8BDD\u5931\u8D25:",e)}}loadConversations(){try{return G(this.storageKey).map(e=>({id:e.id,title:e.title,createdAt:e.createdAt,updatedAt:e.updatedAt,metadata:e.metadata}))}catch(t){return console.error("\u52A0\u8F7D\u4F1A\u8BDD\u5931\u8D25:",t),[]}}saveMessages(t,e){try{let s=G(this.storageKey),n=s.findIndex(r=>r.id===t);n!==-1&&(s[n].messages=e),localStorage.setItem(this.storageKey,JSON.stringify(s))}catch(s){console.error("\u4FDD\u5B58\u4F1A\u8BDD\u6D88\u606F\u5931\u8D25:",s)}}loadMessages(t){try{let s=G(this.storageKey).find(r=>r.id===t);return z(s?.messages||[])}catch(e){return console.error("\u52A0\u8F7D\u4F1A\u8BDD\u6D88\u606F\u5931\u8D25:",e),[]}}deleteConversation(t){let e=G(this.storageKey),s=e.findIndex(n=>n.id===t);s!==-1&&e.splice(s,1),localStorage.setItem(this.storageKey,JSON.stringify(e))}};import{openDB as Re}from"idb";var $=class{constructor(t="tiny-robot-ai-db",e=3){this.db=null;this.dbName=t,this.dbVersion=e}async getDB(){return this.db||(this.db=await Re(this.dbName,this.dbVersion,{upgrade(t){t.objectStoreNames.contains("conversations")||t.createObjectStore("conversations",{keyPath:"id"}).createIndex("by-updated","updatedAt"),t.objectStoreNames.contains("messages")||t.createObjectStore("messages",{keyPath:"conversationId"})}})),this.db}async loadConversations(){try{return(await(await this.getDB()).getAllFromIndex("conversations","by-updated")).reverse()}catch(t){return console.error("\u52A0\u8F7D\u4F1A\u8BDD\u5931\u8D25:",t),[]}}async loadMessages(t){try{let s=await(await this.getDB()).get("messages",t);return s?z(s.messages):[]}catch(e){return console.error("\u52A0\u8F7D\u4F1A\u8BDD\u6D88\u606F\u5931\u8D25:",e),[]}}async saveConversation(t){try{let e=await this.getDB(),s=H(t);await e.put("conversations",s)}catch(e){throw console.error("\u4FDD\u5B58\u4F1A\u8BDD\u5931\u8D25:",e),e}}async saveMessages(t,e){try{let s=await this.getDB(),n=H(e);await s.put("messages",{conversationId:t,messages:n})}catch(s){throw console.error("\u4FDD\u5B58\u4F1A\u8BDD\u6D88\u606F\u5931\u8D25:",s),s}}async deleteConversation(t){try{let e=await this.getDB();await e.delete("conversations",t),await e.delete("messages",t)}catch(e){throw console.error("\u5220\u9664\u4F1A\u8BDD\u5931\u8D25:",e),e}}};function oe(o={}){return new V(o.key||"tiny-robot-ai-conversations")}function xe(o={}){return new $(o.dbName||"tiny-robot-ai-db",o.dbVersion||1)}import{computed as Be,ref as he,watch as Ne}from"vue";import{computed as Ee,reactive as Oe,ref as Q,watch as Ie}from"vue";var ae=(o={})=>{let{fallbackRole:t="assistant",...e}=o;return{name:"fallbackRole",...e,onBeforeRequest(s){let{requestBody:n,messages:r}=s;return n.messages=r.map(a=>({...a,role:a.role||t})),e.onBeforeRequest?.(s)}}};var ie=(o={})=>{let{continueContent:t="Please continue with your previous answer.",...e}=o;return{name:"length",...e,onAfterRequest:async s=>{let{lastChoice:n,appendMessage:r,requestNext:a}=s;return n?.finish_reason==="length"&&(r({role:"user",content:t}),a()),e.onAfterRequest?.(s)}}};var le=(o={})=>({name:"thinking",...o,onCompletionChunk(t){let{choice:e,currentMessage:s}=t,r=typeof(e?.message?.reasoning_content||e?.delta?.reasoning_content)=="string";return s.state?s.state.thinking=r:s.state={thinking:r},o.onCompletionChunk?.(t)},onTurnEnd(t){let e=t.currentTurn.slice(-1)[0];return e?.state&&(e.state.thinking=void 0),o.onTurnEnd?.(t)}});import{reactive as we}from"vue";var K=class extends Error{constructor(t){super(t),this.name="AbortError"}};function Ae(o){if(o.aborted)return{promise:Promise.reject(new K(String(o.reason??"Aborted"))),cleanup:()=>{}};let t=null;return{promise:new Promise((n,r)=>{t=()=>{r(new K(String(o.reason??"Aborted")))},o.addEventListener("abort",t,{once:!0})}),cleanup:()=>{t&&(o.removeEventListener("abort",t),t=null)}}}function de(o,t){let{promise:e,cleanup:s}=Ae(t);return Promise.race([o,e]).finally(s)}function ge(o,t){let e={};for(let s in o)t.includes(s)&&(e[s]=o[s]);return e}function pe(o,t){let e={};for(let s in o)t.includes(s)||(e[s]=o[s]);return e}async function*X(o){if(ce(o)){yield*o;return}let t=await o;if(ce(t)){yield*t;return}yield t}function ce(o){return o&&typeof o=="object"&&typeof o[Symbol.asyncIterator]=="function"}var se=o=>typeof o=="object"&&o!==null,ue=o=>se(o)&&typeof o.index=="number",j=(o,t)=>{for(let[e,s]of Object.entries(t)){let n=o[e];if(n)if(typeof n=="string"&&typeof s=="string")e==="type"&&n||(o[e]=n+s);else if(Array.isArray(n)&&Array.isArray(s))if(n.every(r=>ue(r))&&s.every(r=>ue(r))){let r=new Map(n.map(p=>[p.index,p])),a=new Map(s.map(p=>[p.index,p]));for(let[p,v]of a)if(r.has(p)){let R=r.get(p);r.set(p,j(R,v))}else r.set(p,v);let l=Math.max(...Array.from(r.keys()),-1)+1,u=l>n.length?Array.from({length:l}):n;for(let[p,v]of r)u[p]=v;o[e]=u}else o[e]=[...n,...s];else se(n)&&se(s)&&(o[e]=j(n,s));else o[e]=s}return o};function Te(o,t){let e=[];for(let s=0;s<o.length;s++){let n=o[s];if(n.role==="assistant"&&n.tool_calls&&n.tool_calls.length>0){let r=new Set(n.tool_calls.map(u=>u.id)),a=new Set;for(let u=s+1;u<o.length;u++){let p=o[u];p.role==="tool"&&p.tool_call_id&&r.has(p.tool_call_id)&&a.add(p.tool_call_id)}let l=n.tool_calls.map(u=>u.id).filter(u=>!a.has(u));l.length>0&&e.push({insertAfterIndex:s,missingToolCallIds:l})}}for(let s=e.length-1;s>=0;s--){let{insertAfterIndex:n,missingToolCallIds:r}=e[s],a=r.map(l=>({role:"tool",tool_call_id:l,content:t}));o.splice(n+1,0,...a)}}var Se="remove";function Pe(o,t,e,s){let n=o.filter(a=>a[e]),r=new Set(n.flatMap(a=>a.tool_calls?.map(l=>l.id)??[]));if(t===Se)for(let a=o.length-1;a>=0;a--){let l=o[a];(l[e]||l[s]||l.tool_call_id&&r.has(l.tool_call_id))&&o.splice(a,1)}else if(t===!0)for(let a of o)(a[e]||a.tool_call_id&&r.has(a.tool_call_id))&&(a[s]=!0,delete a[e])}var mt=o=>{let{getTools:t,beforeCallTools:e,callTool:s,onToolCallStart:n,onToolCallEnd:r,toolCallCancelledContent:a="Tool call cancelled.",toolCallFailedContent:l="Tool call failed.",autoFillMissingToolMessages:u=!1,excludeToolMessagesNextTurn:p=!1,...v}=o,R=Symbol("doNotSendNextTurn"),x=Symbol("doNotSend"),A=(...m)=>{let[h,{primaryMessage:T}]=m;T.state.toolCall[h.id].status="running",n?.(...m)},b=(...m)=>{let[h,{status:T,primaryMessage:O}]=m;O.state.toolCall[h.id].status=T,r?.(...m)};return{name:"tool",...v,onTurnStart:m=>{let{messages:h}=m;return u&&Te(h,a),p&&Pe(h,p,R,x),v.onTurnStart?.(m)},onBeforeRequest:async m=>{let{messages:h,requestBody:T}=m;p===!0&&(T.messages=h.filter(E=>!E[x]));let O=await t?.();return O&&O.length>0&&(T.tools=O),v.onBeforeRequest?.(m)},onAfterRequest:async m=>{let{currentMessage:h,lastChoice:T,appendMessage:O,abortSignal:E,setRequestState:i,requestNext:c}=m;if(T?.finish_reason!=="tool_calls"||!h.tool_calls?.length)return;p&&(h[R]=!0),i("processing","calling-tools"),await e?.(h.tool_calls,{...m,currentMessage:h});let f=h.tool_calls.map(async y=>{let S=Math.floor(Date.now()/1e3),w=we({role:"tool",tool_call_id:y.id,content:"",metadata:{createdAt:S,updatedAt:S}});O(w);let U={...m,primaryMessage:h,toolMessage:w};A(y,U);try{let I=s(y,U),d=X(I);for await(let g of d){if(typeof g=="string")w.content+=g;else{let M={};try{M=JSON.parse(w.content||"{}")}catch(P){console.warn(P)}w.content=JSON.stringify(j(M,g))}w.metadata.updatedAt=Math.floor(Date.now()/1e3)}b(y,{...U,status:"success"})}catch(I){let d=I instanceof Error?I:new Error(String(I));if(E.aborted){b(y,{...U,status:"cancelled",error:d});return}console.error(I),w.content.length===0&&(w.content=l),b(y,{...U,status:"failed",error:d})}});return await Promise.all(f),c(),v.onAfterRequest?.(m)},onCompletionChunk:m=>{var T,O,E;let{currentMessage:h}=m;if(Array.isArray(h.tool_calls))for(let i of h.tool_calls)h.state?.toolCall?.[i.id]?.status||(h.state??(h.state={}),(T=h.state).toolCall??(T.toolCall={}),(O=h.state.toolCall)[E=i.id]??(O[E]={}));return v.onCompletionChunk?.(m)}}};var ke=o=>{let t=[];for(let e of o){if(e.name){let s=t.findIndex(n=>n.name===e.name);s!==-1&&t.splice(s,1)}t.push(e)}return t},ne=o=>{let{initialMessages:t=[],requestMessageFields:e=[],requestMessageFieldsExclude:s=["state","metadata","loading"],plugins:n=[],onCompletionChunk:r}=o,a=Q("idle"),l=Q(void 0),u=Q(t),p=Q(o.responseProvider),v=null,R=[],x={},A=[ae(),le(),ie()],b=ke(A.concat(n)),m=Ee(()=>a.value==="processing"),h=async d=>{if(!d||!d.trim()){console.warn("Cannot send empty message");return}if(m.value){console.warn("Cannot send message while processing is in progress");return}let g=Math.floor(Date.now()/1e3);u.value.push({role:"user",content:d.trim(),metadata:{createdAt:g,updatedAt:g}}),R.push(u.value[u.value.length-1]),await S()},T=async(...d)=>{if(m.value){console.warn("Cannot send message while processing is in progress");return}u.value.push(...d),R.push(...d),await S()},O=d=>{let g=d;return e.length&&(g=g.map(M=>ge(M,e))),s.length&&(g=g.map(M=>pe(M,s))),g},E=(d,g)=>{a.value=d,d==="processing"?l.value=g||"requesting":l.value=void 0},i=d=>{Object.assign(x,d)},c=d=>({messages:u.value,currentTurn:R,requestState:a.value,processingState:l.value,plugins:b,abortSignal:d,setRequestState:E,customContext:x,setCustomContext:i}),f=(d,g)=>typeof d.disabled=="function"?d.disabled(g):!!d.disabled,y=async(d,g)=>{E("processing","requesting");let M=new Proxy({messages:O(u.value)},{set(D,k,B){return k==="messages"?(D.messages=O(B),!0):(D[k]=B,!0)}}),P=c(g);for(let D of b.filter(k=>!f(k,P)))await D.onBeforeRequest?.({...P,requestBody:M});let C=Oe({role:"",content:"",loading:!0});I(C);let _,Y=d(M,g),q=X(Y);for await(let D of q){E("processing","completing"),C.loading&&(C.loading=void 0);let k=D.choices?.find(F=>F.index===0);if(k){_=k;let F=()=>{C.metadata||(C.metadata={});let{created:L,...ye}=D;C.metadata.createdAt=L,C.metadata.updatedAt=Math.floor(Date.now()/1e3),Object.assign(C.metadata,ye),j(C,k.message||k.delta)};if(r){let L=c(g);r({...L,chunk:D,choice:k,currentMessage:C},F)}else F()}let B=c(g);for(let F of b.filter(L=>!f(L,B)))F.onCompletionChunk?.({...B,abortSignal:g,chunk:D,choice:k,currentMessage:C})}await U(C,d,g,_)},S=async()=>{let d=new AbortController;v=d,x={};try{E("processing","requesting");let g=c(d.signal);for(let C of b.filter(_=>!f(_,g)))await C.onTurnStart?.(g);let M=p.value;try{await y(M,d.signal),E("completed")}catch(C){if(d.signal.aborted||C instanceof K||C instanceof Error&&C.name==="AbortError")E("aborted");else throw C}let P=c(d.signal);for(let C of b.filter(_=>!f(_,P)))await C.onTurnEnd?.(P)}catch(g){E("error");let M=!1,P=c(d.signal);for(let C of b.filter(_=>!f(_,P)))M=!0,C.onError?.({...P,error:g});if(!M)throw g}finally{let g=c(d.signal);for(let M of b.filter(P=>!f(P,g)))try{M.onFinally?.(g)}catch(P){console.error(`Error in onFinally hook for plugin ${M.name||"Anonymous"}:`,P)}v=null,R.slice(-1)[0]&&(R.slice(-1)[0].loading=void 0),R=[]}},w=async()=>{v?.abort(),m.value&&await new Promise(d=>{let g=Ie(m,M=>{M||(g(),d())},{immediate:!0})})},U=async(d,g,M,P)=>{let C=!1,_=c(M),Y=b.filter(q=>!f(q,_)).map(q=>{if(!q.onAfterRequest)return null;let D=B=>{I(B)},k=()=>{C=!0};return q.onAfterRequest({..._,currentMessage:d,lastChoice:P,appendMessage:D,requestNext:k})}).filter(q=>q!==null);await de(Promise.all(Y),M),C&&await y(g,M)},I=d=>{let g=Array.isArray(d)?d:[d];u.value.push(...g),R.push(...g)};return{requestState:a,processingState:l,messages:u,responseProvider:p,isProcessing:m,sendMessage:h,send:T,abortRequest:w}};import{isRef as _e,toValue as De}from"vue";function me(o,t=200,e=!1,s=!0,n=!1){return Ue(qe(t,e,s,n),o)}function Ue(o,t){function e(...s){return new Promise((n,r)=>{Promise.resolve(o(()=>t.apply(this,s),{fn:t,thisArg:this,args:s})).then(n).catch(r)})}return e}var fe=()=>{};function qe(...o){let t=0,e,s=!0,n=fe,r,a,l,u,p;!_e(o[0])&&typeof o[0]=="object"?{delay:a,trailing:l=!0,leading:u=!0,rejectOnCancel:p=!1}=o[0]:[a,l=!0,u=!0,p=!1]=o;let v=()=>{e&&(clearTimeout(e),e=void 0,n(),n=fe)};return x=>{let A=De(a),b=Date.now()-t,m=()=>r=x();return v(),A<=0?(t=Date.now(),m()):(b>A?(t=Date.now(),(u||!s)&&m()):l&&(r=new Promise((h,T)=>{n=p?T:h,e=setTimeout(()=>{t=Date.now(),s=!0,h(m()),v()},Math.max(0,A-b))})),!u&&!e&&(e=setTimeout(()=>s=!0,A)),s=!1,r)}}var Et=o=>{let t=o.storage||oe(),e=he([]),s=new Map,n=new Map,r=he(null),a=Be(()=>{let i=r.value;if(!i)return null;let c=e.value.find(y=>y.id===i);if(!c)return null;let f=s.get(i);return f?{...c,engine:f}:null}),l=i=>{if(!t?.saveMessages)return;let c=i||r.value,f=e.value.find(S=>S.id===c);if(!f)return;f.updatedAt=Date.now(),t?.saveConversation?.(f);let y=s.get(f.id);y&&t.saveMessages(f.id,y.messages.value)},u=(i,c)=>{if(!o.autoSaveMessages||!t?.saveMessages)return;let f=n.get(i);f&&f();let y=o.autoSaveThrottle??1e3,S=me(()=>{l(i)},y,!0,!0),w=Ne(c.messages,S,{deep:!0});n.set(i,w)},p=i=>{let c=n.get(i);c&&(c(),n.delete(i))};t?.loadConversations&&Promise.resolve(t.loadConversations()).then(i=>{e.value=i}).catch(i=>{console.error("[useConversation] loadConversations failed:",i)});let v=async(i,c)=>{let f=s.get(i);if(f)return f;let y=c?.initialMessages??o.useMessageOptions.initialMessages??[];if(t?.loadMessages)try{y=await t.loadMessages(i)}catch(w){console.error("[useConversation] loadMessages failed:",w)}let S=ne({...o.useMessageOptions,...c,initialMessages:y});return s.set(i,S),u(i,S),S};function R(){return Date.now().toString(36)+Math.random().toString(36).substring(2,9)}let x=i=>{let{id:c=R(),title:f,metadata:y,useMessageOptions:S}=i||{},w=Date.now(),U={id:c,title:f,createdAt:w,updatedAt:w,metadata:y};e.value.unshift(U);let I=ne({...o.useMessageOptions,...S});return s.set(c,I),u(c,I),t?.saveConversation?.(U),t?.saveMessages?.(c,I.messages.value),r.value=c,a.value},A=i=>{let{excludeId:c}=i||{};s.forEach((f,y)=>{if(c&&y===c)return;f.isProcessing?.value||(p(y),s.delete(y))})};return{conversations:e,activeConversationId:r,activeConversation:a,createConversation:x,switchConversation:async i=>i?r.value===i?a.value:e.value.find(f=>f.id===i)?(await v(i),A({excludeId:i}),r.value=i,a.value):null:null,deleteConversation:async i=>{let c=e.value.findIndex(y=>y.id===i);if(c===-1)return;await s.get(i)?.abortRequest(),p(i),s.delete(i),e.value.splice(c,1),t?.deleteConversation?.(i),r.value===i&&(r.value=null,A())},clear:()=>{e.value.map(c=>c.id).forEach(c=>{t?.deleteConversation?.(c)}),s.forEach(c=>{c.abortRequest()}),n.forEach(c=>{c()}),e.value=[],s.clear(),n.clear(),r.value=null},updateConversationTitle:(i,c)=>{let f=e.value.find(y=>y.id===i);f&&(f.title=c,f.updatedAt=Date.now(),t?.saveConversation?.(f))},saveMessages:l,sendMessage:i=>{a.value?.engine.sendMessage(i)},abortActiveRequest:async()=>{await a.value?.engine.abortRequest()}}};export{te as AIClient,Se as EXCLUDE_MODE_REMOVE,Ce as ErrorType,$ as IndexedDBStrategy,V as LocalStorageStrategy,ve as StreamEventType,ae as fallbackRolePlugin,xe as indexedDBStorageStrategyFactory,ie as lengthPlugin,oe as localStorageStrategyFactory,Me as sseStreamToGenerator,le as thinkingPlugin,mt as toolPlugin,Et as useConversation,ne as useMessage};
3
+ `);r=R.pop()||"";for(let x of R)if(x.trim()!==""){if(x.trim()==="data: [DONE]"){c&&(a=c),t.onDone(a);continue}try{let A=x.match(/^data: (.+)$/m);if(!A)continue;let b=JSON.parse(A[1]);t.onData(b),c=b.choices?.[0]?.finish_reason||void 0}catch(A){console.error("Error parsing SSE message:",A)}}}(r.trim()==="data: [DONE]"||e?.aborted)&&(e?.aborted&&(a="aborted"),t.onDone(a))}catch(u){if(e?.aborted)return;throw u}}function Me(o){return o.map(t=>typeof t=="object"&&"role"in t&&"content"in t?{role:t.role,content:String(t.content),...t.name?{name:t.name}:{}}:typeof t=="string"?{role:"user",content:t}:{role:"user",content:String(t)})}function be(o){return!o.choices||!o.choices.length?"":o.choices[0].message?.content||""}function ee(o="The operation was aborted"){let t=new Error(o);return t.name="AbortError",t}async function*Re(o,t={}){let e=o.body?.getReader();if(!e)throw new Error("ReadableStream not supported");let{signal:n}=t,s=new TextDecoder,r="",a=()=>{e.cancel()};n?.addEventListener("abort",a);try{for(;;){if(n?.aborted)throw ee();let c;try{c=await e.read()}catch(x){throw n?.aborted?ee():x}let{done:u,value:f}=c;if(u){if(n?.aborted)throw ee();return}let v=s.decode(f,{stream:!0});r+=v;let R=r.split(`
4
+ `);r=R.pop()||"";for(let x of R)if(x.trim()!==""&&x.startsWith("data: ")){let A=x.slice(6);if(A==="[DONE]")return;try{yield JSON.parse(A)}catch(b){console.warn("Failed to parse SSE data:",A,b)}}}}finally{n?.removeEventListener("abort",a),e.releaseLock()}}var K=class extends H{constructor(e){super(e);this.defaultModel="gpt-3.5-turbo";this.baseURL=e.apiUrl||"https://api.openai.com/v1",this.apiKey=e.apiKey||"",e.defaultModel&&(this.defaultModel=e.defaultModel),this.apiKey||console.warn("API key is not provided. Authentication will likely fail.")}async chat(e){try{this.validateRequest(e);let n={model:e.options?.model||this.config.defaultModel||this.defaultModel,messages:e.messages,...e.options,stream:!1},s={method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(n)};this.apiKey&&Object.assign(s.headers,{Authorization:`Bearer ${this.apiKey}`});let r=await fetch(`${this.baseURL}/chat/completions`,s);if(!r.ok){let a=await r.text();throw new Error(`HTTP error! status: ${r.status}, details: ${a}`)}return await r.json()}catch(n){throw Z(n)}}async chatStream(e,n){let{signal:s,...r}=e.options||{};try{this.validateRequest(e);let a={model:e.options?.model||this.config.defaultModel||this.defaultModel,messages:e.messages,...r,stream:!0},c={method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${this.apiKey}`,Accept:"text/event-stream"},body:JSON.stringify(a),signal:s};this.apiKey&&Object.assign(c.headers,{Authorization:`Bearer ${this.apiKey}`});let u=await fetch(`${this.baseURL}/chat/completions`,c);if(!u.ok){let f=await u.text();throw new Error(`HTTP error! status: ${u.status}, details: ${f}`)}await te(u,n,s)}catch(a){if(s?.aborted)return;n.onError(Z(a))}}updateConfig(e){super.updateConfig(e),e.apiUrl&&(this.baseURL=e.apiUrl),e.apiKey&&(this.apiKey=e.apiKey),e.defaultModel&&(this.defaultModel=e.defaultModel)}};var oe=class{constructor(t){this.config=t,this.provider=this.createProvider(t)}createProvider(t){if(t.provider==="custom"&&"providerImplementation"in t)return t.providerImplementation;if(t.provider==="deepseek"){let e={defaultModel:"deepseek-chat",apiUrl:"https://api.deepseek.com/v1"};return new K({...e,...t})}else return new K(t)}async chat(t){return this.provider.chat(t)}async chatStream(t,e){let n={...t,options:{...t.options,stream:!0}};return this.provider.chatStream(n,e)}getConfig(){return{...this.config}}updateConfig(t){this.config={...this.config,...t},t.provider&&t.provider!==this.config.provider?this.provider=this.createProvider(this.config):this.provider.updateConfig(this.config)}};import{toRaw as xe}from"vue";function G(o,t=new WeakMap){if(o==null||typeof o!="object")return o;try{let e=xe(o);if(t.has(e))return t.get(e);if(Array.isArray(e)){let s=[];return t.set(e,s),s.push(...e.map(r=>G(r,t))),s}if(e instanceof Date||e instanceof RegExp||e instanceof ArrayBuffer||e instanceof Blob)return e;let n={};t.set(e,n);for(let s of Object.keys(e)){let r=Object.getOwnPropertyDescriptor(e,s);if(!r||r.get||r.set)continue;let a=e[s];typeof a!="function"&&typeof a!="symbol"&&(n[s]=G(a,t))}return n}catch(e){return console.warn("unwrapProxy error:",e),Array.isArray(o)?[]:{}}}var z=o=>o.map(t=>{let{renderContent:e,...n}=t;if(!Array.isArray(e))return t;let s=e.filter(a=>a.type==="collapsible-text"),r=e.filter(a=>a.type==="markdown"||a.type==="text");return s.length>0&&(n.reasoning_content=s.map(a=>a.content).join("")),r.length>0&&(n.content=r.map(a=>a.content).join("")),n});var V=o=>{let t=localStorage.getItem(o);return t?JSON.parse(t):[]},$=class{constructor(t="tiny-robot-ai-conversations"){this.storageKey=t}saveConversation(t){try{let e=V(this.storageKey),n=e.findIndex(s=>s.id===t.id);n!==-1?Object.assign(e[n],t):e.unshift({...t,messages:[]}),localStorage.setItem(this.storageKey,JSON.stringify(e))}catch(e){console.error("\u4FDD\u5B58\u4F1A\u8BDD\u5931\u8D25:",e)}}loadConversations(){try{return V(this.storageKey).map(e=>({id:e.id,title:e.title,createdAt:e.createdAt,updatedAt:e.updatedAt,metadata:e.metadata}))}catch(t){return console.error("\u52A0\u8F7D\u4F1A\u8BDD\u5931\u8D25:",t),[]}}saveMessages(t,e){try{let n=V(this.storageKey),s=n.findIndex(r=>r.id===t);s!==-1&&(n[s].messages=e),localStorage.setItem(this.storageKey,JSON.stringify(n))}catch(n){console.error("\u4FDD\u5B58\u4F1A\u8BDD\u6D88\u606F\u5931\u8D25:",n)}}loadMessages(t){try{let n=V(this.storageKey).find(r=>r.id===t);return z(n?.messages||[])}catch(e){return console.error("\u52A0\u8F7D\u4F1A\u8BDD\u6D88\u606F\u5931\u8D25:",e),[]}}deleteConversation(t){let e=V(this.storageKey),n=e.findIndex(s=>s.id===t);n!==-1&&e.splice(n,1),localStorage.setItem(this.storageKey,JSON.stringify(e))}};import{openDB as Ae}from"idb";var J=class{constructor(t="tiny-robot-ai-db",e=3){this.db=null;this.dbName=t,this.dbVersion=e}async getDB(){return this.db||(this.db=await Ae(this.dbName,this.dbVersion,{upgrade(t){t.objectStoreNames.contains("conversations")||t.createObjectStore("conversations",{keyPath:"id"}).createIndex("by-updated","updatedAt"),t.objectStoreNames.contains("messages")||t.createObjectStore("messages",{keyPath:"conversationId"})}})),this.db}async loadConversations(){try{return(await(await this.getDB()).getAllFromIndex("conversations","by-updated")).reverse()}catch(t){return console.error("\u52A0\u8F7D\u4F1A\u8BDD\u5931\u8D25:",t),[]}}async loadMessages(t){try{let n=await(await this.getDB()).get("messages",t);return n?z(n.messages):[]}catch(e){return console.error("\u52A0\u8F7D\u4F1A\u8BDD\u6D88\u606F\u5931\u8D25:",e),[]}}async saveConversation(t){try{let e=await this.getDB(),n=G(t);await e.put("conversations",n)}catch(e){throw console.error("\u4FDD\u5B58\u4F1A\u8BDD\u5931\u8D25:",e),e}}async saveMessages(t,e){try{let n=await this.getDB(),s=G(e);await n.put("messages",{conversationId:t,messages:s})}catch(n){throw console.error("\u4FDD\u5B58\u4F1A\u8BDD\u6D88\u606F\u5931\u8D25:",n),n}}async deleteConversation(t){try{let e=await this.getDB();await e.delete("conversations",t),await e.delete("messages",t)}catch(e){throw console.error("\u5220\u9664\u4F1A\u8BDD\u5931\u8D25:",e),e}}};function ne(o={}){return new $(o.key||"tiny-robot-ai-conversations")}function we(o={}){return new J(o.dbName||"tiny-robot-ai-db",o.dbVersion||1)}import{computed as Fe,ref as he,watch as Ke}from"vue";import{computed as Ie,reactive as ke,ref as Q,watch as _e}from"vue";var ae=(o={})=>{let{fallbackRole:t="assistant",...e}=o;return{name:"fallbackRole",...e,onBeforeRequest(n){let{requestBody:s}=n;return s.messages=s.messages.map(r=>({...r,role:r.role||t})),e.onBeforeRequest?.(n)}}};var ie=(o={})=>{let{continueContent:t="Please continue with your previous answer.",...e}=o;return{name:"length",...e,onAfterRequest:async n=>{let{lastChoice:s,appendMessage:r,requestNext:a}=n;return s?.finish_reason==="length"&&(r({role:"user",content:t}),a()),e.onAfterRequest?.(n)}}};var le=(o={})=>({name:"thinking",...o,onCompletionChunk(t){let{choice:e,currentMessage:n}=t,r=typeof(e?.message?.reasoning_content||e?.delta?.reasoning_content)=="string";return n.state?n.state.thinking=r:n.state={thinking:r},o.onCompletionChunk?.(t)},onTurnEnd(t){let e=t.currentTurn.slice(-1)[0];return e?.state&&(e.state.thinking=void 0),o.onTurnEnd?.(t)}});import{reactive as Se}from"vue";var j=class extends Error{constructor(t){super(t),this.name="AbortError"}};function Te(o){if(o.aborted)return{promise:Promise.reject(new j(String(o.reason??"Aborted"))),cleanup:()=>{}};let t=null;return{promise:new Promise((s,r)=>{t=()=>{r(new j(String(o.reason??"Aborted")))},o.addEventListener("abort",t,{once:!0})}),cleanup:()=>{t&&(o.removeEventListener("abort",t),t=null)}}}function de(o,t){let{promise:e,cleanup:n}=Te(t);return Promise.race([o,e]).finally(n)}function ge(o,t){let e={};for(let n in o)t.includes(n)&&(e[n]=o[n]);return e}function pe(o,t){let e={};for(let n in o)t.includes(n)||(e[n]=o[n]);return e}async function*X(o){if(ce(o)){yield*o;return}let t=await o;if(ce(t)){yield*t;return}yield t}function ce(o){return o&&typeof o=="object"&&typeof o[Symbol.asyncIterator]=="function"}var se=o=>typeof o=="object"&&o!==null,ue=o=>se(o)&&typeof o.index=="number",L=(o,t)=>{for(let[e,n]of Object.entries(t)){let s=o[e];if(s)if(typeof s=="string"&&typeof n=="string")e==="type"&&s||(o[e]=s+n);else if(Array.isArray(s)&&Array.isArray(n))if(s.every(r=>ue(r))&&n.every(r=>ue(r))){let r=new Map(s.map(f=>[f.index,f])),a=new Map(n.map(f=>[f.index,f]));for(let[f,v]of a)if(r.has(f)){let R=r.get(f);r.set(f,L(R,v))}else r.set(f,v);let c=Math.max(...Array.from(r.keys()),-1)+1,u=c>s.length?Array.from({length:c}):s;for(let[f,v]of r)u[f]=v;o[e]=u}else o[e]=[...s,...n];else se(s)&&se(n)&&(o[e]=L(s,n));else o[e]=n}return o};function Pe(o,t){let e=[];for(let n=0;n<o.length;n++){let s=o[n];if(s.role==="assistant"&&s.tool_calls&&s.tool_calls.length>0){let r=new Set(s.tool_calls.map(u=>u.id)),a=new Set;for(let u=n+1;u<o.length;u++){let f=o[u];f.role==="tool"&&f.tool_call_id&&r.has(f.tool_call_id)&&a.add(f.tool_call_id)}let c=s.tool_calls.map(u=>u.id).filter(u=>!a.has(u));c.length>0&&e.push({insertAfterIndex:n,missingToolCallIds:c})}}for(let n=e.length-1;n>=0;n--){let{insertAfterIndex:s,missingToolCallIds:r}=e[n],a=r.map(c=>({role:"tool",tool_call_id:c,content:t}));o.splice(s+1,0,...a)}}var Ee="remove";function Oe(o,t,e,n){let s=o.filter(a=>a[e]),r=new Set(s.flatMap(a=>a.tool_calls?.map(c=>c.id)??[]));if(t===Ee)for(let a=o.length-1;a>=0;a--){let c=o[a];(c[e]||c[n]||c.tool_call_id&&r.has(c.tool_call_id))&&o.splice(a,1)}else if(t===!0)for(let a of o)(a[e]||a.tool_call_id&&r.has(a.tool_call_id))&&(a[n]=!0,delete a[e])}var yt=o=>{let{getTools:t,beforeCallTools:e,callTool:n,onToolCallStart:s,onToolCallEnd:r,toolCallCancelledContent:a="Tool call cancelled.",toolCallFailedContent:c="Tool call failed.",autoFillMissingToolMessages:u=!1,excludeToolMessagesNextTurn:f=!1,...v}=o,R=Symbol("doNotSendNextTurn"),x=Symbol("doNotSend"),A=(...m)=>{let[h,{primaryMessage:T}]=m;T.state.toolCall[h.id].status="running",s?.(...m)},b=(...m)=>{let[h,{status:T,primaryMessage:O}]=m;O.state.toolCall[h.id].status=T,r?.(...m)};return{name:"tool",...v,onTurnStart:m=>{let{messages:h}=m;return u&&Pe(h,a),f&&Oe(h,f,R,x),v.onTurnStart?.(m)},onBeforeRequest:async m=>{let{messages:h,requestBody:T}=m;f===!0&&(T.messages=h.filter(E=>!E[x]));let O=await t?.();return O&&O.length>0&&(T.tools=O),v.onBeforeRequest?.(m)},onAfterRequest:async m=>{let{currentMessage:h,lastChoice:T,appendMessage:O,abortSignal:E,setRequestState:i,requestNext:l}=m;if(T?.finish_reason!=="tool_calls"||!h.tool_calls?.length)return;f&&(h[R]=!0),i("processing","calling-tools"),await e?.(h.tool_calls,{...m,currentMessage:h});let d=h.tool_calls.map(async y=>{let S=Math.floor(Date.now()/1e3),w=Se({role:"tool",tool_call_id:y.id,content:"",metadata:{createdAt:S,updatedAt:S}});O(w);let U={...m,primaryMessage:h,toolMessage:w};A(y,U);try{let I=n(y,U),g=X(I);for await(let p of g){if(typeof p=="string")w.content+=p;else{let M={};try{M=JSON.parse(w.content||"{}")}catch(P){console.warn(P)}w.content=JSON.stringify(L(M,p))}w.metadata.updatedAt=Math.floor(Date.now()/1e3)}b(y,{...U,status:"success"})}catch(I){let g=I instanceof Error?I:new Error(String(I));if(E.aborted){b(y,{...U,status:"cancelled",error:g});return}console.error(I),w.content.length===0&&(w.content=c),b(y,{...U,status:"failed",error:g})}});return await Promise.all(d),l(),v.onAfterRequest?.(m)},onCompletionChunk:m=>{var T,O,E;let{currentMessage:h}=m;if(Array.isArray(h.tool_calls))for(let i of h.tool_calls)h.state?.toolCall?.[i.id]?.status||(h.state??(h.state={}),(T=h.state).toolCall??(T.toolCall={}),(O=h.state.toolCall)[E=i.id]??(O[E]={}));return v.onCompletionChunk?.(m)}}};var De=o=>{let t=[];for(let e of o){if(e.name){let n=t.findIndex(s=>s.name===e.name);n!==-1&&t.splice(n,1)}t.push(e)}return t},re=o=>{let{initialMessages:t=[],requestMessageFields:e=[],requestMessageFieldsExclude:n=["state","metadata","loading"],plugins:s=[],onCompletionChunk:r}=o,a=Q("idle"),c=Q(void 0),u=Q(t),f=Q(o.responseProvider),v=null,R=[],x={},A=[ae(),le(),ie()],b=De(A.concat(s)),m=Ie(()=>a.value==="processing"),h=async g=>{if(!g||!g.trim()){console.warn("Cannot send empty message");return}if(m.value){console.warn("Cannot send message while processing is in progress");return}let p=Math.floor(Date.now()/1e3);u.value.push({role:"user",content:g.trim(),metadata:{createdAt:p,updatedAt:p}}),R.push(u.value[u.value.length-1]),await S()},T=async(...g)=>{if(m.value){console.warn("Cannot send message while processing is in progress");return}u.value.push(...g),R.push(...g),await S()},O=g=>{let p=g;return e.length&&(p=p.map(M=>ge(M,e))),n.length&&(p=p.map(M=>pe(M,n))),p},E=(g,p)=>{a.value=g,g==="processing"?c.value=p||"requesting":c.value=void 0},i=g=>{Object.assign(x,g)},l=g=>({messages:u.value,currentTurn:R,requestState:a.value,processingState:c.value,plugins:b,abortSignal:g,setRequestState:E,customContext:x,setCustomContext:i}),d=(g,p)=>typeof g.disabled=="function"?g.disabled(p):!!g.disabled,y=async(g,p)=>{E("processing","requesting");let M=new Proxy({messages:O(u.value)},{set(D,k,B){return k==="messages"?(D.messages=O(B),!0):(D[k]=B,!0)}}),P=l(p);for(let D of b.filter(k=>!d(k,P)))await D.onBeforeRequest?.({...P,requestBody:M});let C=ke({role:"",content:"",loading:!0});I(C);let _,Y=g(M,p),q=X(Y);for await(let D of q){E("processing","completing"),C.loading&&(C.loading=void 0);let k=D.choices?.find(F=>F.index===0);if(k){_=k;let F=()=>{C.metadata||(C.metadata={});let{created:W,...ye}=D;C.metadata.createdAt=W,C.metadata.updatedAt=Math.floor(Date.now()/1e3),Object.assign(C.metadata,ye),L(C,k.message||k.delta)};if(r){let W=l(p);r({...W,chunk:D,choice:k,currentMessage:C},F)}else F()}let B=l(p);for(let F of b.filter(W=>!d(W,B)))F.onCompletionChunk?.({...B,abortSignal:p,chunk:D,choice:k,currentMessage:C})}await U(C,g,p,_)},S=async()=>{let g=new AbortController;v=g,x={};try{E("processing","requesting");let p=l(g.signal);for(let C of b.filter(_=>!d(_,p)))await C.onTurnStart?.(p);let M=f.value;try{await y(M,g.signal),E("completed")}catch(C){if(g.signal.aborted||C instanceof j||C instanceof Error&&C.name==="AbortError")E("aborted");else throw C}let P=l(g.signal);for(let C of b.filter(_=>!d(_,P)))await C.onTurnEnd?.(P)}catch(p){E("error");let M=!1,P=l(g.signal);for(let C of b.filter(_=>!d(_,P)))C.onError&&(M=!0,C.onError({...P,error:p}));if(!M)throw p}finally{let p=l(g.signal);for(let M of b.filter(P=>!d(P,p)))try{M.onFinally?.(p)}catch(P){console.error(`Error in onFinally hook for plugin ${M.name||"Anonymous"}:`,P)}v=null,R.slice(-1)[0]&&(R.slice(-1)[0].loading=void 0),R=[]}},w=async()=>{v?.abort(),m.value&&await new Promise(g=>{let p=_e(m,M=>{M||(p(),g())},{immediate:!0})})},U=async(g,p,M,P)=>{let C=!1,_=l(M),Y=b.filter(q=>!d(q,_)).map(q=>{if(!q.onAfterRequest)return null;let D=B=>{I(B)},k=()=>{C=!0};return q.onAfterRequest({..._,currentMessage:g,lastChoice:P,appendMessage:D,requestNext:k})}).filter(q=>q!==null);await de(Promise.all(Y),M),C&&await y(p,M)},I=g=>{let p=Array.isArray(g)?g:[g];u.value.push(...p),R.push(...p)};return{requestState:a,processingState:c,messages:u,responseProvider:f,isProcessing:m,sendMessage:h,send:T,abortRequest:w}};import{isRef as Ue,toValue as qe}from"vue";function me(o,t=200,e=!1,n=!0,s=!1){return Be(Ne(t,e,n,s),o)}function Be(o,t){function e(...n){return new Promise((s,r)=>{Promise.resolve(o(()=>t.apply(this,n),{fn:t,thisArg:this,args:n})).then(s).catch(r)})}return e}var fe=()=>{};function Ne(...o){let t=0,e,n=!0,s=fe,r,a,c,u,f;!Ue(o[0])&&typeof o[0]=="object"?{delay:a,trailing:c=!0,leading:u=!0,rejectOnCancel:f=!1}=o[0]:[a,c=!0,u=!0,f=!1]=o;let v=()=>{e&&(clearTimeout(e),e=void 0,s(),s=fe)};return x=>{let A=qe(a),b=Date.now()-t,m=()=>r=x();return v(),A<=0?(t=Date.now(),m()):(b>A?(t=Date.now(),(u||!n)&&m()):c&&(r=new Promise((h,T)=>{s=f?T:h,e=setTimeout(()=>{t=Date.now(),n=!0,h(m()),v()},Math.max(0,A-b))})),!u&&!e&&(e=setTimeout(()=>n=!0,A)),n=!1,r)}}var It=o=>{let t=o.storage||ne(),e=he([]),n=new Map,s=new Map,r=he(null),a=Fe(()=>{let i=r.value;if(!i)return null;let l=e.value.find(y=>y.id===i);if(!l)return null;let d=n.get(i);return d?{...l,engine:d}:null}),c=i=>{if(!t?.saveMessages)return;let l=i||r.value,d=e.value.find(S=>S.id===l);if(!d)return;d.updatedAt=Date.now(),t?.saveConversation?.(d);let y=n.get(d.id);y&&t.saveMessages(d.id,y.messages.value)},u=(i,l)=>{if(!o.autoSaveMessages||!t?.saveMessages)return;let d=s.get(i);d&&d();let y=o.autoSaveThrottle??1e3,S=me(()=>{c(i)},y,!0,!0),w=Ke(l.messages,S,{deep:!0});s.set(i,w)},f=i=>{let l=s.get(i);l&&(l(),s.delete(i))};t?.loadConversations&&Promise.resolve(t.loadConversations()).then(i=>{if(!i?.length)return;if(e.value.length===0){e.value=i;return}let l=new Map(e.value.map(d=>[d.id,d]));i.forEach(d=>{l.has(d.id)||l.set(d.id,d)}),e.value=Array.from(l.values())}).catch(i=>{console.error("[useConversation] loadConversations failed:",i)});let v=async(i,l)=>{let d=n.get(i);if(d)return d;let y=l?.initialMessages??o.useMessageOptions.initialMessages??[];if(t?.loadMessages)try{y=await t.loadMessages(i)}catch(w){console.error("[useConversation] loadMessages failed:",w)}let S=re({...o.useMessageOptions,...l,initialMessages:y});return n.set(i,S),u(i,S),S};function R(){return Date.now().toString(36)+Math.random().toString(36).substring(2,9)}let x=i=>{let{id:l=R(),title:d,metadata:y,useMessageOptions:S}=i||{},w=Date.now(),U={id:l,title:d,createdAt:w,updatedAt:w,metadata:y};e.value.unshift(U);let I=re({...o.useMessageOptions,...S});return n.set(l,I),u(l,I),t?.saveConversation?.(U),t?.saveMessages?.(l,I.messages.value),r.value=l,a.value},A=i=>{let{excludeId:l}=i||{};n.forEach((d,y)=>{if(l&&y===l)return;d.isProcessing?.value||(f(y),n.delete(y))})};return{conversations:e,activeConversationId:r,activeConversation:a,createConversation:x,switchConversation:async i=>i?r.value===i?a.value:e.value.find(d=>d.id===i)?(await v(i),A({excludeId:i}),r.value=i,a.value):null:null,deleteConversation:async i=>{let l=e.value.findIndex(y=>y.id===i);if(l===-1)return;await n.get(i)?.abortRequest(),f(i),n.delete(i),e.value.splice(l,1),t?.deleteConversation?.(i),r.value===i&&(r.value=null,A())},clear:()=>{e.value.map(l=>l.id).forEach(l=>{t?.deleteConversation?.(l)}),n.forEach(l=>{l.abortRequest()}),s.forEach(l=>{l()}),e.value=[],n.clear(),s.clear(),r.value=null},updateConversationTitle:(i,l)=>{let d=e.value.find(y=>y.id===i);d&&(d.title=l,d.updatedAt=Date.now(),t?.saveConversation?.(d))},saveMessages:c,sendMessage:i=>{a.value?.engine.sendMessage(i)},abortActiveRequest:async()=>{await a.value?.engine.abortRequest()}}};export{oe as AIClient,H as BaseModelProvider,Ee as EXCLUDE_MODE_REMOVE,Ce as ErrorType,J as IndexedDBStrategy,$ as LocalStorageStrategy,K as OpenAIProvider,ve as StreamEventType,be as extractTextFromResponse,ae as fallbackRolePlugin,Me as formatMessages,te as handleSSEStream,we as indexedDBStorageStrategyFactory,ie as lengthPlugin,ne as localStorageStrategyFactory,Re as sseStreamToGenerator,le as thinkingPlugin,yt as toolPlugin,It as useConversation,re 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.7",
3
+ "version": "0.4.0-beta.0",
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": "4e9681b79eceedc0b1c8420ac840acf14b200a9e"
32
+ "gitHead": "d33078290102b05d2fde9516b188cf1a5d3801c6"
33
33
  }