@opentiny/tiny-robot-kit 0.3.0-rc.5 → 0.3.0-rc.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.mts CHANGED
@@ -421,6 +421,9 @@ interface ConversationState {
421
421
  /** 是否正在加载 */
422
422
  loading: boolean;
423
423
  }
424
+ type UseConversationEvents = UseMessageOptions['events'] & {
425
+ onLoaded?: (conversations: Conversation[]) => void;
426
+ };
424
427
  /**
425
428
  * useConversation选项接口
426
429
  */
@@ -437,7 +440,8 @@ interface UseConversationOptions {
437
440
  useStreamByDefault?: boolean;
438
441
  /** 错误消息模板 */
439
442
  errorMessage?: string;
440
- events?: UseMessageOptions['events'];
443
+ /** 事件回调 */
444
+ events?: UseConversationEvents;
441
445
  }
442
446
  /**
443
447
  * useConversation返回值接口
@@ -475,4 +479,4 @@ interface UseConversationReturn {
475
479
  */
476
480
  declare function useConversation(options: UseConversationOptions): UseConversationReturn;
477
481
 
478
- 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 };
482
+ 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 UseConversationEvents, type UseConversationOptions, type UseConversationReturn, type UseMessageOptions, type UseMessageReturn, extractTextFromResponse, formatMessages, handleSSEStream, useConversation, useMessage };
package/dist/index.d.ts CHANGED
@@ -421,6 +421,9 @@ interface ConversationState {
421
421
  /** 是否正在加载 */
422
422
  loading: boolean;
423
423
  }
424
+ type UseConversationEvents = UseMessageOptions['events'] & {
425
+ onLoaded?: (conversations: Conversation[]) => void;
426
+ };
424
427
  /**
425
428
  * useConversation选项接口
426
429
  */
@@ -437,7 +440,8 @@ interface UseConversationOptions {
437
440
  useStreamByDefault?: boolean;
438
441
  /** 错误消息模板 */
439
442
  errorMessage?: string;
440
- events?: UseMessageOptions['events'];
443
+ /** 事件回调 */
444
+ events?: UseConversationEvents;
441
445
  }
442
446
  /**
443
447
  * useConversation返回值接口
@@ -475,4 +479,4 @@ interface UseConversationReturn {
475
479
  */
476
480
  declare function useConversation(options: UseConversationOptions): UseConversationReturn;
477
481
 
478
- 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 };
482
+ 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 UseConversationEvents, 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 P=Object.defineProperty;var $=Object.getOwnPropertyDescriptor;var F=Object.getOwnPropertyNames;var L=Object.prototype.hasOwnProperty;var G=(o,e)=>{for(var t in e)P(o,t,{get:e[t],enumerable:!0})},W=(o,e,t,a)=>{if(e&&typeof e=="object"||typeof e=="function")for(let g of F(e))!L.call(o,g)&&g!==t&&P(o,g,{get:()=>e[g],enumerable:!(a=$(e,g))||a.enumerable});return o};var J=o=>W(P({},"__esModule",{value:!0}),o);var X={};G(X,{AIClient:()=>x,BaseModelProvider:()=>I,ErrorType:()=>K,FinalStatus:()=>z,GeneratingStatus:()=>U,LocalStorageStrategy:()=>O,OpenAIProvider:()=>A,STATUS:()=>j,StreamEventType:()=>q,extractTextFromResponse:()=>H,formatMessages:()=>B,handleSSEStream:()=>b,useConversation:()=>Q,useMessage:()=>N});module.exports=J(X);var I=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 K=(s=>(s.NETWORK_ERROR="network_error",s.AUTHENTICATION_ERROR="authentication_error",s.RATE_LIMIT_ERROR="rate_limit_error",s.SERVER_ERROR="server_error",s.MODEL_ERROR="model_error",s.TIMEOUT_ERROR="timeout_error",s.UNKNOWN_ERROR="unknown_error",s))(K||{}),q=(a=>(a.DATA="data",a.ERROR="error",a.DONE="done",a))(q||{});function y(o){return{type:o.type||"unknown_error",message:o.message||"\u672A\u77E5\u9519\u8BEF",statusCode:o.statusCode,originalError:o.originalError}}function D(o){if(!o.response)return y({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:e,data:t}=o.response;return e===401||e===403?y({type:"authentication_error",message:"\u8EAB\u4EFD\u9A8C\u8BC1\u5931\u8D25\uFF0C\u8BF7\u68C0\u67E5\u60A8\u7684API\u5BC6\u94A5",statusCode:e,originalError:o}):e===429?y({type:"rate_limit_error",message:"\u8D85\u51FAAPI\u8C03\u7528\u9650\u5236\uFF0C\u8BF7\u7A0D\u540E\u518D\u8BD5",statusCode:e,originalError:o}):e>=500?y({type:"server_error",message:"\u670D\u52A1\u5668\u9519\u8BEF\uFF0C\u8BF7\u7A0D\u540E\u518D\u8BD5",statusCode:e,originalError:o}):y({type:"unknown_error",message:t?.error?.message||`\u8BF7\u6C42\u5931\u8D25\uFF0C\u72B6\u6001\u7801: ${e}`,statusCode:e,originalError:o})}return o.code==="ECONNABORTED"?y({type:"timeout_error",message:"\u8BF7\u6C42\u8D85\u65F6\uFF0C\u8BF7\u7A0D\u540E\u518D\u8BD5",originalError:o}):y({type:"unknown_error",message:o.message||"\u53D1\u751F\u672A\u77E5\u9519\u8BEF",originalError:o})}async function b(o,e,t){let a=o.body?.getReader();if(!a)throw new Error("Response body is null");let g=new TextDecoder,n="",p,s;t&&t.addEventListener("abort",()=>{a.cancel().catch(c=>console.error("Error cancelling reader:",c))},{once:!0});try{for(;;){if(t?.aborted){await a.cancel();break}let{done:c,value:u}=await a.read();if(c)break;let v=g.decode(u,{stream:!0});n+=v;let E=n.split(`
1
+ "use strict";var T=Object.defineProperty;var L=Object.getOwnPropertyDescriptor;var $=Object.getOwnPropertyNames;var G=Object.prototype.hasOwnProperty;var W=(r,e)=>{for(var t in e)T(r,t,{get:e[t],enumerable:!0})},J=(r,e,t,i)=>{if(e&&typeof e=="object"||typeof e=="function")for(let u of $(e))!G.call(r,u)&&u!==t&&T(r,u,{get:()=>e[u],enumerable:!(i=L(e,u))||i.enumerable});return r};var z=r=>J(T({},"__esModule",{value:!0}),r);var Y={};W(Y,{AIClient:()=>b,BaseModelProvider:()=>E,ErrorType:()=>q,FinalStatus:()=>V,GeneratingStatus:()=>P,LocalStorageStrategy:()=>x,OpenAIProvider:()=>S,STATUS:()=>F,StreamEventType:()=>B,extractTextFromResponse:()=>j,formatMessages:()=>H,handleSSEStream:()=>I,useConversation:()=>X,useMessage:()=>U});module.exports=z(Y);var E=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 q=(d=>(d.NETWORK_ERROR="network_error",d.AUTHENTICATION_ERROR="authentication_error",d.RATE_LIMIT_ERROR="rate_limit_error",d.SERVER_ERROR="server_error",d.MODEL_ERROR="model_error",d.TIMEOUT_ERROR="timeout_error",d.UNKNOWN_ERROR="unknown_error",d))(q||{}),B=(i=>(i.DATA="data",i.ERROR="error",i.DONE="done",i))(B||{});function y(r){return{type:r.type||"unknown_error",message:r.message||"\u672A\u77E5\u9519\u8BEF",statusCode:r.statusCode,originalError:r.originalError}}function D(r){if(!r.response)return y({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:t}=r.response;return e===401||e===403?y({type:"authentication_error",message:"\u8EAB\u4EFD\u9A8C\u8BC1\u5931\u8D25\uFF0C\u8BF7\u68C0\u67E5\u60A8\u7684API\u5BC6\u94A5",statusCode:e,originalError:r}):e===429?y({type:"rate_limit_error",message:"\u8D85\u51FAAPI\u8C03\u7528\u9650\u5236\uFF0C\u8BF7\u7A0D\u540E\u518D\u8BD5",statusCode:e,originalError:r}):e>=500?y({type:"server_error",message:"\u670D\u52A1\u5668\u9519\u8BEF\uFF0C\u8BF7\u7A0D\u540E\u518D\u8BD5",statusCode:e,originalError:r}):y({type:"unknown_error",message:t?.error?.message||`\u8BF7\u6C42\u5931\u8D25\uFF0C\u72B6\u6001\u7801: ${e}`,statusCode:e,originalError:r})}return r.code==="ECONNABORTED"?y({type:"timeout_error",message:"\u8BF7\u6C42\u8D85\u65F6\uFF0C\u8BF7\u7A0D\u540E\u518D\u8BD5",originalError:r}):y({type:"unknown_error",message:r.message||"\u53D1\u751F\u672A\u77E5\u9519\u8BEF",originalError:r})}async function I(r,e,t){let i=r.body?.getReader();if(!i)throw new Error("Response body is null");let u=new TextDecoder,a="",c,d;t&&t.addEventListener("abort",()=>{i.cancel().catch(o=>console.error("Error cancelling reader:",o))},{once:!0});try{for(;;){if(t?.aborted){await i.cancel();break}let{done:o,value:p}=await i.read();if(o)break;let m=u.decode(p,{stream:!0});a+=m;let A=a.split(`
2
2
 
3
- `);n=E.pop()||"";for(let R of E)if(R.trim()!==""){if(R.trim()==="data: [DONE]"){s&&(p=s),e.onDone(p);continue}try{let M=R.match(/^data: (.+)$/m);if(!M)continue;let f=JSON.parse(M[1]);e.onData(f),s=f.choices?.[0]?.finish_reason||void 0}catch(M){console.error("Error parsing SSE message:",M)}}}(n.trim()==="data: [DONE]"||t?.aborted)&&(t?.aborted&&(p="aborted"),e.onDone(p))}catch(c){if(t?.aborted)return;throw c}}function B(o){return o.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 H(o){return!o.choices||!o.choices.length?"":o.choices[0].message?.content||""}var A=class extends I{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},g={method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(a)};this.apiKey&&Object.assign(g.headers,{Authorization:`Bearer ${this.apiKey}`});let n=await fetch(`${this.baseURL}/chat/completions`,g);if(!n.ok){let p=await n.text();throw new Error(`HTTP error! status: ${n.status}, details: ${p}`)}return await n.json()}catch(a){throw D(a)}}async chatStream(t,a){let{signal:g,...n}=t.options||{};try{this.validateRequest(t);let p={model:t.options?.model||this.config.defaultModel||this.defaultModel,messages:t.messages,...n,stream:!0},s={method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${this.apiKey}`,Accept:"text/event-stream"},body:JSON.stringify(p),signal:g};this.apiKey&&Object.assign(s.headers,{Authorization:`Bearer ${this.apiKey}`});let c=await fetch(`${this.baseURL}/chat/completions`,s);if(!c.ok){let u=await c.text();throw new Error(`HTTP error! status: ${c.status}, details: ${u}`)}await b(c,a,g)}catch(p){if(g?.aborted)return;a.onError(D(p))}}updateConfig(t){super.updateConfig(t),t.apiUrl&&(this.baseURL=t.apiUrl),t.apiKey&&(this.apiKey=t.apiKey),t.defaultModel&&(this.defaultModel=t.defaultModel)}};var x=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 A({...t,...e});case"openai":default:return new A(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"),j=(p=>(p.INIT="init",p.PROCESSING="processing",p.STREAMING="streaming",p.FINISHED="finished",p.ABORTED="aborted",p.ERROR="error",p))(j||{}),U=["processing","streaming"],z=["finished","aborted","error"];function N(o){let{client:e,useStreamByDefault:t=!0,errorMessage:a="\u8BF7\u6C42\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5",initialMessages:g=[]}=o,n=(0,C.ref)([...g]),p=(0,C.ref)(""),s=(0,C.ref)(t),c=null,u=(0,C.reactive)({status:"init",errorMsg:null}),v=r=>{let m=o.events?.onReceiveData,h=!1;if(m&&m(r,n,()=>{h=!0}),!h){let S={role:"assistant",content:r.choices[0].message.content};n.value.push(S)}},E=async r=>{let m=await e.chat({messages:(0,C.toRaw)(n.value),options:{stream:!1,signal:r.signal}});v(m)},R=r=>{let m=o.events?.onReceiveData,h=!1;if(m&&m(r,n,()=>{h=!0}),!h){n.value[n.value.length-1].role==="user"&&n.value.push({role:"assistant",content:""});let S=r.choices?.[0];S&&S.delta.content&&(n.value[n.value.length-1].content+=S.delta.content)}},M=async r=>{await e.chatStream({messages:(0,C.toRaw)(n.value),options:{stream:!0,signal:r.signal}},{onData:m=>{u.status="streaming",R(m)},onError:m=>{u.status="error",u.errorMsg=a,console.error("Stream request error:",m)},onDone:m=>{let h=o.events?.onFinish,S=!1;if(h&&h(m,{messages:n,messageState:u},()=>{S=!0}),!S){if(m==="aborted"||u.status==="aborted")return;u.status="finished"}}})},f=async()=>{u.status="processing",u.errorMsg=null,c=new AbortController;try{s.value?await M(c):await E(c)}catch(r){u.errorMsg=a,u.status="error",console.error("Send message error:",r)}finally{c=null}};return{messages:n,messageState:u,inputMessage:p,useStream:s,sendMessage:async(r=p.value,m=!0)=>{if(U.includes(u.status)||!r||typeof r=="string"&&!r.trim()||Array.isArray(r)&&r.length===0)return;let h={role:"user",content:r};n.value.push(h),m&&(p.value=""),await f()},send:async()=>{U.includes(u.status)||await f()},clearMessages:()=>{n.value=[],u.errorMsg=null},addMessage:r=>{Array.isArray(r)?n.value.push(...r):n.value.push(r)},abortRequest:()=>{c&&(c.abort(),c=null,u.status="aborted")},retryRequest:async r=>{r===0||!n.value[r]||n.value[r].role==="user"||(n.value.splice(r),await f())}}}var w=require("vue");var O=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 V(){return Date.now().toString(36)+Math.random().toString(36).substring(2,9)}function Q(o){let{client:e,storage:t=new O,autoSave:a=!0,allowEmpty:g=!1,useStreamByDefault:n=!0,errorMessage:p="\u8BF7\u6C42\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5"}=o,s=(0,w.reactive)({conversations:[],currentId:null,loading:!1}),c=N({client:e,useStreamByDefault:n,errorMessage:p,initialMessages:[],events:o.events});(0,w.watch)(()=>c.messages.value,i=>{if(s.currentId&&i.length>0){let d=s.conversations.findIndex(l=>l.id===s.currentId);d!==-1&&(s.conversations[d].messages=[...i],s.conversations[d].updatedAt=Date.now(),a&&f())}},{deep:!0});let u=(i="\u65B0\u4F1A\u8BDD",d={})=>{if(!g&&c.messages.value.length===0&&s.currentId)return s.currentId;let l=V(),r={id:l,title:i,createdAt:Date.now(),updatedAt:Date.now(),messages:[],metadata:d};return s.conversations.unshift(r),v(l),a&&f(),l},v=i=>{let d=s.conversations.find(l=>l.id===i);d&&(s.currentId=i,c.clearMessages(),d.messages.length>0&&d.messages.forEach(l=>c.addMessage(l)))},E=i=>{let d=s.conversations.findIndex(l=>l.id===i);d!==-1&&(s.conversations.splice(d,1),s.currentId===i&&(s.conversations.length>0?v(s.conversations[0].id):(s.currentId=null,c.clearMessages())),a&&f())},R=(i,d)=>{let l=s.conversations.find(r=>r.id===i);l&&(l.title=d,l.updatedAt=Date.now(),a&&f())},M=(i,d)=>{let l=s.conversations.find(r=>r.id===i);l&&(l.metadata={...l.metadata,...d},l.updatedAt=Date.now(),a&&f())},f=async()=>{try{await t.saveConversations(s.conversations)}catch(i){console.error("\u4FDD\u5B58\u4F1A\u8BDD\u5931\u8D25:",i)}},T=async()=>{s.loading=!0;try{let i=await t.loadConversations();s.conversations=i,i.length>0&&!s.currentId&&v(i[0].id)}catch(i){console.error("\u52A0\u8F7D\u4F1A\u8BDD\u5931\u8D25:",i)}finally{s.loading=!1}},_=async i=>{let d=s.conversations.find(l=>l.id===i);if(!d||d.messages.length<2)return d?.title||"\u65B0\u4F1A\u8BDD";try{let l={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"},r=d.messages.slice(0,Math.min(4,d.messages.length)),h=(await e.chat({messages:[l,...r],options:{stream:!1,max_tokens:30}})).choices[0].message.content.trim();return R(i,h),h}catch(l){return console.error("\u751F\u6210\u6807\u9898\u5931\u8D25:",l),d.title}},k=()=>s.currentId&&s.conversations.find(i=>i.id===s.currentId)||null;return T(),{state:s,messageManager:c,createConversation:u,switchConversation:v,deleteConversation:E,updateTitle:R,updateMetadata:M,saveConversations:f,loadConversations:T,generateTitle:_,getCurrentConversation:k}}0&&(module.exports={AIClient,BaseModelProvider,ErrorType,FinalStatus,GeneratingStatus,LocalStorageStrategy,OpenAIProvider,STATUS,StreamEventType,extractTextFromResponse,formatMessages,handleSSEStream,useConversation,useMessage});
3
+ `);a=A.pop()||"";for(let f of A)if(f.trim()!==""){if(f.trim()==="data: [DONE]"){d&&(c=d),e.onDone(c);continue}try{let R=f.match(/^data: (.+)$/m);if(!R)continue;let h=JSON.parse(R[1]);e.onData(h),d=h.choices?.[0]?.finish_reason||void 0}catch(R){console.error("Error parsing SSE message:",R)}}}(a.trim()==="data: [DONE]"||t?.aborted)&&(t?.aborted&&(c="aborted"),e.onDone(c))}catch(o){if(t?.aborted)return;throw o}}function H(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 j(r){return!r.choices||!r.choices.length?"":r.choices[0].message?.content||""}var S=class extends E{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 i={model:t.options?.model||this.config.defaultModel||this.defaultModel,messages:t.messages,...t.options,stream:!1},u={method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(i)};this.apiKey&&Object.assign(u.headers,{Authorization:`Bearer ${this.apiKey}`});let a=await fetch(`${this.baseURL}/chat/completions`,u);if(!a.ok){let c=await a.text();throw new Error(`HTTP error! status: ${a.status}, details: ${c}`)}return await a.json()}catch(i){throw D(i)}}async chatStream(t,i){let{signal:u,...a}=t.options||{};try{this.validateRequest(t);let c={model:t.options?.model||this.config.defaultModel||this.defaultModel,messages:t.messages,...a,stream:!0},d={method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${this.apiKey}`,Accept:"text/event-stream"},body:JSON.stringify(c),signal:u};this.apiKey&&Object.assign(d.headers,{Authorization:`Bearer ${this.apiKey}`});let o=await fetch(`${this.baseURL}/chat/completions`,d);if(!o.ok){let p=await o.text();throw new Error(`HTTP error! status: ${o.status}, details: ${p}`)}await I(o,i,u)}catch(c){if(u?.aborted)return;i.onError(D(c))}}updateConfig(t){super.updateConfig(t),t.apiUrl&&(this.baseURL=t.apiUrl),t.apiKey&&(this.apiKey=t.apiKey),t.defaultModel&&(this.defaultModel=t.defaultModel)}};var b=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 S({...t,...e});case"openai":default:return new S(e)}}async chat(e){return this.provider.chat(e)}async chatStream(e,t){let i={...e,options:{...e.options,stream:!0}};return this.provider.chatStream(i,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 v=require("vue"),F=(c=>(c.INIT="init",c.PROCESSING="processing",c.STREAMING="streaming",c.FINISHED="finished",c.ABORTED="aborted",c.ERROR="error",c))(F||{}),P=["processing","streaming"],V=["finished","aborted","error"];function U(r){let{client:e,useStreamByDefault:t=!0,errorMessage:i="\u8BF7\u6C42\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5",initialMessages:u=[]}=r,a=(0,v.ref)([...u]),c=(0,v.ref)(""),d=(0,v.ref)(t),o=null,p=(0,v.reactive)({status:"init",errorMsg:null}),m=s=>{let n=r.events?.onReceiveData,g=!1;if(n&&n(s,a,()=>{g=!0}),!g){let C={role:"assistant",content:s.choices[0].message.content};a.value.push(C)}},A=async s=>{let n=await e.chat({messages:(0,v.toRaw)(a.value),options:{stream:!1,signal:s.signal}});m(n)},f=s=>{let n=r.events?.onReceiveData,g=!1;if(n&&n(s,a,()=>{g=!0}),!g){a.value[a.value.length-1].role==="user"&&a.value.push({role:"assistant",content:""});let C=s.choices?.[0];C&&C.delta.content&&(a.value[a.value.length-1].content+=C.delta.content)}},R=async s=>{await e.chatStream({messages:(0,v.toRaw)(a.value),options:{stream:!0,signal:s.signal}},{onData:n=>{p.status="streaming",f(n)},onError:n=>{p.status="error",p.errorMsg=i,console.error("Stream request error:",n)},onDone:n=>{let g=r.events?.onFinish,C=!1;if(g&&g(n,{messages:a,messageState:p},()=>{C=!0}),!C){if(n==="aborted"||p.status==="aborted")return;p.status="finished"}}})},h=async()=>{p.status="processing",p.errorMsg=null,o=new AbortController;try{d.value?await R(o):await A(o)}catch(s){p.errorMsg=i,p.status="error",console.error("Send message error:",s)}finally{o=null}};return{messages:a,messageState:p,inputMessage:c,useStream:d,sendMessage:async(s=c.value,n=!0)=>{if(P.includes(p.status)||!s||typeof s=="string"&&!s.trim()||Array.isArray(s)&&s.length===0)return;let g={role:"user",content:s};a.value.push(g),n&&(c.value=""),await h()},send:async()=>{P.includes(p.status)||await h()},clearMessages:()=>{a.value=[],p.errorMsg=null},addMessage:s=>{Array.isArray(s)?a.value.push(...s):a.value.push(s)},abortRequest:()=>{o&&(o.abort(),o=null,p.status="aborted")},retryRequest:async s=>{s===0||!a.value[s]||a.value[s].role==="user"||(a.value.splice(s),await h())}}}var O=require("vue");var x=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 Q(){return Date.now().toString(36)+Math.random().toString(36).substring(2,9)}function X(r){let{client:e,storage:t=new x,autoSave:i=!0,allowEmpty:u=!1,useStreamByDefault:a=!0,errorMessage:c="\u8BF7\u6C42\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5",events:d}=r,o=(0,O.reactive)({conversations:[],currentId:null,loading:!1}),p=!1,m=U({client:e,useStreamByDefault:a,errorMessage:c,initialMessages:[],events:{onReceiveData:d?.onReceiveData,onFinish:d?.onFinish}});(0,O.watch)(()=>m.messages.value,l=>{if(o.currentId&&l.length>0){let s=o.conversations.findIndex(n=>n.id===o.currentId);s!==-1&&(o.conversations[s].messages=[...l],o.conversations[s].updatedAt=Date.now(),i&&M())}},{deep:!0});let A=(l="\u65B0\u4F1A\u8BDD",s={})=>{if(!u&&m.messages.value.length===0&&o.currentId)return o.currentId;let n=Q(),g={id:n,title:l,createdAt:Date.now(),updatedAt:Date.now(),messages:[],metadata:s};return o.conversations.unshift(g),f(n),i&&M(),n},f=l=>{let s=o.conversations.find(n=>n.id===l);s&&(o.currentId=l,m.clearMessages(),s.messages.length>0&&s.messages.forEach(n=>m.addMessage(n)))},R=l=>{let s=o.conversations.findIndex(n=>n.id===l);s!==-1&&(o.conversations.splice(s,1),o.currentId===l&&(o.conversations.length>0?f(o.conversations[0].id):(o.currentId=null,m.clearMessages())),i&&M())},h=(l,s)=>{let n=o.conversations.find(g=>g.id===l);n&&(n.title=s,n.updatedAt=Date.now(),i&&M())},N=(l,s)=>{let n=o.conversations.find(g=>g.id===l);n&&(n.metadata={...n.metadata,...s},n.updatedAt=Date.now(),i&&M())},M=async()=>{try{await t.saveConversations(o.conversations)}catch(l){console.error("\u4FDD\u5B58\u4F1A\u8BDD\u5931\u8D25:",l)}},w=async()=>{o.loading=!0;try{let l=await t.loadConversations();o.conversations=l,l.length>0&&!o.currentId&&f(l[0].id),!p&&d?.onLoaded&&(p=!0,d.onLoaded(l))}catch(l){console.error("\u52A0\u8F7D\u4F1A\u8BDD\u5931\u8D25:",l)}finally{o.loading=!1}},_=async l=>{let s=o.conversations.find(n=>n.id===l);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"},g=s.messages.slice(0,Math.min(4,s.messages.length)),K=(await e.chat({messages:[n,...g],options:{stream:!1,max_tokens:30}})).choices[0].message.content.trim();return h(l,K),K}catch(n){return console.error("\u751F\u6210\u6807\u9898\u5931\u8D25:",n),s.title}},k=()=>o.currentId&&o.conversations.find(l=>l.id===o.currentId)||null;return w(),{state:o,messageManager:m,createConversation:A,switchConversation:f,deleteConversation:R,updateTitle:h,updateMetadata:N,saveConversations:M,loadConversations:w,generateTitle:_,getCurrentConversation:k}}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 E=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 k=(s=>(s.NETWORK_ERROR="network_error",s.AUTHENTICATION_ERROR="authentication_error",s.RATE_LIMIT_ERROR="rate_limit_error",s.SERVER_ERROR="server_error",s.MODEL_ERROR="model_error",s.TIMEOUT_ERROR="timeout_error",s.UNKNOWN_ERROR="unknown_error",s))(k||{}),K=(l=>(l.DATA="data",l.ERROR="error",l.DONE="done",l))(K||{});function S(o){return{type:o.type||"unknown_error",message:o.message||"\u672A\u77E5\u9519\u8BEF",statusCode:o.statusCode,originalError:o.originalError}}function b(o){if(!o.response)return S({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:e,data:t}=o.response;return e===401||e===403?S({type:"authentication_error",message:"\u8EAB\u4EFD\u9A8C\u8BC1\u5931\u8D25\uFF0C\u8BF7\u68C0\u67E5\u60A8\u7684API\u5BC6\u94A5",statusCode:e,originalError:o}):e===429?S({type:"rate_limit_error",message:"\u8D85\u51FAAPI\u8C03\u7528\u9650\u5236\uFF0C\u8BF7\u7A0D\u540E\u518D\u8BD5",statusCode:e,originalError:o}):e>=500?S({type:"server_error",message:"\u670D\u52A1\u5668\u9519\u8BEF\uFF0C\u8BF7\u7A0D\u540E\u518D\u8BD5",statusCode:e,originalError:o}):S({type:"unknown_error",message:t?.error?.message||`\u8BF7\u6C42\u5931\u8D25\uFF0C\u72B6\u6001\u7801: ${e}`,statusCode:e,originalError:o})}return o.code==="ECONNABORTED"?S({type:"timeout_error",message:"\u8BF7\u6C42\u8D85\u65F6\uFF0C\u8BF7\u7A0D\u540E\u518D\u8BD5",originalError:o}):S({type:"unknown_error",message:o.message||"\u53D1\u751F\u672A\u77E5\u9519\u8BEF",originalError:o})}async function x(o,e,t){let l=o.body?.getReader();if(!l)throw new Error("Response body is null");let h=new TextDecoder,n="",p,s;t&&t.addEventListener("abort",()=>{l.cancel().catch(c=>console.error("Error cancelling reader:",c))},{once:!0});try{for(;;){if(t?.aborted){await l.cancel();break}let{done:c,value:u}=await l.read();if(c)break;let C=h.decode(u,{stream:!0});n+=C;let y=n.split(`
1
+ var A=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 K=(d=>(d.NETWORK_ERROR="network_error",d.AUTHENTICATION_ERROR="authentication_error",d.RATE_LIMIT_ERROR="rate_limit_error",d.SERVER_ERROR="server_error",d.MODEL_ERROR="model_error",d.TIMEOUT_ERROR="timeout_error",d.UNKNOWN_ERROR="unknown_error",d))(K||{}),q=(l=>(l.DATA="data",l.ERROR="error",l.DONE="done",l))(q||{});function M(n){return{type:n.type||"unknown_error",message:n.message||"\u672A\u77E5\u9519\u8BEF",statusCode:n.statusCode,originalError:n.originalError}}function I(n){if(!n.response)return M({type:"network_error",message:"\u7F51\u7EDC\u8FDE\u63A5\u9519\u8BEF\uFF0C\u8BF7\u68C0\u67E5\u60A8\u7684\u7F51\u7EDC\u8FDE\u63A5",originalError:n});if(n.response){let{status:e,data:o}=n.response;return e===401||e===403?M({type:"authentication_error",message:"\u8EAB\u4EFD\u9A8C\u8BC1\u5931\u8D25\uFF0C\u8BF7\u68C0\u67E5\u60A8\u7684API\u5BC6\u94A5",statusCode:e,originalError:n}):e===429?M({type:"rate_limit_error",message:"\u8D85\u51FAAPI\u8C03\u7528\u9650\u5236\uFF0C\u8BF7\u7A0D\u540E\u518D\u8BD5",statusCode:e,originalError:n}):e>=500?M({type:"server_error",message:"\u670D\u52A1\u5668\u9519\u8BEF\uFF0C\u8BF7\u7A0D\u540E\u518D\u8BD5",statusCode:e,originalError:n}):M({type:"unknown_error",message:o?.error?.message||`\u8BF7\u6C42\u5931\u8D25\uFF0C\u72B6\u6001\u7801: ${e}`,statusCode:e,originalError:n})}return n.code==="ECONNABORTED"?M({type:"timeout_error",message:"\u8BF7\u6C42\u8D85\u65F6\uFF0C\u8BF7\u7A0D\u540E\u518D\u8BD5",originalError:n}):M({type:"unknown_error",message:n.message||"\u53D1\u751F\u672A\u77E5\u9519\u8BEF",originalError:n})}async function b(n,e,o){let l=n.body?.getReader();if(!l)throw new Error("Response body is null");let g=new TextDecoder,a="",c,d;o&&o.addEventListener("abort",()=>{l.cancel().catch(s=>console.error("Error cancelling reader:",s))},{once:!0});try{for(;;){if(o?.aborted){await l.cancel();break}let{done:s,value:p}=await l.read();if(s)break;let m=g.decode(p,{stream:!0});a+=m;let y=a.split(`
2
2
 
3
- `);n=y.pop()||"";for(let v of y)if(v.trim()!==""){if(v.trim()==="data: [DONE]"){s&&(p=s),e.onDone(p);continue}try{let R=v.match(/^data: (.+)$/m);if(!R)continue;let m=JSON.parse(R[1]);e.onData(m),s=m.choices?.[0]?.finish_reason||void 0}catch(R){console.error("Error parsing SSE message:",R)}}}(n.trim()==="data: [DONE]"||t?.aborted)&&(t?.aborted&&(p="aborted"),e.onDone(p))}catch(c){if(t?.aborted)return;throw c}}function q(o){return o.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 B(o){return!o.choices||!o.choices.length?"":o.choices[0].message?.content||""}var A=class extends E{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 l={model:t.options?.model||this.config.defaultModel||this.defaultModel,messages:t.messages,...t.options,stream:!1},h={method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(l)};this.apiKey&&Object.assign(h.headers,{Authorization:`Bearer ${this.apiKey}`});let n=await fetch(`${this.baseURL}/chat/completions`,h);if(!n.ok){let p=await n.text();throw new Error(`HTTP error! status: ${n.status}, details: ${p}`)}return await n.json()}catch(l){throw b(l)}}async chatStream(t,l){let{signal:h,...n}=t.options||{};try{this.validateRequest(t);let p={model:t.options?.model||this.config.defaultModel||this.defaultModel,messages:t.messages,...n,stream:!0},s={method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${this.apiKey}`,Accept:"text/event-stream"},body:JSON.stringify(p),signal:h};this.apiKey&&Object.assign(s.headers,{Authorization:`Bearer ${this.apiKey}`});let c=await fetch(`${this.baseURL}/chat/completions`,s);if(!c.ok){let u=await c.text();throw new Error(`HTTP error! status: ${c.status}, details: ${u}`)}await x(c,l,h)}catch(p){if(h?.aborted)return;l.onError(b(p))}}updateConfig(t){super.updateConfig(t),t.apiUrl&&(this.baseURL=t.apiUrl),t.apiKey&&(this.apiKey=t.apiKey),t.defaultModel&&(this.defaultModel=t.defaultModel)}};var O=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 A({...t,...e});case"openai":default:return new A(e)}}async chat(e){return this.provider.chat(e)}async chatStream(e,t){let l={...e,options:{...e.options,stream:!0}};return this.provider.chatStream(l,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)}};import{reactive as H,ref as w,toRaw as U}from"vue";var j=(p=>(p.INIT="init",p.PROCESSING="processing",p.STREAMING="streaming",p.FINISHED="finished",p.ABORTED="aborted",p.ERROR="error",p))(j||{}),N=["processing","streaming"],oe=["finished","aborted","error"];function _(o){let{client:e,useStreamByDefault:t=!0,errorMessage:l="\u8BF7\u6C42\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5",initialMessages:h=[]}=o,n=w([...h]),p=w(""),s=w(t),c=null,u=H({status:"init",errorMsg:null}),C=r=>{let g=o.events?.onReceiveData,f=!1;if(g&&g(r,n,()=>{f=!0}),!f){let M={role:"assistant",content:r.choices[0].message.content};n.value.push(M)}},y=async r=>{let g=await e.chat({messages:U(n.value),options:{stream:!1,signal:r.signal}});C(g)},v=r=>{let g=o.events?.onReceiveData,f=!1;if(g&&g(r,n,()=>{f=!0}),!f){n.value[n.value.length-1].role==="user"&&n.value.push({role:"assistant",content:""});let M=r.choices?.[0];M&&M.delta.content&&(n.value[n.value.length-1].content+=M.delta.content)}},R=async r=>{await e.chatStream({messages:U(n.value),options:{stream:!0,signal:r.signal}},{onData:g=>{u.status="streaming",v(g)},onError:g=>{u.status="error",u.errorMsg=l,console.error("Stream request error:",g)},onDone:g=>{let f=o.events?.onFinish,M=!1;if(f&&f(g,{messages:n,messageState:u},()=>{M=!0}),!M){if(g==="aborted"||u.status==="aborted")return;u.status="finished"}}})},m=async()=>{u.status="processing",u.errorMsg=null,c=new AbortController;try{s.value?await R(c):await y(c)}catch(r){u.errorMsg=l,u.status="error",console.error("Send message error:",r)}finally{c=null}};return{messages:n,messageState:u,inputMessage:p,useStream:s,sendMessage:async(r=p.value,g=!0)=>{if(N.includes(u.status)||!r||typeof r=="string"&&!r.trim()||Array.isArray(r)&&r.length===0)return;let f={role:"user",content:r};n.value.push(f),g&&(p.value=""),await m()},send:async()=>{N.includes(u.status)||await m()},clearMessages:()=>{n.value=[],u.errorMsg=null},addMessage:r=>{Array.isArray(r)?n.value.push(...r):n.value.push(r)},abortRequest:()=>{c&&(c.abort(),c=null,u.status="aborted")},retryRequest:async r=>{r===0||!n.value[r]||n.value[r].role==="user"||(n.value.splice(r),await m())}}}import{reactive as $,watch as F}from"vue";var T=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 L(){return Date.now().toString(36)+Math.random().toString(36).substring(2,9)}function ie(o){let{client:e,storage:t=new T,autoSave:l=!0,allowEmpty:h=!1,useStreamByDefault:n=!0,errorMessage:p="\u8BF7\u6C42\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5"}=o,s=$({conversations:[],currentId:null,loading:!1}),c=_({client:e,useStreamByDefault:n,errorMessage:p,initialMessages:[],events:o.events});F(()=>c.messages.value,a=>{if(s.currentId&&a.length>0){let d=s.conversations.findIndex(i=>i.id===s.currentId);d!==-1&&(s.conversations[d].messages=[...a],s.conversations[d].updatedAt=Date.now(),l&&m())}},{deep:!0});let u=(a="\u65B0\u4F1A\u8BDD",d={})=>{if(!h&&c.messages.value.length===0&&s.currentId)return s.currentId;let i=L(),r={id:i,title:a,createdAt:Date.now(),updatedAt:Date.now(),messages:[],metadata:d};return s.conversations.unshift(r),C(i),l&&m(),i},C=a=>{let d=s.conversations.find(i=>i.id===a);d&&(s.currentId=a,c.clearMessages(),d.messages.length>0&&d.messages.forEach(i=>c.addMessage(i)))},y=a=>{let d=s.conversations.findIndex(i=>i.id===a);d!==-1&&(s.conversations.splice(d,1),s.currentId===a&&(s.conversations.length>0?C(s.conversations[0].id):(s.currentId=null,c.clearMessages())),l&&m())},v=(a,d)=>{let i=s.conversations.find(r=>r.id===a);i&&(i.title=d,i.updatedAt=Date.now(),l&&m())},R=(a,d)=>{let i=s.conversations.find(r=>r.id===a);i&&(i.metadata={...i.metadata,...d},i.updatedAt=Date.now(),l&&m())},m=async()=>{try{await t.saveConversations(s.conversations)}catch(a){console.error("\u4FDD\u5B58\u4F1A\u8BDD\u5931\u8D25:",a)}},I=async()=>{s.loading=!0;try{let a=await t.loadConversations();s.conversations=a,a.length>0&&!s.currentId&&C(a[0].id)}catch(a){console.error("\u52A0\u8F7D\u4F1A\u8BDD\u5931\u8D25:",a)}finally{s.loading=!1}},P=async a=>{let d=s.conversations.find(i=>i.id===a);if(!d||d.messages.length<2)return d?.title||"\u65B0\u4F1A\u8BDD";try{let i={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"},r=d.messages.slice(0,Math.min(4,d.messages.length)),f=(await e.chat({messages:[i,...r],options:{stream:!1,max_tokens:30}})).choices[0].message.content.trim();return v(a,f),f}catch(i){return console.error("\u751F\u6210\u6807\u9898\u5931\u8D25:",i),d.title}},D=()=>s.currentId&&s.conversations.find(a=>a.id===s.currentId)||null;return I(),{state:s,messageManager:c,createConversation:u,switchConversation:C,deleteConversation:y,updateTitle:v,updateMetadata:R,saveConversations:m,loadConversations:I,generateTitle:P,getCurrentConversation:D}}export{O as AIClient,E as BaseModelProvider,k as ErrorType,oe as FinalStatus,N as GeneratingStatus,T as LocalStorageStrategy,A as OpenAIProvider,j as STATUS,K as StreamEventType,B as extractTextFromResponse,q as formatMessages,x as handleSSEStream,ie as useConversation,_ as useMessage};
3
+ `);a=y.pop()||"";for(let f of y)if(f.trim()!==""){if(f.trim()==="data: [DONE]"){d&&(c=d),e.onDone(c);continue}try{let v=f.match(/^data: (.+)$/m);if(!v)continue;let h=JSON.parse(v[1]);e.onData(h),d=h.choices?.[0]?.finish_reason||void 0}catch(v){console.error("Error parsing SSE message:",v)}}}(a.trim()==="data: [DONE]"||o?.aborted)&&(o?.aborted&&(c="aborted"),e.onDone(c))}catch(s){if(o?.aborted)return;throw s}}function B(n){return n.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 H(n){return!n.choices||!n.choices.length?"":n.choices[0].message?.content||""}var S=class extends A{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 c=await a.text();throw new Error(`HTTP error! status: ${a.status}, details: ${c}`)}return await a.json()}catch(l){throw I(l)}}async chatStream(o,l){let{signal:g,...a}=o.options||{};try{this.validateRequest(o);let c={model:o.options?.model||this.config.defaultModel||this.defaultModel,messages:o.messages,...a,stream:!0},d={method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${this.apiKey}`,Accept:"text/event-stream"},body:JSON.stringify(c),signal:g};this.apiKey&&Object.assign(d.headers,{Authorization:`Bearer ${this.apiKey}`});let s=await fetch(`${this.baseURL}/chat/completions`,d);if(!s.ok){let p=await s.text();throw new Error(`HTTP error! status: ${s.status}, details: ${p}`)}await b(s,l,g)}catch(c){if(g?.aborted)return;l.onError(I(c))}}updateConfig(o){super.updateConfig(o),o.apiUrl&&(this.baseURL=o.apiUrl),o.apiKey&&(this.apiKey=o.apiKey),o.defaultModel&&(this.defaultModel=o.defaultModel)}};var x=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 S({...o,...e});case"openai":default:return new S(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 j,ref as O,toRaw as N}from"vue";var F=(c=>(c.INIT="init",c.PROCESSING="processing",c.STREAMING="streaming",c.FINISHED="finished",c.ABORTED="aborted",c.ERROR="error",c))(F||{}),_=["processing","streaming"],re=["finished","aborted","error"];function k(n){let{client:e,useStreamByDefault:o=!0,errorMessage:l="\u8BF7\u6C42\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5",initialMessages:g=[]}=n,a=O([...g]),c=O(""),d=O(o),s=null,p=j({status:"init",errorMsg:null}),m=t=>{let r=n.events?.onReceiveData,u=!1;if(r&&r(t,a,()=>{u=!0}),!u){let C={role:"assistant",content:t.choices[0].message.content};a.value.push(C)}},y=async t=>{let r=await e.chat({messages:N(a.value),options:{stream:!1,signal:t.signal}});m(r)},f=t=>{let r=n.events?.onReceiveData,u=!1;if(r&&r(t,a,()=>{u=!0}),!u){a.value[a.value.length-1].role==="user"&&a.value.push({role:"assistant",content:""});let C=t.choices?.[0];C&&C.delta.content&&(a.value[a.value.length-1].content+=C.delta.content)}},v=async t=>{await e.chatStream({messages:N(a.value),options:{stream:!0,signal:t.signal}},{onData:r=>{p.status="streaming",f(r)},onError:r=>{p.status="error",p.errorMsg=l,console.error("Stream request error:",r)},onDone:r=>{let u=n.events?.onFinish,C=!1;if(u&&u(r,{messages:a,messageState:p},()=>{C=!0}),!C){if(r==="aborted"||p.status==="aborted")return;p.status="finished"}}})},h=async()=>{p.status="processing",p.errorMsg=null,s=new AbortController;try{d.value?await v(s):await y(s)}catch(t){p.errorMsg=l,p.status="error",console.error("Send message error:",t)}finally{s=null}};return{messages:a,messageState:p,inputMessage:c,useStream:d,sendMessage:async(t=c.value,r=!0)=>{if(_.includes(p.status)||!t||typeof t=="string"&&!t.trim()||Array.isArray(t)&&t.length===0)return;let u={role:"user",content:t};a.value.push(u),r&&(c.value=""),await h()},send:async()=>{_.includes(p.status)||await h()},clearMessages:()=>{a.value=[],p.errorMsg=null},addMessage:t=>{Array.isArray(t)?a.value.push(...t):a.value.push(t)},abortRequest:()=>{s&&(s.abort(),s=null,p.status="aborted")},retryRequest:async t=>{t===0||!a.value[t]||a.value[t].role==="user"||(a.value.splice(t),await h())}}}import{reactive as L,watch as $}from"vue";var w=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 G(){return Date.now().toString(36)+Math.random().toString(36).substring(2,9)}function le(n){let{client:e,storage:o=new w,autoSave:l=!0,allowEmpty:g=!1,useStreamByDefault:a=!0,errorMessage:c="\u8BF7\u6C42\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5",events:d}=n,s=L({conversations:[],currentId:null,loading:!1}),p=!1,m=k({client:e,useStreamByDefault:a,errorMessage:c,initialMessages:[],events:{onReceiveData:d?.onReceiveData,onFinish:d?.onFinish}});$(()=>m.messages.value,i=>{if(s.currentId&&i.length>0){let t=s.conversations.findIndex(r=>r.id===s.currentId);t!==-1&&(s.conversations[t].messages=[...i],s.conversations[t].updatedAt=Date.now(),l&&R())}},{deep:!0});let y=(i="\u65B0\u4F1A\u8BDD",t={})=>{if(!g&&m.messages.value.length===0&&s.currentId)return s.currentId;let r=G(),u={id:r,title:i,createdAt:Date.now(),updatedAt:Date.now(),messages:[],metadata:t};return s.conversations.unshift(u),f(r),l&&R(),r},f=i=>{let t=s.conversations.find(r=>r.id===i);t&&(s.currentId=i,m.clearMessages(),t.messages.length>0&&t.messages.forEach(r=>m.addMessage(r)))},v=i=>{let t=s.conversations.findIndex(r=>r.id===i);t!==-1&&(s.conversations.splice(t,1),s.currentId===i&&(s.conversations.length>0?f(s.conversations[0].id):(s.currentId=null,m.clearMessages())),l&&R())},h=(i,t)=>{let r=s.conversations.find(u=>u.id===i);r&&(r.title=t,r.updatedAt=Date.now(),l&&R())},T=(i,t)=>{let r=s.conversations.find(u=>u.id===i);r&&(r.metadata={...r.metadata,...t},r.updatedAt=Date.now(),l&&R())},R=async()=>{try{await o.saveConversations(s.conversations)}catch(i){console.error("\u4FDD\u5B58\u4F1A\u8BDD\u5931\u8D25:",i)}},E=async()=>{s.loading=!0;try{let i=await o.loadConversations();s.conversations=i,i.length>0&&!s.currentId&&f(i[0].id),!p&&d?.onLoaded&&(p=!0,d.onLoaded(i))}catch(i){console.error("\u52A0\u8F7D\u4F1A\u8BDD\u5931\u8D25:",i)}finally{s.loading=!1}},D=async i=>{let t=s.conversations.find(r=>r.id===i);if(!t||t.messages.length<2)return t?.title||"\u65B0\u4F1A\u8BDD";try{let r={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=t.messages.slice(0,Math.min(4,t.messages.length)),U=(await e.chat({messages:[r,...u],options:{stream:!1,max_tokens:30}})).choices[0].message.content.trim();return h(i,U),U}catch(r){return console.error("\u751F\u6210\u6807\u9898\u5931\u8D25:",r),t.title}},P=()=>s.currentId&&s.conversations.find(i=>i.id===s.currentId)||null;return E(),{state:s,messageManager:m,createConversation:y,switchConversation:f,deleteConversation:v,updateTitle:h,updateMetadata:T,saveConversations:R,loadConversations:E,generateTitle:D,getCurrentConversation:P}}export{x as AIClient,A as BaseModelProvider,K as ErrorType,re as FinalStatus,_ as GeneratingStatus,w as LocalStorageStrategy,S as OpenAIProvider,F as STATUS,q as StreamEventType,H as extractTextFromResponse,B as formatMessages,b as handleSSEStream,le as useConversation,k as useMessage};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@opentiny/tiny-robot-kit",
3
- "version": "0.3.0-rc.5",
3
+ "version": "0.3.0-rc.6",
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": "7eda1720baf0381e4b15ffd7e295fc4a3a1b9ac4"
29
+ "gitHead": "33faba113d39072692e56743771e5d97ccbba15c"
30
30
  }