@opentiny/tiny-robot-kit 0.4.0-beta.0 → 0.4.1-alpha.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/dist/index.d.ts CHANGED
@@ -1,216 +1,7 @@
1
+ import { a as AIModelConfig, c as ChatCompletionRequest, d as ChatCompletionResponse, o as StreamHandler, B as BaseModelProvider, l as ChatMessage, M as MaybePromise, T as ToolCall } from './types-CePh-Jcx.js';
2
+ export { A as AIAdapterError, b as AIProvider, C as ChatCompletionOptions, e as ChatCompletionResponseChoice, f as ChatCompletionResponseMessage, g as ChatCompletionResponseUsage, h as ChatCompletionStreamResponse, i as ChatCompletionStreamResponseChoice, j as ChatCompletionStreamResponseDelta, k as ChatHistory, E as ErrorType, m as MessageMetadata, n as MessageRole, S as StreamEventType } from './types-CePh-Jcx.js';
1
3
  import { Ref, ComputedRef } from 'vue';
2
4
 
3
- /**
4
- * 模型Provider基类
5
- */
6
- declare abstract class BaseModelProvider {
7
- protected config: AIModelConfig;
8
- /**
9
- * @param config AI模型配置
10
- */
11
- constructor(config: AIModelConfig);
12
- /**
13
- * 发送聊天请求并获取响应
14
- * @param request 聊天请求参数
15
- * @returns 聊天响应
16
- */
17
- abstract chat(request: ChatCompletionRequest): Promise<ChatCompletionResponse>;
18
- /**
19
- * 发送流式聊天请求并通过处理器处理响应
20
- * @param request 聊天请求参数
21
- * @param handler 流式响应处理器
22
- */
23
- abstract chatStream(request: ChatCompletionRequest, handler: StreamHandler): Promise<void>;
24
- /**
25
- * 更新配置
26
- * @param config 新的AI模型配置
27
- */
28
- updateConfig(config: AIModelConfig): void;
29
- /**
30
- * 获取当前配置
31
- * @returns AI模型配置
32
- */
33
- getConfig(): AIModelConfig;
34
- /**
35
- * 验证请求参数
36
- * @param request 聊天请求参数
37
- */
38
- protected validateRequest(request: ChatCompletionRequest): void;
39
- }
40
-
41
- type MaybePromise<T> = T | Promise<T>;
42
- /**
43
- * 消息角色类型
44
- */
45
- type MessageRole = 'system' | 'user' | 'assistant';
46
- interface ToolCall {
47
- index: number;
48
- id: string;
49
- type: 'function';
50
- function: {
51
- name: string;
52
- arguments: string;
53
- result?: string;
54
- };
55
- }
56
- interface MessageMetadata {
57
- createdAt?: number;
58
- updatedAt?: number;
59
- id?: string;
60
- model?: string;
61
- [key: string]: any;
62
- }
63
- /**
64
- * 聊天消息接口
65
- */
66
- interface ChatMessage {
67
- role: string;
68
- content: string;
69
- reasoning_content?: string;
70
- metadata?: MessageMetadata;
71
- tool_calls?: ToolCall[];
72
- tool_call_id?: string;
73
- [key: string]: any;
74
- [key: symbol]: any;
75
- }
76
- /**
77
- * 聊天历史记录
78
- */
79
- type ChatHistory = ChatMessage[];
80
- /**
81
- * 聊天完成请求选项
82
- */
83
- interface ChatCompletionOptions {
84
- model?: string;
85
- temperature?: number;
86
- top_p?: number;
87
- n?: number;
88
- stream?: boolean;
89
- max_tokens?: number;
90
- signal?: AbortSignal;
91
- }
92
- /**
93
- * 聊天完成请求参数
94
- */
95
- interface ChatCompletionRequest {
96
- messages: ChatMessage[];
97
- options?: ChatCompletionOptions;
98
- }
99
- /**
100
- * 聊天完成响应消息
101
- */
102
- interface ChatCompletionResponseMessage {
103
- role: MessageRole;
104
- content: string;
105
- [x: string]: unknown;
106
- }
107
- /**
108
- * 聊天完成响应选择
109
- */
110
- interface ChatCompletionResponseChoice {
111
- index: number;
112
- message: ChatCompletionResponseMessage;
113
- finish_reason: string;
114
- }
115
- /**
116
- * 聊天完成响应使用情况
117
- */
118
- interface ChatCompletionResponseUsage {
119
- prompt_tokens: number;
120
- completion_tokens: number;
121
- total_tokens: number;
122
- }
123
- /**
124
- * 聊天完成响应
125
- */
126
- interface ChatCompletionResponse {
127
- id: string;
128
- object: string;
129
- created: number;
130
- model: string;
131
- choices: ChatCompletionResponseChoice[];
132
- usage: ChatCompletionResponseUsage;
133
- }
134
- /**
135
- * 流式聊天完成响应增量
136
- */
137
- interface ChatCompletionStreamResponseDelta {
138
- content?: string;
139
- role?: MessageRole;
140
- [x: string]: unknown;
141
- }
142
- /**
143
- * 流式聊天完成响应选择
144
- */
145
- interface ChatCompletionStreamResponseChoice {
146
- index: number;
147
- delta: ChatCompletionStreamResponseDelta;
148
- finish_reason: string | null;
149
- }
150
- /**
151
- * 流式聊天完成响应
152
- */
153
- interface ChatCompletionStreamResponse {
154
- id: string;
155
- object: string;
156
- created: number;
157
- model: string;
158
- choices: ChatCompletionStreamResponseChoice[];
159
- }
160
- /**
161
- * AI模型提供商类型
162
- */
163
- type AIProvider = 'openai' | 'deepseek' | 'custom';
164
- /**
165
- * AI模型配置接口
166
- */
167
- interface AIModelConfig {
168
- provider: AIProvider;
169
- providerImplementation?: BaseModelProvider;
170
- apiKey?: string;
171
- apiUrl?: string;
172
- apiVersion?: string;
173
- defaultModel?: string;
174
- defaultOptions?: ChatCompletionOptions;
175
- }
176
- /**
177
- * 错误类型
178
- */
179
- declare enum ErrorType {
180
- NETWORK_ERROR = "network_error",
181
- AUTHENTICATION_ERROR = "authentication_error",
182
- RATE_LIMIT_ERROR = "rate_limit_error",
183
- SERVER_ERROR = "server_error",
184
- MODEL_ERROR = "model_error",
185
- TIMEOUT_ERROR = "timeout_error",
186
- UNKNOWN_ERROR = "unknown_error"
187
- }
188
- /**
189
- * AI适配器错误
190
- */
191
- interface AIAdapterError {
192
- type: ErrorType;
193
- message: string;
194
- statusCode?: number;
195
- originalError?: object;
196
- }
197
- /**
198
- * 流式响应事件类型
199
- */
200
- declare enum StreamEventType {
201
- DATA = "data",
202
- ERROR = "error",
203
- DONE = "done"
204
- }
205
- /**
206
- * 流式响应处理器
207
- */
208
- interface StreamHandler {
209
- onData: (data: ChatCompletionStreamResponse) => void;
210
- onError: (error: AIAdapterError) => void;
211
- onDone: (finishReason?: string) => void;
212
- }
213
-
214
5
  /**
215
6
  * AI客户端类
216
7
  * 负责根据配置选择合适的提供商并处理请求
@@ -294,11 +85,12 @@ interface Tool {
294
85
  type: 'function';
295
86
  function: {
296
87
  name: string;
297
- description: string;
88
+ description?: string;
298
89
  /**
299
90
  * function 的输入参数,以 JSON Schema 对象描述
300
91
  */
301
- parameters: any;
92
+ parameters?: any;
93
+ inputSchema?: any;
302
94
  };
303
95
  [key: string]: any;
304
96
  }
@@ -352,6 +144,7 @@ interface ChatCompletion {
352
144
  choices: CompletionChoice[];
353
145
  usage?: Usage;
354
146
  }
147
+ type ResponseProvider<T = ChatCompletion> = (requestBody: MessageRequestBody, abortSignal: AbortSignal) => Promise<T> | AsyncGenerator<T> | Promise<AsyncGenerator<T>>;
355
148
  interface UseMessageOptions {
356
149
  initialMessages?: ChatMessage[];
357
150
  /**
@@ -365,7 +158,7 @@ interface UseMessageOptions {
365
158
  */
366
159
  requestMessageFieldsExclude?: string[];
367
160
  plugins?: UseMessagePlugin[];
368
- responseProvider: <T = ChatCompletion>(requestBody: MessageRequestBody, abortSignal: AbortSignal) => Promise<T> | AsyncGenerator<T> | Promise<AsyncGenerator<T>>;
161
+ responseProvider: ResponseProvider;
369
162
  /**
370
163
  * 全局的数据块处理钩子,在接收到每个响应数据块时触发。
371
164
  * 注意:此钩子与插件中的 onCompletionChunk 有区别。
@@ -501,6 +294,11 @@ interface UseConversationOptions {
501
294
  * When provided, conversation list and messages can be loaded and persisted.
502
295
  */
503
296
  storage?: ConversationStorageStrategy;
297
+ /**
298
+ * Called when the initial conversation list has been loaded from storage.
299
+ * Only fired when storage.loadConversations is available and has completed.
300
+ */
301
+ onLoad?: (conversations: ConversationInfo[]) => void;
504
302
  }
505
303
  interface UseConversationReturn {
506
304
  conversations: Ref<ConversationInfo[]>;
@@ -658,21 +456,30 @@ declare function sseStreamToGenerator<T = any>(response: Response, options?: {
658
456
 
659
457
  declare const useConversation: (options: UseConversationOptions) => UseConversationReturn;
660
458
 
661
- declare const fallbackRolePlugin: (options?: UseMessagePlugin & {
662
- fallbackRole?: string;
663
- }) => UseMessagePlugin;
664
-
665
459
  declare const lengthPlugin: (options?: UseMessagePlugin & {
666
460
  continueContent?: string;
667
461
  }) => UseMessagePlugin;
668
462
 
669
463
  declare const thinkingPlugin: (options?: UseMessagePlugin) => UseMessagePlugin;
670
464
 
671
- /**
672
- * 消息排除模式:从 messages 数组中直接移除消息。
673
- * 使用此模式时,消息会被完全从数组中移除,不会保留在 messages 中。
674
- */
675
- declare const EXCLUDE_MODE_REMOVE: "remove";
465
+ interface UseMessageToolActionContext extends BasePluginContext {
466
+ assistantMessage: ChatMessage;
467
+ /**
468
+ * @deprecated use `assistantMessage` instead
469
+ */
470
+ currentMessage: ChatMessage;
471
+ }
472
+ interface UseMessageCallToolContext extends UseMessageToolActionContext {
473
+ toolMessage: ChatMessage;
474
+ }
475
+ interface UseMessageToolCallContext extends BasePluginContext {
476
+ assistantMessage: ChatMessage;
477
+ /**
478
+ * @deprecated use `assistantMessage` instead
479
+ */
480
+ primaryMessage: ChatMessage;
481
+ toolMessage: ChatMessage;
482
+ }
676
483
  declare const toolPlugin: (options: UseMessagePlugin & {
677
484
  /**
678
485
  * 获取工具列表的函数。
@@ -681,25 +488,18 @@ declare const toolPlugin: (options: UseMessagePlugin & {
681
488
  /**
682
489
  * 在处理包含 tool_calls 的响应前调用。
683
490
  */
684
- beforeCallTools?: (toolCalls: ToolCall[], context: BasePluginContext & {
685
- currentMessage: ChatMessage;
686
- }) => Promise<void>;
491
+ beforeCallTools?: (toolCalls: ToolCall[], context: UseMessageToolActionContext) => Promise<void>;
687
492
  /**
688
493
  * 执行单个工具调用并返回其文本结果的函数。
689
494
  */
690
- callTool: (toolCall: ToolCall, context: BasePluginContext & {
691
- currentMessage: ChatMessage;
692
- }) => Promise<string | Record<string, any>> | AsyncGenerator<string | Record<string, any>>;
495
+ callTool: (toolCall: ToolCall, context: UseMessageCallToolContext) => Promise<string | Record<string, any>> | AsyncGenerator<string | Record<string, any>>;
693
496
  /**
694
497
  * 工具调用开始时的回调函数。
695
498
  * 触发时机:工具消息已创建并追加后,调用 callTool 之前触发。
696
499
  * @param toolCall - 工具调用对象
697
500
  * @param context - 插件上下文,包含当前工具消息
698
501
  */
699
- onToolCallStart?: (toolCall: ToolCall, context: BasePluginContext & {
700
- primaryMessage: ChatMessage;
701
- toolMessage: ChatMessage;
702
- }) => void;
502
+ onToolCallStart?: (toolCall: ToolCall, context: UseMessageToolCallContext) => void;
703
503
  /**
704
504
  * 工具调用结束时的回调函数。
705
505
  * 触发时机:工具调用完成(成功、失败或取消)时触发。
@@ -708,9 +508,7 @@ declare const toolPlugin: (options: UseMessagePlugin & {
708
508
  * @param context.status - 工具调用状态:'success' | 'failed' | 'cancelled'
709
509
  * @param context.error - 当状态为 'failed' 或 'cancelled' 时,可能包含错误信息
710
510
  */
711
- onToolCallEnd?: (toolCall: ToolCall, context: BasePluginContext & {
712
- primaryMessage: ChatMessage;
713
- toolMessage: ChatMessage;
511
+ onToolCallEnd?: (toolCall: ToolCall, context: UseMessageToolCallContext & {
714
512
  status: "success" | "failed" | "cancelled";
715
513
  error?: Error;
716
514
  }) => void;
@@ -723,20 +521,13 @@ declare const toolPlugin: (options: UseMessagePlugin & {
723
521
  */
724
522
  toolCallFailedContent?: string;
725
523
  /**
726
- * 是否在请求被中止时自动补充缺失的 tool 消息。
524
+ * 是否在请求前自动补充缺失的 tool 消息。
727
525
  * 当 assistant 响应了 tool_calls 但未追加对应的 tool 消息时,
728
526
  * 插件将自动补充"工具调用已取消"的 tool 消息。默认:false。
729
527
  */
730
528
  autoFillMissingToolMessages?: boolean;
731
- /**
732
- * 是否在下一轮对话中,排除包含 tool_calls 的 assistant 消息和对应的 tool 消息,只保留结果。
733
- * - 当为 `true` 时,这些消息会被标记为不发送,不会包含在下一次请求的 messages 中。
734
- * - 当为 `'remove'` 时,这些消息会直接从 messages 数组中移除。
735
- * 默认:false。
736
- */
737
- excludeToolMessagesNextTurn?: boolean | typeof EXCLUDE_MODE_REMOVE;
738
529
  }) => UseMessagePlugin;
739
530
 
740
531
  declare const useMessage: (options: UseMessageOptions) => UseMessageReturn;
741
532
 
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 };
533
+ export { AIClient, AIModelConfig, BaseModelProvider, type BasePluginContext, type ChatCompletion, ChatCompletionRequest, ChatCompletionResponse, ChatMessage, type Choice, type CompletionChoice, type Conversation, type ConversationInfo, type ConversationStorageStrategy, type DeltaChoice, type IndexedDBConfig, IndexedDBStrategy, type LocalStorageConfig, LocalStorageStrategy, MaybePromise, type MessageRequestBody, OpenAIProvider, type RequestProcessingState, type RequestState, type ResponseProvider, StreamHandler, type Tool, ToolCall, type Usage, type UseConversationOptions, type UseConversationReturn, type UseMessageCallToolContext, type UseMessageOptions, type UseMessagePlugin, type UseMessageReturn, type UseMessageToolActionContext, type UseMessageToolCallContext, extractTextFromResponse, formatMessages, handleSSEStream, indexedDBStorageStrategyFactory, lengthPlugin, localStorageStrategyFactory, sseStreamToGenerator, thinkingPlugin, toolPlugin, useConversation, useMessage };
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
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(`
1
+ "use strict";var ge=Object.defineProperty;var Ne=Object.getOwnPropertyDescriptor;var je=Object.getOwnPropertyNames;var Ke=Object.prototype.hasOwnProperty;var Ve=(s,e)=>{for(var t in e)ge(s,t,{get:e[t],enumerable:!0})},We=(s,e,t,o)=>{if(e&&typeof e=="object"||typeof e=="function")for(let n of je(e))!Ke.call(s,n)&&n!==t&&ge(s,n,{get:()=>e[n],enumerable:!(o=Ne(e,n))||o.enumerable});return s};var He=s=>We(ge({},"__esModule",{value:!0}),s);var st={};Ve(st,{AIClient:()=>ae,BaseModelProvider:()=>z,ErrorType:()=>ve,IndexedDBStrategy:()=>J,LocalStorageStrategy:()=>$,OpenAIProvider:()=>W,StreamEventType:()=>Re,extractTextFromResponse:()=>xe,formatMessages:()=>be,handleSSEStream:()=>re,indexedDBStorageStrategyFactory:()=>Ae,lengthPlugin:()=>Ze,localStorageStrategyFactory:()=>le,sseStreamToGenerator:()=>Pe,thinkingPlugin:()=>et,toolPlugin:()=>tt,useConversation:()=>Ye,useMessage:()=>ce});module.exports=He(st);var z=class{constructor(e){this.config=e}updateConfig(e){this.config={...this.config,...e}}getConfig(){return{...this.config}}validateRequest(e){if(!e.messages||!Array.isArray(e.messages)||e.messages.length===0)throw new Error("\u8BF7\u6C42\u5FC5\u987B\u5305\u542B\u81F3\u5C11\u4E00\u6761\u6D88\u606F");for(let t of e.messages)if(!t.role||!t.content)throw new Error("\u6BCF\u6761\u6D88\u606F\u5FC5\u987B\u5305\u542B\u89D2\u8272\u548C\u5185\u5BB9")}};var ve=(u=>(u.NETWORK_ERROR="network_error",u.AUTHENTICATION_ERROR="authentication_error",u.RATE_LIMIT_ERROR="rate_limit_error",u.SERVER_ERROR="server_error",u.MODEL_ERROR="model_error",u.TIMEOUT_ERROR="timeout_error",u.UNKNOWN_ERROR="unknown_error",u))(ve||{}),Re=(o=>(o.DATA="data",o.ERROR="error",o.DONE="done",o))(Re||{});function V(s){return{type:s.type||"unknown_error",message:s.message||"\u672A\u77E5\u9519\u8BEF",statusCode:s.statusCode,originalError:s.originalError}}function pe(s){if(!s.response)return V({type:"network_error",message:"\u7F51\u7EDC\u8FDE\u63A5\u9519\u8BEF\uFF0C\u8BF7\u68C0\u67E5\u60A8\u7684\u7F51\u7EDC\u8FDE\u63A5",originalError:s});if(s.response){let{status:e,data:t}=s.response;return e===401||e===403?V({type:"authentication_error",message:"\u8EAB\u4EFD\u9A8C\u8BC1\u5931\u8D25\uFF0C\u8BF7\u68C0\u67E5\u60A8\u7684API\u5BC6\u94A5",statusCode:e,originalError:s}):e===429?V({type:"rate_limit_error",message:"\u8D85\u51FAAPI\u8C03\u7528\u9650\u5236\uFF0C\u8BF7\u7A0D\u540E\u518D\u8BD5",statusCode:e,originalError:s}):e>=500?V({type:"server_error",message:"\u670D\u52A1\u5668\u9519\u8BEF\uFF0C\u8BF7\u7A0D\u540E\u518D\u8BD5",statusCode:e,originalError:s}):V({type:"unknown_error",message:t?.error?.message||`\u8BF7\u6C42\u5931\u8D25\uFF0C\u72B6\u6001\u7801: ${e}`,statusCode:e,originalError:s})}return s.code==="ECONNABORTED"?V({type:"timeout_error",message:"\u8BF7\u6C42\u8D85\u65F6\uFF0C\u8BF7\u7A0D\u540E\u518D\u8BD5",originalError:s}):V({type:"unknown_error",message:s.message||"\u53D1\u751F\u672A\u77E5\u9519\u8BEF",originalError:s})}async function re(s,e,t){let o=s.body?.getReader();if(!o)throw new Error("Response body is null");let n=new TextDecoder,r="",a,u;t&&t.addEventListener("abort",()=>{o.cancel().catch(d=>console.error("Error cancelling reader:",d))},{once:!0});try{for(;;){if(t?.aborted){await o.cancel();break}let{done:d,value:i}=await o.read();if(d)break;let g=n.decode(i,{stream:!0});r+=g;let b=r.split(`
2
2
 
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});
3
+ `);r=b.pop()||"";for(let y of b)if(y.trim()!==""){if(y.trim()==="data: [DONE]"){u&&(a=u),e.onDone(a);continue}try{let c=y.match(/^data: (.+)$/m);if(!c)continue;let l=JSON.parse(c[1]);e.onData(l),u=l.choices?.[0]?.finish_reason||void 0}catch(c){console.error("Error parsing SSE message:",c)}}}(r.trim()==="data: [DONE]"||t?.aborted)&&(t?.aborted&&(a="aborted"),e.onDone(a))}catch(d){if(t?.aborted)return;throw d}}function be(s){return s.map(e=>typeof e=="object"&&"role"in e&&"content"in e?{role:e.role,content:String(e.content),...e.name?{name:e.name}:{}}:typeof e=="string"?{role:"user",content:e}:{role:"user",content:String(e)})}function xe(s){return!s.choices||!s.choices.length?"":s.choices[0].message?.content||""}function de(s="The operation was aborted"){let e=new Error(s);return e.name="AbortError",e}async function*Pe(s,e={}){let t=s.body?.getReader();if(!t)throw new Error("ReadableStream not supported");let{signal:o}=e,n=new TextDecoder,r="",a=()=>{t.cancel()};o?.addEventListener("abort",a);try{for(;;){if(o?.aborted)throw de();let u;try{u=await t.read()}catch(y){throw o?.aborted?de():y}let{done:d,value:i}=u;if(d){if(o?.aborted)throw de();return}let g=n.decode(i,{stream:!0});r+=g;let b=r.split(`
4
+ `);r=b.pop()||"";for(let y of b)if(y.trim()!==""&&y.startsWith("data: ")){let c=y.slice(6);if(c==="[DONE]")return;try{yield JSON.parse(c)}catch(l){console.warn("Failed to parse SSE data:",c,l)}}}}finally{o?.removeEventListener("abort",a),t.releaseLock()}}var W=class extends z{constructor(t){super(t);this.defaultModel="gpt-3.5-turbo";this.baseURL=t.apiUrl||"https://api.openai.com/v1",this.apiKey=t.apiKey||"",t.defaultModel&&(this.defaultModel=t.defaultModel),this.apiKey||console.warn("API key is not provided. Authentication will likely fail.")}async chat(t){try{this.validateRequest(t);let o={model:t.options?.model||this.config.defaultModel||this.defaultModel,messages:t.messages,...t.options,stream:!1},n={method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(o)};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(o){throw pe(o)}}async chatStream(t,o){let{signal:n,...r}=t.options||{};try{this.validateRequest(t);let a={model:t.options?.model||this.config.defaultModel||this.defaultModel,messages:t.messages,...r,stream:!0},u={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(u.headers,{Authorization:`Bearer ${this.apiKey}`});let d=await fetch(`${this.baseURL}/chat/completions`,u);if(!d.ok){let i=await d.text();throw new Error(`HTTP error! status: ${d.status}, details: ${i}`)}await re(d,o,n)}catch(a){if(n?.aborted)return;o.onError(pe(a))}}updateConfig(t){super.updateConfig(t),t.apiUrl&&(this.baseURL=t.apiUrl),t.apiKey&&(this.apiKey=t.apiKey),t.defaultModel&&(this.defaultModel=t.defaultModel)}};var ae=class{constructor(e){this.config=e,this.provider=this.createProvider(e)}createProvider(e){if(e.provider==="custom"&&"providerImplementation"in e)return e.providerImplementation;if(e.provider==="deepseek"){let t={defaultModel:"deepseek-chat",apiUrl:"https://api.deepseek.com/v1"};return new W({...t,...e})}else return new W(e)}async chat(e){return this.provider.chat(e)}async chatStream(e,t){let o={...e,options:{...e.options,stream:!0}};return this.provider.chatStream(o,t)}getConfig(){return{...this.config}}updateConfig(e){this.config={...this.config,...e},e.provider&&e.provider!==this.config.provider?this.provider=this.createProvider(this.config):this.provider.updateConfig(this.config)}};var Se=require("vue");function ee(s,e=new WeakMap){if(s==null||typeof s!="object")return s;try{let t=(0,Se.toRaw)(s);if(e.has(t))return e.get(t);if(Array.isArray(t)){let n=[];return e.set(t,n),n.push(...t.map(r=>ee(r,e))),n}if(t instanceof Date||t instanceof RegExp||t instanceof ArrayBuffer||t instanceof Blob)return t;let o={};e.set(t,o);for(let n of Object.keys(t)){let r=Object.getOwnPropertyDescriptor(t,n);if(!r||r.get||r.set)continue;let a=t[n];typeof a!="function"&&typeof a!="symbol"&&(o[n]=ee(a,e))}return o}catch(t){return console.warn("unwrapProxy error:",t),Array.isArray(s)?[]:{}}}var ie=s=>s.map(e=>{let{renderContent:t,...o}=e;if(!Array.isArray(t))return e;let n=t.filter(a=>a.type==="collapsible-text"),r=t.filter(a=>a.type==="markdown"||a.type==="text");return n.length>0&&(o.reasoning_content=n.map(a=>a.content).join("")),r.length>0&&(o.content=r.map(a=>a.content).join("")),o});var te=s=>{let e=localStorage.getItem(s);return e?JSON.parse(e):[]},$=class{constructor(e="tiny-robot-ai-conversations"){this.storageKey=e}saveConversation(e){try{let t=te(this.storageKey),o=t.findIndex(n=>n.id===e.id);o!==-1?Object.assign(t[o],e):t.unshift({...e,messages:[]}),localStorage.setItem(this.storageKey,JSON.stringify(t))}catch(t){console.error("\u4FDD\u5B58\u4F1A\u8BDD\u5931\u8D25:",t)}}loadConversations(){try{return te(this.storageKey).map(t=>({id:t.id,title:t.title,createdAt:t.createdAt,updatedAt:t.updatedAt,metadata:t.metadata}))}catch(e){return console.error("\u52A0\u8F7D\u4F1A\u8BDD\u5931\u8D25:",e),[]}}saveMessages(e,t){try{let o=te(this.storageKey),n=o.findIndex(r=>r.id===e);n!==-1&&(o[n].messages=t),localStorage.setItem(this.storageKey,JSON.stringify(o))}catch(o){console.error("\u4FDD\u5B58\u4F1A\u8BDD\u6D88\u606F\u5931\u8D25:",o)}}loadMessages(e){try{let o=te(this.storageKey).find(r=>r.id===e);return ie(o?.messages||[])}catch(t){return console.error("\u52A0\u8F7D\u4F1A\u8BDD\u6D88\u606F\u5931\u8D25:",t),[]}}deleteConversation(e){let t=te(this.storageKey),o=t.findIndex(n=>n.id===e);o!==-1&&t.splice(o,1),localStorage.setItem(this.storageKey,JSON.stringify(t))}};var Te=require("idb");var J=class{constructor(e="tiny-robot-ai-db",t=3){this.db=null;this.dbName=e,this.dbVersion=t}async getDB(){return this.db||(this.db=await(0,Te.openDB)(this.dbName,this.dbVersion,{upgrade(e){e.objectStoreNames.contains("conversations")||e.createObjectStore("conversations",{keyPath:"id"}).createIndex("by-updated","updatedAt"),e.objectStoreNames.contains("messages")||e.createObjectStore("messages",{keyPath:"conversationId"})}})),this.db}async loadConversations(){try{return(await(await this.getDB()).getAllFromIndex("conversations","by-updated")).reverse()}catch(e){return console.error("\u52A0\u8F7D\u4F1A\u8BDD\u5931\u8D25:",e),[]}}async loadMessages(e){try{let o=await(await this.getDB()).get("messages",e);return o?ie(o.messages):[]}catch(t){return console.error("\u52A0\u8F7D\u4F1A\u8BDD\u6D88\u606F\u5931\u8D25:",t),[]}}async saveConversation(e){try{let t=await this.getDB(),o=ee(e);await t.put("conversations",o)}catch(t){throw console.error("\u4FDD\u5B58\u4F1A\u8BDD\u5931\u8D25:",t),t}}async saveMessages(e,t){try{let o=await this.getDB(),n=ee(t);await o.put("messages",{conversationId:e,messages:n})}catch(o){throw console.error("\u4FDD\u5B58\u4F1A\u8BDD\u6D88\u606F\u5931\u8D25:",o),o}}async deleteConversation(e){try{let t=await this.getDB();await t.delete("conversations",e),await t.delete("messages",e)}catch(t){throw console.error("\u5220\u9664\u4F1A\u8BDD\u5931\u8D25:",t),t}}};function le(s={}){return new $(s.key||"tiny-robot-ai-conversations")}function Ae(s={}){return new J(s.dbName||"tiny-robot-ai-db",s.dbVersion||1)}var L=require("vue");var K=require("vue");var Le=s=>typeof s=="function"?null:Array.isArray(s)?s.length>0?new Set(s):null:new Set([s]),we=s=>{let e=new Set,t=(r,a)=>{try{r.listener(a)}catch(u){console.error("Error in message state subscriber:",u)}};return{notify:r=>{let a=new Set(Array.isArray(r)?r:[r]),u=s(),d=Array.from(e);for(let i of d){if(i.kinds){let g=!1;for(let b of i.kinds)if(a.has(b)){g=!0;break}if(!g)continue}t(i,u)}},subscribe:(r,a)=>{let u=typeof r=="function"?r:a;if(!u)throw new Error("subscribe listener is required");let d={kinds:Le(r),listener:u};return e.add(d),t(d,s()),()=>{e.delete(d)}}}};var B=require("vue");var Ee=s=>(0,B.reactive)(s),fe=s=>{let e=(0,B.isProxy)(s)?(0,B.toRaw)(s):s;if(Array.isArray(e))return e.map(t=>fe(t));if(e&&typeof e=="object"){let t={};for(let[o,n]of Object.entries(e))t[o]=fe(n);return t}return e},ke=()=>{let s=!1,e=(0,B.ref)("idle"),t=(0,B.ref)(void 0),o=(0,B.ref)([]),n=(0,B.computed)(()=>e.value==="processing"),r=g=>{if(s)throw new Error("Message state adapter is already initialized");e.value=g.requestState,t.value=g.processingState,o.value=g.messages.map(Ee),s=!0},a=g=>Ee(g),u=()=>{if(!s)throw new Error("Message state adapter is not initialized");return{requestState:e.value,processingState:t.value,messages:fe(o.value),isProcessing:n.value}},d=we(u);return{requestState:e,processingState:t,messages:o,isProcessing:n,initialize:r,getState:u,createMessage:a,mutate:(g,b)=>{if(!s)throw new Error("Message state adapter is not initialized");let y={get requestState(){return e.value},set requestState(S){e.value=S},get processingState(){return t.value},set processingState(S){t.value=S},get messages(){return o.value},set messages(S){o.value=S.map(a)}},c=!1;if(b(y,()=>{c=!0}),c)return;(Array.isArray(g)?g:[g]).includes("messages")&&(o.value=[...o.value]),d.notify(g)},subscribe:d.subscribe}};var se=(s={})=>{let{continueContent:e="Please continue with your previous answer.",...t}=s;return{name:"length",...t,onAfterRequest:async o=>{let{lastChoice:n,appendMessage:r,requestNext:a}=o;return n?.finish_reason==="length"&&(r({role:"user",content:e}),a()),t.onAfterRequest?.(o)}}};var oe=(s={})=>{let e=(t,o)=>!!t.thinking!==o||!!t.open!==o;return{name:"thinking",...s,onCompletionChunk(t){let{choice:o,currentMessage:n,updateCurrentMessage:r}=t,a=o,u=a?.message?.reasoning_content||a?.delta?.reasoning_content,d=typeof u=="string"&&u.trim()!=="";return d?n.state&&typeof n.state=="object"?e(n.state,d)&&r(i=>{i.state.thinking=!0,i.state.open=!0}):r(i=>{i.state={thinking:d,open:d}}):n.state&&typeof n.state=="object"&&"thinking"in n.state&&e(n.state,d)&&r(i=>{i.state.thinking=!1,i.state.open=!1}),s.onCompletionChunk?.(t)},onTurnEnd(t){let{currentTurn:o,mutate:n}=t,r=o.at(-1);return r?.state&&typeof r.state=="object"&&"thinking"in r.state&&e(r.state,!1)&&n("messages",()=>{r.state.thinking=!1,r.state.open=!1}),s.onTurnEnd?.(t)}}};var Q=class extends Error{constructor(e){super(e),this.name="AbortError"}};function Ge(s){if(s.aborted)return{promise:Promise.reject(new Q(String(s.reason??"Aborted"))),cleanup:()=>{}};let e=null;return{promise:new Promise((n,r)=>{e=()=>{r(new Q(String(s.reason??"Aborted")))},s.addEventListener("abort",e,{once:!0})}),cleanup:()=>{e&&(s.removeEventListener("abort",e),e=null)}}}function qe(s,e){let{promise:t,cleanup:o}=Ge(e);return Promise.race([s,t]).finally(o)}function Be(s,e){let t={};for(let o in s)e.includes(o)&&(t[o]=s[o]);return t}function _e(s,e){let t={};for(let o in s)e.includes(o)||(t[o]=s[o]);return t}async function*Y(s){if(Ie(s)){yield*s;return}let e=await s;if(Ie(e)){yield*e;return}yield e}function Ie(s){return s&&typeof s=="object"&&typeof s[Symbol.asyncIterator]=="function"}var me=s=>typeof s=="object"&&s!==null,Oe=s=>me(s)&&typeof s.index=="number",X=(s,e)=>{for(let[t,o]of Object.entries(e)){let n=s[t];if(n)if(typeof n=="string"&&typeof o=="string")t==="type"&&n||(s[t]=n+o);else if(Array.isArray(n)&&Array.isArray(o))if(n.every(r=>Oe(r))&&o.every(r=>Oe(r))){let r=new Map(n.map(i=>[i.index,i])),a=new Map(o.map(i=>[i.index,i]));for(let[i,g]of a)if(r.has(i)){let b=r.get(i);r.set(i,X(b,g))}else r.set(i,g);let u=Math.max(...Array.from(r.keys()),-1)+1,d=u>n.length?Array.from({length:u}):n;for(let[i,g]of r)d[i]=g;s[t]=d}else s[t]=[...n,...o];else me(n)&&me(o)&&(s[t]=X(n,o));else s[t]=o}return s};function ze({messages:s,cancelledContent:e,createMessage:t,mutate:o}){let n=[];for(let r=0;r<s.length;r++){let a=s[r];if(a.role==="assistant"&&a.tool_calls&&a.tool_calls.length>0){let u=new Set(a.tool_calls.map(g=>g.id)),d=new Set;for(let g=r+1;g<s.length;g++){let b=s[g];b.role==="tool"&&b.tool_call_id&&u.has(b.tool_call_id)&&d.add(b.tool_call_id)}let i=a.tool_calls.map(g=>g.id).filter(g=>!d.has(g));i.length>0&&n.push({insertAfterIndex:r,missingToolCallIds:i})}}n.length!==0&&o("messages",r=>{for(let a=n.length-1;a>=0;a--){let{insertAfterIndex:u,missingToolCallIds:d}=n[a],i=d.map(g=>t({role:"tool",tool_call_id:g,content:e}));r.messages.splice(u+1,0,...i)}})}var Ce=s=>{let{getTools:e,beforeCallTools:t,callTool:o,onToolCallStart:n,onToolCallEnd:r,toolCallCancelledContent:a="Tool call cancelled.",toolCallFailedContent:u="Tool call failed.",autoFillMissingToolMessages:d=!1,...i}=s,g=(c,l)=>{var C,S;return c.state??(c.state={}),(C=c.state).toolCall??(C.toolCall={}),(S=c.state.toolCall)[l]??(S[l]={}),c},b=(...c)=>{let[l,{assistantMessage:C,mutate:S}]=c;S("messages",()=>{let w=g(C,l.id);w.state.toolCall[l.id].status="running"}),n?.(...c)},y=(...c)=>{let[l,{status:C,assistantMessage:S,mutate:w}]=c;w("messages",()=>{let U=g(S,l.id);U.state.toolCall[l.id].status=C}),r?.(...c)};return{name:"tool",...i,onTurnStart:c=>{let{getState:l,createMessage:C,mutate:S}=c,w=l().messages;return d&&ze({messages:w,cancelledContent:a,createMessage:C,mutate:S}),i.onTurnStart?.(c)},onBeforeRequest:async c=>{let{requestBody:l}=c,C=await e();return C&&C.length>0&&(l.tools=C),i.onBeforeRequest?.(c)},onAfterRequest:async c=>{let{currentMessage:l,lastChoice:C,appendMessage:S,abortSignal:w,setRequestState:U,requestNext:q,mutate:p,createMessage:f}=c;if(C?.finish_reason!=="tool_calls"||!l.tool_calls?.length)return;U("processing","calling-tools"),await t?.(l.tool_calls,{...c,assistantMessage:l});let h=l.tool_calls.map(async P=>{let E=Math.floor(Date.now()/1e3),T=!1,M=f({role:"tool",tool_call_id:P.id,content:"",metadata:{createdAt:E,updatedAt:E}});S(M);let _={...c,assistantMessage:l,toolMessage:M};b(P,_);try{let m=o(P,_),v=Y(m);for await(let x of v)p("messages",()=>{if((typeof x=="string"&&x.length>0||x&&typeof x=="object"&&Object.keys(x).length>0)&&(T=!0),typeof x=="string")M.content+=x;else{let A={};try{let k=Array.isArray(M.content)?M.content.map(R=>R.text).join(""):M.content;A=JSON.parse(k||"{}")}catch(k){console.warn(k)}M.content=JSON.stringify(X(A,x))}M.metadata.updatedAt=Math.floor(Date.now()/1e3)});y(P,{..._,status:"success"})}catch(m){let v=m instanceof Error?m:new Error(String(m));if(w.aborted){y(P,{..._,status:"cancelled",error:v});return}console.error(m),T||p("messages",()=>{M.content=u,M.metadata.updatedAt=Math.floor(Date.now()/1e3)}),y(P,{..._,status:"failed",error:v})}});return await Promise.all(h),w.aborted||q(),i.onAfterRequest?.(c)}}};var $e=async()=>{throw new Error("Response provider is not set")},Je=s=>{let e=[];for(let t of s){if(t.name){let o=e.findIndex(n=>n.name===t.name);o!==-1&&e.splice(o,1)}e.push(t)}return e},H=(s,e)=>typeof s.disabled=="function"?s.disabled(e):!!s.disabled,he=(s,e={})=>{let{initialMessages:t=[],requestMessageFields:o=[],requestMessageFieldsExclude:n=["state","metadata","loading"],responseProvider:r=$e,onCompletionChunk:a,plugins:u=[]}=e,d={requestState:"idle",processingState:void 0,messages:[...t]};s.initialize(d);let i={currentTurn:[],customContext:{},abortController:null,responseProvider:r},g=[oe(),se()],b=Je(g.concat(u)),y=()=>s.getState(),c=m=>s.createMessage(m),l=s.subscribe,C=s.mutate,S=m=>!m||Object.keys(m).length===0?!1:Object.values(m).some(v=>!!v),w=m=>{let v=m;return o.length&&(v=v.map(x=>Be(x,o))),n.length&&(v=v.map(x=>_e(x,n))),v},U=m=>{Object.assign(i.customContext,m)},q=(m,v)=>{C("requestState",(x,A)=>{if(x.requestState===m&&x.processingState===v){A();return}x.requestState=m,x.processingState=m==="processing"?v??"requesting":void 0})},p=(...m)=>{let v=m.map(x=>c(x));return C("messages",x=>{x.messages.push(...v)}),i.currentTurn.push(...v),v},f=m=>({getState:y,createMessage:c,mutate:C,abortSignal:m,currentTurn:i.currentTurn,customContext:i.customContext,setRequestState:q,setCustomContext:U});async function h(m,v,x={}){q("processing","requesting");let A={messages:y().messages},k=f(v);for(let j of b.filter(O=>!H(O,k)))await j.onBeforeRequest?.({...k,requestBody:A});A.messages=w(A.messages);let R={role:"assistant",content:"",loading:!0};[R]=p(R),x.setAssistantMessage?.(R);let I=m(A,v),F=Y(I),N;for await(let j of F){q("processing","completing"),C("messages",(D,Z)=>{R.loading?R.loading=void 0:Z()});let O=(j.choices||[]).find(D=>D.index===0)??j.choices?.[0];if(!O)continue;N=O;let G=()=>{C("messages",()=>{R.metadata||(R.metadata={});let{created:D,...Z}=j;R.metadata.createdAt=D,R.metadata.updatedAt=Math.floor(Date.now()/1e3),Object.assign(R.metadata,Z);let ne="delta"in O&&S(O.delta)&&O.delta||"message"in O&&S(O.message)&&O.message||null;if(ne?.role&&(R.role=ne.role),ne){let{role:ot,...Fe}=ne;X(R,Fe)}})},Me=D=>{C("messages",()=>{D(R)})};if(a){let D=f(v);a({...D,chunk:j,choice:O,currentMessage:R,updateCurrentMessage:Me},G)}else G();let ye=f(v);for(let D of b.filter(Z=>!H(Z,ye)))D.onCompletionChunk?.({...ye,abortSignal:v,chunk:j,choice:O,currentMessage:R,updateCurrentMessage:Me})}await P(R,m,v,N,x)}async function P(m,v,x,A,k){let R=!1,I=f(x),F=b.filter(N=>!H(N,I)).map(N=>{if(!N.onAfterRequest)return null;let j=G=>{p(...Array.isArray(G)?G:[G])},O=()=>{R=!0};return N.onAfterRequest({...I,currentMessage:m,lastChoice:A,appendMessage:j,requestNext:O})}).filter(N=>N!==null);await qe(Promise.all(F),x),R&&await h(v,x,k)}async function E(){let m=new AbortController;i.abortController=m,i.customContext={};let v=null,x=A=>{v=A};try{q("processing","requesting");let A=f(m.signal);for(let I of b.filter(F=>!H(F,A)))await I.onTurnStart?.(A);let k=i.responseProvider;try{await h(k,m.signal,{setAssistantMessage:x}),q("completed")}catch(I){if(m.signal.aborted||I instanceof Q||I instanceof Error&&I.name==="AbortError")q("aborted");else throw I}let R=f(m.signal);for(let I of b.filter(F=>!H(F,R)))await I.onTurnEnd?.(R)}catch(A){q("error");let k=!1,R=f(m.signal);for(let I of b.filter(F=>!H(F,R)))I.onError&&(k=!0,I.onError({...R,error:A}));if(!k)throw A}finally{let A=f(m.signal);for(let k of b.filter(R=>!H(R,A)))try{k.onFinally?.(A)}catch(R){console.error(`Error in onFinally hook for plugin [${k.name||"Anonymous"}]:`,R)}i.abortController=null,i.currentTurn=[],C("messages",(k,R)=>{v?.loading?v.loading=void 0:R()})}}async function T(m){if(!m||!m.trim()){console.warn("Cannot send empty message");return}if(y().requestState==="processing"){console.warn("Cannot send message while processing is in progress");return}let v=Math.floor(Date.now()/1e3);p({role:"user",content:m.trim(),metadata:{createdAt:v,updatedAt:v}}),await E()}async function M(...m){if(y().requestState==="processing"){console.warn("Cannot send message while processing is in progress");return}p(...m),await E()}async function _(){i.abortController?.abort(),y().isProcessing&&await new Promise(m=>{let v=()=>{};v=l("requestState",x=>{x.isProcessing||(v(),m())})})}return{getState:y,subscribe:l,sendMessage:T,send:M,abort:_,setResponseProvider(m){i.responseProvider=m}}};var ce=s=>{let{initialMessages:e=[],requestMessageFields:t=[],requestMessageFieldsExclude:o=["state","metadata","loading"],plugins:n=[],responseProvider:r,onCompletionChunk:a}=s,u=ke(),d=l=>u.messages.value.find(C=>C===l||(0,K.toRaw)(C)===l||(0,K.toRaw)(C)===(0,K.toRaw)(l))??l,i=l=>({messages:u.messages.value,currentTurn:l.currentTurn.map(C=>d(C)),requestState:u.requestState.value,processingState:u.processingState.value,plugins:n,setRequestState:l.setRequestState,abortSignal:l.abortSignal,customContext:l.customContext,setCustomContext:l.setCustomContext}),g=l=>{let C=l;if(typeof C.__corePluginFactory=="function")return C.__corePluginFactory({createCorePlugin:g,createVueBaseContext:i,resolveReactiveMessage:d});let{name:S,disabled:w,onTurnStart:U,onTurnEnd:q,onBeforeRequest:p,onAfterRequest:f,onCompletionChunk:h,onError:P,onFinally:E}=l,T={};return S!==void 0&&(T.name=S),w!==void 0&&(T.disabled=typeof w=="function"?M=>w(i(M)):w),U&&(T.onTurnStart=M=>U(i(M))),q&&(T.onTurnEnd=M=>q(i(M))),p&&(T.onBeforeRequest=M=>p({...i(M),requestBody:M.requestBody})),f&&(T.onAfterRequest=M=>f({...i(M),currentMessage:d(M.currentMessage),lastChoice:M.lastChoice,appendMessage:M.appendMessage,requestNext:M.requestNext})),h&&(T.onCompletionChunk=M=>h({...i(M),currentMessage:d(M.currentMessage),choice:M.choice,chunk:M.chunk})),P&&(T.onError=M=>P({...i(M),error:M.error})),E&&(T.onFinally=M=>E(i(M))),T},y=he(u,{initialMessages:e,requestMessageFields:t,requestMessageFieldsExclude:o,responseProvider:r,onCompletionChunk:a?(l,C)=>{if(a)return a({...i(l),currentMessage:d(l.currentMessage),choice:l.choice,chunk:l.chunk},C)}:void 0,plugins:n.map(l=>g(l))}),c=(0,K.ref)(r);return(0,K.watch)(c,l=>{y.setResponseProvider(l)},{flush:"sync"}),{requestState:u.requestState,processingState:u.processingState,messages:u.messages,responseProvider:c,isProcessing:u.isProcessing,sendMessage:y.sendMessage,send:y.send,abortRequest:y.abort}};var ue=require("vue");function Ue(s,e=200,t=!1,o=!0,n=!1){return Qe(Xe(e,t,o,n),s)}function Qe(s,e){function t(...o){return new Promise((n,r)=>{Promise.resolve(s(()=>e.apply(this,o),{fn:e,thisArg:this,args:o})).then(n).catch(r)})}return t}var De=()=>{};function Xe(...s){let e=0,t,o=!0,n=De,r,a,u,d,i;!(0,ue.isRef)(s[0])&&typeof s[0]=="object"?{delay:a,trailing:u=!0,leading:d=!0,rejectOnCancel:i=!1}=s[0]:[a,u=!0,d=!0,i=!1]=s;let g=()=>{t&&(clearTimeout(t),t=void 0,n(),n=De)};return y=>{let c=(0,ue.toValue)(a),l=Date.now()-e,C=()=>r=y();return g(),c<=0?(e=Date.now(),C()):(l>c?(e=Date.now(),(d||!o)&&C()):u&&(r=new Promise((S,w)=>{n=i?w:S,t=setTimeout(()=>{e=Date.now(),o=!0,S(C()),g()},Math.max(0,c-l))})),!d&&!t&&(t=setTimeout(()=>o=!0,c)),o=!1,r)}}var Ye=s=>{let e=s.storage||le(),t=(0,L.ref)([]),o=new Map,n=new Map,r=(0,L.ref)(null),a=(0,L.computed)(()=>{let p=r.value;if(!p)return null;let f=t.value.find(P=>P.id===p);if(!f)return null;let h=o.get(p);return h?{...f,engine:h}:null}),u=p=>{if(!e?.saveMessages)return;let f=p||r.value,h=t.value.find(E=>E.id===f);if(!h)return;h.updatedAt=Date.now(),e?.saveConversation?.(h);let P=o.get(h.id);P&&e.saveMessages(h.id,P.messages.value)},d=(p,f)=>{if(!s.autoSaveMessages||!e?.saveMessages)return;let h=n.get(p);h&&h();let P=s.autoSaveThrottle??1e3,E=Ue(()=>{u(p)},P,!0,!0),T=(0,L.watch)(f.messages,E,{deep:!0});n.set(p,T)},i=p=>{let f=n.get(p);f&&(f(),n.delete(p))};e?.loadConversations&&Promise.resolve(e.loadConversations()).then(p=>{if(!p?.length)return[];if(t.value.length===0)return t.value=p,t.value;let f=new Map(t.value.map(h=>[h.id,h]));return p.forEach(h=>{f.has(h.id)||f.set(h.id,h)}),t.value=Array.from(f.values()),t.value}).then(p=>{s.onLoad?.(p)}).catch(p=>{console.error("[useConversation] loadConversations failed:",p)});let g=async(p,f)=>{let h=o.get(p);if(h)return h;let P=f?.initialMessages??s.useMessageOptions.initialMessages??[];if(e?.loadMessages)try{P=await e.loadMessages(p)}catch(T){console.error("[useConversation] loadMessages failed:",T)}let E=ce({...s.useMessageOptions,...f,initialMessages:P});return o.set(p,E),d(p,E),E};function b(){return Date.now().toString(36)+Math.random().toString(36).substring(2,9)}let y=p=>{let{id:f=b(),title:h,metadata:P,useMessageOptions:E}=p||{},T=Date.now(),M={id:f,title:h,createdAt:T,updatedAt:T,metadata:P};t.value.unshift(M);let _=ce({...s.useMessageOptions,...E});return o.set(f,_),d(f,_),e?.saveConversation?.(M),e?.saveMessages?.(f,_.messages.value),r.value=f,a.value},c=p=>{let{excludeId:f}=p||{};o.forEach((h,P)=>{if(f&&P===f)return;h.isProcessing?.value||(i(P),o.delete(P))})};return{conversations:t,activeConversationId:r,activeConversation:a,createConversation:y,switchConversation:async p=>p?r.value===p?a.value:t.value.find(h=>h.id===p)?(await g(p),c({excludeId:p}),r.value=p,a.value):null:null,deleteConversation:async p=>{let f=t.value.findIndex(P=>P.id===p);if(f===-1)return;await o.get(p)?.abortRequest(),i(p),o.delete(p),t.value.splice(f,1),e?.deleteConversation?.(p),r.value===p&&(r.value=null,c())},clear:()=>{t.value.map(f=>f.id).forEach(f=>{e?.deleteConversation?.(f)}),o.forEach(f=>{f.abortRequest()}),n.forEach(f=>{f()}),t.value=[],o.clear(),n.clear(),r.value=null},updateConversationTitle:(p,f)=>{let h=t.value.find(P=>P.id===p);h&&(h.title=f,h.updatedAt=Date.now(),e?.saveConversation?.(h))},saveMessages:u,sendMessage:p=>{a.value?.engine.sendMessage(p)},abortActiveRequest:async()=>{await a.value?.engine.abortRequest()}}};var Ze=(s={})=>{let{continueContent:e="Please continue with your previous answer.",...t}=s;return{name:"length",__corePluginFactory(o){return se({...o.createCorePlugin(t),continueContent:e})}}};var et=(s={})=>({name:"thinking",__corePluginFactory(e){return oe(e.createCorePlugin(s))}});var tt=s=>{let{getTools:e,beforeCallTools:t,callTool:o,onToolCallStart:n,onToolCallEnd:r,toolCallCancelledContent:a="Tool call cancelled.",toolCallFailedContent:u="Tool call failed.",autoFillMissingToolMessages:d=!1,...i}=s;return{name:"tool",__corePluginFactory(g){let b=g.createCorePlugin(i);return Ce({...b,getTools:async()=>await e(),beforeCallTools:t?async(y,c)=>{let l=g.resolveReactiveMessage(c.assistantMessage);await t(y,{...g.createVueBaseContext(c),assistantMessage:l,currentMessage:l})}:void 0,callTool:async function*(y,c){let l=g.resolveReactiveMessage(c.assistantMessage),C=g.resolveReactiveMessage(c.toolMessage),S=o(y,{...g.createVueBaseContext(c),assistantMessage:l,currentMessage:l,toolMessage:C});for await(let w of Y(S))yield w},onToolCallStart:n?(y,c)=>{let l=g.resolveReactiveMessage(c.assistantMessage),C=g.resolveReactiveMessage(c.toolMessage);n(y,{...g.createVueBaseContext(c),assistantMessage:l,primaryMessage:l,toolMessage:C})}:void 0,onToolCallEnd:r?(y,c)=>{let l=g.resolveReactiveMessage(c.assistantMessage),C=g.resolveReactiveMessage(c.toolMessage);r(y,{...g.createVueBaseContext(c),assistantMessage:l,primaryMessage:l,toolMessage:C,status:c.status,error:c.error})}:void 0,toolCallCancelledContent:a,toolCallFailedContent:u,autoFillMissingToolMessages:d})}}};0&&(module.exports={AIClient,BaseModelProvider,ErrorType,IndexedDBStrategy,LocalStorageStrategy,OpenAIProvider,StreamEventType,extractTextFromResponse,formatMessages,handleSSEStream,indexedDBStorageStrategyFactory,lengthPlugin,localStorageStrategyFactory,sseStreamToGenerator,thinkingPlugin,toolPlugin,useConversation,useMessage});
package/dist/index.mjs CHANGED
@@ -1,4 +1,4 @@
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(`
1
+ import{b as H,c as L,d as W,e as $,g as G,h as J}from"./chunk-EES4JUCD.mjs";var A=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 Y=(g=>(g.NETWORK_ERROR="network_error",g.AUTHENTICATION_ERROR="authentication_error",g.RATE_LIMIT_ERROR="rate_limit_error",g.SERVER_ERROR="server_error",g.MODEL_ERROR="model_error",g.TIMEOUT_ERROR="timeout_error",g.UNKNOWN_ERROR="unknown_error",g))(Y||{}),Z=(s=>(s.DATA="data",s.ERROR="error",s.DONE="done",s))(Z||{});function T(o){return{type:o.type||"unknown_error",message:o.message||"\u672A\u77E5\u9519\u8BEF",statusCode:o.statusCode,originalError:o.originalError}}function F(o){if(!o.response)return T({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?T({type:"authentication_error",message:"\u8EAB\u4EFD\u9A8C\u8BC1\u5931\u8D25\uFF0C\u8BF7\u68C0\u67E5\u60A8\u7684API\u5BC6\u94A5",statusCode:t,originalError:o}):t===429?T({type:"rate_limit_error",message:"\u8D85\u51FAAPI\u8C03\u7528\u9650\u5236\uFF0C\u8BF7\u7A0D\u540E\u518D\u8BD5",statusCode:t,originalError:o}):t>=500?T({type:"server_error",message:"\u670D\u52A1\u5668\u9519\u8BEF\uFF0C\u8BF7\u7A0D\u540E\u518D\u8BD5",statusCode:t,originalError:o}):T({type:"unknown_error",message:e?.error?.message||`\u8BF7\u6C42\u5931\u8D25\uFF0C\u72B6\u6001\u7801: ${t}`,statusCode:t,originalError:o})}return o.code==="ECONNABORTED"?T({type:"timeout_error",message:"\u8BF7\u6C42\u8D85\u65F6\uFF0C\u8BF7\u7A0D\u540E\u518D\u8BD5",originalError:o}):T({type:"unknown_error",message:o.message||"\u53D1\u751F\u672A\u77E5\u9519\u8BEF",originalError:o})}async function q(o,t,e){let s=o.body?.getReader();if(!s)throw new Error("Response body is null");let r=new TextDecoder,a="",l,g;e&&e.addEventListener("abort",()=>{s.cancel().catch(d=>console.error("Error cancelling reader:",d))},{once:!0});try{for(;;){if(e?.aborted){await s.cancel();break}let{done:d,value:C}=await s.read();if(d)break;let h=r.decode(C,{stream:!0});a+=h;let b=a.split(`
2
2
 
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};
3
+ `);a=b.pop()||"";for(let f of b)if(f.trim()!==""){if(f.trim()==="data: [DONE]"){g&&(l=g),t.onDone(l);continue}try{let u=f.match(/^data: (.+)$/m);if(!u)continue;let i=JSON.parse(u[1]);t.onData(i),g=i.choices?.[0]?.finish_reason||void 0}catch(u){console.error("Error parsing SSE message:",u)}}}(a.trim()==="data: [DONE]"||e?.aborted)&&(e?.aborted&&(l="aborted"),t.onDone(l))}catch(d){if(e?.aborted)return;throw d}}function ee(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 te(o){return!o.choices||!o.choices.length?"":o.choices[0].message?.content||""}function _(o="The operation was aborted"){let t=new Error(o);return t.name="AbortError",t}async function*se(o,t={}){let e=o.body?.getReader();if(!e)throw new Error("ReadableStream not supported");let{signal:s}=t,r=new TextDecoder,a="",l=()=>{e.cancel()};s?.addEventListener("abort",l);try{for(;;){if(s?.aborted)throw _();let g;try{g=await e.read()}catch(f){throw s?.aborted?_():f}let{done:d,value:C}=g;if(d){if(s?.aborted)throw _();return}let h=r.decode(C,{stream:!0});a+=h;let b=a.split(`
4
+ `);a=b.pop()||"";for(let f of b)if(f.trim()!==""&&f.startsWith("data: ")){let u=f.slice(6);if(u==="[DONE]")return;try{yield JSON.parse(u)}catch(i){console.warn("Failed to parse SSE data:",u,i)}}}}finally{s?.removeEventListener("abort",l),e.releaseLock()}}var S=class extends A{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},r={method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(s)};this.apiKey&&Object.assign(r.headers,{Authorization:`Bearer ${this.apiKey}`});let a=await fetch(`${this.baseURL}/chat/completions`,r);if(!a.ok){let l=await a.text();throw new Error(`HTTP error! status: ${a.status}, details: ${l}`)}return await a.json()}catch(s){throw F(s)}}async chatStream(e,s){let{signal:r,...a}=e.options||{};try{this.validateRequest(e);let l={model:e.options?.model||this.config.defaultModel||this.defaultModel,messages:e.messages,...a,stream:!0},g={method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${this.apiKey}`,Accept:"text/event-stream"},body:JSON.stringify(l),signal:r};this.apiKey&&Object.assign(g.headers,{Authorization:`Bearer ${this.apiKey}`});let d=await fetch(`${this.baseURL}/chat/completions`,g);if(!d.ok){let C=await d.text();throw new Error(`HTTP error! status: ${d.status}, details: ${C}`)}await q(d,s,r)}catch(l){if(r?.aborted)return;s.onError(F(l))}}updateConfig(e){super.updateConfig(e),e.apiUrl&&(this.baseURL=e.apiUrl),e.apiKey&&(this.apiKey=e.apiKey),e.defaultModel&&(this.defaultModel=e.defaultModel)}};var N=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 S({...e,...t})}else return new S(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 oe}from"vue";function w(o,t=new WeakMap){if(o==null||typeof o!="object")return o;try{let e=oe(o);if(t.has(e))return t.get(e);if(Array.isArray(e)){let r=[];return t.set(e,r),r.push(...e.map(a=>w(a,t))),r}if(e instanceof Date||e instanceof RegExp||e instanceof ArrayBuffer||e instanceof Blob)return e;let s={};t.set(e,s);for(let r of Object.keys(e)){let a=Object.getOwnPropertyDescriptor(e,r);if(!a||a.get||a.set)continue;let l=e[r];typeof l!="function"&&typeof l!="symbol"&&(s[r]=w(l,t))}return s}catch(e){return console.warn("unwrapProxy error:",e),Array.isArray(o)?[]:{}}}var k=o=>o.map(t=>{let{renderContent:e,...s}=t;if(!Array.isArray(e))return t;let r=e.filter(l=>l.type==="collapsible-text"),a=e.filter(l=>l.type==="markdown"||l.type==="text");return r.length>0&&(s.reasoning_content=r.map(l=>l.content).join("")),a.length>0&&(s.content=a.map(l=>l.content).join("")),s});var E=o=>{let t=localStorage.getItem(o);return t?JSON.parse(t):[]},O=class{constructor(t="tiny-robot-ai-conversations"){this.storageKey=t}saveConversation(t){try{let e=E(this.storageKey),s=e.findIndex(r=>r.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 E(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=E(this.storageKey),r=s.findIndex(a=>a.id===t);r!==-1&&(s[r].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=E(this.storageKey).find(a=>a.id===t);return k(s?.messages||[])}catch(e){return console.error("\u52A0\u8F7D\u4F1A\u8BDD\u6D88\u606F\u5931\u8D25:",e),[]}}deleteConversation(t){let e=E(this.storageKey),s=e.findIndex(r=>r.id===t);s!==-1&&e.splice(s,1),localStorage.setItem(this.storageKey,JSON.stringify(e))}};import{openDB as re}from"idb";var I=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?k(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=w(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(),r=w(e);await s.put("messages",{conversationId:t,messages:r})}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 K(o={}){return new O(o.key||"tiny-robot-ai-conversations")}function ne(o={}){return new I(o.dbName||"tiny-robot-ai-db",o.dbVersion||1)}import{computed as pe,ref as X,watch as de}from"vue";import{ref as ae,toRaw as j,watch as ie}from"vue";var V=o=>{let{initialMessages:t=[],requestMessageFields:e=[],requestMessageFieldsExclude:s=["state","metadata","loading"],plugins:r=[],responseProvider:a,onCompletionChunk:l}=o,g=H(),d=i=>g.messages.value.find(M=>M===i||j(M)===i||j(M)===j(i))??i,C=i=>({messages:g.messages.value,currentTurn:i.currentTurn.map(M=>d(M)),requestState:g.requestState.value,processingState:g.processingState.value,plugins:r,setRequestState:i.setRequestState,abortSignal:i.abortSignal,customContext:i.customContext,setCustomContext:i.setCustomContext}),h=i=>{let M=i;if(typeof M.__corePluginFactory=="function")return M.__corePluginFactory({createCorePlugin:h,createVueBaseContext:C,resolveReactiveMessage:d});let{name:P,disabled:x,onTurnStart:U,onTurnEnd:B,onBeforeRequest:n,onAfterRequest:c,onCompletionChunk:p,onError:y,onFinally:R}=i,v={};return P!==void 0&&(v.name=P),x!==void 0&&(v.disabled=typeof x=="function"?m=>x(C(m)):x),U&&(v.onTurnStart=m=>U(C(m))),B&&(v.onTurnEnd=m=>B(C(m))),n&&(v.onBeforeRequest=m=>n({...C(m),requestBody:m.requestBody})),c&&(v.onAfterRequest=m=>c({...C(m),currentMessage:d(m.currentMessage),lastChoice:m.lastChoice,appendMessage:m.appendMessage,requestNext:m.requestNext})),p&&(v.onCompletionChunk=m=>p({...C(m),currentMessage:d(m.currentMessage),choice:m.choice,chunk:m.chunk})),y&&(v.onError=m=>y({...C(m),error:m.error})),R&&(v.onFinally=m=>R(C(m))),v},f=J(g,{initialMessages:t,requestMessageFields:e,requestMessageFieldsExclude:s,responseProvider:a,onCompletionChunk:l?(i,M)=>{if(l)return l({...C(i),currentMessage:d(i.currentMessage),choice:i.choice,chunk:i.chunk},M)}:void 0,plugins:r.map(i=>h(i))}),u=ae(a);return ie(u,i=>{f.setResponseProvider(i)},{flush:"sync"}),{requestState:g.requestState,processingState:g.processingState,messages:g.messages,responseProvider:u,isProcessing:g.isProcessing,sendMessage:f.sendMessage,send:f.send,abortRequest:f.abort}};import{isRef as le,toValue as ce}from"vue";function Q(o,t=200,e=!1,s=!0,r=!1){return ge(ue(t,e,s,r),o)}function ge(o,t){function e(...s){return new Promise((r,a)=>{Promise.resolve(o(()=>t.apply(this,s),{fn:t,thisArg:this,args:s})).then(r).catch(a)})}return e}var z=()=>{};function ue(...o){let t=0,e,s=!0,r=z,a,l,g,d,C;!le(o[0])&&typeof o[0]=="object"?{delay:l,trailing:g=!0,leading:d=!0,rejectOnCancel:C=!1}=o[0]:[l,g=!0,d=!0,C=!1]=o;let h=()=>{e&&(clearTimeout(e),e=void 0,r(),r=z)};return f=>{let u=ce(l),i=Date.now()-t,M=()=>a=f();return h(),u<=0?(t=Date.now(),M()):(i>u?(t=Date.now(),(d||!s)&&M()):g&&(a=new Promise((P,x)=>{r=C?x:P,e=setTimeout(()=>{t=Date.now(),s=!0,P(M()),h()},Math.max(0,u-i))})),!d&&!e&&(e=setTimeout(()=>s=!0,u)),s=!1,a)}}var Qe=o=>{let t=o.storage||K(),e=X([]),s=new Map,r=new Map,a=X(null),l=pe(()=>{let n=a.value;if(!n)return null;let c=e.value.find(y=>y.id===n);if(!c)return null;let p=s.get(n);return p?{...c,engine:p}:null}),g=n=>{if(!t?.saveMessages)return;let c=n||a.value,p=e.value.find(R=>R.id===c);if(!p)return;p.updatedAt=Date.now(),t?.saveConversation?.(p);let y=s.get(p.id);y&&t.saveMessages(p.id,y.messages.value)},d=(n,c)=>{if(!o.autoSaveMessages||!t?.saveMessages)return;let p=r.get(n);p&&p();let y=o.autoSaveThrottle??1e3,R=Q(()=>{g(n)},y,!0,!0),v=de(c.messages,R,{deep:!0});r.set(n,v)},C=n=>{let c=r.get(n);c&&(c(),r.delete(n))};t?.loadConversations&&Promise.resolve(t.loadConversations()).then(n=>{if(!n?.length)return[];if(e.value.length===0)return e.value=n,e.value;let c=new Map(e.value.map(p=>[p.id,p]));return n.forEach(p=>{c.has(p.id)||c.set(p.id,p)}),e.value=Array.from(c.values()),e.value}).then(n=>{o.onLoad?.(n)}).catch(n=>{console.error("[useConversation] loadConversations failed:",n)});let h=async(n,c)=>{let p=s.get(n);if(p)return p;let y=c?.initialMessages??o.useMessageOptions.initialMessages??[];if(t?.loadMessages)try{y=await t.loadMessages(n)}catch(v){console.error("[useConversation] loadMessages failed:",v)}let R=V({...o.useMessageOptions,...c,initialMessages:y});return s.set(n,R),d(n,R),R};function b(){return Date.now().toString(36)+Math.random().toString(36).substring(2,9)}let f=n=>{let{id:c=b(),title:p,metadata:y,useMessageOptions:R}=n||{},v=Date.now(),m={id:c,title:p,createdAt:v,updatedAt:v,metadata:y};e.value.unshift(m);let D=V({...o.useMessageOptions,...R});return s.set(c,D),d(c,D),t?.saveConversation?.(m),t?.saveMessages?.(c,D.messages.value),a.value=c,l.value},u=n=>{let{excludeId:c}=n||{};s.forEach((p,y)=>{if(c&&y===c)return;p.isProcessing?.value||(C(y),s.delete(y))})};return{conversations:e,activeConversationId:a,activeConversation:l,createConversation:f,switchConversation:async n=>n?a.value===n?l.value:e.value.find(p=>p.id===n)?(await h(n),u({excludeId:n}),a.value=n,l.value):null:null,deleteConversation:async n=>{let c=e.value.findIndex(y=>y.id===n);if(c===-1)return;await s.get(n)?.abortRequest(),C(n),s.delete(n),e.value.splice(c,1),t?.deleteConversation?.(n),a.value===n&&(a.value=null,u())},clear:()=>{e.value.map(c=>c.id).forEach(c=>{t?.deleteConversation?.(c)}),s.forEach(c=>{c.abortRequest()}),r.forEach(c=>{c()}),e.value=[],s.clear(),r.clear(),a.value=null},updateConversationTitle:(n,c)=>{let p=e.value.find(y=>y.id===n);p&&(p.title=c,p.updatedAt=Date.now(),t?.saveConversation?.(p))},saveMessages:g,sendMessage:n=>{l.value?.engine.sendMessage(n)},abortActiveRequest:async()=>{await l.value?.engine.abortRequest()}}};var Ze=(o={})=>{let{continueContent:t="Please continue with your previous answer.",...e}=o;return{name:"length",__corePluginFactory(s){return L({...s.createCorePlugin(e),continueContent:t})}}};var st=(o={})=>({name:"thinking",__corePluginFactory(t){return W(t.createCorePlugin(o))}});var at=o=>{let{getTools:t,beforeCallTools:e,callTool:s,onToolCallStart:r,onToolCallEnd:a,toolCallCancelledContent:l="Tool call cancelled.",toolCallFailedContent:g="Tool call failed.",autoFillMissingToolMessages:d=!1,...C}=o;return{name:"tool",__corePluginFactory(h){let b=h.createCorePlugin(C);return G({...b,getTools:async()=>await t(),beforeCallTools:e?async(f,u)=>{let i=h.resolveReactiveMessage(u.assistantMessage);await e(f,{...h.createVueBaseContext(u),assistantMessage:i,currentMessage:i})}:void 0,callTool:async function*(f,u){let i=h.resolveReactiveMessage(u.assistantMessage),M=h.resolveReactiveMessage(u.toolMessage),P=s(f,{...h.createVueBaseContext(u),assistantMessage:i,currentMessage:i,toolMessage:M});for await(let x of $(P))yield x},onToolCallStart:r?(f,u)=>{let i=h.resolveReactiveMessage(u.assistantMessage),M=h.resolveReactiveMessage(u.toolMessage);r(f,{...h.createVueBaseContext(u),assistantMessage:i,primaryMessage:i,toolMessage:M})}:void 0,onToolCallEnd:a?(f,u)=>{let i=h.resolveReactiveMessage(u.assistantMessage),M=h.resolveReactiveMessage(u.toolMessage);a(f,{...h.createVueBaseContext(u),assistantMessage:i,primaryMessage:i,toolMessage:M,status:u.status,error:u.error})}:void 0,toolCallCancelledContent:l,toolCallFailedContent:g,autoFillMissingToolMessages:d})}}};export{N as AIClient,A as BaseModelProvider,Y as ErrorType,I as IndexedDBStrategy,O as LocalStorageStrategy,S as OpenAIProvider,Z as StreamEventType,te as extractTextFromResponse,ee as formatMessages,q as handleSSEStream,ne as indexedDBStorageStrategyFactory,Ze as lengthPlugin,K as localStorageStrategyFactory,se as sseStreamToGenerator,st as thinkingPlugin,at as toolPlugin,Qe as useConversation,V as useMessage};