@opentiny/tiny-robot-kit 0.3.0-rc.3 → 0.3.0-rc.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +7 -1
- package/dist/index.d.ts +7 -1
- package/dist/index.js +2 -2
- package/dist/index.mjs +2 -2
- package/package.json +2 -2
package/dist/index.d.mts
CHANGED
|
@@ -189,7 +189,7 @@ declare enum StreamEventType {
|
|
|
189
189
|
interface StreamHandler {
|
|
190
190
|
onData: (data: ChatCompletionStreamResponse) => void;
|
|
191
191
|
onError: (error: AIAdapterError) => void;
|
|
192
|
-
onDone: () => void;
|
|
192
|
+
onDone: (finishReason?: string) => void;
|
|
193
193
|
}
|
|
194
194
|
|
|
195
195
|
/**
|
|
@@ -331,6 +331,10 @@ interface UseMessageOptions {
|
|
|
331
331
|
initialMessages?: ChatMessage[];
|
|
332
332
|
events?: {
|
|
333
333
|
onReceiveData?: <T = any>(data: T, messages: Ref<ChatMessage[]>, preventDefault: () => void) => void;
|
|
334
|
+
onFinish?: (finishReason: string | undefined, context: {
|
|
335
|
+
messages: Ref<ChatMessage[]>;
|
|
336
|
+
messageState: Reactive<MessageState>;
|
|
337
|
+
}, preventDefault: () => void) => void;
|
|
334
338
|
};
|
|
335
339
|
}
|
|
336
340
|
/**
|
|
@@ -427,6 +431,8 @@ interface UseConversationOptions {
|
|
|
427
431
|
storage?: ConversationStorageStrategy;
|
|
428
432
|
/** 是否自动保存 */
|
|
429
433
|
autoSave?: boolean;
|
|
434
|
+
/** 是否允许空会话 */
|
|
435
|
+
allowEmpty?: boolean;
|
|
430
436
|
/** 是否默认使用流式响应 */
|
|
431
437
|
useStreamByDefault?: boolean;
|
|
432
438
|
/** 错误消息模板 */
|
package/dist/index.d.ts
CHANGED
|
@@ -189,7 +189,7 @@ declare enum StreamEventType {
|
|
|
189
189
|
interface StreamHandler {
|
|
190
190
|
onData: (data: ChatCompletionStreamResponse) => void;
|
|
191
191
|
onError: (error: AIAdapterError) => void;
|
|
192
|
-
onDone: () => void;
|
|
192
|
+
onDone: (finishReason?: string) => void;
|
|
193
193
|
}
|
|
194
194
|
|
|
195
195
|
/**
|
|
@@ -331,6 +331,10 @@ interface UseMessageOptions {
|
|
|
331
331
|
initialMessages?: ChatMessage[];
|
|
332
332
|
events?: {
|
|
333
333
|
onReceiveData?: <T = any>(data: T, messages: Ref<ChatMessage[]>, preventDefault: () => void) => void;
|
|
334
|
+
onFinish?: (finishReason: string | undefined, context: {
|
|
335
|
+
messages: Ref<ChatMessage[]>;
|
|
336
|
+
messageState: Reactive<MessageState>;
|
|
337
|
+
}, preventDefault: () => void) => void;
|
|
334
338
|
};
|
|
335
339
|
}
|
|
336
340
|
/**
|
|
@@ -427,6 +431,8 @@ interface UseConversationOptions {
|
|
|
427
431
|
storage?: ConversationStorageStrategy;
|
|
428
432
|
/** 是否自动保存 */
|
|
429
433
|
autoSave?: boolean;
|
|
434
|
+
/** 是否允许空会话 */
|
|
435
|
+
allowEmpty?: boolean;
|
|
430
436
|
/** 是否默认使用流式响应 */
|
|
431
437
|
useStreamByDefault?: boolean;
|
|
432
438
|
/** 错误消息模板 */
|
package/dist/index.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
"use strict";var P=Object.defineProperty;var $=Object.getOwnPropertyDescriptor;var
|
|
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(`
|
|
2
2
|
|
|
3
|
-
`);
|
|
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});
|
package/dist/index.mjs
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
var
|
|
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(`
|
|
2
2
|
|
|
3
|
-
`);
|
|
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};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@opentiny/tiny-robot-kit",
|
|
3
|
-
"version": "0.3.0-rc.
|
|
3
|
+
"version": "0.3.0-rc.5",
|
|
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": "7eda1720baf0381e4b15ffd7e295fc4a3a1b9ac4"
|
|
30
30
|
}
|