@opentiny/tiny-robot-kit 0.3.0-rc.0 → 0.3.0-rc.1
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 +5 -3
- package/dist/index.d.ts +5 -3
- package/dist/index.js +1 -1
- package/dist/index.mjs +1 -1
- package/package.json +2 -2
package/dist/index.d.mts
CHANGED
|
@@ -48,7 +48,7 @@ type MessageRole = 'system' | 'user' | 'assistant';
|
|
|
48
48
|
interface ChatMessage {
|
|
49
49
|
role: MessageRole;
|
|
50
50
|
content: string | {
|
|
51
|
-
type:
|
|
51
|
+
type: string;
|
|
52
52
|
[x: string]: unknown;
|
|
53
53
|
}[];
|
|
54
54
|
name?: string;
|
|
@@ -83,6 +83,7 @@ interface ChatCompletionRequest {
|
|
|
83
83
|
interface ChatCompletionResponseMessage {
|
|
84
84
|
role: MessageRole;
|
|
85
85
|
content: string;
|
|
86
|
+
[x: string]: unknown;
|
|
86
87
|
}
|
|
87
88
|
/**
|
|
88
89
|
* 聊天完成响应选择
|
|
@@ -117,6 +118,7 @@ interface ChatCompletionResponse {
|
|
|
117
118
|
interface ChatCompletionStreamResponseDelta {
|
|
118
119
|
content?: string;
|
|
119
120
|
role?: MessageRole;
|
|
121
|
+
[x: string]: unknown;
|
|
120
122
|
}
|
|
121
123
|
/**
|
|
122
124
|
* 流式聊天完成响应选择
|
|
@@ -328,7 +330,7 @@ interface UseMessageOptions {
|
|
|
328
330
|
/** 初始消息列表 */
|
|
329
331
|
initialMessages?: ChatMessage[];
|
|
330
332
|
events?: {
|
|
331
|
-
onReceiveData?: <T
|
|
333
|
+
onReceiveData?: <T = any>(data: T, messages: Ref<ChatMessage[]>, preventDefault: () => void) => void;
|
|
332
334
|
};
|
|
333
335
|
}
|
|
334
336
|
/**
|
|
@@ -343,7 +345,7 @@ interface UseMessageReturn {
|
|
|
343
345
|
/** 是否使用流式响应 */
|
|
344
346
|
useStream: Ref<boolean>;
|
|
345
347
|
/** 发送消息 */
|
|
346
|
-
sendMessage: (content?:
|
|
348
|
+
sendMessage: (content?: ChatMessage['content'], clearInput?: boolean) => Promise<void>;
|
|
347
349
|
/** 手动执行addMessage添加消息后,可以执行send发送消息 */
|
|
348
350
|
send: () => Promise<void>;
|
|
349
351
|
/** 清空消息 */
|
package/dist/index.d.ts
CHANGED
|
@@ -48,7 +48,7 @@ type MessageRole = 'system' | 'user' | 'assistant';
|
|
|
48
48
|
interface ChatMessage {
|
|
49
49
|
role: MessageRole;
|
|
50
50
|
content: string | {
|
|
51
|
-
type:
|
|
51
|
+
type: string;
|
|
52
52
|
[x: string]: unknown;
|
|
53
53
|
}[];
|
|
54
54
|
name?: string;
|
|
@@ -83,6 +83,7 @@ interface ChatCompletionRequest {
|
|
|
83
83
|
interface ChatCompletionResponseMessage {
|
|
84
84
|
role: MessageRole;
|
|
85
85
|
content: string;
|
|
86
|
+
[x: string]: unknown;
|
|
86
87
|
}
|
|
87
88
|
/**
|
|
88
89
|
* 聊天完成响应选择
|
|
@@ -117,6 +118,7 @@ interface ChatCompletionResponse {
|
|
|
117
118
|
interface ChatCompletionStreamResponseDelta {
|
|
118
119
|
content?: string;
|
|
119
120
|
role?: MessageRole;
|
|
121
|
+
[x: string]: unknown;
|
|
120
122
|
}
|
|
121
123
|
/**
|
|
122
124
|
* 流式聊天完成响应选择
|
|
@@ -328,7 +330,7 @@ interface UseMessageOptions {
|
|
|
328
330
|
/** 初始消息列表 */
|
|
329
331
|
initialMessages?: ChatMessage[];
|
|
330
332
|
events?: {
|
|
331
|
-
onReceiveData?: <T
|
|
333
|
+
onReceiveData?: <T = any>(data: T, messages: Ref<ChatMessage[]>, preventDefault: () => void) => void;
|
|
332
334
|
};
|
|
333
335
|
}
|
|
334
336
|
/**
|
|
@@ -343,7 +345,7 @@ interface UseMessageReturn {
|
|
|
343
345
|
/** 是否使用流式响应 */
|
|
344
346
|
useStream: Ref<boolean>;
|
|
345
347
|
/** 发送消息 */
|
|
346
|
-
sendMessage: (content?:
|
|
348
|
+
sendMessage: (content?: ChatMessage['content'], clearInput?: boolean) => Promise<void>;
|
|
347
349
|
/** 手动执行addMessage添加消息后,可以执行send发送消息 */
|
|
348
350
|
send: () => Promise<void>;
|
|
349
351
|
/** 清空消息 */
|
package/dist/index.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
"use strict";var P=Object.defineProperty;var $=Object.getOwnPropertyDescriptor;var L=Object.getOwnPropertyNames;var F=Object.prototype.hasOwnProperty;var G=(s,e)=>{for(var t in e)P(s,t,{get:e[t],enumerable:!0})},W=(s,e,t,n)=>{if(e&&typeof e=="object"||typeof e=="function")for(let u of L(e))!F.call(s,u)&&u!==t&&P(s,u,{get:()=>e[u],enumerable:!(n=$(e,u))||n.enumerable});return s};var J=s=>W(P({},"__esModule",{value:!0}),s);var X={};G(X,{AIClient:()=>O,BaseModelProvider:()=>E,ErrorType:()=>K,FinalStatus:()=>z,GeneratingStatus:()=>N,LocalStorageStrategy:()=>w,OpenAIProvider:()=>y,STATUS:()=>j,StreamEventType:()=>q,extractTextFromResponse:()=>H,formatMessages:()=>B,handleSSEStream:()=>x,useConversation:()=>Q,useMessage:()=>U});module.exports=J(X);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=(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=(n=>(n.DATA="data",n.ERROR="error",n.DONE="done",n))(q||{});function S(s){return{type:s.type||"unknown_error",message:s.message||"\u672A\u77E5\u9519\u8BEF",statusCode:s.statusCode,originalError:s.originalError}}function D(s){if(!s.response)return S({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?S({type:"authentication_error",message:"\u8EAB\u4EFD\u9A8C\u8BC1\u5931\u8D25\uFF0C\u8BF7\u68C0\u67E5\u60A8\u7684API\u5BC6\u94A5",statusCode:e,originalError:s}):e===429?S({type:"rate_limit_error",message:"\u8D85\u51FAAPI\u8C03\u7528\u9650\u5236\uFF0C\u8BF7\u7A0D\u540E\u518D\u8BD5",statusCode:e,originalError:s}):e>=500?S({type:"server_error",message:"\u670D\u52A1\u5668\u9519\u8BEF\uFF0C\u8BF7\u7A0D\u540E\u518D\u8BD5",statusCode:e,originalError:s}):S({type:"unknown_error",message:t?.error?.message||`\u8BF7\u6C42\u5931\u8D25\uFF0C\u72B6\u6001\u7801: ${e}`,statusCode:e,originalError:s})}return s.code==="ECONNABORTED"?S({type:"timeout_error",message:"\u8BF7\u6C42\u8D85\u65F6\uFF0C\u8BF7\u7A0D\u540E\u518D\u8BD5",originalError:s}):S({type:"unknown_error",message:s.message||"\u53D1\u751F\u672A\u77E5\u9519\u8BEF",originalError:s})}async function x(s,e,t){let n=s.body?.getReader();if(!n)throw new Error("Response body is null");let u=new TextDecoder,r="";t&&t.addEventListener("abort",()=>{n.cancel().catch(o=>console.error("Error cancelling reader:",o))},{once:!0});try{for(;;){if(t?.aborted){await n.cancel();break}let{done:o,value:d}=await n.read();if(o)break;let g=u.decode(d,{stream:!0});r+=g;let c=r.split(`
|
|
2
2
|
|
|
3
|
-
`);r=c.pop()||"";for(let R of c)if(R.trim()!==""){if(R.trim()==="data: [DONE]"){e.onDone();continue}try{let C=R.match(/^data: (.+)$/m);if(!C)continue;let I=JSON.parse(C[1]);e.onData(I)}catch(C){console.error("Error parsing SSE message:",C)}}}(r.trim()==="data: [DONE]"||t?.aborted)&&e.onDone()}catch(o){if(t?.aborted)return;throw o}}function B(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 H(s){return!s.choices||!s.choices.length?"":s.choices[0].message?.content||""}var y=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 n={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(n)};this.apiKey&&Object.assign(u.headers,{Authorization:`Bearer ${this.apiKey}`});let r=await fetch(`${this.baseURL}/chat/completions`,u);if(!r.ok){let o=await r.text();throw new Error(`HTTP error! status: ${r.status}, details: ${o}`)}return await r.json()}catch(n){throw D(n)}}async chatStream(t,n){let{signal:u,...r}=t.options||{};try{this.validateRequest(t);let o={model:t.options?.model||this.config.defaultModel||this.defaultModel,messages:t.messages,...r,stream:!0},d={method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${this.apiKey}`,Accept:"text/event-stream"},body:JSON.stringify(o),signal:u};this.apiKey&&Object.assign(d.headers,{Authorization:`Bearer ${this.apiKey}`});let g=await fetch(`${this.baseURL}/chat/completions`,d);if(!g.ok){let c=await g.text();throw new Error(`HTTP error! status: ${g.status}, details: ${c}`)}await x(g,n,u)}catch(o){if(u?.aborted)return;n.onError(D(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 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 y({...t,...e});case"openai":default:return new y(e)}}async chat(e){return this.provider.chat(e)}async chatStream(e,t){let n={...e,options:{...e.options,stream:!0}};return this.provider.chatStream(n,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
|
|
3
|
+
`);r=c.pop()||"";for(let R of c)if(R.trim()!==""){if(R.trim()==="data: [DONE]"){e.onDone();continue}try{let C=R.match(/^data: (.+)$/m);if(!C)continue;let I=JSON.parse(C[1]);e.onData(I)}catch(C){console.error("Error parsing SSE message:",C)}}}(r.trim()==="data: [DONE]"||t?.aborted)&&e.onDone()}catch(o){if(t?.aborted)return;throw o}}function B(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 H(s){return!s.choices||!s.choices.length?"":s.choices[0].message?.content||""}var y=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 n={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(n)};this.apiKey&&Object.assign(u.headers,{Authorization:`Bearer ${this.apiKey}`});let r=await fetch(`${this.baseURL}/chat/completions`,u);if(!r.ok){let o=await r.text();throw new Error(`HTTP error! status: ${r.status}, details: ${o}`)}return await r.json()}catch(n){throw D(n)}}async chatStream(t,n){let{signal:u,...r}=t.options||{};try{this.validateRequest(t);let o={model:t.options?.model||this.config.defaultModel||this.defaultModel,messages:t.messages,...r,stream:!0},d={method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${this.apiKey}`,Accept:"text/event-stream"},body:JSON.stringify(o),signal:u};this.apiKey&&Object.assign(d.headers,{Authorization:`Bearer ${this.apiKey}`});let g=await fetch(`${this.baseURL}/chat/completions`,d);if(!g.ok){let c=await g.text();throw new Error(`HTTP error! status: ${g.status}, details: ${c}`)}await x(g,n,u)}catch(o){if(u?.aborted)return;n.onError(D(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 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 y({...t,...e});case"openai":default:return new y(e)}}async chat(e){return this.provider.chat(e)}async chatStream(e,t){let n={...e,options:{...e.options,stream:!0}};return this.provider.chatStream(n,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 f=require("vue"),j=(o=>(o.INIT="init",o.PROCESSING="processing",o.STREAMING="streaming",o.FINISHED="finished",o.ABORTED="aborted",o.ERROR="error",o))(j||{}),N=["processing","streaming"],z=["finished","aborted","error"];function U(s){let{client:e,useStreamByDefault:t=!0,errorMessage:n="\u8BF7\u6C42\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5",initialMessages:u=[]}=s,r=(0,f.ref)([...u]),o=(0,f.ref)(""),d=(0,f.ref)(t),g=null,c=(0,f.reactive)({status:"init",errorMsg:null}),R=i=>{let m=s.events?.onReceiveData,M=!1;if(m&&m(i,r,()=>{M=!0}),!M){let b={role:"assistant",content:i.choices[0].message.content};r.value.push(b)}},C=async i=>{let m=await e.chat({messages:(0,f.toRaw)(r.value),options:{stream:!1,signal:i.signal}});R(m)},I=i=>{let m=s.events?.onReceiveData,M=!1;if(m&&m(i,r,()=>{M=!0}),!M){r.value[r.value.length-1].role==="user"&&r.value.push({role:"assistant",content:""});let b=i.choices?.[0];b&&b.delta.content&&(r.value[r.value.length-1].content+=b.delta.content)}},h=async i=>{await e.chatStream({messages:(0,f.toRaw)(r.value),options:{stream:!0,signal:i.signal}},{onData:m=>{c.status="streaming",I(m)},onError:m=>{c.status="error",c.errorMsg=n,console.error("Stream request error:",m)},onDone:()=>{c.status="finished"}})},A=async()=>{c.status="processing",c.errorMsg=null,g=new AbortController;try{d.value?await h(g):await C(g),c.status="finished"}catch(i){c.errorMsg=n,c.status="error",console.error("Send message error:",i)}finally{g=null}};return{messages:r,messageState:c,inputMessage:o,useStream:d,sendMessage:async(i=o.value,m=!0)=>{if(N.includes(c.status)||!i||typeof i=="string"&&!i.trim()||Array.isArray(i)&&i.length===0)return;let M={role:"user",content:i};r.value.push(M),m&&(o.value=""),await A()},send:async()=>{N.includes(c.status)||await A()},clearMessages:()=>{r.value=[],c.errorMsg=null},addMessage:i=>{Array.isArray(i)?r.value.push(...i):r.value.push(i)},abortRequest:()=>{g&&(g.abort(),g=null,c.status="aborted")},retryRequest:async i=>{i===0||!r.value[i]||r.value[i].role==="user"||(r.value.splice(i),await A())}}}var T=require("vue");var w=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(s){let{client:e,storage:t=new w,autoSave:n=!0,useStreamByDefault:u=!0,errorMessage:r="\u8BF7\u6C42\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5"}=s,o=(0,T.reactive)({conversations:[],currentId:null,loading:!1}),d=U({client:e,useStreamByDefault:u,errorMessage:r,initialMessages:[],events:s.events});(0,T.watch)(()=>d.messages.value,a=>{if(o.currentId&&a.length>0){let p=o.conversations.findIndex(l=>l.id===o.currentId);p!==-1&&(o.conversations[p].messages=[...a],o.conversations[p].updatedAt=Date.now(),n&&h())}},{deep:!0});let g=(a="\u65B0\u4F1A\u8BDD",p={})=>{let l=V(),v={id:l,title:a,createdAt:Date.now(),updatedAt:Date.now(),messages:[],metadata:p};return o.conversations.unshift(v),c(l),n&&h(),l},c=a=>{let p=o.conversations.find(l=>l.id===a);p&&(o.currentId=a,d.clearMessages(),p.messages.length>0&&p.messages.forEach(l=>d.addMessage(l)))},R=a=>{let p=o.conversations.findIndex(l=>l.id===a);p!==-1&&(o.conversations.splice(p,1),o.currentId===a&&(o.conversations.length>0?c(o.conversations[0].id):(o.currentId=null,d.clearMessages())),n&&h())},C=(a,p)=>{let l=o.conversations.find(v=>v.id===a);l&&(l.title=p,l.updatedAt=Date.now(),n&&h())},I=(a,p)=>{let l=o.conversations.find(v=>v.id===a);l&&(l.metadata={...l.metadata,...p},l.updatedAt=Date.now(),n&&h())},h=async()=>{try{await t.saveConversations(o.conversations)}catch(a){console.error("\u4FDD\u5B58\u4F1A\u8BDD\u5931\u8D25:",a)}},A=async()=>{o.loading=!0;try{let a=await t.loadConversations();o.conversations=a,a.length>0&&!o.currentId&&c(a[0].id)}catch(a){console.error("\u52A0\u8F7D\u4F1A\u8BDD\u5931\u8D25:",a)}finally{o.loading=!1}},_=async a=>{let p=o.conversations.find(l=>l.id===a);if(!p||p.messages.length<2)return p?.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"},v=p.messages.slice(0,Math.min(4,p.messages.length)),m=(await e.chat({messages:[l,...v],options:{stream:!1,max_tokens:30}})).choices[0].message.content.trim();return C(a,m),m}catch(l){return console.error("\u751F\u6210\u6807\u9898\u5931\u8D25:",l),p.title}},k=()=>o.currentId&&o.conversations.find(a=>a.id===o.currentId)||null;return A(),{state:o,messageManager:d,createConversation:g,switchConversation:c,deleteConversation:R,updateTitle:C,updateMetadata:I,saveConversations:h,loadConversations:A,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
1
|
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 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||{}),K=(l=>(l.DATA="data",l.ERROR="error",l.DONE="done",l))(K||{});function M(s){return{type:s.type||"unknown_error",message:s.message||"\u672A\u77E5\u9519\u8BEF",statusCode:s.statusCode,originalError:s.originalError}}function b(s){if(!s.response)return M({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:o}=s.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:s}):e===429?M({type:"rate_limit_error",message:"\u8D85\u51FAAPI\u8C03\u7528\u9650\u5236\uFF0C\u8BF7\u7A0D\u540E\u518D\u8BD5",statusCode:e,originalError:s}):e>=500?M({type:"server_error",message:"\u670D\u52A1\u5668\u9519\u8BEF\uFF0C\u8BF7\u7A0D\u540E\u518D\u8BD5",statusCode:e,originalError:s}):M({type:"unknown_error",message:o?.error?.message||`\u8BF7\u6C42\u5931\u8D25\uFF0C\u72B6\u6001\u7801: ${e}`,statusCode:e,originalError:s})}return s.code==="ECONNABORTED"?M({type:"timeout_error",message:"\u8BF7\u6C42\u8D85\u65F6\uFF0C\u8BF7\u7A0D\u540E\u518D\u8BD5",originalError:s}):M({type:"unknown_error",message:s.message||"\u53D1\u751F\u672A\u77E5\u9519\u8BEF",originalError:s})}async function x(s,e,o){let l=s.body?.getReader();if(!l)throw new Error("Response body is null");let m=new TextDecoder,r="";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:d}=await l.read();if(t)break;let u=m.decode(d,{stream:!0});r+=u;let c=r.split(`
|
|
2
2
|
|
|
3
|
-
`);r=c.pop()||"";for(let v of c)if(v.trim()!==""){if(v.trim()==="data: [DONE]"){e.onDone();continue}try{let C=v.match(/^data: (.+)$/m);if(!C)continue;let A=JSON.parse(C[1]);e.onData(A)}catch(C){console.error("Error parsing SSE message:",C)}}}(r.trim()==="data: [DONE]"||o?.aborted)&&e.onDone()}catch(t){if(o?.aborted)return;throw t}}function q(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 B(s){return!s.choices||!s.choices.length?"":s.choices[0].message?.content||""}var y=class extends I{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},m={method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(l)};this.apiKey&&Object.assign(m.headers,{Authorization:`Bearer ${this.apiKey}`});let r=await fetch(`${this.baseURL}/chat/completions`,m);if(!r.ok){let t=await r.text();throw new Error(`HTTP error! status: ${r.status}, details: ${t}`)}return await r.json()}catch(l){throw b(l)}}async chatStream(o,l){let{signal:m,...r}=o.options||{};try{this.validateRequest(o);let t={model:o.options?.model||this.config.defaultModel||this.defaultModel,messages:o.messages,...r,stream:!0},d={method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${this.apiKey}`,Accept:"text/event-stream"},body:JSON.stringify(t),signal:m};this.apiKey&&Object.assign(d.headers,{Authorization:`Bearer ${this.apiKey}`});let u=await fetch(`${this.baseURL}/chat/completions`,d);if(!u.ok){let c=await u.text();throw new Error(`HTTP error! status: ${u.status}, details: ${c}`)}await x(u,l,m)}catch(t){if(m?.aborted)return;l.onError(b(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 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 o={defaultModel:"deepseek-chat",apiUrl:"https://api.deepseek.com/v1"};return new y({...o,...e});case"openai":default:return new y(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 H,ref as w,toRaw as N}from"vue";var j=(t=>(t.INIT="init",t.PROCESSING="processing",t.STREAMING="streaming",t.FINISHED="finished",t.ABORTED="aborted",t.ERROR="error",t))(j||{}),U=["processing","streaming"],se=["finished","aborted","error"];function _(s){let{client:e,useStreamByDefault:o=!0,errorMessage:l="\u8BF7\u6C42\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5",initialMessages:m=[]}=s,r=w([...m]),t=w(""),d=w(o),u=null,c=H({status:"init",errorMsg:null}),v=a=>{let g=s.events?.onReceiveData,R=!1;if(g&&g(a,r,()=>{R=!0}),!R){let E={role:"assistant",content:a.choices[0].message.content};r.value.push(E)}},C=async a=>{let g=await e.chat({messages:N(r.value),options:{stream:!1,signal:a.signal}});v(g)},A=a=>{let g=s.events?.onReceiveData,R=!1;if(g&&g(a,r,()=>{R=!0}),!R){r.value[r.value.length-1].role==="user"&&r.value.push({role:"assistant",content:""});let E=a.choices?.[0];E&&E.delta.content&&(r.value[r.value.length-1].content+=E.delta.content)}},
|
|
3
|
+
`);r=c.pop()||"";for(let v of c)if(v.trim()!==""){if(v.trim()==="data: [DONE]"){e.onDone();continue}try{let C=v.match(/^data: (.+)$/m);if(!C)continue;let A=JSON.parse(C[1]);e.onData(A)}catch(C){console.error("Error parsing SSE message:",C)}}}(r.trim()==="data: [DONE]"||o?.aborted)&&e.onDone()}catch(t){if(o?.aborted)return;throw t}}function q(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 B(s){return!s.choices||!s.choices.length?"":s.choices[0].message?.content||""}var y=class extends I{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},m={method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(l)};this.apiKey&&Object.assign(m.headers,{Authorization:`Bearer ${this.apiKey}`});let r=await fetch(`${this.baseURL}/chat/completions`,m);if(!r.ok){let t=await r.text();throw new Error(`HTTP error! status: ${r.status}, details: ${t}`)}return await r.json()}catch(l){throw b(l)}}async chatStream(o,l){let{signal:m,...r}=o.options||{};try{this.validateRequest(o);let t={model:o.options?.model||this.config.defaultModel||this.defaultModel,messages:o.messages,...r,stream:!0},d={method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${this.apiKey}`,Accept:"text/event-stream"},body:JSON.stringify(t),signal:m};this.apiKey&&Object.assign(d.headers,{Authorization:`Bearer ${this.apiKey}`});let u=await fetch(`${this.baseURL}/chat/completions`,d);if(!u.ok){let c=await u.text();throw new Error(`HTTP error! status: ${u.status}, details: ${c}`)}await x(u,l,m)}catch(t){if(m?.aborted)return;l.onError(b(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 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 o={defaultModel:"deepseek-chat",apiUrl:"https://api.deepseek.com/v1"};return new y({...o,...e});case"openai":default:return new y(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 H,ref as w,toRaw as N}from"vue";var j=(t=>(t.INIT="init",t.PROCESSING="processing",t.STREAMING="streaming",t.FINISHED="finished",t.ABORTED="aborted",t.ERROR="error",t))(j||{}),U=["processing","streaming"],se=["finished","aborted","error"];function _(s){let{client:e,useStreamByDefault:o=!0,errorMessage:l="\u8BF7\u6C42\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5",initialMessages:m=[]}=s,r=w([...m]),t=w(""),d=w(o),u=null,c=H({status:"init",errorMsg:null}),v=a=>{let g=s.events?.onReceiveData,R=!1;if(g&&g(a,r,()=>{R=!0}),!R){let E={role:"assistant",content:a.choices[0].message.content};r.value.push(E)}},C=async a=>{let g=await e.chat({messages:N(r.value),options:{stream:!1,signal:a.signal}});v(g)},A=a=>{let g=s.events?.onReceiveData,R=!1;if(g&&g(a,r,()=>{R=!0}),!R){r.value[r.value.length-1].role==="user"&&r.value.push({role:"assistant",content:""});let E=a.choices?.[0];E&&E.delta.content&&(r.value[r.value.length-1].content+=E.delta.content)}},f=async a=>{await e.chatStream({messages:N(r.value),options:{stream:!0,signal:a.signal}},{onData:g=>{c.status="streaming",A(g)},onError:g=>{c.status="error",c.errorMsg=l,console.error("Stream request error:",g)},onDone:()=>{c.status="finished"}})},S=async()=>{c.status="processing",c.errorMsg=null,u=new AbortController;try{d.value?await f(u):await C(u),c.status="finished"}catch(a){c.errorMsg=l,c.status="error",console.error("Send message error:",a)}finally{u=null}};return{messages:r,messageState:c,inputMessage:t,useStream:d,sendMessage:async(a=t.value,g=!0)=>{if(U.includes(c.status)||!a||typeof a=="string"&&!a.trim()||Array.isArray(a)&&a.length===0)return;let R={role:"user",content:a};r.value.push(R),g&&(t.value=""),await S()},send:async()=>{U.includes(c.status)||await S()},clearMessages:()=>{r.value=[],c.errorMsg=null},addMessage:a=>{Array.isArray(a)?r.value.push(...a):r.value.push(a)},abortRequest:()=>{u&&(u.abort(),u=null,c.status="aborted")},retryRequest:async a=>{a===0||!r.value[a]||r.value[a].role==="user"||(r.value.splice(a),await S())}}}import{reactive as $,watch as L}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(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 F(){return Date.now().toString(36)+Math.random().toString(36).substring(2,9)}function ie(s){let{client:e,storage:o=new T,autoSave:l=!0,useStreamByDefault:m=!0,errorMessage:r="\u8BF7\u6C42\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5"}=s,t=$({conversations:[],currentId:null,loading:!1}),d=_({client:e,useStreamByDefault:m,errorMessage:r,initialMessages:[],events:s.events});L(()=>d.messages.value,n=>{if(t.currentId&&n.length>0){let p=t.conversations.findIndex(i=>i.id===t.currentId);p!==-1&&(t.conversations[p].messages=[...n],t.conversations[p].updatedAt=Date.now(),l&&f())}},{deep:!0});let u=(n="\u65B0\u4F1A\u8BDD",p={})=>{let i=F(),h={id:i,title:n,createdAt:Date.now(),updatedAt:Date.now(),messages:[],metadata:p};return t.conversations.unshift(h),c(i),l&&f(),i},c=n=>{let p=t.conversations.find(i=>i.id===n);p&&(t.currentId=n,d.clearMessages(),p.messages.length>0&&p.messages.forEach(i=>d.addMessage(i)))},v=n=>{let p=t.conversations.findIndex(i=>i.id===n);p!==-1&&(t.conversations.splice(p,1),t.currentId===n&&(t.conversations.length>0?c(t.conversations[0].id):(t.currentId=null,d.clearMessages())),l&&f())},C=(n,p)=>{let i=t.conversations.find(h=>h.id===n);i&&(i.title=p,i.updatedAt=Date.now(),l&&f())},A=(n,p)=>{let i=t.conversations.find(h=>h.id===n);i&&(i.metadata={...i.metadata,...p},i.updatedAt=Date.now(),l&&f())},f=async()=>{try{await o.saveConversations(t.conversations)}catch(n){console.error("\u4FDD\u5B58\u4F1A\u8BDD\u5931\u8D25:",n)}},S=async()=>{t.loading=!0;try{let n=await o.loadConversations();t.conversations=n,n.length>0&&!t.currentId&&c(n[0].id)}catch(n){console.error("\u52A0\u8F7D\u4F1A\u8BDD\u5931\u8D25:",n)}finally{t.loading=!1}},P=async n=>{let p=t.conversations.find(i=>i.id===n);if(!p||p.messages.length<2)return p?.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"},h=p.messages.slice(0,Math.min(4,p.messages.length)),g=(await e.chat({messages:[i,...h],options:{stream:!1,max_tokens:30}})).choices[0].message.content.trim();return C(n,g),g}catch(i){return console.error("\u751F\u6210\u6807\u9898\u5931\u8D25:",i),p.title}},D=()=>t.currentId&&t.conversations.find(n=>n.id===t.currentId)||null;return S(),{state:t,messageManager:d,createConversation:u,switchConversation:c,deleteConversation:v,updateTitle:C,updateMetadata:A,saveConversations:f,loadConversations:S,generateTitle:P,getCurrentConversation:D}}export{O as AIClient,I as BaseModelProvider,k as ErrorType,se as FinalStatus,U as GeneratingStatus,T as LocalStorageStrategy,y 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.1",
|
|
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": "b13a1f0beb7148d219a590f00521246dfcc69a55"
|
|
30
30
|
}
|