@opentiny/tiny-robot-kit 0.4.2-alpha.4 → 0.4.2-alpha.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.
@@ -0,0 +1,212 @@
1
+ /**
2
+ * 模型Provider基类
3
+ */
4
+ declare abstract class BaseModelProvider {
5
+ protected config: AIModelConfig;
6
+ /**
7
+ * @param config AI模型配置
8
+ */
9
+ constructor(config: AIModelConfig);
10
+ /**
11
+ * 发送聊天请求并获取响应
12
+ * @param request 聊天请求参数
13
+ * @returns 聊天响应
14
+ */
15
+ abstract chat(request: ChatCompletionRequest): Promise<ChatCompletionResponse>;
16
+ /**
17
+ * 发送流式聊天请求并通过处理器处理响应
18
+ * @param request 聊天请求参数
19
+ * @param handler 流式响应处理器
20
+ */
21
+ abstract chatStream(request: ChatCompletionRequest, handler: StreamHandler): Promise<void>;
22
+ /**
23
+ * 更新配置
24
+ * @param config 新的AI模型配置
25
+ */
26
+ updateConfig(config: AIModelConfig): void;
27
+ /**
28
+ * 获取当前配置
29
+ * @returns AI模型配置
30
+ */
31
+ getConfig(): AIModelConfig;
32
+ /**
33
+ * 验证请求参数
34
+ * @param request 聊天请求参数
35
+ */
36
+ protected validateRequest(request: ChatCompletionRequest): void;
37
+ }
38
+
39
+ type MaybePromise<T> = T | Promise<T>;
40
+ /**
41
+ * 消息角色类型
42
+ */
43
+ type MessageRole = 'system' | 'user' | 'assistant';
44
+ interface ToolCall {
45
+ index: number;
46
+ id: string;
47
+ type: 'function';
48
+ function: {
49
+ name: string;
50
+ arguments: string;
51
+ result?: string;
52
+ };
53
+ }
54
+ interface MessageMetadata {
55
+ createdAt?: number;
56
+ updatedAt?: number;
57
+ id?: string;
58
+ model?: string;
59
+ [key: string]: any;
60
+ }
61
+ /**
62
+ * 聊天消息接口
63
+ */
64
+ interface ChatMessage {
65
+ role: string;
66
+ content: string;
67
+ reasoning_content?: string;
68
+ metadata?: MessageMetadata;
69
+ tool_calls?: ToolCall[];
70
+ tool_call_id?: string;
71
+ [key: string]: any;
72
+ [key: symbol]: any;
73
+ }
74
+ /**
75
+ * 聊天历史记录
76
+ */
77
+ type ChatHistory = ChatMessage[];
78
+ /**
79
+ * 聊天完成请求选项
80
+ */
81
+ interface ChatCompletionOptions {
82
+ model?: string;
83
+ temperature?: number;
84
+ top_p?: number;
85
+ n?: number;
86
+ stream?: boolean;
87
+ max_tokens?: number;
88
+ signal?: AbortSignal;
89
+ }
90
+ /**
91
+ * 聊天完成请求参数
92
+ */
93
+ interface ChatCompletionRequest {
94
+ messages: ChatMessage[];
95
+ options?: ChatCompletionOptions;
96
+ }
97
+ /**
98
+ * 聊天完成响应消息
99
+ */
100
+ interface ChatCompletionResponseMessage {
101
+ role: MessageRole;
102
+ content: string;
103
+ [x: string]: unknown;
104
+ }
105
+ /**
106
+ * 聊天完成响应选择
107
+ */
108
+ interface ChatCompletionResponseChoice {
109
+ index: number;
110
+ message: ChatCompletionResponseMessage;
111
+ finish_reason: string;
112
+ }
113
+ /**
114
+ * 聊天完成响应使用情况
115
+ */
116
+ interface ChatCompletionResponseUsage {
117
+ prompt_tokens: number;
118
+ completion_tokens: number;
119
+ total_tokens: number;
120
+ }
121
+ /**
122
+ * 聊天完成响应
123
+ */
124
+ interface ChatCompletionResponse {
125
+ id: string;
126
+ object: string;
127
+ created: number;
128
+ model: string;
129
+ choices: ChatCompletionResponseChoice[];
130
+ usage: ChatCompletionResponseUsage;
131
+ }
132
+ /**
133
+ * 流式聊天完成响应增量
134
+ */
135
+ interface ChatCompletionStreamResponseDelta {
136
+ content?: string;
137
+ role?: MessageRole;
138
+ [x: string]: unknown;
139
+ }
140
+ /**
141
+ * 流式聊天完成响应选择
142
+ */
143
+ interface ChatCompletionStreamResponseChoice {
144
+ index: number;
145
+ delta: ChatCompletionStreamResponseDelta;
146
+ finish_reason: string | null;
147
+ }
148
+ /**
149
+ * 流式聊天完成响应
150
+ */
151
+ interface ChatCompletionStreamResponse {
152
+ id: string;
153
+ object: string;
154
+ created: number;
155
+ model: string;
156
+ choices: ChatCompletionStreamResponseChoice[];
157
+ }
158
+ /**
159
+ * AI模型提供商类型
160
+ */
161
+ type AIProvider = 'openai' | 'deepseek' | 'custom';
162
+ /**
163
+ * AI模型配置接口
164
+ */
165
+ interface AIModelConfig {
166
+ provider: AIProvider;
167
+ providerImplementation?: BaseModelProvider;
168
+ apiKey?: string;
169
+ apiUrl?: string;
170
+ apiVersion?: string;
171
+ defaultModel?: string;
172
+ defaultOptions?: ChatCompletionOptions;
173
+ }
174
+ /**
175
+ * 错误类型
176
+ */
177
+ declare enum ErrorType {
178
+ NETWORK_ERROR = "network_error",
179
+ AUTHENTICATION_ERROR = "authentication_error",
180
+ RATE_LIMIT_ERROR = "rate_limit_error",
181
+ SERVER_ERROR = "server_error",
182
+ MODEL_ERROR = "model_error",
183
+ TIMEOUT_ERROR = "timeout_error",
184
+ UNKNOWN_ERROR = "unknown_error"
185
+ }
186
+ /**
187
+ * AI适配器错误
188
+ */
189
+ interface AIAdapterError {
190
+ type: ErrorType;
191
+ message: string;
192
+ statusCode?: number;
193
+ originalError?: object;
194
+ }
195
+ /**
196
+ * 流式响应事件类型
197
+ */
198
+ declare enum StreamEventType {
199
+ DATA = "data",
200
+ ERROR = "error",
201
+ DONE = "done"
202
+ }
203
+ /**
204
+ * 流式响应处理器
205
+ */
206
+ interface StreamHandler {
207
+ onData: (data: ChatCompletionStreamResponse) => void;
208
+ onError: (error: AIAdapterError) => void;
209
+ onDone: (finishReason?: string) => void;
210
+ }
211
+
212
+ export { type AIAdapterError as A, BaseModelProvider as B, type ChatCompletionOptions as C, ErrorType as E, type MaybePromise as M, StreamEventType as S, type ToolCall as T, type AIModelConfig as a, type AIProvider as b, type ChatCompletionRequest as c, type ChatCompletionResponse as d, type ChatCompletionResponseChoice as e, type ChatCompletionResponseMessage as f, type ChatCompletionResponseUsage as g, type ChatCompletionStreamResponse as h, type ChatCompletionStreamResponseChoice as i, type ChatCompletionStreamResponseDelta as j, type ChatHistory as k, type ChatMessage as l, type MessageMetadata as m, type MessageRole as n, type StreamHandler as o };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@opentiny/tiny-robot-kit",
3
- "version": "0.4.2-alpha.4",
3
+ "version": "0.4.2-alpha.6",
4
4
  "homepage": "https://docs.opentiny.design/tiny-robot/",
5
5
  "repository": {
6
6
  "type": "git",
@@ -44,11 +44,6 @@
44
44
  "types": "./dist/core.d.ts",
45
45
  "import": "./dist/core.mjs",
46
46
  "require": "./dist/core.js"
47
- },
48
- "./node": {
49
- "types": "./dist/node.d.ts",
50
- "import": "./dist/node.mjs",
51
- "require": "./dist/node.js"
52
47
  }
53
48
  },
54
49
  "files": [
@@ -56,10 +51,8 @@
56
51
  ],
57
52
  "sideEffects": false,
58
53
  "scripts": {
59
- "build": "tsup src/index.ts src/core.ts src/node.ts --format cjs,esm --dts --minify",
60
- "dev": "tsup src/index.ts src/core.ts src/node.ts --format cjs,esm --dts --watch",
61
- "lint": "eslint src",
62
- "pretest": "node scripts/download-skill-fixtures.mjs",
54
+ "build": "tsup src/index.ts src/core.ts --format cjs,esm --dts --minify",
55
+ "dev": "tsup src/index.ts src/core.ts --format cjs,esm --dts --watch",
63
56
  "test": "vitest run",
64
57
  "test:watch": "vitest"
65
58
  },
@@ -76,8 +69,7 @@
76
69
  "vue": ">=3.0.0"
77
70
  },
78
71
  "dependencies": {
79
- "idb": "^8.0.3",
80
- "yaml": "^2.8.3"
72
+ "idb": "^8.0.3"
81
73
  },
82
- "gitHead": "6a47cf299b30a57c28835726309bbc0fd12022e9"
74
+ "gitHead": "9c5e401df9d908c7c30fe1ec9887061b9e8160a9"
83
75
  }
@@ -1,5 +0,0 @@
1
- import{computed as Ce,isProxy as ye,reactive as he,ref as H,toRaw as Me}from"vue";var fe=e=>typeof e=="function"?null:Array.isArray(e)?e.length>0?new Set(e):null:new Set([e]),se=e=>{let t=new Set,o=(n,i)=>{try{n.listener(i)}catch(g){console.error("Error in message state subscriber:",g)}};return{notify:n=>{let i=new Set(Array.isArray(n)?n:[n]),g=e(),f=Array.from(t);for(let l of f){if(l.kinds){let p=!1;for(let T of l.kinds)if(i.has(T)){p=!0;break}if(!p)continue}o(l,g)}},subscribe:(n,i)=>{let g=typeof n=="function"?n:i;if(!g)throw new Error("subscribe listener is required");let f={kinds:fe(n),listener:g};return t.add(f),o(f,e()),()=>{t.delete(f)}}}};var oe=e=>he(e),Q=e=>{let t=ye(e)?Me(e):e;if(Array.isArray(t))return t.map(o=>Q(o));if(t&&typeof t=="object"){let o={};for(let[s,r]of Object.entries(t))o[s]=Q(r);return o}return t},je=()=>{let e=!1,t=H("idle"),o=H(void 0),s=H([]),r=Ce(()=>t.value==="processing"),n=p=>{if(e)throw new Error("Message state adapter is already initialized");t.value=p.requestState,o.value=p.processingState,s.value=p.messages.map(oe),e=!0},i=p=>oe(p),g=()=>{if(!e)throw new Error("Message state adapter is not initialized");return{requestState:t.value,processingState:o.value,messages:Q(s.value),isProcessing:r.value}},f=se(g);return{requestState:t,processingState:o,messages:s,isProcessing:r,initialize:n,getState:g,createMessage:i,mutate:(p,T)=>{if(!e)throw new Error("Message state adapter is not initialized");let v={get requestState(){return t.value},set requestState(F){t.value=F},get processingState(){return o.value},set processingState(F){o.value=F},get messages(){return s.value},set messages(F){s.value=F.map(i)}},N=!1;if(T(v,()=>{N=!0}),N)return;(Array.isArray(p)?p:[p]).includes("messages")&&(s.value=[...s.value]),f.notify(p)},subscribe:f.subscribe}};var X=(e={})=>{let{continueContent:t="Please continue with your previous answer.",...o}=e;return{name:"length",...o,onAfterRequest:async s=>{let{lastChoice:r,appendMessage:n,requestNext:i}=s;return r?.finish_reason==="length"&&(n({role:"user",content:t}),i()),o.onAfterRequest?.(s)}}};var re={listSkillFiles:"list_skill_files",readSkillFile:"read_skill_file"},Se="execute_skill_command",ae=[{type:"function",function:{name:re.listSkillFiles,description:"List files available from the current skills.",parameters:{type:"object",properties:{skillName:{type:"string",description:"Optional skill name. When omitted, files from all current skills are listed."}},additionalProperties:!1}}},{type:"function",function:{name:re.readSkillFile,description:"Read a file from a current skill by skill name and relative path.",parameters:{type:"object",properties:{skillName:{type:"string",description:"Skill name that owns the file."},path:{type:"string",description:"File path relative to the skill root."}},required:["skillName","path"],additionalProperties:!1}}}],Te={type:"function",function:{name:Se,description:"Execute a command in the backend runtime environment for a selected skill.",parameters:{type:"object",properties:{skillName:{type:"string",description:"Name of the current skill that provides the command instructions."},command:{type:"string",description:"Command name to execute in the skill backend runtime."},args:{type:"array",description:"Command arguments passed as argv items.",items:{type:"string"}}},required:["skillName","command","args"],additionalProperties:!1}}},Y=(e,t)=>({skillName:e,id:t.id,path:t.path,kind:t.kind,mimeType:t.mimeType,size:t.size,lastModified:t.lastModified}),Z=e=>{let t=e.function.arguments;if(!t)return{};try{let o=JSON.parse(t);return o&&typeof o=="object"&&!Array.isArray(o)?o:{}}catch{return{}}},ke=e=>Array.isArray(e)&&e.every(t=>typeof t=="string")?e:void 0,Pe=e=>{if(!e.some(s=>!!s.files?.length))return[];let o=s=>{if(!(typeof s!="string"||!s))return e.find(r=>r.name===s)};return[{tool:ae[0],handler:s=>{let r=Z(s),n=o(r.skillName);return{files:(n?[n]:e).flatMap(g=>(g.files??[]).map(f=>Y(g.name,f)))}}},{tool:ae[1],handler:s=>{let r=Z(s),n=o(r.skillName),i=typeof r.path=="string"?r.path:void 0;if(!n)return{error:"skill_not_found"};if(!i)return{error:"file_path_required",skillName:n.name};let g=n.files?.find(f=>f.path===i);return g?g.kind==="binary"?{error:"binary_file_not_readable",file:Y(n.name,g)}:{file:Y(n.name,g),content:g.content}:{error:"file_not_found",skillName:n.name,path:i}}}]},be=(e,t)=>{if(!t||e.length===0)return[];let o=s=>{if(!(typeof s!="string"||!s))return e.find(r=>r.name===s)};return[{tool:Te,handler:async s=>{let r=Z(s),n=o(r.skillName),i=typeof r.command=="string"?r.command:void 0,g=ke(r.args);return n?i?g?t({skill:n,skillName:n.name,command:i,args:g}):{error:"args_required",skillName:n.name,command:i}:{error:"command_required",skillName:n.name}:{error:"skill_not_found"}}}]},ie=(e,t={})=>[...Pe(e),...be(e,t.executeSkillCommand)],le=async e=>{let t=[];for(let o of e){let s=o.instructions?.trim();s&&t.push(`## ${o.name}
2
-
3
- ${s}`)}if(t.length!==0)return{role:"system",content:["Apply these skill instructions when generating the response.",...t].join(`
4
-
5
- `)}};var ee="__tiny_robot_skill",xe=e=>{let{getSkills:t,executeSkillCommand:o,onSkillsResolved:s,...r}=e;return{name:"skill",...r,provideTools:async n=>n.customContext[ee]?.runtimeTools??[],onTurnStart:async n=>{let i=await t?.(n)??[],g={skills:i,skillNames:i.map(f=>f.name),runtimeTools:ie(i,{executeSkillCommand:o&&(f=>o(f,n))})};return n.setCustomContext({[ee]:g}),await s?.(g,n),r.onTurnStart?.(n)},onBeforeRequest:async n=>{let i=n.customContext[ee];if(i){let g=await le(i.skills);g&&(n.requestBody.messages=[g,...n.requestBody.messages])}return r.onBeforeRequest?.(n)}}};var te=(e={})=>{let t=(o,s)=>!!o.thinking!==s||!!o.open!==s;return{name:"thinking",...e,onCompletionChunk(o){let{choice:s,currentMessage:r,updateCurrentMessage:n}=o,i=s,g=i?.message?.reasoning_content||i?.delta?.reasoning_content,f=typeof g=="string"&&g.trim()!=="";return f?r.state&&typeof r.state=="object"?t(r.state,f)&&n(l=>{l.state.thinking=!0,l.state.open=!0}):n(l=>{l.state={thinking:f,open:f}}):r.state&&typeof r.state=="object"&&"thinking"in r.state&&t(r.state,f)&&n(l=>{l.state.thinking=!1,l.state.open=!1}),e.onCompletionChunk?.(o)},onTurnEnd(o){let{currentTurn:s,mutate:r}=o,n=s.at(-1);return n?.state&&typeof n.state=="object"&&"thinking"in n.state&&t(n.state,!1)&&r("messages",()=>{n.state.thinking=!1,n.state.open=!1}),e.onTurnEnd?.(o)}}};var G=class extends Error{constructor(t){super(t),this.name="AbortError"}};function Re(e){if(e.aborted)return{promise:Promise.reject(new G(String(e.reason??"Aborted"))),cleanup:()=>{}};let t=null;return{promise:new Promise((r,n)=>{t=()=>{n(new G(String(e.reason??"Aborted")))},e.addEventListener("abort",t,{once:!0})}),cleanup:()=>{t&&(e.removeEventListener("abort",t),t=null)}}}function ge(e,t){let{promise:o,cleanup:s}=Re(t);return Promise.race([e,o]).finally(s)}function me(e,t){let o={};for(let s in e)t.includes(s)&&(o[s]=e[s]);return o}function de(e,t){let o={};for(let s in e)t.includes(s)||(o[s]=e[s]);return o}async function*J(e){if(ce(e)){yield*e;return}let t=await e;if(ce(t)){yield*t;return}yield t}function ce(e){return e&&typeof e=="object"&&typeof e[Symbol.asyncIterator]=="function"}var ne=e=>typeof e=="object"&&e!==null,ue=e=>ne(e)&&typeof e.index=="number",V=(e,t)=>{for(let[o,s]of Object.entries(t)){let r=e[o];if(r)if(typeof r=="string"&&typeof s=="string")o==="type"&&r||(e[o]=r+s);else if(Array.isArray(r)&&Array.isArray(s))if(r.every(n=>ue(n))&&s.every(n=>ue(n))){let n=new Map(r.map(l=>[l.index,l])),i=new Map(s.map(l=>[l.index,l]));for(let[l,p]of i)if(n.has(l)){let T=n.get(l);n.set(l,V(T,p))}else n.set(l,p);let g=Math.max(...Array.from(n.keys()),-1)+1,f=g>r.length?Array.from({length:g}):r;for(let[l,p]of n)f[l]=p;e[o]=f}else e[o]=[...r,...s];else ne(r)&&ne(s)&&(e[o]=V(r,s));else e[o]=s}return e};function Ae({messages:e,cancelledContent:t,createMessage:o,mutate:s}){let r=[];for(let n=0;n<e.length;n++){let i=e[n];if(i.role==="assistant"&&i.tool_calls&&i.tool_calls.length>0){let g=new Set(i.tool_calls.map(p=>p.id)),f=new Set;for(let p=n+1;p<e.length;p++){let T=e[p];T.role==="tool"&&T.tool_call_id&&g.has(T.tool_call_id)&&f.add(T.tool_call_id)}let l=i.tool_calls.map(p=>p.id).filter(p=>!f.has(p));l.length>0&&r.push({insertAfterIndex:n,missingToolCallIds:l})}}r.length!==0&&s("messages",n=>{for(let i=r.length-1;i>=0;i--){let{insertAfterIndex:g,missingToolCallIds:f}=r[i],l=f.map(p=>o({role:"tool",tool_call_id:p,content:t}));n.messages.splice(g+1,0,...l)}})}var we=e=>{let{getTools:t,beforeCallTools:o,callTool:s,onToolCallStart:r,onToolCallEnd:n,toolCallCancelledContent:i="Tool call cancelled.",toolCallFailedContent:g="Tool call failed.",autoFillMissingToolMessages:f=!1,...l}=e,p=(c,d)=>{var M,y;return c.state??(c.state={}),(M=c.state).toolCall??(M.toolCall={}),(y=c.state.toolCall)[d]??(y[d]={}),c},T=(...c)=>{let[d,{assistantMessage:M,mutate:y}]=c;y("messages",()=>{let A=p(M,d.id);A.state.toolCall[d.id].status="running"}),r?.(...c)},v=(...c)=>{let[d,{status:M,assistantMessage:y,mutate:A}]=c;A("messages",()=>{let I=p(y,d.id);I.state.toolCall[d.id].status=M}),n?.(...c)},N=c=>c.type==="function"&&"function"in c,z=c=>!!(c&&typeof c=="object"&&"tool"in c&&"handler"in c),_=c=>{let d=c;return typeof d.provideTools=="function"?d:void 0},F=(c,d)=>typeof c.disabled=="function"?c.disabled(d):!!c.disabled,L=async(c,d=[])=>{let M=[];for(let k of c.plugins){let a=_(k);!F(k,c)&&a&&M.push(...(await a.provideTools(c)).map(m=>({item:m,source:{type:"toolProvider",pluginName:k.name}})))}let y=[...M,...(await t(c)).map(k=>({item:k,source:{type:"toolPlugin"}}))],A=[],I=new Map,D=new Map,j=new Set,W=k=>{let a=k.function.name;if(j.has(a))throw new Error(`Duplicate tool name "${a}" detected. Tool names must be unique because tool calls are routed by function.name.`);j.add(a)};d.forEach(W);for(let{item:k,source:a}of y){let m=z(k)?k.tool:k;W(m),D.set(m.function.name,a),z(k)?(A.push(k.tool),I.set(k.tool.function.name,k)):A.push(k)}return{tools:A,runtimeToolMap:I,toolSourceMap:D}};return{name:"tool",...l,onTurnStart:c=>{let{getState:d,createMessage:M,mutate:y}=c,A=d().messages;return f&&Ae({messages:A,cancelledContent:i,createMessage:M,mutate:y}),l.onTurnStart?.(c)},onBeforeRequest:async c=>{let{requestBody:d}=c,M=Array.isArray(d.tools)?d.tools:[],{tools:y}=await L(c,M);return y&&y.length>0&&(d.tools=M.length?[...M,...y]:y),l.onBeforeRequest?.(c)},onAfterRequest:async c=>{let{currentMessage:d,lastChoice:M,appendMessage:y,abortSignal:A,setRequestState:I,requestNext:D,mutate:j,createMessage:W}=c;if(M?.finish_reason!=="tool_calls"||!d.tool_calls?.length)return;I("processing","calling-tools"),await o?.(d.tool_calls,{...c,assistantMessage:d});let{runtimeToolMap:k,toolSourceMap:a}=await L(c),m=d.tool_calls.map(async C=>{let S=Math.floor(Date.now()/1e3),x=!1,u=W({role:"tool",tool_call_id:C.id,content:"",metadata:{createdAt:S,updatedAt:S}});y(u);let h=N(C)?C:void 0,E=h?a.get(h.function.name)??{type:"unknown"}:{type:"unknown"},R={...c,assistantMessage:d,toolMessage:u,toolSource:E};T(C,R);try{let b=h?k.get(h.function.name):void 0,P=b&&h?b.handler(h,R):s(C,R),B=J(P);for await(let q of B)j("messages",()=>{if((typeof q=="string"&&q.length>0||q&&typeof q=="object"&&Object.keys(q).length>0)&&(x=!0),typeof q=="string")u.content+=q;else{let U={};try{let w=Array.isArray(u.content)?u.content.map(O=>O.text).join(""):u.content;U=JSON.parse(w||"{}")}catch(w){console.warn(w)}u.content=JSON.stringify(V(U,q))}u.metadata.updatedAt=Math.floor(Date.now()/1e3)});v(C,{...R,status:"success"})}catch(b){let P=b instanceof Error?b:new Error(String(b));if(A.aborted){v(C,{...R,status:"cancelled",error:P});return}console.error(b),x||j("messages",()=>{u.content=g,u.metadata.updatedAt=Math.floor(Date.now()/1e3)}),v(C,{...R,status:"failed",error:P})}});return await Promise.all(m),A.aborted||D(),l.onAfterRequest?.(c)}}};var ve=async()=>{throw new Error("Response provider is not set")},Ee=e=>{let t=[];for(let o of e){if(o.name){let s=t.findIndex(r=>r.name===o.name);s!==-1&&t.splice(s,1)}t.push(o)}return t},K=(e,t)=>typeof e.disabled=="function"?e.disabled(t):!!e.disabled,qe=(e,t={})=>{let{initialMessages:o=[],requestMessageFields:s=[],requestMessageFieldsExclude:r=["state","metadata","loading"],responseProvider:n=ve,onCompletionChunk:i,plugins:g=[]}=t,f={requestState:"idle",processingState:void 0,messages:[...o]};e.initialize(f);let l={currentTurn:[],customContext:{},abortController:null,responseProvider:n},p=[te(),X()],T=Ee(p.concat(g)),v=()=>e.getState(),N=a=>e.createMessage(a),z=e.subscribe,_=e.mutate,F=a=>!a||Object.keys(a).length===0?!1:Object.values(a).some(m=>!!m),L=a=>{let m=a;return s.length&&(m=m.map(C=>me(C,s))),r.length&&(m=m.map(C=>de(C,r))),m},c=a=>{Object.assign(l.customContext,a)},d=(a,m)=>{_("requestState",(C,S)=>{if(C.requestState===a&&C.processingState===m){S();return}C.requestState=a,C.processingState=a==="processing"?m??"requesting":void 0})},M=(...a)=>{let m=a.map(C=>N(C));return _("messages",C=>{C.messages.push(...m)}),l.currentTurn.push(...m),m},y=a=>({getState:v,createMessage:N,mutate:_,abortSignal:a,currentTurn:l.currentTurn,plugins:T,customContext:l.customContext,setRequestState:d,setCustomContext:c});async function A(a,m,C={}){d("processing","requesting");let S={messages:v().messages},x=y(m);for(let b of T.filter(P=>!K(P,x)))await b.onBeforeRequest?.({...x,requestBody:S});S.messages=L(S.messages);let u={role:"assistant",content:"",loading:!0};[u]=M(u),C.setAssistantMessage?.(u);let h=a(S,m),E=J(h),R;for await(let b of E){d("processing","completing"),_("messages",(w,O)=>{u.loading?u.loading=void 0:O()});let P=(b.choices||[]).find(w=>w.index===0)??b.choices?.[0];if(!P)continue;R=P;let B=()=>{_("messages",()=>{u.metadata||(u.metadata={});let{created:w,...O}=b;u.metadata.createdAt=w,u.metadata.updatedAt=Math.floor(Date.now()/1e3),Object.assign(u.metadata,O);let $="delta"in P&&F(P.delta)&&P.delta||"message"in P&&F(P.message)&&P.message||null;if($?.role&&(u.role=$.role),$){let{role:_e,...pe}=$;V(u,pe)}})},q=w=>{_("messages",()=>{w(u)})};if(i){let w=y(m);i({...w,chunk:b,choice:P,currentMessage:u,updateCurrentMessage:q},B)}else B();let U=y(m);for(let w of T.filter(O=>!K(O,U)))w.onCompletionChunk?.({...U,abortSignal:m,chunk:b,choice:P,currentMessage:u,updateCurrentMessage:q})}await I(u,a,m,R,C)}async function I(a,m,C,S,x){let u=!1,h=y(C),E=T.filter(R=>!K(R,h)).map(R=>{if(!R.onAfterRequest)return null;let b=B=>{M(...Array.isArray(B)?B:[B])},P=()=>{u=!0};return R.onAfterRequest({...h,currentMessage:a,lastChoice:S,appendMessage:b,requestNext:P})}).filter(R=>R!==null);await ge(Promise.all(E),C),u&&await A(m,C,x)}async function D(){let a=new AbortController;l.abortController=a,l.customContext={};let m=null,C=S=>{m=S};try{d("processing","requesting");let S=y(a.signal);for(let h of T.filter(E=>!K(E,S)))await h.onTurnStart?.(S);let x=l.responseProvider;try{await A(x,a.signal,{setAssistantMessage:C}),d("completed")}catch(h){if(a.signal.aborted||h instanceof G||h instanceof Error&&h.name==="AbortError")d("aborted");else throw h}let u=y(a.signal);for(let h of T.filter(E=>!K(E,u)))await h.onTurnEnd?.(u)}catch(S){d("error");let x=!1,u=y(a.signal);for(let h of T.filter(E=>!K(E,u)))h.onError&&(x=!0,h.onError({...u,error:S}));if(!x)throw S}finally{let S=y(a.signal);for(let x of T.filter(u=>!K(u,S)))try{x.onFinally?.(S)}catch(u){console.error(`Error in onFinally hook for plugin [${x.name||"Anonymous"}]:`,u)}l.abortController=null,l.currentTurn=[],_("messages",(x,u)=>{m?.loading?m.loading=void 0:u()})}}async function j(a){if(!a||!a.trim()){console.warn("Cannot send empty message");return}if(v().requestState==="processing"){console.warn("Cannot send message while processing is in progress");return}let m=Math.floor(Date.now()/1e3);M({role:"user",content:a.trim(),metadata:{createdAt:m,updatedAt:m}}),await D()}async function W(...a){if(v().requestState==="processing"){console.warn("Cannot send message while processing is in progress");return}M(...a),await D()}async function k(){l.abortController?.abort(),v().isProcessing&&await new Promise(a=>{let m=()=>{};m=z("requestState",C=>{C.isProcessing||(m(),a())})})}return{getState:v,subscribe:z,sendMessage:j,send:W,abort:k,setResponseProvider(a){l.responseProvider=a}}};export{se as a,je as b,X as c,ie as d,le as e,xe as f,te as g,J as h,V as i,we as j,qe as k};
@@ -1 +0,0 @@
1
- var i=n=>{let t=n.split("\\").join("/").replace(/^\.\/+/,"");return!t||t.startsWith("/")||t.includes("\0")||t.split("/").some(e=>e===".."||e==="")?null:t},l=n=>[".md",".txt",".json"].includes(s(n)),s=n=>{let t=n.split("/").at(-1)||n,e=t.lastIndexOf(".");return e===-1?"":t.slice(e).toLowerCase()};export{i as a,l as b,s as c};
package/dist/node.d.mts DELETED
@@ -1,14 +0,0 @@
1
- import { b as SkillFile } from './types-ChCZ8jKB.mjs';
2
-
3
- interface FsSkillFilesOptions {
4
- /**
5
- * 遍历时排除的目录名。
6
- */
7
- ignoredDirectories?: string[];
8
- }
9
- /**
10
- * Node.js 目录适配器,将本地 skill 目录读取为 SkillFile 记录。
11
- */
12
- declare const loadSkillFilesFromFs: (root: string, options?: FsSkillFilesOptions) => Promise<SkillFile[]>;
13
-
14
- export { type FsSkillFilesOptions, loadSkillFilesFromFs };
package/dist/node.d.ts DELETED
@@ -1,14 +0,0 @@
1
- import { b as SkillFile } from './types-ChCZ8jKB.js';
2
-
3
- interface FsSkillFilesOptions {
4
- /**
5
- * 遍历时排除的目录名。
6
- */
7
- ignoredDirectories?: string[];
8
- }
9
- /**
10
- * Node.js 目录适配器,将本地 skill 目录读取为 SkillFile 记录。
11
- */
12
- declare const loadSkillFilesFromFs: (root: string, options?: FsSkillFilesOptions) => Promise<SkillFile[]>;
13
-
14
- export { type FsSkillFilesOptions, loadSkillFilesFromFs };
package/dist/node.js DELETED
@@ -1 +0,0 @@
1
- "use strict";var F=Object.defineProperty;var S=Object.getOwnPropertyDescriptor;var x=Object.getOwnPropertyNames;var h=Object.prototype.hasOwnProperty;var g=(t,i)=>{for(var e in i)F(t,e,{get:i[e],enumerable:!0})},w=(t,i,e,n)=>{if(i&&typeof i=="object"||typeof i=="function")for(let s of x(i))!h.call(t,s)&&s!==e&&F(t,s,{get:()=>i[s],enumerable:!(n=S(i,s))||n.enumerable});return t};var y=t=>w(F({},"__esModule",{value:!0}),t);var P={};g(P,{loadSkillFilesFromFs:()=>k});module.exports=y(P);var l=require("fs/promises"),p=require("path");var d=t=>{let i=t.split("\\").join("/").replace(/^\.\/+/,"");return!i||i.startsWith("/")||i.includes("\0")||i.split("/").some(e=>e===".."||e==="")?null:i},u=t=>[".md",".txt",".json"].includes(z(t)),z=t=>{let i=t.split("/").at(-1)||t,e=i.lastIndexOf(".");return e===-1?"":i.slice(e).toLowerCase()};var k=async(t,i={})=>{let e=new Set(i.ignoredDirectories??[".git","node_modules"]),n=[],s=async a=>{let f=await(0,l.readdir)(a,{withFileTypes:!0});for(let c of f){let o=(0,p.join)(a,c.name);if(c.isDirectory()){e.has(c.name)||await s(o);continue}if(!c.isFile())continue;let r=await(0,l.stat)(o);if(!r.isFile())continue;let m=d((0,p.relative)(t,o));m&&(u(m)?n.push({path:m,kind:"text",content:await(0,l.readFile)(o,"utf-8"),size:r.size,lastModified:r.mtimeMs}):n.push({path:m,kind:"binary",content:await(0,l.readFile)(o),size:r.size,lastModified:r.mtimeMs}))}};return await s(t),n.sort((a,f)=>a.path.localeCompare(f.path))};0&&(module.exports={loadSkillFilesFromFs});
package/dist/node.mjs DELETED
@@ -1 +0,0 @@
1
- import{a as c,b as m}from"./chunk-ZO2ZONVX.mjs";import{readdir as d,readFile as f,stat as k}from"fs/promises";import{join as S,relative as u}from"path";var h=async(r,p={})=>{let F=new Set(p.ignoredDirectories??[".git","node_modules"]),o=[],a=async t=>{let n=await d(t,{withFileTypes:!0});for(let s of n){let i=S(t,s.name);if(s.isDirectory()){F.has(s.name)||await a(i);continue}if(!s.isFile())continue;let e=await k(i);if(!e.isFile())continue;let l=c(u(r,i));l&&(m(l)?o.push({path:l,kind:"text",content:await f(i,"utf-8"),size:e.size,lastModified:e.mtimeMs}):o.push({path:l,kind:"binary",content:await f(i),size:e.size,lastModified:e.mtimeMs}))}};return await a(r),o.sort((t,n)=>t.path.localeCompare(n.path))};export{h as loadSkillFilesFromFs};