@opentiny/tiny-robot-kit 0.2.0-alpha.7 → 0.2.0-alpha.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +46 -39
- package/dist/index.d.ts +46 -39
- package/dist/index.js +2 -2
- package/dist/index.mjs +2 -2
- package/package.json +2 -2
package/dist/index.d.mts
CHANGED
|
@@ -1,5 +1,43 @@
|
|
|
1
1
|
import { Ref, Reactive } from 'vue';
|
|
2
2
|
|
|
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
|
+
|
|
3
41
|
/**
|
|
4
42
|
* 消息角色类型
|
|
5
43
|
*/
|
|
@@ -103,6 +141,7 @@ type AIProvider = 'openai' | 'deepseek' | 'custom';
|
|
|
103
141
|
*/
|
|
104
142
|
interface AIModelConfig {
|
|
105
143
|
provider: AIProvider;
|
|
144
|
+
providerImplementation?: BaseModelProvider;
|
|
106
145
|
apiKey?: string;
|
|
107
146
|
apiUrl?: string;
|
|
108
147
|
apiVersion?: string;
|
|
@@ -193,44 +232,6 @@ declare class AIClient {
|
|
|
193
232
|
updateConfig(config: Partial<AIModelConfig>): void;
|
|
194
233
|
}
|
|
195
234
|
|
|
196
|
-
/**
|
|
197
|
-
* 模型Provider基类
|
|
198
|
-
*/
|
|
199
|
-
declare abstract class BaseModelProvider {
|
|
200
|
-
protected config: AIModelConfig;
|
|
201
|
-
/**
|
|
202
|
-
* @param config AI模型配置
|
|
203
|
-
*/
|
|
204
|
-
constructor(config: AIModelConfig);
|
|
205
|
-
/**
|
|
206
|
-
* 发送聊天请求并获取响应
|
|
207
|
-
* @param request 聊天请求参数
|
|
208
|
-
* @returns 聊天响应
|
|
209
|
-
*/
|
|
210
|
-
abstract chat(request: ChatCompletionRequest): Promise<ChatCompletionResponse>;
|
|
211
|
-
/**
|
|
212
|
-
* 发送流式聊天请求并通过处理器处理响应
|
|
213
|
-
* @param request 聊天请求参数
|
|
214
|
-
* @param handler 流式响应处理器
|
|
215
|
-
*/
|
|
216
|
-
abstract chatStream(request: ChatCompletionRequest, handler: StreamHandler): Promise<void>;
|
|
217
|
-
/**
|
|
218
|
-
* 更新配置
|
|
219
|
-
* @param config 新的AI模型配置
|
|
220
|
-
*/
|
|
221
|
-
updateConfig(config: AIModelConfig): void;
|
|
222
|
-
/**
|
|
223
|
-
* 获取当前配置
|
|
224
|
-
* @returns AI模型配置
|
|
225
|
-
*/
|
|
226
|
-
getConfig(): AIModelConfig;
|
|
227
|
-
/**
|
|
228
|
-
* 验证请求参数
|
|
229
|
-
* @param request 聊天请求参数
|
|
230
|
-
*/
|
|
231
|
-
protected validateRequest(request: ChatCompletionRequest): void;
|
|
232
|
-
}
|
|
233
|
-
|
|
234
235
|
/**
|
|
235
236
|
* OpenAI提供商
|
|
236
237
|
* 用于与OpenAI API进行交互
|
|
@@ -268,6 +269,12 @@ declare class OpenAIProvider extends BaseModelProvider {
|
|
|
268
269
|
* 提供一些实用的辅助函数
|
|
269
270
|
*/
|
|
270
271
|
|
|
272
|
+
/**
|
|
273
|
+
* 处理SSE流式响应
|
|
274
|
+
* @param response fetch响应对象
|
|
275
|
+
* @param handler 流处理器
|
|
276
|
+
*/
|
|
277
|
+
declare function handleSSEStream(response: Response, handler: StreamHandler, signal?: AbortSignal): Promise<void>;
|
|
271
278
|
/**
|
|
272
279
|
* 格式化消息
|
|
273
280
|
* 将各种格式的消息转换为标准的ChatMessage格式
|
|
@@ -450,4 +457,4 @@ interface UseConversationReturn {
|
|
|
450
457
|
*/
|
|
451
458
|
declare function useConversation(options: UseConversationOptions): UseConversationReturn;
|
|
452
459
|
|
|
453
|
-
export { type AIAdapterError, AIClient, type AIModelConfig, type AIProvider, BaseModelProvider, type ChatCompletionOptions, type ChatCompletionRequest, type ChatCompletionResponse, type ChatCompletionResponseChoice, type ChatCompletionResponseMessage, type ChatCompletionResponseUsage, type ChatCompletionStreamResponse, type ChatCompletionStreamResponseChoice, type ChatCompletionStreamResponseDelta, type ChatHistory, type ChatMessage, type Conversation, type ConversationState, type ConversationStorageStrategy, ErrorType, FinalStatus, GeneratingStatus, LocalStorageStrategy, type MessageRole, type MessageState, OpenAIProvider, STATUS, StreamEventType, type StreamHandler, type UseConversationOptions, type UseConversationReturn, type UseMessageOptions, type UseMessageReturn, extractTextFromResponse, formatMessages, useConversation, useMessage };
|
|
460
|
+
export { type AIAdapterError, AIClient, type AIModelConfig, type AIProvider, BaseModelProvider, type ChatCompletionOptions, type ChatCompletionRequest, type ChatCompletionResponse, type ChatCompletionResponseChoice, type ChatCompletionResponseMessage, type ChatCompletionResponseUsage, type ChatCompletionStreamResponse, type ChatCompletionStreamResponseChoice, type ChatCompletionStreamResponseDelta, type ChatHistory, type ChatMessage, type Conversation, type ConversationState, type ConversationStorageStrategy, ErrorType, FinalStatus, GeneratingStatus, LocalStorageStrategy, type MessageRole, type MessageState, OpenAIProvider, STATUS, StreamEventType, type StreamHandler, type UseConversationOptions, type UseConversationReturn, type UseMessageOptions, type UseMessageReturn, extractTextFromResponse, formatMessages, handleSSEStream, useConversation, useMessage };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,43 @@
|
|
|
1
1
|
import { Ref, Reactive } from 'vue';
|
|
2
2
|
|
|
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
|
+
|
|
3
41
|
/**
|
|
4
42
|
* 消息角色类型
|
|
5
43
|
*/
|
|
@@ -103,6 +141,7 @@ type AIProvider = 'openai' | 'deepseek' | 'custom';
|
|
|
103
141
|
*/
|
|
104
142
|
interface AIModelConfig {
|
|
105
143
|
provider: AIProvider;
|
|
144
|
+
providerImplementation?: BaseModelProvider;
|
|
106
145
|
apiKey?: string;
|
|
107
146
|
apiUrl?: string;
|
|
108
147
|
apiVersion?: string;
|
|
@@ -193,44 +232,6 @@ declare class AIClient {
|
|
|
193
232
|
updateConfig(config: Partial<AIModelConfig>): void;
|
|
194
233
|
}
|
|
195
234
|
|
|
196
|
-
/**
|
|
197
|
-
* 模型Provider基类
|
|
198
|
-
*/
|
|
199
|
-
declare abstract class BaseModelProvider {
|
|
200
|
-
protected config: AIModelConfig;
|
|
201
|
-
/**
|
|
202
|
-
* @param config AI模型配置
|
|
203
|
-
*/
|
|
204
|
-
constructor(config: AIModelConfig);
|
|
205
|
-
/**
|
|
206
|
-
* 发送聊天请求并获取响应
|
|
207
|
-
* @param request 聊天请求参数
|
|
208
|
-
* @returns 聊天响应
|
|
209
|
-
*/
|
|
210
|
-
abstract chat(request: ChatCompletionRequest): Promise<ChatCompletionResponse>;
|
|
211
|
-
/**
|
|
212
|
-
* 发送流式聊天请求并通过处理器处理响应
|
|
213
|
-
* @param request 聊天请求参数
|
|
214
|
-
* @param handler 流式响应处理器
|
|
215
|
-
*/
|
|
216
|
-
abstract chatStream(request: ChatCompletionRequest, handler: StreamHandler): Promise<void>;
|
|
217
|
-
/**
|
|
218
|
-
* 更新配置
|
|
219
|
-
* @param config 新的AI模型配置
|
|
220
|
-
*/
|
|
221
|
-
updateConfig(config: AIModelConfig): void;
|
|
222
|
-
/**
|
|
223
|
-
* 获取当前配置
|
|
224
|
-
* @returns AI模型配置
|
|
225
|
-
*/
|
|
226
|
-
getConfig(): AIModelConfig;
|
|
227
|
-
/**
|
|
228
|
-
* 验证请求参数
|
|
229
|
-
* @param request 聊天请求参数
|
|
230
|
-
*/
|
|
231
|
-
protected validateRequest(request: ChatCompletionRequest): void;
|
|
232
|
-
}
|
|
233
|
-
|
|
234
235
|
/**
|
|
235
236
|
* OpenAI提供商
|
|
236
237
|
* 用于与OpenAI API进行交互
|
|
@@ -268,6 +269,12 @@ declare class OpenAIProvider extends BaseModelProvider {
|
|
|
268
269
|
* 提供一些实用的辅助函数
|
|
269
270
|
*/
|
|
270
271
|
|
|
272
|
+
/**
|
|
273
|
+
* 处理SSE流式响应
|
|
274
|
+
* @param response fetch响应对象
|
|
275
|
+
* @param handler 流处理器
|
|
276
|
+
*/
|
|
277
|
+
declare function handleSSEStream(response: Response, handler: StreamHandler, signal?: AbortSignal): Promise<void>;
|
|
271
278
|
/**
|
|
272
279
|
* 格式化消息
|
|
273
280
|
* 将各种格式的消息转换为标准的ChatMessage格式
|
|
@@ -450,4 +457,4 @@ interface UseConversationReturn {
|
|
|
450
457
|
*/
|
|
451
458
|
declare function useConversation(options: UseConversationOptions): UseConversationReturn;
|
|
452
459
|
|
|
453
|
-
export { type AIAdapterError, AIClient, type AIModelConfig, type AIProvider, BaseModelProvider, type ChatCompletionOptions, type ChatCompletionRequest, type ChatCompletionResponse, type ChatCompletionResponseChoice, type ChatCompletionResponseMessage, type ChatCompletionResponseUsage, type ChatCompletionStreamResponse, type ChatCompletionStreamResponseChoice, type ChatCompletionStreamResponseDelta, type ChatHistory, type ChatMessage, type Conversation, type ConversationState, type ConversationStorageStrategy, ErrorType, FinalStatus, GeneratingStatus, LocalStorageStrategy, type MessageRole, type MessageState, OpenAIProvider, STATUS, StreamEventType, type StreamHandler, type UseConversationOptions, type UseConversationReturn, type UseMessageOptions, type UseMessageReturn, extractTextFromResponse, formatMessages, useConversation, useMessage };
|
|
460
|
+
export { type AIAdapterError, AIClient, type AIModelConfig, type AIProvider, BaseModelProvider, type ChatCompletionOptions, type ChatCompletionRequest, type ChatCompletionResponse, type ChatCompletionResponseChoice, type ChatCompletionResponseMessage, type ChatCompletionResponseUsage, type ChatCompletionStreamResponse, type ChatCompletionStreamResponseChoice, type ChatCompletionStreamResponseDelta, type ChatHistory, type ChatMessage, type Conversation, type ConversationState, type ConversationStorageStrategy, ErrorType, FinalStatus, GeneratingStatus, LocalStorageStrategy, type MessageRole, type MessageState, OpenAIProvider, STATUS, StreamEventType, type StreamHandler, type UseConversationOptions, type UseConversationReturn, type UseMessageOptions, type UseMessageReturn, extractTextFromResponse, formatMessages, handleSSEStream, useConversation, useMessage };
|
package/dist/index.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
"use strict";var
|
|
1
|
+
"use strict";var x=Object.defineProperty;var B=Object.getOwnPropertyDescriptor;var H=Object.getOwnPropertyNames;var j=Object.prototype.hasOwnProperty;var $=(s,e)=>{for(var t in e)x(s,t,{get:e[t],enumerable:!0})},L=(s,e,t,a)=>{if(e&&typeof e=="object"||typeof e=="function")for(let d of H(e))!j.call(s,d)&&d!==t&&x(s,d,{get:()=>e[d],enumerable:!(a=B(e,d))||a.enumerable});return s};var F=s=>L(x({},"__esModule",{value:!0}),s);var z={};$(z,{AIClient:()=>A,BaseModelProvider:()=>S,ErrorType:()=>U,FinalStatus:()=>G,GeneratingStatus:()=>q,LocalStorageStrategy:()=>E,OpenAIProvider:()=>R,STATUS:()=>K,StreamEventType:()=>D,extractTextFromResponse:()=>k,formatMessages:()=>_,handleSSEStream:()=>y,useConversation:()=>J,useMessage:()=>w});module.exports=F(z);var S=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 U=(p=>(p.NETWORK_ERROR="network_error",p.AUTHENTICATION_ERROR="authentication_error",p.RATE_LIMIT_ERROR="rate_limit_error",p.SERVER_ERROR="server_error",p.MODEL_ERROR="model_error",p.TIMEOUT_ERROR="timeout_error",p.UNKNOWN_ERROR="unknown_error",p))(U||{}),D=(a=>(a.DATA="data",a.ERROR="error",a.DONE="done",a))(D||{});function v(s){return{type:s.type||"unknown_error",message:s.message||"\u672A\u77E5\u9519\u8BEF",statusCode:s.statusCode,originalError:s.originalError}}function O(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 y(s,e,t){let a=s.body?.getReader();if(!a)throw new Error("Response body is null");let d=new TextDecoder,i="";t&&t.addEventListener("abort",()=>{a.cancel().catch(o=>console.error("Error cancelling reader:",o))},{once:!0});try{for(;;){if(t?.aborted){await a.cancel();break}let{done:o,value:p}=await a.read();if(o)break;let u=d.decode(p,{stream:!0});i+=u;let c=i.split(`
|
|
2
2
|
|
|
3
|
-
`);i=c.pop()||"";for(let h of c)if(h.trim()!==""){if(h.trim()==="data: [DONE]"){e.onDone();continue}try{let m=h.match(/^data: (.+)$/m);if(!m)continue;let M=JSON.parse(m[1]);e.onData(M)}catch(m){console.error("Error parsing SSE message:",m)}}}(i.trim()==="data: [DONE]"||t?.aborted)&&e.onDone()}catch(o){if(t?.aborted)return;throw o}}function _(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 k(s){return!s.choices||!s.choices.length?"":s.choices[0].message?.content||""}var R=class extends S{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 a={model:t.options?.model||this.config.defaultModel||this.defaultModel,messages:t.messages,...t.options,stream:!1},d={method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(a)};this.apiKey&&Object.assign(d.headers,{Authorization:`Bearer ${this.apiKey}`});let i=await fetch(`${this.baseURL}/chat/completions`,d);if(!i.ok){let o=await i.text();throw new Error(`HTTP error! status: ${i.status}, details: ${o}`)}return await i.json()}catch(a){throw
|
|
3
|
+
`);i=c.pop()||"";for(let h of c)if(h.trim()!==""){if(h.trim()==="data: [DONE]"){e.onDone();continue}try{let m=h.match(/^data: (.+)$/m);if(!m)continue;let M=JSON.parse(m[1]);e.onData(M)}catch(m){console.error("Error parsing SSE message:",m)}}}(i.trim()==="data: [DONE]"||t?.aborted)&&e.onDone()}catch(o){if(t?.aborted)return;throw o}}function _(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 k(s){return!s.choices||!s.choices.length?"":s.choices[0].message?.content||""}var R=class extends S{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 a={model:t.options?.model||this.config.defaultModel||this.defaultModel,messages:t.messages,...t.options,stream:!1},d={method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(a)};this.apiKey&&Object.assign(d.headers,{Authorization:`Bearer ${this.apiKey}`});let i=await fetch(`${this.baseURL}/chat/completions`,d);if(!i.ok){let o=await i.text();throw new Error(`HTTP error! status: ${i.status}, details: ${o}`)}return await i.json()}catch(a){throw O(a)}}async chatStream(t,a){let{signal:d,...i}=t.options||{};try{this.validateRequest(t);let o={model:t.options?.model||this.config.defaultModel||this.defaultModel,messages:t.messages,...i,stream:!0},p={method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${this.apiKey}`,Accept:"text/event-stream"},body:JSON.stringify(o),signal:d};this.apiKey&&Object.assign(p.headers,{Authorization:`Bearer ${this.apiKey}`});let u=await fetch(`${this.baseURL}/chat/completions`,p);if(!u.ok){let c=await u.text();throw new Error(`HTTP error! status: ${u.status}, details: ${c}`)}await y(u,a,d)}catch(o){if(d?.aborted)return;a.onError(O(o))}}updateConfig(t){super.updateConfig(t),t.apiUrl&&(this.baseURL=t.apiUrl),t.apiKey&&(this.apiKey=t.apiKey),t.defaultModel&&(this.defaultModel=t.defaultModel)}};var A=class{constructor(e){this.config=e,this.provider=this.createProvider(e)}createProvider(e){if(e.provider==="custom"&&"providerImplementation"in e)return e.providerImplementation;switch(e.provider){case"deepseek":let t={defaultModel:"deepseek-chat",apiUrl:"https://api.deepseek.com/v1"};return new R({...t,...e});case"openai":default:return new R(e)}}async chat(e){return this.provider.chat(e)}async chatStream(e,t){let a={...e,options:{...e.options,stream:!0}};return this.provider.chatStream(a,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 C=require("vue"),K=(o=>(o.INIT="init",o.PROCESSING="processing",o.STREAMING="streaming",o.FINISHED="finished",o.ABORTED="aborted",o.ERROR="error",o))(K||{}),q=["processing","streaming"],G=["finished","aborted","error"];function w(s){let{client:e,useStreamByDefault:t=!0,errorMessage:a="\u8BF7\u6C42\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5",initialMessages:d=[]}=s,i=(0,C.ref)([...d]),o=(0,C.ref)(""),p=(0,C.ref)(t),u=null,c=(0,C.reactive)({status:"init",errorMsg:null}),h=async r=>{let g={role:"assistant",content:(await e.chat({messages:(0,C.toRaw)(i.value),options:{stream:!1,signal:r.signal}})).choices[0].message.content};i.value.push(g)},m=async r=>{await e.chatStream({messages:(0,C.toRaw)(i.value),options:{stream:!0,signal:r.signal}},{onData:n=>{c.status="streaming",i.value[i.value.length-1].role==="user"&&i.value.push({role:"assistant",content:""});let g=n.choices?.[0];g&&g.delta.content&&(i.value[i.value.length-1].content+=g.delta.content)},onError:n=>{c.status="error",c.errorMsg=a,console.error("Stream request error:",n)},onDone:()=>{c.status="finished"}})},M=async()=>{c.status="processing",c.errorMsg=null,u=new AbortController;try{p.value?await m(u):await h(u),c.status="finished"}catch(r){c.errorMsg=a,c.status="error",console.error("Send message error:",r)}finally{u=null}};return{messages:i,messageState:c,inputMessage:o,useStream:p,sendMessage:async(r=o.value,n=!0)=>{if(!r?.trim()||q.includes(c.status))return;let g={role:"user",content:r};i.value.push(g),n&&(o.value=""),await M()},clearMessages:()=>{i.value=[],c.errorMsg=null},addMessage:r=>{i.value.push(r)},abortRequest:()=>{u&&(u.abort(),u=null,c.status="aborted")},retryRequest:async r=>{r===0||!i.value[r]||i.value[r].role==="user"||(i.value.splice(r),await M())}}}var I=require("vue");var E=class{constructor(e="tiny-robot-ai-conversations"){this.storageKey=e}saveConversations(e){try{localStorage.setItem(this.storageKey,JSON.stringify(e))}catch(t){console.error("\u4FDD\u5B58\u4F1A\u8BDD\u5931\u8D25:",t)}}loadConversations(){try{let e=localStorage.getItem(this.storageKey);return e?JSON.parse(e):[]}catch(e){return console.error("\u52A0\u8F7D\u4F1A\u8BDD\u5931\u8D25:",e),[]}}};function W(){return Date.now().toString(36)+Math.random().toString(36).substring(2,9)}function J(s){let{client:e,storage:t=new E,autoSave:a=!0,useStreamByDefault:d=!0,errorMessage:i="\u8BF7\u6C42\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5"}=s,o=(0,I.reactive)({conversations:[],currentId:null,loading:!1}),p=w({client:e,useStreamByDefault:d,errorMessage:i,initialMessages:[]});(0,I.watch)(()=>p.messages.value,l=>{if(o.currentId&&l.length>0){let r=o.conversations.findIndex(n=>n.id===o.currentId);r!==-1&&(o.conversations[r].messages=[...l],o.conversations[r].updatedAt=Date.now(),a&&f())}},{deep:!0});let u=(l="\u65B0\u4F1A\u8BDD",r={})=>{let n=W(),g={id:n,title:l,createdAt:Date.now(),updatedAt:Date.now(),messages:[],metadata:r};return o.conversations.unshift(g),c(n),a&&f(),n},c=l=>{let r=o.conversations.find(n=>n.id===l);r&&(o.currentId=l,p.clearMessages(),r.messages.length>0&&r.messages.forEach(n=>p.addMessage(n)))},h=l=>{let r=o.conversations.findIndex(n=>n.id===l);r!==-1&&(o.conversations.splice(r,1),o.currentId===l&&(o.conversations.length>0?c(o.conversations[0].id):(o.currentId=null,p.clearMessages())),a&&f())},m=(l,r)=>{let n=o.conversations.find(g=>g.id===l);n&&(n.title=r,n.updatedAt=Date.now(),a&&f())},M=(l,r)=>{let n=o.conversations.find(g=>g.id===l);n&&(n.metadata={...n.metadata,...r},n.updatedAt=Date.now(),a&&f())},f=async()=>{try{await t.saveConversations(o.conversations)}catch(l){console.error("\u4FDD\u5B58\u4F1A\u8BDD\u5931\u8D25:",l)}},b=async()=>{o.loading=!0;try{let l=await t.loadConversations();o.conversations=l,l.length>0&&!o.currentId&&c(l[0].id)}catch(l){console.error("\u52A0\u8F7D\u4F1A\u8BDD\u5931\u8D25:",l)}finally{o.loading=!1}},T=async l=>{let r=o.conversations.find(n=>n.id===l);if(!r||r.messages.length<2)return r?.title||"\u65B0\u4F1A\u8BDD";try{let n={role:"system",content:"\u8BF7\u6839\u636E\u4EE5\u4E0B\u5BF9\u8BDD\u5185\u5BB9\uFF0C\u751F\u6210\u4E00\u4E2A\u7B80\u77ED\u7684\u6807\u9898\uFF08\u4E0D\u8D85\u8FC720\u4E2A\u5B57\u7B26\uFF09\u3002\u53EA\u9700\u8981\u8FD4\u56DE\u6807\u9898\u6587\u672C\uFF0C\u4E0D\u9700\u8981\u4EFB\u4F55\u89E3\u91CA\u6216\u989D\u5916\u5185\u5BB9\u3002"},g=r.messages.slice(0,Math.min(4,r.messages.length)),N=(await e.chat({messages:[n,...g],options:{stream:!1,max_tokens:30}})).choices[0].message.content.trim();return m(l,N),N}catch(n){return console.error("\u751F\u6210\u6807\u9898\u5931\u8D25:",n),r.title}},P=()=>o.currentId&&o.conversations.find(l=>l.id===o.currentId)||null;return b(),{state:o,messageManager:p,createConversation:u,switchConversation:c,deleteConversation:h,updateTitle:m,updateMetadata:M,saveConversations:f,loadConversations:b,generateTitle:T,getCurrentConversation:P}}0&&(module.exports={AIClient,BaseModelProvider,ErrorType,FinalStatus,GeneratingStatus,LocalStorageStrategy,OpenAIProvider,STATUS,StreamEventType,extractTextFromResponse,formatMessages,handleSSEStream,useConversation,useMessage});
|
package/dist/index.mjs
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
var M=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 o of e.messages)if(!o.role||!o.content)throw new Error("\u6BCF\u6761\u6D88\u606F\u5FC5\u987B\u5305\u542B\u89D2\u8272\u548C\u5185\u5BB9")}};var
|
|
1
|
+
var M=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 o of e.messages)if(!o.role||!o.content)throw new Error("\u6BCF\u6761\u6D88\u606F\u5FC5\u987B\u5305\u542B\u89D2\u8272\u548C\u5185\u5BB9")}};var N=(p=>(p.NETWORK_ERROR="network_error",p.AUTHENTICATION_ERROR="authentication_error",p.RATE_LIMIT_ERROR="rate_limit_error",p.SERVER_ERROR="server_error",p.MODEL_ERROR="model_error",p.TIMEOUT_ERROR="timeout_error",p.UNKNOWN_ERROR="unknown_error",p))(N||{}),U=(l=>(l.DATA="data",l.ERROR="error",l.DONE="done",l))(U||{});function f(r){return{type:r.type||"unknown_error",message:r.message||"\u672A\u77E5\u9519\u8BEF",statusCode:r.statusCode,originalError:r.originalError}}function y(r){if(!r.response)return f({type:"network_error",message:"\u7F51\u7EDC\u8FDE\u63A5\u9519\u8BEF\uFF0C\u8BF7\u68C0\u67E5\u60A8\u7684\u7F51\u7EDC\u8FDE\u63A5",originalError:r});if(r.response){let{status:e,data:o}=r.response;return e===401||e===403?f({type:"authentication_error",message:"\u8EAB\u4EFD\u9A8C\u8BC1\u5931\u8D25\uFF0C\u8BF7\u68C0\u67E5\u60A8\u7684API\u5BC6\u94A5",statusCode:e,originalError:r}):e===429?f({type:"rate_limit_error",message:"\u8D85\u51FAAPI\u8C03\u7528\u9650\u5236\uFF0C\u8BF7\u7A0D\u540E\u518D\u8BD5",statusCode:e,originalError:r}):e>=500?f({type:"server_error",message:"\u670D\u52A1\u5668\u9519\u8BEF\uFF0C\u8BF7\u7A0D\u540E\u518D\u8BD5",statusCode:e,originalError:r}):f({type:"unknown_error",message:o?.error?.message||`\u8BF7\u6C42\u5931\u8D25\uFF0C\u72B6\u6001\u7801: ${e}`,statusCode:e,originalError:r})}return r.code==="ECONNABORTED"?f({type:"timeout_error",message:"\u8BF7\u6C42\u8D85\u65F6\uFF0C\u8BF7\u7A0D\u540E\u518D\u8BD5",originalError:r}):f({type:"unknown_error",message:r.message||"\u53D1\u751F\u672A\u77E5\u9519\u8BEF",originalError:r})}async function A(r,e,o){let l=r.body?.getReader();if(!l)throw new Error("Response body is null");let g=new TextDecoder,a="";o&&o.addEventListener("abort",()=>{l.cancel().catch(t=>console.error("Error cancelling reader:",t))},{once:!0});try{for(;;){if(o?.aborted){await l.cancel();break}let{done:t,value:p}=await l.read();if(t)break;let d=g.decode(p,{stream:!0});a+=d;let c=a.split(`
|
|
2
2
|
|
|
3
|
-
`);a=c.pop()||"";for(let C of c)if(C.trim()!==""){if(C.trim()==="data: [DONE]"){e.onDone();continue}try{let m=C.match(/^data: (.+)$/m);if(!m)continue;let v=JSON.parse(m[1]);e.onData(v)}catch(m){console.error("Error parsing SSE message:",m)}}}(a.trim()==="data: [DONE]"||o?.aborted)&&e.onDone()}catch(t){if(o?.aborted)return;throw t}}function D(r){return r.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 _(r){return!r.choices||!r.choices.length?"":r.choices[0].message?.content||""}var R=class extends M{constructor(o){super(o);this.defaultModel="gpt-3.5-turbo";this.baseURL=o.apiUrl||"https://api.openai.com/v1",this.apiKey=o.apiKey||"",o.defaultModel&&(this.defaultModel=o.defaultModel),this.apiKey||console.warn("API key is not provided. Authentication will likely fail.")}async chat(o){try{this.validateRequest(o);let l={model:o.options?.model||this.config.defaultModel||this.defaultModel,messages:o.messages,...o.options,stream:!1},g={method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(l)};this.apiKey&&Object.assign(g.headers,{Authorization:`Bearer ${this.apiKey}`});let a=await fetch(`${this.baseURL}/chat/completions`,g);if(!a.ok){let t=await a.text();throw new Error(`HTTP error! status: ${a.status}, details: ${t}`)}return await a.json()}catch(l){throw y(l)}}async chatStream(o,l){let{signal:g,...a}=o.options||{};try{this.validateRequest(o);let t={model:o.options?.model||this.config.defaultModel||this.defaultModel,messages:o.messages,...a,stream:!0},p={method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${this.apiKey}`,Accept:"text/event-stream"},body:JSON.stringify(t),signal:g};this.apiKey&&Object.assign(p.headers,{Authorization:`Bearer ${this.apiKey}`});let d=await fetch(`${this.baseURL}/chat/completions`,p);if(!d.ok){let c=await d.text();throw new Error(`HTTP error! status: ${d.status}, details: ${c}`)}await
|
|
3
|
+
`);a=c.pop()||"";for(let C of c)if(C.trim()!==""){if(C.trim()==="data: [DONE]"){e.onDone();continue}try{let m=C.match(/^data: (.+)$/m);if(!m)continue;let v=JSON.parse(m[1]);e.onData(v)}catch(m){console.error("Error parsing SSE message:",m)}}}(a.trim()==="data: [DONE]"||o?.aborted)&&e.onDone()}catch(t){if(o?.aborted)return;throw t}}function D(r){return r.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 _(r){return!r.choices||!r.choices.length?"":r.choices[0].message?.content||""}var R=class extends M{constructor(o){super(o);this.defaultModel="gpt-3.5-turbo";this.baseURL=o.apiUrl||"https://api.openai.com/v1",this.apiKey=o.apiKey||"",o.defaultModel&&(this.defaultModel=o.defaultModel),this.apiKey||console.warn("API key is not provided. Authentication will likely fail.")}async chat(o){try{this.validateRequest(o);let l={model:o.options?.model||this.config.defaultModel||this.defaultModel,messages:o.messages,...o.options,stream:!1},g={method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(l)};this.apiKey&&Object.assign(g.headers,{Authorization:`Bearer ${this.apiKey}`});let a=await fetch(`${this.baseURL}/chat/completions`,g);if(!a.ok){let t=await a.text();throw new Error(`HTTP error! status: ${a.status}, details: ${t}`)}return await a.json()}catch(l){throw y(l)}}async chatStream(o,l){let{signal:g,...a}=o.options||{};try{this.validateRequest(o);let t={model:o.options?.model||this.config.defaultModel||this.defaultModel,messages:o.messages,...a,stream:!0},p={method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${this.apiKey}`,Accept:"text/event-stream"},body:JSON.stringify(t),signal:g};this.apiKey&&Object.assign(p.headers,{Authorization:`Bearer ${this.apiKey}`});let d=await fetch(`${this.baseURL}/chat/completions`,p);if(!d.ok){let c=await d.text();throw new Error(`HTTP error! status: ${d.status}, details: ${c}`)}await A(d,l,g)}catch(t){if(g?.aborted)return;l.onError(y(t))}}updateConfig(o){super.updateConfig(o),o.apiUrl&&(this.baseURL=o.apiUrl),o.apiKey&&(this.apiKey=o.apiKey),o.defaultModel&&(this.defaultModel=o.defaultModel)}};var E=class{constructor(e){this.config=e,this.provider=this.createProvider(e)}createProvider(e){if(e.provider==="custom"&&"providerImplementation"in e)return e.providerImplementation;switch(e.provider){case"deepseek":let o={defaultModel:"deepseek-chat",apiUrl:"https://api.deepseek.com/v1"};return new R({...o,...e});case"openai":default:return new R(e)}}async chat(e){return this.provider.chat(e)}async chatStream(e,o){let l={...e,options:{...e.options,stream:!0}};return this.provider.chatStream(l,o)}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)}};import{reactive as k,ref as I,toRaw as T}from"vue";var K=(t=>(t.INIT="init",t.PROCESSING="processing",t.STREAMING="streaming",t.FINISHED="finished",t.ABORTED="aborted",t.ERROR="error",t))(K||{}),q=["processing","streaming"],te=["finished","aborted","error"];function P(r){let{client:e,useStreamByDefault:o=!0,errorMessage:l="\u8BF7\u6C42\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5",initialMessages:g=[]}=r,a=I([...g]),t=I(""),p=I(o),d=null,c=k({status:"init",errorMsg:null}),C=async s=>{let u={role:"assistant",content:(await e.chat({messages:T(a.value),options:{stream:!1,signal:s.signal}})).choices[0].message.content};a.value.push(u)},m=async s=>{await e.chatStream({messages:T(a.value),options:{stream:!0,signal:s.signal}},{onData:n=>{c.status="streaming",a.value[a.value.length-1].role==="user"&&a.value.push({role:"assistant",content:""});let u=n.choices?.[0];u&&u.delta.content&&(a.value[a.value.length-1].content+=u.delta.content)},onError:n=>{c.status="error",c.errorMsg=l,console.error("Stream request error:",n)},onDone:()=>{c.status="finished"}})},v=async()=>{c.status="processing",c.errorMsg=null,d=new AbortController;try{p.value?await m(d):await C(d),c.status="finished"}catch(s){c.errorMsg=l,c.status="error",console.error("Send message error:",s)}finally{d=null}};return{messages:a,messageState:c,inputMessage:t,useStream:p,sendMessage:async(s=t.value,n=!0)=>{if(!s?.trim()||q.includes(c.status))return;let u={role:"user",content:s};a.value.push(u),n&&(t.value=""),await v()},clearMessages:()=>{a.value=[],c.errorMsg=null},addMessage:s=>{a.value.push(s)},abortRequest:()=>{d&&(d.abort(),d=null,c.status="aborted")},retryRequest:async s=>{s===0||!a.value[s]||a.value[s].role==="user"||(a.value.splice(s),await v())}}}import{reactive as B,watch as H}from"vue";var b=class{constructor(e="tiny-robot-ai-conversations"){this.storageKey=e}saveConversations(e){try{localStorage.setItem(this.storageKey,JSON.stringify(e))}catch(o){console.error("\u4FDD\u5B58\u4F1A\u8BDD\u5931\u8D25:",o)}}loadConversations(){try{let e=localStorage.getItem(this.storageKey);return e?JSON.parse(e):[]}catch(e){return console.error("\u52A0\u8F7D\u4F1A\u8BDD\u5931\u8D25:",e),[]}}};function j(){return Date.now().toString(36)+Math.random().toString(36).substring(2,9)}function ne(r){let{client:e,storage:o=new b,autoSave:l=!0,useStreamByDefault:g=!0,errorMessage:a="\u8BF7\u6C42\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5"}=r,t=B({conversations:[],currentId:null,loading:!1}),p=P({client:e,useStreamByDefault:g,errorMessage:a,initialMessages:[]});H(()=>p.messages.value,i=>{if(t.currentId&&i.length>0){let s=t.conversations.findIndex(n=>n.id===t.currentId);s!==-1&&(t.conversations[s].messages=[...i],t.conversations[s].updatedAt=Date.now(),l&&h())}},{deep:!0});let d=(i="\u65B0\u4F1A\u8BDD",s={})=>{let n=j(),u={id:n,title:i,createdAt:Date.now(),updatedAt:Date.now(),messages:[],metadata:s};return t.conversations.unshift(u),c(n),l&&h(),n},c=i=>{let s=t.conversations.find(n=>n.id===i);s&&(t.currentId=i,p.clearMessages(),s.messages.length>0&&s.messages.forEach(n=>p.addMessage(n)))},C=i=>{let s=t.conversations.findIndex(n=>n.id===i);s!==-1&&(t.conversations.splice(s,1),t.currentId===i&&(t.conversations.length>0?c(t.conversations[0].id):(t.currentId=null,p.clearMessages())),l&&h())},m=(i,s)=>{let n=t.conversations.find(u=>u.id===i);n&&(n.title=s,n.updatedAt=Date.now(),l&&h())},v=(i,s)=>{let n=t.conversations.find(u=>u.id===i);n&&(n.metadata={...n.metadata,...s},n.updatedAt=Date.now(),l&&h())},h=async()=>{try{await o.saveConversations(t.conversations)}catch(i){console.error("\u4FDD\u5B58\u4F1A\u8BDD\u5931\u8D25:",i)}},S=async()=>{t.loading=!0;try{let i=await o.loadConversations();t.conversations=i,i.length>0&&!t.currentId&&c(i[0].id)}catch(i){console.error("\u52A0\u8F7D\u4F1A\u8BDD\u5931\u8D25:",i)}finally{t.loading=!1}},x=async i=>{let s=t.conversations.find(n=>n.id===i);if(!s||s.messages.length<2)return s?.title||"\u65B0\u4F1A\u8BDD";try{let n={role:"system",content:"\u8BF7\u6839\u636E\u4EE5\u4E0B\u5BF9\u8BDD\u5185\u5BB9\uFF0C\u751F\u6210\u4E00\u4E2A\u7B80\u77ED\u7684\u6807\u9898\uFF08\u4E0D\u8D85\u8FC720\u4E2A\u5B57\u7B26\uFF09\u3002\u53EA\u9700\u8981\u8FD4\u56DE\u6807\u9898\u6587\u672C\uFF0C\u4E0D\u9700\u8981\u4EFB\u4F55\u89E3\u91CA\u6216\u989D\u5916\u5185\u5BB9\u3002"},u=s.messages.slice(0,Math.min(4,s.messages.length)),w=(await e.chat({messages:[n,...u],options:{stream:!1,max_tokens:30}})).choices[0].message.content.trim();return m(i,w),w}catch(n){return console.error("\u751F\u6210\u6807\u9898\u5931\u8D25:",n),s.title}},O=()=>t.currentId&&t.conversations.find(i=>i.id===t.currentId)||null;return S(),{state:t,messageManager:p,createConversation:d,switchConversation:c,deleteConversation:C,updateTitle:m,updateMetadata:v,saveConversations:h,loadConversations:S,generateTitle:x,getCurrentConversation:O}}export{E as AIClient,M as BaseModelProvider,N as ErrorType,te as FinalStatus,q as GeneratingStatus,b as LocalStorageStrategy,R as OpenAIProvider,K as STATUS,U as StreamEventType,_ as extractTextFromResponse,D as formatMessages,A as handleSSEStream,ne as useConversation,P as useMessage};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@opentiny/tiny-robot-kit",
|
|
3
|
-
"version": "0.2.0-alpha.
|
|
3
|
+
"version": "0.2.0-alpha.9",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"access": "public"
|
|
6
6
|
},
|
|
@@ -26,5 +26,5 @@
|
|
|
26
26
|
"peerDependencies": {
|
|
27
27
|
"vue": ">=3.0.0"
|
|
28
28
|
},
|
|
29
|
-
"gitHead": "
|
|
29
|
+
"gitHead": "824d6e634a32bec8e702089cc4507c10a6feadc0"
|
|
30
30
|
}
|