@ztimson/ai-utils 0.1.18 → 0.1.19
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.js +9 -9
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +132 -123
- package/dist/index.mjs.map +1 -1
- package/dist/llm.d.ts +2 -2
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,20 +1,20 @@
|
|
|
1
|
-
(function(
|
|
1
|
+
(function(p,b){typeof exports=="object"&&typeof module<"u"?b(exports,require("tesseract.js"),require("@ztimson/utils"),require("@anthropic-ai/sdk"),require("ollama"),require("openai"),require("node:fs/promises"),require("node:path"),require("@tensorflow/tfjs"),require("node:child_process"),require("@ztimson/node-utils")):typeof define=="function"&&define.amd?define(["exports","tesseract.js","@ztimson/utils","@anthropic-ai/sdk","ollama","openai","node:fs/promises","node:path","@tensorflow/tfjs","node:child_process","@ztimson/node-utils"],b):(p=typeof globalThis<"u"?globalThis:p||self,b(p.utils={},p.tesseract_js,p.utils,p.sdk,p.ollama,p.openai,p.fs,p.Path,p.tf,p.node_child_process,p.nodeUtils))})(this,(function(p,b,f,A,M,D,j,E,J,N,x){"use strict";function z(u){const t=Object.create(null,{[Symbol.toStringTag]:{value:"Module"}});if(u){for(const e in u)if(e!=="default"){const n=Object.getOwnPropertyDescriptor(u,e);Object.defineProperty(t,e,n.get?n:{enumerable:!0,get:()=>u[e]})}}return t.default=u,Object.freeze(t)}const S=z(J);class k{}class T extends k{constructor(t,e,n){super(),this.ai=t,this.apiToken=e,this.model=n,this.client=new A.Anthropic({apiKey:e})}client;toStandard(t){for(let e=0;e<t.length;e++){const n=e;typeof t[n].content!="string"&&(t[n].role=="assistant"?t[n].content.filter(s=>s.type=="tool_use").forEach(s=>{e++,t.splice(e,0,{role:"tool",id:s.id,name:s.name,args:s.input,timestamp:Date.now()})}):t[n].role=="user"&&t[n].content.filter(s=>s.type=="tool_result").forEach(s=>{const l=t.find(h=>h.id==s.tool_use_id);l[s.is_error?"error":"content"]=s.content}),t[n].content=t[n].content.filter(s=>s.type=="text").map(s=>s.text).join(`
|
|
2
2
|
|
|
3
|
-
`)),t[n].timestamp||(t[n].timestamp=Date.now())}return t.filter(e=>!!e.content)}fromStandard(t){for(let e=0;e<t.length;e++)if(t[e].role=="tool"){const n=t[e];t.splice(e,1,{role:"assistant",content:[{type:"tool_use",id:n.id,name:n.name,input:n.args}]
|
|
3
|
+
`)),t[n].timestamp||(t[n].timestamp=Date.now())}return t.filter(e=>!!e.content)}fromStandard(t){for(let e=0;e<t.length;e++)if(t[e].role=="tool"){const n=t[e];t.splice(e,1,{role:"assistant",content:[{type:"tool_use",id:n.id,name:n.name,input:n.args}]},{role:"user",content:[{type:"tool_result",tool_use_id:n.id,is_error:!!n.error,content:n.error||n.content}]}),e++}return t.map(({timestamp:e,...n})=>n)}ask(t,e={}){const n=new AbortController,s=new Promise(async(l,h)=>{let m=this.fromStandard([...e.history||[],{role:"user",content:t,timestamp:Date.now()}]);e.compress&&(m=await this.ai.llm.compress(m,e.compress.max,e.compress.min,e));const d={model:e.model||this.model,max_tokens:e.max_tokens||this.ai.options.max_tokens||4096,system:e.system||this.ai.options.system||"",temperature:e.temperature||this.ai.options.temperature||.7,tools:(e.tools||this.ai.options.tools||[]).map(a=>({name:a.name,description:a.description,input_schema:{type:"object",properties:a.args?f.objectMap(a.args,(o,i)=>({...i,required:void 0})):{},required:a.args?Object.entries(a.args).filter(o=>o[1].required).map(o=>o[0]):[]},fn:void 0})),messages:m,stream:!!e.stream};let c;const r=[];do{if(c=await this.client.messages.create(d),e.stream){r.length&&e.stream({text:`
|
|
4
4
|
|
|
5
|
-
`}),
|
|
5
|
+
`}),c.content=[];for await(const o of c){if(n.signal.aborted)break;if(o.type==="content_block_start")o.content_block.type==="text"?c.content.push({type:"text",text:""}):o.content_block.type==="tool_use"&&c.content.push({type:"tool_use",id:o.content_block.id,name:o.content_block.name,input:""});else if(o.type==="content_block_delta")if(o.delta.type==="text_delta"){const i=o.delta.text;c.content.at(-1).text+=i,e.stream({text:i})}else o.delta.type==="input_json_delta"&&(c.content.at(-1).input+=o.delta.partial_json);else if(o.type==="content_block_stop"){const i=c.content.at(-1);i.input!=null&&(i.input=i.input?f.JSONAttemptParse(i.input,{}):{})}else if(o.type==="message_stop")break}}r.push({role:"assistant",content:c.content,timestamp:Date.now()});const a=c.content.filter(o=>o.type==="tool_use");if(a.length&&!n.signal.aborted){m.push({role:"assistant",content:c.content});const i={role:"user",content:await Promise.all(a.map(async g=>{const w=e.tools?.find(f.findByProp("name",g.name));if(!w)return{tool_use_id:g.id,is_error:!0,content:"Tool not found"};try{const _=await w.fn(g.input,this.ai);return{type:"tool_result",tool_use_id:g.id,content:f.JSONSanitize(_)}}catch(_){return{type:"tool_result",tool_use_id:g.id,is_error:!0,content:_?.message||_?.toString()||"Unknown"}}}))};m.push(i),r.push({...i,timestamp:Date.now()}),d.messages=m}}while(!n.signal.aborted&&c.content.some(a=>a.type==="tool_use"));const y=r.filter(a=>a.role==="assistant").map(a=>a.content.filter(o=>o.type=="text").map(o=>o.text).join(`
|
|
6
6
|
|
|
7
7
|
`)).filter(a=>a).join(`
|
|
8
8
|
|
|
9
|
-
`);e.stream&&e.stream({done:!0}),
|
|
9
|
+
`);e.stream&&e.stream({done:!0}),l(this.toStandard([...m,{role:"assistant",content:y,timestamp:Date.now()}]))});return Object.assign(s,{abort:()=>n.abort()})}}class U extends k{constructor(t,e,n){super(),this.ai=t,this.host=e,this.model=n,this.client=new M.Ollama({host:e})}client;toStandard(t){for(let e=0;e<t.length;e++){if(t[e].role=="assistant"&&t[e].tool_calls)t[e].content?delete t[e].tool_calls:(t.splice(e,1),e--);else if(t[e].role=="tool"){const n=t[e].content.startsWith('{"error":');t[e]={role:"tool",name:t[e].tool_name,args:t[e].args,[n?"error":"content"]:t[e].content,timestamp:t[e].timestamp}}t[e]?.timestamp||(t[e].timestamp=Date.now())}return t}fromStandard(t){return t.map(e=>{const{timestamp:n,...s}=e;return e.role!="tool"?s:{role:"tool",tool_name:e.name,content:e.error||e.content}})}ask(t,e={}){const n=new AbortController,s=new Promise(async(l,h)=>{let m=e.system||this.ai.options.system,d=this.fromStandard([...e.history||[],{role:"user",content:t,timestamp:Date.now()}]);d[0].roll=="system"&&(m?d.shift():m=d.shift()),e.compress&&(d=await this.ai.llm.compress(d,e.compress.max,e.compress.min)),e.system&&d.unshift({role:"system",content:m});const c={model:e.model||this.model,messages:d,stream:!!e.stream,signal:n.signal,options:{temperature:e.temperature||this.ai.options.temperature||.7,num_predict:e.max_tokens||this.ai.options.max_tokens||4096},tools:(e.tools||this.ai.options.tools||[]).map(o=>({type:"function",function:{name:o.name,description:o.description,parameters:{type:"object",properties:o.args?f.objectMap(o.args,(i,g)=>({...g,required:void 0})):{},required:o.args?Object.entries(o.args).filter(i=>i[1].required).map(i=>i[0]):[]}}}))};let r;const y=[];do{if(r=await this.client.chat(c),e.stream){y.length&&e.stream({text:`
|
|
10
10
|
|
|
11
|
-
`}),r.message={role:"assistant",content:"",tool_calls:[]};for await(const o of r)if(n.signal.aborted||(o.message?.content&&(r.message.content+=o.message.content,e.stream({text:o.message.content})),o.message?.tool_calls&&(r.message.tool_calls=o.message.tool_calls),o.done))break}if(y.push({role:"assistant",content:r.message?.content,timestamp:Date.now()}),r.message?.tool_calls?.length&&!n.signal.aborted){d.push(
|
|
11
|
+
`}),r.message={role:"assistant",content:"",tool_calls:[]};for await(const o of r)if(n.signal.aborted||(o.message?.content&&(r.message.content+=o.message.content,e.stream({text:o.message.content})),o.message?.tool_calls&&(r.message.tool_calls=o.message.tool_calls),o.done))break}if(y.push({role:"assistant",content:r.message?.content,timestamp:Date.now()}),r.message?.tool_calls?.length&&!n.signal.aborted){d.push(r.message);const o=await Promise.all(r.message.tool_calls.map(async i=>{const g=(e.tools||this.ai.options.tools)?.find(f.findByProp("name",i.function.name));if(!g)return{role:"tool",tool_name:i.function.name,content:'{"error": "Tool not found"}'};const w=typeof i.function.arguments=="string"?f.JSONAttemptParse(i.function.arguments,{}):i.function.arguments;try{const _=await g.fn(w,this.ai);return{role:"tool",tool_name:i.function.name,args:w,content:f.JSONSanitize(_)}}catch(_){return{role:"tool",tool_name:i.function.name,args:w,content:f.JSONSanitize({error:_?.message||_?.toString()||"Unknown"})}}}));d.push(...o),y.push(...o.map(i=>({...i,timestamp:Date.now()}))),c.messages=d}}while(!n.signal.aborted&&r.message?.tool_calls?.length);const a=y.filter(o=>o.role==="assistant").map(o=>o.content).filter(o=>o).join(`
|
|
12
12
|
|
|
13
|
-
`);e.stream&&e.stream({done:!0}),
|
|
13
|
+
`);e.stream&&e.stream({done:!0}),l(this.toStandard([...d,{role:"assistant",content:a,timestamp:Date.now()}]))});return Object.assign(s,{abort:()=>n.abort()})}}class L extends k{constructor(t,e,n){super(),this.ai=t,this.apiToken=e,this.model=n,this.client=new D.OpenAI({apiKey:e})}client;toStandard(t){for(let e=0;e<t.length;e++){const n=t[e];if(n.role==="assistant"&&n.tool_calls){const s=n.tool_calls.map(l=>({role:"tool",id:l.id,name:l.function.name,args:f.JSONAttemptParse(l.function.arguments,{}),timestamp:n.timestamp}));t.splice(e,1,...s),e+=s.length-1}else if(n.role==="tool"&&n.content){const s=t.find(l=>n.tool_call_id==l.id);s&&(n.content.includes('"error":')?s.error=n.content:s.content=n.content),t.splice(e,1),e--}t[e]?.timestamp||(t[e].timestamp=Date.now())}return t}fromStandard(t){return t.reduce((e,n)=>{if(n.role==="tool")e.push({role:"assistant",content:null,tool_calls:[{id:n.id,type:"function",function:{name:n.name,arguments:JSON.stringify(n.args)}}],refusal:null,annotations:[]},{role:"tool",tool_call_id:n.id,content:n.error||n.content});else{const{timestamp:s,...l}=n;e.push(l)}return e},[])}ask(t,e={}){const n=new AbortController,s=new Promise(async(l,h)=>{let m=this.fromStandard([...e.history||[],{role:"user",content:t,timestamp:Date.now()}]);e.compress&&(m=await this.ai.llm.compress(m,e.compress.max,e.compress.min,e));const d={model:e.model||this.model,messages:m,stream:!!e.stream,max_tokens:e.max_tokens||this.ai.options.max_tokens||4096,temperature:e.temperature||this.ai.options.temperature||.7,tools:(e.tools||this.ai.options.tools||[]).map(a=>({type:"function",function:{name:a.name,description:a.description,parameters:{type:"object",properties:a.args?f.objectMap(a.args,(o,i)=>({...i,required:void 0})):{},required:a.args?Object.entries(a.args).filter(o=>o[1].required).map(o=>o[0]):[]}}}))};let c;const r=[];do{if(c=await this.client.chat.completions.create(d),e.stream){r.length&&e.stream({text:`
|
|
14
14
|
|
|
15
|
-
`}),
|
|
15
|
+
`}),c.choices=[{message:{content:"",tool_calls:[]}}];for await(const o of c){if(n.signal.aborted)break;o.choices[0].delta.content&&(c.choices[0].message.content+=o.choices[0].delta.content,e.stream({text:o.choices[0].delta.content})),o.choices[0].delta.tool_calls&&(c.choices[0].message.tool_calls=o.choices[0].delta.tool_calls)}}r.push({role:"assistant",content:c.choices[0].message.content||"",timestamp:Date.now()});const a=c.choices[0].message.tool_calls||[];if(a.length&&!n.signal.aborted){m.push(c.choices[0].message);const o=await Promise.all(a.map(async i=>{const g=e.tools?.find(f.findByProp("name",i.function.name));if(!g)return{role:"tool",tool_call_id:i.id,content:'{"error": "Tool not found"}'};try{const w=f.JSONAttemptParse(i.function.arguments,{}),_=await g.fn(w,this.ai);return{role:"tool",tool_call_id:i.id,content:f.JSONSanitize(_)}}catch(w){return{role:"tool",tool_call_id:i.id,content:f.JSONSanitize({error:w?.message||w?.toString()||"Unknown"})}}}));m.push(...o),r.push(...o.map(i=>({...i,timestamp:Date.now()}))),d.messages=m}}while(!n.signal.aborted&&c.choices?.[0]?.message?.tool_calls?.length);const y=r.filter(a=>a.role==="assistant").map(a=>a.content).filter(a=>a).join(`
|
|
16
16
|
|
|
17
|
-
`);e.stream&&e.stream({done:!0}),
|
|
17
|
+
`);e.stream&&e.stream({done:!0}),l(this.toStandard([...m,{role:"assistant",content:y,timestamp:Date.now()}]))});return Object.assign(s,{abort:()=>n.abort()})}}class q{constructor(t,e){this.ai=t,this.options=e,e.anthropic?.token&&(this.providers.anthropic=new T(this.ai,e.anthropic.token,e.anthropic.model)),e.ollama?.host&&(this.providers.ollama=new U(this.ai,e.ollama.host,e.ollama.model)),e.openAi?.token&&(this.providers.openAi=new L(this.ai,e.openAi.token,e.openAi.model))}providers={};ask(t,e={}){let n=[null,null];if(e.model&&(typeof e.model=="object"?n=e.model:n=[e.model,this.options[e.model]?.model]),(!e.model||n[1]==null)&&(typeof this.options.model=="object"?n=this.options.model:n=[this.options.model,this.options[this.options.model]?.model]),!n[0]||!n[1])throw new Error(`Unknown LLM provider or model: ${n[0]} / ${n[1]}`);return this.providers[n[0]].ask(t,{...e,model:n[1]})}async compress(t,e,n,s){if(this.estimateTokens(t)<e)return t;let l=0,h=0;for(let r of t.toReversed())if(h+=this.estimateTokens(r.content),h<n)l++;else break;if(t.length<=l)return t;const m=l==0?[]:t.slice(-l),d=(l==0?t:t.slice(0,-l)).filter(r=>r.role==="assistant"||r.role==="user");return[{role:"assistant",content:`Conversation Summary: ${await this.summarize(d.map(r=>`${r.role}: ${r.content}`).join(`
|
|
18
18
|
|
|
19
|
-
`),250,s)}`,timestamp:Date.now()},...
|
|
19
|
+
`),250,s)}`,timestamp:Date.now()},...m]}estimateTokens(t){const e=JSON.stringify(t);return Math.ceil(e.length/4*1.2)}async json(t,e){let n=await this.ask(t,{system:"Respond using a JSON blob",...e});return n?.[0]?.content?f.JSONAttemptParse(new RegExp("{[sS]*}").exec(n[0].content),{}):{}}summarize(t,e,n){return this.ask(t,{system:`Generate a brief summary <= ${e} tokens. Output nothing else`,temperature:.3,...n}).then(s=>s.pop()?.content||null)}}class ${constructor(t){this.options=t,this.llm=new q(this,t),this.options.whisper?.binary&&(this.whisperModel=this.options.whisper?.model.endsWith(".bin")?this.options.whisper?.model:this.options.whisper?.model+".bin",this.downloadAsrModel())}downloads={};whisperModel;llm;asr(t,e=this.whisperModel){if(!this.options.whisper?.binary)throw new Error("Whisper not configured");let n=()=>{};return{response:new Promise((l,h)=>{this.downloadAsrModel(e).then(m=>{let d="";const c=N.spawn(this.options.whisper?.binary,["-nt","-np","-m",m,"-f",t],{stdio:["ignore","pipe","ignore"]});n=()=>c.kill("SIGTERM"),c.on("error",r=>h(r)),c.stdout.on("data",r=>d+=r.toString()),c.on("close",r=>{r===0?l(d.trim()||null):h(new Error(`Exit code ${r}`))})})}),abort:n}}async downloadAsrModel(t=this.whisperModel){if(!this.options.whisper?.binary)throw new Error("Whisper not configured");t.endsWith(".bin")||(t+=".bin");const e=E.join(this.options.whisper.path,t);return await j.stat(e).then(()=>!0).catch(()=>!1)?e:this.downloads[t]?this.downloads[t]:(this.downloads[t]=fetch(`https://huggingface.co/ggerganov/whisper.cpp/resolve/main/${t}`).then(n=>n.arrayBuffer()).then(n=>Buffer.from(n)).then(async n=>(await j.writeFile(e,n),delete this.downloads[t],e)),this.downloads[t])}ocr(t){let e;return{abort:()=>{e?.terminate()},response:new Promise(async n=>{e=await b.createWorker("eng");const{data:s}=await e.recognize(t);await e.terminate(),n(s.text.trim()||null)})}}semanticSimilarity(t,...e){if(e.length<2)throw new Error("Requires at least 2 strings to compare");const n=(m,d=10)=>m.toLowerCase().split("").map((c,r)=>c.charCodeAt(0)*(r+1)%d/d).slice(0,d),s=(m,d)=>{if(m.length!==d.length)throw new Error("Vectors must be same length");const c=S.tensor1d(m),r=S.tensor1d(d),y=S.dot(c,r),a=S.norm(c),o=S.norm(r);return a.dataSync()[0]===0||o.dataSync()[0]===0?0:y.dataSync()[0]/(a.dataSync()[0]*o.dataSync()[0])},l=n(t),h=e.map(m=>n(m)).map(m=>s(l,m));return{avg:h.reduce((m,d)=>m+d,0)/h.length,max:Math.max(...h),similarities:h}}}const P={name:"cli",description:"Use the command line interface, returns any output",args:{command:{type:"string",description:"Command to run",required:!0}},fn:u=>x.$`${u.command}`},R={name:"get_datetime",description:"Get current date and time",args:{},fn:async()=>new Date().toISOString()},I={name:"exec",description:"Run code/scripts",args:{language:{type:"string",description:"Execution language",enum:["cli","node","python"],required:!0},code:{type:"string",description:"Code to execute",required:!0}},fn:async(u,t)=>{try{switch(u.type){case"bash":return await P.fn({command:u.code},t);case"node":return await O.fn({code:u.code},t);case"python":return await v.fn({code:u.code},t)}}catch(e){return{error:e?.message||e.toString()}}}},W={name:"fetch",description:"Make HTTP request to URL",args:{url:{type:"string",description:"URL to fetch",required:!0},method:{type:"string",description:"HTTP method to use",enum:["GET","POST","PUT","DELETE"],default:"GET"},headers:{type:"object",description:"HTTP headers to send",default:{}},body:{type:"object",description:"HTTP body to send"}},fn:u=>new f.Http({url:u.url,headers:u.headers}).request({method:u.method||"GET",body:u.body})},O={name:"exec_javascript",description:"Execute commonjs javascript",args:{code:{type:"string",description:"CommonJS javascript",required:!0}},fn:async u=>{const t=f.consoleInterceptor(null),e=await f.fn({console:t},u.code,!0).catch(n=>t.output.error.push(n));return{...t.output,return:e,stdout:void 0,stderr:void 0}}},v={name:"exec_javascript",description:"Execute commonjs javascript",args:{code:{type:"string",description:"CommonJS javascript",required:!0}},fn:async u=>({result:x.$Sync`python -c "${u.code}"`})},C={name:"search",description:"Use a search engine to find relevant URLs, should be changed with fetch to scrape sources",args:{query:{type:"string",description:"Search string",required:!0},length:{type:"string",description:"Number of results to return",default:5}},fn:async u=>{const t=await fetch(`https://html.duckduckgo.com/html/?q=${encodeURIComponent(u.query)}`,{headers:{"User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64)","Accept-Language":"en-US,en;q=0.9"}}).then(l=>l.text());let e,n=/<a .*?href="(.+?)".+?<\/a>/g;const s=new f.ASet;for(;(e=n.exec(t))!==null;){let l=/uddg=(.+)&?/.exec(decodeURIComponent(e[1]))?.[1];if(l&&(l=decodeURIComponent(l)),l&&s.add(l),s.size>=(u.length||5))break}return s}};p.Ai=$,p.Anthropic=T,p.CliTool=P,p.DateTimeTool=R,p.ExecTool=I,p.FetchTool=W,p.JSTool=O,p.LLM=q,p.PythonTool=v,p.SearchTool=C,Object.defineProperty(p,Symbol.toStringTag,{value:"Module"})}));
|
|
20
20
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../src/provider.ts","../src/antrhopic.ts","../src/ollama.ts","../src/open-ai.ts","../src/llm.ts","../src/ai.ts","../src/tools.ts"],"sourcesContent":["import {LLMMessage, LLMOptions, LLMRequest} from './llm.ts';\n\nexport type AbortablePromise<T> = Promise<T> & {abort: () => void};\n\nexport abstract class LLMProvider {\n\tabstract ask(message: string, options: LLMRequest): AbortablePromise<LLMMessage[]>;\n}\n","import {Anthropic as anthropic} from '@anthropic-ai/sdk';\nimport {findByProp, objectMap, JSONSanitize, JSONAttemptParse} from '@ztimson/utils';\nimport {Ai} from './ai.ts';\nimport {LLMMessage, LLMRequest} from './llm.ts';\nimport {AbortablePromise, LLMProvider} from './provider.ts';\n\nexport class Anthropic extends LLMProvider {\n\tclient!: anthropic;\n\n\tconstructor(public readonly ai: Ai, public readonly apiToken: string, public model: string) {\n\t\tsuper();\n\t\tthis.client = new anthropic({apiKey: apiToken});\n\t}\n\n\tprivate toStandard(history: any[]): LLMMessage[] {\n\t\tfor(let i = 0; i < history.length; i++) {\n\t\t\tconst orgI = i;\n\t\t\tif(typeof history[orgI].content != 'string') {\n\t\t\t\tif(history[orgI].role == 'assistant') {\n\t\t\t\t\thistory[orgI].content.filter((c: any) => c.type =='tool_use').forEach((c: any) => {\n\t\t\t\t\t\ti++;\n\t\t\t\t\t\thistory.splice(i, 0, {role: 'tool', id: c.id, name: c.name, args: c.input, timestamp: Date.now()});\n\t\t\t\t\t});\n\t\t\t\t} else if(history[orgI].role == 'user') {\n\t\t\t\t\thistory[orgI].content.filter((c: any) => c.type =='tool_result').forEach((c: any) => {\n\t\t\t\t\t\tconst h = history.find((h: any) => h.id == c.tool_use_id);\n\t\t\t\t\t\th[c.is_error ? 'error' : 'content'] = c.content;\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\thistory[orgI].content = history[orgI].content.filter((c: any) => c.type == 'text').map((c: any) => c.text).join('\\n\\n');\n\t\t\t}\n\t\t\tif(!history[orgI].timestamp) history[orgI].timestamp = Date.now();\n\t\t}\n\t\treturn history.filter(h => !!h.content);\n\t}\n\n\tprivate fromStandard(history: LLMMessage[]): any[] {\n\t\tfor(let i = 0; i < history.length; i++) {\n\t\t\tif(history[i].role == 'tool') {\n\t\t\t\tconst h: any = history[i];\n\t\t\t\thistory.splice(i, 1,\n\t\t\t\t\t{role: 'assistant', content: [{type: 'tool_use', id: h.id, name: h.name, input: h.args}], timestamp: h.timestamp},\n\t\t\t\t\t{role: 'user', content: [{type: 'tool_result', tool_use_id: h.id, is_error: !!h.error, content: h.error || h.content}], timestamp: Date.now()}\n\t\t\t\t)\n\t\t\t\ti++;\n\t\t\t}\n\t\t}\n\t\treturn history;\n\t}\n\n\task(message: string, options: LLMRequest = {}): AbortablePromise<LLMMessage[]> {\n\t\tconst controller = new AbortController();\n\t\tconst response = new Promise<any>(async (res, rej) => {\n\t\t\tlet history = this.fromStandard([...options.history || [], {role: 'user', content: message, timestamp: Date.now()}]);\n\t\t\tif(options.compress) history = await this.ai.llm.compress(<any>history, options.compress.max, options.compress.min, options);\n\t\t\tconst requestParams: any = {\n\t\t\t\tmodel: options.model || this.model,\n\t\t\t\tmax_tokens: options.max_tokens || this.ai.options.max_tokens || 4096,\n\t\t\t\tsystem: options.system || this.ai.options.system || '',\n\t\t\t\ttemperature: options.temperature || this.ai.options.temperature || 0.7,\n\t\t\t\ttools: (options.tools || this.ai.options.tools || []).map(t => ({\n\t\t\t\t\tname: t.name,\n\t\t\t\t\tdescription: t.description,\n\t\t\t\t\tinput_schema: {\n\t\t\t\t\t\ttype: 'object',\n\t\t\t\t\t\tproperties: t.args ? objectMap(t.args, (key, value) => ({...value, required: undefined})) : {},\n\t\t\t\t\t\trequired: t.args ? Object.entries(t.args).filter(t => t[1].required).map(t => t[0]) : []\n\t\t\t\t\t},\n\t\t\t\t\tfn: undefined\n\t\t\t\t})),\n\t\t\t\tmessages: history,\n\t\t\t\tstream: !!options.stream,\n\t\t\t};\n\n\t\t\tlet resp: any;\n\t\t\tconst loopMessages: any[] = [];\n\t\t\tdo {\n\t\t\t\tresp = await this.client.messages.create(requestParams);\n\t\t\t\tif(options.stream) {\n\t\t\t\t\tif(loopMessages.length) options.stream({text: '\\n\\n'});\n\t\t\t\t\tresp.content = [];\n\t\t\t\t\tfor await (const chunk of resp) {\n\t\t\t\t\t\tif(controller.signal.aborted) break;\n\t\t\t\t\t\tif(chunk.type === 'content_block_start') {\n\t\t\t\t\t\t\tif(chunk.content_block.type === 'text') {\n\t\t\t\t\t\t\t\tresp.content.push({type: 'text', text: ''});\n\t\t\t\t\t\t\t} else if(chunk.content_block.type === 'tool_use') {\n\t\t\t\t\t\t\t\tresp.content.push({type: 'tool_use', id: chunk.content_block.id, name: chunk.content_block.name, input: <any>''});\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else if(chunk.type === 'content_block_delta') {\n\t\t\t\t\t\t\tif(chunk.delta.type === 'text_delta') {\n\t\t\t\t\t\t\t\tconst text = chunk.delta.text;\n\t\t\t\t\t\t\t\tresp.content.at(-1).text += text;\n\t\t\t\t\t\t\t\toptions.stream({text});\n\t\t\t\t\t\t\t} else if(chunk.delta.type === 'input_json_delta') {\n\t\t\t\t\t\t\t\tresp.content.at(-1).input += chunk.delta.partial_json;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else if(chunk.type === 'content_block_stop') {\n\t\t\t\t\t\t\tconst last = resp.content.at(-1);\n\t\t\t\t\t\t\tif(last.input != null) last.input = last.input ? JSONAttemptParse(last.input, {}) : {};\n\t\t\t\t\t\t} else if(chunk.type === 'message_stop') {\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tloopMessages.push({role: 'assistant', content: resp.content, timestamp: Date.now()});\n\t\t\t\tconst toolCalls = resp.content.filter((c: any) => c.type === 'tool_use');\n\t\t\t\tif(toolCalls.length && !controller.signal.aborted) {\n\t\t\t\t\thistory.push({role: 'assistant', content: resp.content, timestamp: Date.now()});\n\t\t\t\t\tconst results = await Promise.all(toolCalls.map(async (toolCall: any) => {\n\t\t\t\t\t\tconst tool = options.tools?.find(findByProp('name', toolCall.name));\n\t\t\t\t\t\tif(!tool) return {tool_use_id: toolCall.id, is_error: true, content: 'Tool not found'};\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tconst result = await tool.fn(toolCall.input, this.ai);\n\t\t\t\t\t\t\treturn {type: 'tool_result', tool_use_id: toolCall.id, content: JSONSanitize(result)};\n\t\t\t\t\t\t} catch (err: any) {\n\t\t\t\t\t\t\treturn {type: 'tool_result', tool_use_id: toolCall.id, is_error: true, content: err?.message || err?.toString() || 'Unknown'};\n\t\t\t\t\t\t}\n\t\t\t\t\t}));\n\t\t\t\t\tconst userMsg = {role: 'user', content: results, timestamp: Date.now()};\n\t\t\t\t\thistory.push(userMsg);\n\t\t\t\t\tloopMessages.push(userMsg);\n\t\t\t\t\trequestParams.messages = history;\n\t\t\t\t}\n\t\t\t} while (!controller.signal.aborted && resp.content.some((c: any) => c.type === 'tool_use'));\n\n\t\t\tconst combinedContent = loopMessages.filter(m => m.role === 'assistant')\n\t\t\t\t.map(m => m.content.filter((c: any) => c.type == 'text').map((c: any) => c.text).join('\\n\\n'))\n\t\t\t\t.filter(c => c).join('\\n\\n');\n\t\t\tif(options.stream) options.stream({done: true});\n\t\t\tres(this.toStandard([...history, {role: 'assistant', content: combinedContent, timestamp: Date.now()}]));\n\t\t});\n\n\t\treturn Object.assign(response, {abort: () => controller.abort()});\n\t}\n}\n","import {findByProp, objectMap, JSONSanitize, JSONAttemptParse} from '@ztimson/utils';\nimport {Ai} from './ai.ts';\nimport {LLMMessage, LLMRequest} from './llm.ts';\nimport {AbortablePromise, LLMProvider} from './provider.ts';\nimport {Ollama as ollama} from 'ollama';\n\nexport class Ollama extends LLMProvider {\n\tclient!: ollama;\n\n\tconstructor(public readonly ai: Ai, public host: string, public model: string) {\n\t\tsuper();\n\t\tthis.client = new ollama({host});\n\t}\n\n\tprivate toStandard(history: any[]): LLMMessage[] {\n\t\tfor(let i = 0; i < history.length; i++) {\n\t\t\tif(history[i].role == 'assistant' && history[i].tool_calls) {\n\t\t\t\tif(history[i].content) delete history[i].tool_calls;\n\t\t\t\telse {\n\t\t\t\t\thistory.splice(i, 1);\n\t\t\t\t\ti--;\n\t\t\t\t}\n\t\t\t} else if(history[i].role == 'tool') {\n\t\t\t\tconst error = history[i].content.startsWith('{\"error\":');\n\t\t\t\thistory[i] = {role: 'tool', name: history[i].tool_name, args: history[i].args, [error ? 'error' : 'content']: history[i].content, timestamp: history[i].timestamp};\n\t\t\t}\n\t\t\tif(!history[i]?.timestamp) history[i].timestamp = Date.now();\n\t\t}\n\t\treturn history;\n\t}\n\n\tprivate fromStandard(history: LLMMessage[]): any[] {\n\t\treturn history.map((h: any) => {\n\t\t\tif(h.role != 'tool') return h;\n\t\t\treturn {role: 'tool', tool_name: h.name, content: h.error || h.content, timestamp: h.timestamp}\n\t\t});\n\t}\n\n\task(message: string, options: LLMRequest = {}): AbortablePromise<LLMMessage[]> {\n\t\tconst controller = new AbortController();\n\t\tconst response = new Promise<any>(async (res, rej) => {\n\t\t\tlet system = options.system || this.ai.options.system;\n\t\t\tlet history = this.fromStandard([...options.history || [], {role: 'user', content: message, timestamp: Date.now()}]);\n\t\t\tif(history[0].roll == 'system') {\n\t\t\t\tif(!system) system = history.shift();\n\t\t\t\telse history.shift();\n\t\t\t}\n\t\t\tif(options.compress) history = await this.ai.llm.compress(<any>history, options.compress.max, options.compress.min);\n\t\t\tif(options.system) history.unshift({role: 'system', content: system})\n\n\t\t\tconst requestParams: any = {\n\t\t\t\tmodel: options.model || this.model,\n\t\t\t\tmessages: history,\n\t\t\t\tstream: !!options.stream,\n\t\t\t\tsignal: controller.signal,\n\t\t\t\toptions: {\n\t\t\t\t\ttemperature: options.temperature || this.ai.options.temperature || 0.7,\n\t\t\t\t\tnum_predict: options.max_tokens || this.ai.options.max_tokens || 4096,\n\t\t\t\t},\n\t\t\t\ttools: (options.tools || this.ai.options.tools || []).map(t => ({\n\t\t\t\t\ttype: 'function',\n\t\t\t\t\tfunction: {\n\t\t\t\t\t\tname: t.name,\n\t\t\t\t\t\tdescription: t.description,\n\t\t\t\t\t\tparameters: {\n\t\t\t\t\t\t\ttype: 'object',\n\t\t\t\t\t\t\tproperties: t.args ? objectMap(t.args, (key, value) => ({...value, required: undefined})) : {},\n\t\t\t\t\t\t\trequired: t.args ? Object.entries(t.args).filter(t => t[1].required).map(t => t[0]) : []\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}))\n\t\t\t}\n\n\t\t\tlet resp: any;\n\t\t\tconst loopMessages: any[] = [];\n\t\t\tdo {\n\t\t\t\tresp = await this.client.chat(requestParams);\n\t\t\t\tif(options.stream) {\n\t\t\t\t\tif(loopMessages.length) options.stream({text: '\\n\\n'});\n\t\t\t\t\tresp.message = {role: 'assistant', content: '', tool_calls: []};\n\t\t\t\t\tfor await (const chunk of resp) {\n\t\t\t\t\t\tif(controller.signal.aborted) break;\n\t\t\t\t\t\tif(chunk.message?.content) {\n\t\t\t\t\t\t\tresp.message.content += chunk.message.content;\n\t\t\t\t\t\t\toptions.stream({text: chunk.message.content});\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif(chunk.message?.tool_calls) resp.message.tool_calls = chunk.message.tool_calls;\n\t\t\t\t\t\tif(chunk.done) break;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tloopMessages.push({role: 'assistant', content: resp.message?.content, timestamp: Date.now()});\n\n\t\t\t\tif(resp.message?.tool_calls?.length && !controller.signal.aborted) {\n\t\t\t\t\thistory.push({...resp.message, timestamp: Date.now()});\n\t\t\t\t\tconst results = await Promise.all(resp.message.tool_calls.map(async (toolCall: any) => {\n\t\t\t\t\t\tconst tool = (options.tools || this.ai.options.tools)?.find(findByProp('name', toolCall.function.name));\n\t\t\t\t\t\tif(!tool) return {role: 'tool', tool_name: toolCall.function.name, content: '{\"error\": \"Tool not found\"}', timestamp: Date.now()};\n\t\t\t\t\t\tconst args = typeof toolCall.function.arguments === 'string' ? JSONAttemptParse(toolCall.function.arguments, {}) : toolCall.function.arguments;\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tconst result = await tool.fn(args, this.ai);\n\t\t\t\t\t\t\treturn {role: 'tool', tool_name: toolCall.function.name, args, content: JSONSanitize(result), timestamp: Date.now()};\n\t\t\t\t\t\t} catch (err: any) {\n\t\t\t\t\t\t\treturn {role: 'tool', tool_name: toolCall.function.name, args, content: JSONSanitize({error: err?.message || err?.toString() || 'Unknown'}), timestamp: Date.now()};\n\t\t\t\t\t\t}\n\t\t\t\t\t}));\n\t\t\t\t\thistory.push(...results);\n\t\t\t\t\tloopMessages.push(...results);\n\t\t\t\t\trequestParams.messages = history;\n\t\t\t\t}\n\t\t\t} while (!controller.signal.aborted && resp.message?.tool_calls?.length);\n\n\t\t\tconst combinedContent = loopMessages.filter(m => m.role === 'assistant')\n\t\t\t\t.map(m => m.content).filter(c => c).join('\\n\\n');\n\t\t\tif(options.stream) options.stream({done: true});\n\t\t\tres(this.toStandard([...history, {role: 'assistant', content: combinedContent, timestamp: Date.now()}]));\n\t\t});\n\n\t\treturn Object.assign(response, {abort: () => controller.abort()});\n\t}\n}\n","import {OpenAI as openAI} from 'openai';\nimport {findByProp, objectMap, JSONSanitize, JSONAttemptParse} from '@ztimson/utils';\nimport {Ai} from './ai.ts';\nimport {LLMMessage, LLMRequest} from './llm.ts';\nimport {AbortablePromise, LLMProvider} from './provider.ts';\n\nexport class OpenAi extends LLMProvider {\n\tclient!: openAI;\n\n\tconstructor(public readonly ai: Ai, public readonly apiToken: string, public model: string) {\n\t\tsuper();\n\t\tthis.client = new openAI({apiKey: apiToken});\n\t}\n\n\tprivate toStandard(history: any[]): LLMMessage[] {\n\t\tfor(let i = 0; i < history.length; i++) {\n\t\t\tconst h = history[i];\n\t\t\tif(h.role === 'assistant' && h.tool_calls) {\n\t\t\t\tconst tools = h.tool_calls.map((tc: any) => ({\n\t\t\t\t\trole: 'tool',\n\t\t\t\t\tid: tc.id,\n\t\t\t\t\tname: tc.function.name,\n\t\t\t\t\targs: JSONAttemptParse(tc.function.arguments, {}),\n\t\t\t\t\ttimestamp: h.timestamp\n\t\t\t\t}));\n\t\t\t\thistory.splice(i, 1, ...tools);\n\t\t\t\ti += tools.length - 1;\n\t\t\t} else if(h.role === 'tool' && h.content) {\n\t\t\t\tconst record = history.find(h2 => h.tool_call_id == h2.id);\n\t\t\t\tif(record) {\n\t\t\t\t\tif(h.content.includes('\"error\":')) record.error = h.content;\n\t\t\t\t\telse record.content = h.content;\n\t\t\t\t}\n\t\t\t\thistory.splice(i, 1);\n\t\t\t\ti--;\n\t\t\t}\n\t\t\tif(!history[i]?.timestamp) history[i].timestamp = Date.now();\n\t\t}\n\t\treturn history;\n\t}\n\n\tprivate fromStandard(history: LLMMessage[]): any[] {\n\t\treturn history.reduce((result, h) => {\n\t\t\tif(h.role === 'tool') {\n\t\t\t\tresult.push({\n\t\t\t\t\trole: 'assistant',\n\t\t\t\t\tcontent: null,\n\t\t\t\t\ttool_calls: [{ id: h.id, type: 'function', function: { name: h.name, arguments: JSON.stringify(h.args) } }],\n\t\t\t\t\trefusal: null,\n\t\t\t\t\tannotations: [],\n\t\t\t\t\ttimestamp: h.timestamp\n\t\t\t\t}, {\n\t\t\t\t\trole: 'tool',\n\t\t\t\t\ttool_call_id: h.id,\n\t\t\t\t\tcontent: h.error || h.content,\n\t\t\t\t\ttimestamp: Date.now()\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\tresult.push(h);\n\t\t\t}\n\t\t\treturn result;\n\t\t}, [] as any[]);\n\t}\n\n\task(message: string, options: LLMRequest = {}): AbortablePromise<LLMMessage[]> {\n\t\tconst controller = new AbortController();\n\t\tconst response = new Promise<any>(async (res, rej) => {\n\t\t\tlet history = this.fromStandard([...options.history || [], {role: 'user', content: message, timestamp: Date.now()}]);\n\t\t\tif(options.compress) history = await this.ai.llm.compress(<any>history, options.compress.max, options.compress.min, options);\n\n\t\t\tconst requestParams: any = {\n\t\t\t\tmodel: options.model || this.model,\n\t\t\t\tmessages: history,\n\t\t\t\tstream: !!options.stream,\n\t\t\t\tmax_tokens: options.max_tokens || this.ai.options.max_tokens || 4096,\n\t\t\t\ttemperature: options.temperature || this.ai.options.temperature || 0.7,\n\t\t\t\ttools: (options.tools || this.ai.options.tools || []).map(t => ({\n\t\t\t\t\ttype: 'function',\n\t\t\t\t\tfunction: {\n\t\t\t\t\t\tname: t.name,\n\t\t\t\t\t\tdescription: t.description,\n\t\t\t\t\t\tparameters: {\n\t\t\t\t\t\t\ttype: 'object',\n\t\t\t\t\t\t\tproperties: t.args ? objectMap(t.args, (key, value) => ({...value, required: undefined})) : {},\n\t\t\t\t\t\t\trequired: t.args ? Object.entries(t.args).filter(t => t[1].required).map(t => t[0]) : []\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}))\n\t\t\t};\n\n\t\t\tlet resp: any;\n\t\t\tconst loopMessages: any[] = [];\n\t\t\tdo {\n\t\t\t\tresp = await this.client.chat.completions.create(requestParams);\n\t\t\t\tif(options.stream) {\n\t\t\t\t\tif(loopMessages.length) options.stream({text: '\\n\\n'});\n\t\t\t\t\tresp.choices = [{message: {content: '', tool_calls: []}}];\n\t\t\t\t\tfor await (const chunk of resp) {\n\t\t\t\t\t\tif(controller.signal.aborted) break;\n\t\t\t\t\t\tif(chunk.choices[0].delta.content) {\n\t\t\t\t\t\t\tresp.choices[0].message.content += chunk.choices[0].delta.content;\n\t\t\t\t\t\t\toptions.stream({text: chunk.choices[0].delta.content});\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif(chunk.choices[0].delta.tool_calls) {\n\t\t\t\t\t\t\tresp.choices[0].message.tool_calls = chunk.choices[0].delta.tool_calls;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tloopMessages.push({role: 'assistant', content: resp.choices[0].message.content || '', timestamp: Date.now()});\n\n\t\t\t\tconst toolCalls = resp.choices[0].message.tool_calls || [];\n\t\t\t\tif(toolCalls.length && !controller.signal.aborted) {\n\t\t\t\t\thistory.push({...resp.choices[0].message, timestamp: Date.now()});\n\t\t\t\t\tconst results = await Promise.all(toolCalls.map(async (toolCall: any) => {\n\t\t\t\t\t\tconst tool = options.tools?.find(findByProp('name', toolCall.function.name));\n\t\t\t\t\t\tif(!tool) return {role: 'tool', tool_call_id: toolCall.id, content: '{\"error\": \"Tool not found\"}', timestamp: Date.now()};\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tconst args = JSONAttemptParse(toolCall.function.arguments, {});\n\t\t\t\t\t\t\tconst result = await tool.fn(args, this.ai);\n\t\t\t\t\t\t\treturn {role: 'tool', tool_call_id: toolCall.id, content: JSONSanitize(result), timestamp: Date.now()};\n\t\t\t\t\t\t} catch (err: any) {\n\t\t\t\t\t\t\treturn {role: 'tool', tool_call_id: toolCall.id, content: JSONSanitize({error: err?.message || err?.toString() || 'Unknown'}), timestamp: Date.now()};\n\t\t\t\t\t\t}\n\t\t\t\t\t}));\n\t\t\t\t\thistory.push(...results);\n\t\t\t\t\tloopMessages.push(...results);\n\t\t\t\t\trequestParams.messages = history;\n\t\t\t\t}\n\t\t\t} while (!controller.signal.aborted && resp.choices?.[0]?.message?.tool_calls?.length);\n\n\t\t\tconst combinedContent = loopMessages.filter(m => m.role === 'assistant')\n\t\t\t\t.map(m => m.content).filter(c => c).join('\\n\\n');\n\t\t\tif(options.stream) options.stream({done: true});\n\t\t\tres(this.toStandard([...history, {role: 'assistant', content: combinedContent, timestamp: Date.now()}]));\n\t\t});\n\n\t\treturn Object.assign(response, {abort: () => controller.abort()});\n\t}\n}\n","import {JSONAttemptParse} from '@ztimson/utils';\nimport {Ai} from './ai.ts';\nimport {Anthropic} from './antrhopic.ts';\nimport {Ollama} from './ollama.ts';\nimport {OpenAi} from './open-ai.ts';\nimport {AbortablePromise, LLMProvider} from './provider.ts';\nimport {AiTool} from './tools.ts';\n\nexport type LLMMessage = {\n\t/** Message originator */\n\trole: 'assistant' | 'system' | 'user';\n\t/** Message content */\n\tcontent: string | any;\n\t/** Timestamp */\n\ttimestamp: number;\n} | {\n\t/** Tool call */\n\trole: 'tool';\n\t/** Unique ID for call */\n\tid: string;\n\t/** Tool that was run */\n\tname: string;\n\t/** Tool arguments */\n\targs: any;\n\t/** Tool result */\n\tcontent: undefined | string;\n\t/** Tool error */\n\terror: undefined | string;\n\t/** Timestamp */\n\ttimestamp: number;\n}\n\nexport type LLMOptions = {\n\t/** Anthropic settings */\n\tanthropic?: {\n\t\t/** API Token */\n\t\ttoken: string;\n\t\t/** Default model */\n\t\tmodel: string;\n\t},\n\t/** Ollama settings */\n\tollama?: {\n\t\t/** connection URL */\n\t\thost: string;\n\t\t/** Default model */\n\t\tmodel: string;\n\t},\n\t/** Open AI settings */\n\topenAi?: {\n\t\t/** API Token */\n\t\ttoken: string;\n\t\t/** Default model */\n\t\tmodel: string;\n\t},\n\t/** Default provider & model */\n\tmodel: string | [string, string];\n} & Omit<LLMRequest, 'model'>;\n\nexport type LLMRequest = {\n\t/** System prompt */\n\tsystem?: string;\n\t/** Message history */\n\thistory?: LLMMessage[];\n\t/** Max tokens for request */\n\tmax_tokens?: number;\n\t/** 0 = Rigid Logic, 1 = Balanced, 2 = Hyper Creative **/\n\ttemperature?: number;\n\t/** Available tools */\n\ttools?: AiTool[];\n\t/** LLM model */\n\tmodel?: string | [string, string];\n\t/** Stream response */\n\tstream?: (chunk: {text?: string, done?: true}) => any;\n\t/** Compress old messages in the chat to free up context */\n\tcompress?: {\n\t\t/** Trigger chat compression once context exceeds the token count */\n\t\tmax: number;\n\t\t/** Compress chat until context size smaller than */\n\t\tmin: number\n\t}\n}\n\nexport class LLM {\n\tprivate providers: {[key: string]: LLMProvider} = {};\n\n\tconstructor(public readonly ai: Ai, public readonly options: LLMOptions) {\n\t\tif(options.anthropic?.token) this.providers.anthropic = new Anthropic(this.ai, options.anthropic.token, options.anthropic.model);\n\t\tif(options.ollama?.host) this.providers.ollama = new Ollama(this.ai, options.ollama.host, options.ollama.model);\n\t\tif(options.openAi?.token) this.providers.openAi = new OpenAi(this.ai, options.openAi.token, options.openAi.model);\n\t}\n\n\t/**\n\t * Chat with LLM\n\t * @param {string} message Question\n\t * @param {LLMRequest} options Configuration options and chat history\n\t * @returns {{abort: () => void, response: Promise<LLMMessage[]>}} Function to abort response and chat history\n\t */\n\task(message: string, options: LLMRequest = {}): AbortablePromise<LLMMessage[]> {\n\t\tlet model: any = [null, null];\n\t\tif(options.model) {\n\t\t\tif(typeof options.model == 'object') model = options.model;\n\t\t\telse model = [options.model, (<any>this.options)[options.model]?.model];\n\t\t}\n\t\tif(!options.model || model[1] == null) {\n\t\t\tif(typeof this.options.model == 'object') model = this.options.model;\n\t\t\telse model = [this.options.model, (<any>this.options)[this.options.model]?.model];\n\t\t}\n\t\tif(!model[0] || !model[1]) throw new Error(`Unknown LLM provider or model: ${model[0]} / ${model[1]}`);\n\t\treturn this.providers[model[0]].ask(message, {...options, model: model[1]});\n\t}\n\n\t/**\n\t * Compress chat history to reduce context size\n\t * @param {LLMMessage[]} history Chatlog that will be compressed\n\t * @param max Trigger compression once context is larger than max\n\t * @param min Summarize until context size is less than min\n\t * @param {LLMRequest} options LLM options\n\t * @returns {Promise<LLMMessage[]>} New chat history will summary at index 0\n\t */\n\tasync compress(history: LLMMessage[], max: number, min: number, options?: LLMRequest): Promise<LLMMessage[]> {\n\t\tif(this.estimateTokens(history) < max) return history;\n\t\tlet keep = 0, tokens = 0;\n\t\tfor(let m of history.toReversed()) {\n\t\t\ttokens += this.estimateTokens(m.content);\n\t\t\tif(tokens < min) keep++;\n\t\t\telse break;\n\t\t}\n\t\tif(history.length <= keep) return history;\n\t\tconst recent = keep == 0 ? [] : history.slice(-keep),\n\t\t\tprocess = (keep == 0 ? history : history.slice(0, -keep)).filter(h => h.role === 'assistant' || h.role === 'user');\n\t\tconst summary = await this.summarize(process.map(m => `${m.role}: ${m.content}`).join('\\n\\n'), 250, options);\n\t\treturn [{role: 'assistant', content: `Conversation Summary: ${summary}`, timestamp: Date.now()}, ...recent];\n\t}\n\n\t/**\n\t * Estimate variable as tokens\n\t * @param history Object to size\n\t * @returns {number} Rough token count\n\t */\n\testimateTokens(history: any): number {\n\t\tconst text = JSON.stringify(history);\n\t\treturn Math.ceil((text.length / 4) * 1.2);\n\t}\n\n\t/**\n\t * Ask a question with JSON response\n\t * @param {string} message Question\n\t * @param {LLMRequest} options Configuration options and chat history\n\t * @returns {Promise<{} | {} | RegExpExecArray | null>}\n\t */\n\tasync json(message: string, options?: LLMRequest) {\n\t\tlet resp = await this.ask(message, {\n\t\t\tsystem: 'Respond using a JSON blob',\n\t\t\t...options\n\t\t});\n\t\tif(!resp?.[0]?.content) return {};\n\t\treturn JSONAttemptParse(new RegExp('\\{[\\s\\S]*\\}').exec(resp[0].content), {});\n\t}\n\n\t/**\n\t * Create a summary of some text\n\t * @param {string} text Text to summarize\n\t * @param {number} tokens Max number of tokens\n\t * @param options LLM request options\n\t * @returns {Promise<string>} Summary\n\t */\n\tsummarize(text: string, tokens: number, options?: LLMRequest): Promise<string | null> {\n\t\treturn this.ask(text, {system: `Generate a brief summary <= ${tokens} tokens. Output nothing else`, temperature: 0.3, ...options})\n\t\t\t.then(history => <string>history.pop()?.content || null);\n\t}\n}\n","import {createWorker} from 'tesseract.js';\nimport {LLM, LLMOptions} from './llm';\nimport fs from 'node:fs/promises';\nimport Path from 'node:path';\nimport * as tf from '@tensorflow/tfjs';\nimport {spawn} from 'node:child_process';\n\nexport type AiOptions = LLMOptions & {\n\twhisper?: {\n\t\t/** Whisper binary location */\n\t\tbinary: string;\n\t\t/** Model: `ggml-base.en.bin` */\n\t\tmodel: string;\n\t\t/** Path to models */\n\t\tpath: string;\n\t}\n}\n\nexport class Ai {\n\tprivate downloads: {[key: string]: Promise<string>} = {};\n\tprivate whisperModel!: string;\n\n\t/** Large Language Models */\n\tllm!: LLM;\n\n\tconstructor(public readonly options: AiOptions) {\n\t\tthis.llm = new LLM(this, options);\n\t\tif(this.options.whisper?.binary) {\n\t\t\tthis.whisperModel = this.options.whisper?.model.endsWith('.bin') ? this.options.whisper?.model : this.options.whisper?.model + '.bin';\n\t\t\tthis.downloadAsrModel();\n\t\t}\n\t}\n\n\t/**\n\t * Convert audio to text using Auditory Speech Recognition\n\t * @param {string} path Path to audio\n\t * @param model Whisper model\n\t * @returns {Promise<any>} Extracted text\n\t */\n\tasr(path: string, model: string = this.whisperModel): {abort: () => void, response: Promise<string | null>} {\n\t\tif(!this.options.whisper?.binary) throw new Error('Whisper not configured');\n\t\tlet abort: any = () => {};\n\t\tconst response = new Promise<string | null>((resolve, reject) => {\n\t\t\tthis.downloadAsrModel(model).then(m => {\n\t\t\t\tlet output = '';\n\t\t\t\tconst proc = spawn(<string>this.options.whisper?.binary, ['-nt', '-np', '-m', m, '-f', path], {stdio: ['ignore', 'pipe', 'ignore']});\n\t\t\t\tabort = () => proc.kill('SIGTERM');\n\t\t\t\tproc.on('error', (err: Error) => reject(err));\n\t\t\t\tproc.stdout.on('data', (data: Buffer) => output += data.toString());\n\t\t\t\tproc.on('close', (code: number) => {\n\t\t\t\t\tif(code === 0) resolve(output.trim() || null);\n\t\t\t\t\telse reject(new Error(`Exit code ${code}`));\n\t\t\t\t});\n\t\t\t});\n\t\t});\n\t\treturn {response, abort};\n\t}\n\n\t/**\n\t * Downloads the specified Whisper model if it is not already present locally.\n\t *\n\t * @param {string} model Whisper model that will be downloaded\n\t * @return {Promise<string>} Absolute path to model file, resolves once downloaded\n\t */\n\tasync downloadAsrModel(model: string = this.whisperModel): Promise<string> {\n\t\tif(!this.options.whisper?.binary) throw new Error('Whisper not configured');\n\t\tif(!model.endsWith('.bin')) model += '.bin';\n\t\tconst p = Path.join(this.options.whisper.path, model);\n\t\tif(await fs.stat(p).then(() => true).catch(() => false)) return p;\n\t\tif(!!this.downloads[model]) return this.downloads[model];\n\t\tthis.downloads[model] = fetch(`https://huggingface.co/ggerganov/whisper.cpp/resolve/main/${model}`)\n\t\t\t.then(resp => resp.arrayBuffer())\n\t\t\t.then(arr => Buffer.from(arr)).then(async buffer => {\n\t\t\t\tawait fs.writeFile(p, buffer);\n\t\t\t\tdelete this.downloads[model];\n\t\t\t\treturn p;\n\t\t\t});\n\t\treturn this.downloads[model];\n\t}\n\n\t/**\n\t * Convert image to text using Optical Character Recognition\n\t * @param {string} path Path to image\n\t * @returns {{abort: Function, response: Promise<string | null>}} Abort function & Promise of extracted text\n\t */\n\tocr(path: string): {abort: () => void, response: Promise<string | null>} {\n\t\tlet worker: any;\n\t\treturn {\n\t\t\tabort: () => { worker?.terminate(); },\n\t\t\tresponse: new Promise(async res => {\n\t\t\t\tworker = await createWorker('eng');\n\t\t\t\tconst {data} = await worker.recognize(path);\n\t\t\t\tawait worker.terminate();\n\t\t\t\tres(data.text.trim() || null);\n\t\t\t})\n\t\t}\n\t}\n\n\t/**\n\t * Compare the difference between two strings using tensor math\n\t * @param target Text that will checked\n\t * @param {string} searchTerms Multiple search terms to check against target\n\t * @returns {{avg: number, max: number, similarities: number[]}} Similarity values 0-1: 0 = unique, 1 = identical\n\t */\n\tsemanticSimilarity(target: string, ...searchTerms: string[]) {\n\t\tif(searchTerms.length < 2) throw new Error('Requires at least 2 strings to compare');\n\n\t\tconst vector = (text: string, dimensions: number = 10): number[] => {\n\t\t\treturn text.toLowerCase().split('').map((char, index) =>\n\t\t\t\t(char.charCodeAt(0) * (index + 1)) % dimensions / dimensions).slice(0, dimensions);\n\t\t}\n\n\t\tconst cosineSimilarity = (v1: number[], v2: number[]): number => {\n\t\t\tif (v1.length !== v2.length) throw new Error('Vectors must be same length');\n\t\t\tconst tensor1 = tf.tensor1d(v1), tensor2 = tf.tensor1d(v2)\n\t\t\tconst dotProduct = tf.dot(tensor1, tensor2)\n\t\t\tconst magnitude1 = tf.norm(tensor1)\n\t\t\tconst magnitude2 = tf.norm(tensor2)\n\t\t\tif(magnitude1.dataSync()[0] === 0 || magnitude2.dataSync()[0] === 0) return 0\n\t\t\treturn dotProduct.dataSync()[0] / (magnitude1.dataSync()[0] * magnitude2.dataSync()[0])\n\t\t}\n\n\t\tconst v = vector(target);\n\t\tconst similarities = searchTerms.map(t => vector(t)).map(refVector => cosineSimilarity(v, refVector))\n\t\treturn {avg: similarities.reduce((acc, s) => acc + s, 0) / similarities.length, max: Math.max(...similarities), similarities}\n\t}\n}\n","import {$, $Sync} from '@ztimson/node-utils';\nimport {ASet, consoleInterceptor, Http, fn as Fn} from '@ztimson/utils';\nimport {Ai} from './ai.ts';\n\nexport type AiToolArg = {[key: string]: {\n\t/** Argument type */\n\ttype: 'array' | 'boolean' | 'number' | 'object' | 'string',\n\t/** Argument description */\n\tdescription: string,\n\t/** Required argument */\n\trequired?: boolean;\n\t/** Default value */\n\tdefault?: any,\n\t/** Options */\n\tenum?: string[],\n\t/** Minimum value or length */\n\tmin?: number,\n\t/** Maximum value or length */\n\tmax?: number,\n\t/** Match pattern */\n\tpattern?: string,\n\t/** Child arguments */\n\titems?: {[key: string]: AiToolArg}\n}}\n\nexport type AiTool = {\n\t/** Tool ID / Name - Must be snail_case */\n\tname: string,\n\t/** Tool description / prompt */\n\tdescription: string,\n\t/** Tool arguments */\n\targs?: AiToolArg,\n\t/** Callback function */\n\tfn: (args: any, ai: Ai) => any | Promise<any>,\n};\n\nexport const CliTool: AiTool = {\n\tname: 'cli',\n\tdescription: 'Use the command line interface, returns any output',\n\targs: {command: {type: 'string', description: 'Command to run', required: true}},\n\tfn: (args: {command: string}) => $`${args.command}`\n}\n\nexport const DateTimeTool: AiTool = {\n\tname: 'get_datetime',\n\tdescription: 'Get current date and time',\n\targs: {},\n\tfn: async () => new Date().toISOString()\n}\n\nexport const ExecTool: AiTool = {\n\tname: 'exec',\n\tdescription: 'Run code/scripts',\n\targs: {\n\t\tlanguage: {type: 'string', description: 'Execution language', enum: ['cli', 'node', 'python'], required: true},\n\t\tcode: {type: 'string', description: 'Code to execute', required: true}\n\t},\n\tfn: async (args, ai) => {\n\t\ttry {\n\t\t\tswitch(args.type) {\n\t\t\t\tcase 'bash':\n\t\t\t\t\treturn await CliTool.fn({command: args.code}, ai);\n\t\t\t\tcase 'node':\n\t\t\t\t\treturn await JSTool.fn({code: args.code}, ai);\n\t\t\t\tcase 'python': {\n\t\t\t\t\treturn await PythonTool.fn({code: args.code}, ai);\n\t\t\t\t}\n\t\t\t}\n\t\t} catch(err: any) {\n\t\t\treturn {error: err?.message || err.toString()};\n\t\t}\n\t}\n}\n\nexport const FetchTool: AiTool = {\n\tname: 'fetch',\n\tdescription: 'Make HTTP request to URL',\n\targs: {\n\t\turl: {type: 'string', description: 'URL to fetch', required: true},\n\t\tmethod: {type: 'string', description: 'HTTP method to use', enum: ['GET', 'POST', 'PUT', 'DELETE'], default: 'GET'},\n\t\theaders: {type: 'object', description: 'HTTP headers to send', default: {}},\n\t\tbody: {type: 'object', description: 'HTTP body to send'},\n\t},\n\tfn: (args: {\n\t\turl: string;\n\t\tmethod: 'GET' | 'POST' | 'PUT' | 'DELETE';\n\t\theaders: {[key: string]: string};\n\t\tbody: any;\n\t}) => new Http({url: args.url, headers: args.headers}).request({method: args.method || 'GET', body: args.body})\n}\n\nexport const JSTool: AiTool = {\n\tname: 'exec_javascript',\n\tdescription: 'Execute commonjs javascript',\n\targs: {\n\t\tcode: {type: 'string', description: 'CommonJS javascript', required: true}\n\t},\n\tfn: async (args: {code: string}) => {\n\t\tconst console = consoleInterceptor(null);\n\t\tconst resp = await Fn<any>({console}, args.code, true).catch((err: any) => console.output.error.push(err));\n\t\treturn {...console.output, return: resp, stdout: undefined, stderr: undefined};\n\t}\n}\n\nexport const PythonTool: AiTool = {\n\tname: 'exec_javascript',\n\tdescription: 'Execute commonjs javascript',\n\targs: {\n\t\tcode: {type: 'string', description: 'CommonJS javascript', required: true}\n\t},\n\tfn: async (args: {code: string}) => ({result: $Sync`python -c \"${args.code}\"`})\n}\n\nexport const SearchTool: AiTool = {\n\tname: 'search',\n\tdescription: 'Use a search engine to find relevant URLs, should be changed with fetch to scrape sources',\n\targs: {\n\t\tquery: {type: 'string', description: 'Search string', required: true},\n\t\tlength: {type: 'string', description: 'Number of results to return', default: 5},\n\t},\n\tfn: async (args: {\n\t\tquery: string;\n\t\tlength: number;\n\t}) => {\n\t\tconst html = await fetch(`https://html.duckduckgo.com/html/?q=${encodeURIComponent(args.query)}`, {\n\t\t\theaders: {\"User-Agent\": \"Mozilla/5.0 (Windows NT 10.0; Win64; x64)\", \"Accept-Language\": \"en-US,en;q=0.9\"}\n\t\t}).then(resp => resp.text());\n\t\tlet match, regex = /<a .*?href=\"(.+?)\".+?<\\/a>/g;\n\t\tconst results = new ASet<string>();\n\t\twhile((match = regex.exec(html)) !== null) {\n\t\t\tlet url = /uddg=(.+)&?/.exec(decodeURIComponent(match[1]))?.[1];\n\t\t\tif(url) url = decodeURIComponent(url);\n\t\t\tif(url) results.add(url);\n\t\t\tif(results.size >= (args.length || 5)) break;\n\t\t}\n\t\treturn results;\n\t}\n}\n"],"names":["LLMProvider","Anthropic","ai","apiToken","model","anthropic","history","i","orgI","c","h","message","options","controller","response","res","rej","requestParams","t","objectMap","key","value","resp","loopMessages","chunk","text","last","JSONAttemptParse","toolCalls","userMsg","toolCall","tool","findByProp","result","JSONSanitize","err","combinedContent","m","Ollama","host","ollama","error","system","results","args","OpenAi","openAI","tools","tc","record","h2","LLM","max","min","keep","tokens","recent","process","Ai","path","abort","resolve","reject","output","proc","spawn","data","code","p","Path","fs","arr","buffer","worker","createWorker","target","searchTerms","vector","dimensions","char","index","cosineSimilarity","v1","v2","tensor1","tf","tensor2","dotProduct","magnitude1","magnitude2","v","similarities","refVector","acc","s","CliTool","$","DateTimeTool","ExecTool","JSTool","PythonTool","FetchTool","Http","console","consoleInterceptor","Fn","$Sync","SearchTool","html","match","regex","ASet","url"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../src/provider.ts","../src/antrhopic.ts","../src/ollama.ts","../src/open-ai.ts","../src/llm.ts","../src/ai.ts","../src/tools.ts"],"sourcesContent":["import {LLMMessage, LLMOptions, LLMRequest} from './llm.ts';\n\nexport type AbortablePromise<T> = Promise<T> & {abort: () => void};\n\nexport abstract class LLMProvider {\n\tabstract ask(message: string, options: LLMRequest): AbortablePromise<LLMMessage[]>;\n}\n","import {Anthropic as anthropic} from '@anthropic-ai/sdk';\nimport {findByProp, objectMap, JSONSanitize, JSONAttemptParse} from '@ztimson/utils';\nimport {Ai} from './ai.ts';\nimport {LLMMessage, LLMRequest} from './llm.ts';\nimport {AbortablePromise, LLMProvider} from './provider.ts';\n\nexport class Anthropic extends LLMProvider {\n\tclient!: anthropic;\n\n\tconstructor(public readonly ai: Ai, public readonly apiToken: string, public model: string) {\n\t\tsuper();\n\t\tthis.client = new anthropic({apiKey: apiToken});\n\t}\n\n\tprivate toStandard(history: any[]): LLMMessage[] {\n\t\tfor(let i = 0; i < history.length; i++) {\n\t\t\tconst orgI = i;\n\t\t\tif(typeof history[orgI].content != 'string') {\n\t\t\t\tif(history[orgI].role == 'assistant') {\n\t\t\t\t\thistory[orgI].content.filter((c: any) => c.type =='tool_use').forEach((c: any) => {\n\t\t\t\t\t\ti++;\n\t\t\t\t\t\thistory.splice(i, 0, {role: 'tool', id: c.id, name: c.name, args: c.input, timestamp: Date.now()});\n\t\t\t\t\t});\n\t\t\t\t} else if(history[orgI].role == 'user') {\n\t\t\t\t\thistory[orgI].content.filter((c: any) => c.type =='tool_result').forEach((c: any) => {\n\t\t\t\t\t\tconst h = history.find((h: any) => h.id == c.tool_use_id);\n\t\t\t\t\t\th[c.is_error ? 'error' : 'content'] = c.content;\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\thistory[orgI].content = history[orgI].content.filter((c: any) => c.type == 'text').map((c: any) => c.text).join('\\n\\n');\n\t\t\t}\n\t\t\tif(!history[orgI].timestamp) history[orgI].timestamp = Date.now();\n\t\t}\n\t\treturn history.filter(h => !!h.content);\n\t}\n\n\tprivate fromStandard(history: LLMMessage[]): any[] {\n\t\tfor(let i = 0; i < history.length; i++) {\n\t\t\tif(history[i].role == 'tool') {\n\t\t\t\tconst h: any = history[i];\n\t\t\t\thistory.splice(i, 1,\n\t\t\t\t\t{role: 'assistant', content: [{type: 'tool_use', id: h.id, name: h.name, input: h.args}]},\n\t\t\t\t\t{role: 'user', content: [{type: 'tool_result', tool_use_id: h.id, is_error: !!h.error, content: h.error || h.content}]}\n\t\t\t\t)\n\t\t\t\ti++;\n\t\t\t}\n\t\t}\n\t\treturn history.map(({timestamp, ...h}) => h);\n\t}\n\n\task(message: string, options: LLMRequest = {}): AbortablePromise<LLMMessage[]> {\n\t\tconst controller = new AbortController();\n\t\tconst response = new Promise<any>(async (res, rej) => {\n\t\t\tlet history = this.fromStandard([...options.history || [], {role: 'user', content: message, timestamp: Date.now()}]);\n\t\t\tif(options.compress) history = await this.ai.llm.compress(<any>history, options.compress.max, options.compress.min, options);\n\t\t\tconst requestParams: any = {\n\t\t\t\tmodel: options.model || this.model,\n\t\t\t\tmax_tokens: options.max_tokens || this.ai.options.max_tokens || 4096,\n\t\t\t\tsystem: options.system || this.ai.options.system || '',\n\t\t\t\ttemperature: options.temperature || this.ai.options.temperature || 0.7,\n\t\t\t\ttools: (options.tools || this.ai.options.tools || []).map(t => ({\n\t\t\t\t\tname: t.name,\n\t\t\t\t\tdescription: t.description,\n\t\t\t\t\tinput_schema: {\n\t\t\t\t\t\ttype: 'object',\n\t\t\t\t\t\tproperties: t.args ? objectMap(t.args, (key, value) => ({...value, required: undefined})) : {},\n\t\t\t\t\t\trequired: t.args ? Object.entries(t.args).filter(t => t[1].required).map(t => t[0]) : []\n\t\t\t\t\t},\n\t\t\t\t\tfn: undefined\n\t\t\t\t})),\n\t\t\t\tmessages: history,\n\t\t\t\tstream: !!options.stream,\n\t\t\t};\n\n\t\t\tlet resp: any;\n\t\t\tconst loopMessages: any[] = [];\n\t\t\tdo {\n\t\t\t\tresp = await this.client.messages.create(requestParams);\n\t\t\t\tif(options.stream) {\n\t\t\t\t\tif(loopMessages.length) options.stream({text: '\\n\\n'});\n\t\t\t\t\tresp.content = [];\n\t\t\t\t\tfor await (const chunk of resp) {\n\t\t\t\t\t\tif(controller.signal.aborted) break;\n\t\t\t\t\t\tif(chunk.type === 'content_block_start') {\n\t\t\t\t\t\t\tif(chunk.content_block.type === 'text') {\n\t\t\t\t\t\t\t\tresp.content.push({type: 'text', text: ''});\n\t\t\t\t\t\t\t} else if(chunk.content_block.type === 'tool_use') {\n\t\t\t\t\t\t\t\tresp.content.push({type: 'tool_use', id: chunk.content_block.id, name: chunk.content_block.name, input: <any>''});\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else if(chunk.type === 'content_block_delta') {\n\t\t\t\t\t\t\tif(chunk.delta.type === 'text_delta') {\n\t\t\t\t\t\t\t\tconst text = chunk.delta.text;\n\t\t\t\t\t\t\t\tresp.content.at(-1).text += text;\n\t\t\t\t\t\t\t\toptions.stream({text});\n\t\t\t\t\t\t\t} else if(chunk.delta.type === 'input_json_delta') {\n\t\t\t\t\t\t\t\tresp.content.at(-1).input += chunk.delta.partial_json;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else if(chunk.type === 'content_block_stop') {\n\t\t\t\t\t\t\tconst last = resp.content.at(-1);\n\t\t\t\t\t\t\tif(last.input != null) last.input = last.input ? JSONAttemptParse(last.input, {}) : {};\n\t\t\t\t\t\t} else if(chunk.type === 'message_stop') {\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tloopMessages.push({role: 'assistant', content: resp.content, timestamp: Date.now()});\n\t\t\t\tconst toolCalls = resp.content.filter((c: any) => c.type === 'tool_use');\n\t\t\t\tif(toolCalls.length && !controller.signal.aborted) {\n\t\t\t\t\thistory.push({role: 'assistant', content: resp.content});\n\t\t\t\t\tconst results = await Promise.all(toolCalls.map(async (toolCall: any) => {\n\t\t\t\t\t\tconst tool = options.tools?.find(findByProp('name', toolCall.name));\n\t\t\t\t\t\tif(!tool) return {tool_use_id: toolCall.id, is_error: true, content: 'Tool not found'};\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tconst result = await tool.fn(toolCall.input, this.ai);\n\t\t\t\t\t\t\treturn {type: 'tool_result', tool_use_id: toolCall.id, content: JSONSanitize(result)};\n\t\t\t\t\t\t} catch (err: any) {\n\t\t\t\t\t\t\treturn {type: 'tool_result', tool_use_id: toolCall.id, is_error: true, content: err?.message || err?.toString() || 'Unknown'};\n\t\t\t\t\t\t}\n\t\t\t\t\t}));\n\t\t\t\t\tconst userMsg = {role: 'user', content: results};\n\t\t\t\t\thistory.push(userMsg);\n\t\t\t\t\tloopMessages.push({...userMsg, timestamp: Date.now()});\n\t\t\t\t\trequestParams.messages = history;\n\t\t\t\t}\n\t\t\t} while (!controller.signal.aborted && resp.content.some((c: any) => c.type === 'tool_use'));\n\n\t\t\tconst combinedContent = loopMessages.filter(m => m.role === 'assistant')\n\t\t\t\t.map(m => m.content.filter((c: any) => c.type == 'text').map((c: any) => c.text).join('\\n\\n'))\n\t\t\t\t.filter(c => c).join('\\n\\n');\n\t\t\tif(options.stream) options.stream({done: true});\n\t\t\tres(this.toStandard([...history, {role: 'assistant', content: combinedContent, timestamp: Date.now()}]));\n\t\t});\n\n\t\treturn Object.assign(response, {abort: () => controller.abort()});\n\t}\n}\n","import {findByProp, objectMap, JSONSanitize, JSONAttemptParse} from '@ztimson/utils';\nimport {Ai} from './ai.ts';\nimport {LLMMessage, LLMRequest} from './llm.ts';\nimport {AbortablePromise, LLMProvider} from './provider.ts';\nimport {Ollama as ollama} from 'ollama';\n\nexport class Ollama extends LLMProvider {\n\tclient!: ollama;\n\n\tconstructor(public readonly ai: Ai, public host: string, public model: string) {\n\t\tsuper();\n\t\tthis.client = new ollama({host});\n\t}\n\n\tprivate toStandard(history: any[]): LLMMessage[] {\n\t\tfor(let i = 0; i < history.length; i++) {\n\t\t\tif(history[i].role == 'assistant' && history[i].tool_calls) {\n\t\t\t\tif(history[i].content) delete history[i].tool_calls;\n\t\t\t\telse {\n\t\t\t\t\thistory.splice(i, 1);\n\t\t\t\t\ti--;\n\t\t\t\t}\n\t\t\t} else if(history[i].role == 'tool') {\n\t\t\t\tconst error = history[i].content.startsWith('{\"error\":');\n\t\t\t\thistory[i] = {role: 'tool', name: history[i].tool_name, args: history[i].args, [error ? 'error' : 'content']: history[i].content, timestamp: history[i].timestamp};\n\t\t\t}\n\t\t\tif(!history[i]?.timestamp) history[i].timestamp = Date.now();\n\t\t}\n\t\treturn history;\n\t}\n\n\tprivate fromStandard(history: LLMMessage[]): any[] {\n\t\treturn history.map((h: any) => {\n\t\t\tconst {timestamp, ...rest} = h;\n\t\t\tif(h.role != 'tool') return rest;\n\t\t\treturn {role: 'tool', tool_name: h.name, content: h.error || h.content}\n\t\t});\n\t}\n\n\task(message: string, options: LLMRequest = {}): AbortablePromise<LLMMessage[]> {\n\t\tconst controller = new AbortController();\n\t\tconst response = new Promise<any>(async (res, rej) => {\n\t\t\tlet system = options.system || this.ai.options.system;\n\t\t\tlet history = this.fromStandard([...options.history || [], {role: 'user', content: message, timestamp: Date.now()}]);\n\t\t\tif(history[0].roll == 'system') {\n\t\t\t\tif(!system) system = history.shift();\n\t\t\t\telse history.shift();\n\t\t\t}\n\t\t\tif(options.compress) history = await this.ai.llm.compress(<any>history, options.compress.max, options.compress.min);\n\t\t\tif(options.system) history.unshift({role: 'system', content: system})\n\n\t\t\tconst requestParams: any = {\n\t\t\t\tmodel: options.model || this.model,\n\t\t\t\tmessages: history,\n\t\t\t\tstream: !!options.stream,\n\t\t\t\tsignal: controller.signal,\n\t\t\t\toptions: {\n\t\t\t\t\ttemperature: options.temperature || this.ai.options.temperature || 0.7,\n\t\t\t\t\tnum_predict: options.max_tokens || this.ai.options.max_tokens || 4096,\n\t\t\t\t},\n\t\t\t\ttools: (options.tools || this.ai.options.tools || []).map(t => ({\n\t\t\t\t\ttype: 'function',\n\t\t\t\t\tfunction: {\n\t\t\t\t\t\tname: t.name,\n\t\t\t\t\t\tdescription: t.description,\n\t\t\t\t\t\tparameters: {\n\t\t\t\t\t\t\ttype: 'object',\n\t\t\t\t\t\t\tproperties: t.args ? objectMap(t.args, (key, value) => ({...value, required: undefined})) : {},\n\t\t\t\t\t\t\trequired: t.args ? Object.entries(t.args).filter(t => t[1].required).map(t => t[0]) : []\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}))\n\t\t\t}\n\n\t\t\tlet resp: any;\n\t\t\tconst loopMessages: any[] = [];\n\t\t\tdo {\n\t\t\t\tresp = await this.client.chat(requestParams);\n\t\t\t\tif(options.stream) {\n\t\t\t\t\tif(loopMessages.length) options.stream({text: '\\n\\n'});\n\t\t\t\t\tresp.message = {role: 'assistant', content: '', tool_calls: []};\n\t\t\t\t\tfor await (const chunk of resp) {\n\t\t\t\t\t\tif(controller.signal.aborted) break;\n\t\t\t\t\t\tif(chunk.message?.content) {\n\t\t\t\t\t\t\tresp.message.content += chunk.message.content;\n\t\t\t\t\t\t\toptions.stream({text: chunk.message.content});\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif(chunk.message?.tool_calls) resp.message.tool_calls = chunk.message.tool_calls;\n\t\t\t\t\t\tif(chunk.done) break;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tloopMessages.push({role: 'assistant', content: resp.message?.content, timestamp: Date.now()});\n\t\t\t\tif(resp.message?.tool_calls?.length && !controller.signal.aborted) {\n\t\t\t\t\thistory.push(resp.message);\n\t\t\t\t\tconst results = await Promise.all(resp.message.tool_calls.map(async (toolCall: any) => {\n\t\t\t\t\t\tconst tool = (options.tools || this.ai.options.tools)?.find(findByProp('name', toolCall.function.name));\n\t\t\t\t\t\tif(!tool) return {role: 'tool', tool_name: toolCall.function.name, content: '{\"error\": \"Tool not found\"}'};\n\t\t\t\t\t\tconst args = typeof toolCall.function.arguments === 'string' ? JSONAttemptParse(toolCall.function.arguments, {}) : toolCall.function.arguments;\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tconst result = await tool.fn(args, this.ai);\n\t\t\t\t\t\t\treturn {role: 'tool', tool_name: toolCall.function.name, args, content: JSONSanitize(result)};\n\t\t\t\t\t\t} catch (err: any) {\n\t\t\t\t\t\t\treturn {role: 'tool', tool_name: toolCall.function.name, args, content: JSONSanitize({error: err?.message || err?.toString() || 'Unknown'})};\n\t\t\t\t\t\t}\n\t\t\t\t\t}));\n\t\t\t\t\thistory.push(...results);\n\t\t\t\t\tloopMessages.push(...results.map(r => ({...r, timestamp: Date.now()})));\n\t\t\t\t\trequestParams.messages = history;\n\t\t\t\t}\n\t\t\t} while (!controller.signal.aborted && resp.message?.tool_calls?.length);\n\n\t\t\tconst combinedContent = loopMessages.filter(m => m.role === 'assistant')\n\t\t\t\t.map(m => m.content).filter(c => c).join('\\n\\n');\n\t\t\tif(options.stream) options.stream({done: true});\n\t\t\tres(this.toStandard([...history, {role: 'assistant', content: combinedContent, timestamp: Date.now()}]));\n\t\t});\n\n\t\treturn Object.assign(response, {abort: () => controller.abort()});\n\t}\n}\n","import {OpenAI as openAI} from 'openai';\nimport {findByProp, objectMap, JSONSanitize, JSONAttemptParse} from '@ztimson/utils';\nimport {Ai} from './ai.ts';\nimport {LLMMessage, LLMRequest} from './llm.ts';\nimport {AbortablePromise, LLMProvider} from './provider.ts';\n\nexport class OpenAi extends LLMProvider {\n\tclient!: openAI;\n\n\tconstructor(public readonly ai: Ai, public readonly apiToken: string, public model: string) {\n\t\tsuper();\n\t\tthis.client = new openAI({apiKey: apiToken});\n\t}\n\n\tprivate toStandard(history: any[]): LLMMessage[] {\n\t\tfor(let i = 0; i < history.length; i++) {\n\t\t\tconst h = history[i];\n\t\t\tif(h.role === 'assistant' && h.tool_calls) {\n\t\t\t\tconst tools = h.tool_calls.map((tc: any) => ({\n\t\t\t\t\trole: 'tool',\n\t\t\t\t\tid: tc.id,\n\t\t\t\t\tname: tc.function.name,\n\t\t\t\t\targs: JSONAttemptParse(tc.function.arguments, {}),\n\t\t\t\t\ttimestamp: h.timestamp\n\t\t\t\t}));\n\t\t\t\thistory.splice(i, 1, ...tools);\n\t\t\t\ti += tools.length - 1;\n\t\t\t} else if(h.role === 'tool' && h.content) {\n\t\t\t\tconst record = history.find(h2 => h.tool_call_id == h2.id);\n\t\t\t\tif(record) {\n\t\t\t\t\tif(h.content.includes('\"error\":')) record.error = h.content;\n\t\t\t\t\telse record.content = h.content;\n\t\t\t\t}\n\t\t\t\thistory.splice(i, 1);\n\t\t\t\ti--;\n\t\t\t}\n\t\t\tif(!history[i]?.timestamp) history[i].timestamp = Date.now();\n\t\t}\n\t\treturn history;\n\t}\n\n\tprivate fromStandard(history: LLMMessage[]): any[] {\n\t\treturn history.reduce((result, h) => {\n\t\t\tif(h.role === 'tool') {\n\t\t\t\tresult.push({\n\t\t\t\t\trole: 'assistant',\n\t\t\t\t\tcontent: null,\n\t\t\t\t\ttool_calls: [{ id: h.id, type: 'function', function: { name: h.name, arguments: JSON.stringify(h.args) } }],\n\t\t\t\t\trefusal: null,\n\t\t\t\t\tannotations: []\n\t\t\t\t}, {\n\t\t\t\t\trole: 'tool',\n\t\t\t\t\ttool_call_id: h.id,\n\t\t\t\t\tcontent: h.error || h.content\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\tconst {timestamp, ...rest} = h;\n\t\t\t\tresult.push(rest);\n\t\t\t}\n\t\t\treturn result;\n\t\t}, [] as any[]);\n\t}\n\n\task(message: string, options: LLMRequest = {}): AbortablePromise<LLMMessage[]> {\n\t\tconst controller = new AbortController();\n\t\tconst response = new Promise<any>(async (res, rej) => {\n\t\t\tlet history = this.fromStandard([...options.history || [], {role: 'user', content: message, timestamp: Date.now()}]);\n\t\t\tif(options.compress) history = await this.ai.llm.compress(<any>history, options.compress.max, options.compress.min, options);\n\n\t\t\tconst requestParams: any = {\n\t\t\t\tmodel: options.model || this.model,\n\t\t\t\tmessages: history,\n\t\t\t\tstream: !!options.stream,\n\t\t\t\tmax_tokens: options.max_tokens || this.ai.options.max_tokens || 4096,\n\t\t\t\ttemperature: options.temperature || this.ai.options.temperature || 0.7,\n\t\t\t\ttools: (options.tools || this.ai.options.tools || []).map(t => ({\n\t\t\t\t\ttype: 'function',\n\t\t\t\t\tfunction: {\n\t\t\t\t\t\tname: t.name,\n\t\t\t\t\t\tdescription: t.description,\n\t\t\t\t\t\tparameters: {\n\t\t\t\t\t\t\ttype: 'object',\n\t\t\t\t\t\t\tproperties: t.args ? objectMap(t.args, (key, value) => ({...value, required: undefined})) : {},\n\t\t\t\t\t\t\trequired: t.args ? Object.entries(t.args).filter(t => t[1].required).map(t => t[0]) : []\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}))\n\t\t\t};\n\n\t\t\tlet resp: any;\n\t\t\tconst loopMessages: any[] = [];\n\t\t\tdo {\n\t\t\t\tresp = await this.client.chat.completions.create(requestParams);\n\t\t\t\tif(options.stream) {\n\t\t\t\t\tif(loopMessages.length) options.stream({text: '\\n\\n'});\n\t\t\t\t\tresp.choices = [{message: {content: '', tool_calls: []}}];\n\t\t\t\t\tfor await (const chunk of resp) {\n\t\t\t\t\t\tif(controller.signal.aborted) break;\n\t\t\t\t\t\tif(chunk.choices[0].delta.content) {\n\t\t\t\t\t\t\tresp.choices[0].message.content += chunk.choices[0].delta.content;\n\t\t\t\t\t\t\toptions.stream({text: chunk.choices[0].delta.content});\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif(chunk.choices[0].delta.tool_calls) {\n\t\t\t\t\t\t\tresp.choices[0].message.tool_calls = chunk.choices[0].delta.tool_calls;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tloopMessages.push({role: 'assistant', content: resp.choices[0].message.content || '', timestamp: Date.now()});\n\n\t\t\t\tconst toolCalls = resp.choices[0].message.tool_calls || [];\n\t\t\t\tif(toolCalls.length && !controller.signal.aborted) {\n\t\t\t\t\thistory.push(resp.choices[0].message);\n\t\t\t\t\tconst results = await Promise.all(toolCalls.map(async (toolCall: any) => {\n\t\t\t\t\t\tconst tool = options.tools?.find(findByProp('name', toolCall.function.name));\n\t\t\t\t\t\tif(!tool) return {role: 'tool', tool_call_id: toolCall.id, content: '{\"error\": \"Tool not found\"}'};\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tconst args = JSONAttemptParse(toolCall.function.arguments, {});\n\t\t\t\t\t\t\tconst result = await tool.fn(args, this.ai);\n\t\t\t\t\t\t\treturn {role: 'tool', tool_call_id: toolCall.id, content: JSONSanitize(result)};\n\t\t\t\t\t\t} catch (err: any) {\n\t\t\t\t\t\t\treturn {role: 'tool', tool_call_id: toolCall.id, content: JSONSanitize({error: err?.message || err?.toString() || 'Unknown'})};\n\t\t\t\t\t\t}\n\t\t\t\t\t}));\n\t\t\t\t\thistory.push(...results);\n\t\t\t\t\tloopMessages.push(...results.map(r => ({...r, timestamp: Date.now()})));\n\t\t\t\t\trequestParams.messages = history;\n\t\t\t\t}\n\t\t\t} while (!controller.signal.aborted && resp.choices?.[0]?.message?.tool_calls?.length);\n\n\t\t\tconst combinedContent = loopMessages.filter(m => m.role === 'assistant')\n\t\t\t\t.map(m => m.content).filter(c => c).join('\\n\\n');\n\t\t\tif(options.stream) options.stream({done: true});\n\t\t\tres(this.toStandard([...history, {role: 'assistant', content: combinedContent, timestamp: Date.now()}]));\n\t\t});\n\t\treturn Object.assign(response, {abort: () => controller.abort()});\n\t}\n}\n","import {JSONAttemptParse} from '@ztimson/utils';\nimport {Ai} from './ai.ts';\nimport {Anthropic} from './antrhopic.ts';\nimport {Ollama} from './ollama.ts';\nimport {OpenAi} from './open-ai.ts';\nimport {AbortablePromise, LLMProvider} from './provider.ts';\nimport {AiTool} from './tools.ts';\n\nexport type LLMMessage = {\n\t/** Message originator */\n\trole: 'assistant' | 'system' | 'user';\n\t/** Message content */\n\tcontent: string | any;\n\t/** Timestamp */\n\ttimestamp?: number;\n} | {\n\t/** Tool call */\n\trole: 'tool';\n\t/** Unique ID for call */\n\tid: string;\n\t/** Tool that was run */\n\tname: string;\n\t/** Tool arguments */\n\targs: any;\n\t/** Tool result */\n\tcontent: undefined | string;\n\t/** Tool error */\n\terror: undefined | string;\n\t/** Timestamp */\n\ttimestamp?: number;\n}\n\nexport type LLMOptions = {\n\t/** Anthropic settings */\n\tanthropic?: {\n\t\t/** API Token */\n\t\ttoken: string;\n\t\t/** Default model */\n\t\tmodel: string;\n\t},\n\t/** Ollama settings */\n\tollama?: {\n\t\t/** connection URL */\n\t\thost: string;\n\t\t/** Default model */\n\t\tmodel: string;\n\t},\n\t/** Open AI settings */\n\topenAi?: {\n\t\t/** API Token */\n\t\ttoken: string;\n\t\t/** Default model */\n\t\tmodel: string;\n\t},\n\t/** Default provider & model */\n\tmodel: string | [string, string];\n} & Omit<LLMRequest, 'model'>;\n\nexport type LLMRequest = {\n\t/** System prompt */\n\tsystem?: string;\n\t/** Message history */\n\thistory?: LLMMessage[];\n\t/** Max tokens for request */\n\tmax_tokens?: number;\n\t/** 0 = Rigid Logic, 1 = Balanced, 2 = Hyper Creative **/\n\ttemperature?: number;\n\t/** Available tools */\n\ttools?: AiTool[];\n\t/** LLM model */\n\tmodel?: string | [string, string];\n\t/** Stream response */\n\tstream?: (chunk: {text?: string, done?: true}) => any;\n\t/** Compress old messages in the chat to free up context */\n\tcompress?: {\n\t\t/** Trigger chat compression once context exceeds the token count */\n\t\tmax: number;\n\t\t/** Compress chat until context size smaller than */\n\t\tmin: number\n\t}\n}\n\nexport class LLM {\n\tprivate providers: {[key: string]: LLMProvider} = {};\n\n\tconstructor(public readonly ai: Ai, public readonly options: LLMOptions) {\n\t\tif(options.anthropic?.token) this.providers.anthropic = new Anthropic(this.ai, options.anthropic.token, options.anthropic.model);\n\t\tif(options.ollama?.host) this.providers.ollama = new Ollama(this.ai, options.ollama.host, options.ollama.model);\n\t\tif(options.openAi?.token) this.providers.openAi = new OpenAi(this.ai, options.openAi.token, options.openAi.model);\n\t}\n\n\t/**\n\t * Chat with LLM\n\t * @param {string} message Question\n\t * @param {LLMRequest} options Configuration options and chat history\n\t * @returns {{abort: () => void, response: Promise<LLMMessage[]>}} Function to abort response and chat history\n\t */\n\task(message: string, options: LLMRequest = {}): AbortablePromise<LLMMessage[]> {\n\t\tlet model: any = [null, null];\n\t\tif(options.model) {\n\t\t\tif(typeof options.model == 'object') model = options.model;\n\t\t\telse model = [options.model, (<any>this.options)[options.model]?.model];\n\t\t}\n\t\tif(!options.model || model[1] == null) {\n\t\t\tif(typeof this.options.model == 'object') model = this.options.model;\n\t\t\telse model = [this.options.model, (<any>this.options)[this.options.model]?.model];\n\t\t}\n\t\tif(!model[0] || !model[1]) throw new Error(`Unknown LLM provider or model: ${model[0]} / ${model[1]}`);\n\t\treturn this.providers[model[0]].ask(message, {...options, model: model[1]});\n\t}\n\n\t/**\n\t * Compress chat history to reduce context size\n\t * @param {LLMMessage[]} history Chatlog that will be compressed\n\t * @param max Trigger compression once context is larger than max\n\t * @param min Summarize until context size is less than min\n\t * @param {LLMRequest} options LLM options\n\t * @returns {Promise<LLMMessage[]>} New chat history will summary at index 0\n\t */\n\tasync compress(history: LLMMessage[], max: number, min: number, options?: LLMRequest): Promise<LLMMessage[]> {\n\t\tif(this.estimateTokens(history) < max) return history;\n\t\tlet keep = 0, tokens = 0;\n\t\tfor(let m of history.toReversed()) {\n\t\t\ttokens += this.estimateTokens(m.content);\n\t\t\tif(tokens < min) keep++;\n\t\t\telse break;\n\t\t}\n\t\tif(history.length <= keep) return history;\n\t\tconst recent = keep == 0 ? [] : history.slice(-keep),\n\t\t\tprocess = (keep == 0 ? history : history.slice(0, -keep)).filter(h => h.role === 'assistant' || h.role === 'user');\n\t\tconst summary = await this.summarize(process.map(m => `${m.role}: ${m.content}`).join('\\n\\n'), 250, options);\n\t\treturn [{role: 'assistant', content: `Conversation Summary: ${summary}`, timestamp: Date.now()}, ...recent];\n\t}\n\n\t/**\n\t * Estimate variable as tokens\n\t * @param history Object to size\n\t * @returns {number} Rough token count\n\t */\n\testimateTokens(history: any): number {\n\t\tconst text = JSON.stringify(history);\n\t\treturn Math.ceil((text.length / 4) * 1.2);\n\t}\n\n\t/**\n\t * Ask a question with JSON response\n\t * @param {string} message Question\n\t * @param {LLMRequest} options Configuration options and chat history\n\t * @returns {Promise<{} | {} | RegExpExecArray | null>}\n\t */\n\tasync json(message: string, options?: LLMRequest) {\n\t\tlet resp = await this.ask(message, {\n\t\t\tsystem: 'Respond using a JSON blob',\n\t\t\t...options\n\t\t});\n\t\tif(!resp?.[0]?.content) return {};\n\t\treturn JSONAttemptParse(new RegExp('\\{[\\s\\S]*\\}').exec(resp[0].content), {});\n\t}\n\n\t/**\n\t * Create a summary of some text\n\t * @param {string} text Text to summarize\n\t * @param {number} tokens Max number of tokens\n\t * @param options LLM request options\n\t * @returns {Promise<string>} Summary\n\t */\n\tsummarize(text: string, tokens: number, options?: LLMRequest): Promise<string | null> {\n\t\treturn this.ask(text, {system: `Generate a brief summary <= ${tokens} tokens. Output nothing else`, temperature: 0.3, ...options})\n\t\t\t.then(history => <string>history.pop()?.content || null);\n\t}\n}\n","import {createWorker} from 'tesseract.js';\nimport {LLM, LLMOptions} from './llm';\nimport fs from 'node:fs/promises';\nimport Path from 'node:path';\nimport * as tf from '@tensorflow/tfjs';\nimport {spawn} from 'node:child_process';\n\nexport type AiOptions = LLMOptions & {\n\twhisper?: {\n\t\t/** Whisper binary location */\n\t\tbinary: string;\n\t\t/** Model: `ggml-base.en.bin` */\n\t\tmodel: string;\n\t\t/** Path to models */\n\t\tpath: string;\n\t}\n}\n\nexport class Ai {\n\tprivate downloads: {[key: string]: Promise<string>} = {};\n\tprivate whisperModel!: string;\n\n\t/** Large Language Models */\n\tllm!: LLM;\n\n\tconstructor(public readonly options: AiOptions) {\n\t\tthis.llm = new LLM(this, options);\n\t\tif(this.options.whisper?.binary) {\n\t\t\tthis.whisperModel = this.options.whisper?.model.endsWith('.bin') ? this.options.whisper?.model : this.options.whisper?.model + '.bin';\n\t\t\tthis.downloadAsrModel();\n\t\t}\n\t}\n\n\t/**\n\t * Convert audio to text using Auditory Speech Recognition\n\t * @param {string} path Path to audio\n\t * @param model Whisper model\n\t * @returns {Promise<any>} Extracted text\n\t */\n\tasr(path: string, model: string = this.whisperModel): {abort: () => void, response: Promise<string | null>} {\n\t\tif(!this.options.whisper?.binary) throw new Error('Whisper not configured');\n\t\tlet abort: any = () => {};\n\t\tconst response = new Promise<string | null>((resolve, reject) => {\n\t\t\tthis.downloadAsrModel(model).then(m => {\n\t\t\t\tlet output = '';\n\t\t\t\tconst proc = spawn(<string>this.options.whisper?.binary, ['-nt', '-np', '-m', m, '-f', path], {stdio: ['ignore', 'pipe', 'ignore']});\n\t\t\t\tabort = () => proc.kill('SIGTERM');\n\t\t\t\tproc.on('error', (err: Error) => reject(err));\n\t\t\t\tproc.stdout.on('data', (data: Buffer) => output += data.toString());\n\t\t\t\tproc.on('close', (code: number) => {\n\t\t\t\t\tif(code === 0) resolve(output.trim() || null);\n\t\t\t\t\telse reject(new Error(`Exit code ${code}`));\n\t\t\t\t});\n\t\t\t});\n\t\t});\n\t\treturn {response, abort};\n\t}\n\n\t/**\n\t * Downloads the specified Whisper model if it is not already present locally.\n\t *\n\t * @param {string} model Whisper model that will be downloaded\n\t * @return {Promise<string>} Absolute path to model file, resolves once downloaded\n\t */\n\tasync downloadAsrModel(model: string = this.whisperModel): Promise<string> {\n\t\tif(!this.options.whisper?.binary) throw new Error('Whisper not configured');\n\t\tif(!model.endsWith('.bin')) model += '.bin';\n\t\tconst p = Path.join(this.options.whisper.path, model);\n\t\tif(await fs.stat(p).then(() => true).catch(() => false)) return p;\n\t\tif(!!this.downloads[model]) return this.downloads[model];\n\t\tthis.downloads[model] = fetch(`https://huggingface.co/ggerganov/whisper.cpp/resolve/main/${model}`)\n\t\t\t.then(resp => resp.arrayBuffer())\n\t\t\t.then(arr => Buffer.from(arr)).then(async buffer => {\n\t\t\t\tawait fs.writeFile(p, buffer);\n\t\t\t\tdelete this.downloads[model];\n\t\t\t\treturn p;\n\t\t\t});\n\t\treturn this.downloads[model];\n\t}\n\n\t/**\n\t * Convert image to text using Optical Character Recognition\n\t * @param {string} path Path to image\n\t * @returns {{abort: Function, response: Promise<string | null>}} Abort function & Promise of extracted text\n\t */\n\tocr(path: string): {abort: () => void, response: Promise<string | null>} {\n\t\tlet worker: any;\n\t\treturn {\n\t\t\tabort: () => { worker?.terminate(); },\n\t\t\tresponse: new Promise(async res => {\n\t\t\t\tworker = await createWorker('eng');\n\t\t\t\tconst {data} = await worker.recognize(path);\n\t\t\t\tawait worker.terminate();\n\t\t\t\tres(data.text.trim() || null);\n\t\t\t})\n\t\t}\n\t}\n\n\t/**\n\t * Compare the difference between two strings using tensor math\n\t * @param target Text that will checked\n\t * @param {string} searchTerms Multiple search terms to check against target\n\t * @returns {{avg: number, max: number, similarities: number[]}} Similarity values 0-1: 0 = unique, 1 = identical\n\t */\n\tsemanticSimilarity(target: string, ...searchTerms: string[]) {\n\t\tif(searchTerms.length < 2) throw new Error('Requires at least 2 strings to compare');\n\n\t\tconst vector = (text: string, dimensions: number = 10): number[] => {\n\t\t\treturn text.toLowerCase().split('').map((char, index) =>\n\t\t\t\t(char.charCodeAt(0) * (index + 1)) % dimensions / dimensions).slice(0, dimensions);\n\t\t}\n\n\t\tconst cosineSimilarity = (v1: number[], v2: number[]): number => {\n\t\t\tif (v1.length !== v2.length) throw new Error('Vectors must be same length');\n\t\t\tconst tensor1 = tf.tensor1d(v1), tensor2 = tf.tensor1d(v2)\n\t\t\tconst dotProduct = tf.dot(tensor1, tensor2)\n\t\t\tconst magnitude1 = tf.norm(tensor1)\n\t\t\tconst magnitude2 = tf.norm(tensor2)\n\t\t\tif(magnitude1.dataSync()[0] === 0 || magnitude2.dataSync()[0] === 0) return 0\n\t\t\treturn dotProduct.dataSync()[0] / (magnitude1.dataSync()[0] * magnitude2.dataSync()[0])\n\t\t}\n\n\t\tconst v = vector(target);\n\t\tconst similarities = searchTerms.map(t => vector(t)).map(refVector => cosineSimilarity(v, refVector))\n\t\treturn {avg: similarities.reduce((acc, s) => acc + s, 0) / similarities.length, max: Math.max(...similarities), similarities}\n\t}\n}\n","import {$, $Sync} from '@ztimson/node-utils';\nimport {ASet, consoleInterceptor, Http, fn as Fn} from '@ztimson/utils';\nimport {Ai} from './ai.ts';\n\nexport type AiToolArg = {[key: string]: {\n\t/** Argument type */\n\ttype: 'array' | 'boolean' | 'number' | 'object' | 'string',\n\t/** Argument description */\n\tdescription: string,\n\t/** Required argument */\n\trequired?: boolean;\n\t/** Default value */\n\tdefault?: any,\n\t/** Options */\n\tenum?: string[],\n\t/** Minimum value or length */\n\tmin?: number,\n\t/** Maximum value or length */\n\tmax?: number,\n\t/** Match pattern */\n\tpattern?: string,\n\t/** Child arguments */\n\titems?: {[key: string]: AiToolArg}\n}}\n\nexport type AiTool = {\n\t/** Tool ID / Name - Must be snail_case */\n\tname: string,\n\t/** Tool description / prompt */\n\tdescription: string,\n\t/** Tool arguments */\n\targs?: AiToolArg,\n\t/** Callback function */\n\tfn: (args: any, ai: Ai) => any | Promise<any>,\n};\n\nexport const CliTool: AiTool = {\n\tname: 'cli',\n\tdescription: 'Use the command line interface, returns any output',\n\targs: {command: {type: 'string', description: 'Command to run', required: true}},\n\tfn: (args: {command: string}) => $`${args.command}`\n}\n\nexport const DateTimeTool: AiTool = {\n\tname: 'get_datetime',\n\tdescription: 'Get current date and time',\n\targs: {},\n\tfn: async () => new Date().toISOString()\n}\n\nexport const ExecTool: AiTool = {\n\tname: 'exec',\n\tdescription: 'Run code/scripts',\n\targs: {\n\t\tlanguage: {type: 'string', description: 'Execution language', enum: ['cli', 'node', 'python'], required: true},\n\t\tcode: {type: 'string', description: 'Code to execute', required: true}\n\t},\n\tfn: async (args, ai) => {\n\t\ttry {\n\t\t\tswitch(args.type) {\n\t\t\t\tcase 'bash':\n\t\t\t\t\treturn await CliTool.fn({command: args.code}, ai);\n\t\t\t\tcase 'node':\n\t\t\t\t\treturn await JSTool.fn({code: args.code}, ai);\n\t\t\t\tcase 'python': {\n\t\t\t\t\treturn await PythonTool.fn({code: args.code}, ai);\n\t\t\t\t}\n\t\t\t}\n\t\t} catch(err: any) {\n\t\t\treturn {error: err?.message || err.toString()};\n\t\t}\n\t}\n}\n\nexport const FetchTool: AiTool = {\n\tname: 'fetch',\n\tdescription: 'Make HTTP request to URL',\n\targs: {\n\t\turl: {type: 'string', description: 'URL to fetch', required: true},\n\t\tmethod: {type: 'string', description: 'HTTP method to use', enum: ['GET', 'POST', 'PUT', 'DELETE'], default: 'GET'},\n\t\theaders: {type: 'object', description: 'HTTP headers to send', default: {}},\n\t\tbody: {type: 'object', description: 'HTTP body to send'},\n\t},\n\tfn: (args: {\n\t\turl: string;\n\t\tmethod: 'GET' | 'POST' | 'PUT' | 'DELETE';\n\t\theaders: {[key: string]: string};\n\t\tbody: any;\n\t}) => new Http({url: args.url, headers: args.headers}).request({method: args.method || 'GET', body: args.body})\n}\n\nexport const JSTool: AiTool = {\n\tname: 'exec_javascript',\n\tdescription: 'Execute commonjs javascript',\n\targs: {\n\t\tcode: {type: 'string', description: 'CommonJS javascript', required: true}\n\t},\n\tfn: async (args: {code: string}) => {\n\t\tconst console = consoleInterceptor(null);\n\t\tconst resp = await Fn<any>({console}, args.code, true).catch((err: any) => console.output.error.push(err));\n\t\treturn {...console.output, return: resp, stdout: undefined, stderr: undefined};\n\t}\n}\n\nexport const PythonTool: AiTool = {\n\tname: 'exec_javascript',\n\tdescription: 'Execute commonjs javascript',\n\targs: {\n\t\tcode: {type: 'string', description: 'CommonJS javascript', required: true}\n\t},\n\tfn: async (args: {code: string}) => ({result: $Sync`python -c \"${args.code}\"`})\n}\n\nexport const SearchTool: AiTool = {\n\tname: 'search',\n\tdescription: 'Use a search engine to find relevant URLs, should be changed with fetch to scrape sources',\n\targs: {\n\t\tquery: {type: 'string', description: 'Search string', required: true},\n\t\tlength: {type: 'string', description: 'Number of results to return', default: 5},\n\t},\n\tfn: async (args: {\n\t\tquery: string;\n\t\tlength: number;\n\t}) => {\n\t\tconst html = await fetch(`https://html.duckduckgo.com/html/?q=${encodeURIComponent(args.query)}`, {\n\t\t\theaders: {\"User-Agent\": \"Mozilla/5.0 (Windows NT 10.0; Win64; x64)\", \"Accept-Language\": \"en-US,en;q=0.9\"}\n\t\t}).then(resp => resp.text());\n\t\tlet match, regex = /<a .*?href=\"(.+?)\".+?<\\/a>/g;\n\t\tconst results = new ASet<string>();\n\t\twhile((match = regex.exec(html)) !== null) {\n\t\t\tlet url = /uddg=(.+)&?/.exec(decodeURIComponent(match[1]))?.[1];\n\t\t\tif(url) url = decodeURIComponent(url);\n\t\t\tif(url) results.add(url);\n\t\t\tif(results.size >= (args.length || 5)) break;\n\t\t}\n\t\treturn results;\n\t}\n}\n"],"names":["LLMProvider","Anthropic","ai","apiToken","model","anthropic","history","i","orgI","c","h","timestamp","message","options","controller","response","res","rej","requestParams","t","objectMap","key","value","resp","loopMessages","chunk","text","last","JSONAttemptParse","toolCalls","userMsg","toolCall","tool","findByProp","result","JSONSanitize","err","combinedContent","m","Ollama","host","ollama","error","rest","system","results","args","r","OpenAi","openAI","tools","tc","record","h2","LLM","max","min","keep","tokens","recent","process","Ai","path","abort","resolve","reject","output","proc","spawn","data","code","p","Path","fs","arr","buffer","worker","createWorker","target","searchTerms","vector","dimensions","char","index","cosineSimilarity","v1","v2","tensor1","tf","tensor2","dotProduct","magnitude1","magnitude2","v","similarities","refVector","acc","s","CliTool","$","DateTimeTool","ExecTool","JSTool","PythonTool","FetchTool","Http","console","consoleInterceptor","Fn","$Sync","SearchTool","html","match","regex","ASet","url"],"mappings":"6gCAIO,MAAeA,CAAY,CAElC,CCAO,MAAMC,UAAkBD,CAAY,CAG1C,YAA4BE,EAAwBC,EAAyBC,EAAe,CAC3F,MAAA,EAD2B,KAAA,GAAAF,EAAwB,KAAA,SAAAC,EAAyB,KAAA,MAAAC,EAE5E,KAAK,OAAS,IAAIC,EAAAA,UAAU,CAAC,OAAQF,EAAS,CAC/C,CALA,OAOQ,WAAWG,EAA8B,CAChD,QAAQC,EAAI,EAAGA,EAAID,EAAQ,OAAQC,IAAK,CACvC,MAAMC,EAAOD,EACV,OAAOD,EAAQE,CAAI,EAAE,SAAW,WAC/BF,EAAQE,CAAI,EAAE,MAAQ,YACxBF,EAAQE,CAAI,EAAE,QAAQ,OAAQC,GAAWA,EAAE,MAAO,UAAU,EAAE,QAASA,GAAW,CACjFF,IACAD,EAAQ,OAAOC,EAAG,EAAG,CAAC,KAAM,OAAQ,GAAIE,EAAE,GAAI,KAAMA,EAAE,KAAM,KAAMA,EAAE,MAAO,UAAW,KAAK,IAAA,EAAM,CAClG,CAAC,EACQH,EAAQE,CAAI,EAAE,MAAQ,QAC/BF,EAAQE,CAAI,EAAE,QAAQ,OAAQC,GAAWA,EAAE,MAAO,aAAa,EAAE,QAASA,GAAW,CACpF,MAAMC,EAAIJ,EAAQ,KAAMI,GAAWA,EAAE,IAAMD,EAAE,WAAW,EACxDC,EAAED,EAAE,SAAW,QAAU,SAAS,EAAIA,EAAE,OACzC,CAAC,EAEFH,EAAQE,CAAI,EAAE,QAAUF,EAAQE,CAAI,EAAE,QAAQ,OAAQC,GAAWA,EAAE,MAAQ,MAAM,EAAE,IAAKA,GAAWA,EAAE,IAAI,EAAE,KAAK;AAAA;AAAA,CAAM,GAEnHH,EAAQE,CAAI,EAAE,cAAmBA,CAAI,EAAE,UAAY,KAAK,IAAA,EAC7D,CACA,OAAOF,EAAQ,OAAOI,GAAK,CAAC,CAACA,EAAE,OAAO,CACvC,CAEQ,aAAaJ,EAA8B,CAClD,QAAQC,EAAI,EAAGA,EAAID,EAAQ,OAAQC,IAClC,GAAGD,EAAQC,CAAC,EAAE,MAAQ,OAAQ,CAC7B,MAAMG,EAASJ,EAAQC,CAAC,EACxBD,EAAQ,OAAOC,EAAG,EACjB,CAAC,KAAM,YAAa,QAAS,CAAC,CAAC,KAAM,WAAY,GAAIG,EAAE,GAAI,KAAMA,EAAE,KAAM,MAAOA,EAAE,IAAA,CAAK,CAAA,EACvF,CAAC,KAAM,OAAQ,QAAS,CAAC,CAAC,KAAM,cAAe,YAAaA,EAAE,GAAI,SAAU,CAAC,CAACA,EAAE,MAAO,QAAUA,EAAE,OAASA,EAAE,QAAQ,CAAA,CAAC,EAExHH,GACD,CAED,OAAOD,EAAQ,IAAI,CAAC,CAAC,UAAAK,EAAW,GAAGD,CAAA,IAAOA,CAAC,CAC5C,CAEA,IAAIE,EAAiBC,EAAsB,GAAoC,CAC9E,MAAMC,EAAa,IAAI,gBACjBC,EAAW,IAAI,QAAa,MAAOC,EAAKC,IAAQ,CACrD,IAAIX,EAAU,KAAK,aAAa,CAAC,GAAGO,EAAQ,SAAW,GAAI,CAAC,KAAM,OAAQ,QAASD,EAAS,UAAW,KAAK,IAAA,CAAI,CAAE,CAAC,EAChHC,EAAQ,WAAUP,EAAU,MAAM,KAAK,GAAG,IAAI,SAAcA,EAASO,EAAQ,SAAS,IAAKA,EAAQ,SAAS,IAAKA,CAAO,GAC3H,MAAMK,EAAqB,CAC1B,MAAOL,EAAQ,OAAS,KAAK,MAC7B,WAAYA,EAAQ,YAAc,KAAK,GAAG,QAAQ,YAAc,KAChE,OAAQA,EAAQ,QAAU,KAAK,GAAG,QAAQ,QAAU,GACpD,YAAaA,EAAQ,aAAe,KAAK,GAAG,QAAQ,aAAe,GACnE,OAAQA,EAAQ,OAAS,KAAK,GAAG,QAAQ,OAAS,CAAA,GAAI,IAAIM,IAAM,CAC/D,KAAMA,EAAE,KACR,YAAaA,EAAE,YACf,aAAc,CACb,KAAM,SACN,WAAYA,EAAE,KAAOC,EAAAA,UAAUD,EAAE,KAAM,CAACE,EAAKC,KAAW,CAAC,GAAGA,EAAO,SAAU,MAAA,EAAW,EAAI,CAAA,EAC5F,SAAUH,EAAE,KAAO,OAAO,QAAQA,EAAE,IAAI,EAAE,OAAOA,GAAKA,EAAE,CAAC,EAAE,QAAQ,EAAE,IAAIA,GAAKA,EAAE,CAAC,CAAC,EAAI,CAAA,CAAC,EAExF,GAAI,MAAA,EACH,EACF,SAAUb,EACV,OAAQ,CAAC,CAACO,EAAQ,MAAA,EAGnB,IAAIU,EACJ,MAAMC,EAAsB,CAAA,EAC5B,EAAG,CAEF,GADAD,EAAO,MAAM,KAAK,OAAO,SAAS,OAAOL,CAAa,EACnDL,EAAQ,OAAQ,CACfW,EAAa,QAAQX,EAAQ,OAAO,CAAC,KAAM;AAAA;AAAA,EAAO,EACrDU,EAAK,QAAU,CAAA,EACf,gBAAiBE,KAASF,EAAM,CAC/B,GAAGT,EAAW,OAAO,QAAS,MAC9B,GAAGW,EAAM,OAAS,sBACdA,EAAM,cAAc,OAAS,OAC/BF,EAAK,QAAQ,KAAK,CAAC,KAAM,OAAQ,KAAM,GAAG,EACjCE,EAAM,cAAc,OAAS,YACtCF,EAAK,QAAQ,KAAK,CAAC,KAAM,WAAY,GAAIE,EAAM,cAAc,GAAI,KAAMA,EAAM,cAAc,KAAM,MAAY,GAAG,UAExGA,EAAM,OAAS,sBACxB,GAAGA,EAAM,MAAM,OAAS,aAAc,CACrC,MAAMC,EAAOD,EAAM,MAAM,KACzBF,EAAK,QAAQ,GAAG,EAAE,EAAE,MAAQG,EAC5Bb,EAAQ,OAAO,CAAC,KAAAa,EAAK,CACtB,MAAUD,EAAM,MAAM,OAAS,qBAC9BF,EAAK,QAAQ,GAAG,EAAE,EAAE,OAASE,EAAM,MAAM,sBAEjCA,EAAM,OAAS,qBAAsB,CAC9C,MAAME,EAAOJ,EAAK,QAAQ,GAAG,EAAE,EAC5BI,EAAK,OAAS,OAAMA,EAAK,MAAQA,EAAK,MAAQC,EAAAA,iBAAiBD,EAAK,MAAO,CAAA,CAAE,EAAI,CAAA,EACrF,SAAUF,EAAM,OAAS,eACxB,KAEF,CACD,CAEAD,EAAa,KAAK,CAAC,KAAM,YAAa,QAASD,EAAK,QAAS,UAAW,KAAK,IAAA,CAAI,CAAE,EACnF,MAAMM,EAAYN,EAAK,QAAQ,OAAQd,GAAWA,EAAE,OAAS,UAAU,EACvE,GAAGoB,EAAU,QAAU,CAACf,EAAW,OAAO,QAAS,CAClDR,EAAQ,KAAK,CAAC,KAAM,YAAa,QAASiB,EAAK,QAAQ,EAWvD,MAAMO,EAAU,CAAC,KAAM,OAAQ,QAVf,MAAM,QAAQ,IAAID,EAAU,IAAI,MAAOE,GAAkB,CACxE,MAAMC,EAAOnB,EAAQ,OAAO,KAAKoB,EAAAA,WAAW,OAAQF,EAAS,IAAI,CAAC,EAClE,GAAG,CAACC,EAAM,MAAO,CAAC,YAAaD,EAAS,GAAI,SAAU,GAAM,QAAS,gBAAA,EACrE,GAAI,CACH,MAAMG,EAAS,MAAMF,EAAK,GAAGD,EAAS,MAAO,KAAK,EAAE,EACpD,MAAO,CAAC,KAAM,cAAe,YAAaA,EAAS,GAAI,QAASI,eAAaD,CAAM,CAAA,CACpF,OAASE,EAAU,CAClB,MAAO,CAAC,KAAM,cAAe,YAAaL,EAAS,GAAI,SAAU,GAAM,QAASK,GAAK,SAAWA,GAAK,SAAA,GAAc,SAAA,CACpH,CACD,CAAC,CAAC,CACsC,EACxC9B,EAAQ,KAAKwB,CAAO,EACpBN,EAAa,KAAK,CAAC,GAAGM,EAAS,UAAW,KAAK,IAAA,EAAM,EACrDZ,EAAc,SAAWZ,CAC1B,CACD,OAAS,CAACQ,EAAW,OAAO,SAAWS,EAAK,QAAQ,KAAMd,GAAWA,EAAE,OAAS,UAAU,GAE1F,MAAM4B,EAAkBb,EAAa,OAAOc,GAAKA,EAAE,OAAS,WAAW,EACrE,OAASA,EAAE,QAAQ,OAAQ7B,GAAWA,EAAE,MAAQ,MAAM,EAAE,IAAKA,GAAWA,EAAE,IAAI,EAAE,KAAK;AAAA;AAAA,CAAM,CAAC,EAC5F,OAAOA,GAAKA,CAAC,EAAE,KAAK;AAAA;AAAA,CAAM,EACzBI,EAAQ,QAAQA,EAAQ,OAAO,CAAC,KAAM,GAAK,EAC9CG,EAAI,KAAK,WAAW,CAAC,GAAGV,EAAS,CAAC,KAAM,YAAa,QAAS+B,EAAiB,UAAW,KAAK,IAAA,CAAI,CAAE,CAAC,CAAC,CACxG,CAAC,EAED,OAAO,OAAO,OAAOtB,EAAU,CAAC,MAAO,IAAMD,EAAW,MAAA,EAAQ,CACjE,CACD,CClIO,MAAMyB,UAAevC,CAAY,CAGvC,YAA4BE,EAAesC,EAAqBpC,EAAe,CAC9E,MAAA,EAD2B,KAAA,GAAAF,EAAe,KAAA,KAAAsC,EAAqB,KAAA,MAAApC,EAE/D,KAAK,OAAS,IAAIqC,SAAO,CAAC,KAAAD,EAAK,CAChC,CALA,OAOQ,WAAWlC,EAA8B,CAChD,QAAQC,EAAI,EAAGA,EAAID,EAAQ,OAAQC,IAAK,CACvC,GAAGD,EAAQC,CAAC,EAAE,MAAQ,aAAeD,EAAQC,CAAC,EAAE,WAC5CD,EAAQC,CAAC,EAAE,QAAS,OAAOD,EAAQC,CAAC,EAAE,YAExCD,EAAQ,OAAOC,EAAG,CAAC,EACnBA,aAEQD,EAAQC,CAAC,EAAE,MAAQ,OAAQ,CACpC,MAAMmC,EAAQpC,EAAQC,CAAC,EAAE,QAAQ,WAAW,WAAW,EACvDD,EAAQC,CAAC,EAAI,CAAC,KAAM,OAAQ,KAAMD,EAAQC,CAAC,EAAE,UAAW,KAAMD,EAAQC,CAAC,EAAE,KAAM,CAACmC,EAAQ,QAAU,SAAS,EAAGpC,EAAQC,CAAC,EAAE,QAAS,UAAWD,EAAQC,CAAC,EAAE,SAAA,CACzJ,CACID,EAAQC,CAAC,GAAG,cAAmBA,CAAC,EAAE,UAAY,KAAK,IAAA,EACxD,CACA,OAAOD,CACR,CAEQ,aAAaA,EAA8B,CAClD,OAAOA,EAAQ,IAAKI,GAAW,CAC9B,KAAM,CAAC,UAAAC,EAAW,GAAGgC,CAAA,EAAQjC,EAC7B,OAAGA,EAAE,MAAQ,OAAeiC,EACrB,CAAC,KAAM,OAAQ,UAAWjC,EAAE,KAAM,QAASA,EAAE,OAASA,EAAE,OAAA,CAChE,CAAC,CACF,CAEA,IAAIE,EAAiBC,EAAsB,GAAoC,CAC9E,MAAMC,EAAa,IAAI,gBACjBC,EAAW,IAAI,QAAa,MAAOC,EAAKC,IAAQ,CACrD,IAAI2B,EAAS/B,EAAQ,QAAU,KAAK,GAAG,QAAQ,OAC3CP,EAAU,KAAK,aAAa,CAAC,GAAGO,EAAQ,SAAW,GAAI,CAAC,KAAM,OAAQ,QAASD,EAAS,UAAW,KAAK,IAAA,CAAI,CAAE,CAAC,EAChHN,EAAQ,CAAC,EAAE,MAAQ,WACjBsC,IACS,MAAA,EADDA,EAAStC,EAAQ,MAAA,GAG3BO,EAAQ,WAAUP,EAAU,MAAM,KAAK,GAAG,IAAI,SAAcA,EAASO,EAAQ,SAAS,IAAKA,EAAQ,SAAS,GAAG,GAC/GA,EAAQ,QAAQP,EAAQ,QAAQ,CAAC,KAAM,SAAU,QAASsC,EAAO,EAEpE,MAAM1B,EAAqB,CAC1B,MAAOL,EAAQ,OAAS,KAAK,MAC7B,SAAUP,EACV,OAAQ,CAAC,CAACO,EAAQ,OAClB,OAAQC,EAAW,OACnB,QAAS,CACR,YAAaD,EAAQ,aAAe,KAAK,GAAG,QAAQ,aAAe,GACnE,YAAaA,EAAQ,YAAc,KAAK,GAAG,QAAQ,YAAc,IAAA,EAElE,OAAQA,EAAQ,OAAS,KAAK,GAAG,QAAQ,OAAS,CAAA,GAAI,IAAIM,IAAM,CAC/D,KAAM,WACN,SAAU,CACT,KAAMA,EAAE,KACR,YAAaA,EAAE,YACf,WAAY,CACX,KAAM,SACN,WAAYA,EAAE,KAAOC,EAAAA,UAAUD,EAAE,KAAM,CAACE,EAAKC,KAAW,CAAC,GAAGA,EAAO,SAAU,MAAA,EAAW,EAAI,CAAA,EAC5F,SAAUH,EAAE,KAAO,OAAO,QAAQA,EAAE,IAAI,EAAE,OAAOA,GAAKA,EAAE,CAAC,EAAE,QAAQ,EAAE,IAAIA,GAAKA,EAAE,CAAC,CAAC,EAAI,CAAA,CAAC,CACxF,CACD,EACC,CAAA,EAGH,IAAII,EACJ,MAAMC,EAAsB,CAAA,EAC5B,EAAG,CAEF,GADAD,EAAO,MAAM,KAAK,OAAO,KAAKL,CAAa,EACxCL,EAAQ,OAAQ,CACfW,EAAa,QAAQX,EAAQ,OAAO,CAAC,KAAM;AAAA;AAAA,EAAO,EACrDU,EAAK,QAAU,CAAC,KAAM,YAAa,QAAS,GAAI,WAAY,EAAC,EAC7D,gBAAiBE,KAASF,EAOzB,GANGT,EAAW,OAAO,UAClBW,EAAM,SAAS,UACjBF,EAAK,QAAQ,SAAWE,EAAM,QAAQ,QACtCZ,EAAQ,OAAO,CAAC,KAAMY,EAAM,QAAQ,QAAQ,GAE1CA,EAAM,SAAS,eAAiB,QAAQ,WAAaA,EAAM,QAAQ,YACnEA,EAAM,MAAM,KAEjB,CAGA,GADAD,EAAa,KAAK,CAAC,KAAM,YAAa,QAASD,EAAK,SAAS,QAAS,UAAW,KAAK,IAAA,CAAI,CAAE,EACzFA,EAAK,SAAS,YAAY,QAAU,CAACT,EAAW,OAAO,QAAS,CAClER,EAAQ,KAAKiB,EAAK,OAAO,EACzB,MAAMsB,EAAU,MAAM,QAAQ,IAAItB,EAAK,QAAQ,WAAW,IAAI,MAAOQ,GAAkB,CACtF,MAAMC,GAAQnB,EAAQ,OAAS,KAAK,GAAG,QAAQ,QAAQ,KAAKoB,EAAAA,WAAW,OAAQF,EAAS,SAAS,IAAI,CAAC,EACtG,GAAG,CAACC,EAAM,MAAO,CAAC,KAAM,OAAQ,UAAWD,EAAS,SAAS,KAAM,QAAS,6BAAA,EAC5E,MAAMe,EAAO,OAAOf,EAAS,SAAS,WAAc,SAAWH,EAAAA,iBAAiBG,EAAS,SAAS,UAAW,CAAA,CAAE,EAAIA,EAAS,SAAS,UACrI,GAAI,CACH,MAAMG,EAAS,MAAMF,EAAK,GAAGc,EAAM,KAAK,EAAE,EAC1C,MAAO,CAAC,KAAM,OAAQ,UAAWf,EAAS,SAAS,KAAM,KAAAe,EAAM,QAASX,EAAAA,aAAaD,CAAM,CAAA,CAC5F,OAASE,EAAU,CAClB,MAAO,CAAC,KAAM,OAAQ,UAAWL,EAAS,SAAS,KAAM,KAAAe,EAAM,QAASX,EAAAA,aAAa,CAAC,MAAOC,GAAK,SAAWA,GAAK,YAAc,SAAA,CAAU,CAAA,CAC3I,CACD,CAAC,CAAC,EACF9B,EAAQ,KAAK,GAAGuC,CAAO,EACvBrB,EAAa,KAAK,GAAGqB,EAAQ,IAAIE,IAAM,CAAC,GAAGA,EAAG,UAAW,KAAK,IAAA,CAAI,EAAG,CAAC,EACtE7B,EAAc,SAAWZ,CAC1B,CACD,OAAS,CAACQ,EAAW,OAAO,SAAWS,EAAK,SAAS,YAAY,QAEjE,MAAMc,EAAkBb,EAAa,UAAYc,EAAE,OAAS,WAAW,EACrE,IAAIA,GAAKA,EAAE,OAAO,EAAE,UAAY7B,CAAC,EAAE,KAAK;AAAA;AAAA,CAAM,EAC7CI,EAAQ,QAAQA,EAAQ,OAAO,CAAC,KAAM,GAAK,EAC9CG,EAAI,KAAK,WAAW,CAAC,GAAGV,EAAS,CAAC,KAAM,YAAa,QAAS+B,EAAiB,UAAW,KAAK,IAAA,CAAI,CAAE,CAAC,CAAC,CACxG,CAAC,EAED,OAAO,OAAO,OAAOtB,EAAU,CAAC,MAAO,IAAMD,EAAW,MAAA,EAAQ,CACjE,CACD,CClHO,MAAMkC,UAAehD,CAAY,CAGvC,YAA4BE,EAAwBC,EAAyBC,EAAe,CAC3F,MAAA,EAD2B,KAAA,GAAAF,EAAwB,KAAA,SAAAC,EAAyB,KAAA,MAAAC,EAE5E,KAAK,OAAS,IAAI6C,EAAAA,OAAO,CAAC,OAAQ9C,EAAS,CAC5C,CALA,OAOQ,WAAWG,EAA8B,CAChD,QAAQC,EAAI,EAAGA,EAAID,EAAQ,OAAQC,IAAK,CACvC,MAAMG,EAAIJ,EAAQC,CAAC,EACnB,GAAGG,EAAE,OAAS,aAAeA,EAAE,WAAY,CAC1C,MAAMwC,EAAQxC,EAAE,WAAW,IAAKyC,IAAa,CAC5C,KAAM,OACN,GAAIA,EAAG,GACP,KAAMA,EAAG,SAAS,KAClB,KAAMvB,EAAAA,iBAAiBuB,EAAG,SAAS,UAAW,CAAA,CAAE,EAChD,UAAWzC,EAAE,SAAA,EACZ,EACFJ,EAAQ,OAAOC,EAAG,EAAG,GAAG2C,CAAK,EAC7B3C,GAAK2C,EAAM,OAAS,CACrB,SAAUxC,EAAE,OAAS,QAAUA,EAAE,QAAS,CACzC,MAAM0C,EAAS9C,EAAQ,QAAWI,EAAE,cAAgB2C,EAAG,EAAE,EACtDD,IACC1C,EAAE,QAAQ,SAAS,UAAU,EAAG0C,EAAO,MAAQ1C,EAAE,QAC/C0C,EAAO,QAAU1C,EAAE,SAEzBJ,EAAQ,OAAOC,EAAG,CAAC,EACnBA,GACD,CACID,EAAQC,CAAC,GAAG,cAAmBA,CAAC,EAAE,UAAY,KAAK,IAAA,EACxD,CACA,OAAOD,CACR,CAEQ,aAAaA,EAA8B,CAClD,OAAOA,EAAQ,OAAO,CAAC4B,EAAQxB,IAAM,CACpC,GAAGA,EAAE,OAAS,OACbwB,EAAO,KAAK,CACX,KAAM,YACN,QAAS,KACT,WAAY,CAAC,CAAE,GAAIxB,EAAE,GAAI,KAAM,WAAY,SAAU,CAAE,KAAMA,EAAE,KAAM,UAAW,KAAK,UAAUA,EAAE,IAAI,CAAA,EAAK,EAC1G,QAAS,KACT,YAAa,CAAA,CAAC,EACZ,CACF,KAAM,OACN,aAAcA,EAAE,GAChB,QAASA,EAAE,OAASA,EAAE,OAAA,CACtB,MACK,CACN,KAAM,CAAC,UAAAC,EAAW,GAAGgC,CAAA,EAAQjC,EAC7BwB,EAAO,KAAKS,CAAI,CACjB,CACA,OAAOT,CACR,EAAG,CAAA,CAAW,CACf,CAEA,IAAItB,EAAiBC,EAAsB,GAAoC,CAC9E,MAAMC,EAAa,IAAI,gBACjBC,EAAW,IAAI,QAAa,MAAOC,EAAKC,IAAQ,CACrD,IAAIX,EAAU,KAAK,aAAa,CAAC,GAAGO,EAAQ,SAAW,GAAI,CAAC,KAAM,OAAQ,QAASD,EAAS,UAAW,KAAK,IAAA,CAAI,CAAE,CAAC,EAChHC,EAAQ,WAAUP,EAAU,MAAM,KAAK,GAAG,IAAI,SAAcA,EAASO,EAAQ,SAAS,IAAKA,EAAQ,SAAS,IAAKA,CAAO,GAE3H,MAAMK,EAAqB,CAC1B,MAAOL,EAAQ,OAAS,KAAK,MAC7B,SAAUP,EACV,OAAQ,CAAC,CAACO,EAAQ,OAClB,WAAYA,EAAQ,YAAc,KAAK,GAAG,QAAQ,YAAc,KAChE,YAAaA,EAAQ,aAAe,KAAK,GAAG,QAAQ,aAAe,GACnE,OAAQA,EAAQ,OAAS,KAAK,GAAG,QAAQ,OAAS,CAAA,GAAI,IAAIM,IAAM,CAC/D,KAAM,WACN,SAAU,CACT,KAAMA,EAAE,KACR,YAAaA,EAAE,YACf,WAAY,CACX,KAAM,SACN,WAAYA,EAAE,KAAOC,EAAAA,UAAUD,EAAE,KAAM,CAACE,EAAKC,KAAW,CAAC,GAAGA,EAAO,SAAU,MAAA,EAAW,EAAI,CAAA,EAC5F,SAAUH,EAAE,KAAO,OAAO,QAAQA,EAAE,IAAI,EAAE,OAAOA,GAAKA,EAAE,CAAC,EAAE,QAAQ,EAAE,IAAIA,GAAKA,EAAE,CAAC,CAAC,EAAI,CAAA,CAAC,CACxF,CACD,EACC,CAAA,EAGH,IAAII,EACJ,MAAMC,EAAsB,CAAA,EAC5B,EAAG,CAEF,GADAD,EAAO,MAAM,KAAK,OAAO,KAAK,YAAY,OAAOL,CAAa,EAC3DL,EAAQ,OAAQ,CACfW,EAAa,QAAQX,EAAQ,OAAO,CAAC,KAAM;AAAA;AAAA,EAAO,EACrDU,EAAK,QAAU,CAAC,CAAC,QAAS,CAAC,QAAS,GAAI,WAAY,CAAA,CAAC,EAAG,EACxD,gBAAiBE,KAASF,EAAM,CAC/B,GAAGT,EAAW,OAAO,QAAS,MAC3BW,EAAM,QAAQ,CAAC,EAAE,MAAM,UACzBF,EAAK,QAAQ,CAAC,EAAE,QAAQ,SAAWE,EAAM,QAAQ,CAAC,EAAE,MAAM,QAC1DZ,EAAQ,OAAO,CAAC,KAAMY,EAAM,QAAQ,CAAC,EAAE,MAAM,QAAQ,GAEnDA,EAAM,QAAQ,CAAC,EAAE,MAAM,aACzBF,EAAK,QAAQ,CAAC,EAAE,QAAQ,WAAaE,EAAM,QAAQ,CAAC,EAAE,MAAM,WAE9D,CACD,CAEAD,EAAa,KAAK,CAAC,KAAM,YAAa,QAASD,EAAK,QAAQ,CAAC,EAAE,QAAQ,SAAW,GAAI,UAAW,KAAK,IAAA,EAAM,EAE5G,MAAMM,EAAYN,EAAK,QAAQ,CAAC,EAAE,QAAQ,YAAc,CAAA,EACxD,GAAGM,EAAU,QAAU,CAACf,EAAW,OAAO,QAAS,CAClDR,EAAQ,KAAKiB,EAAK,QAAQ,CAAC,EAAE,OAAO,EACpC,MAAMsB,EAAU,MAAM,QAAQ,IAAIhB,EAAU,IAAI,MAAOE,GAAkB,CACxE,MAAMC,EAAOnB,EAAQ,OAAO,KAAKoB,aAAW,OAAQF,EAAS,SAAS,IAAI,CAAC,EAC3E,GAAG,CAACC,EAAM,MAAO,CAAC,KAAM,OAAQ,aAAcD,EAAS,GAAI,QAAS,6BAAA,EACpE,GAAI,CACH,MAAMe,EAAOlB,EAAAA,iBAAiBG,EAAS,SAAS,UAAW,CAAA,CAAE,EACvDG,EAAS,MAAMF,EAAK,GAAGc,EAAM,KAAK,EAAE,EAC1C,MAAO,CAAC,KAAM,OAAQ,aAAcf,EAAS,GAAI,QAASI,eAAaD,CAAM,CAAA,CAC9E,OAASE,EAAU,CAClB,MAAO,CAAC,KAAM,OAAQ,aAAcL,EAAS,GAAI,QAASI,EAAAA,aAAa,CAAC,MAAOC,GAAK,SAAWA,GAAK,YAAc,SAAA,CAAU,CAAA,CAC7H,CACD,CAAC,CAAC,EACF9B,EAAQ,KAAK,GAAGuC,CAAO,EACvBrB,EAAa,KAAK,GAAGqB,EAAQ,IAAIE,IAAM,CAAC,GAAGA,EAAG,UAAW,KAAK,IAAA,CAAI,EAAG,CAAC,EACtE7B,EAAc,SAAWZ,CAC1B,CACD,OAAS,CAACQ,EAAW,OAAO,SAAWS,EAAK,UAAU,CAAC,GAAG,SAAS,YAAY,QAE/E,MAAMc,EAAkBb,EAAa,UAAYc,EAAE,OAAS,WAAW,EACrE,IAAIA,GAAKA,EAAE,OAAO,EAAE,UAAY7B,CAAC,EAAE,KAAK;AAAA;AAAA,CAAM,EAC7CI,EAAQ,QAAQA,EAAQ,OAAO,CAAC,KAAM,GAAK,EAC9CG,EAAI,KAAK,WAAW,CAAC,GAAGV,EAAS,CAAC,KAAM,YAAa,QAAS+B,EAAiB,UAAW,KAAK,IAAA,CAAI,CAAE,CAAC,CAAC,CACxG,CAAC,EACD,OAAO,OAAO,OAAOtB,EAAU,CAAC,MAAO,IAAMD,EAAW,MAAA,EAAQ,CACjE,CACD,CCvDO,MAAMwC,CAAI,CAGhB,YAA4BpD,EAAwBW,EAAqB,CAA7C,KAAA,GAAAX,EAAwB,KAAA,QAAAW,EAChDA,EAAQ,WAAW,QAAO,KAAK,UAAU,UAAY,IAAIZ,EAAU,KAAK,GAAIY,EAAQ,UAAU,MAAOA,EAAQ,UAAU,KAAK,GAC5HA,EAAQ,QAAQ,OAAM,KAAK,UAAU,OAAS,IAAI0B,EAAO,KAAK,GAAI1B,EAAQ,OAAO,KAAMA,EAAQ,OAAO,KAAK,GAC3GA,EAAQ,QAAQ,QAAO,KAAK,UAAU,OAAS,IAAImC,EAAO,KAAK,GAAInC,EAAQ,OAAO,MAAOA,EAAQ,OAAO,KAAK,EACjH,CANQ,UAA0C,CAAA,EAclD,IAAID,EAAiBC,EAAsB,GAAoC,CAC9E,IAAIT,EAAa,CAAC,KAAM,IAAI,EAS5B,GARGS,EAAQ,QACP,OAAOA,EAAQ,OAAS,WAAkBA,EAAQ,MAChDT,EAAQ,CAACS,EAAQ,MAAa,KAAK,QAASA,EAAQ,KAAK,GAAG,KAAK,IAEpE,CAACA,EAAQ,OAAST,EAAM,CAAC,GAAK,QAC7B,OAAO,KAAK,QAAQ,OAAS,SAAUA,EAAQ,KAAK,QAAQ,MAC1DA,EAAQ,CAAC,KAAK,QAAQ,MAAa,KAAK,QAAS,KAAK,QAAQ,KAAK,GAAG,KAAK,GAE9E,CAACA,EAAM,CAAC,GAAK,CAACA,EAAM,CAAC,EAAG,MAAM,IAAI,MAAM,kCAAkCA,EAAM,CAAC,CAAC,MAAMA,EAAM,CAAC,CAAC,EAAE,EACrG,OAAO,KAAK,UAAUA,EAAM,CAAC,CAAC,EAAE,IAAIQ,EAAS,CAAC,GAAGC,EAAS,MAAOT,EAAM,CAAC,EAAE,CAC3E,CAUA,MAAM,SAASE,EAAuBiD,EAAaC,EAAa3C,EAA6C,CAC5G,GAAG,KAAK,eAAeP,CAAO,EAAIiD,EAAK,OAAOjD,EAC9C,IAAImD,EAAO,EAAGC,EAAS,EACvB,QAAQpB,KAAKhC,EAAQ,aAEpB,GADAoD,GAAU,KAAK,eAAepB,EAAE,OAAO,EACpCoB,EAASF,EAAKC,QACZ,OAEN,GAAGnD,EAAQ,QAAUmD,EAAM,OAAOnD,EAClC,MAAMqD,EAASF,GAAQ,EAAI,CAAA,EAAKnD,EAAQ,MAAM,CAACmD,CAAI,EAClDG,GAAWH,GAAQ,EAAInD,EAAUA,EAAQ,MAAM,EAAG,CAACmD,CAAI,GAAG,OAAO/C,GAAKA,EAAE,OAAS,aAAeA,EAAE,OAAS,MAAM,EAElH,MAAO,CAAC,CAAC,KAAM,YAAa,QAAS,yBADrB,MAAM,KAAK,UAAUkD,EAAQ,OAAS,GAAGtB,EAAE,IAAI,KAAKA,EAAE,OAAO,EAAE,EAAE,KAAK;AAAA;AAAA,CAAM,EAAG,IAAKzB,CAAO,CACtC,GAAI,UAAW,KAAK,IAAA,CAAI,EAAI,GAAG8C,CAAM,CAC3G,CAOA,eAAerD,EAAsB,CACpC,MAAMoB,EAAO,KAAK,UAAUpB,CAAO,EACnC,OAAO,KAAK,KAAMoB,EAAK,OAAS,EAAK,GAAG,CACzC,CAQA,MAAM,KAAKd,EAAiBC,EAAsB,CACjD,IAAIU,EAAO,MAAM,KAAK,IAAIX,EAAS,CAClC,OAAQ,4BACR,GAAGC,CAAA,CACH,EACD,OAAIU,IAAO,CAAC,GAAG,QACRK,mBAAiB,IAAI,OAAO,SAAa,EAAE,KAAKL,EAAK,CAAC,EAAE,OAAO,EAAG,EAAE,EAD5C,CAAA,CAEhC,CASA,UAAUG,EAAcgC,EAAgB7C,EAA8C,CACrF,OAAO,KAAK,IAAIa,EAAM,CAAC,OAAQ,+BAA+BgC,CAAM,+BAAgC,YAAa,GAAK,GAAG7C,CAAA,CAAQ,EAC/H,KAAKP,GAAmBA,EAAQ,IAAA,GAAO,SAAW,IAAI,CACzD,CACD,CCxJO,MAAMuD,CAAG,CAOf,YAA4BhD,EAAoB,CAApB,KAAA,QAAAA,EAC3B,KAAK,IAAM,IAAIyC,EAAI,KAAMzC,CAAO,EAC7B,KAAK,QAAQ,SAAS,SACxB,KAAK,aAAe,KAAK,QAAQ,SAAS,MAAM,SAAS,MAAM,EAAI,KAAK,QAAQ,SAAS,MAAQ,KAAK,QAAQ,SAAS,MAAQ,OAC/H,KAAK,iBAAA,EAEP,CAZQ,UAA8C,CAAA,EAC9C,aAGR,IAgBA,IAAIiD,EAAc1D,EAAgB,KAAK,aAAqE,CAC3G,GAAG,CAAC,KAAK,QAAQ,SAAS,OAAQ,MAAM,IAAI,MAAM,wBAAwB,EAC1E,IAAI2D,EAAa,IAAM,CAAC,EAcxB,MAAO,CAAC,SAbS,IAAI,QAAuB,CAACC,EAASC,IAAW,CAChE,KAAK,iBAAiB7D,CAAK,EAAE,KAAK,GAAK,CACtC,IAAI8D,EAAS,GACb,MAAMC,EAAOC,EAAAA,MAAc,KAAK,QAAQ,SAAS,OAAQ,CAAC,MAAO,MAAO,KAAM,EAAG,KAAMN,CAAI,EAAG,CAAC,MAAO,CAAC,SAAU,OAAQ,QAAQ,EAAE,EACnIC,EAAQ,IAAMI,EAAK,KAAK,SAAS,EACjCA,EAAK,GAAG,QAAU/B,GAAe6B,EAAO7B,CAAG,CAAC,EAC5C+B,EAAK,OAAO,GAAG,OAASE,GAAiBH,GAAUG,EAAK,UAAU,EAClEF,EAAK,GAAG,QAAUG,GAAiB,CAC/BA,IAAS,EAAGN,EAAQE,EAAO,KAAA,GAAU,IAAI,IAChC,IAAI,MAAM,aAAaI,CAAI,EAAE,CAAC,CAC3C,CAAC,CACF,CAAC,CACF,CAAC,EACiB,MAAAP,CAAA,CACnB,CAQA,MAAM,iBAAiB3D,EAAgB,KAAK,aAA+B,CAC1E,GAAG,CAAC,KAAK,QAAQ,SAAS,OAAQ,MAAM,IAAI,MAAM,wBAAwB,EACtEA,EAAM,SAAS,MAAM,IAAGA,GAAS,QACrC,MAAMmE,EAAIC,EAAK,KAAK,KAAK,QAAQ,QAAQ,KAAMpE,CAAK,EACpD,OAAG,MAAMqE,EAAG,KAAKF,CAAC,EAAE,KAAK,IAAM,EAAI,EAAE,MAAM,IAAM,EAAK,EAAUA,EAC3D,KAAK,UAAUnE,CAAK,EAAU,KAAK,UAAUA,CAAK,GACvD,KAAK,UAAUA,CAAK,EAAI,MAAM,6DAA6DA,CAAK,EAAE,EAChG,KAAKmB,GAAQA,EAAK,aAAa,EAC/B,KAAKmD,GAAO,OAAO,KAAKA,CAAG,CAAC,EAAE,KAAK,MAAMC,IACzC,MAAMF,EAAG,UAAUF,EAAGI,CAAM,EAC5B,OAAO,KAAK,UAAUvE,CAAK,EACpBmE,EACP,EACK,KAAK,UAAUnE,CAAK,EAC5B,CAOA,IAAI0D,EAAqE,CACxE,IAAIc,EACJ,MAAO,CACN,MAAO,IAAM,CAAEA,GAAQ,UAAA,CAAa,EACpC,SAAU,IAAI,QAAQ,MAAM5D,GAAO,CAClC4D,EAAS,MAAMC,EAAAA,aAAa,KAAK,EACjC,KAAM,CAAC,KAAAR,CAAA,EAAQ,MAAMO,EAAO,UAAUd,CAAI,EAC1C,MAAMc,EAAO,UAAA,EACb5D,EAAIqD,EAAK,KAAK,KAAA,GAAU,IAAI,CAC7B,CAAC,CAAA,CAEH,CAQA,mBAAmBS,KAAmBC,EAAuB,CAC5D,GAAGA,EAAY,OAAS,EAAG,MAAM,IAAI,MAAM,wCAAwC,EAEnF,MAAMC,EAAS,CAACtD,EAAcuD,EAAqB,KAC3CvD,EAAK,cAAc,MAAM,EAAE,EAAE,IAAI,CAACwD,EAAMC,IAC7CD,EAAK,WAAW,CAAC,GAAKC,EAAQ,GAAMF,EAAaA,CAAU,EAAE,MAAM,EAAGA,CAAU,EAG7EG,EAAmB,CAACC,EAAcC,IAAyB,CAChE,GAAID,EAAG,SAAWC,EAAG,OAAQ,MAAM,IAAI,MAAM,6BAA6B,EAC1E,MAAMC,EAAUC,EAAG,SAASH,CAAE,EAAGI,EAAUD,EAAG,SAASF,CAAE,EACnDI,EAAaF,EAAG,IAAID,EAASE,CAAO,EACpCE,EAAaH,EAAG,KAAKD,CAAO,EAC5BK,EAAaJ,EAAG,KAAKC,CAAO,EAClC,OAAGE,EAAW,WAAW,CAAC,IAAM,GAAKC,EAAW,WAAW,CAAC,IAAM,EAAU,EACrEF,EAAW,SAAA,EAAW,CAAC,GAAKC,EAAW,WAAW,CAAC,EAAIC,EAAW,SAAA,EAAW,CAAC,EACtF,EAEMC,EAAIb,EAAOF,CAAM,EACjBgB,EAAef,EAAY,IAAI5D,GAAK6D,EAAO7D,CAAC,CAAC,EAAE,IAAI4E,GAAaX,EAAiBS,EAAGE,CAAS,CAAC,EACpG,MAAO,CAAC,IAAKD,EAAa,OAAO,CAACE,EAAKC,IAAMD,EAAMC,EAAG,CAAC,EAAIH,EAAa,OAAQ,IAAK,KAAK,IAAI,GAAGA,CAAY,EAAG,aAAAA,CAAA,CACjH,CACD,CC1FO,MAAMI,EAAkB,CAC9B,KAAM,MACN,YAAa,qDACb,KAAM,CAAC,QAAS,CAAC,KAAM,SAAU,YAAa,iBAAkB,SAAU,GAAI,EAC9E,GAAKpD,GAA4BqD,EAAAA,IAAIrD,EAAK,OAAO,EAClD,EAEasD,EAAuB,CACnC,KAAM,eACN,YAAa,4BACb,KAAM,CAAA,EACN,GAAI,SAAY,IAAI,KAAA,EAAO,YAAA,CAC5B,EAEaC,EAAmB,CAC/B,KAAM,OACN,YAAa,mBACb,KAAM,CACL,SAAU,CAAC,KAAM,SAAU,YAAa,qBAAsB,KAAM,CAAC,MAAO,OAAQ,QAAQ,EAAG,SAAU,EAAA,EACzG,KAAM,CAAC,KAAM,SAAU,YAAa,kBAAmB,SAAU,EAAA,CAAI,EAEtE,GAAI,MAAOvD,EAAM5C,IAAO,CACvB,GAAI,CACH,OAAO4C,EAAK,KAAA,CACX,IAAK,OACJ,OAAO,MAAMoD,EAAQ,GAAG,CAAC,QAASpD,EAAK,IAAA,EAAO5C,CAAE,EACjD,IAAK,OACJ,OAAO,MAAMoG,EAAO,GAAG,CAAC,KAAMxD,EAAK,IAAA,EAAO5C,CAAE,EAC7C,IAAK,SACJ,OAAO,MAAMqG,EAAW,GAAG,CAAC,KAAMzD,EAAK,IAAA,EAAO5C,CAAE,CACjD,CAEF,OAAQkC,EAAU,CACjB,MAAO,CAAC,MAAOA,GAAK,SAAWA,EAAI,UAAS,CAC7C,CACD,CACD,EAEaoE,EAAoB,CAChC,KAAM,QACN,YAAa,2BACb,KAAM,CACL,IAAK,CAAC,KAAM,SAAU,YAAa,eAAgB,SAAU,EAAA,EAC7D,OAAQ,CAAC,KAAM,SAAU,YAAa,qBAAsB,KAAM,CAAC,MAAO,OAAQ,MAAO,QAAQ,EAAG,QAAS,KAAA,EAC7G,QAAS,CAAC,KAAM,SAAU,YAAa,uBAAwB,QAAS,EAAC,EACzE,KAAM,CAAC,KAAM,SAAU,YAAa,mBAAA,CAAmB,EAExD,GAAK1D,GAKC,IAAI2D,EAAAA,KAAK,CAAC,IAAK3D,EAAK,IAAK,QAASA,EAAK,QAAQ,EAAE,QAAQ,CAAC,OAAQA,EAAK,QAAU,MAAO,KAAMA,EAAK,IAAA,CAAK,CAC/G,EAEawD,EAAiB,CAC7B,KAAM,kBACN,YAAa,8BACb,KAAM,CACL,KAAM,CAAC,KAAM,SAAU,YAAa,sBAAuB,SAAU,EAAA,CAAI,EAE1E,GAAI,MAAOxD,GAAyB,CACnC,MAAM4D,EAAUC,EAAAA,mBAAmB,IAAI,EACjCpF,EAAO,MAAMqF,KAAQ,CAAC,QAAAF,CAAA,EAAU5D,EAAK,KAAM,EAAI,EAAE,MAAOV,GAAasE,EAAQ,OAAO,MAAM,KAAKtE,CAAG,CAAC,EACzG,MAAO,CAAC,GAAGsE,EAAQ,OAAQ,OAAQnF,EAAM,OAAQ,OAAW,OAAQ,MAAA,CACrE,CACD,EAEagF,EAAqB,CACjC,KAAM,kBACN,YAAa,8BACb,KAAM,CACL,KAAM,CAAC,KAAM,SAAU,YAAa,sBAAuB,SAAU,EAAA,CAAI,EAE1E,GAAI,MAAOzD,IAA0B,CAAC,OAAQ+D,EAAAA,mBAAmB/D,EAAK,IAAI,GAAA,EAC3E,EAEagE,EAAqB,CACjC,KAAM,SACN,YAAa,4FACb,KAAM,CACL,MAAO,CAAC,KAAM,SAAU,YAAa,gBAAiB,SAAU,EAAA,EAChE,OAAQ,CAAC,KAAM,SAAU,YAAa,8BAA+B,QAAS,CAAA,CAAC,EAEhF,GAAI,MAAOhE,GAGL,CACL,MAAMiE,EAAO,MAAM,MAAM,uCAAuC,mBAAmBjE,EAAK,KAAK,CAAC,GAAI,CACjG,QAAS,CAAC,aAAc,4CAA6C,kBAAmB,gBAAA,CAAgB,CACxG,EAAE,KAAKvB,GAAQA,EAAK,MAAM,EAC3B,IAAIyF,EAAOC,EAAQ,8BACnB,MAAMpE,EAAU,IAAIqE,OACpB,MAAOF,EAAQC,EAAM,KAAKF,CAAI,KAAO,MAAM,CAC1C,IAAII,EAAM,iBAAiB,KAAK,mBAAmBH,EAAM,CAAC,CAAC,CAAC,IAAI,CAAC,EAGjE,GAFGG,IAAKA,EAAM,mBAAmBA,CAAG,GACjCA,GAAKtE,EAAQ,IAAIsE,CAAG,EACpBtE,EAAQ,OAASC,EAAK,QAAU,GAAI,KACxC,CACA,OAAOD,CACR,CACD"}
|
package/dist/index.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { createWorker as
|
|
2
|
-
import { objectMap as k, JSONAttemptParse as b, findByProp as x, JSONSanitize as y, Http as
|
|
3
|
-
import { Anthropic as
|
|
4
|
-
import { Ollama as
|
|
1
|
+
import { createWorker as T } from "tesseract.js";
|
|
2
|
+
import { objectMap as k, JSONAttemptParse as b, findByProp as x, JSONSanitize as y, Http as q, consoleInterceptor as v, fn as P, ASet as A } from "@ztimson/utils";
|
|
3
|
+
import { Anthropic as E } from "@anthropic-ai/sdk";
|
|
4
|
+
import { Ollama as D } from "ollama";
|
|
5
5
|
import { OpenAI as M } from "openai";
|
|
6
6
|
import j from "node:fs/promises";
|
|
7
7
|
import O from "node:path";
|
|
@@ -12,7 +12,7 @@ class S {
|
|
|
12
12
|
}
|
|
13
13
|
class R extends S {
|
|
14
14
|
constructor(t, e, n) {
|
|
15
|
-
super(), this.ai = t, this.apiToken = e, this.model = n, this.client = new
|
|
15
|
+
super(), this.ai = t, this.apiToken = e, this.model = n, this.client = new E({ apiKey: e });
|
|
16
16
|
}
|
|
17
17
|
client;
|
|
18
18
|
toStandard(t) {
|
|
@@ -21,8 +21,8 @@ class R extends S {
|
|
|
21
21
|
typeof t[n].content != "string" && (t[n].role == "assistant" ? t[n].content.filter((o) => o.type == "tool_use").forEach((o) => {
|
|
22
22
|
e++, t.splice(e, 0, { role: "tool", id: o.id, name: o.name, args: o.input, timestamp: Date.now() });
|
|
23
23
|
}) : t[n].role == "user" && t[n].content.filter((o) => o.type == "tool_result").forEach((o) => {
|
|
24
|
-
const
|
|
25
|
-
|
|
24
|
+
const l = t.find((p) => p.id == o.tool_use_id);
|
|
25
|
+
l[o.is_error ? "error" : "content"] = o.content;
|
|
26
26
|
}), t[n].content = t[n].content.filter((o) => o.type == "text").map((o) => o.text).join(`
|
|
27
27
|
|
|
28
28
|
`)), t[n].timestamp || (t[n].timestamp = Date.now());
|
|
@@ -36,16 +36,16 @@ class R extends S {
|
|
|
36
36
|
t.splice(
|
|
37
37
|
e,
|
|
38
38
|
1,
|
|
39
|
-
{ role: "assistant", content: [{ type: "tool_use", id: n.id, name: n.name, input: n.args }]
|
|
40
|
-
{ role: "user", content: [{ type: "tool_result", tool_use_id: n.id, is_error: !!n.error, content: n.error || n.content }]
|
|
39
|
+
{ role: "assistant", content: [{ type: "tool_use", id: n.id, name: n.name, input: n.args }] },
|
|
40
|
+
{ role: "user", content: [{ type: "tool_result", tool_use_id: n.id, is_error: !!n.error, content: n.error || n.content }] }
|
|
41
41
|
), e++;
|
|
42
42
|
}
|
|
43
|
-
return t;
|
|
43
|
+
return t.map(({ timestamp: e, ...n }) => n);
|
|
44
44
|
}
|
|
45
45
|
ask(t, e = {}) {
|
|
46
|
-
const n = new AbortController(), o = new Promise(async (
|
|
47
|
-
let
|
|
48
|
-
e.compress && (
|
|
46
|
+
const n = new AbortController(), o = new Promise(async (l, p) => {
|
|
47
|
+
let m = this.fromStandard([...e.history || [], { role: "user", content: t, timestamp: Date.now() }]);
|
|
48
|
+
e.compress && (m = await this.ai.llm.compress(m, e.compress.max, e.compress.min, e));
|
|
49
49
|
const d = {
|
|
50
50
|
model: e.model || this.model,
|
|
51
51
|
max_tokens: e.max_tokens || this.ai.options.max_tokens || 4096,
|
|
@@ -56,42 +56,42 @@ class R extends S {
|
|
|
56
56
|
description: a.description,
|
|
57
57
|
input_schema: {
|
|
58
58
|
type: "object",
|
|
59
|
-
properties: a.args ? k(a.args, (s,
|
|
59
|
+
properties: a.args ? k(a.args, (s, i) => ({ ...i, required: void 0 })) : {},
|
|
60
60
|
required: a.args ? Object.entries(a.args).filter((s) => s[1].required).map((s) => s[0]) : []
|
|
61
61
|
},
|
|
62
62
|
fn: void 0
|
|
63
63
|
})),
|
|
64
|
-
messages:
|
|
64
|
+
messages: m,
|
|
65
65
|
stream: !!e.stream
|
|
66
66
|
};
|
|
67
|
-
let
|
|
67
|
+
let c;
|
|
68
68
|
const r = [];
|
|
69
69
|
do {
|
|
70
|
-
if (
|
|
70
|
+
if (c = await this.client.messages.create(d), e.stream) {
|
|
71
71
|
r.length && e.stream({ text: `
|
|
72
72
|
|
|
73
|
-
` }),
|
|
74
|
-
for await (const s of
|
|
73
|
+
` }), c.content = [];
|
|
74
|
+
for await (const s of c) {
|
|
75
75
|
if (n.signal.aborted) break;
|
|
76
76
|
if (s.type === "content_block_start")
|
|
77
|
-
s.content_block.type === "text" ?
|
|
77
|
+
s.content_block.type === "text" ? c.content.push({ type: "text", text: "" }) : s.content_block.type === "tool_use" && c.content.push({ type: "tool_use", id: s.content_block.id, name: s.content_block.name, input: "" });
|
|
78
78
|
else if (s.type === "content_block_delta")
|
|
79
79
|
if (s.delta.type === "text_delta") {
|
|
80
|
-
const
|
|
81
|
-
|
|
82
|
-
} else s.delta.type === "input_json_delta" && (
|
|
80
|
+
const i = s.delta.text;
|
|
81
|
+
c.content.at(-1).text += i, e.stream({ text: i });
|
|
82
|
+
} else s.delta.type === "input_json_delta" && (c.content.at(-1).input += s.delta.partial_json);
|
|
83
83
|
else if (s.type === "content_block_stop") {
|
|
84
|
-
const
|
|
85
|
-
|
|
84
|
+
const i = c.content.at(-1);
|
|
85
|
+
i.input != null && (i.input = i.input ? b(i.input, {}) : {});
|
|
86
86
|
} else if (s.type === "message_stop")
|
|
87
87
|
break;
|
|
88
88
|
}
|
|
89
89
|
}
|
|
90
|
-
r.push({ role: "assistant", content:
|
|
91
|
-
const a =
|
|
90
|
+
r.push({ role: "assistant", content: c.content, timestamp: Date.now() });
|
|
91
|
+
const a = c.content.filter((s) => s.type === "tool_use");
|
|
92
92
|
if (a.length && !n.signal.aborted) {
|
|
93
|
-
|
|
94
|
-
const
|
|
93
|
+
m.push({ role: "assistant", content: c.content });
|
|
94
|
+
const i = { role: "user", content: await Promise.all(a.map(async (f) => {
|
|
95
95
|
const h = e.tools?.find(x("name", f.name));
|
|
96
96
|
if (!h) return { tool_use_id: f.id, is_error: !0, content: "Tool not found" };
|
|
97
97
|
try {
|
|
@@ -100,23 +100,23 @@ class R extends S {
|
|
|
100
100
|
} catch (g) {
|
|
101
101
|
return { type: "tool_result", tool_use_id: f.id, is_error: !0, content: g?.message || g?.toString() || "Unknown" };
|
|
102
102
|
}
|
|
103
|
-
}))
|
|
104
|
-
|
|
103
|
+
})) };
|
|
104
|
+
m.push(i), r.push({ ...i, timestamp: Date.now() }), d.messages = m;
|
|
105
105
|
}
|
|
106
|
-
} while (!n.signal.aborted &&
|
|
106
|
+
} while (!n.signal.aborted && c.content.some((a) => a.type === "tool_use"));
|
|
107
107
|
const w = r.filter((a) => a.role === "assistant").map((a) => a.content.filter((s) => s.type == "text").map((s) => s.text).join(`
|
|
108
108
|
|
|
109
109
|
`)).filter((a) => a).join(`
|
|
110
110
|
|
|
111
111
|
`);
|
|
112
|
-
e.stream && e.stream({ done: !0 }),
|
|
112
|
+
e.stream && e.stream({ done: !0 }), l(this.toStandard([...m, { role: "assistant", content: w, timestamp: Date.now() }]));
|
|
113
113
|
});
|
|
114
114
|
return Object.assign(o, { abort: () => n.abort() });
|
|
115
115
|
}
|
|
116
116
|
}
|
|
117
117
|
class I extends S {
|
|
118
118
|
constructor(t, e, n) {
|
|
119
|
-
super(), this.ai = t, this.host = e, this.model = n, this.client = new
|
|
119
|
+
super(), this.ai = t, this.host = e, this.model = n, this.client = new D({ host: e });
|
|
120
120
|
}
|
|
121
121
|
client;
|
|
122
122
|
toStandard(t) {
|
|
@@ -132,13 +132,16 @@ class I extends S {
|
|
|
132
132
|
return t;
|
|
133
133
|
}
|
|
134
134
|
fromStandard(t) {
|
|
135
|
-
return t.map((e) =>
|
|
135
|
+
return t.map((e) => {
|
|
136
|
+
const { timestamp: n, ...o } = e;
|
|
137
|
+
return e.role != "tool" ? o : { role: "tool", tool_name: e.name, content: e.error || e.content };
|
|
138
|
+
});
|
|
136
139
|
}
|
|
137
140
|
ask(t, e = {}) {
|
|
138
|
-
const n = new AbortController(), o = new Promise(async (
|
|
139
|
-
let
|
|
140
|
-
d[0].roll == "system" && (
|
|
141
|
-
const
|
|
141
|
+
const n = new AbortController(), o = new Promise(async (l, p) => {
|
|
142
|
+
let m = e.system || this.ai.options.system, d = this.fromStandard([...e.history || [], { role: "user", content: t, timestamp: Date.now() }]);
|
|
143
|
+
d[0].roll == "system" && (m ? d.shift() : m = d.shift()), e.compress && (d = await this.ai.llm.compress(d, e.compress.max, e.compress.min)), e.system && d.unshift({ role: "system", content: m });
|
|
144
|
+
const c = {
|
|
142
145
|
model: e.model || this.model,
|
|
143
146
|
messages: d,
|
|
144
147
|
stream: !!e.stream,
|
|
@@ -154,8 +157,8 @@ class I extends S {
|
|
|
154
157
|
description: s.description,
|
|
155
158
|
parameters: {
|
|
156
159
|
type: "object",
|
|
157
|
-
properties: s.args ? k(s.args, (
|
|
158
|
-
required: s.args ? Object.entries(s.args).filter((
|
|
160
|
+
properties: s.args ? k(s.args, (i, f) => ({ ...f, required: void 0 })) : {},
|
|
161
|
+
required: s.args ? Object.entries(s.args).filter((i) => i[1].required).map((i) => i[0]) : []
|
|
159
162
|
}
|
|
160
163
|
}
|
|
161
164
|
}))
|
|
@@ -163,7 +166,7 @@ class I extends S {
|
|
|
163
166
|
let r;
|
|
164
167
|
const w = [];
|
|
165
168
|
do {
|
|
166
|
-
if (r = await this.client.chat(
|
|
169
|
+
if (r = await this.client.chat(c), e.stream) {
|
|
167
170
|
w.length && e.stream({ text: `
|
|
168
171
|
|
|
169
172
|
` }), r.message = { role: "assistant", content: "", tool_calls: [] };
|
|
@@ -171,25 +174,25 @@ class I extends S {
|
|
|
171
174
|
if (n.signal.aborted || (s.message?.content && (r.message.content += s.message.content, e.stream({ text: s.message.content })), s.message?.tool_calls && (r.message.tool_calls = s.message.tool_calls), s.done)) break;
|
|
172
175
|
}
|
|
173
176
|
if (w.push({ role: "assistant", content: r.message?.content, timestamp: Date.now() }), r.message?.tool_calls?.length && !n.signal.aborted) {
|
|
174
|
-
d.push(
|
|
175
|
-
const s = await Promise.all(r.message.tool_calls.map(async (
|
|
176
|
-
const f = (e.tools || this.ai.options.tools)?.find(x("name",
|
|
177
|
-
if (!f) return { role: "tool", tool_name:
|
|
178
|
-
const h = typeof
|
|
177
|
+
d.push(r.message);
|
|
178
|
+
const s = await Promise.all(r.message.tool_calls.map(async (i) => {
|
|
179
|
+
const f = (e.tools || this.ai.options.tools)?.find(x("name", i.function.name));
|
|
180
|
+
if (!f) return { role: "tool", tool_name: i.function.name, content: '{"error": "Tool not found"}' };
|
|
181
|
+
const h = typeof i.function.arguments == "string" ? b(i.function.arguments, {}) : i.function.arguments;
|
|
179
182
|
try {
|
|
180
183
|
const g = await f.fn(h, this.ai);
|
|
181
|
-
return { role: "tool", tool_name:
|
|
184
|
+
return { role: "tool", tool_name: i.function.name, args: h, content: y(g) };
|
|
182
185
|
} catch (g) {
|
|
183
|
-
return { role: "tool", tool_name:
|
|
186
|
+
return { role: "tool", tool_name: i.function.name, args: h, content: y({ error: g?.message || g?.toString() || "Unknown" }) };
|
|
184
187
|
}
|
|
185
188
|
}));
|
|
186
|
-
d.push(...s), w.push(...s),
|
|
189
|
+
d.push(...s), w.push(...s.map((i) => ({ ...i, timestamp: Date.now() }))), c.messages = d;
|
|
187
190
|
}
|
|
188
191
|
} while (!n.signal.aborted && r.message?.tool_calls?.length);
|
|
189
192
|
const a = w.filter((s) => s.role === "assistant").map((s) => s.content).filter((s) => s).join(`
|
|
190
193
|
|
|
191
194
|
`);
|
|
192
|
-
e.stream && e.stream({ done: !0 }),
|
|
195
|
+
e.stream && e.stream({ done: !0 }), l(this.toStandard([...d, { role: "assistant", content: a, timestamp: Date.now() }]));
|
|
193
196
|
});
|
|
194
197
|
return Object.assign(o, { abort: () => n.abort() });
|
|
195
198
|
}
|
|
@@ -203,16 +206,16 @@ class J extends S {
|
|
|
203
206
|
for (let e = 0; e < t.length; e++) {
|
|
204
207
|
const n = t[e];
|
|
205
208
|
if (n.role === "assistant" && n.tool_calls) {
|
|
206
|
-
const o = n.tool_calls.map((
|
|
209
|
+
const o = n.tool_calls.map((l) => ({
|
|
207
210
|
role: "tool",
|
|
208
|
-
id:
|
|
209
|
-
name:
|
|
210
|
-
args: b(
|
|
211
|
+
id: l.id,
|
|
212
|
+
name: l.function.name,
|
|
213
|
+
args: b(l.function.arguments, {}),
|
|
211
214
|
timestamp: n.timestamp
|
|
212
215
|
}));
|
|
213
216
|
t.splice(e, 1, ...o), e += o.length - 1;
|
|
214
217
|
} else if (n.role === "tool" && n.content) {
|
|
215
|
-
const o = t.find((
|
|
218
|
+
const o = t.find((l) => n.tool_call_id == l.id);
|
|
216
219
|
o && (n.content.includes('"error":') ? o.error = n.content : o.content = n.content), t.splice(e, 1), e--;
|
|
217
220
|
}
|
|
218
221
|
t[e]?.timestamp || (t[e].timestamp = Date.now());
|
|
@@ -220,27 +223,33 @@ class J extends S {
|
|
|
220
223
|
return t;
|
|
221
224
|
}
|
|
222
225
|
fromStandard(t) {
|
|
223
|
-
return t.reduce((e, n) =>
|
|
224
|
-
role
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
226
|
+
return t.reduce((e, n) => {
|
|
227
|
+
if (n.role === "tool")
|
|
228
|
+
e.push({
|
|
229
|
+
role: "assistant",
|
|
230
|
+
content: null,
|
|
231
|
+
tool_calls: [{ id: n.id, type: "function", function: { name: n.name, arguments: JSON.stringify(n.args) } }],
|
|
232
|
+
refusal: null,
|
|
233
|
+
annotations: []
|
|
234
|
+
}, {
|
|
235
|
+
role: "tool",
|
|
236
|
+
tool_call_id: n.id,
|
|
237
|
+
content: n.error || n.content
|
|
238
|
+
});
|
|
239
|
+
else {
|
|
240
|
+
const { timestamp: o, ...l } = n;
|
|
241
|
+
e.push(l);
|
|
242
|
+
}
|
|
243
|
+
return e;
|
|
244
|
+
}, []);
|
|
236
245
|
}
|
|
237
246
|
ask(t, e = {}) {
|
|
238
|
-
const n = new AbortController(), o = new Promise(async (
|
|
239
|
-
let
|
|
240
|
-
e.compress && (
|
|
247
|
+
const n = new AbortController(), o = new Promise(async (l, p) => {
|
|
248
|
+
let m = this.fromStandard([...e.history || [], { role: "user", content: t, timestamp: Date.now() }]);
|
|
249
|
+
e.compress && (m = await this.ai.llm.compress(m, e.compress.max, e.compress.min, e));
|
|
241
250
|
const d = {
|
|
242
251
|
model: e.model || this.model,
|
|
243
|
-
messages:
|
|
252
|
+
messages: m,
|
|
244
253
|
stream: !!e.stream,
|
|
245
254
|
max_tokens: e.max_tokens || this.ai.options.max_tokens || 4096,
|
|
246
255
|
temperature: e.temperature || this.ai.options.temperature || 0.7,
|
|
@@ -251,45 +260,45 @@ class J extends S {
|
|
|
251
260
|
description: a.description,
|
|
252
261
|
parameters: {
|
|
253
262
|
type: "object",
|
|
254
|
-
properties: a.args ? k(a.args, (s,
|
|
263
|
+
properties: a.args ? k(a.args, (s, i) => ({ ...i, required: void 0 })) : {},
|
|
255
264
|
required: a.args ? Object.entries(a.args).filter((s) => s[1].required).map((s) => s[0]) : []
|
|
256
265
|
}
|
|
257
266
|
}
|
|
258
267
|
}))
|
|
259
268
|
};
|
|
260
|
-
let
|
|
269
|
+
let c;
|
|
261
270
|
const r = [];
|
|
262
271
|
do {
|
|
263
|
-
if (
|
|
272
|
+
if (c = await this.client.chat.completions.create(d), e.stream) {
|
|
264
273
|
r.length && e.stream({ text: `
|
|
265
274
|
|
|
266
|
-
` }),
|
|
267
|
-
for await (const s of
|
|
275
|
+
` }), c.choices = [{ message: { content: "", tool_calls: [] } }];
|
|
276
|
+
for await (const s of c) {
|
|
268
277
|
if (n.signal.aborted) break;
|
|
269
|
-
s.choices[0].delta.content && (
|
|
278
|
+
s.choices[0].delta.content && (c.choices[0].message.content += s.choices[0].delta.content, e.stream({ text: s.choices[0].delta.content })), s.choices[0].delta.tool_calls && (c.choices[0].message.tool_calls = s.choices[0].delta.tool_calls);
|
|
270
279
|
}
|
|
271
280
|
}
|
|
272
|
-
r.push({ role: "assistant", content:
|
|
273
|
-
const a =
|
|
281
|
+
r.push({ role: "assistant", content: c.choices[0].message.content || "", timestamp: Date.now() });
|
|
282
|
+
const a = c.choices[0].message.tool_calls || [];
|
|
274
283
|
if (a.length && !n.signal.aborted) {
|
|
275
|
-
|
|
276
|
-
const s = await Promise.all(a.map(async (
|
|
277
|
-
const f = e.tools?.find(x("name",
|
|
278
|
-
if (!f) return { role: "tool", tool_call_id:
|
|
284
|
+
m.push(c.choices[0].message);
|
|
285
|
+
const s = await Promise.all(a.map(async (i) => {
|
|
286
|
+
const f = e.tools?.find(x("name", i.function.name));
|
|
287
|
+
if (!f) return { role: "tool", tool_call_id: i.id, content: '{"error": "Tool not found"}' };
|
|
279
288
|
try {
|
|
280
|
-
const h = b(
|
|
281
|
-
return { role: "tool", tool_call_id:
|
|
289
|
+
const h = b(i.function.arguments, {}), g = await f.fn(h, this.ai);
|
|
290
|
+
return { role: "tool", tool_call_id: i.id, content: y(g) };
|
|
282
291
|
} catch (h) {
|
|
283
|
-
return { role: "tool", tool_call_id:
|
|
292
|
+
return { role: "tool", tool_call_id: i.id, content: y({ error: h?.message || h?.toString() || "Unknown" }) };
|
|
284
293
|
}
|
|
285
294
|
}));
|
|
286
|
-
|
|
295
|
+
m.push(...s), r.push(...s.map((i) => ({ ...i, timestamp: Date.now() }))), d.messages = m;
|
|
287
296
|
}
|
|
288
|
-
} while (!n.signal.aborted &&
|
|
297
|
+
} while (!n.signal.aborted && c.choices?.[0]?.message?.tool_calls?.length);
|
|
289
298
|
const w = r.filter((a) => a.role === "assistant").map((a) => a.content).filter((a) => a).join(`
|
|
290
299
|
|
|
291
300
|
`);
|
|
292
|
-
e.stream && e.stream({ done: !0 }),
|
|
301
|
+
e.stream && e.stream({ done: !0 }), l(this.toStandard([...m, { role: "assistant", content: w, timestamp: Date.now() }]));
|
|
293
302
|
});
|
|
294
303
|
return Object.assign(o, { abort: () => n.abort() });
|
|
295
304
|
}
|
|
@@ -320,15 +329,15 @@ class W {
|
|
|
320
329
|
*/
|
|
321
330
|
async compress(t, e, n, o) {
|
|
322
331
|
if (this.estimateTokens(t) < e) return t;
|
|
323
|
-
let
|
|
332
|
+
let l = 0, p = 0;
|
|
324
333
|
for (let r of t.toReversed())
|
|
325
|
-
if (
|
|
334
|
+
if (p += this.estimateTokens(r.content), p < n) l++;
|
|
326
335
|
else break;
|
|
327
|
-
if (t.length <=
|
|
328
|
-
const
|
|
336
|
+
if (t.length <= l) return t;
|
|
337
|
+
const m = l == 0 ? [] : t.slice(-l), d = (l == 0 ? t : t.slice(0, -l)).filter((r) => r.role === "assistant" || r.role === "user");
|
|
329
338
|
return [{ role: "assistant", content: `Conversation Summary: ${await this.summarize(d.map((r) => `${r.role}: ${r.content}`).join(`
|
|
330
339
|
|
|
331
|
-
`), 250, o)}`, timestamp: Date.now() }, ...
|
|
340
|
+
`), 250, o)}`, timestamp: Date.now() }, ...m];
|
|
332
341
|
}
|
|
333
342
|
/**
|
|
334
343
|
* Estimate variable as tokens
|
|
@@ -381,12 +390,12 @@ class Z {
|
|
|
381
390
|
if (!this.options.whisper?.binary) throw new Error("Whisper not configured");
|
|
382
391
|
let n = () => {
|
|
383
392
|
};
|
|
384
|
-
return { response: new Promise((
|
|
385
|
-
this.downloadAsrModel(e).then((
|
|
393
|
+
return { response: new Promise((l, p) => {
|
|
394
|
+
this.downloadAsrModel(e).then((m) => {
|
|
386
395
|
let d = "";
|
|
387
|
-
const
|
|
388
|
-
n = () =>
|
|
389
|
-
r === 0 ?
|
|
396
|
+
const c = U(this.options.whisper?.binary, ["-nt", "-np", "-m", m, "-f", t], { stdio: ["ignore", "pipe", "ignore"] });
|
|
397
|
+
n = () => c.kill("SIGTERM"), c.on("error", (r) => p(r)), c.stdout.on("data", (r) => d += r.toString()), c.on("close", (r) => {
|
|
398
|
+
r === 0 ? l(d.trim() || null) : p(new Error(`Exit code ${r}`));
|
|
390
399
|
});
|
|
391
400
|
});
|
|
392
401
|
}), abort: n };
|
|
@@ -415,7 +424,7 @@ class Z {
|
|
|
415
424
|
e?.terminate();
|
|
416
425
|
},
|
|
417
426
|
response: new Promise(async (n) => {
|
|
418
|
-
e = await
|
|
427
|
+
e = await T("eng");
|
|
419
428
|
const { data: o } = await e.recognize(t);
|
|
420
429
|
await e.terminate(), n(o.text.trim() || null);
|
|
421
430
|
})
|
|
@@ -429,19 +438,19 @@ class Z {
|
|
|
429
438
|
*/
|
|
430
439
|
semanticSimilarity(t, ...e) {
|
|
431
440
|
if (e.length < 2) throw new Error("Requires at least 2 strings to compare");
|
|
432
|
-
const n = (
|
|
433
|
-
if (
|
|
434
|
-
const
|
|
441
|
+
const n = (m, d = 10) => m.toLowerCase().split("").map((c, r) => c.charCodeAt(0) * (r + 1) % d / d).slice(0, d), o = (m, d) => {
|
|
442
|
+
if (m.length !== d.length) throw new Error("Vectors must be same length");
|
|
443
|
+
const c = _.tensor1d(m), r = _.tensor1d(d), w = _.dot(c, r), a = _.norm(c), s = _.norm(r);
|
|
435
444
|
return a.dataSync()[0] === 0 || s.dataSync()[0] === 0 ? 0 : w.dataSync()[0] / (a.dataSync()[0] * s.dataSync()[0]);
|
|
436
|
-
},
|
|
437
|
-
return { avg:
|
|
445
|
+
}, l = n(t), p = e.map((m) => n(m)).map((m) => o(l, m));
|
|
446
|
+
return { avg: p.reduce((m, d) => m + d, 0) / p.length, max: Math.max(...p), similarities: p };
|
|
438
447
|
}
|
|
439
448
|
}
|
|
440
449
|
const N = {
|
|
441
450
|
name: "cli",
|
|
442
451
|
description: "Use the command line interface, returns any output",
|
|
443
452
|
args: { command: { type: "string", description: "Command to run", required: !0 } },
|
|
444
|
-
fn: (
|
|
453
|
+
fn: (u) => $`${u.command}`
|
|
445
454
|
}, ee = {
|
|
446
455
|
name: "get_datetime",
|
|
447
456
|
description: "Get current date and time",
|
|
@@ -454,15 +463,15 @@ const N = {
|
|
|
454
463
|
language: { type: "string", description: "Execution language", enum: ["cli", "node", "python"], required: !0 },
|
|
455
464
|
code: { type: "string", description: "Code to execute", required: !0 }
|
|
456
465
|
},
|
|
457
|
-
fn: async (
|
|
466
|
+
fn: async (u, t) => {
|
|
458
467
|
try {
|
|
459
|
-
switch (
|
|
468
|
+
switch (u.type) {
|
|
460
469
|
case "bash":
|
|
461
|
-
return await N.fn({ command:
|
|
470
|
+
return await N.fn({ command: u.code }, t);
|
|
462
471
|
case "node":
|
|
463
|
-
return await z.fn({ code:
|
|
472
|
+
return await z.fn({ code: u.code }, t);
|
|
464
473
|
case "python":
|
|
465
|
-
return await G.fn({ code:
|
|
474
|
+
return await G.fn({ code: u.code }, t);
|
|
466
475
|
}
|
|
467
476
|
} catch (e) {
|
|
468
477
|
return { error: e?.message || e.toString() };
|
|
@@ -477,15 +486,15 @@ const N = {
|
|
|
477
486
|
headers: { type: "object", description: "HTTP headers to send", default: {} },
|
|
478
487
|
body: { type: "object", description: "HTTP body to send" }
|
|
479
488
|
},
|
|
480
|
-
fn: (
|
|
489
|
+
fn: (u) => new q({ url: u.url, headers: u.headers }).request({ method: u.method || "GET", body: u.body })
|
|
481
490
|
}, z = {
|
|
482
491
|
name: "exec_javascript",
|
|
483
492
|
description: "Execute commonjs javascript",
|
|
484
493
|
args: {
|
|
485
494
|
code: { type: "string", description: "CommonJS javascript", required: !0 }
|
|
486
495
|
},
|
|
487
|
-
fn: async (
|
|
488
|
-
const t =
|
|
496
|
+
fn: async (u) => {
|
|
497
|
+
const t = v(null), e = await P({ console: t }, u.code, !0).catch((n) => t.output.error.push(n));
|
|
489
498
|
return { ...t.output, return: e, stdout: void 0, stderr: void 0 };
|
|
490
499
|
}
|
|
491
500
|
}, G = {
|
|
@@ -494,7 +503,7 @@ const N = {
|
|
|
494
503
|
args: {
|
|
495
504
|
code: { type: "string", description: "CommonJS javascript", required: !0 }
|
|
496
505
|
},
|
|
497
|
-
fn: async (
|
|
506
|
+
fn: async (u) => ({ result: L`python -c "${u.code}"` })
|
|
498
507
|
}, se = {
|
|
499
508
|
name: "search",
|
|
500
509
|
description: "Use a search engine to find relevant URLs, should be changed with fetch to scrape sources",
|
|
@@ -502,15 +511,15 @@ const N = {
|
|
|
502
511
|
query: { type: "string", description: "Search string", required: !0 },
|
|
503
512
|
length: { type: "string", description: "Number of results to return", default: 5 }
|
|
504
513
|
},
|
|
505
|
-
fn: async (
|
|
506
|
-
const t = await fetch(`https://html.duckduckgo.com/html/?q=${encodeURIComponent(
|
|
514
|
+
fn: async (u) => {
|
|
515
|
+
const t = await fetch(`https://html.duckduckgo.com/html/?q=${encodeURIComponent(u.query)}`, {
|
|
507
516
|
headers: { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64)", "Accept-Language": "en-US,en;q=0.9" }
|
|
508
|
-
}).then((
|
|
517
|
+
}).then((l) => l.text());
|
|
509
518
|
let e, n = /<a .*?href="(.+?)".+?<\/a>/g;
|
|
510
|
-
const o = new
|
|
519
|
+
const o = new A();
|
|
511
520
|
for (; (e = n.exec(t)) !== null; ) {
|
|
512
|
-
let
|
|
513
|
-
if (
|
|
521
|
+
let l = /uddg=(.+)&?/.exec(decodeURIComponent(e[1]))?.[1];
|
|
522
|
+
if (l && (l = decodeURIComponent(l)), l && o.add(l), o.size >= (u.length || 5)) break;
|
|
514
523
|
}
|
|
515
524
|
return o;
|
|
516
525
|
}
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","sources":["../src/provider.ts","../src/antrhopic.ts","../src/ollama.ts","../src/open-ai.ts","../src/llm.ts","../src/ai.ts","../src/tools.ts"],"sourcesContent":["import {LLMMessage, LLMOptions, LLMRequest} from './llm.ts';\n\nexport type AbortablePromise<T> = Promise<T> & {abort: () => void};\n\nexport abstract class LLMProvider {\n\tabstract ask(message: string, options: LLMRequest): AbortablePromise<LLMMessage[]>;\n}\n","import {Anthropic as anthropic} from '@anthropic-ai/sdk';\nimport {findByProp, objectMap, JSONSanitize, JSONAttemptParse} from '@ztimson/utils';\nimport {Ai} from './ai.ts';\nimport {LLMMessage, LLMRequest} from './llm.ts';\nimport {AbortablePromise, LLMProvider} from './provider.ts';\n\nexport class Anthropic extends LLMProvider {\n\tclient!: anthropic;\n\n\tconstructor(public readonly ai: Ai, public readonly apiToken: string, public model: string) {\n\t\tsuper();\n\t\tthis.client = new anthropic({apiKey: apiToken});\n\t}\n\n\tprivate toStandard(history: any[]): LLMMessage[] {\n\t\tfor(let i = 0; i < history.length; i++) {\n\t\t\tconst orgI = i;\n\t\t\tif(typeof history[orgI].content != 'string') {\n\t\t\t\tif(history[orgI].role == 'assistant') {\n\t\t\t\t\thistory[orgI].content.filter((c: any) => c.type =='tool_use').forEach((c: any) => {\n\t\t\t\t\t\ti++;\n\t\t\t\t\t\thistory.splice(i, 0, {role: 'tool', id: c.id, name: c.name, args: c.input, timestamp: Date.now()});\n\t\t\t\t\t});\n\t\t\t\t} else if(history[orgI].role == 'user') {\n\t\t\t\t\thistory[orgI].content.filter((c: any) => c.type =='tool_result').forEach((c: any) => {\n\t\t\t\t\t\tconst h = history.find((h: any) => h.id == c.tool_use_id);\n\t\t\t\t\t\th[c.is_error ? 'error' : 'content'] = c.content;\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\thistory[orgI].content = history[orgI].content.filter((c: any) => c.type == 'text').map((c: any) => c.text).join('\\n\\n');\n\t\t\t}\n\t\t\tif(!history[orgI].timestamp) history[orgI].timestamp = Date.now();\n\t\t}\n\t\treturn history.filter(h => !!h.content);\n\t}\n\n\tprivate fromStandard(history: LLMMessage[]): any[] {\n\t\tfor(let i = 0; i < history.length; i++) {\n\t\t\tif(history[i].role == 'tool') {\n\t\t\t\tconst h: any = history[i];\n\t\t\t\thistory.splice(i, 1,\n\t\t\t\t\t{role: 'assistant', content: [{type: 'tool_use', id: h.id, name: h.name, input: h.args}], timestamp: h.timestamp},\n\t\t\t\t\t{role: 'user', content: [{type: 'tool_result', tool_use_id: h.id, is_error: !!h.error, content: h.error || h.content}], timestamp: Date.now()}\n\t\t\t\t)\n\t\t\t\ti++;\n\t\t\t}\n\t\t}\n\t\treturn history;\n\t}\n\n\task(message: string, options: LLMRequest = {}): AbortablePromise<LLMMessage[]> {\n\t\tconst controller = new AbortController();\n\t\tconst response = new Promise<any>(async (res, rej) => {\n\t\t\tlet history = this.fromStandard([...options.history || [], {role: 'user', content: message, timestamp: Date.now()}]);\n\t\t\tif(options.compress) history = await this.ai.llm.compress(<any>history, options.compress.max, options.compress.min, options);\n\t\t\tconst requestParams: any = {\n\t\t\t\tmodel: options.model || this.model,\n\t\t\t\tmax_tokens: options.max_tokens || this.ai.options.max_tokens || 4096,\n\t\t\t\tsystem: options.system || this.ai.options.system || '',\n\t\t\t\ttemperature: options.temperature || this.ai.options.temperature || 0.7,\n\t\t\t\ttools: (options.tools || this.ai.options.tools || []).map(t => ({\n\t\t\t\t\tname: t.name,\n\t\t\t\t\tdescription: t.description,\n\t\t\t\t\tinput_schema: {\n\t\t\t\t\t\ttype: 'object',\n\t\t\t\t\t\tproperties: t.args ? objectMap(t.args, (key, value) => ({...value, required: undefined})) : {},\n\t\t\t\t\t\trequired: t.args ? Object.entries(t.args).filter(t => t[1].required).map(t => t[0]) : []\n\t\t\t\t\t},\n\t\t\t\t\tfn: undefined\n\t\t\t\t})),\n\t\t\t\tmessages: history,\n\t\t\t\tstream: !!options.stream,\n\t\t\t};\n\n\t\t\tlet resp: any;\n\t\t\tconst loopMessages: any[] = [];\n\t\t\tdo {\n\t\t\t\tresp = await this.client.messages.create(requestParams);\n\t\t\t\tif(options.stream) {\n\t\t\t\t\tif(loopMessages.length) options.stream({text: '\\n\\n'});\n\t\t\t\t\tresp.content = [];\n\t\t\t\t\tfor await (const chunk of resp) {\n\t\t\t\t\t\tif(controller.signal.aborted) break;\n\t\t\t\t\t\tif(chunk.type === 'content_block_start') {\n\t\t\t\t\t\t\tif(chunk.content_block.type === 'text') {\n\t\t\t\t\t\t\t\tresp.content.push({type: 'text', text: ''});\n\t\t\t\t\t\t\t} else if(chunk.content_block.type === 'tool_use') {\n\t\t\t\t\t\t\t\tresp.content.push({type: 'tool_use', id: chunk.content_block.id, name: chunk.content_block.name, input: <any>''});\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else if(chunk.type === 'content_block_delta') {\n\t\t\t\t\t\t\tif(chunk.delta.type === 'text_delta') {\n\t\t\t\t\t\t\t\tconst text = chunk.delta.text;\n\t\t\t\t\t\t\t\tresp.content.at(-1).text += text;\n\t\t\t\t\t\t\t\toptions.stream({text});\n\t\t\t\t\t\t\t} else if(chunk.delta.type === 'input_json_delta') {\n\t\t\t\t\t\t\t\tresp.content.at(-1).input += chunk.delta.partial_json;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else if(chunk.type === 'content_block_stop') {\n\t\t\t\t\t\t\tconst last = resp.content.at(-1);\n\t\t\t\t\t\t\tif(last.input != null) last.input = last.input ? JSONAttemptParse(last.input, {}) : {};\n\t\t\t\t\t\t} else if(chunk.type === 'message_stop') {\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tloopMessages.push({role: 'assistant', content: resp.content, timestamp: Date.now()});\n\t\t\t\tconst toolCalls = resp.content.filter((c: any) => c.type === 'tool_use');\n\t\t\t\tif(toolCalls.length && !controller.signal.aborted) {\n\t\t\t\t\thistory.push({role: 'assistant', content: resp.content, timestamp: Date.now()});\n\t\t\t\t\tconst results = await Promise.all(toolCalls.map(async (toolCall: any) => {\n\t\t\t\t\t\tconst tool = options.tools?.find(findByProp('name', toolCall.name));\n\t\t\t\t\t\tif(!tool) return {tool_use_id: toolCall.id, is_error: true, content: 'Tool not found'};\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tconst result = await tool.fn(toolCall.input, this.ai);\n\t\t\t\t\t\t\treturn {type: 'tool_result', tool_use_id: toolCall.id, content: JSONSanitize(result)};\n\t\t\t\t\t\t} catch (err: any) {\n\t\t\t\t\t\t\treturn {type: 'tool_result', tool_use_id: toolCall.id, is_error: true, content: err?.message || err?.toString() || 'Unknown'};\n\t\t\t\t\t\t}\n\t\t\t\t\t}));\n\t\t\t\t\tconst userMsg = {role: 'user', content: results, timestamp: Date.now()};\n\t\t\t\t\thistory.push(userMsg);\n\t\t\t\t\tloopMessages.push(userMsg);\n\t\t\t\t\trequestParams.messages = history;\n\t\t\t\t}\n\t\t\t} while (!controller.signal.aborted && resp.content.some((c: any) => c.type === 'tool_use'));\n\n\t\t\tconst combinedContent = loopMessages.filter(m => m.role === 'assistant')\n\t\t\t\t.map(m => m.content.filter((c: any) => c.type == 'text').map((c: any) => c.text).join('\\n\\n'))\n\t\t\t\t.filter(c => c).join('\\n\\n');\n\t\t\tif(options.stream) options.stream({done: true});\n\t\t\tres(this.toStandard([...history, {role: 'assistant', content: combinedContent, timestamp: Date.now()}]));\n\t\t});\n\n\t\treturn Object.assign(response, {abort: () => controller.abort()});\n\t}\n}\n","import {findByProp, objectMap, JSONSanitize, JSONAttemptParse} from '@ztimson/utils';\nimport {Ai} from './ai.ts';\nimport {LLMMessage, LLMRequest} from './llm.ts';\nimport {AbortablePromise, LLMProvider} from './provider.ts';\nimport {Ollama as ollama} from 'ollama';\n\nexport class Ollama extends LLMProvider {\n\tclient!: ollama;\n\n\tconstructor(public readonly ai: Ai, public host: string, public model: string) {\n\t\tsuper();\n\t\tthis.client = new ollama({host});\n\t}\n\n\tprivate toStandard(history: any[]): LLMMessage[] {\n\t\tfor(let i = 0; i < history.length; i++) {\n\t\t\tif(history[i].role == 'assistant' && history[i].tool_calls) {\n\t\t\t\tif(history[i].content) delete history[i].tool_calls;\n\t\t\t\telse {\n\t\t\t\t\thistory.splice(i, 1);\n\t\t\t\t\ti--;\n\t\t\t\t}\n\t\t\t} else if(history[i].role == 'tool') {\n\t\t\t\tconst error = history[i].content.startsWith('{\"error\":');\n\t\t\t\thistory[i] = {role: 'tool', name: history[i].tool_name, args: history[i].args, [error ? 'error' : 'content']: history[i].content, timestamp: history[i].timestamp};\n\t\t\t}\n\t\t\tif(!history[i]?.timestamp) history[i].timestamp = Date.now();\n\t\t}\n\t\treturn history;\n\t}\n\n\tprivate fromStandard(history: LLMMessage[]): any[] {\n\t\treturn history.map((h: any) => {\n\t\t\tif(h.role != 'tool') return h;\n\t\t\treturn {role: 'tool', tool_name: h.name, content: h.error || h.content, timestamp: h.timestamp}\n\t\t});\n\t}\n\n\task(message: string, options: LLMRequest = {}): AbortablePromise<LLMMessage[]> {\n\t\tconst controller = new AbortController();\n\t\tconst response = new Promise<any>(async (res, rej) => {\n\t\t\tlet system = options.system || this.ai.options.system;\n\t\t\tlet history = this.fromStandard([...options.history || [], {role: 'user', content: message, timestamp: Date.now()}]);\n\t\t\tif(history[0].roll == 'system') {\n\t\t\t\tif(!system) system = history.shift();\n\t\t\t\telse history.shift();\n\t\t\t}\n\t\t\tif(options.compress) history = await this.ai.llm.compress(<any>history, options.compress.max, options.compress.min);\n\t\t\tif(options.system) history.unshift({role: 'system', content: system})\n\n\t\t\tconst requestParams: any = {\n\t\t\t\tmodel: options.model || this.model,\n\t\t\t\tmessages: history,\n\t\t\t\tstream: !!options.stream,\n\t\t\t\tsignal: controller.signal,\n\t\t\t\toptions: {\n\t\t\t\t\ttemperature: options.temperature || this.ai.options.temperature || 0.7,\n\t\t\t\t\tnum_predict: options.max_tokens || this.ai.options.max_tokens || 4096,\n\t\t\t\t},\n\t\t\t\ttools: (options.tools || this.ai.options.tools || []).map(t => ({\n\t\t\t\t\ttype: 'function',\n\t\t\t\t\tfunction: {\n\t\t\t\t\t\tname: t.name,\n\t\t\t\t\t\tdescription: t.description,\n\t\t\t\t\t\tparameters: {\n\t\t\t\t\t\t\ttype: 'object',\n\t\t\t\t\t\t\tproperties: t.args ? objectMap(t.args, (key, value) => ({...value, required: undefined})) : {},\n\t\t\t\t\t\t\trequired: t.args ? Object.entries(t.args).filter(t => t[1].required).map(t => t[0]) : []\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}))\n\t\t\t}\n\n\t\t\tlet resp: any;\n\t\t\tconst loopMessages: any[] = [];\n\t\t\tdo {\n\t\t\t\tresp = await this.client.chat(requestParams);\n\t\t\t\tif(options.stream) {\n\t\t\t\t\tif(loopMessages.length) options.stream({text: '\\n\\n'});\n\t\t\t\t\tresp.message = {role: 'assistant', content: '', tool_calls: []};\n\t\t\t\t\tfor await (const chunk of resp) {\n\t\t\t\t\t\tif(controller.signal.aborted) break;\n\t\t\t\t\t\tif(chunk.message?.content) {\n\t\t\t\t\t\t\tresp.message.content += chunk.message.content;\n\t\t\t\t\t\t\toptions.stream({text: chunk.message.content});\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif(chunk.message?.tool_calls) resp.message.tool_calls = chunk.message.tool_calls;\n\t\t\t\t\t\tif(chunk.done) break;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tloopMessages.push({role: 'assistant', content: resp.message?.content, timestamp: Date.now()});\n\n\t\t\t\tif(resp.message?.tool_calls?.length && !controller.signal.aborted) {\n\t\t\t\t\thistory.push({...resp.message, timestamp: Date.now()});\n\t\t\t\t\tconst results = await Promise.all(resp.message.tool_calls.map(async (toolCall: any) => {\n\t\t\t\t\t\tconst tool = (options.tools || this.ai.options.tools)?.find(findByProp('name', toolCall.function.name));\n\t\t\t\t\t\tif(!tool) return {role: 'tool', tool_name: toolCall.function.name, content: '{\"error\": \"Tool not found\"}', timestamp: Date.now()};\n\t\t\t\t\t\tconst args = typeof toolCall.function.arguments === 'string' ? JSONAttemptParse(toolCall.function.arguments, {}) : toolCall.function.arguments;\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tconst result = await tool.fn(args, this.ai);\n\t\t\t\t\t\t\treturn {role: 'tool', tool_name: toolCall.function.name, args, content: JSONSanitize(result), timestamp: Date.now()};\n\t\t\t\t\t\t} catch (err: any) {\n\t\t\t\t\t\t\treturn {role: 'tool', tool_name: toolCall.function.name, args, content: JSONSanitize({error: err?.message || err?.toString() || 'Unknown'}), timestamp: Date.now()};\n\t\t\t\t\t\t}\n\t\t\t\t\t}));\n\t\t\t\t\thistory.push(...results);\n\t\t\t\t\tloopMessages.push(...results);\n\t\t\t\t\trequestParams.messages = history;\n\t\t\t\t}\n\t\t\t} while (!controller.signal.aborted && resp.message?.tool_calls?.length);\n\n\t\t\tconst combinedContent = loopMessages.filter(m => m.role === 'assistant')\n\t\t\t\t.map(m => m.content).filter(c => c).join('\\n\\n');\n\t\t\tif(options.stream) options.stream({done: true});\n\t\t\tres(this.toStandard([...history, {role: 'assistant', content: combinedContent, timestamp: Date.now()}]));\n\t\t});\n\n\t\treturn Object.assign(response, {abort: () => controller.abort()});\n\t}\n}\n","import {OpenAI as openAI} from 'openai';\nimport {findByProp, objectMap, JSONSanitize, JSONAttemptParse} from '@ztimson/utils';\nimport {Ai} from './ai.ts';\nimport {LLMMessage, LLMRequest} from './llm.ts';\nimport {AbortablePromise, LLMProvider} from './provider.ts';\n\nexport class OpenAi extends LLMProvider {\n\tclient!: openAI;\n\n\tconstructor(public readonly ai: Ai, public readonly apiToken: string, public model: string) {\n\t\tsuper();\n\t\tthis.client = new openAI({apiKey: apiToken});\n\t}\n\n\tprivate toStandard(history: any[]): LLMMessage[] {\n\t\tfor(let i = 0; i < history.length; i++) {\n\t\t\tconst h = history[i];\n\t\t\tif(h.role === 'assistant' && h.tool_calls) {\n\t\t\t\tconst tools = h.tool_calls.map((tc: any) => ({\n\t\t\t\t\trole: 'tool',\n\t\t\t\t\tid: tc.id,\n\t\t\t\t\tname: tc.function.name,\n\t\t\t\t\targs: JSONAttemptParse(tc.function.arguments, {}),\n\t\t\t\t\ttimestamp: h.timestamp\n\t\t\t\t}));\n\t\t\t\thistory.splice(i, 1, ...tools);\n\t\t\t\ti += tools.length - 1;\n\t\t\t} else if(h.role === 'tool' && h.content) {\n\t\t\t\tconst record = history.find(h2 => h.tool_call_id == h2.id);\n\t\t\t\tif(record) {\n\t\t\t\t\tif(h.content.includes('\"error\":')) record.error = h.content;\n\t\t\t\t\telse record.content = h.content;\n\t\t\t\t}\n\t\t\t\thistory.splice(i, 1);\n\t\t\t\ti--;\n\t\t\t}\n\t\t\tif(!history[i]?.timestamp) history[i].timestamp = Date.now();\n\t\t}\n\t\treturn history;\n\t}\n\n\tprivate fromStandard(history: LLMMessage[]): any[] {\n\t\treturn history.reduce((result, h) => {\n\t\t\tif(h.role === 'tool') {\n\t\t\t\tresult.push({\n\t\t\t\t\trole: 'assistant',\n\t\t\t\t\tcontent: null,\n\t\t\t\t\ttool_calls: [{ id: h.id, type: 'function', function: { name: h.name, arguments: JSON.stringify(h.args) } }],\n\t\t\t\t\trefusal: null,\n\t\t\t\t\tannotations: [],\n\t\t\t\t\ttimestamp: h.timestamp\n\t\t\t\t}, {\n\t\t\t\t\trole: 'tool',\n\t\t\t\t\ttool_call_id: h.id,\n\t\t\t\t\tcontent: h.error || h.content,\n\t\t\t\t\ttimestamp: Date.now()\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\tresult.push(h);\n\t\t\t}\n\t\t\treturn result;\n\t\t}, [] as any[]);\n\t}\n\n\task(message: string, options: LLMRequest = {}): AbortablePromise<LLMMessage[]> {\n\t\tconst controller = new AbortController();\n\t\tconst response = new Promise<any>(async (res, rej) => {\n\t\t\tlet history = this.fromStandard([...options.history || [], {role: 'user', content: message, timestamp: Date.now()}]);\n\t\t\tif(options.compress) history = await this.ai.llm.compress(<any>history, options.compress.max, options.compress.min, options);\n\n\t\t\tconst requestParams: any = {\n\t\t\t\tmodel: options.model || this.model,\n\t\t\t\tmessages: history,\n\t\t\t\tstream: !!options.stream,\n\t\t\t\tmax_tokens: options.max_tokens || this.ai.options.max_tokens || 4096,\n\t\t\t\ttemperature: options.temperature || this.ai.options.temperature || 0.7,\n\t\t\t\ttools: (options.tools || this.ai.options.tools || []).map(t => ({\n\t\t\t\t\ttype: 'function',\n\t\t\t\t\tfunction: {\n\t\t\t\t\t\tname: t.name,\n\t\t\t\t\t\tdescription: t.description,\n\t\t\t\t\t\tparameters: {\n\t\t\t\t\t\t\ttype: 'object',\n\t\t\t\t\t\t\tproperties: t.args ? objectMap(t.args, (key, value) => ({...value, required: undefined})) : {},\n\t\t\t\t\t\t\trequired: t.args ? Object.entries(t.args).filter(t => t[1].required).map(t => t[0]) : []\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}))\n\t\t\t};\n\n\t\t\tlet resp: any;\n\t\t\tconst loopMessages: any[] = [];\n\t\t\tdo {\n\t\t\t\tresp = await this.client.chat.completions.create(requestParams);\n\t\t\t\tif(options.stream) {\n\t\t\t\t\tif(loopMessages.length) options.stream({text: '\\n\\n'});\n\t\t\t\t\tresp.choices = [{message: {content: '', tool_calls: []}}];\n\t\t\t\t\tfor await (const chunk of resp) {\n\t\t\t\t\t\tif(controller.signal.aborted) break;\n\t\t\t\t\t\tif(chunk.choices[0].delta.content) {\n\t\t\t\t\t\t\tresp.choices[0].message.content += chunk.choices[0].delta.content;\n\t\t\t\t\t\t\toptions.stream({text: chunk.choices[0].delta.content});\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif(chunk.choices[0].delta.tool_calls) {\n\t\t\t\t\t\t\tresp.choices[0].message.tool_calls = chunk.choices[0].delta.tool_calls;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tloopMessages.push({role: 'assistant', content: resp.choices[0].message.content || '', timestamp: Date.now()});\n\n\t\t\t\tconst toolCalls = resp.choices[0].message.tool_calls || [];\n\t\t\t\tif(toolCalls.length && !controller.signal.aborted) {\n\t\t\t\t\thistory.push({...resp.choices[0].message, timestamp: Date.now()});\n\t\t\t\t\tconst results = await Promise.all(toolCalls.map(async (toolCall: any) => {\n\t\t\t\t\t\tconst tool = options.tools?.find(findByProp('name', toolCall.function.name));\n\t\t\t\t\t\tif(!tool) return {role: 'tool', tool_call_id: toolCall.id, content: '{\"error\": \"Tool not found\"}', timestamp: Date.now()};\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tconst args = JSONAttemptParse(toolCall.function.arguments, {});\n\t\t\t\t\t\t\tconst result = await tool.fn(args, this.ai);\n\t\t\t\t\t\t\treturn {role: 'tool', tool_call_id: toolCall.id, content: JSONSanitize(result), timestamp: Date.now()};\n\t\t\t\t\t\t} catch (err: any) {\n\t\t\t\t\t\t\treturn {role: 'tool', tool_call_id: toolCall.id, content: JSONSanitize({error: err?.message || err?.toString() || 'Unknown'}), timestamp: Date.now()};\n\t\t\t\t\t\t}\n\t\t\t\t\t}));\n\t\t\t\t\thistory.push(...results);\n\t\t\t\t\tloopMessages.push(...results);\n\t\t\t\t\trequestParams.messages = history;\n\t\t\t\t}\n\t\t\t} while (!controller.signal.aborted && resp.choices?.[0]?.message?.tool_calls?.length);\n\n\t\t\tconst combinedContent = loopMessages.filter(m => m.role === 'assistant')\n\t\t\t\t.map(m => m.content).filter(c => c).join('\\n\\n');\n\t\t\tif(options.stream) options.stream({done: true});\n\t\t\tres(this.toStandard([...history, {role: 'assistant', content: combinedContent, timestamp: Date.now()}]));\n\t\t});\n\n\t\treturn Object.assign(response, {abort: () => controller.abort()});\n\t}\n}\n","import {JSONAttemptParse} from '@ztimson/utils';\nimport {Ai} from './ai.ts';\nimport {Anthropic} from './antrhopic.ts';\nimport {Ollama} from './ollama.ts';\nimport {OpenAi} from './open-ai.ts';\nimport {AbortablePromise, LLMProvider} from './provider.ts';\nimport {AiTool} from './tools.ts';\n\nexport type LLMMessage = {\n\t/** Message originator */\n\trole: 'assistant' | 'system' | 'user';\n\t/** Message content */\n\tcontent: string | any;\n\t/** Timestamp */\n\ttimestamp: number;\n} | {\n\t/** Tool call */\n\trole: 'tool';\n\t/** Unique ID for call */\n\tid: string;\n\t/** Tool that was run */\n\tname: string;\n\t/** Tool arguments */\n\targs: any;\n\t/** Tool result */\n\tcontent: undefined | string;\n\t/** Tool error */\n\terror: undefined | string;\n\t/** Timestamp */\n\ttimestamp: number;\n}\n\nexport type LLMOptions = {\n\t/** Anthropic settings */\n\tanthropic?: {\n\t\t/** API Token */\n\t\ttoken: string;\n\t\t/** Default model */\n\t\tmodel: string;\n\t},\n\t/** Ollama settings */\n\tollama?: {\n\t\t/** connection URL */\n\t\thost: string;\n\t\t/** Default model */\n\t\tmodel: string;\n\t},\n\t/** Open AI settings */\n\topenAi?: {\n\t\t/** API Token */\n\t\ttoken: string;\n\t\t/** Default model */\n\t\tmodel: string;\n\t},\n\t/** Default provider & model */\n\tmodel: string | [string, string];\n} & Omit<LLMRequest, 'model'>;\n\nexport type LLMRequest = {\n\t/** System prompt */\n\tsystem?: string;\n\t/** Message history */\n\thistory?: LLMMessage[];\n\t/** Max tokens for request */\n\tmax_tokens?: number;\n\t/** 0 = Rigid Logic, 1 = Balanced, 2 = Hyper Creative **/\n\ttemperature?: number;\n\t/** Available tools */\n\ttools?: AiTool[];\n\t/** LLM model */\n\tmodel?: string | [string, string];\n\t/** Stream response */\n\tstream?: (chunk: {text?: string, done?: true}) => any;\n\t/** Compress old messages in the chat to free up context */\n\tcompress?: {\n\t\t/** Trigger chat compression once context exceeds the token count */\n\t\tmax: number;\n\t\t/** Compress chat until context size smaller than */\n\t\tmin: number\n\t}\n}\n\nexport class LLM {\n\tprivate providers: {[key: string]: LLMProvider} = {};\n\n\tconstructor(public readonly ai: Ai, public readonly options: LLMOptions) {\n\t\tif(options.anthropic?.token) this.providers.anthropic = new Anthropic(this.ai, options.anthropic.token, options.anthropic.model);\n\t\tif(options.ollama?.host) this.providers.ollama = new Ollama(this.ai, options.ollama.host, options.ollama.model);\n\t\tif(options.openAi?.token) this.providers.openAi = new OpenAi(this.ai, options.openAi.token, options.openAi.model);\n\t}\n\n\t/**\n\t * Chat with LLM\n\t * @param {string} message Question\n\t * @param {LLMRequest} options Configuration options and chat history\n\t * @returns {{abort: () => void, response: Promise<LLMMessage[]>}} Function to abort response and chat history\n\t */\n\task(message: string, options: LLMRequest = {}): AbortablePromise<LLMMessage[]> {\n\t\tlet model: any = [null, null];\n\t\tif(options.model) {\n\t\t\tif(typeof options.model == 'object') model = options.model;\n\t\t\telse model = [options.model, (<any>this.options)[options.model]?.model];\n\t\t}\n\t\tif(!options.model || model[1] == null) {\n\t\t\tif(typeof this.options.model == 'object') model = this.options.model;\n\t\t\telse model = [this.options.model, (<any>this.options)[this.options.model]?.model];\n\t\t}\n\t\tif(!model[0] || !model[1]) throw new Error(`Unknown LLM provider or model: ${model[0]} / ${model[1]}`);\n\t\treturn this.providers[model[0]].ask(message, {...options, model: model[1]});\n\t}\n\n\t/**\n\t * Compress chat history to reduce context size\n\t * @param {LLMMessage[]} history Chatlog that will be compressed\n\t * @param max Trigger compression once context is larger than max\n\t * @param min Summarize until context size is less than min\n\t * @param {LLMRequest} options LLM options\n\t * @returns {Promise<LLMMessage[]>} New chat history will summary at index 0\n\t */\n\tasync compress(history: LLMMessage[], max: number, min: number, options?: LLMRequest): Promise<LLMMessage[]> {\n\t\tif(this.estimateTokens(history) < max) return history;\n\t\tlet keep = 0, tokens = 0;\n\t\tfor(let m of history.toReversed()) {\n\t\t\ttokens += this.estimateTokens(m.content);\n\t\t\tif(tokens < min) keep++;\n\t\t\telse break;\n\t\t}\n\t\tif(history.length <= keep) return history;\n\t\tconst recent = keep == 0 ? [] : history.slice(-keep),\n\t\t\tprocess = (keep == 0 ? history : history.slice(0, -keep)).filter(h => h.role === 'assistant' || h.role === 'user');\n\t\tconst summary = await this.summarize(process.map(m => `${m.role}: ${m.content}`).join('\\n\\n'), 250, options);\n\t\treturn [{role: 'assistant', content: `Conversation Summary: ${summary}`, timestamp: Date.now()}, ...recent];\n\t}\n\n\t/**\n\t * Estimate variable as tokens\n\t * @param history Object to size\n\t * @returns {number} Rough token count\n\t */\n\testimateTokens(history: any): number {\n\t\tconst text = JSON.stringify(history);\n\t\treturn Math.ceil((text.length / 4) * 1.2);\n\t}\n\n\t/**\n\t * Ask a question with JSON response\n\t * @param {string} message Question\n\t * @param {LLMRequest} options Configuration options and chat history\n\t * @returns {Promise<{} | {} | RegExpExecArray | null>}\n\t */\n\tasync json(message: string, options?: LLMRequest) {\n\t\tlet resp = await this.ask(message, {\n\t\t\tsystem: 'Respond using a JSON blob',\n\t\t\t...options\n\t\t});\n\t\tif(!resp?.[0]?.content) return {};\n\t\treturn JSONAttemptParse(new RegExp('\\{[\\s\\S]*\\}').exec(resp[0].content), {});\n\t}\n\n\t/**\n\t * Create a summary of some text\n\t * @param {string} text Text to summarize\n\t * @param {number} tokens Max number of tokens\n\t * @param options LLM request options\n\t * @returns {Promise<string>} Summary\n\t */\n\tsummarize(text: string, tokens: number, options?: LLMRequest): Promise<string | null> {\n\t\treturn this.ask(text, {system: `Generate a brief summary <= ${tokens} tokens. Output nothing else`, temperature: 0.3, ...options})\n\t\t\t.then(history => <string>history.pop()?.content || null);\n\t}\n}\n","import {createWorker} from 'tesseract.js';\nimport {LLM, LLMOptions} from './llm';\nimport fs from 'node:fs/promises';\nimport Path from 'node:path';\nimport * as tf from '@tensorflow/tfjs';\nimport {spawn} from 'node:child_process';\n\nexport type AiOptions = LLMOptions & {\n\twhisper?: {\n\t\t/** Whisper binary location */\n\t\tbinary: string;\n\t\t/** Model: `ggml-base.en.bin` */\n\t\tmodel: string;\n\t\t/** Path to models */\n\t\tpath: string;\n\t}\n}\n\nexport class Ai {\n\tprivate downloads: {[key: string]: Promise<string>} = {};\n\tprivate whisperModel!: string;\n\n\t/** Large Language Models */\n\tllm!: LLM;\n\n\tconstructor(public readonly options: AiOptions) {\n\t\tthis.llm = new LLM(this, options);\n\t\tif(this.options.whisper?.binary) {\n\t\t\tthis.whisperModel = this.options.whisper?.model.endsWith('.bin') ? this.options.whisper?.model : this.options.whisper?.model + '.bin';\n\t\t\tthis.downloadAsrModel();\n\t\t}\n\t}\n\n\t/**\n\t * Convert audio to text using Auditory Speech Recognition\n\t * @param {string} path Path to audio\n\t * @param model Whisper model\n\t * @returns {Promise<any>} Extracted text\n\t */\n\tasr(path: string, model: string = this.whisperModel): {abort: () => void, response: Promise<string | null>} {\n\t\tif(!this.options.whisper?.binary) throw new Error('Whisper not configured');\n\t\tlet abort: any = () => {};\n\t\tconst response = new Promise<string | null>((resolve, reject) => {\n\t\t\tthis.downloadAsrModel(model).then(m => {\n\t\t\t\tlet output = '';\n\t\t\t\tconst proc = spawn(<string>this.options.whisper?.binary, ['-nt', '-np', '-m', m, '-f', path], {stdio: ['ignore', 'pipe', 'ignore']});\n\t\t\t\tabort = () => proc.kill('SIGTERM');\n\t\t\t\tproc.on('error', (err: Error) => reject(err));\n\t\t\t\tproc.stdout.on('data', (data: Buffer) => output += data.toString());\n\t\t\t\tproc.on('close', (code: number) => {\n\t\t\t\t\tif(code === 0) resolve(output.trim() || null);\n\t\t\t\t\telse reject(new Error(`Exit code ${code}`));\n\t\t\t\t});\n\t\t\t});\n\t\t});\n\t\treturn {response, abort};\n\t}\n\n\t/**\n\t * Downloads the specified Whisper model if it is not already present locally.\n\t *\n\t * @param {string} model Whisper model that will be downloaded\n\t * @return {Promise<string>} Absolute path to model file, resolves once downloaded\n\t */\n\tasync downloadAsrModel(model: string = this.whisperModel): Promise<string> {\n\t\tif(!this.options.whisper?.binary) throw new Error('Whisper not configured');\n\t\tif(!model.endsWith('.bin')) model += '.bin';\n\t\tconst p = Path.join(this.options.whisper.path, model);\n\t\tif(await fs.stat(p).then(() => true).catch(() => false)) return p;\n\t\tif(!!this.downloads[model]) return this.downloads[model];\n\t\tthis.downloads[model] = fetch(`https://huggingface.co/ggerganov/whisper.cpp/resolve/main/${model}`)\n\t\t\t.then(resp => resp.arrayBuffer())\n\t\t\t.then(arr => Buffer.from(arr)).then(async buffer => {\n\t\t\t\tawait fs.writeFile(p, buffer);\n\t\t\t\tdelete this.downloads[model];\n\t\t\t\treturn p;\n\t\t\t});\n\t\treturn this.downloads[model];\n\t}\n\n\t/**\n\t * Convert image to text using Optical Character Recognition\n\t * @param {string} path Path to image\n\t * @returns {{abort: Function, response: Promise<string | null>}} Abort function & Promise of extracted text\n\t */\n\tocr(path: string): {abort: () => void, response: Promise<string | null>} {\n\t\tlet worker: any;\n\t\treturn {\n\t\t\tabort: () => { worker?.terminate(); },\n\t\t\tresponse: new Promise(async res => {\n\t\t\t\tworker = await createWorker('eng');\n\t\t\t\tconst {data} = await worker.recognize(path);\n\t\t\t\tawait worker.terminate();\n\t\t\t\tres(data.text.trim() || null);\n\t\t\t})\n\t\t}\n\t}\n\n\t/**\n\t * Compare the difference between two strings using tensor math\n\t * @param target Text that will checked\n\t * @param {string} searchTerms Multiple search terms to check against target\n\t * @returns {{avg: number, max: number, similarities: number[]}} Similarity values 0-1: 0 = unique, 1 = identical\n\t */\n\tsemanticSimilarity(target: string, ...searchTerms: string[]) {\n\t\tif(searchTerms.length < 2) throw new Error('Requires at least 2 strings to compare');\n\n\t\tconst vector = (text: string, dimensions: number = 10): number[] => {\n\t\t\treturn text.toLowerCase().split('').map((char, index) =>\n\t\t\t\t(char.charCodeAt(0) * (index + 1)) % dimensions / dimensions).slice(0, dimensions);\n\t\t}\n\n\t\tconst cosineSimilarity = (v1: number[], v2: number[]): number => {\n\t\t\tif (v1.length !== v2.length) throw new Error('Vectors must be same length');\n\t\t\tconst tensor1 = tf.tensor1d(v1), tensor2 = tf.tensor1d(v2)\n\t\t\tconst dotProduct = tf.dot(tensor1, tensor2)\n\t\t\tconst magnitude1 = tf.norm(tensor1)\n\t\t\tconst magnitude2 = tf.norm(tensor2)\n\t\t\tif(magnitude1.dataSync()[0] === 0 || magnitude2.dataSync()[0] === 0) return 0\n\t\t\treturn dotProduct.dataSync()[0] / (magnitude1.dataSync()[0] * magnitude2.dataSync()[0])\n\t\t}\n\n\t\tconst v = vector(target);\n\t\tconst similarities = searchTerms.map(t => vector(t)).map(refVector => cosineSimilarity(v, refVector))\n\t\treturn {avg: similarities.reduce((acc, s) => acc + s, 0) / similarities.length, max: Math.max(...similarities), similarities}\n\t}\n}\n","import {$, $Sync} from '@ztimson/node-utils';\nimport {ASet, consoleInterceptor, Http, fn as Fn} from '@ztimson/utils';\nimport {Ai} from './ai.ts';\n\nexport type AiToolArg = {[key: string]: {\n\t/** Argument type */\n\ttype: 'array' | 'boolean' | 'number' | 'object' | 'string',\n\t/** Argument description */\n\tdescription: string,\n\t/** Required argument */\n\trequired?: boolean;\n\t/** Default value */\n\tdefault?: any,\n\t/** Options */\n\tenum?: string[],\n\t/** Minimum value or length */\n\tmin?: number,\n\t/** Maximum value or length */\n\tmax?: number,\n\t/** Match pattern */\n\tpattern?: string,\n\t/** Child arguments */\n\titems?: {[key: string]: AiToolArg}\n}}\n\nexport type AiTool = {\n\t/** Tool ID / Name - Must be snail_case */\n\tname: string,\n\t/** Tool description / prompt */\n\tdescription: string,\n\t/** Tool arguments */\n\targs?: AiToolArg,\n\t/** Callback function */\n\tfn: (args: any, ai: Ai) => any | Promise<any>,\n};\n\nexport const CliTool: AiTool = {\n\tname: 'cli',\n\tdescription: 'Use the command line interface, returns any output',\n\targs: {command: {type: 'string', description: 'Command to run', required: true}},\n\tfn: (args: {command: string}) => $`${args.command}`\n}\n\nexport const DateTimeTool: AiTool = {\n\tname: 'get_datetime',\n\tdescription: 'Get current date and time',\n\targs: {},\n\tfn: async () => new Date().toISOString()\n}\n\nexport const ExecTool: AiTool = {\n\tname: 'exec',\n\tdescription: 'Run code/scripts',\n\targs: {\n\t\tlanguage: {type: 'string', description: 'Execution language', enum: ['cli', 'node', 'python'], required: true},\n\t\tcode: {type: 'string', description: 'Code to execute', required: true}\n\t},\n\tfn: async (args, ai) => {\n\t\ttry {\n\t\t\tswitch(args.type) {\n\t\t\t\tcase 'bash':\n\t\t\t\t\treturn await CliTool.fn({command: args.code}, ai);\n\t\t\t\tcase 'node':\n\t\t\t\t\treturn await JSTool.fn({code: args.code}, ai);\n\t\t\t\tcase 'python': {\n\t\t\t\t\treturn await PythonTool.fn({code: args.code}, ai);\n\t\t\t\t}\n\t\t\t}\n\t\t} catch(err: any) {\n\t\t\treturn {error: err?.message || err.toString()};\n\t\t}\n\t}\n}\n\nexport const FetchTool: AiTool = {\n\tname: 'fetch',\n\tdescription: 'Make HTTP request to URL',\n\targs: {\n\t\turl: {type: 'string', description: 'URL to fetch', required: true},\n\t\tmethod: {type: 'string', description: 'HTTP method to use', enum: ['GET', 'POST', 'PUT', 'DELETE'], default: 'GET'},\n\t\theaders: {type: 'object', description: 'HTTP headers to send', default: {}},\n\t\tbody: {type: 'object', description: 'HTTP body to send'},\n\t},\n\tfn: (args: {\n\t\turl: string;\n\t\tmethod: 'GET' | 'POST' | 'PUT' | 'DELETE';\n\t\theaders: {[key: string]: string};\n\t\tbody: any;\n\t}) => new Http({url: args.url, headers: args.headers}).request({method: args.method || 'GET', body: args.body})\n}\n\nexport const JSTool: AiTool = {\n\tname: 'exec_javascript',\n\tdescription: 'Execute commonjs javascript',\n\targs: {\n\t\tcode: {type: 'string', description: 'CommonJS javascript', required: true}\n\t},\n\tfn: async (args: {code: string}) => {\n\t\tconst console = consoleInterceptor(null);\n\t\tconst resp = await Fn<any>({console}, args.code, true).catch((err: any) => console.output.error.push(err));\n\t\treturn {...console.output, return: resp, stdout: undefined, stderr: undefined};\n\t}\n}\n\nexport const PythonTool: AiTool = {\n\tname: 'exec_javascript',\n\tdescription: 'Execute commonjs javascript',\n\targs: {\n\t\tcode: {type: 'string', description: 'CommonJS javascript', required: true}\n\t},\n\tfn: async (args: {code: string}) => ({result: $Sync`python -c \"${args.code}\"`})\n}\n\nexport const SearchTool: AiTool = {\n\tname: 'search',\n\tdescription: 'Use a search engine to find relevant URLs, should be changed with fetch to scrape sources',\n\targs: {\n\t\tquery: {type: 'string', description: 'Search string', required: true},\n\t\tlength: {type: 'string', description: 'Number of results to return', default: 5},\n\t},\n\tfn: async (args: {\n\t\tquery: string;\n\t\tlength: number;\n\t}) => {\n\t\tconst html = await fetch(`https://html.duckduckgo.com/html/?q=${encodeURIComponent(args.query)}`, {\n\t\t\theaders: {\"User-Agent\": \"Mozilla/5.0 (Windows NT 10.0; Win64; x64)\", \"Accept-Language\": \"en-US,en;q=0.9\"}\n\t\t}).then(resp => resp.text());\n\t\tlet match, regex = /<a .*?href=\"(.+?)\".+?<\\/a>/g;\n\t\tconst results = new ASet<string>();\n\t\twhile((match = regex.exec(html)) !== null) {\n\t\t\tlet url = /uddg=(.+)&?/.exec(decodeURIComponent(match[1]))?.[1];\n\t\t\tif(url) url = decodeURIComponent(url);\n\t\t\tif(url) results.add(url);\n\t\t\tif(results.size >= (args.length || 5)) break;\n\t\t}\n\t\treturn results;\n\t}\n}\n"],"names":["LLMProvider","Anthropic","ai","apiToken","model","anthropic","history","i","orgI","c","h","message","options","controller","response","res","rej","requestParams","t","objectMap","key","value","resp","loopMessages","chunk","text","last","JSONAttemptParse","toolCalls","userMsg","toolCall","tool","findByProp","result","JSONSanitize","err","combinedContent","m","Ollama","host","ollama","error","system","results","args","OpenAi","openAI","tools","tc","record","h2","LLM","max","min","keep","tokens","recent","process","Ai","path","abort","resolve","reject","output","proc","spawn","data","code","p","Path","fs","arr","buffer","worker","createWorker","target","searchTerms","vector","dimensions","char","index","cosineSimilarity","v1","v2","tensor1","tf","tensor2","dotProduct","magnitude1","magnitude2","v","similarities","refVector","acc","s","CliTool","DateTimeTool","ExecTool","JSTool","PythonTool","FetchTool","Http","console","consoleInterceptor","Fn","$Sync","SearchTool","html","match","regex","ASet","url"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.mjs","sources":["../src/provider.ts","../src/antrhopic.ts","../src/ollama.ts","../src/open-ai.ts","../src/llm.ts","../src/ai.ts","../src/tools.ts"],"sourcesContent":["import {LLMMessage, LLMOptions, LLMRequest} from './llm.ts';\n\nexport type AbortablePromise<T> = Promise<T> & {abort: () => void};\n\nexport abstract class LLMProvider {\n\tabstract ask(message: string, options: LLMRequest): AbortablePromise<LLMMessage[]>;\n}\n","import {Anthropic as anthropic} from '@anthropic-ai/sdk';\nimport {findByProp, objectMap, JSONSanitize, JSONAttemptParse} from '@ztimson/utils';\nimport {Ai} from './ai.ts';\nimport {LLMMessage, LLMRequest} from './llm.ts';\nimport {AbortablePromise, LLMProvider} from './provider.ts';\n\nexport class Anthropic extends LLMProvider {\n\tclient!: anthropic;\n\n\tconstructor(public readonly ai: Ai, public readonly apiToken: string, public model: string) {\n\t\tsuper();\n\t\tthis.client = new anthropic({apiKey: apiToken});\n\t}\n\n\tprivate toStandard(history: any[]): LLMMessage[] {\n\t\tfor(let i = 0; i < history.length; i++) {\n\t\t\tconst orgI = i;\n\t\t\tif(typeof history[orgI].content != 'string') {\n\t\t\t\tif(history[orgI].role == 'assistant') {\n\t\t\t\t\thistory[orgI].content.filter((c: any) => c.type =='tool_use').forEach((c: any) => {\n\t\t\t\t\t\ti++;\n\t\t\t\t\t\thistory.splice(i, 0, {role: 'tool', id: c.id, name: c.name, args: c.input, timestamp: Date.now()});\n\t\t\t\t\t});\n\t\t\t\t} else if(history[orgI].role == 'user') {\n\t\t\t\t\thistory[orgI].content.filter((c: any) => c.type =='tool_result').forEach((c: any) => {\n\t\t\t\t\t\tconst h = history.find((h: any) => h.id == c.tool_use_id);\n\t\t\t\t\t\th[c.is_error ? 'error' : 'content'] = c.content;\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\thistory[orgI].content = history[orgI].content.filter((c: any) => c.type == 'text').map((c: any) => c.text).join('\\n\\n');\n\t\t\t}\n\t\t\tif(!history[orgI].timestamp) history[orgI].timestamp = Date.now();\n\t\t}\n\t\treturn history.filter(h => !!h.content);\n\t}\n\n\tprivate fromStandard(history: LLMMessage[]): any[] {\n\t\tfor(let i = 0; i < history.length; i++) {\n\t\t\tif(history[i].role == 'tool') {\n\t\t\t\tconst h: any = history[i];\n\t\t\t\thistory.splice(i, 1,\n\t\t\t\t\t{role: 'assistant', content: [{type: 'tool_use', id: h.id, name: h.name, input: h.args}]},\n\t\t\t\t\t{role: 'user', content: [{type: 'tool_result', tool_use_id: h.id, is_error: !!h.error, content: h.error || h.content}]}\n\t\t\t\t)\n\t\t\t\ti++;\n\t\t\t}\n\t\t}\n\t\treturn history.map(({timestamp, ...h}) => h);\n\t}\n\n\task(message: string, options: LLMRequest = {}): AbortablePromise<LLMMessage[]> {\n\t\tconst controller = new AbortController();\n\t\tconst response = new Promise<any>(async (res, rej) => {\n\t\t\tlet history = this.fromStandard([...options.history || [], {role: 'user', content: message, timestamp: Date.now()}]);\n\t\t\tif(options.compress) history = await this.ai.llm.compress(<any>history, options.compress.max, options.compress.min, options);\n\t\t\tconst requestParams: any = {\n\t\t\t\tmodel: options.model || this.model,\n\t\t\t\tmax_tokens: options.max_tokens || this.ai.options.max_tokens || 4096,\n\t\t\t\tsystem: options.system || this.ai.options.system || '',\n\t\t\t\ttemperature: options.temperature || this.ai.options.temperature || 0.7,\n\t\t\t\ttools: (options.tools || this.ai.options.tools || []).map(t => ({\n\t\t\t\t\tname: t.name,\n\t\t\t\t\tdescription: t.description,\n\t\t\t\t\tinput_schema: {\n\t\t\t\t\t\ttype: 'object',\n\t\t\t\t\t\tproperties: t.args ? objectMap(t.args, (key, value) => ({...value, required: undefined})) : {},\n\t\t\t\t\t\trequired: t.args ? Object.entries(t.args).filter(t => t[1].required).map(t => t[0]) : []\n\t\t\t\t\t},\n\t\t\t\t\tfn: undefined\n\t\t\t\t})),\n\t\t\t\tmessages: history,\n\t\t\t\tstream: !!options.stream,\n\t\t\t};\n\n\t\t\tlet resp: any;\n\t\t\tconst loopMessages: any[] = [];\n\t\t\tdo {\n\t\t\t\tresp = await this.client.messages.create(requestParams);\n\t\t\t\tif(options.stream) {\n\t\t\t\t\tif(loopMessages.length) options.stream({text: '\\n\\n'});\n\t\t\t\t\tresp.content = [];\n\t\t\t\t\tfor await (const chunk of resp) {\n\t\t\t\t\t\tif(controller.signal.aborted) break;\n\t\t\t\t\t\tif(chunk.type === 'content_block_start') {\n\t\t\t\t\t\t\tif(chunk.content_block.type === 'text') {\n\t\t\t\t\t\t\t\tresp.content.push({type: 'text', text: ''});\n\t\t\t\t\t\t\t} else if(chunk.content_block.type === 'tool_use') {\n\t\t\t\t\t\t\t\tresp.content.push({type: 'tool_use', id: chunk.content_block.id, name: chunk.content_block.name, input: <any>''});\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else if(chunk.type === 'content_block_delta') {\n\t\t\t\t\t\t\tif(chunk.delta.type === 'text_delta') {\n\t\t\t\t\t\t\t\tconst text = chunk.delta.text;\n\t\t\t\t\t\t\t\tresp.content.at(-1).text += text;\n\t\t\t\t\t\t\t\toptions.stream({text});\n\t\t\t\t\t\t\t} else if(chunk.delta.type === 'input_json_delta') {\n\t\t\t\t\t\t\t\tresp.content.at(-1).input += chunk.delta.partial_json;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else if(chunk.type === 'content_block_stop') {\n\t\t\t\t\t\t\tconst last = resp.content.at(-1);\n\t\t\t\t\t\t\tif(last.input != null) last.input = last.input ? JSONAttemptParse(last.input, {}) : {};\n\t\t\t\t\t\t} else if(chunk.type === 'message_stop') {\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tloopMessages.push({role: 'assistant', content: resp.content, timestamp: Date.now()});\n\t\t\t\tconst toolCalls = resp.content.filter((c: any) => c.type === 'tool_use');\n\t\t\t\tif(toolCalls.length && !controller.signal.aborted) {\n\t\t\t\t\thistory.push({role: 'assistant', content: resp.content});\n\t\t\t\t\tconst results = await Promise.all(toolCalls.map(async (toolCall: any) => {\n\t\t\t\t\t\tconst tool = options.tools?.find(findByProp('name', toolCall.name));\n\t\t\t\t\t\tif(!tool) return {tool_use_id: toolCall.id, is_error: true, content: 'Tool not found'};\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tconst result = await tool.fn(toolCall.input, this.ai);\n\t\t\t\t\t\t\treturn {type: 'tool_result', tool_use_id: toolCall.id, content: JSONSanitize(result)};\n\t\t\t\t\t\t} catch (err: any) {\n\t\t\t\t\t\t\treturn {type: 'tool_result', tool_use_id: toolCall.id, is_error: true, content: err?.message || err?.toString() || 'Unknown'};\n\t\t\t\t\t\t}\n\t\t\t\t\t}));\n\t\t\t\t\tconst userMsg = {role: 'user', content: results};\n\t\t\t\t\thistory.push(userMsg);\n\t\t\t\t\tloopMessages.push({...userMsg, timestamp: Date.now()});\n\t\t\t\t\trequestParams.messages = history;\n\t\t\t\t}\n\t\t\t} while (!controller.signal.aborted && resp.content.some((c: any) => c.type === 'tool_use'));\n\n\t\t\tconst combinedContent = loopMessages.filter(m => m.role === 'assistant')\n\t\t\t\t.map(m => m.content.filter((c: any) => c.type == 'text').map((c: any) => c.text).join('\\n\\n'))\n\t\t\t\t.filter(c => c).join('\\n\\n');\n\t\t\tif(options.stream) options.stream({done: true});\n\t\t\tres(this.toStandard([...history, {role: 'assistant', content: combinedContent, timestamp: Date.now()}]));\n\t\t});\n\n\t\treturn Object.assign(response, {abort: () => controller.abort()});\n\t}\n}\n","import {findByProp, objectMap, JSONSanitize, JSONAttemptParse} from '@ztimson/utils';\nimport {Ai} from './ai.ts';\nimport {LLMMessage, LLMRequest} from './llm.ts';\nimport {AbortablePromise, LLMProvider} from './provider.ts';\nimport {Ollama as ollama} from 'ollama';\n\nexport class Ollama extends LLMProvider {\n\tclient!: ollama;\n\n\tconstructor(public readonly ai: Ai, public host: string, public model: string) {\n\t\tsuper();\n\t\tthis.client = new ollama({host});\n\t}\n\n\tprivate toStandard(history: any[]): LLMMessage[] {\n\t\tfor(let i = 0; i < history.length; i++) {\n\t\t\tif(history[i].role == 'assistant' && history[i].tool_calls) {\n\t\t\t\tif(history[i].content) delete history[i].tool_calls;\n\t\t\t\telse {\n\t\t\t\t\thistory.splice(i, 1);\n\t\t\t\t\ti--;\n\t\t\t\t}\n\t\t\t} else if(history[i].role == 'tool') {\n\t\t\t\tconst error = history[i].content.startsWith('{\"error\":');\n\t\t\t\thistory[i] = {role: 'tool', name: history[i].tool_name, args: history[i].args, [error ? 'error' : 'content']: history[i].content, timestamp: history[i].timestamp};\n\t\t\t}\n\t\t\tif(!history[i]?.timestamp) history[i].timestamp = Date.now();\n\t\t}\n\t\treturn history;\n\t}\n\n\tprivate fromStandard(history: LLMMessage[]): any[] {\n\t\treturn history.map((h: any) => {\n\t\t\tconst {timestamp, ...rest} = h;\n\t\t\tif(h.role != 'tool') return rest;\n\t\t\treturn {role: 'tool', tool_name: h.name, content: h.error || h.content}\n\t\t});\n\t}\n\n\task(message: string, options: LLMRequest = {}): AbortablePromise<LLMMessage[]> {\n\t\tconst controller = new AbortController();\n\t\tconst response = new Promise<any>(async (res, rej) => {\n\t\t\tlet system = options.system || this.ai.options.system;\n\t\t\tlet history = this.fromStandard([...options.history || [], {role: 'user', content: message, timestamp: Date.now()}]);\n\t\t\tif(history[0].roll == 'system') {\n\t\t\t\tif(!system) system = history.shift();\n\t\t\t\telse history.shift();\n\t\t\t}\n\t\t\tif(options.compress) history = await this.ai.llm.compress(<any>history, options.compress.max, options.compress.min);\n\t\t\tif(options.system) history.unshift({role: 'system', content: system})\n\n\t\t\tconst requestParams: any = {\n\t\t\t\tmodel: options.model || this.model,\n\t\t\t\tmessages: history,\n\t\t\t\tstream: !!options.stream,\n\t\t\t\tsignal: controller.signal,\n\t\t\t\toptions: {\n\t\t\t\t\ttemperature: options.temperature || this.ai.options.temperature || 0.7,\n\t\t\t\t\tnum_predict: options.max_tokens || this.ai.options.max_tokens || 4096,\n\t\t\t\t},\n\t\t\t\ttools: (options.tools || this.ai.options.tools || []).map(t => ({\n\t\t\t\t\ttype: 'function',\n\t\t\t\t\tfunction: {\n\t\t\t\t\t\tname: t.name,\n\t\t\t\t\t\tdescription: t.description,\n\t\t\t\t\t\tparameters: {\n\t\t\t\t\t\t\ttype: 'object',\n\t\t\t\t\t\t\tproperties: t.args ? objectMap(t.args, (key, value) => ({...value, required: undefined})) : {},\n\t\t\t\t\t\t\trequired: t.args ? Object.entries(t.args).filter(t => t[1].required).map(t => t[0]) : []\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}))\n\t\t\t}\n\n\t\t\tlet resp: any;\n\t\t\tconst loopMessages: any[] = [];\n\t\t\tdo {\n\t\t\t\tresp = await this.client.chat(requestParams);\n\t\t\t\tif(options.stream) {\n\t\t\t\t\tif(loopMessages.length) options.stream({text: '\\n\\n'});\n\t\t\t\t\tresp.message = {role: 'assistant', content: '', tool_calls: []};\n\t\t\t\t\tfor await (const chunk of resp) {\n\t\t\t\t\t\tif(controller.signal.aborted) break;\n\t\t\t\t\t\tif(chunk.message?.content) {\n\t\t\t\t\t\t\tresp.message.content += chunk.message.content;\n\t\t\t\t\t\t\toptions.stream({text: chunk.message.content});\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif(chunk.message?.tool_calls) resp.message.tool_calls = chunk.message.tool_calls;\n\t\t\t\t\t\tif(chunk.done) break;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tloopMessages.push({role: 'assistant', content: resp.message?.content, timestamp: Date.now()});\n\t\t\t\tif(resp.message?.tool_calls?.length && !controller.signal.aborted) {\n\t\t\t\t\thistory.push(resp.message);\n\t\t\t\t\tconst results = await Promise.all(resp.message.tool_calls.map(async (toolCall: any) => {\n\t\t\t\t\t\tconst tool = (options.tools || this.ai.options.tools)?.find(findByProp('name', toolCall.function.name));\n\t\t\t\t\t\tif(!tool) return {role: 'tool', tool_name: toolCall.function.name, content: '{\"error\": \"Tool not found\"}'};\n\t\t\t\t\t\tconst args = typeof toolCall.function.arguments === 'string' ? JSONAttemptParse(toolCall.function.arguments, {}) : toolCall.function.arguments;\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tconst result = await tool.fn(args, this.ai);\n\t\t\t\t\t\t\treturn {role: 'tool', tool_name: toolCall.function.name, args, content: JSONSanitize(result)};\n\t\t\t\t\t\t} catch (err: any) {\n\t\t\t\t\t\t\treturn {role: 'tool', tool_name: toolCall.function.name, args, content: JSONSanitize({error: err?.message || err?.toString() || 'Unknown'})};\n\t\t\t\t\t\t}\n\t\t\t\t\t}));\n\t\t\t\t\thistory.push(...results);\n\t\t\t\t\tloopMessages.push(...results.map(r => ({...r, timestamp: Date.now()})));\n\t\t\t\t\trequestParams.messages = history;\n\t\t\t\t}\n\t\t\t} while (!controller.signal.aborted && resp.message?.tool_calls?.length);\n\n\t\t\tconst combinedContent = loopMessages.filter(m => m.role === 'assistant')\n\t\t\t\t.map(m => m.content).filter(c => c).join('\\n\\n');\n\t\t\tif(options.stream) options.stream({done: true});\n\t\t\tres(this.toStandard([...history, {role: 'assistant', content: combinedContent, timestamp: Date.now()}]));\n\t\t});\n\n\t\treturn Object.assign(response, {abort: () => controller.abort()});\n\t}\n}\n","import {OpenAI as openAI} from 'openai';\nimport {findByProp, objectMap, JSONSanitize, JSONAttemptParse} from '@ztimson/utils';\nimport {Ai} from './ai.ts';\nimport {LLMMessage, LLMRequest} from './llm.ts';\nimport {AbortablePromise, LLMProvider} from './provider.ts';\n\nexport class OpenAi extends LLMProvider {\n\tclient!: openAI;\n\n\tconstructor(public readonly ai: Ai, public readonly apiToken: string, public model: string) {\n\t\tsuper();\n\t\tthis.client = new openAI({apiKey: apiToken});\n\t}\n\n\tprivate toStandard(history: any[]): LLMMessage[] {\n\t\tfor(let i = 0; i < history.length; i++) {\n\t\t\tconst h = history[i];\n\t\t\tif(h.role === 'assistant' && h.tool_calls) {\n\t\t\t\tconst tools = h.tool_calls.map((tc: any) => ({\n\t\t\t\t\trole: 'tool',\n\t\t\t\t\tid: tc.id,\n\t\t\t\t\tname: tc.function.name,\n\t\t\t\t\targs: JSONAttemptParse(tc.function.arguments, {}),\n\t\t\t\t\ttimestamp: h.timestamp\n\t\t\t\t}));\n\t\t\t\thistory.splice(i, 1, ...tools);\n\t\t\t\ti += tools.length - 1;\n\t\t\t} else if(h.role === 'tool' && h.content) {\n\t\t\t\tconst record = history.find(h2 => h.tool_call_id == h2.id);\n\t\t\t\tif(record) {\n\t\t\t\t\tif(h.content.includes('\"error\":')) record.error = h.content;\n\t\t\t\t\telse record.content = h.content;\n\t\t\t\t}\n\t\t\t\thistory.splice(i, 1);\n\t\t\t\ti--;\n\t\t\t}\n\t\t\tif(!history[i]?.timestamp) history[i].timestamp = Date.now();\n\t\t}\n\t\treturn history;\n\t}\n\n\tprivate fromStandard(history: LLMMessage[]): any[] {\n\t\treturn history.reduce((result, h) => {\n\t\t\tif(h.role === 'tool') {\n\t\t\t\tresult.push({\n\t\t\t\t\trole: 'assistant',\n\t\t\t\t\tcontent: null,\n\t\t\t\t\ttool_calls: [{ id: h.id, type: 'function', function: { name: h.name, arguments: JSON.stringify(h.args) } }],\n\t\t\t\t\trefusal: null,\n\t\t\t\t\tannotations: []\n\t\t\t\t}, {\n\t\t\t\t\trole: 'tool',\n\t\t\t\t\ttool_call_id: h.id,\n\t\t\t\t\tcontent: h.error || h.content\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\tconst {timestamp, ...rest} = h;\n\t\t\t\tresult.push(rest);\n\t\t\t}\n\t\t\treturn result;\n\t\t}, [] as any[]);\n\t}\n\n\task(message: string, options: LLMRequest = {}): AbortablePromise<LLMMessage[]> {\n\t\tconst controller = new AbortController();\n\t\tconst response = new Promise<any>(async (res, rej) => {\n\t\t\tlet history = this.fromStandard([...options.history || [], {role: 'user', content: message, timestamp: Date.now()}]);\n\t\t\tif(options.compress) history = await this.ai.llm.compress(<any>history, options.compress.max, options.compress.min, options);\n\n\t\t\tconst requestParams: any = {\n\t\t\t\tmodel: options.model || this.model,\n\t\t\t\tmessages: history,\n\t\t\t\tstream: !!options.stream,\n\t\t\t\tmax_tokens: options.max_tokens || this.ai.options.max_tokens || 4096,\n\t\t\t\ttemperature: options.temperature || this.ai.options.temperature || 0.7,\n\t\t\t\ttools: (options.tools || this.ai.options.tools || []).map(t => ({\n\t\t\t\t\ttype: 'function',\n\t\t\t\t\tfunction: {\n\t\t\t\t\t\tname: t.name,\n\t\t\t\t\t\tdescription: t.description,\n\t\t\t\t\t\tparameters: {\n\t\t\t\t\t\t\ttype: 'object',\n\t\t\t\t\t\t\tproperties: t.args ? objectMap(t.args, (key, value) => ({...value, required: undefined})) : {},\n\t\t\t\t\t\t\trequired: t.args ? Object.entries(t.args).filter(t => t[1].required).map(t => t[0]) : []\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}))\n\t\t\t};\n\n\t\t\tlet resp: any;\n\t\t\tconst loopMessages: any[] = [];\n\t\t\tdo {\n\t\t\t\tresp = await this.client.chat.completions.create(requestParams);\n\t\t\t\tif(options.stream) {\n\t\t\t\t\tif(loopMessages.length) options.stream({text: '\\n\\n'});\n\t\t\t\t\tresp.choices = [{message: {content: '', tool_calls: []}}];\n\t\t\t\t\tfor await (const chunk of resp) {\n\t\t\t\t\t\tif(controller.signal.aborted) break;\n\t\t\t\t\t\tif(chunk.choices[0].delta.content) {\n\t\t\t\t\t\t\tresp.choices[0].message.content += chunk.choices[0].delta.content;\n\t\t\t\t\t\t\toptions.stream({text: chunk.choices[0].delta.content});\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif(chunk.choices[0].delta.tool_calls) {\n\t\t\t\t\t\t\tresp.choices[0].message.tool_calls = chunk.choices[0].delta.tool_calls;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tloopMessages.push({role: 'assistant', content: resp.choices[0].message.content || '', timestamp: Date.now()});\n\n\t\t\t\tconst toolCalls = resp.choices[0].message.tool_calls || [];\n\t\t\t\tif(toolCalls.length && !controller.signal.aborted) {\n\t\t\t\t\thistory.push(resp.choices[0].message);\n\t\t\t\t\tconst results = await Promise.all(toolCalls.map(async (toolCall: any) => {\n\t\t\t\t\t\tconst tool = options.tools?.find(findByProp('name', toolCall.function.name));\n\t\t\t\t\t\tif(!tool) return {role: 'tool', tool_call_id: toolCall.id, content: '{\"error\": \"Tool not found\"}'};\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tconst args = JSONAttemptParse(toolCall.function.arguments, {});\n\t\t\t\t\t\t\tconst result = await tool.fn(args, this.ai);\n\t\t\t\t\t\t\treturn {role: 'tool', tool_call_id: toolCall.id, content: JSONSanitize(result)};\n\t\t\t\t\t\t} catch (err: any) {\n\t\t\t\t\t\t\treturn {role: 'tool', tool_call_id: toolCall.id, content: JSONSanitize({error: err?.message || err?.toString() || 'Unknown'})};\n\t\t\t\t\t\t}\n\t\t\t\t\t}));\n\t\t\t\t\thistory.push(...results);\n\t\t\t\t\tloopMessages.push(...results.map(r => ({...r, timestamp: Date.now()})));\n\t\t\t\t\trequestParams.messages = history;\n\t\t\t\t}\n\t\t\t} while (!controller.signal.aborted && resp.choices?.[0]?.message?.tool_calls?.length);\n\n\t\t\tconst combinedContent = loopMessages.filter(m => m.role === 'assistant')\n\t\t\t\t.map(m => m.content).filter(c => c).join('\\n\\n');\n\t\t\tif(options.stream) options.stream({done: true});\n\t\t\tres(this.toStandard([...history, {role: 'assistant', content: combinedContent, timestamp: Date.now()}]));\n\t\t});\n\t\treturn Object.assign(response, {abort: () => controller.abort()});\n\t}\n}\n","import {JSONAttemptParse} from '@ztimson/utils';\nimport {Ai} from './ai.ts';\nimport {Anthropic} from './antrhopic.ts';\nimport {Ollama} from './ollama.ts';\nimport {OpenAi} from './open-ai.ts';\nimport {AbortablePromise, LLMProvider} from './provider.ts';\nimport {AiTool} from './tools.ts';\n\nexport type LLMMessage = {\n\t/** Message originator */\n\trole: 'assistant' | 'system' | 'user';\n\t/** Message content */\n\tcontent: string | any;\n\t/** Timestamp */\n\ttimestamp?: number;\n} | {\n\t/** Tool call */\n\trole: 'tool';\n\t/** Unique ID for call */\n\tid: string;\n\t/** Tool that was run */\n\tname: string;\n\t/** Tool arguments */\n\targs: any;\n\t/** Tool result */\n\tcontent: undefined | string;\n\t/** Tool error */\n\terror: undefined | string;\n\t/** Timestamp */\n\ttimestamp?: number;\n}\n\nexport type LLMOptions = {\n\t/** Anthropic settings */\n\tanthropic?: {\n\t\t/** API Token */\n\t\ttoken: string;\n\t\t/** Default model */\n\t\tmodel: string;\n\t},\n\t/** Ollama settings */\n\tollama?: {\n\t\t/** connection URL */\n\t\thost: string;\n\t\t/** Default model */\n\t\tmodel: string;\n\t},\n\t/** Open AI settings */\n\topenAi?: {\n\t\t/** API Token */\n\t\ttoken: string;\n\t\t/** Default model */\n\t\tmodel: string;\n\t},\n\t/** Default provider & model */\n\tmodel: string | [string, string];\n} & Omit<LLMRequest, 'model'>;\n\nexport type LLMRequest = {\n\t/** System prompt */\n\tsystem?: string;\n\t/** Message history */\n\thistory?: LLMMessage[];\n\t/** Max tokens for request */\n\tmax_tokens?: number;\n\t/** 0 = Rigid Logic, 1 = Balanced, 2 = Hyper Creative **/\n\ttemperature?: number;\n\t/** Available tools */\n\ttools?: AiTool[];\n\t/** LLM model */\n\tmodel?: string | [string, string];\n\t/** Stream response */\n\tstream?: (chunk: {text?: string, done?: true}) => any;\n\t/** Compress old messages in the chat to free up context */\n\tcompress?: {\n\t\t/** Trigger chat compression once context exceeds the token count */\n\t\tmax: number;\n\t\t/** Compress chat until context size smaller than */\n\t\tmin: number\n\t}\n}\n\nexport class LLM {\n\tprivate providers: {[key: string]: LLMProvider} = {};\n\n\tconstructor(public readonly ai: Ai, public readonly options: LLMOptions) {\n\t\tif(options.anthropic?.token) this.providers.anthropic = new Anthropic(this.ai, options.anthropic.token, options.anthropic.model);\n\t\tif(options.ollama?.host) this.providers.ollama = new Ollama(this.ai, options.ollama.host, options.ollama.model);\n\t\tif(options.openAi?.token) this.providers.openAi = new OpenAi(this.ai, options.openAi.token, options.openAi.model);\n\t}\n\n\t/**\n\t * Chat with LLM\n\t * @param {string} message Question\n\t * @param {LLMRequest} options Configuration options and chat history\n\t * @returns {{abort: () => void, response: Promise<LLMMessage[]>}} Function to abort response and chat history\n\t */\n\task(message: string, options: LLMRequest = {}): AbortablePromise<LLMMessage[]> {\n\t\tlet model: any = [null, null];\n\t\tif(options.model) {\n\t\t\tif(typeof options.model == 'object') model = options.model;\n\t\t\telse model = [options.model, (<any>this.options)[options.model]?.model];\n\t\t}\n\t\tif(!options.model || model[1] == null) {\n\t\t\tif(typeof this.options.model == 'object') model = this.options.model;\n\t\t\telse model = [this.options.model, (<any>this.options)[this.options.model]?.model];\n\t\t}\n\t\tif(!model[0] || !model[1]) throw new Error(`Unknown LLM provider or model: ${model[0]} / ${model[1]}`);\n\t\treturn this.providers[model[0]].ask(message, {...options, model: model[1]});\n\t}\n\n\t/**\n\t * Compress chat history to reduce context size\n\t * @param {LLMMessage[]} history Chatlog that will be compressed\n\t * @param max Trigger compression once context is larger than max\n\t * @param min Summarize until context size is less than min\n\t * @param {LLMRequest} options LLM options\n\t * @returns {Promise<LLMMessage[]>} New chat history will summary at index 0\n\t */\n\tasync compress(history: LLMMessage[], max: number, min: number, options?: LLMRequest): Promise<LLMMessage[]> {\n\t\tif(this.estimateTokens(history) < max) return history;\n\t\tlet keep = 0, tokens = 0;\n\t\tfor(let m of history.toReversed()) {\n\t\t\ttokens += this.estimateTokens(m.content);\n\t\t\tif(tokens < min) keep++;\n\t\t\telse break;\n\t\t}\n\t\tif(history.length <= keep) return history;\n\t\tconst recent = keep == 0 ? [] : history.slice(-keep),\n\t\t\tprocess = (keep == 0 ? history : history.slice(0, -keep)).filter(h => h.role === 'assistant' || h.role === 'user');\n\t\tconst summary = await this.summarize(process.map(m => `${m.role}: ${m.content}`).join('\\n\\n'), 250, options);\n\t\treturn [{role: 'assistant', content: `Conversation Summary: ${summary}`, timestamp: Date.now()}, ...recent];\n\t}\n\n\t/**\n\t * Estimate variable as tokens\n\t * @param history Object to size\n\t * @returns {number} Rough token count\n\t */\n\testimateTokens(history: any): number {\n\t\tconst text = JSON.stringify(history);\n\t\treturn Math.ceil((text.length / 4) * 1.2);\n\t}\n\n\t/**\n\t * Ask a question with JSON response\n\t * @param {string} message Question\n\t * @param {LLMRequest} options Configuration options and chat history\n\t * @returns {Promise<{} | {} | RegExpExecArray | null>}\n\t */\n\tasync json(message: string, options?: LLMRequest) {\n\t\tlet resp = await this.ask(message, {\n\t\t\tsystem: 'Respond using a JSON blob',\n\t\t\t...options\n\t\t});\n\t\tif(!resp?.[0]?.content) return {};\n\t\treturn JSONAttemptParse(new RegExp('\\{[\\s\\S]*\\}').exec(resp[0].content), {});\n\t}\n\n\t/**\n\t * Create a summary of some text\n\t * @param {string} text Text to summarize\n\t * @param {number} tokens Max number of tokens\n\t * @param options LLM request options\n\t * @returns {Promise<string>} Summary\n\t */\n\tsummarize(text: string, tokens: number, options?: LLMRequest): Promise<string | null> {\n\t\treturn this.ask(text, {system: `Generate a brief summary <= ${tokens} tokens. Output nothing else`, temperature: 0.3, ...options})\n\t\t\t.then(history => <string>history.pop()?.content || null);\n\t}\n}\n","import {createWorker} from 'tesseract.js';\nimport {LLM, LLMOptions} from './llm';\nimport fs from 'node:fs/promises';\nimport Path from 'node:path';\nimport * as tf from '@tensorflow/tfjs';\nimport {spawn} from 'node:child_process';\n\nexport type AiOptions = LLMOptions & {\n\twhisper?: {\n\t\t/** Whisper binary location */\n\t\tbinary: string;\n\t\t/** Model: `ggml-base.en.bin` */\n\t\tmodel: string;\n\t\t/** Path to models */\n\t\tpath: string;\n\t}\n}\n\nexport class Ai {\n\tprivate downloads: {[key: string]: Promise<string>} = {};\n\tprivate whisperModel!: string;\n\n\t/** Large Language Models */\n\tllm!: LLM;\n\n\tconstructor(public readonly options: AiOptions) {\n\t\tthis.llm = new LLM(this, options);\n\t\tif(this.options.whisper?.binary) {\n\t\t\tthis.whisperModel = this.options.whisper?.model.endsWith('.bin') ? this.options.whisper?.model : this.options.whisper?.model + '.bin';\n\t\t\tthis.downloadAsrModel();\n\t\t}\n\t}\n\n\t/**\n\t * Convert audio to text using Auditory Speech Recognition\n\t * @param {string} path Path to audio\n\t * @param model Whisper model\n\t * @returns {Promise<any>} Extracted text\n\t */\n\tasr(path: string, model: string = this.whisperModel): {abort: () => void, response: Promise<string | null>} {\n\t\tif(!this.options.whisper?.binary) throw new Error('Whisper not configured');\n\t\tlet abort: any = () => {};\n\t\tconst response = new Promise<string | null>((resolve, reject) => {\n\t\t\tthis.downloadAsrModel(model).then(m => {\n\t\t\t\tlet output = '';\n\t\t\t\tconst proc = spawn(<string>this.options.whisper?.binary, ['-nt', '-np', '-m', m, '-f', path], {stdio: ['ignore', 'pipe', 'ignore']});\n\t\t\t\tabort = () => proc.kill('SIGTERM');\n\t\t\t\tproc.on('error', (err: Error) => reject(err));\n\t\t\t\tproc.stdout.on('data', (data: Buffer) => output += data.toString());\n\t\t\t\tproc.on('close', (code: number) => {\n\t\t\t\t\tif(code === 0) resolve(output.trim() || null);\n\t\t\t\t\telse reject(new Error(`Exit code ${code}`));\n\t\t\t\t});\n\t\t\t});\n\t\t});\n\t\treturn {response, abort};\n\t}\n\n\t/**\n\t * Downloads the specified Whisper model if it is not already present locally.\n\t *\n\t * @param {string} model Whisper model that will be downloaded\n\t * @return {Promise<string>} Absolute path to model file, resolves once downloaded\n\t */\n\tasync downloadAsrModel(model: string = this.whisperModel): Promise<string> {\n\t\tif(!this.options.whisper?.binary) throw new Error('Whisper not configured');\n\t\tif(!model.endsWith('.bin')) model += '.bin';\n\t\tconst p = Path.join(this.options.whisper.path, model);\n\t\tif(await fs.stat(p).then(() => true).catch(() => false)) return p;\n\t\tif(!!this.downloads[model]) return this.downloads[model];\n\t\tthis.downloads[model] = fetch(`https://huggingface.co/ggerganov/whisper.cpp/resolve/main/${model}`)\n\t\t\t.then(resp => resp.arrayBuffer())\n\t\t\t.then(arr => Buffer.from(arr)).then(async buffer => {\n\t\t\t\tawait fs.writeFile(p, buffer);\n\t\t\t\tdelete this.downloads[model];\n\t\t\t\treturn p;\n\t\t\t});\n\t\treturn this.downloads[model];\n\t}\n\n\t/**\n\t * Convert image to text using Optical Character Recognition\n\t * @param {string} path Path to image\n\t * @returns {{abort: Function, response: Promise<string | null>}} Abort function & Promise of extracted text\n\t */\n\tocr(path: string): {abort: () => void, response: Promise<string | null>} {\n\t\tlet worker: any;\n\t\treturn {\n\t\t\tabort: () => { worker?.terminate(); },\n\t\t\tresponse: new Promise(async res => {\n\t\t\t\tworker = await createWorker('eng');\n\t\t\t\tconst {data} = await worker.recognize(path);\n\t\t\t\tawait worker.terminate();\n\t\t\t\tres(data.text.trim() || null);\n\t\t\t})\n\t\t}\n\t}\n\n\t/**\n\t * Compare the difference between two strings using tensor math\n\t * @param target Text that will checked\n\t * @param {string} searchTerms Multiple search terms to check against target\n\t * @returns {{avg: number, max: number, similarities: number[]}} Similarity values 0-1: 0 = unique, 1 = identical\n\t */\n\tsemanticSimilarity(target: string, ...searchTerms: string[]) {\n\t\tif(searchTerms.length < 2) throw new Error('Requires at least 2 strings to compare');\n\n\t\tconst vector = (text: string, dimensions: number = 10): number[] => {\n\t\t\treturn text.toLowerCase().split('').map((char, index) =>\n\t\t\t\t(char.charCodeAt(0) * (index + 1)) % dimensions / dimensions).slice(0, dimensions);\n\t\t}\n\n\t\tconst cosineSimilarity = (v1: number[], v2: number[]): number => {\n\t\t\tif (v1.length !== v2.length) throw new Error('Vectors must be same length');\n\t\t\tconst tensor1 = tf.tensor1d(v1), tensor2 = tf.tensor1d(v2)\n\t\t\tconst dotProduct = tf.dot(tensor1, tensor2)\n\t\t\tconst magnitude1 = tf.norm(tensor1)\n\t\t\tconst magnitude2 = tf.norm(tensor2)\n\t\t\tif(magnitude1.dataSync()[0] === 0 || magnitude2.dataSync()[0] === 0) return 0\n\t\t\treturn dotProduct.dataSync()[0] / (magnitude1.dataSync()[0] * magnitude2.dataSync()[0])\n\t\t}\n\n\t\tconst v = vector(target);\n\t\tconst similarities = searchTerms.map(t => vector(t)).map(refVector => cosineSimilarity(v, refVector))\n\t\treturn {avg: similarities.reduce((acc, s) => acc + s, 0) / similarities.length, max: Math.max(...similarities), similarities}\n\t}\n}\n","import {$, $Sync} from '@ztimson/node-utils';\nimport {ASet, consoleInterceptor, Http, fn as Fn} from '@ztimson/utils';\nimport {Ai} from './ai.ts';\n\nexport type AiToolArg = {[key: string]: {\n\t/** Argument type */\n\ttype: 'array' | 'boolean' | 'number' | 'object' | 'string',\n\t/** Argument description */\n\tdescription: string,\n\t/** Required argument */\n\trequired?: boolean;\n\t/** Default value */\n\tdefault?: any,\n\t/** Options */\n\tenum?: string[],\n\t/** Minimum value or length */\n\tmin?: number,\n\t/** Maximum value or length */\n\tmax?: number,\n\t/** Match pattern */\n\tpattern?: string,\n\t/** Child arguments */\n\titems?: {[key: string]: AiToolArg}\n}}\n\nexport type AiTool = {\n\t/** Tool ID / Name - Must be snail_case */\n\tname: string,\n\t/** Tool description / prompt */\n\tdescription: string,\n\t/** Tool arguments */\n\targs?: AiToolArg,\n\t/** Callback function */\n\tfn: (args: any, ai: Ai) => any | Promise<any>,\n};\n\nexport const CliTool: AiTool = {\n\tname: 'cli',\n\tdescription: 'Use the command line interface, returns any output',\n\targs: {command: {type: 'string', description: 'Command to run', required: true}},\n\tfn: (args: {command: string}) => $`${args.command}`\n}\n\nexport const DateTimeTool: AiTool = {\n\tname: 'get_datetime',\n\tdescription: 'Get current date and time',\n\targs: {},\n\tfn: async () => new Date().toISOString()\n}\n\nexport const ExecTool: AiTool = {\n\tname: 'exec',\n\tdescription: 'Run code/scripts',\n\targs: {\n\t\tlanguage: {type: 'string', description: 'Execution language', enum: ['cli', 'node', 'python'], required: true},\n\t\tcode: {type: 'string', description: 'Code to execute', required: true}\n\t},\n\tfn: async (args, ai) => {\n\t\ttry {\n\t\t\tswitch(args.type) {\n\t\t\t\tcase 'bash':\n\t\t\t\t\treturn await CliTool.fn({command: args.code}, ai);\n\t\t\t\tcase 'node':\n\t\t\t\t\treturn await JSTool.fn({code: args.code}, ai);\n\t\t\t\tcase 'python': {\n\t\t\t\t\treturn await PythonTool.fn({code: args.code}, ai);\n\t\t\t\t}\n\t\t\t}\n\t\t} catch(err: any) {\n\t\t\treturn {error: err?.message || err.toString()};\n\t\t}\n\t}\n}\n\nexport const FetchTool: AiTool = {\n\tname: 'fetch',\n\tdescription: 'Make HTTP request to URL',\n\targs: {\n\t\turl: {type: 'string', description: 'URL to fetch', required: true},\n\t\tmethod: {type: 'string', description: 'HTTP method to use', enum: ['GET', 'POST', 'PUT', 'DELETE'], default: 'GET'},\n\t\theaders: {type: 'object', description: 'HTTP headers to send', default: {}},\n\t\tbody: {type: 'object', description: 'HTTP body to send'},\n\t},\n\tfn: (args: {\n\t\turl: string;\n\t\tmethod: 'GET' | 'POST' | 'PUT' | 'DELETE';\n\t\theaders: {[key: string]: string};\n\t\tbody: any;\n\t}) => new Http({url: args.url, headers: args.headers}).request({method: args.method || 'GET', body: args.body})\n}\n\nexport const JSTool: AiTool = {\n\tname: 'exec_javascript',\n\tdescription: 'Execute commonjs javascript',\n\targs: {\n\t\tcode: {type: 'string', description: 'CommonJS javascript', required: true}\n\t},\n\tfn: async (args: {code: string}) => {\n\t\tconst console = consoleInterceptor(null);\n\t\tconst resp = await Fn<any>({console}, args.code, true).catch((err: any) => console.output.error.push(err));\n\t\treturn {...console.output, return: resp, stdout: undefined, stderr: undefined};\n\t}\n}\n\nexport const PythonTool: AiTool = {\n\tname: 'exec_javascript',\n\tdescription: 'Execute commonjs javascript',\n\targs: {\n\t\tcode: {type: 'string', description: 'CommonJS javascript', required: true}\n\t},\n\tfn: async (args: {code: string}) => ({result: $Sync`python -c \"${args.code}\"`})\n}\n\nexport const SearchTool: AiTool = {\n\tname: 'search',\n\tdescription: 'Use a search engine to find relevant URLs, should be changed with fetch to scrape sources',\n\targs: {\n\t\tquery: {type: 'string', description: 'Search string', required: true},\n\t\tlength: {type: 'string', description: 'Number of results to return', default: 5},\n\t},\n\tfn: async (args: {\n\t\tquery: string;\n\t\tlength: number;\n\t}) => {\n\t\tconst html = await fetch(`https://html.duckduckgo.com/html/?q=${encodeURIComponent(args.query)}`, {\n\t\t\theaders: {\"User-Agent\": \"Mozilla/5.0 (Windows NT 10.0; Win64; x64)\", \"Accept-Language\": \"en-US,en;q=0.9\"}\n\t\t}).then(resp => resp.text());\n\t\tlet match, regex = /<a .*?href=\"(.+?)\".+?<\\/a>/g;\n\t\tconst results = new ASet<string>();\n\t\twhile((match = regex.exec(html)) !== null) {\n\t\t\tlet url = /uddg=(.+)&?/.exec(decodeURIComponent(match[1]))?.[1];\n\t\t\tif(url) url = decodeURIComponent(url);\n\t\t\tif(url) results.add(url);\n\t\t\tif(results.size >= (args.length || 5)) break;\n\t\t}\n\t\treturn results;\n\t}\n}\n"],"names":["LLMProvider","Anthropic","ai","apiToken","model","anthropic","history","i","orgI","c","h","timestamp","message","options","controller","response","res","rej","requestParams","t","objectMap","key","value","resp","loopMessages","chunk","text","last","JSONAttemptParse","toolCalls","userMsg","toolCall","tool","findByProp","result","JSONSanitize","err","combinedContent","m","Ollama","host","ollama","error","rest","system","results","args","r","OpenAi","openAI","tools","tc","record","h2","LLM","max","min","keep","tokens","recent","process","Ai","path","abort","resolve","reject","output","proc","spawn","data","code","p","Path","fs","arr","buffer","worker","createWorker","target","searchTerms","vector","dimensions","char","index","cosineSimilarity","v1","v2","tensor1","tf","tensor2","dotProduct","magnitude1","magnitude2","v","similarities","refVector","acc","s","CliTool","DateTimeTool","ExecTool","JSTool","PythonTool","FetchTool","Http","console","consoleInterceptor","Fn","$Sync","SearchTool","html","match","regex","ASet","url"],"mappings":"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"}
|
package/dist/llm.d.ts
CHANGED
|
@@ -7,7 +7,7 @@ export type LLMMessage = {
|
|
|
7
7
|
/** Message content */
|
|
8
8
|
content: string | any;
|
|
9
9
|
/** Timestamp */
|
|
10
|
-
timestamp
|
|
10
|
+
timestamp?: number;
|
|
11
11
|
} | {
|
|
12
12
|
/** Tool call */
|
|
13
13
|
role: 'tool';
|
|
@@ -22,7 +22,7 @@ export type LLMMessage = {
|
|
|
22
22
|
/** Tool error */
|
|
23
23
|
error: undefined | string;
|
|
24
24
|
/** Timestamp */
|
|
25
|
-
timestamp
|
|
25
|
+
timestamp?: number;
|
|
26
26
|
};
|
|
27
27
|
export type LLMOptions = {
|
|
28
28
|
/** Anthropic settings */
|