@nickyzj2023/utils 1.0.82 → 1.0.84
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 +41 -8
- package/dist/index.mjs +2 -2
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -839,16 +839,18 @@ declare const qs: {
|
|
|
839
839
|
*/
|
|
840
840
|
declare const createXMLText: (tagName: string, content: any, props?: Record<string, any>) => string;
|
|
841
841
|
/**
|
|
842
|
-
*
|
|
842
|
+
* 提取文本中检测到的XML标签列表
|
|
843
843
|
* @param text 待检测文本
|
|
844
|
-
* @param
|
|
845
|
-
* @returns
|
|
844
|
+
* @param tags 可选:只提取属于该列表中的标签(不区分大小写);不传或传空数组时提取全部标签
|
|
845
|
+
* @returns 检测到的标签名数组(统一小写、按首次出现顺序去重),未检测到任何标签时返回空数组
|
|
846
846
|
* @example
|
|
847
|
-
*
|
|
848
|
-
*
|
|
849
|
-
*
|
|
847
|
+
* extractXmlTags("纯文本") // []
|
|
848
|
+
* extractXmlTags("<summary>摘要</summary>", ["summary"]) // ["summary"]
|
|
849
|
+
* extractXmlTags("<system-reminder>提醒</system-reminder>", ["summary", "system-reminder"]) // ["system-reminder"]
|
|
850
|
+
* extractXmlTags("<system-reminder>提醒</system-reminder>", ["summary"]) // []
|
|
851
|
+
* extractXmlTags("<summary>摘要</summary><foo>x</foo>") // ["summary", "foo"]
|
|
850
852
|
*/
|
|
851
|
-
declare const
|
|
853
|
+
declare const extractXmlTags: (text: string, tags?: string[]) => string[];
|
|
852
854
|
//#endregion
|
|
853
855
|
//#region src/time/debounce.d.ts
|
|
854
856
|
/**
|
|
@@ -876,10 +878,19 @@ declare const debounce: <T extends (...args: any[]) => any>(fn: T, delay?: numbe
|
|
|
876
878
|
/**
|
|
877
879
|
* 排队锁
|
|
878
880
|
*
|
|
881
|
+
* @deprecated 建议改用 Web Locks API(`navigator.locks`),本类仅保留以兼容旧代码。
|
|
882
|
+
*
|
|
883
|
+
* 废弃原因:本实现是用 Promise 链手动编排的队列,锁的释放完全依赖调用方
|
|
884
|
+
* 手动调用返回的 `release` 函数;一旦遗漏 release(例如请求抛异常后未释放),
|
|
885
|
+
* 后续所有任务会永久卡死。而 Web Locks API 是浏览器原生标准,锁在回调
|
|
886
|
+
* 执行结束(含抛异常)时自动释放,并自带排队、超时(`timeout`)、
|
|
887
|
+
* 条件获取(`ifAvailable`)等语义,更安全、更标准。
|
|
888
|
+
*
|
|
879
889
|
* @remarks
|
|
880
890
|
* 使用场景如:同时给大模型发送多条消息,使其依次回复
|
|
881
891
|
*
|
|
882
892
|
* @example
|
|
893
|
+
* // ❌ 废弃用法:手动 release,容易忘记释放导致死锁
|
|
883
894
|
* const queue = new LockQueue();
|
|
884
895
|
* const messages = [];
|
|
885
896
|
*
|
|
@@ -898,10 +909,32 @@ declare const debounce: <T extends (...args: any[]) => any>(fn: T, delay?: numbe
|
|
|
898
909
|
* chatCompletions();
|
|
899
910
|
* chatCompletions();
|
|
900
911
|
* chatCompletions();
|
|
912
|
+
*
|
|
913
|
+
* @example
|
|
914
|
+
* // ✅ 推荐用法:Web Locks API(需要运行环境支持 navigator.locks,
|
|
915
|
+
* // 如 Chrome 69+ / Edge / Firefox 96+ / Safari 15.4+)
|
|
916
|
+
* const messages = [];
|
|
917
|
+
* const LOCK_NAME = "chat-completions"; // 锁名相同的请求才会互相排队
|
|
918
|
+
*
|
|
919
|
+
* const chatCompletions = async () => {
|
|
920
|
+
* // 回调执行完(或抛异常)时自动释放锁,无需手动 release
|
|
921
|
+
* await navigator.locks.request(LOCK_NAME, async (lock) => {
|
|
922
|
+
* const message = await requestLLM();
|
|
923
|
+
* messages.push(message);
|
|
924
|
+
* sendMessage(message);
|
|
925
|
+
* });
|
|
926
|
+
* };
|
|
927
|
+
*
|
|
928
|
+
* chatCompletions();
|
|
929
|
+
* chatCompletions();
|
|
930
|
+
* chatCompletions();
|
|
901
931
|
*/
|
|
902
932
|
declare class LockQueue {
|
|
903
933
|
queue: Promise<any>;
|
|
904
934
|
constructor();
|
|
935
|
+
/**
|
|
936
|
+
* 等待前一个队列释放,返回释放当前队列的函数
|
|
937
|
+
*/
|
|
905
938
|
waitInQueue(): Promise<(value?: any) => void>;
|
|
906
939
|
}
|
|
907
940
|
//#endregion
|
|
@@ -936,4 +969,4 @@ declare const sleep: (time?: number) => Promise<unknown>;
|
|
|
936
969
|
*/
|
|
937
970
|
declare const throttle: <T extends (...args: any[]) => any>(fn: T, delay?: number) => (this: any, ...args: Parameters<T>) => void;
|
|
938
971
|
//#endregion
|
|
939
|
-
export { AI, CamelToSnake, Capitalize, type ChatCompletions, type Compact, Decapitalize, DeepMapKeys, DeepMapValues, ImageCompressionOptions, LockQueue, LoggerOptions, Primitive, RequestInit, SetTtl, SnakeToCamel, camelToSnake, capitalize, chatCompletions, compactMessages, compactStr, createXMLText, debounce, decapitalize, defineModel, defineTool, estimateTokens, extractErrorMessage, fetcher, getModelName, getRealURL,
|
|
972
|
+
export { AI, CamelToSnake, Capitalize, type ChatCompletions, type Compact, Decapitalize, DeepMapKeys, DeepMapValues, ImageCompressionOptions, LockQueue, LoggerOptions, Primitive, RequestInit, SetTtl, SnakeToCamel, camelToSnake, capitalize, chatCompletions, compactMessages, compactStr, createXMLText, debounce, decapitalize, defineModel, defineTool, estimateTokens, extractErrorMessage, extractXmlTags, fetcher, getModelName, getRealURL, imageUrlToBase64, isNil, isObject, isPrimitive, logger, loopUntil, mapKeys, mapValues, mergeObjects, omit, omitBy, parseSSE, pick, pickBy, qs, randomInt, sleep, snakeToCamel, throttle, to, withCache };
|
package/dist/index.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
const e=e=>e==null,t=e=>e?.constructor===Object,n=e=>e==null||typeof e!=`object`&&typeof e!=`function`,r=(e,n)=>Array.isArray(e)?e.map(e=>r(e,n)):t(e)?Object.keys(e).reduce((t,i)=>{let a=n(i),o=e[i];return t[a]=r(o,n),t},{}):e,i=(e,n,r)=>{let{filter:a}=r??{};if(Array.isArray(e)){let o=e.map((e,a)=>t(e)?i(e,n,r):n(e,a));return a?o.filter((e,t)=>a(e,t)):o}return t(e)?Object.keys(e).reduce((o,s)=>{let c=e[s],l;return l=t(c)||Array.isArray(c)?i(c,n,r):n(c,s),(!a||a(l,s))&&(o[s]=l),o},{}):e},a=(e,r)=>{let i={...e};for(let e of Object.keys(r)){let o=i[e],s=r[e];if(n(o)&&n(s)){i[e]=s;continue}if(Array.isArray(o)&&Array.isArray(s)){i[e]=o.concat(s);continue}if(t(o)&&t(s)){i[e]=a(o,s);continue}i[e]=s}return i},o=(e,t)=>{let n={...e};for(let e of t)delete n[e];return n},s=(e,t)=>{let n={};for(let[r,i]of Object.entries(e))t(r,i)||(n[r]=i);return n},c=(e,t)=>t.reduce((t,n)=>(Object.hasOwn(e,n)&&(t[n]=e[n]),t),{}),l=(e,t)=>{let n={};for(let[r,i]of Object.entries(e))t(r,i)&&(n[r]=i);return n},u=e=>e.replace(/_([a-zA-Z])/g,(e,t)=>t.toUpperCase()),d=e=>e.replace(/([A-Z])/g,(e,t)=>`_${t.toLowerCase()}`),f=e=>e.charAt(0).toUpperCase()+e.slice(1),p=e=>e.charAt(0).toLowerCase()+e.slice(1),m=(e=``,t)=>{if(!e)return``;let{maxLength:n=1/0,disableNewLineReplace:r=!1,disableCollapse:i=!1}=t??{},a=e;return i||(a=a.replace(/[\n\t]+/g,`
|
|
2
|
-
`)),a=r?a.replace(/\r?\n/g,` `):a.replace(/\r?\n/g,`\\n`),a=a.replace(/\s+/g,` `).trim(),n>0&&a.length>n?`${a.slice(0,n)}...`:a},h=e=>{if(e instanceof Error)return e.message;if(typeof e==`string`)return e;if(t(e)){let t=e.message||e.msg;if(t)return t;for(let t of Object.values(e)){let e=h(t);if(e)return e}}return JSON.stringify(e,null,2)},g={parse:e=>{let t=new URLSearchParams(e),n={};for(let[e,r]of t)Number.isNaN(Number(r))?n[e]=r:n[e]=Number(r);return n},stringify:(e,t)=>{let{addQueryPrefix:n=!1}=t??{},r=new URLSearchParams(e).toString();return r?n?`?${r}`:r:``}},_=(e,t,n={})=>{let r=Object.entries(n).map(([e,t])=>`${e}="${t}"`);return`<${e}${r.length>0?` ${r.join(` `)}`:``}>\n${t}\n</${e}>`},v=(e,t=[])=>{let n=new Set(t.map(e=>e.toLowerCase()));for(let t of e.matchAll(/<\/?([a-zA-Z][\w-]*)/g))
|
|
2
|
+
`)),a=r?a.replace(/\r?\n/g,` `):a.replace(/\r?\n/g,`\\n`),a=a.replace(/\s+/g,` `).trim(),n>0&&a.length>n?`${a.slice(0,n)}...`:a},h=e=>{if(e instanceof Error)return e.message;if(typeof e==`string`)return e;if(t(e)){let t=e.message||e.msg;if(t)return t;for(let t of Object.values(e)){let e=h(t);if(e)return e}}return JSON.stringify(e,null,2)},g={parse:e=>{let t=new URLSearchParams(e),n={};for(let[e,r]of t)Number.isNaN(Number(r))?n[e]=r:n[e]=Number(r);return n},stringify:(e,t)=>{let{addQueryPrefix:n=!1}=t??{},r=new URLSearchParams(e).toString();return r?n?`?${r}`:r:``}},_=(e,t,n={})=>{let r=Object.entries(n).map(([e,t])=>`${e}="${t}"`);return`<${e}${r.length>0?` ${r.join(` `)}`:``}>\n${t}\n</${e}>`},v=(e,t=[])=>{let n=new Set(t.map(e=>e.toLowerCase())),r=new Set;for(let t of e.matchAll(/<\/?([a-zA-Z][\w-]*)/g)){let e=(t[1]??``).toLowerCase();(n.size===0||n.has(e))&&r.add(e)}return[...r]},y=(n=``,r={})=>{let i=async(i,o={})=>{let s=new URL(n?`${n}${i}`:i),{params:c,parser:l,...u}=a(r,o);t(c)&&Object.entries(c).forEach(([t,n])=>{e(n)||s.searchParams.append(t,n.toString())}),(t(u.body)||Array.isArray(u.body))&&(u.body=JSON.stringify(u.body),u.headers={...u.headers,"Content-Type":`application/json`});let d=await fetch(s,u);if(!d.ok){let e=d.statusText||await d.text();try{e=h(JSON.parse(e))}catch{}throw Error(e)}return await(l?.(d)??d.json())};return{get:(e,t)=>i(e,{...t,method:`GET`}),post:(e,t,n)=>i(e,{...n,method:`POST`,body:t}),put:(e,t,n)=>i(e,{...n,method:`PUT`,body:t}),delete:(e,t)=>i(e,{...t,method:`DELETE`})}},b=async e=>{try{return[null,await e]}catch(e){return[e,void 0]}},x=async e=>{let[t,n]=await b(fetch(e,{method:`HEAD`,redirect:`manual`}));return t?e:n.headers.get(`location`)||e},S=e=>{let t=new Uint8Array(e),n=``;for(let e=0;e<t.byteLength;e++)n+=String.fromCharCode(t[e]);return btoa(n)},C=async(e,t={})=>{let{quality:n=.92,compressor:r,fetcher:i=fetch}=t;if(!e.startsWith(`http`))throw Error(`图片地址必须以http或https开头`);let a=await i(e);if(!a.ok)throw Error(`获取图片失败: ${a.statusText}`);let o=a.headers.get(`Content-Type`)||`image/jpeg`,s=await a.arrayBuffer();if(o!==`image/jpeg`&&o!==`image/png`)return`data:${o};base64,${S(s)}`;if(r)return await r(s,o,n);if(typeof OffscreenCanvas<`u`){let e=null;try{let t=new Blob([s],{type:o});e=await createImageBitmap(t);let r=new OffscreenCanvas(e.width,e.height),i=r.getContext(`2d`);if(!i)throw Error(`无法获取 OffscreenCanvas context`);return i.drawImage(e,0,0),e.close(),e=null,`data:${o};base64,${S(await(await r.convertToBlob({type:o,quality:n})).arrayBuffer())}`}catch{return e?.close(),`data:${o};base64,${S(s)}`}}return`data:${o};base64,${S(s)}`};async function*w(e){let t=e.body?.getReader();if(!t)return;let n=new TextDecoder,r=``;try{for(;;){let{value:e,done:i}=await t.read();if(i)break;r+=n.decode(e,{stream:!0});let a=r.split(`
|
|
3
3
|
|
|
4
4
|
`);r=a.pop()||``;for(let e of a){let t=e.split(`
|
|
5
5
|
`);for(let e of t){if(!e.startsWith(`data:`))continue;let t=e.replace(/^data:\s*/,``).trim();try{yield JSON.parse(t)}catch{yield t}}}}}finally{t.releaseLock()}}const T=e=>({inputs:[`text`],context:128e3,...e}),E=(e,t,n,r)=>{let i=[];return{type:`function`,function:{name:e,description:t,parameters:{type:`object`,properties:l(n,e=>e===`required`?(i.push(e),!1):!0),required:i}},handler:r}},D=async e=>{let t=(await y(e).get(`/v1/models`)).data[0]?.id;if(!t)throw Error(`无法从/models获取模型名称`);return t},O=e=>{if(!e?.length)return 0;let t=new Intl.Segmenter([],{granularity:`word`}),n=e=>{let n=0,r=0;for(let i of t.segment(e))i.isWordLike?n++:r++;return Math.ceil(n*1.5+r/4)};return e.reduce((e,t)=>{let{content:r,tool_calls:i,...a}=t;if(typeof r==`string`)e+=n(r);else for(let t of r)t.type===`text`?e+=n(t.text):e+=4096;return i&&(e+=n(JSON.stringify(i))),e+=n(JSON.stringify(a)),e},0)},k=e=>[c(e,[`type`,`function`]),c(e,[`handler`])],A=async(e,t,n)=>{let r=t.find(t=>t.function.name===e.function.name)?.handler;if(!r)return`没有找到工具“${e.function.name}”的处理函数`;try{let t=await r(JSON.parse(e.function.arguments),n);return typeof t==`string`?t:JSON.stringify(t)}catch(t){if(t instanceof Error&&t.name===e.function.name)throw t;return`工具“${e.function.name}”处理失败:${h(t)}`}},j=e=>e.reasoning||e.reasoning_content,M=e=>typeof e==`string`?e:e.filter(e=>e.type===`text`).map(e=>e.text).join(`
|
|
6
6
|
`),N=e=>{switch(e.type){case`text`:return`text`;case`image_url`:return`image`;case`input_audio`:return`audio`;case`video_url`:return`video`}},P=(e,t)=>{let{inputs:n=[`text`]}=e;for(let e of t){let{content:t}=e;if(typeof t!=`string`&&Array.isArray(t))for(let e of t){let t=N(e);if(!t||!n.includes(t))return t||`unknown`}}return``},F=async(e,t,n=[],r)=>{let{onToolHandled:i}=r??{};for(;;){let{choices:r,usage:a,...o}=await e.post(`/chat/completions`,{}),{message:s}=r?.[0]??{};if(!s)throw Error(`模型没有回复任何内容`);t.push(s);let{content:c=``,tool_calls:l=[],...u}=s,d=j(s);if(l.length>0&&n.length>0){for(let e of l){let r=await A(e,n,{messages:t});t.push({role:`tool`,content:r,tool_call_id:e.id}),i?.(e.function.name,e.function.arguments,r)}continue}return{content:M(c),reasoning:d,usage:a,...o,...u}}},I=async function*(e,t,n=[],r){let{onToolHandled:i}=r??{};for(;;){let r=new Map,a=``,o=null,s,c=await e.post(`/chat/completions`,{stream:!0},{parser:async e=>e});for await(let e of w(c)){e.usage&&(s=e.usage);let t=e.choices?.[0];if(!t)continue;let{delta:n}=t,{content:i,tool_calls:c}=n,l=j(n);if(l&&(yield{reasoning:l}),i&&(a+=i,yield{content:i}),c)for(let e of c){let t=r.get(e.index)??{id:``,type:`function`,function:{name:``,arguments:``}};e.id&&(t.id=e.id),e.function?.name&&(t.function.name+=e.function.name),e.function?.arguments&&(t.function.arguments+=e.function.arguments),r.set(e.index,t)}t.finish_reason&&(o=t.finish_reason)}let l=Array.from(r.values());if(o===`tool_calls`&&l.length>0&&n.length>0){t.push({role:`assistant`,content:a,tool_calls:l});for(let e of l){let r=await A(e,n,{messages:t});t.push({role:`tool`,content:r,tool_call_id:e.id}),i?.(e.function.name,e.function.arguments,r)}continue}t.push({role:`assistant`,content:a}),s&&(yield{usage:s});break}};async function L(e,t,n){let{baseUrl:r,apiKey:i=``,model:a,customBody:o,inputs:s,...c}=e,{stream:l,tools:u=[],...d}=n??{},f=P(e,t);if(f)throw Error(`当前上下文含有模型不支持的输入类型:${f}`);let p=y(r,{headers:{Authorization:`Bearer ${i}`},body:{model:a??await D(r),messages:t,tools:u?.map(e=>k(e)[0]),...o}});return(l?I:F)(p,t,u,{...d,...c})}function R(e={},t=0){let{withTime:n=!0,withFileName:r=!0}=e;return(...e)=>{let i=[];if(n&&i.push(`[${new Date().toLocaleTimeString()}]`),r){let{stack:e}=Error(),n=(e?.split(`
|
|
7
|
-
`)[2+t]?.trim())?.match(/^at\s+(?:.*?\s*\()?(.*?):(\d+)(?::(\d+))?\)?/);if(n?.[1]){let e=n[1].split(/[/\\]/).pop();i.push(`[${e}:${n[2]}]`)}}i.push(...e),console.log(...i)}}function z(e,...n){if(t(e)&&(`withTime`in e||`withFileName`in e))return R(e,0);R({},1)(e,...n)}const B=e=>{if(e.role===`system`)return!1;let t;if(typeof e.content==`string`)t=e.content;else if(Array.isArray(e.content))t=e.content.filter(e=>e.type===`text`).map(e=>e.text).join(``);else return!1;
|
|
7
|
+
`)[2+t]?.trim())?.match(/^at\s+(?:.*?\s*\()?(.*?):(\d+)(?::(\d+))?\)?/);if(n?.[1]){let e=n[1].split(/[/\\]/).pop();i.push(`[${e}:${n[2]}]`)}}i.push(...e),console.log(...i)}}function z(e,...n){if(t(e)&&(`withTime`in e||`withFileName`in e))return R(e,0);R({},1)(e,...n)}const B=e=>{if(e.role===`system`)return!1;let t;if(typeof e.content==`string`)t=e.content;else if(Array.isArray(e.content))t=e.content.filter(e=>e.type===`text`).map(e=>e.text).join(``);else return!1;let n=v(t);return n.length===0||n.every(e=>e===`summary`)},V=e=>e?.role===`assistant`&&Array.isArray(e.tool_calls),H=(e,t)=>{for(t=Math.min(t,e.length);e[t]?.role===`tool`;)t++;return t},U=(e,t)=>{let n=e.reduce((e,n)=>(n.role===`tool`&&(n.content=t(n.content),e++),e),0);n>0&&z(`软删除了${n}条工具调用结果消息`)},W=(e,t)=>{let n=[`image_url`,`input_audio`,`video_url`],r=e.reduce((e,r)=>(Array.isArray(r.content)&&r.content.some(e=>n.includes(e.type))&&(r.content=t(r.content),e++),e),0);r>0&&z(`软删除了${r}条旧图片/音频/视频消息`)},G=async(e,t)=>{let{model:n,keepCount:r,systemPrompt:i}=t??{},a=e.length-r;if(a<=0){z(`消息太少,无需总结`);return}a=H(e,a);let o=[],s=[];for(let t=0;t<a;t++){let n=e[t];if(n){if(V(n)){let n=t+1;for(;n<a&&e[n]?.role===`tool`;)n++;let r=e.slice(t,n);if(r.every(B)){for(let e=t;e<n;e++)o.push(e);s.push(...r)}t=n-1;continue}n.role!==`tool`&&B(n)&&(o.push(t),s.push(n))}}if(o.length===0){z(`没有可总结的消息`);return}s.push({role:`system`,content:i},{role:`user`,content:`开始总结上下文`});let[c,l]=await b(L(n,s));if(c){z(`总结失败:${c.message}`);return}let u=o[0]??0;for(let t=o.length-1;t>=0;t--){let n=o[t];n!==void 0&&e.splice(n,1)}e.splice(u,0,{role:`user`,content:_(`summary`,l.content)})},K=(e,t)=>{let n=e.findIndex(e=>e.role===`user`),r=e.length-t;if(r<=n){z(`消息太少,无需硬删除`);return}r=H(e,r);let i=r-n;e.splice(n,i),z(`硬删除了${i}条较早的消息`)},q=async(e,t,n)=>{let{usage:r,ratioToCompactToolResult:i=.6,replacerOfToolResultContent:a=()=>`已被消费`,ratioToCompactMedia:o=.7,replacerOfMediaContent:s=()=>`已被丢弃`,ratioToSummarize:c=.8,summarizeOptions:l}=n??{},u=t?.context??128e3,d=r?.total_tokens??O(e);if(d>u*i&&U(e,a),d>u*o&&W(e,s),d>u*c){let{keepCount:n=10,systemPrompt:r=`总结历史消息`}=l??{},[i]=await b(G(e,{model:t,keepCount:n,systemPrompt:r}));if(!i)return;K(e,n)}},J=async(e,t)=>{let{maxRetries:n=5,shouldStop:r}=t??{},i;for(let t=0;t<n;t++)if(i=await e(t),r?.(i)===!0)return i;if(!r)return i;throw Error(`超过了最大循环次数(${n})且未满足停止执行条件`)},Y=(e,t=-1)=>{let n=new Map,r=(...r)=>{let i=JSON.stringify(r),a=Date.now(),o=n.get(i);if(o&&a<o.expiresAt)return o.value;let s=t===-1?1/0:a+t*1e3,c=e.apply({setTtl:e=>{s=a+e*1e3}},r);if(c instanceof Promise){let e=c.then(e=>(n.set(i,{value:e,expiresAt:s}),e));return n.set(i,{value:e,expiresAt:s}),e}return n.set(i,{value:c,expiresAt:s}),c};return r.clear=()=>n.clear(),r.updateTtl=e=>{t=e;let r=Date.now(),i=r+e*1e3;for(let[e,t]of n.entries())t.expiresAt>r&&(t.expiresAt=i,n.set(e,t))},r},X=(e,t)=>Math.floor(Math.random()*(t-e+1))+e,Z=(e,t=300)=>{let n=null;return(...r)=>{n&&clearTimeout(n),n=setTimeout(()=>{e(...r)},t)}};var Q=class{queue;constructor(){this.queue=Promise.resolve()}waitInQueue(){let e,t=new Promise(t=>{e=t}),n=this.queue.then(()=>e);return this.queue=t,n}};const $=async(e=150)=>new Promise(t=>{setTimeout(t,e)}),ee=(e,t=300)=>{let n=null;return function(...r){n||=setTimeout(()=>{n=null,e.apply(this,r)},t)}};export{Q as LockQueue,d as camelToSnake,f as capitalize,L as chatCompletions,q as compactMessages,m as compactStr,_ as createXMLText,Z as debounce,p as decapitalize,T as defineModel,E as defineTool,O as estimateTokens,h as extractErrorMessage,v as extractXmlTags,y as fetcher,D as getModelName,x as getRealURL,C as imageUrlToBase64,e as isNil,t as isObject,n as isPrimitive,z as logger,J as loopUntil,r as mapKeys,i as mapValues,a as mergeObjects,o as omit,s as omitBy,w as parseSSE,c as pick,l as pickBy,g as qs,X as randomInt,$ as sleep,u as snakeToCamel,ee as throttle,b as to,Y as withCache};
|