@ztimson/ai-utils 0.4.0 → 0.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +16 -16
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const U=require("node:os"),h=require("@ztimson/utils"),$=require("@anthropic-ai/sdk"),L=require("openai"),N=require("worker_threads"),v=require("url"),k=require("path"),W=require("node:child_process"),x=require("node:fs/promises"),J=require("node:path"),
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const U=require("node:os"),h=require("@ztimson/utils"),$=require("@anthropic-ai/sdk"),L=require("openai"),N=require("worker_threads"),v=require("url"),k=require("path"),W=require("node:child_process"),x=require("node:fs/promises"),J=require("node:path"),C=require("tesseract.js");require("./embedder.js");const z=require("cheerio"),S=require("@ztimson/node-utils");var b=typeof document<"u"?document.currentScript:null;function T(l){const t=Object.create(null,{[Symbol.toStringTag]:{value:"Module"}});if(l){for(const e in l)if(e!=="default"){const n=Object.getOwnPropertyDescriptor(l,e);Object.defineProperty(t,e,n.get?n:{enumerable:!0,get:()=>l[e]})}}return t.default=l,Object.freeze(t)}const D=T(U),I=T(z);class _{}class j extends _{constructor(t,e,n){super(),this.ai=t,this.apiToken=e,this.model=n,this.client=new $.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(o=>o.type=="tool_use").forEach(o=>{e++,t.splice(e,0,{role:"tool",id:o.id,name:o.name,args:o.input,timestamp:Date.now()})}):t[n].role=="user"&&t[n].content.filter(o=>o.type=="tool_result").forEach(o=>{const i=t.find(c=>c.id==o.tool_use_id);i[o.is_error?"error":"content"]=o.content}),t[n].content=t[n].content.filter(o=>o.type=="text").map(o=>o.text).join(`
|
|
2
2
|
|
|
3
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,o=new Promise(async(i,c)=>{let s=[...e.history||[],{role:"user",content:t,timestamp:Date.now()}];e.compress&&(s=await this.ai.language.compressHistory(s,e.compress.max,e.compress.min,e)),s=this.fromStandard(s);const u=e.tools||this.ai.options.llm?.tools||[],m={model:e.model||this.model,max_tokens:e.max_tokens||this.ai.options.llm?.max_tokens||4096,system:e.system||this.ai.options.llm?.system||"",temperature:e.temperature||this.ai.options.llm?.temperature||.7,tools:u.map(d=>({name:d.name,description:d.description,input_schema:{type:"object",properties:d.args?h.objectMap(d.args,(a,p)=>({...p,required:void 0})):{},required:d.args?Object.entries(d.args).filter(a=>a[1].required).map(a=>a[0]):[]},fn:void 0})),messages:s,stream:!!e.stream};let r,f=!0;do{if(r=await this.client.messages.create(m).catch(a=>{throw a.message+=`
|
|
4
4
|
|
|
@@ -18,5 +18,5 @@ ${JSON.stringify(s,null,2)}`,a}),e.stream){f?f=!1:e.stream({text:`
|
|
|
18
18
|
`)).flatMap(u=>[...u.split(/\s+/).filter(Boolean),`
|
|
19
19
|
`]),s=[];for(let u=0;u<c.length;){let m="",r=u;for(;r<c.length;){const d=m+(m?" ":"")+c[r];if(this.estimateTokens(d.replace(/\s*\n\s*/g,`
|
|
20
20
|
`))>e&&m)break;m=d,r++}const f=m.replace(/\s*\n\s*/g,`
|
|
21
|
-
`).trim();f&&s.push(f),u=Math.max(r-n,r===u?u+1:r)}return s}embedding(t,e=500,n=50){const o=c=>new Promise((s,u)=>{const m=this.embedId++;this.embedQueue.set(m,{resolve:s,reject:u}),this.embedWorker?.postMessage({id:m,text:c})}),i=this.chunk(t,e,n);return Promise.all(i.map(async(c,s)=>({index:s,embedding:await o(c),text:c,tokens:this.estimateTokens(c)})))}estimateTokens(t){const e=JSON.stringify(t);return Math.ceil(e.length/4*1.2)}fuzzyMatch(t,...e){if(e.length<2)throw new Error("Requires at least 2 strings to compare");const n=(c,s=10)=>c.toLowerCase().split("").map((u,m)=>u.charCodeAt(0)*(m+1)%s/s).slice(0,s),o=n(t),i=e.map(c=>n(c)).map(c=>this.cosineSimilarity(o,c));return{avg:i.reduce((c,s)=>c+s,0)/i.length,max:Math.max(...i),similarities:i}}async json(t,e){let n=await this.ask(t,{system:"Respond using a JSON blob",...e});return n?.[0]?.content?h.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(o=>o.pop()?.content||null)}}class M{constructor(t){this.ai=t,t.options.whisper?.binary&&(this.whisperModel=t.options.whisper?.model.endsWith(".bin")?t.options.whisper?.model:t.options.whisper?.model+".bin",this.downloadAsrModel())}downloads={};whisperModel;asr(t,e=this.whisperModel){if(!this.ai.options.whisper?.binary)throw new Error("Whisper not configured");let n=()=>{};const o=new Promise(async(i,c)=>{const s=await this.downloadAsrModel(e);let u="";const m=W.spawn(this.ai.options.whisper?.binary,["-nt","-np","-m",s,"-f",t],{stdio:["ignore","pipe","ignore"]});n=()=>m.kill("SIGTERM"),m.on("error",r=>c(r)),m.stdout.on("data",r=>u+=r.toString()),m.on("close",r=>{r===0?i(u.trim()||null):c(new Error(`Exit code ${r}`))})});return Object.assign(o,{abort:n})}async downloadAsrModel(t=this.whisperModel){if(!this.ai.options.whisper?.binary)throw new Error("Whisper not configured");t.endsWith(".bin")||(t+=".bin");const e=J.join(this.ai.options.path,t);return await x.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 x.writeFile(e,n),delete this.downloads[t],e)),this.downloads[t])}}class
|
|
21
|
+
`).trim();f&&s.push(f),u=Math.max(r-n,r===u?u+1:r)}return s}embedding(t,e=500,n=50){const o=c=>new Promise((s,u)=>{const m=this.embedId++;this.embedQueue.set(m,{resolve:s,reject:u}),this.embedWorker?.postMessage({id:m,text:c})}),i=this.chunk(t,e,n);return Promise.all(i.map(async(c,s)=>({index:s,embedding:await o(c),text:c,tokens:this.estimateTokens(c)})))}estimateTokens(t){const e=JSON.stringify(t);return Math.ceil(e.length/4*1.2)}fuzzyMatch(t,...e){if(e.length<2)throw new Error("Requires at least 2 strings to compare");const n=(c,s=10)=>c.toLowerCase().split("").map((u,m)=>u.charCodeAt(0)*(m+1)%s/s).slice(0,s),o=n(t),i=e.map(c=>n(c)).map(c=>this.cosineSimilarity(o,c));return{avg:i.reduce((c,s)=>c+s,0)/i.length,max:Math.max(...i),similarities:i}}async json(t,e){let n=await this.ask(t,{system:"Respond using a JSON blob",...e});return n?.[0]?.content?h.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(o=>o.pop()?.content||null)}}class M{constructor(t){this.ai=t,t.options.whisper?.binary&&(this.whisperModel=t.options.whisper?.model.endsWith(".bin")?t.options.whisper?.model:t.options.whisper?.model+".bin",this.downloadAsrModel())}downloads={};whisperModel;asr(t,e=this.whisperModel){if(!this.ai.options.whisper?.binary)throw new Error("Whisper not configured");let n=()=>{};const o=new Promise(async(i,c)=>{const s=await this.downloadAsrModel(e);let u="";const m=W.spawn(this.ai.options.whisper?.binary,["-nt","-np","-m",s,"-f",t],{stdio:["ignore","pipe","ignore"]});n=()=>m.kill("SIGTERM"),m.on("error",r=>c(r)),m.stdout.on("data",r=>u+=r.toString()),m.on("close",r=>{r===0?i(u.trim()||null):c(new Error(`Exit code ${r}`))})});return Object.assign(o,{abort:n})}async downloadAsrModel(t=this.whisperModel){if(!this.ai.options.whisper?.binary)throw new Error("Whisper not configured");t.endsWith(".bin")||(t+=".bin");const e=J.join(this.ai.options.path,t);return await x.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 x.writeFile(e,n),delete this.downloads[t],e)),this.downloads[t])}}class P{constructor(t){this.ai=t}ocr(t){let e;const n=new Promise(async o=>{e=await C.createWorker(this.ai.options.tesseract?.model||"eng",2,{cachePath:this.ai.options.path});const{data:i}=await e.recognize(t);await e.terminate(),o(i.text.trim()||null)});return Object.assign(n,{abort:()=>e?.terminate()})}}class H{constructor(t){this.options=t,t.path||(t.path=D.tmpdir()),process.env.TRANSFORMERS_CACHE=t.path,this.audio=new M(this),this.language=new q(this),this.vision=new P(this)}audio;language;vision}const O={name:"cli",description:"Use the command line interface, returns any output",args:{command:{type:"string",description:"Command to run",required:!0}},fn:l=>S.$`${l.command}`},F={name:"get_datetime",description:"Get current UTC date / time",args:{},fn:async()=>new Date().toUTCString()},B={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(l,t)=>{try{switch(l.type){case"bash":return await O.fn({command:l.code},t);case"node":return await A.fn({code:l.code},t);case"python":return await E.fn({code:l.code},t)}}catch(e){return{error:e?.message||e.toString()}}}},G={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:l=>new h.Http({url:l.url,headers:l.headers}).request({method:l.method||"GET",body:l.body})},A={name:"exec_javascript",description:"Execute commonjs javascript",args:{code:{type:"string",description:"CommonJS javascript",required:!0}},fn:async l=>{const t=h.consoleInterceptor(null),e=await h.fn({console:t},l.code,!0).catch(n=>t.output.error.push(n));return{...t.output,return:e,stdout:void 0,stderr:void 0}}},E={name:"exec_javascript",description:"Execute commonjs javascript",args:{code:{type:"string",description:"CommonJS javascript",required:!0}},fn:async l=>({result:S.$Sync`python -c "${l.code}"`})},Q={name:"read_webpage",description:"Extract clean, structured content from a webpage. Use after web_search to read specific URLs",args:{url:{type:"string",description:"URL to extract content from",required:!0},focus:{type:"string",description:'Optional: What aspect to focus on (e.g., "pricing", "features", "contact info")'}},fn:async l=>{const t=await fetch(l.url,{headers:{"User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64)"}}).then(c=>c.text()).catch(c=>{throw new Error(`Failed to fetch: ${c.message}`)}),e=I.load(t);e('script, style, nav, footer, header, aside, iframe, noscript, [role="navigation"], [role="banner"], .ad, .ads, .cookie, .popup').remove();const n={title:e('meta[property="og:title"]').attr("content")||e("title").text()||"",description:e('meta[name="description"]').attr("content")||e('meta[property="og:description"]').attr("content")||""};let o="";const i=["article","main",'[role="main"]',".content",".post",".entry","body"];for(const c of i){const s=e(c).first();if(s.length&&s.text().trim().length>200){o=s.text();break}}return o||(o=e("body").text()),o=o.replace(/\s+/g," ").trim().slice(0,8e3),{url:l.url,title:n.title.trim(),description:n.description.trim(),content:o,focus:l.focus}}},V={name:"web_search",description:"Use duckduckgo (anonymous) to find find relevant online resources. Returns a list of URLs that works great with the `read_webpage` tool",args:{query:{type:"string",description:"Search string",required:!0},length:{type:"string",description:"Number of results to return",default:5}},fn:async l=>{const t=await fetch(`https://html.duckduckgo.com/html/?q=${encodeURIComponent(l.query)}`,{headers:{"User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64)","Accept-Language":"en-US,en;q=0.9"}}).then(i=>i.text());let e,n=/<a .*?href="(.+?)".+?<\/a>/g;const o=new h.ASet;for(;(e=n.exec(t))!==null;){let i=/uddg=(.+)&?/.exec(decodeURIComponent(e[1]))?.[1];if(i&&(i=decodeURIComponent(i)),i&&o.add(i),o.size>=(l.length||5))break}return o}};exports.Ai=H;exports.Anthropic=j;exports.Audio=M;exports.CliTool=O;exports.DateTimeTool=F;exports.ExecTool=B;exports.FetchTool=G;exports.JSTool=A;exports.LLM=q;exports.LLMProvider=_;exports.OpenAi=y;exports.PythonTool=E;exports.ReadWebpageTool=Q;exports.Vision=P;exports.WebSearchTool=V;
|
|
22
22
|
//# 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/open-ai.ts","../src/llm.ts","../src/audio.ts","../src/vision.ts","../src/ai.ts","../src/tools.ts"],"sourcesContent":["import {AbortablePromise} from './ai.ts';\nimport {LLMMessage, LLMRequest} from './llm.ts';\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 {AbortablePromise, Ai} from './ai.ts';\nimport {LLMMessage, LLMRequest} from './llm.ts';\nimport {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 = [...options.history || [], {role: 'user', content: message, timestamp: Date.now()}];\n\t\t\tif(options.compress) history = await this.ai.language.compressHistory(<any>history, options.compress.max, options.compress.min, options);\n\t\t\thistory = this.fromStandard(<any>history);\n\n\t\t\tconst tools = options.tools || this.ai.options.llm?.tools || [];\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.llm?.max_tokens || 4096,\n\t\t\t\tsystem: options.system || this.ai.options.llm?.system || '',\n\t\t\t\ttemperature: options.temperature || this.ai.options.llm?.temperature || 0.7,\n\t\t\t\ttools: 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, isFirstMessage = true;\n\t\t\tconst assistantMessages: string[] = [];\n\t\t\tdo {\n\t\t\t\tresp = await this.client.messages.create(requestParams).catch(err => {\n\t\t\t\t\terr.message += `\\n\\nMessages:\\n${JSON.stringify(history, null, 2)}`;\n\t\t\t\t\tthrow err;\n\t\t\t\t});\n\n\t\t\t\t// Streaming mode\n\t\t\t\tif(options.stream) {\n\t\t\t\t\tif(!isFirstMessage) options.stream({text: '\\n\\n'});\n\t\t\t\t\telse isFirstMessage = false;\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\t// Run tools\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 = tools.find(findByProp('name', toolCall.name));\n\t\t\t\t\t\tif(options.stream) options.stream({tool: 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\thistory.push({role: 'user', content: results});\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\tif(options.stream) options.stream({done: true});\n\t\t\tres(this.toStandard([...history, {role: 'assistant', content: resp.content.filter((c: any) => c.type == 'text').map((c: any) => c.text).join('\\n\\n')}]));\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, clean} from '@ztimson/utils';\nimport {AbortablePromise, Ai} from './ai.ts';\nimport {LLMMessage, LLMRequest} from './llm.ts';\nimport {LLMProvider} from './provider.ts';\n\nexport class OpenAi extends LLMProvider {\n\tclient!: openAI;\n\n\tconstructor(public readonly ai: Ai, public readonly host: string | null, public readonly token: string, public model: string) {\n\t\tsuper();\n\t\tthis.client = new openAI(clean({\n\t\t\tbaseURL: host,\n\t\t\tapiKey: token\n\t\t}));\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 = [...options.history || [], {role: 'user', content: message, timestamp: Date.now()}];\n\t\t\tif(options.compress) history = await this.ai.language.compressHistory(<any>history, options.compress.max, options.compress.min, options);\n\t\t\thistory = this.fromStandard(<any>history);\n\n\t\t\tconst tools = options.tools || this.ai.options.llm?.tools || [];\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.llm?.max_tokens || 4096,\n\t\t\t\ttemperature: options.temperature || this.ai.options.llm?.temperature || 0.7,\n\t\t\t\ttools: 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, isFirstMessage = true;\n\t\t\tdo {\n\t\t\t\tresp = await this.client.chat.completions.create(requestParams).catch(err => {\n\t\t\t\t\terr.message += `\\n\\nMessages:\\n${JSON.stringify(history, null, 2)}`;\n\t\t\t\t\tthrow err;\n\t\t\t\t});\n\n\t\t\t\tif(options.stream) {\n\t\t\t\t\tif(!isFirstMessage) options.stream({text: '\\n\\n'});\n\t\t\t\t\telse isFirstMessage = false;\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\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 = tools?.find(findByProp('name', toolCall.function.name));\n\t\t\t\t\t\tif(options.stream) options.stream({tool: 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\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\tif(options.stream) options.stream({done: true});\n\t\t\tres(this.toStandard([...history, {role: 'assistant', content: resp.choices[0].message.content || ''}]));\n\t\t});\n\t\treturn Object.assign(response, {abort: () => controller.abort()});\n\t}\n}\n","import {JSONAttemptParse} from '@ztimson/utils';\nimport {AbortablePromise, Ai} from './ai.ts';\nimport {Anthropic} from './antrhopic.ts';\nimport {OpenAi} from './open-ai.ts';\nimport {LLMProvider} from './provider.ts';\nimport {AiTool} from './tools.ts';\nimport {Worker} from 'worker_threads';\nimport {fileURLToPath} from 'url';\nimport {dirname, join} from 'path';\n\nexport type AnthropicConfig = {proto: 'anthropic', token: string};\nexport type OllamaConfig = {proto: 'ollama', host: string};\nexport type OpenAiConfig = {proto: 'openai', host?: string, token: string};\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 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;\n\t/** Stream response */\n\tstream?: (chunk: {text?: string, tool?: 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 embedWorker: Worker | null = null;\n\tprivate embedQueue = new Map<number, { resolve: (value: number[]) => void; reject: (error: any) => void }>();\n\tprivate embedId = 0;\n\tprivate models: {[model: string]: LLMProvider} = {};\n\tprivate defaultModel!: string;\n\n\tconstructor(public readonly ai: Ai) {\n\t\tthis.embedWorker = new Worker(join(dirname(fileURLToPath(import.meta.url)), 'embedder.js'));\n\t\tthis.embedWorker.on('message', ({ id, embedding }) => {\n\t\t\tconst pending = this.embedQueue.get(id);\n\t\t\tif (pending) {\n\t\t\t\tpending.resolve(embedding);\n\t\t\t\tthis.embedQueue.delete(id);\n\t\t\t}\n\t\t});\n\n\t\tif(!ai.options.llm?.models) return;\n\t\tObject.entries(ai.options.llm.models).forEach(([model, config]) => {\n\t\t\tif(!this.defaultModel) this.defaultModel = model;\n\t\t\tif(config.proto == 'anthropic') this.models[model] = new Anthropic(this.ai, config.token, model);\n\t\t\telse if(config.proto == 'ollama') this.models[model] = new OpenAi(this.ai, config.host, 'not-needed', model);\n\t\t\telse if(config.proto == 'openai') this.models[model] = new OpenAi(this.ai, config.host || null, config.token, model);\n\t\t});\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\tconst m = options.model || this.defaultModel;\n\t\tif(!this.models[m]) throw new Error(`Model does not exist: ${m}`);\n\t\treturn this.models[m].ask(message, options);\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 compressHistory(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\tcosineSimilarity(v1: number[], v2: number[]): number {\n\t\tif (v1.length !== v2.length) throw new Error('Vectors must be same length');\n\t\tlet dotProduct = 0, normA = 0, normB = 0;\n\t\tfor (let i = 0; i < v1.length; i++) {\n\t\t\tdotProduct += v1[i] * v2[i];\n\t\t\tnormA += v1[i] * v1[i];\n\t\t\tnormB += v2[i] * v2[i];\n\t\t}\n\t\tconst denominator = Math.sqrt(normA) * Math.sqrt(normB);\n\t\treturn denominator === 0 ? 0 : dotProduct / denominator;\n\t}\n\n\tchunk(target: object | string, maxTokens = 500, overlapTokens = 50): string[] {\n\t\tconst objString = (obj: any, path = ''): string[] => {\n\t\t\tif(!obj) return [];\n\t\t\treturn Object.entries(obj).flatMap(([key, value]) => {\n\t\t\t\tconst p = path ? `${path}${isNaN(+key) ? `.${key}` : `[${key}]`}` : key;\n\t\t\t\tif(typeof value === 'object' && !Array.isArray(value)) return objString(value, p);\n\t\t\t\treturn `${p}: ${Array.isArray(value) ? value.join(', ') : value}`;\n\t\t\t});\n\t\t};\n\n\t\tconst lines = typeof target === 'object' ? objString(target) : target.split('\\n');\n\t\tconst tokens = lines.flatMap(l => [...l.split(/\\s+/).filter(Boolean), '\\n']);\n\t\tconst chunks: string[] = [];\n\t\tfor(let i = 0; i < tokens.length;) {\n\t\t\tlet text = '', j = i;\n\t\t\twhile(j < tokens.length) {\n\t\t\t\tconst next = text + (text ? ' ' : '') + tokens[j];\n\t\t\t\tif(this.estimateTokens(next.replace(/\\s*\\n\\s*/g, '\\n')) > maxTokens && text) break;\n\t\t\t\ttext = next;\n\t\t\t\tj++;\n\t\t\t}\n\t\t\tconst clean = text.replace(/\\s*\\n\\s*/g, '\\n').trim();\n\t\t\tif(clean) chunks.push(clean);\n\t\t\ti = Math.max(j - overlapTokens, j === i ? i + 1 : j);\n\t\t}\n\t\treturn chunks;\n\t}\n\n\tembedding(target: object | string, maxTokens = 500, overlapTokens = 50) {\n\t\tconst embed = (text: string): Promise<number[]> => {\n\t\t\treturn new Promise((resolve, reject) => {\n\t\t\t\tconst id = this.embedId++;\n\t\t\t\tthis.embedQueue.set(id, { resolve, reject });\n\t\t\t\tthis.embedWorker?.postMessage({ id, text });\n\t\t\t});\n\t\t};\n\n\t\tconst chunks = this.chunk(target, maxTokens, overlapTokens);\n\t\treturn Promise.all(chunks.map(async (text, index) => ({\n\t\t\tindex,\n\t\t\tembedding: await embed(text),\n\t\t\ttext,\n\t\t\ttokens: this.estimateTokens(text),\n\t\t})));\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 * 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\tfuzzyMatch(target: string, ...searchTerms: string[]) {\n\t\tif(searchTerms.length < 2) throw new Error('Requires at least 2 strings to compare');\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\t\tconst v = vector(target);\n\t\tconst similarities = searchTerms.map(t => vector(t)).map(refVector => this.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\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 {spawn} from 'node:child_process';\nimport fs from 'node:fs/promises';\nimport Path from 'node:path';\nimport {AbortablePromise, Ai} from './ai.ts';\n\nexport class Audio {\n\tprivate downloads: {[key: string]: Promise<string>} = {};\n\tprivate whisperModel!: string;\n\n\tconstructor(private ai: Ai) {\n\t\tif(ai.options.whisper?.binary) {\n\t\t\tthis.whisperModel = ai.options.whisper?.model.endsWith('.bin') ? ai.options.whisper?.model : ai.options.whisper?.model + '.bin';\n\t\t\tthis.downloadAsrModel();\n\t\t}\n\t}\n\n\tasr(path: string, model: string = this.whisperModel): AbortablePromise<string | null> {\n\t\tif(!this.ai.options.whisper?.binary) throw new Error('Whisper not configured');\n\t\tlet abort: any = () => {};\n\t\tconst p = new Promise<string | null>(async (resolve, reject) => {\n\t\t\tconst m = await this.downloadAsrModel(model);\n\t\t\tlet output = '';\n\t\t\tconst proc = spawn(<string>this.ai.options.whisper?.binary, ['-nt', '-np', '-m', m, '-f', path], {stdio: ['ignore', 'pipe', 'ignore']});\n\t\t\tabort = () => proc.kill('SIGTERM');\n\t\t\tproc.on('error', (err: Error) => reject(err));\n\t\t\tproc.stdout.on('data', (data: Buffer) => output += data.toString());\n\t\t\tproc.on('close', (code: number) => {\n\t\t\t\tif(code === 0) resolve(output.trim() || null);\n\t\t\t\telse reject(new Error(`Exit code ${code}`));\n\t\t\t});\n\t\t});\n\t\treturn Object.assign(p, {abort});\n\t}\n\n\tasync downloadAsrModel(model: string = this.whisperModel): Promise<string> {\n\t\tif(!this.ai.options.whisper?.binary) throw new Error('Whisper not configured');\n\t\tif(!model.endsWith('.bin')) model += '.bin';\n\t\tconst p = Path.join(<string>this.ai.options.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","import {createWorker} from 'tesseract.js';\nimport {AbortablePromise, Ai} from './ai.ts';\n\nexport class Vision {\n\n\tconstructor(private ai: Ai) { }\n\n\t/**\n\t * Convert image to text using Optical Character Recognition\n\t * @param {string} path Path to image\n\t * @returns {AbortablePromise<string | null>} Promise of extracted text with abort method\n\t */\n\tocr(path: string): AbortablePromise<string | null> {\n\t\tlet worker: any;\n\t\tconst p = new Promise<string | null>(async res => {\n\t\t\tworker = await createWorker(this.ai.options.tesseract?.model || 'eng', 2, {cachePath: this.ai.options.path});\n\t\t\tconst {data} = await worker.recognize(path);\n\t\t\tawait worker.terminate();\n\t\t\tres(data.text.trim() || null);\n\t\t});\n\t\treturn Object.assign(p, {abort: () => worker?.terminate()});\n\t}\n}\n","import * as os from 'node:os';\nimport {LLM, AnthropicConfig, OllamaConfig, OpenAiConfig, LLMRequest} from './llm';\nimport { Audio } from './audio.ts';\nimport {Vision} from './vision.ts';\n\nexport type AbortablePromise<T> = Promise<T> & {abort: () => any};\n\nexport type AiOptions = {\n\t/** Path to models */\n\tpath?: string;\n\t/** Large language models, first is default */\n\tllm?: Omit<LLMRequest, 'model'> & {\n\t\tmodels: {[model: string]: AnthropicConfig | OllamaConfig | OpenAiConfig};\n\t}\n\t/** Tesseract OCR configuration */\n\ttesseract?: {\n\t\t/** Model: eng, eng_best, eng_fast */\n\t\tmodel?: string;\n\t}\n\t/** Whisper ASR configuration */\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}\n}\n\nexport class Ai {\n\t/** Audio processing AI */\n\taudio!: Audio;\n\t/** Language processing AI */\n\tlanguage!: LLM;\n\t/** Vision processing AI */\n\tvision!: Vision;\n\n\tconstructor(public readonly options: AiOptions) {\n\t\tif(!options.path) options.path = os.tmpdir();\n\t\tprocess.env.TRANSFORMERS_CACHE = options.path;\n\t\tthis.audio = new Audio(this);\n\t\tthis.language = new LLM(this);\n\t\tthis.vision = new Vision(this);\n\t}\n}\n","import * as cheerio from 'cheerio';\nimport {$, $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 ReadWebpageTool: AiTool = {\n\tname: 'read_webpage',\n\tdescription: 'Extract clean, structured content from a webpage. Use after web_search to read specific URLs',\n\targs: {\n\t\turl: {type: 'string', description: 'URL to extract content from', required: true},\n\t\tfocus: {type: 'string', description: 'Optional: What aspect to focus on (e.g., \"pricing\", \"features\", \"contact info\")'}\n\t},\n\tfn: async (args: {url: string; focus?: string}) => {\n\t\tconst html = await fetch(args.url, {headers: {\"User-Agent\": \"Mozilla/5.0 (Windows NT 10.0; Win64; x64)\"}})\n\t\t\t.then(r => r.text()).catch(err => {throw new Error(`Failed to fetch: ${err.message}`)});\n\n\t\tconst $ = cheerio.load(html);\n\t\t$('script, style, nav, footer, header, aside, iframe, noscript, [role=\"navigation\"], [role=\"banner\"], .ad, .ads, .cookie, .popup').remove();\n\t\tconst metadata = {\n\t\t\ttitle: $('meta[property=\"og:title\"]').attr('content') || $('title').text() || '',\n\t\t\tdescription: $('meta[name=\"description\"]').attr('content') || $('meta[property=\"og:description\"]').attr('content') || '',\n\t\t};\n\n\t\tlet content = '';\n\t\tconst contentSelectors = ['article', 'main', '[role=\"main\"]', '.content', '.post', '.entry', 'body'];\n\t\tfor (const selector of contentSelectors) {\n\t\t\tconst el = $(selector).first();\n\t\t\tif (el.length && el.text().trim().length > 200) {\n\t\t\t\tcontent = el.text();\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tif (!content) content = $('body').text();\n\t\tcontent = content.replace(/\\s+/g, ' ').trim().slice(0, 8000);\n\n\t\treturn {url: args.url, title: metadata.title.trim(), description: metadata.description.trim(), content, focus: args.focus};\n\t}\n}\n\nexport const WebSearchTool: AiTool = {\n\tname: 'web_search',\n\tdescription: 'Use duckduckgo (anonymous) to find find relevant online resources. Returns a list of URLs that works great with the `read_webpage` tool',\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","tools","requestParams","t","objectMap","key","value","resp","isFirstMessage","err","chunk","text","last","JSONAttemptParse","toolCalls","results","toolCall","tool","findByProp","result","JSONSanitize","OpenAi","host","token","openAI","clean","tc","record","h2","rest","args","LLM","Worker","join","dirname","fileURLToPath","_documentCurrentScript","id","embedding","pending","config","m","max","min","keep","tokens","recent","process","v1","v2","dotProduct","normA","normB","denominator","target","maxTokens","overlapTokens","objString","obj","path","p","l","chunks","j","next","embed","resolve","reject","index","searchTerms","vector","dimensions","char","v","similarities","refVector","acc","Audio","abort","output","proc","spawn","data","code","Path","fs","arr","buffer","Vision","worker","createWorker","Ai","os","CliTool","$","DateTimeTool","ExecTool","JSTool","PythonTool","FetchTool","Http","console","consoleInterceptor","Fn","$Sync","ReadWebpageTool","html","r","cheerio","metadata","content","contentSelectors","selector","el","WebSearchTool","match","regex","ASet","url"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../src/provider.ts","../src/antrhopic.ts","../src/open-ai.ts","../src/llm.ts","../src/audio.ts","../src/vision.ts","../src/ai.ts","../src/tools.ts"],"sourcesContent":["import {AbortablePromise} from './ai.ts';\nimport {LLMMessage, LLMRequest} from './llm.ts';\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 {AbortablePromise, Ai} from './ai.ts';\nimport {LLMMessage, LLMRequest} from './llm.ts';\nimport {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 = [...options.history || [], {role: 'user', content: message, timestamp: Date.now()}];\n\t\t\tif(options.compress) history = await this.ai.language.compressHistory(<any>history, options.compress.max, options.compress.min, options);\n\t\t\thistory = this.fromStandard(<any>history);\n\n\t\t\tconst tools = options.tools || this.ai.options.llm?.tools || [];\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.llm?.max_tokens || 4096,\n\t\t\t\tsystem: options.system || this.ai.options.llm?.system || '',\n\t\t\t\ttemperature: options.temperature || this.ai.options.llm?.temperature || 0.7,\n\t\t\t\ttools: 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, isFirstMessage = true;\n\t\t\tconst assistantMessages: string[] = [];\n\t\t\tdo {\n\t\t\t\tresp = await this.client.messages.create(requestParams).catch(err => {\n\t\t\t\t\terr.message += `\\n\\nMessages:\\n${JSON.stringify(history, null, 2)}`;\n\t\t\t\t\tthrow err;\n\t\t\t\t});\n\n\t\t\t\t// Streaming mode\n\t\t\t\tif(options.stream) {\n\t\t\t\t\tif(!isFirstMessage) options.stream({text: '\\n\\n'});\n\t\t\t\t\telse isFirstMessage = false;\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\t// Run tools\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 = tools.find(findByProp('name', toolCall.name));\n\t\t\t\t\t\tif(options.stream) options.stream({tool: 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\thistory.push({role: 'user', content: results});\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\tif(options.stream) options.stream({done: true});\n\t\t\tres(this.toStandard([...history, {role: 'assistant', content: resp.content.filter((c: any) => c.type == 'text').map((c: any) => c.text).join('\\n\\n')}]));\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, clean} from '@ztimson/utils';\nimport {AbortablePromise, Ai} from './ai.ts';\nimport {LLMMessage, LLMRequest} from './llm.ts';\nimport {LLMProvider} from './provider.ts';\n\nexport class OpenAi extends LLMProvider {\n\tclient!: openAI;\n\n\tconstructor(public readonly ai: Ai, public readonly host: string | null, public readonly token: string, public model: string) {\n\t\tsuper();\n\t\tthis.client = new openAI(clean({\n\t\t\tbaseURL: host,\n\t\t\tapiKey: token\n\t\t}));\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 = [...options.history || [], {role: 'user', content: message, timestamp: Date.now()}];\n\t\t\tif(options.compress) history = await this.ai.language.compressHistory(<any>history, options.compress.max, options.compress.min, options);\n\t\t\thistory = this.fromStandard(<any>history);\n\n\t\t\tconst tools = options.tools || this.ai.options.llm?.tools || [];\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.llm?.max_tokens || 4096,\n\t\t\t\ttemperature: options.temperature || this.ai.options.llm?.temperature || 0.7,\n\t\t\t\ttools: 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, isFirstMessage = true;\n\t\t\tdo {\n\t\t\t\tresp = await this.client.chat.completions.create(requestParams).catch(err => {\n\t\t\t\t\terr.message += `\\n\\nMessages:\\n${JSON.stringify(history, null, 2)}`;\n\t\t\t\t\tthrow err;\n\t\t\t\t});\n\n\t\t\t\tif(options.stream) {\n\t\t\t\t\tif(!isFirstMessage) options.stream({text: '\\n\\n'});\n\t\t\t\t\telse isFirstMessage = false;\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\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 = tools?.find(findByProp('name', toolCall.function.name));\n\t\t\t\t\t\tif(options.stream) options.stream({tool: 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\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\tif(options.stream) options.stream({done: true});\n\t\t\tres(this.toStandard([...history, {role: 'assistant', content: resp.choices[0].message.content || ''}]));\n\t\t});\n\t\treturn Object.assign(response, {abort: () => controller.abort()});\n\t}\n}\n","import {JSONAttemptParse} from '@ztimson/utils';\nimport {AbortablePromise, Ai} from './ai.ts';\nimport {Anthropic} from './antrhopic.ts';\nimport {OpenAi} from './open-ai.ts';\nimport {LLMProvider} from './provider.ts';\nimport {AiTool} from './tools.ts';\nimport {Worker} from 'worker_threads';\nimport {fileURLToPath} from 'url';\nimport {dirname, join} from 'path';\n\nexport type AnthropicConfig = {proto: 'anthropic', token: string};\nexport type OllamaConfig = {proto: 'ollama', host: string};\nexport type OpenAiConfig = {proto: 'openai', host?: string, token: string};\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 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;\n\t/** Stream response */\n\tstream?: (chunk: {text?: string, tool?: 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 embedWorker: Worker | null = null;\n\tprivate embedQueue = new Map<number, { resolve: (value: number[]) => void; reject: (error: any) => void }>();\n\tprivate embedId = 0;\n\tprivate models: {[model: string]: LLMProvider} = {};\n\tprivate defaultModel!: string;\n\n\tconstructor(public readonly ai: Ai) {\n\t\tthis.embedWorker = new Worker(join(dirname(fileURLToPath(import.meta.url)), 'embedder.js'));\n\t\tthis.embedWorker.on('message', ({ id, embedding }) => {\n\t\t\tconst pending = this.embedQueue.get(id);\n\t\t\tif (pending) {\n\t\t\t\tpending.resolve(embedding);\n\t\t\t\tthis.embedQueue.delete(id);\n\t\t\t}\n\t\t});\n\n\t\tif(!ai.options.llm?.models) return;\n\t\tObject.entries(ai.options.llm.models).forEach(([model, config]) => {\n\t\t\tif(!this.defaultModel) this.defaultModel = model;\n\t\t\tif(config.proto == 'anthropic') this.models[model] = new Anthropic(this.ai, config.token, model);\n\t\t\telse if(config.proto == 'ollama') this.models[model] = new OpenAi(this.ai, config.host, 'not-needed', model);\n\t\t\telse if(config.proto == 'openai') this.models[model] = new OpenAi(this.ai, config.host || null, config.token, model);\n\t\t});\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\tconst m = options.model || this.defaultModel;\n\t\tif(!this.models[m]) throw new Error(`Model does not exist: ${m}`);\n\t\treturn this.models[m].ask(message, options);\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 compressHistory(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\tcosineSimilarity(v1: number[], v2: number[]): number {\n\t\tif (v1.length !== v2.length) throw new Error('Vectors must be same length');\n\t\tlet dotProduct = 0, normA = 0, normB = 0;\n\t\tfor (let i = 0; i < v1.length; i++) {\n\t\t\tdotProduct += v1[i] * v2[i];\n\t\t\tnormA += v1[i] * v1[i];\n\t\t\tnormB += v2[i] * v2[i];\n\t\t}\n\t\tconst denominator = Math.sqrt(normA) * Math.sqrt(normB);\n\t\treturn denominator === 0 ? 0 : dotProduct / denominator;\n\t}\n\n\tchunk(target: object | string, maxTokens = 500, overlapTokens = 50): string[] {\n\t\tconst objString = (obj: any, path = ''): string[] => {\n\t\t\tif(!obj) return [];\n\t\t\treturn Object.entries(obj).flatMap(([key, value]) => {\n\t\t\t\tconst p = path ? `${path}${isNaN(+key) ? `.${key}` : `[${key}]`}` : key;\n\t\t\t\tif(typeof value === 'object' && !Array.isArray(value)) return objString(value, p);\n\t\t\t\treturn `${p}: ${Array.isArray(value) ? value.join(', ') : value}`;\n\t\t\t});\n\t\t};\n\n\t\tconst lines = typeof target === 'object' ? objString(target) : target.split('\\n');\n\t\tconst tokens = lines.flatMap(l => [...l.split(/\\s+/).filter(Boolean), '\\n']);\n\t\tconst chunks: string[] = [];\n\t\tfor(let i = 0; i < tokens.length;) {\n\t\t\tlet text = '', j = i;\n\t\t\twhile(j < tokens.length) {\n\t\t\t\tconst next = text + (text ? ' ' : '') + tokens[j];\n\t\t\t\tif(this.estimateTokens(next.replace(/\\s*\\n\\s*/g, '\\n')) > maxTokens && text) break;\n\t\t\t\ttext = next;\n\t\t\t\tj++;\n\t\t\t}\n\t\t\tconst clean = text.replace(/\\s*\\n\\s*/g, '\\n').trim();\n\t\t\tif(clean) chunks.push(clean);\n\t\t\ti = Math.max(j - overlapTokens, j === i ? i + 1 : j);\n\t\t}\n\t\treturn chunks;\n\t}\n\n\tembedding(target: object | string, maxTokens = 500, overlapTokens = 50) {\n\t\tconst embed = (text: string): Promise<number[]> => {\n\t\t\treturn new Promise((resolve, reject) => {\n\t\t\t\tconst id = this.embedId++;\n\t\t\t\tthis.embedQueue.set(id, { resolve, reject });\n\t\t\t\tthis.embedWorker?.postMessage({ id, text });\n\t\t\t});\n\t\t};\n\n\t\tconst chunks = this.chunk(target, maxTokens, overlapTokens);\n\t\treturn Promise.all(chunks.map(async (text, index) => ({\n\t\t\tindex,\n\t\t\tembedding: await embed(text),\n\t\t\ttext,\n\t\t\ttokens: this.estimateTokens(text),\n\t\t})));\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 * 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\tfuzzyMatch(target: string, ...searchTerms: string[]) {\n\t\tif(searchTerms.length < 2) throw new Error('Requires at least 2 strings to compare');\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\t\tconst v = vector(target);\n\t\tconst similarities = searchTerms.map(t => vector(t)).map(refVector => this.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\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 {spawn} from 'node:child_process';\nimport fs from 'node:fs/promises';\nimport Path from 'node:path';\nimport {AbortablePromise, Ai} from './ai.ts';\n\nexport class Audio {\n\tprivate downloads: {[key: string]: Promise<string>} = {};\n\tprivate whisperModel!: string;\n\n\tconstructor(private ai: Ai) {\n\t\tif(ai.options.whisper?.binary) {\n\t\t\tthis.whisperModel = ai.options.whisper?.model.endsWith('.bin') ? ai.options.whisper?.model : ai.options.whisper?.model + '.bin';\n\t\t\tthis.downloadAsrModel();\n\t\t}\n\t}\n\n\tasr(path: string, model: string = this.whisperModel): AbortablePromise<string | null> {\n\t\tif(!this.ai.options.whisper?.binary) throw new Error('Whisper not configured');\n\t\tlet abort: any = () => {};\n\t\tconst p = new Promise<string | null>(async (resolve, reject) => {\n\t\t\tconst m = await this.downloadAsrModel(model);\n\t\t\tlet output = '';\n\t\t\tconst proc = spawn(<string>this.ai.options.whisper?.binary, ['-nt', '-np', '-m', m, '-f', path], {stdio: ['ignore', 'pipe', 'ignore']});\n\t\t\tabort = () => proc.kill('SIGTERM');\n\t\t\tproc.on('error', (err: Error) => reject(err));\n\t\t\tproc.stdout.on('data', (data: Buffer) => output += data.toString());\n\t\t\tproc.on('close', (code: number) => {\n\t\t\t\tif(code === 0) resolve(output.trim() || null);\n\t\t\t\telse reject(new Error(`Exit code ${code}`));\n\t\t\t});\n\t\t});\n\t\treturn Object.assign(p, {abort});\n\t}\n\n\tasync downloadAsrModel(model: string = this.whisperModel): Promise<string> {\n\t\tif(!this.ai.options.whisper?.binary) throw new Error('Whisper not configured');\n\t\tif(!model.endsWith('.bin')) model += '.bin';\n\t\tconst p = Path.join(<string>this.ai.options.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","import {createWorker} from 'tesseract.js';\nimport {AbortablePromise, Ai} from './ai.ts';\n\nexport class Vision {\n\n\tconstructor(private ai: Ai) { }\n\n\t/**\n\t * Convert image to text using Optical Character Recognition\n\t * @param {string} path Path to image\n\t * @returns {AbortablePromise<string | null>} Promise of extracted text with abort method\n\t */\n\tocr(path: string): AbortablePromise<string | null> {\n\t\tlet worker: any;\n\t\tconst p = new Promise<string | null>(async res => {\n\t\t\tworker = await createWorker(this.ai.options.tesseract?.model || 'eng', 2, {cachePath: this.ai.options.path});\n\t\t\tconst {data} = await worker.recognize(path);\n\t\t\tawait worker.terminate();\n\t\t\tres(data.text.trim() || null);\n\t\t});\n\t\treturn Object.assign(p, {abort: () => worker?.terminate()});\n\t}\n}\n","import * as os from 'node:os';\nimport {LLM, AnthropicConfig, OllamaConfig, OpenAiConfig, LLMRequest} from './llm';\nimport { Audio } from './audio.ts';\nimport {Vision} from './vision.ts';\n\nexport type AbortablePromise<T> = Promise<T> & {abort: () => any};\n\nexport type AiOptions = {\n\t/** Path to models */\n\tpath?: string;\n\t/** Large language models, first is default */\n\tllm?: Omit<LLMRequest, 'model'> & {\n\t\tmodels: {[model: string]: AnthropicConfig | OllamaConfig | OpenAiConfig};\n\t}\n\t/** Tesseract OCR configuration */\n\ttesseract?: {\n\t\t/** Model: eng, eng_best, eng_fast */\n\t\tmodel?: string;\n\t}\n\t/** Whisper ASR configuration */\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}\n}\n\nexport class Ai {\n\t/** Audio processing AI */\n\taudio!: Audio;\n\t/** Language processing AI */\n\tlanguage!: LLM;\n\t/** Vision processing AI */\n\tvision!: Vision;\n\n\tconstructor(public readonly options: AiOptions) {\n\t\tif(!options.path) options.path = os.tmpdir();\n\t\tprocess.env.TRANSFORMERS_CACHE = options.path;\n\t\tthis.audio = new Audio(this);\n\t\tthis.language = new LLM(this);\n\t\tthis.vision = new Vision(this);\n\t}\n}\n","import * as cheerio from 'cheerio';\nimport {$, $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 UTC date / time',\n\targs: {},\n\tfn: async () => new Date().toUTCString()\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 ReadWebpageTool: AiTool = {\n\tname: 'read_webpage',\n\tdescription: 'Extract clean, structured content from a webpage. Use after web_search to read specific URLs',\n\targs: {\n\t\turl: {type: 'string', description: 'URL to extract content from', required: true},\n\t\tfocus: {type: 'string', description: 'Optional: What aspect to focus on (e.g., \"pricing\", \"features\", \"contact info\")'}\n\t},\n\tfn: async (args: {url: string; focus?: string}) => {\n\t\tconst html = await fetch(args.url, {headers: {\"User-Agent\": \"Mozilla/5.0 (Windows NT 10.0; Win64; x64)\"}})\n\t\t\t.then(r => r.text()).catch(err => {throw new Error(`Failed to fetch: ${err.message}`)});\n\n\t\tconst $ = cheerio.load(html);\n\t\t$('script, style, nav, footer, header, aside, iframe, noscript, [role=\"navigation\"], [role=\"banner\"], .ad, .ads, .cookie, .popup').remove();\n\t\tconst metadata = {\n\t\t\ttitle: $('meta[property=\"og:title\"]').attr('content') || $('title').text() || '',\n\t\t\tdescription: $('meta[name=\"description\"]').attr('content') || $('meta[property=\"og:description\"]').attr('content') || '',\n\t\t};\n\n\t\tlet content = '';\n\t\tconst contentSelectors = ['article', 'main', '[role=\"main\"]', '.content', '.post', '.entry', 'body'];\n\t\tfor (const selector of contentSelectors) {\n\t\t\tconst el = $(selector).first();\n\t\t\tif (el.length && el.text().trim().length > 200) {\n\t\t\t\tcontent = el.text();\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tif (!content) content = $('body').text();\n\t\tcontent = content.replace(/\\s+/g, ' ').trim().slice(0, 8000);\n\n\t\treturn {url: args.url, title: metadata.title.trim(), description: metadata.description.trim(), content, focus: args.focus};\n\t}\n}\n\nexport const WebSearchTool: AiTool = {\n\tname: 'web_search',\n\tdescription: 'Use duckduckgo (anonymous) to find find relevant online resources. Returns a list of URLs that works great with the `read_webpage` tool',\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","tools","requestParams","t","objectMap","key","value","resp","isFirstMessage","err","chunk","text","last","JSONAttemptParse","toolCalls","results","toolCall","tool","findByProp","result","JSONSanitize","OpenAi","host","token","openAI","clean","tc","record","h2","rest","args","LLM","Worker","join","dirname","fileURLToPath","_documentCurrentScript","id","embedding","pending","config","m","max","min","keep","tokens","recent","process","v1","v2","dotProduct","normA","normB","denominator","target","maxTokens","overlapTokens","objString","obj","path","p","l","chunks","j","next","embed","resolve","reject","index","searchTerms","vector","dimensions","char","v","similarities","refVector","acc","Audio","abort","output","proc","spawn","data","code","Path","fs","arr","buffer","Vision","worker","createWorker","Ai","os","CliTool","$","DateTimeTool","ExecTool","JSTool","PythonTool","FetchTool","Http","console","consoleInterceptor","Fn","$Sync","ReadWebpageTool","html","r","cheerio","metadata","content","contentSelectors","selector","el","WebSearchTool","match","regex","ASet","url"],"mappings":"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"}
|
package/dist/index.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import * as
|
|
2
|
-
import { objectMap as k, JSONAttemptParse as w, findByProp as x, JSONSanitize as b, clean as
|
|
1
|
+
import * as j from "node:os";
|
|
2
|
+
import { objectMap as k, JSONAttemptParse as w, findByProp as x, JSONSanitize as b, clean as M, Http as E, consoleInterceptor as q, fn as A, ASet as P } from "@ztimson/utils";
|
|
3
3
|
import { Anthropic as $ } from "@anthropic-ai/sdk";
|
|
4
4
|
import { OpenAI as O } from "openai";
|
|
5
5
|
import { Worker as R } from "worker_threads";
|
|
@@ -8,10 +8,10 @@ import { join as W, dirname as v } from "path";
|
|
|
8
8
|
import { spawn as L } from "node:child_process";
|
|
9
9
|
import y from "node:fs/promises";
|
|
10
10
|
import N from "node:path";
|
|
11
|
-
import { createWorker as
|
|
11
|
+
import { createWorker as J } from "tesseract.js";
|
|
12
12
|
import "./embedder.mjs";
|
|
13
|
-
import * as
|
|
14
|
-
import { $ as
|
|
13
|
+
import * as z from "cheerio";
|
|
14
|
+
import { $ as C, $Sync as D } from "@ztimson/node-utils";
|
|
15
15
|
class S {
|
|
16
16
|
}
|
|
17
17
|
class H extends S {
|
|
@@ -120,7 +120,7 @@ ${JSON.stringify(s, null, 2)}`, a;
|
|
|
120
120
|
}
|
|
121
121
|
class _ extends S {
|
|
122
122
|
constructor(t, e, n, o) {
|
|
123
|
-
super(), this.ai = t, this.host = e, this.token = n, this.model = o, this.client = new O(
|
|
123
|
+
super(), this.ai = t, this.host = e, this.token = n, this.model = o, this.client = new O(M({
|
|
124
124
|
baseURL: e,
|
|
125
125
|
apiKey: n
|
|
126
126
|
}));
|
|
@@ -213,8 +213,8 @@ ${JSON.stringify(s, null, 2)}`, a;
|
|
|
213
213
|
const g = d?.find(x("name", p.function.name));
|
|
214
214
|
if (e.stream && e.stream({ tool: p.function.name }), !g) return { role: "tool", tool_call_id: p.id, content: '{"error": "Tool not found"}' };
|
|
215
215
|
try {
|
|
216
|
-
const f = w(p.function.arguments, {}),
|
|
217
|
-
return { role: "tool", tool_call_id: p.id, content: b(
|
|
216
|
+
const f = w(p.function.arguments, {}), T = await g.fn(f, this.ai);
|
|
217
|
+
return { role: "tool", tool_call_id: p.id, content: b(T) };
|
|
218
218
|
} catch (f) {
|
|
219
219
|
return { role: "tool", tool_call_id: p.id, content: b({ error: f?.message || f?.toString() || "Unknown" }) };
|
|
220
220
|
}
|
|
@@ -227,7 +227,7 @@ ${JSON.stringify(s, null, 2)}`, a;
|
|
|
227
227
|
return Object.assign(o, { abort: () => n.abort() });
|
|
228
228
|
}
|
|
229
229
|
}
|
|
230
|
-
class
|
|
230
|
+
class I {
|
|
231
231
|
constructor(t) {
|
|
232
232
|
this.ai = t, this.embedWorker = new R(W(v(U(import.meta.url)), "embedder.js")), this.embedWorker.on("message", ({ id: e, embedding: n }) => {
|
|
233
233
|
const o = this.embedQueue.get(e);
|
|
@@ -396,7 +396,7 @@ class G {
|
|
|
396
396
|
ocr(t) {
|
|
397
397
|
let e;
|
|
398
398
|
const n = new Promise(async (o) => {
|
|
399
|
-
e = await
|
|
399
|
+
e = await J(this.ai.options.tesseract?.model || "eng", 2, { cachePath: this.ai.options.path });
|
|
400
400
|
const { data: i } = await e.recognize(t);
|
|
401
401
|
await e.terminate(), o(i.text.trim() || null);
|
|
402
402
|
});
|
|
@@ -405,7 +405,7 @@ class G {
|
|
|
405
405
|
}
|
|
406
406
|
class ce {
|
|
407
407
|
constructor(t) {
|
|
408
|
-
this.options = t, t.path || (t.path =
|
|
408
|
+
this.options = t, t.path || (t.path = j.tmpdir()), process.env.TRANSFORMERS_CACHE = t.path, this.audio = new F(this), this.language = new I(this), this.vision = new G(this);
|
|
409
409
|
}
|
|
410
410
|
/** Audio processing AI */
|
|
411
411
|
audio;
|
|
@@ -418,12 +418,12 @@ const B = {
|
|
|
418
418
|
name: "cli",
|
|
419
419
|
description: "Use the command line interface, returns any output",
|
|
420
420
|
args: { command: { type: "string", description: "Command to run", required: !0 } },
|
|
421
|
-
fn: (m) =>
|
|
421
|
+
fn: (m) => C`${m.command}`
|
|
422
422
|
}, le = {
|
|
423
423
|
name: "get_datetime",
|
|
424
|
-
description: "Get current date
|
|
424
|
+
description: "Get current UTC date / time",
|
|
425
425
|
args: {},
|
|
426
|
-
fn: async () => (/* @__PURE__ */ new Date()).
|
|
426
|
+
fn: async () => (/* @__PURE__ */ new Date()).toUTCString()
|
|
427
427
|
}, me = {
|
|
428
428
|
name: "exec",
|
|
429
429
|
description: "Run code/scripts",
|
|
@@ -482,7 +482,7 @@ const B = {
|
|
|
482
482
|
fn: async (m) => {
|
|
483
483
|
const t = await fetch(m.url, { headers: { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64)" } }).then((c) => c.text()).catch((c) => {
|
|
484
484
|
throw new Error(`Failed to fetch: ${c.message}`);
|
|
485
|
-
}), e =
|
|
485
|
+
}), e = z.load(t);
|
|
486
486
|
e('script, style, nav, footer, header, aside, iframe, noscript, [role="navigation"], [role="banner"], .ad, .ads, .cookie, .popup').remove();
|
|
487
487
|
const n = {
|
|
488
488
|
title: e('meta[property="og:title"]').attr("content") || e("title").text() || "",
|
|
@@ -528,7 +528,7 @@ export {
|
|
|
528
528
|
me as ExecTool,
|
|
529
529
|
de as FetchTool,
|
|
530
530
|
Q as JSTool,
|
|
531
|
-
|
|
531
|
+
I as LLM,
|
|
532
532
|
S as LLMProvider,
|
|
533
533
|
_ as OpenAi,
|
|
534
534
|
K as PythonTool,
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","sources":["../src/provider.ts","../src/antrhopic.ts","../src/open-ai.ts","../src/llm.ts","../src/audio.ts","../src/vision.ts","../src/ai.ts","../src/tools.ts"],"sourcesContent":["import {AbortablePromise} from './ai.ts';\nimport {LLMMessage, LLMRequest} from './llm.ts';\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 {AbortablePromise, Ai} from './ai.ts';\nimport {LLMMessage, LLMRequest} from './llm.ts';\nimport {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 = [...options.history || [], {role: 'user', content: message, timestamp: Date.now()}];\n\t\t\tif(options.compress) history = await this.ai.language.compressHistory(<any>history, options.compress.max, options.compress.min, options);\n\t\t\thistory = this.fromStandard(<any>history);\n\n\t\t\tconst tools = options.tools || this.ai.options.llm?.tools || [];\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.llm?.max_tokens || 4096,\n\t\t\t\tsystem: options.system || this.ai.options.llm?.system || '',\n\t\t\t\ttemperature: options.temperature || this.ai.options.llm?.temperature || 0.7,\n\t\t\t\ttools: 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, isFirstMessage = true;\n\t\t\tconst assistantMessages: string[] = [];\n\t\t\tdo {\n\t\t\t\tresp = await this.client.messages.create(requestParams).catch(err => {\n\t\t\t\t\terr.message += `\\n\\nMessages:\\n${JSON.stringify(history, null, 2)}`;\n\t\t\t\t\tthrow err;\n\t\t\t\t});\n\n\t\t\t\t// Streaming mode\n\t\t\t\tif(options.stream) {\n\t\t\t\t\tif(!isFirstMessage) options.stream({text: '\\n\\n'});\n\t\t\t\t\telse isFirstMessage = false;\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\t// Run tools\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 = tools.find(findByProp('name', toolCall.name));\n\t\t\t\t\t\tif(options.stream) options.stream({tool: 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\thistory.push({role: 'user', content: results});\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\tif(options.stream) options.stream({done: true});\n\t\t\tres(this.toStandard([...history, {role: 'assistant', content: resp.content.filter((c: any) => c.type == 'text').map((c: any) => c.text).join('\\n\\n')}]));\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, clean} from '@ztimson/utils';\nimport {AbortablePromise, Ai} from './ai.ts';\nimport {LLMMessage, LLMRequest} from './llm.ts';\nimport {LLMProvider} from './provider.ts';\n\nexport class OpenAi extends LLMProvider {\n\tclient!: openAI;\n\n\tconstructor(public readonly ai: Ai, public readonly host: string | null, public readonly token: string, public model: string) {\n\t\tsuper();\n\t\tthis.client = new openAI(clean({\n\t\t\tbaseURL: host,\n\t\t\tapiKey: token\n\t\t}));\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 = [...options.history || [], {role: 'user', content: message, timestamp: Date.now()}];\n\t\t\tif(options.compress) history = await this.ai.language.compressHistory(<any>history, options.compress.max, options.compress.min, options);\n\t\t\thistory = this.fromStandard(<any>history);\n\n\t\t\tconst tools = options.tools || this.ai.options.llm?.tools || [];\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.llm?.max_tokens || 4096,\n\t\t\t\ttemperature: options.temperature || this.ai.options.llm?.temperature || 0.7,\n\t\t\t\ttools: 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, isFirstMessage = true;\n\t\t\tdo {\n\t\t\t\tresp = await this.client.chat.completions.create(requestParams).catch(err => {\n\t\t\t\t\terr.message += `\\n\\nMessages:\\n${JSON.stringify(history, null, 2)}`;\n\t\t\t\t\tthrow err;\n\t\t\t\t});\n\n\t\t\t\tif(options.stream) {\n\t\t\t\t\tif(!isFirstMessage) options.stream({text: '\\n\\n'});\n\t\t\t\t\telse isFirstMessage = false;\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\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 = tools?.find(findByProp('name', toolCall.function.name));\n\t\t\t\t\t\tif(options.stream) options.stream({tool: 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\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\tif(options.stream) options.stream({done: true});\n\t\t\tres(this.toStandard([...history, {role: 'assistant', content: resp.choices[0].message.content || ''}]));\n\t\t});\n\t\treturn Object.assign(response, {abort: () => controller.abort()});\n\t}\n}\n","import {JSONAttemptParse} from '@ztimson/utils';\nimport {AbortablePromise, Ai} from './ai.ts';\nimport {Anthropic} from './antrhopic.ts';\nimport {OpenAi} from './open-ai.ts';\nimport {LLMProvider} from './provider.ts';\nimport {AiTool} from './tools.ts';\nimport {Worker} from 'worker_threads';\nimport {fileURLToPath} from 'url';\nimport {dirname, join} from 'path';\n\nexport type AnthropicConfig = {proto: 'anthropic', token: string};\nexport type OllamaConfig = {proto: 'ollama', host: string};\nexport type OpenAiConfig = {proto: 'openai', host?: string, token: string};\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 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;\n\t/** Stream response */\n\tstream?: (chunk: {text?: string, tool?: 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 embedWorker: Worker | null = null;\n\tprivate embedQueue = new Map<number, { resolve: (value: number[]) => void; reject: (error: any) => void }>();\n\tprivate embedId = 0;\n\tprivate models: {[model: string]: LLMProvider} = {};\n\tprivate defaultModel!: string;\n\n\tconstructor(public readonly ai: Ai) {\n\t\tthis.embedWorker = new Worker(join(dirname(fileURLToPath(import.meta.url)), 'embedder.js'));\n\t\tthis.embedWorker.on('message', ({ id, embedding }) => {\n\t\t\tconst pending = this.embedQueue.get(id);\n\t\t\tif (pending) {\n\t\t\t\tpending.resolve(embedding);\n\t\t\t\tthis.embedQueue.delete(id);\n\t\t\t}\n\t\t});\n\n\t\tif(!ai.options.llm?.models) return;\n\t\tObject.entries(ai.options.llm.models).forEach(([model, config]) => {\n\t\t\tif(!this.defaultModel) this.defaultModel = model;\n\t\t\tif(config.proto == 'anthropic') this.models[model] = new Anthropic(this.ai, config.token, model);\n\t\t\telse if(config.proto == 'ollama') this.models[model] = new OpenAi(this.ai, config.host, 'not-needed', model);\n\t\t\telse if(config.proto == 'openai') this.models[model] = new OpenAi(this.ai, config.host || null, config.token, model);\n\t\t});\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\tconst m = options.model || this.defaultModel;\n\t\tif(!this.models[m]) throw new Error(`Model does not exist: ${m}`);\n\t\treturn this.models[m].ask(message, options);\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 compressHistory(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\tcosineSimilarity(v1: number[], v2: number[]): number {\n\t\tif (v1.length !== v2.length) throw new Error('Vectors must be same length');\n\t\tlet dotProduct = 0, normA = 0, normB = 0;\n\t\tfor (let i = 0; i < v1.length; i++) {\n\t\t\tdotProduct += v1[i] * v2[i];\n\t\t\tnormA += v1[i] * v1[i];\n\t\t\tnormB += v2[i] * v2[i];\n\t\t}\n\t\tconst denominator = Math.sqrt(normA) * Math.sqrt(normB);\n\t\treturn denominator === 0 ? 0 : dotProduct / denominator;\n\t}\n\n\tchunk(target: object | string, maxTokens = 500, overlapTokens = 50): string[] {\n\t\tconst objString = (obj: any, path = ''): string[] => {\n\t\t\tif(!obj) return [];\n\t\t\treturn Object.entries(obj).flatMap(([key, value]) => {\n\t\t\t\tconst p = path ? `${path}${isNaN(+key) ? `.${key}` : `[${key}]`}` : key;\n\t\t\t\tif(typeof value === 'object' && !Array.isArray(value)) return objString(value, p);\n\t\t\t\treturn `${p}: ${Array.isArray(value) ? value.join(', ') : value}`;\n\t\t\t});\n\t\t};\n\n\t\tconst lines = typeof target === 'object' ? objString(target) : target.split('\\n');\n\t\tconst tokens = lines.flatMap(l => [...l.split(/\\s+/).filter(Boolean), '\\n']);\n\t\tconst chunks: string[] = [];\n\t\tfor(let i = 0; i < tokens.length;) {\n\t\t\tlet text = '', j = i;\n\t\t\twhile(j < tokens.length) {\n\t\t\t\tconst next = text + (text ? ' ' : '') + tokens[j];\n\t\t\t\tif(this.estimateTokens(next.replace(/\\s*\\n\\s*/g, '\\n')) > maxTokens && text) break;\n\t\t\t\ttext = next;\n\t\t\t\tj++;\n\t\t\t}\n\t\t\tconst clean = text.replace(/\\s*\\n\\s*/g, '\\n').trim();\n\t\t\tif(clean) chunks.push(clean);\n\t\t\ti = Math.max(j - overlapTokens, j === i ? i + 1 : j);\n\t\t}\n\t\treturn chunks;\n\t}\n\n\tembedding(target: object | string, maxTokens = 500, overlapTokens = 50) {\n\t\tconst embed = (text: string): Promise<number[]> => {\n\t\t\treturn new Promise((resolve, reject) => {\n\t\t\t\tconst id = this.embedId++;\n\t\t\t\tthis.embedQueue.set(id, { resolve, reject });\n\t\t\t\tthis.embedWorker?.postMessage({ id, text });\n\t\t\t});\n\t\t};\n\n\t\tconst chunks = this.chunk(target, maxTokens, overlapTokens);\n\t\treturn Promise.all(chunks.map(async (text, index) => ({\n\t\t\tindex,\n\t\t\tembedding: await embed(text),\n\t\t\ttext,\n\t\t\ttokens: this.estimateTokens(text),\n\t\t})));\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 * 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\tfuzzyMatch(target: string, ...searchTerms: string[]) {\n\t\tif(searchTerms.length < 2) throw new Error('Requires at least 2 strings to compare');\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\t\tconst v = vector(target);\n\t\tconst similarities = searchTerms.map(t => vector(t)).map(refVector => this.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\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 {spawn} from 'node:child_process';\nimport fs from 'node:fs/promises';\nimport Path from 'node:path';\nimport {AbortablePromise, Ai} from './ai.ts';\n\nexport class Audio {\n\tprivate downloads: {[key: string]: Promise<string>} = {};\n\tprivate whisperModel!: string;\n\n\tconstructor(private ai: Ai) {\n\t\tif(ai.options.whisper?.binary) {\n\t\t\tthis.whisperModel = ai.options.whisper?.model.endsWith('.bin') ? ai.options.whisper?.model : ai.options.whisper?.model + '.bin';\n\t\t\tthis.downloadAsrModel();\n\t\t}\n\t}\n\n\tasr(path: string, model: string = this.whisperModel): AbortablePromise<string | null> {\n\t\tif(!this.ai.options.whisper?.binary) throw new Error('Whisper not configured');\n\t\tlet abort: any = () => {};\n\t\tconst p = new Promise<string | null>(async (resolve, reject) => {\n\t\t\tconst m = await this.downloadAsrModel(model);\n\t\t\tlet output = '';\n\t\t\tconst proc = spawn(<string>this.ai.options.whisper?.binary, ['-nt', '-np', '-m', m, '-f', path], {stdio: ['ignore', 'pipe', 'ignore']});\n\t\t\tabort = () => proc.kill('SIGTERM');\n\t\t\tproc.on('error', (err: Error) => reject(err));\n\t\t\tproc.stdout.on('data', (data: Buffer) => output += data.toString());\n\t\t\tproc.on('close', (code: number) => {\n\t\t\t\tif(code === 0) resolve(output.trim() || null);\n\t\t\t\telse reject(new Error(`Exit code ${code}`));\n\t\t\t});\n\t\t});\n\t\treturn Object.assign(p, {abort});\n\t}\n\n\tasync downloadAsrModel(model: string = this.whisperModel): Promise<string> {\n\t\tif(!this.ai.options.whisper?.binary) throw new Error('Whisper not configured');\n\t\tif(!model.endsWith('.bin')) model += '.bin';\n\t\tconst p = Path.join(<string>this.ai.options.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","import {createWorker} from 'tesseract.js';\nimport {AbortablePromise, Ai} from './ai.ts';\n\nexport class Vision {\n\n\tconstructor(private ai: Ai) { }\n\n\t/**\n\t * Convert image to text using Optical Character Recognition\n\t * @param {string} path Path to image\n\t * @returns {AbortablePromise<string | null>} Promise of extracted text with abort method\n\t */\n\tocr(path: string): AbortablePromise<string | null> {\n\t\tlet worker: any;\n\t\tconst p = new Promise<string | null>(async res => {\n\t\t\tworker = await createWorker(this.ai.options.tesseract?.model || 'eng', 2, {cachePath: this.ai.options.path});\n\t\t\tconst {data} = await worker.recognize(path);\n\t\t\tawait worker.terminate();\n\t\t\tres(data.text.trim() || null);\n\t\t});\n\t\treturn Object.assign(p, {abort: () => worker?.terminate()});\n\t}\n}\n","import * as os from 'node:os';\nimport {LLM, AnthropicConfig, OllamaConfig, OpenAiConfig, LLMRequest} from './llm';\nimport { Audio } from './audio.ts';\nimport {Vision} from './vision.ts';\n\nexport type AbortablePromise<T> = Promise<T> & {abort: () => any};\n\nexport type AiOptions = {\n\t/** Path to models */\n\tpath?: string;\n\t/** Large language models, first is default */\n\tllm?: Omit<LLMRequest, 'model'> & {\n\t\tmodels: {[model: string]: AnthropicConfig | OllamaConfig | OpenAiConfig};\n\t}\n\t/** Tesseract OCR configuration */\n\ttesseract?: {\n\t\t/** Model: eng, eng_best, eng_fast */\n\t\tmodel?: string;\n\t}\n\t/** Whisper ASR configuration */\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}\n}\n\nexport class Ai {\n\t/** Audio processing AI */\n\taudio!: Audio;\n\t/** Language processing AI */\n\tlanguage!: LLM;\n\t/** Vision processing AI */\n\tvision!: Vision;\n\n\tconstructor(public readonly options: AiOptions) {\n\t\tif(!options.path) options.path = os.tmpdir();\n\t\tprocess.env.TRANSFORMERS_CACHE = options.path;\n\t\tthis.audio = new Audio(this);\n\t\tthis.language = new LLM(this);\n\t\tthis.vision = new Vision(this);\n\t}\n}\n","import * as cheerio from 'cheerio';\nimport {$, $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 ReadWebpageTool: AiTool = {\n\tname: 'read_webpage',\n\tdescription: 'Extract clean, structured content from a webpage. Use after web_search to read specific URLs',\n\targs: {\n\t\turl: {type: 'string', description: 'URL to extract content from', required: true},\n\t\tfocus: {type: 'string', description: 'Optional: What aspect to focus on (e.g., \"pricing\", \"features\", \"contact info\")'}\n\t},\n\tfn: async (args: {url: string; focus?: string}) => {\n\t\tconst html = await fetch(args.url, {headers: {\"User-Agent\": \"Mozilla/5.0 (Windows NT 10.0; Win64; x64)\"}})\n\t\t\t.then(r => r.text()).catch(err => {throw new Error(`Failed to fetch: ${err.message}`)});\n\n\t\tconst $ = cheerio.load(html);\n\t\t$('script, style, nav, footer, header, aside, iframe, noscript, [role=\"navigation\"], [role=\"banner\"], .ad, .ads, .cookie, .popup').remove();\n\t\tconst metadata = {\n\t\t\ttitle: $('meta[property=\"og:title\"]').attr('content') || $('title').text() || '',\n\t\t\tdescription: $('meta[name=\"description\"]').attr('content') || $('meta[property=\"og:description\"]').attr('content') || '',\n\t\t};\n\n\t\tlet content = '';\n\t\tconst contentSelectors = ['article', 'main', '[role=\"main\"]', '.content', '.post', '.entry', 'body'];\n\t\tfor (const selector of contentSelectors) {\n\t\t\tconst el = $(selector).first();\n\t\t\tif (el.length && el.text().trim().length > 200) {\n\t\t\t\tcontent = el.text();\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tif (!content) content = $('body').text();\n\t\tcontent = content.replace(/\\s+/g, ' ').trim().slice(0, 8000);\n\n\t\treturn {url: args.url, title: metadata.title.trim(), description: metadata.description.trim(), content, focus: args.focus};\n\t}\n}\n\nexport const WebSearchTool: AiTool = {\n\tname: 'web_search',\n\tdescription: 'Use duckduckgo (anonymous) to find find relevant online resources. Returns a list of URLs that works great with the `read_webpage` tool',\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","tools","requestParams","t","objectMap","key","value","resp","isFirstMessage","err","chunk","text","last","JSONAttemptParse","toolCalls","results","toolCall","tool","findByProp","result","JSONSanitize","OpenAi","host","token","openAI","clean","tc","record","h2","rest","args","LLM","Worker","join","dirname","fileURLToPath","id","embedding","pending","config","m","max","min","keep","tokens","recent","process","v1","v2","dotProduct","normA","normB","denominator","target","maxTokens","overlapTokens","objString","obj","path","p","l","chunks","j","next","embed","resolve","reject","index","searchTerms","vector","dimensions","char","v","similarities","refVector","acc","Audio","abort","output","proc","spawn","data","code","Path","fs","arr","buffer","Vision","worker","createWorker","Ai","os","CliTool","$","DateTimeTool","ExecTool","JSTool","PythonTool","FetchTool","Http","console","consoleInterceptor","Fn","$Sync","ReadWebpageTool","html","r","cheerio","metadata","content","contentSelectors","selector","el","WebSearchTool","match","regex","ASet","url"],"mappings":";;;;;;;;;;;;;;AAGO,MAAeA,EAAY;AAElC;ACCO,MAAMC,UAAkBD,EAAY;AAAA,EAG1C,YAA4BE,GAAwBC,GAAyBC,GAAe;AAC3F,UAAA,GAD2B,KAAA,KAAAF,GAAwB,KAAA,WAAAC,GAAyB,KAAA,QAAAC,GAE5E,KAAK,SAAS,IAAIC,EAAU,EAAC,QAAQF,GAAS;AAAA,EAC/C;AAAA,EALA;AAAA,EAOQ,WAAWG,GAA8B;AAChD,aAAQC,IAAI,GAAGA,IAAID,EAAQ,QAAQC,KAAK;AACvC,YAAMC,IAAOD;AACb,MAAG,OAAOD,EAAQE,CAAI,EAAE,WAAW,aAC/BF,EAAQE,CAAI,EAAE,QAAQ,cACxBF,EAAQE,CAAI,EAAE,QAAQ,OAAO,CAACC,MAAWA,EAAE,QAAO,UAAU,EAAE,QAAQ,CAACA,MAAW;AACjF,QAAAF,KACAD,EAAQ,OAAOC,GAAG,GAAG,EAAC,MAAM,QAAQ,IAAIE,EAAE,IAAI,MAAMA,EAAE,MAAM,MAAMA,EAAE,OAAO,WAAW,KAAK,IAAA,GAAM;AAAA,MAClG,CAAC,IACQH,EAAQE,CAAI,EAAE,QAAQ,UAC/BF,EAAQE,CAAI,EAAE,QAAQ,OAAO,CAACC,MAAWA,EAAE,QAAO,aAAa,EAAE,QAAQ,CAACA,MAAW;AACpF,cAAMC,IAAIJ,EAAQ,KAAK,CAACI,MAAWA,EAAE,MAAMD,EAAE,WAAW;AACxD,QAAAC,EAAED,EAAE,WAAW,UAAU,SAAS,IAAIA,EAAE;AAAA,MACzC,CAAC,GAEFH,EAAQE,CAAI,EAAE,UAAUF,EAAQE,CAAI,EAAE,QAAQ,OAAO,CAACC,MAAWA,EAAE,QAAQ,MAAM,EAAE,IAAI,CAACA,MAAWA,EAAE,IAAI,EAAE,KAAK;AAAA;AAAA,CAAM,IAEnHH,EAAQE,CAAI,EAAE,gBAAmBA,CAAI,EAAE,YAAY,KAAK,IAAA;AAAA,IAC7D;AACA,WAAOF,EAAQ,OAAO,CAAAI,MAAK,CAAC,CAACA,EAAE,OAAO;AAAA,EACvC;AAAA,EAEQ,aAAaJ,GAA8B;AAClD,aAAQC,IAAI,GAAGA,IAAID,EAAQ,QAAQC;AAClC,UAAGD,EAAQC,CAAC,EAAE,QAAQ,QAAQ;AAC7B,cAAMG,IAASJ,EAAQC,CAAC;AACxB,QAAAD,EAAQ;AAAA,UAAOC;AAAA,UAAG;AAAA,UACjB,EAAC,MAAM,aAAa,SAAS,CAAC,EAAC,MAAM,YAAY,IAAIG,EAAE,IAAI,MAAMA,EAAE,MAAM,OAAOA,EAAE,KAAA,CAAK,EAAA;AAAA,UACvF,EAAC,MAAM,QAAQ,SAAS,CAAC,EAAC,MAAM,eAAe,aAAaA,EAAE,IAAI,UAAU,CAAC,CAACA,EAAE,OAAO,SAAUA,EAAE,SAASA,EAAE,SAAQ,EAAA;AAAA,QAAC,GAExHH;AAAA,MACD;AAED,WAAOD,EAAQ,IAAI,CAAC,EAAC,WAAAK,GAAW,GAAGD,EAAA,MAAOA,CAAC;AAAA,EAC5C;AAAA,EAEA,IAAIE,GAAiBC,IAAsB,IAAoC;AAC9E,UAAMC,IAAa,IAAI,gBAAA,GACjBC,IAAW,IAAI,QAAa,OAAOC,GAAKC,MAAQ;AACrD,UAAIX,IAAU,CAAC,GAAGO,EAAQ,WAAW,CAAA,GAAI,EAAC,MAAM,QAAQ,SAASD,GAAS,WAAW,KAAK,IAAA,GAAM;AAChG,MAAGC,EAAQ,aAAUP,IAAU,MAAM,KAAK,GAAG,SAAS,gBAAqBA,GAASO,EAAQ,SAAS,KAAKA,EAAQ,SAAS,KAAKA,CAAO,IACvIP,IAAU,KAAK,aAAkBA,CAAO;AAExC,YAAMY,IAAQL,EAAQ,SAAS,KAAK,GAAG,QAAQ,KAAK,SAAS,CAAA,GACvDM,IAAqB;AAAA,QAC1B,OAAON,EAAQ,SAAS,KAAK;AAAA,QAC7B,YAAYA,EAAQ,cAAc,KAAK,GAAG,QAAQ,KAAK,cAAc;AAAA,QACrE,QAAQA,EAAQ,UAAU,KAAK,GAAG,QAAQ,KAAK,UAAU;AAAA,QACzD,aAAaA,EAAQ,eAAe,KAAK,GAAG,QAAQ,KAAK,eAAe;AAAA,QACxE,OAAOK,EAAM,IAAI,CAAAE,OAAM;AAAA,UACtB,MAAMA,EAAE;AAAA,UACR,aAAaA,EAAE;AAAA,UACf,cAAc;AAAA,YACb,MAAM;AAAA,YACN,YAAYA,EAAE,OAAOC,EAAUD,EAAE,MAAM,CAACE,GAAKC,OAAW,EAAC,GAAGA,GAAO,UAAU,OAAA,EAAW,IAAI,CAAA;AAAA,YAC5F,UAAUH,EAAE,OAAO,OAAO,QAAQA,EAAE,IAAI,EAAE,OAAO,CAAAA,MAAKA,EAAE,CAAC,EAAE,QAAQ,EAAE,IAAI,CAAAA,MAAKA,EAAE,CAAC,CAAC,IAAI,CAAA;AAAA,UAAC;AAAA,UAExF,IAAI;AAAA,QAAA,EACH;AAAA,QACF,UAAUd;AAAA,QACV,QAAQ,CAAC,CAACO,EAAQ;AAAA,MAAA;AAGnB,UAAIW,GAAWC,IAAiB;AAEhC,SAAG;AAOF,YANAD,IAAO,MAAM,KAAK,OAAO,SAAS,OAAOL,CAAa,EAAE,MAAM,CAAAO,MAAO;AACpE,gBAAAA,EAAI,WAAW;AAAA;AAAA;AAAA,EAAkB,KAAK,UAAUpB,GAAS,MAAM,CAAC,CAAC,IAC3DoB;AAAA,QACP,CAAC,GAGEb,EAAQ,QAAQ;AAClB,UAAIY,IACCA,IAAiB,KADFZ,EAAQ,OAAO,EAAC,MAAM;AAAA;AAAA,GAAO,GAEjDW,EAAK,UAAU,CAAA;AACf,2BAAiBG,KAASH,GAAM;AAC/B,gBAAGV,EAAW,OAAO,QAAS;AAC9B,gBAAGa,EAAM,SAAS;AACjB,cAAGA,EAAM,cAAc,SAAS,SAC/BH,EAAK,QAAQ,KAAK,EAAC,MAAM,QAAQ,MAAM,IAAG,IACjCG,EAAM,cAAc,SAAS,cACtCH,EAAK,QAAQ,KAAK,EAAC,MAAM,YAAY,IAAIG,EAAM,cAAc,IAAI,MAAMA,EAAM,cAAc,MAAM,OAAY,IAAG;AAAA,qBAExGA,EAAM,SAAS;AACxB,kBAAGA,EAAM,MAAM,SAAS,cAAc;AACrC,sBAAMC,IAAOD,EAAM,MAAM;AACzB,gBAAAH,EAAK,QAAQ,GAAG,EAAE,EAAE,QAAQI,GAC5Bf,EAAQ,OAAO,EAAC,MAAAe,GAAK;AAAA,cACtB,MAAA,CAAUD,EAAM,MAAM,SAAS,uBAC9BH,EAAK,QAAQ,GAAG,EAAE,EAAE,SAASG,EAAM,MAAM;AAAA,qBAEjCA,EAAM,SAAS,sBAAsB;AAC9C,oBAAME,IAAOL,EAAK,QAAQ,GAAG,EAAE;AAC/B,cAAGK,EAAK,SAAS,SAAMA,EAAK,QAAQA,EAAK,QAAQC,EAAiBD,EAAK,OAAO,CAAA,CAAE,IAAI,CAAA;AAAA,YACrF,WAAUF,EAAM,SAAS;AACxB;AAAA,UAEF;AAAA,QACD;AAGA,cAAMI,IAAYP,EAAK,QAAQ,OAAO,CAACf,MAAWA,EAAE,SAAS,UAAU;AACvE,YAAGsB,EAAU,UAAU,CAACjB,EAAW,OAAO,SAAS;AAClD,UAAAR,EAAQ,KAAK,EAAC,MAAM,aAAa,SAASkB,EAAK,SAAQ;AACvD,gBAAMQ,IAAU,MAAM,QAAQ,IAAID,EAAU,IAAI,OAAOE,MAAkB;AACxE,kBAAMC,IAAOhB,EAAM,KAAKiB,EAAW,QAAQF,EAAS,IAAI,CAAC;AAEzD,gBADGpB,EAAQ,UAAQA,EAAQ,OAAO,EAAC,MAAMoB,EAAS,MAAK,GACpD,CAACC,EAAM,QAAO,EAAC,aAAaD,EAAS,IAAI,UAAU,IAAM,SAAS,iBAAA;AACrE,gBAAI;AACH,oBAAMG,IAAS,MAAMF,EAAK,GAAGD,EAAS,OAAO,KAAK,EAAE;AACpD,qBAAO,EAAC,MAAM,eAAe,aAAaA,EAAS,IAAI,SAASI,EAAaD,CAAM,EAAA;AAAA,YACpF,SAASV,GAAU;AAClB,qBAAO,EAAC,MAAM,eAAe,aAAaO,EAAS,IAAI,UAAU,IAAM,SAASP,GAAK,WAAWA,GAAK,SAAA,KAAc,UAAA;AAAA,YACpH;AAAA,UACD,CAAC,CAAC;AACF,UAAApB,EAAQ,KAAK,EAAC,MAAM,QAAQ,SAAS0B,GAAQ,GAC7Cb,EAAc,WAAWb;AAAA,QAC1B;AAAA,MACD,SAAS,CAACQ,EAAW,OAAO,WAAWU,EAAK,QAAQ,KAAK,CAACf,MAAWA,EAAE,SAAS,UAAU;AAE1F,MAAGI,EAAQ,UAAQA,EAAQ,OAAO,EAAC,MAAM,IAAK,GAC9CG,EAAI,KAAK,WAAW,CAAC,GAAGV,GAAS,EAAC,MAAM,aAAa,SAASkB,EAAK,QAAQ,OAAO,CAACf,MAAWA,EAAE,QAAQ,MAAM,EAAE,IAAI,CAACA,MAAWA,EAAE,IAAI,EAAE,KAAK;AAAA;AAAA,CAAM,EAAA,CAAE,CAAC,CAAC;AAAA,IACxJ,CAAC;AAED,WAAO,OAAO,OAAOM,GAAU,EAAC,OAAO,MAAMD,EAAW,MAAA,GAAQ;AAAA,EACjE;AACD;ACvIO,MAAMwB,UAAetC,EAAY;AAAA,EAGvC,YAA4BE,GAAwBqC,GAAqCC,GAAsBpC,GAAe;AAC7H,UAAA,GAD2B,KAAA,KAAAF,GAAwB,KAAA,OAAAqC,GAAqC,KAAA,QAAAC,GAAsB,KAAA,QAAApC,GAE9G,KAAK,SAAS,IAAIqC,EAAOC,EAAM;AAAA,MAC9B,SAASH;AAAA,MACT,QAAQC;AAAA,IAAA,CACR,CAAC;AAAA,EACH;AAAA,EARA;AAAA,EAUQ,WAAWlC,GAA8B;AAChD,aAAQC,IAAI,GAAGA,IAAID,EAAQ,QAAQC,KAAK;AACvC,YAAMG,IAAIJ,EAAQC,CAAC;AACnB,UAAGG,EAAE,SAAS,eAAeA,EAAE,YAAY;AAC1C,cAAMQ,IAAQR,EAAE,WAAW,IAAI,CAACiC,OAAa;AAAA,UAC5C,MAAM;AAAA,UACN,IAAIA,EAAG;AAAA,UACP,MAAMA,EAAG,SAAS;AAAA,UAClB,MAAMb,EAAiBa,EAAG,SAAS,WAAW,CAAA,CAAE;AAAA,UAChD,WAAWjC,EAAE;AAAA,QAAA,EACZ;AACF,QAAAJ,EAAQ,OAAOC,GAAG,GAAG,GAAGW,CAAK,GAC7BX,KAAKW,EAAM,SAAS;AAAA,MACrB,WAAUR,EAAE,SAAS,UAAUA,EAAE,SAAS;AACzC,cAAMkC,IAAStC,EAAQ,KAAK,OAAMI,EAAE,gBAAgBmC,EAAG,EAAE;AACzD,QAAGD,MACClC,EAAE,QAAQ,SAAS,UAAU,IAAGkC,EAAO,QAAQlC,EAAE,UAC/CkC,EAAO,UAAUlC,EAAE,UAEzBJ,EAAQ,OAAOC,GAAG,CAAC,GACnBA;AAAA,MACD;AACA,MAAID,EAAQC,CAAC,GAAG,gBAAmBA,CAAC,EAAE,YAAY,KAAK,IAAA;AAAA,IACxD;AACA,WAAOD;AAAA,EACR;AAAA,EAEQ,aAAaA,GAA8B;AAClD,WAAOA,EAAQ,OAAO,CAAC8B,GAAQ1B,MAAM;AACpC,UAAGA,EAAE,SAAS;AACb,QAAA0B,EAAO,KAAK;AAAA,UACX,MAAM;AAAA,UACN,SAAS;AAAA,UACT,YAAY,CAAC,EAAE,IAAI1B,EAAE,IAAI,MAAM,YAAY,UAAU,EAAE,MAAMA,EAAE,MAAM,WAAW,KAAK,UAAUA,EAAE,IAAI,EAAA,GAAK;AAAA,UAC1G,SAAS;AAAA,UACT,aAAa,CAAA;AAAA,QAAC,GACZ;AAAA,UACF,MAAM;AAAA,UACN,cAAcA,EAAE;AAAA,UAChB,SAASA,EAAE,SAASA,EAAE;AAAA,QAAA,CACtB;AAAA,WACK;AACN,cAAM,EAAC,WAAAC,GAAW,GAAGmC,EAAA,IAAQpC;AAC7B,QAAA0B,EAAO,KAAKU,CAAI;AAAA,MACjB;AACA,aAAOV;AAAA,IACR,GAAG,CAAA,CAAW;AAAA,EACf;AAAA,EAEA,IAAIxB,GAAiBC,IAAsB,IAAoC;AAC9E,UAAMC,IAAa,IAAI,gBAAA,GACjBC,IAAW,IAAI,QAAa,OAAOC,GAAKC,MAAQ;AACrD,UAAIX,IAAU,CAAC,GAAGO,EAAQ,WAAW,CAAA,GAAI,EAAC,MAAM,QAAQ,SAASD,GAAS,WAAW,KAAK,IAAA,GAAM;AAChG,MAAGC,EAAQ,aAAUP,IAAU,MAAM,KAAK,GAAG,SAAS,gBAAqBA,GAASO,EAAQ,SAAS,KAAKA,EAAQ,SAAS,KAAKA,CAAO,IACvIP,IAAU,KAAK,aAAkBA,CAAO;AAExC,YAAMY,IAAQL,EAAQ,SAAS,KAAK,GAAG,QAAQ,KAAK,SAAS,CAAA,GACvDM,IAAqB;AAAA,QAC1B,OAAON,EAAQ,SAAS,KAAK;AAAA,QAC7B,UAAUP;AAAA,QACV,QAAQ,CAAC,CAACO,EAAQ;AAAA,QAClB,YAAYA,EAAQ,cAAc,KAAK,GAAG,QAAQ,KAAK,cAAc;AAAA,QACrE,aAAaA,EAAQ,eAAe,KAAK,GAAG,QAAQ,KAAK,eAAe;AAAA,QACxE,OAAOK,EAAM,IAAI,CAAAE,OAAM;AAAA,UACtB,MAAM;AAAA,UACN,UAAU;AAAA,YACT,MAAMA,EAAE;AAAA,YACR,aAAaA,EAAE;AAAA,YACf,YAAY;AAAA,cACX,MAAM;AAAA,cACN,YAAYA,EAAE,OAAOC,EAAUD,EAAE,MAAM,CAACE,GAAKC,OAAW,EAAC,GAAGA,GAAO,UAAU,OAAA,EAAW,IAAI,CAAA;AAAA,cAC5F,UAAUH,EAAE,OAAO,OAAO,QAAQA,EAAE,IAAI,EAAE,OAAO,CAAAA,MAAKA,EAAE,CAAC,EAAE,QAAQ,EAAE,IAAI,CAAAA,MAAKA,EAAE,CAAC,CAAC,IAAI,CAAA;AAAA,YAAC;AAAA,UACxF;AAAA,QACD,EACC;AAAA,MAAA;AAGH,UAAII,GAAWC,IAAiB;AAChC,SAAG;AAMF,YALAD,IAAO,MAAM,KAAK,OAAO,KAAK,YAAY,OAAOL,CAAa,EAAE,MAAM,CAAAO,MAAO;AAC5E,gBAAAA,EAAI,WAAW;AAAA;AAAA;AAAA,EAAkB,KAAK,UAAUpB,GAAS,MAAM,CAAC,CAAC,IAC3DoB;AAAA,QACP,CAAC,GAEEb,EAAQ,QAAQ;AAClB,UAAIY,IACCA,IAAiB,KADFZ,EAAQ,OAAO,EAAC,MAAM;AAAA;AAAA,GAAO,GAEjDW,EAAK,UAAU,CAAC,EAAC,SAAS,EAAC,SAAS,IAAI,YAAY,CAAA,EAAC,GAAG;AACxD,2BAAiBG,KAASH,GAAM;AAC/B,gBAAGV,EAAW,OAAO,QAAS;AAC9B,YAAGa,EAAM,QAAQ,CAAC,EAAE,MAAM,YACzBH,EAAK,QAAQ,CAAC,EAAE,QAAQ,WAAWG,EAAM,QAAQ,CAAC,EAAE,MAAM,SAC1Dd,EAAQ,OAAO,EAAC,MAAMc,EAAM,QAAQ,CAAC,EAAE,MAAM,SAAQ,IAEnDA,EAAM,QAAQ,CAAC,EAAE,MAAM,eACzBH,EAAK,QAAQ,CAAC,EAAE,QAAQ,aAAaG,EAAM,QAAQ,CAAC,EAAE,MAAM;AAAA,UAE9D;AAAA,QACD;AAEA,cAAMI,IAAYP,EAAK,QAAQ,CAAC,EAAE,QAAQ,cAAc,CAAA;AACxD,YAAGO,EAAU,UAAU,CAACjB,EAAW,OAAO,SAAS;AAClD,UAAAR,EAAQ,KAAKkB,EAAK,QAAQ,CAAC,EAAE,OAAO;AACpC,gBAAMQ,IAAU,MAAM,QAAQ,IAAID,EAAU,IAAI,OAAOE,MAAkB;AACxE,kBAAMC,IAAOhB,GAAO,KAAKiB,EAAW,QAAQF,EAAS,SAAS,IAAI,CAAC;AAEnE,gBADGpB,EAAQ,UAAQA,EAAQ,OAAO,EAAC,MAAMoB,EAAS,SAAS,MAAK,GAC7D,CAACC,EAAM,QAAO,EAAC,MAAM,QAAQ,cAAcD,EAAS,IAAI,SAAS,8BAAA;AACpE,gBAAI;AACH,oBAAMc,IAAOjB,EAAiBG,EAAS,SAAS,WAAW,CAAA,CAAE,GACvDG,IAAS,MAAMF,EAAK,GAAGa,GAAM,KAAK,EAAE;AAC1C,qBAAO,EAAC,MAAM,QAAQ,cAAcd,EAAS,IAAI,SAASI,EAAaD,CAAM,EAAA;AAAA,YAC9E,SAASV,GAAU;AAClB,qBAAO,EAAC,MAAM,QAAQ,cAAcO,EAAS,IAAI,SAASI,EAAa,EAAC,OAAOX,GAAK,WAAWA,GAAK,cAAc,UAAA,CAAU,EAAA;AAAA,YAC7H;AAAA,UACD,CAAC,CAAC;AACF,UAAApB,EAAQ,KAAK,GAAG0B,CAAO,GACvBb,EAAc,WAAWb;AAAA,QAC1B;AAAA,MACD,SAAS,CAACQ,EAAW,OAAO,WAAWU,EAAK,UAAU,CAAC,GAAG,SAAS,YAAY;AAE/E,MAAGX,EAAQ,UAAQA,EAAQ,OAAO,EAAC,MAAM,IAAK,GAC9CG,EAAI,KAAK,WAAW,CAAC,GAAGV,GAAS,EAAC,MAAM,aAAa,SAASkB,EAAK,QAAQ,CAAC,EAAE,QAAQ,WAAW,GAAA,CAAG,CAAC,CAAC;AAAA,IACvG,CAAC;AACD,WAAO,OAAO,OAAOT,GAAU,EAAC,OAAO,MAAMD,EAAW,MAAA,GAAQ;AAAA,EACjE;AACD;AChFO,MAAMkC,EAAI;AAAA,EAOhB,YAA4B9C,GAAQ;AAUnC,IAV2B,KAAA,KAAAA,GAC3B,KAAK,cAAc,IAAI+C,EAAOC,EAAKC,EAAQC,EAAc,YAAY,GAAG,CAAC,GAAG,aAAa,CAAC,GAC1F,KAAK,YAAY,GAAG,WAAW,CAAC,EAAE,IAAAC,GAAI,WAAAC,QAAgB;AACrD,YAAMC,IAAU,KAAK,WAAW,IAAIF,CAAE;AACtC,MAAIE,MACHA,EAAQ,QAAQD,CAAS,GACzB,KAAK,WAAW,OAAOD,CAAE;AAAA,IAE3B,CAAC,GAEGnD,EAAG,QAAQ,KAAK,UACpB,OAAO,QAAQA,EAAG,QAAQ,IAAI,MAAM,EAAE,QAAQ,CAAC,CAACE,GAAOoD,CAAM,MAAM;AAClE,MAAI,KAAK,iBAAc,KAAK,eAAepD,IACxCoD,EAAO,SAAS,cAAa,KAAK,OAAOpD,CAAK,IAAI,IAAIH,EAAU,KAAK,IAAIuD,EAAO,OAAOpD,CAAK,IACvFoD,EAAO,SAAS,WAAU,KAAK,OAAOpD,CAAK,IAAI,IAAIkC,EAAO,KAAK,IAAIkB,EAAO,MAAM,cAAcpD,CAAK,IACnGoD,EAAO,SAAS,aAAU,KAAK,OAAOpD,CAAK,IAAI,IAAIkC,EAAO,KAAK,IAAIkB,EAAO,QAAQ,MAAMA,EAAO,OAAOpD,CAAK;AAAA,IACpH,CAAC;AAAA,EACF;AAAA,EAvBQ,cAA6B;AAAA,EAC7B,iCAAiB,IAAA;AAAA,EACjB,UAAU;AAAA,EACV,SAAyC,CAAA;AAAA,EACzC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EA2BR,IAAIQ,GAAiBC,IAAsB,IAAoC;AAC9E,UAAM4C,IAAI5C,EAAQ,SAAS,KAAK;AAChC,QAAG,CAAC,KAAK,OAAO4C,CAAC,SAAS,IAAI,MAAM,yBAAyBA,CAAC,EAAE;AAChE,WAAO,KAAK,OAAOA,CAAC,EAAE,IAAI7C,GAASC,CAAO;AAAA,EAC3C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,MAAM,gBAAgBP,GAAuBoD,GAAaC,GAAa9C,GAA6C;AACnH,QAAG,KAAK,eAAeP,CAAO,IAAIoD,EAAK,QAAOpD;AAC9C,QAAIsD,IAAO,GAAGC,IAAS;AACvB,aAAQJ,KAAKnD,EAAQ;AAEpB,UADAuD,KAAU,KAAK,eAAeJ,EAAE,OAAO,GACpCI,IAASF,EAAK,CAAAC;AAAA,UACZ;AAEN,QAAGtD,EAAQ,UAAUsD,EAAM,QAAOtD;AAClC,UAAMwD,IAASF,KAAQ,IAAI,CAAA,IAAKtD,EAAQ,MAAM,CAACsD,CAAI,GAClDG,KAAWH,KAAQ,IAAItD,IAAUA,EAAQ,MAAM,GAAG,CAACsD,CAAI,GAAG,OAAO,CAAAlD,MAAKA,EAAE,SAAS,eAAeA,EAAE,SAAS,MAAM;AAElH,WAAO,CAAC,EAAC,MAAM,aAAa,SAAS,yBADrB,MAAM,KAAK,UAAUqD,EAAQ,IAAI,OAAK,GAAGN,EAAE,IAAI,KAAKA,EAAE,OAAO,EAAE,EAAE,KAAK;AAAA;AAAA,CAAM,GAAG,KAAK5C,CAAO,CACtC,IAAI,WAAW,KAAK,IAAA,EAAI,GAAI,GAAGiD,CAAM;AAAA,EAC3G;AAAA,EAEA,iBAAiBE,GAAcC,GAAsB;AACpD,QAAID,EAAG,WAAWC,EAAG,OAAQ,OAAM,IAAI,MAAM,6BAA6B;AAC1E,QAAIC,IAAa,GAAGC,IAAQ,GAAGC,IAAQ;AACvC,aAAS7D,IAAI,GAAGA,IAAIyD,EAAG,QAAQzD;AAC9B,MAAA2D,KAAcF,EAAGzD,CAAC,IAAI0D,EAAG1D,CAAC,GAC1B4D,KAASH,EAAGzD,CAAC,IAAIyD,EAAGzD,CAAC,GACrB6D,KAASH,EAAG1D,CAAC,IAAI0D,EAAG1D,CAAC;AAEtB,UAAM8D,IAAc,KAAK,KAAKF,CAAK,IAAI,KAAK,KAAKC,CAAK;AACtD,WAAOC,MAAgB,IAAI,IAAIH,IAAaG;AAAA,EAC7C;AAAA,EAEA,MAAMC,GAAyBC,IAAY,KAAKC,IAAgB,IAAc;AAC7E,UAAMC,IAAY,CAACC,GAAUC,IAAO,OAC/BD,IACG,OAAO,QAAQA,CAAG,EAAE,QAAQ,CAAC,CAACpD,GAAKC,CAAK,MAAM;AACpD,YAAMqD,IAAID,IAAO,GAAGA,CAAI,GAAG,MAAM,CAACrD,CAAG,IAAI,IAAIA,CAAG,KAAK,IAAIA,CAAG,GAAG,KAAKA;AACpE,aAAG,OAAOC,KAAU,YAAY,CAAC,MAAM,QAAQA,CAAK,IAAUkD,EAAUlD,GAAOqD,CAAC,IACzE,GAAGA,CAAC,KAAK,MAAM,QAAQrD,CAAK,IAAIA,EAAM,KAAK,IAAI,IAAIA,CAAK;AAAA,IAChE,CAAC,IALe,CAAA,GASXsC,KADQ,OAAOS,KAAW,WAAWG,EAAUH,CAAM,IAAIA,EAAO,MAAM;AAAA,CAAI,GAC3D,QAAQ,CAAAO,MAAK,CAAC,GAAGA,EAAE,MAAM,KAAK,EAAE,OAAO,OAAO,GAAG;AAAA,CAAI,CAAC,GACrEC,IAAmB,CAAA;AACzB,aAAQvE,IAAI,GAAGA,IAAIsD,EAAO,UAAS;AAClC,UAAIjC,IAAO,IAAImD,IAAIxE;AACnB,aAAMwE,IAAIlB,EAAO,UAAQ;AACxB,cAAMmB,IAAOpD,KAAQA,IAAO,MAAM,MAAMiC,EAAOkB,CAAC;AAChD,YAAG,KAAK,eAAeC,EAAK,QAAQ,aAAa;AAAA,CAAI,CAAC,IAAIT,KAAa3C,EAAM;AAC7E,QAAAA,IAAOoD,GACPD;AAAA,MACD;AACA,YAAMrC,IAAQd,EAAK,QAAQ,aAAa;AAAA,CAAI,EAAE,KAAA;AAC9C,MAAGc,KAAOoC,EAAO,KAAKpC,CAAK,GAC3BnC,IAAI,KAAK,IAAIwE,IAAIP,GAAeO,MAAMxE,IAAIA,IAAI,IAAIwE,CAAC;AAAA,IACpD;AACA,WAAOD;AAAA,EACR;AAAA,EAEA,UAAUR,GAAyBC,IAAY,KAAKC,IAAgB,IAAI;AACvE,UAAMS,IAAQ,CAACrD,MACP,IAAI,QAAQ,CAACsD,GAASC,MAAW;AACvC,YAAM9B,IAAK,KAAK;AAChB,WAAK,WAAW,IAAIA,GAAI,EAAE,SAAA6B,GAAS,QAAAC,GAAQ,GAC3C,KAAK,aAAa,YAAY,EAAE,IAAA9B,GAAI,MAAAzB,GAAM;AAAA,IAC3C,CAAC,GAGIkD,IAAS,KAAK,MAAMR,GAAQC,GAAWC,CAAa;AAC1D,WAAO,QAAQ,IAAIM,EAAO,IAAI,OAAOlD,GAAMwD,OAAW;AAAA,MACrD,OAAAA;AAAA,MACA,WAAW,MAAMH,EAAMrD,CAAI;AAAA,MAC3B,MAAAA;AAAA,MACA,QAAQ,KAAK,eAAeA,CAAI;AAAA,IAAA,EAC/B,CAAC;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,eAAetB,GAAsB;AACpC,UAAMsB,IAAO,KAAK,UAAUtB,CAAO;AACnC,WAAO,KAAK,KAAMsB,EAAK,SAAS,IAAK,GAAG;AAAA,EACzC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,WAAW0C,MAAmBe,GAAuB;AACpD,QAAGA,EAAY,SAAS,EAAG,OAAM,IAAI,MAAM,wCAAwC;AACnF,UAAMC,IAAS,CAAC1D,GAAc2D,IAAqB,OAC3C3D,EAAK,cAAc,MAAM,EAAE,EAAE,IAAI,CAAC4D,GAAMJ,MAC7CI,EAAK,WAAW,CAAC,KAAKJ,IAAQ,KAAMG,IAAaA,CAAU,EAAE,MAAM,GAAGA,CAAU,GAE7EE,IAAIH,EAAOhB,CAAM,GACjBoB,IAAeL,EAAY,IAAI,CAAAjE,MAAKkE,EAAOlE,CAAC,CAAC,EAAE,IAAI,CAAAuE,MAAa,KAAK,iBAAiBF,GAAGE,CAAS,CAAC;AACzG,WAAO,EAAC,KAAKD,EAAa,OAAO,CAACE,GAAK,MAAMA,IAAM,GAAG,CAAC,IAAIF,EAAa,QAAQ,KAAK,KAAK,IAAI,GAAGA,CAAY,GAAG,cAAAA,EAAA;AAAA,EACjH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,KAAK9E,GAAiBC,GAAsB;AACjD,QAAIW,IAAO,MAAM,KAAK,IAAIZ,GAAS;AAAA,MAClC,QAAQ;AAAA,MACR,GAAGC;AAAA,IAAA,CACH;AACD,WAAIW,IAAO,CAAC,GAAG,UACRM,EAAiB,IAAI,OAAO,SAAa,EAAE,KAAKN,EAAK,CAAC,EAAE,OAAO,GAAG,EAAE,IAD5C,CAAA;AAAA,EAEhC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,UAAUI,GAAciC,GAAgBhD,GAA8C;AACrF,WAAO,KAAK,IAAIe,GAAM,EAAC,QAAQ,+BAA+BiC,CAAM,gCAAgC,aAAa,KAAK,GAAGhD,EAAA,CAAQ,EAC/H,KAAK,CAAAP,MAAmBA,EAAQ,IAAA,GAAO,WAAW,IAAI;AAAA,EACzD;AACD;ACrOO,MAAMuF,EAAM;AAAA,EAIlB,YAAoB3F,GAAQ;AAAR,SAAA,KAAAA,GAChBA,EAAG,QAAQ,SAAS,WACtB,KAAK,eAAeA,EAAG,QAAQ,SAAS,MAAM,SAAS,MAAM,IAAIA,EAAG,QAAQ,SAAS,QAAQA,EAAG,QAAQ,SAAS,QAAQ,QACzH,KAAK,iBAAA;AAAA,EAEP;AAAA,EARQ,YAA8C,CAAA;AAAA,EAC9C;AAAA,EASR,IAAIyE,GAAcvE,IAAgB,KAAK,cAA+C;AACrF,QAAG,CAAC,KAAK,GAAG,QAAQ,SAAS,OAAQ,OAAM,IAAI,MAAM,wBAAwB;AAC7E,QAAI0F,IAAa,MAAM;AAAA,IAAC;AACxB,UAAMlB,IAAI,IAAI,QAAuB,OAAOM,GAASC,MAAW;AAC/D,YAAM1B,IAAI,MAAM,KAAK,iBAAiBrD,CAAK;AAC3C,UAAI2F,IAAS;AACb,YAAMC,IAAOC,EAAc,KAAK,GAAG,QAAQ,SAAS,QAAQ,CAAC,OAAO,OAAO,MAAMxC,GAAG,MAAMkB,CAAI,GAAG,EAAC,OAAO,CAAC,UAAU,QAAQ,QAAQ,GAAE;AACtI,MAAAmB,IAAQ,MAAME,EAAK,KAAK,SAAS,GACjCA,EAAK,GAAG,SAAS,CAACtE,MAAeyD,EAAOzD,CAAG,CAAC,GAC5CsE,EAAK,OAAO,GAAG,QAAQ,CAACE,MAAiBH,KAAUG,EAAK,UAAU,GAClEF,EAAK,GAAG,SAAS,CAACG,MAAiB;AAClC,QAAGA,MAAS,IAAGjB,EAAQa,EAAO,KAAA,KAAU,IAAI,MAChC,IAAI,MAAM,aAAaI,CAAI,EAAE,CAAC;AAAA,MAC3C,CAAC;AAAA,IACF,CAAC;AACD,WAAO,OAAO,OAAOvB,GAAG,EAAC,OAAAkB,GAAM;AAAA,EAChC;AAAA,EAEA,MAAM,iBAAiB1F,IAAgB,KAAK,cAA+B;AAC1E,QAAG,CAAC,KAAK,GAAG,QAAQ,SAAS,OAAQ,OAAM,IAAI,MAAM,wBAAwB;AAC7E,IAAIA,EAAM,SAAS,MAAM,MAAGA,KAAS;AACrC,UAAMwE,IAAIwB,EAAK,KAAa,KAAK,GAAG,QAAQ,MAAMhG,CAAK;AACvD,WAAG,MAAMiG,EAAG,KAAKzB,CAAC,EAAE,KAAK,MAAM,EAAI,EAAE,MAAM,MAAM,EAAK,IAAUA,IAC3D,KAAK,UAAUxE,CAAK,IAAU,KAAK,UAAUA,CAAK,KACvD,KAAK,UAAUA,CAAK,IAAI,MAAM,6DAA6DA,CAAK,EAAE,EAChG,KAAK,CAAAoB,MAAQA,EAAK,aAAa,EAC/B,KAAK,CAAA8E,MAAO,OAAO,KAAKA,CAAG,CAAC,EAAE,KAAK,OAAMC,OACzC,MAAMF,EAAG,UAAUzB,GAAG2B,CAAM,GAC5B,OAAO,KAAK,UAAUnG,CAAK,GACpBwE,EACP,GACK,KAAK,UAAUxE,CAAK;AAAA,EAC5B;AACD;AC9CO,MAAMoG,EAAO;AAAA,EAEnB,YAAoBtG,GAAQ;AAAR,SAAA,KAAAA;AAAA,EAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAO9B,IAAIyE,GAA+C;AAClD,QAAI8B;AACJ,UAAM7B,IAAI,IAAI,QAAuB,OAAM5D,MAAO;AACjD,MAAAyF,IAAS,MAAMC,EAAa,KAAK,GAAG,QAAQ,WAAW,SAAS,OAAO,GAAG,EAAC,WAAW,KAAK,GAAG,QAAQ,MAAK;AAC3G,YAAM,EAAC,MAAAR,EAAA,IAAQ,MAAMO,EAAO,UAAU9B,CAAI;AAC1C,YAAM8B,EAAO,UAAA,GACbzF,EAAIkF,EAAK,KAAK,KAAA,KAAU,IAAI;AAAA,IAC7B,CAAC;AACD,WAAO,OAAO,OAAOtB,GAAG,EAAC,OAAO,MAAM6B,GAAQ,UAAA,GAAY;AAAA,EAC3D;AACD;ACMO,MAAME,GAAG;AAAA,EAQf,YAA4B9F,GAAoB;AAApB,SAAA,UAAAA,GACvBA,EAAQ,SAAMA,EAAQ,OAAO+F,EAAG,OAAA,IACpC,QAAQ,IAAI,qBAAqB/F,EAAQ,MACzC,KAAK,QAAQ,IAAIgF,EAAM,IAAI,GAC3B,KAAK,WAAW,IAAI7C,EAAI,IAAI,GAC5B,KAAK,SAAS,IAAIwD,EAAO,IAAI;AAAA,EAC9B;AAAA;AAAA,EAZA;AAAA;AAAA,EAEA;AAAA;AAAA,EAEA;AASD;ACNO,MAAMK,IAAkB;AAAA,EAC9B,MAAM;AAAA,EACN,aAAa;AAAA,EACb,MAAM,EAAC,SAAS,EAAC,MAAM,UAAU,aAAa,kBAAkB,UAAU,KAAI;AAAA,EAC9E,IAAI,CAAC9D,MAA4B+D,IAAI/D,EAAK,OAAO;AAClD,GAEagE,KAAuB;AAAA,EACnC,MAAM;AAAA,EACN,aAAa;AAAA,EACb,MAAM,CAAA;AAAA,EACN,IAAI,aAAY,oBAAI,KAAA,GAAO,YAAA;AAC5B,GAEaC,KAAmB;AAAA,EAC/B,MAAM;AAAA,EACN,aAAa;AAAA,EACb,MAAM;AAAA,IACL,UAAU,EAAC,MAAM,UAAU,aAAa,sBAAsB,MAAM,CAAC,OAAO,QAAQ,QAAQ,GAAG,UAAU,GAAA;AAAA,IACzG,MAAM,EAAC,MAAM,UAAU,aAAa,mBAAmB,UAAU,GAAA;AAAA,EAAI;AAAA,EAEtE,IAAI,OAAOjE,GAAM7C,MAAO;AACvB,QAAI;AACH,cAAO6C,EAAK,MAAA;AAAA,QACX,KAAK;AACJ,iBAAO,MAAM8D,EAAQ,GAAG,EAAC,SAAS9D,EAAK,KAAA,GAAO7C,CAAE;AAAA,QACjD,KAAK;AACJ,iBAAO,MAAM+G,EAAO,GAAG,EAAC,MAAMlE,EAAK,KAAA,GAAO7C,CAAE;AAAA,QAC7C,KAAK;AACJ,iBAAO,MAAMgH,EAAW,GAAG,EAAC,MAAMnE,EAAK,KAAA,GAAO7C,CAAE;AAAA,MACjD;AAAA,IAEF,SAAQwB,GAAU;AACjB,aAAO,EAAC,OAAOA,GAAK,WAAWA,EAAI,WAAS;AAAA,IAC7C;AAAA,EACD;AACD,GAEayF,KAAoB;AAAA,EAChC,MAAM;AAAA,EACN,aAAa;AAAA,EACb,MAAM;AAAA,IACL,KAAK,EAAC,MAAM,UAAU,aAAa,gBAAgB,UAAU,GAAA;AAAA,IAC7D,QAAQ,EAAC,MAAM,UAAU,aAAa,sBAAsB,MAAM,CAAC,OAAO,QAAQ,OAAO,QAAQ,GAAG,SAAS,MAAA;AAAA,IAC7G,SAAS,EAAC,MAAM,UAAU,aAAa,wBAAwB,SAAS,GAAC;AAAA,IACzE,MAAM,EAAC,MAAM,UAAU,aAAa,oBAAA;AAAA,EAAmB;AAAA,EAExD,IAAI,CAACpE,MAKC,IAAIqE,EAAK,EAAC,KAAKrE,EAAK,KAAK,SAASA,EAAK,SAAQ,EAAE,QAAQ,EAAC,QAAQA,EAAK,UAAU,OAAO,MAAMA,EAAK,KAAA,CAAK;AAC/G,GAEakE,IAAiB;AAAA,EAC7B,MAAM;AAAA,EACN,aAAa;AAAA,EACb,MAAM;AAAA,IACL,MAAM,EAAC,MAAM,UAAU,aAAa,uBAAuB,UAAU,GAAA;AAAA,EAAI;AAAA,EAE1E,IAAI,OAAOlE,MAAyB;AACnC,UAAMsE,IAAUC,EAAmB,IAAI,GACjC9F,IAAO,MAAM+F,EAAQ,EAAC,SAAAF,EAAA,GAAUtE,EAAK,MAAM,EAAI,EAAE,MAAM,CAACrB,MAAa2F,EAAQ,OAAO,MAAM,KAAK3F,CAAG,CAAC;AACzG,WAAO,EAAC,GAAG2F,EAAQ,QAAQ,QAAQ7F,GAAM,QAAQ,QAAW,QAAQ,OAAA;AAAA,EACrE;AACD,GAEa0F,IAAqB;AAAA,EACjC,MAAM;AAAA,EACN,aAAa;AAAA,EACb,MAAM;AAAA,IACL,MAAM,EAAC,MAAM,UAAU,aAAa,uBAAuB,UAAU,GAAA;AAAA,EAAI;AAAA,EAE1E,IAAI,OAAOnE,OAA0B,EAAC,QAAQyE,eAAmBzE,EAAK,IAAI,IAAA;AAC3E,GAEa0E,KAA0B;AAAA,EACtC,MAAM;AAAA,EACN,aAAa;AAAA,EACb,MAAM;AAAA,IACL,KAAK,EAAC,MAAM,UAAU,aAAa,+BAA+B,UAAU,GAAA;AAAA,IAC5E,OAAO,EAAC,MAAM,UAAU,aAAa,kFAAA;AAAA,EAAiF;AAAA,EAEvH,IAAI,OAAO1E,MAAwC;AAClD,UAAM2E,IAAO,MAAM,MAAM3E,EAAK,KAAK,EAAC,SAAS,EAAC,cAAc,4CAAA,GAA6C,EACvG,KAAK,CAAA4E,MAAKA,EAAE,MAAM,EAAE,MAAM,CAAAjG,MAAO;AAAC,YAAM,IAAI,MAAM,oBAAoBA,EAAI,OAAO,EAAE;AAAA,IAAC,CAAC,GAEjFoF,IAAIc,EAAQ,KAAKF,CAAI;AAC3BZ,IAAAA,EAAE,+HAA+H,EAAE,OAAA;AACnI,UAAMe,IAAW;AAAA,MAChB,OAAOf,EAAE,2BAA2B,EAAE,KAAK,SAAS,KAAKA,EAAE,OAAO,EAAE,KAAA,KAAU;AAAA,MAC9E,aAAaA,EAAE,0BAA0B,EAAE,KAAK,SAAS,KAAKA,EAAE,iCAAiC,EAAE,KAAK,SAAS,KAAK;AAAA,IAAA;AAGvH,QAAIgB,IAAU;AACd,UAAMC,IAAmB,CAAC,WAAW,QAAQ,iBAAiB,YAAY,SAAS,UAAU,MAAM;AACnG,eAAWC,KAAYD,GAAkB;AACxC,YAAME,IAAKnB,EAAEkB,CAAQ,EAAE,MAAA;AACvB,UAAIC,EAAG,UAAUA,EAAG,KAAA,EAAO,KAAA,EAAO,SAAS,KAAK;AAC/C,QAAAH,IAAUG,EAAG,KAAA;AACb;AAAA,MACD;AAAA,IACD;AACA,WAAKH,MAASA,IAAUhB,EAAE,MAAM,EAAE,KAAA,IAClCgB,IAAUA,EAAQ,QAAQ,QAAQ,GAAG,EAAE,OAAO,MAAM,GAAG,GAAI,GAEpD,EAAC,KAAK/E,EAAK,KAAK,OAAO8E,EAAS,MAAM,KAAA,GAAQ,aAAaA,EAAS,YAAY,KAAA,GAAQ,SAAAC,GAAS,OAAO/E,EAAK,MAAA;AAAA,EACrH;AACD,GAEamF,KAAwB;AAAA,EACpC,MAAM;AAAA,EACN,aAAa;AAAA,EACb,MAAM;AAAA,IACL,OAAO,EAAC,MAAM,UAAU,aAAa,iBAAiB,UAAU,GAAA;AAAA,IAChE,QAAQ,EAAC,MAAM,UAAU,aAAa,+BAA+B,SAAS,EAAA;AAAA,EAAC;AAAA,EAEhF,IAAI,OAAOnF,MAGL;AACL,UAAM2E,IAAO,MAAM,MAAM,uCAAuC,mBAAmB3E,EAAK,KAAK,CAAC,IAAI;AAAA,MACjG,SAAS,EAAC,cAAc,6CAA6C,mBAAmB,iBAAA;AAAA,IAAgB,CACxG,EAAE,KAAK,CAAAvB,MAAQA,EAAK,MAAM;AAC3B,QAAI2G,GAAOC,IAAQ;AACnB,UAAMpG,IAAU,IAAIqG,EAAA;AACpB,YAAOF,IAAQC,EAAM,KAAKV,CAAI,OAAO,QAAM;AAC1C,UAAIY,IAAM,iBAAiB,KAAK,mBAAmBH,EAAM,CAAC,CAAC,CAAC,IAAI,CAAC;AAGjE,UAFGG,MAAKA,IAAM,mBAAmBA,CAAG,IACjCA,KAAKtG,EAAQ,IAAIsG,CAAG,GACpBtG,EAAQ,SAASe,EAAK,UAAU,GAAI;AAAA,IACxC;AACA,WAAOf;AAAA,EACR;AACD;"}
|
|
1
|
+
{"version":3,"file":"index.mjs","sources":["../src/provider.ts","../src/antrhopic.ts","../src/open-ai.ts","../src/llm.ts","../src/audio.ts","../src/vision.ts","../src/ai.ts","../src/tools.ts"],"sourcesContent":["import {AbortablePromise} from './ai.ts';\nimport {LLMMessage, LLMRequest} from './llm.ts';\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 {AbortablePromise, Ai} from './ai.ts';\nimport {LLMMessage, LLMRequest} from './llm.ts';\nimport {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 = [...options.history || [], {role: 'user', content: message, timestamp: Date.now()}];\n\t\t\tif(options.compress) history = await this.ai.language.compressHistory(<any>history, options.compress.max, options.compress.min, options);\n\t\t\thistory = this.fromStandard(<any>history);\n\n\t\t\tconst tools = options.tools || this.ai.options.llm?.tools || [];\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.llm?.max_tokens || 4096,\n\t\t\t\tsystem: options.system || this.ai.options.llm?.system || '',\n\t\t\t\ttemperature: options.temperature || this.ai.options.llm?.temperature || 0.7,\n\t\t\t\ttools: 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, isFirstMessage = true;\n\t\t\tconst assistantMessages: string[] = [];\n\t\t\tdo {\n\t\t\t\tresp = await this.client.messages.create(requestParams).catch(err => {\n\t\t\t\t\terr.message += `\\n\\nMessages:\\n${JSON.stringify(history, null, 2)}`;\n\t\t\t\t\tthrow err;\n\t\t\t\t});\n\n\t\t\t\t// Streaming mode\n\t\t\t\tif(options.stream) {\n\t\t\t\t\tif(!isFirstMessage) options.stream({text: '\\n\\n'});\n\t\t\t\t\telse isFirstMessage = false;\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\t// Run tools\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 = tools.find(findByProp('name', toolCall.name));\n\t\t\t\t\t\tif(options.stream) options.stream({tool: 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\thistory.push({role: 'user', content: results});\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\tif(options.stream) options.stream({done: true});\n\t\t\tres(this.toStandard([...history, {role: 'assistant', content: resp.content.filter((c: any) => c.type == 'text').map((c: any) => c.text).join('\\n\\n')}]));\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, clean} from '@ztimson/utils';\nimport {AbortablePromise, Ai} from './ai.ts';\nimport {LLMMessage, LLMRequest} from './llm.ts';\nimport {LLMProvider} from './provider.ts';\n\nexport class OpenAi extends LLMProvider {\n\tclient!: openAI;\n\n\tconstructor(public readonly ai: Ai, public readonly host: string | null, public readonly token: string, public model: string) {\n\t\tsuper();\n\t\tthis.client = new openAI(clean({\n\t\t\tbaseURL: host,\n\t\t\tapiKey: token\n\t\t}));\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 = [...options.history || [], {role: 'user', content: message, timestamp: Date.now()}];\n\t\t\tif(options.compress) history = await this.ai.language.compressHistory(<any>history, options.compress.max, options.compress.min, options);\n\t\t\thistory = this.fromStandard(<any>history);\n\n\t\t\tconst tools = options.tools || this.ai.options.llm?.tools || [];\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.llm?.max_tokens || 4096,\n\t\t\t\ttemperature: options.temperature || this.ai.options.llm?.temperature || 0.7,\n\t\t\t\ttools: 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, isFirstMessage = true;\n\t\t\tdo {\n\t\t\t\tresp = await this.client.chat.completions.create(requestParams).catch(err => {\n\t\t\t\t\terr.message += `\\n\\nMessages:\\n${JSON.stringify(history, null, 2)}`;\n\t\t\t\t\tthrow err;\n\t\t\t\t});\n\n\t\t\t\tif(options.stream) {\n\t\t\t\t\tif(!isFirstMessage) options.stream({text: '\\n\\n'});\n\t\t\t\t\telse isFirstMessage = false;\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\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 = tools?.find(findByProp('name', toolCall.function.name));\n\t\t\t\t\t\tif(options.stream) options.stream({tool: 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\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\tif(options.stream) options.stream({done: true});\n\t\t\tres(this.toStandard([...history, {role: 'assistant', content: resp.choices[0].message.content || ''}]));\n\t\t});\n\t\treturn Object.assign(response, {abort: () => controller.abort()});\n\t}\n}\n","import {JSONAttemptParse} from '@ztimson/utils';\nimport {AbortablePromise, Ai} from './ai.ts';\nimport {Anthropic} from './antrhopic.ts';\nimport {OpenAi} from './open-ai.ts';\nimport {LLMProvider} from './provider.ts';\nimport {AiTool} from './tools.ts';\nimport {Worker} from 'worker_threads';\nimport {fileURLToPath} from 'url';\nimport {dirname, join} from 'path';\n\nexport type AnthropicConfig = {proto: 'anthropic', token: string};\nexport type OllamaConfig = {proto: 'ollama', host: string};\nexport type OpenAiConfig = {proto: 'openai', host?: string, token: string};\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 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;\n\t/** Stream response */\n\tstream?: (chunk: {text?: string, tool?: 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 embedWorker: Worker | null = null;\n\tprivate embedQueue = new Map<number, { resolve: (value: number[]) => void; reject: (error: any) => void }>();\n\tprivate embedId = 0;\n\tprivate models: {[model: string]: LLMProvider} = {};\n\tprivate defaultModel!: string;\n\n\tconstructor(public readonly ai: Ai) {\n\t\tthis.embedWorker = new Worker(join(dirname(fileURLToPath(import.meta.url)), 'embedder.js'));\n\t\tthis.embedWorker.on('message', ({ id, embedding }) => {\n\t\t\tconst pending = this.embedQueue.get(id);\n\t\t\tif (pending) {\n\t\t\t\tpending.resolve(embedding);\n\t\t\t\tthis.embedQueue.delete(id);\n\t\t\t}\n\t\t});\n\n\t\tif(!ai.options.llm?.models) return;\n\t\tObject.entries(ai.options.llm.models).forEach(([model, config]) => {\n\t\t\tif(!this.defaultModel) this.defaultModel = model;\n\t\t\tif(config.proto == 'anthropic') this.models[model] = new Anthropic(this.ai, config.token, model);\n\t\t\telse if(config.proto == 'ollama') this.models[model] = new OpenAi(this.ai, config.host, 'not-needed', model);\n\t\t\telse if(config.proto == 'openai') this.models[model] = new OpenAi(this.ai, config.host || null, config.token, model);\n\t\t});\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\tconst m = options.model || this.defaultModel;\n\t\tif(!this.models[m]) throw new Error(`Model does not exist: ${m}`);\n\t\treturn this.models[m].ask(message, options);\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 compressHistory(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\tcosineSimilarity(v1: number[], v2: number[]): number {\n\t\tif (v1.length !== v2.length) throw new Error('Vectors must be same length');\n\t\tlet dotProduct = 0, normA = 0, normB = 0;\n\t\tfor (let i = 0; i < v1.length; i++) {\n\t\t\tdotProduct += v1[i] * v2[i];\n\t\t\tnormA += v1[i] * v1[i];\n\t\t\tnormB += v2[i] * v2[i];\n\t\t}\n\t\tconst denominator = Math.sqrt(normA) * Math.sqrt(normB);\n\t\treturn denominator === 0 ? 0 : dotProduct / denominator;\n\t}\n\n\tchunk(target: object | string, maxTokens = 500, overlapTokens = 50): string[] {\n\t\tconst objString = (obj: any, path = ''): string[] => {\n\t\t\tif(!obj) return [];\n\t\t\treturn Object.entries(obj).flatMap(([key, value]) => {\n\t\t\t\tconst p = path ? `${path}${isNaN(+key) ? `.${key}` : `[${key}]`}` : key;\n\t\t\t\tif(typeof value === 'object' && !Array.isArray(value)) return objString(value, p);\n\t\t\t\treturn `${p}: ${Array.isArray(value) ? value.join(', ') : value}`;\n\t\t\t});\n\t\t};\n\n\t\tconst lines = typeof target === 'object' ? objString(target) : target.split('\\n');\n\t\tconst tokens = lines.flatMap(l => [...l.split(/\\s+/).filter(Boolean), '\\n']);\n\t\tconst chunks: string[] = [];\n\t\tfor(let i = 0; i < tokens.length;) {\n\t\t\tlet text = '', j = i;\n\t\t\twhile(j < tokens.length) {\n\t\t\t\tconst next = text + (text ? ' ' : '') + tokens[j];\n\t\t\t\tif(this.estimateTokens(next.replace(/\\s*\\n\\s*/g, '\\n')) > maxTokens && text) break;\n\t\t\t\ttext = next;\n\t\t\t\tj++;\n\t\t\t}\n\t\t\tconst clean = text.replace(/\\s*\\n\\s*/g, '\\n').trim();\n\t\t\tif(clean) chunks.push(clean);\n\t\t\ti = Math.max(j - overlapTokens, j === i ? i + 1 : j);\n\t\t}\n\t\treturn chunks;\n\t}\n\n\tembedding(target: object | string, maxTokens = 500, overlapTokens = 50) {\n\t\tconst embed = (text: string): Promise<number[]> => {\n\t\t\treturn new Promise((resolve, reject) => {\n\t\t\t\tconst id = this.embedId++;\n\t\t\t\tthis.embedQueue.set(id, { resolve, reject });\n\t\t\t\tthis.embedWorker?.postMessage({ id, text });\n\t\t\t});\n\t\t};\n\n\t\tconst chunks = this.chunk(target, maxTokens, overlapTokens);\n\t\treturn Promise.all(chunks.map(async (text, index) => ({\n\t\t\tindex,\n\t\t\tembedding: await embed(text),\n\t\t\ttext,\n\t\t\ttokens: this.estimateTokens(text),\n\t\t})));\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 * 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\tfuzzyMatch(target: string, ...searchTerms: string[]) {\n\t\tif(searchTerms.length < 2) throw new Error('Requires at least 2 strings to compare');\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\t\tconst v = vector(target);\n\t\tconst similarities = searchTerms.map(t => vector(t)).map(refVector => this.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\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 {spawn} from 'node:child_process';\nimport fs from 'node:fs/promises';\nimport Path from 'node:path';\nimport {AbortablePromise, Ai} from './ai.ts';\n\nexport class Audio {\n\tprivate downloads: {[key: string]: Promise<string>} = {};\n\tprivate whisperModel!: string;\n\n\tconstructor(private ai: Ai) {\n\t\tif(ai.options.whisper?.binary) {\n\t\t\tthis.whisperModel = ai.options.whisper?.model.endsWith('.bin') ? ai.options.whisper?.model : ai.options.whisper?.model + '.bin';\n\t\t\tthis.downloadAsrModel();\n\t\t}\n\t}\n\n\tasr(path: string, model: string = this.whisperModel): AbortablePromise<string | null> {\n\t\tif(!this.ai.options.whisper?.binary) throw new Error('Whisper not configured');\n\t\tlet abort: any = () => {};\n\t\tconst p = new Promise<string | null>(async (resolve, reject) => {\n\t\t\tconst m = await this.downloadAsrModel(model);\n\t\t\tlet output = '';\n\t\t\tconst proc = spawn(<string>this.ai.options.whisper?.binary, ['-nt', '-np', '-m', m, '-f', path], {stdio: ['ignore', 'pipe', 'ignore']});\n\t\t\tabort = () => proc.kill('SIGTERM');\n\t\t\tproc.on('error', (err: Error) => reject(err));\n\t\t\tproc.stdout.on('data', (data: Buffer) => output += data.toString());\n\t\t\tproc.on('close', (code: number) => {\n\t\t\t\tif(code === 0) resolve(output.trim() || null);\n\t\t\t\telse reject(new Error(`Exit code ${code}`));\n\t\t\t});\n\t\t});\n\t\treturn Object.assign(p, {abort});\n\t}\n\n\tasync downloadAsrModel(model: string = this.whisperModel): Promise<string> {\n\t\tif(!this.ai.options.whisper?.binary) throw new Error('Whisper not configured');\n\t\tif(!model.endsWith('.bin')) model += '.bin';\n\t\tconst p = Path.join(<string>this.ai.options.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","import {createWorker} from 'tesseract.js';\nimport {AbortablePromise, Ai} from './ai.ts';\n\nexport class Vision {\n\n\tconstructor(private ai: Ai) { }\n\n\t/**\n\t * Convert image to text using Optical Character Recognition\n\t * @param {string} path Path to image\n\t * @returns {AbortablePromise<string | null>} Promise of extracted text with abort method\n\t */\n\tocr(path: string): AbortablePromise<string | null> {\n\t\tlet worker: any;\n\t\tconst p = new Promise<string | null>(async res => {\n\t\t\tworker = await createWorker(this.ai.options.tesseract?.model || 'eng', 2, {cachePath: this.ai.options.path});\n\t\t\tconst {data} = await worker.recognize(path);\n\t\t\tawait worker.terminate();\n\t\t\tres(data.text.trim() || null);\n\t\t});\n\t\treturn Object.assign(p, {abort: () => worker?.terminate()});\n\t}\n}\n","import * as os from 'node:os';\nimport {LLM, AnthropicConfig, OllamaConfig, OpenAiConfig, LLMRequest} from './llm';\nimport { Audio } from './audio.ts';\nimport {Vision} from './vision.ts';\n\nexport type AbortablePromise<T> = Promise<T> & {abort: () => any};\n\nexport type AiOptions = {\n\t/** Path to models */\n\tpath?: string;\n\t/** Large language models, first is default */\n\tllm?: Omit<LLMRequest, 'model'> & {\n\t\tmodels: {[model: string]: AnthropicConfig | OllamaConfig | OpenAiConfig};\n\t}\n\t/** Tesseract OCR configuration */\n\ttesseract?: {\n\t\t/** Model: eng, eng_best, eng_fast */\n\t\tmodel?: string;\n\t}\n\t/** Whisper ASR configuration */\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}\n}\n\nexport class Ai {\n\t/** Audio processing AI */\n\taudio!: Audio;\n\t/** Language processing AI */\n\tlanguage!: LLM;\n\t/** Vision processing AI */\n\tvision!: Vision;\n\n\tconstructor(public readonly options: AiOptions) {\n\t\tif(!options.path) options.path = os.tmpdir();\n\t\tprocess.env.TRANSFORMERS_CACHE = options.path;\n\t\tthis.audio = new Audio(this);\n\t\tthis.language = new LLM(this);\n\t\tthis.vision = new Vision(this);\n\t}\n}\n","import * as cheerio from 'cheerio';\nimport {$, $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 UTC date / time',\n\targs: {},\n\tfn: async () => new Date().toUTCString()\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 ReadWebpageTool: AiTool = {\n\tname: 'read_webpage',\n\tdescription: 'Extract clean, structured content from a webpage. Use after web_search to read specific URLs',\n\targs: {\n\t\turl: {type: 'string', description: 'URL to extract content from', required: true},\n\t\tfocus: {type: 'string', description: 'Optional: What aspect to focus on (e.g., \"pricing\", \"features\", \"contact info\")'}\n\t},\n\tfn: async (args: {url: string; focus?: string}) => {\n\t\tconst html = await fetch(args.url, {headers: {\"User-Agent\": \"Mozilla/5.0 (Windows NT 10.0; Win64; x64)\"}})\n\t\t\t.then(r => r.text()).catch(err => {throw new Error(`Failed to fetch: ${err.message}`)});\n\n\t\tconst $ = cheerio.load(html);\n\t\t$('script, style, nav, footer, header, aside, iframe, noscript, [role=\"navigation\"], [role=\"banner\"], .ad, .ads, .cookie, .popup').remove();\n\t\tconst metadata = {\n\t\t\ttitle: $('meta[property=\"og:title\"]').attr('content') || $('title').text() || '',\n\t\t\tdescription: $('meta[name=\"description\"]').attr('content') || $('meta[property=\"og:description\"]').attr('content') || '',\n\t\t};\n\n\t\tlet content = '';\n\t\tconst contentSelectors = ['article', 'main', '[role=\"main\"]', '.content', '.post', '.entry', 'body'];\n\t\tfor (const selector of contentSelectors) {\n\t\t\tconst el = $(selector).first();\n\t\t\tif (el.length && el.text().trim().length > 200) {\n\t\t\t\tcontent = el.text();\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tif (!content) content = $('body').text();\n\t\tcontent = content.replace(/\\s+/g, ' ').trim().slice(0, 8000);\n\n\t\treturn {url: args.url, title: metadata.title.trim(), description: metadata.description.trim(), content, focus: args.focus};\n\t}\n}\n\nexport const WebSearchTool: AiTool = {\n\tname: 'web_search',\n\tdescription: 'Use duckduckgo (anonymous) to find find relevant online resources. Returns a list of URLs that works great with the `read_webpage` tool',\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","tools","requestParams","t","objectMap","key","value","resp","isFirstMessage","err","chunk","text","last","JSONAttemptParse","toolCalls","results","toolCall","tool","findByProp","result","JSONSanitize","OpenAi","host","token","openAI","clean","tc","record","h2","rest","args","LLM","Worker","join","dirname","fileURLToPath","id","embedding","pending","config","m","max","min","keep","tokens","recent","process","v1","v2","dotProduct","normA","normB","denominator","target","maxTokens","overlapTokens","objString","obj","path","p","l","chunks","j","next","embed","resolve","reject","index","searchTerms","vector","dimensions","char","v","similarities","refVector","acc","Audio","abort","output","proc","spawn","data","code","Path","fs","arr","buffer","Vision","worker","createWorker","Ai","os","CliTool","$","DateTimeTool","ExecTool","JSTool","PythonTool","FetchTool","Http","console","consoleInterceptor","Fn","$Sync","ReadWebpageTool","html","r","cheerio","metadata","content","contentSelectors","selector","el","WebSearchTool","match","regex","ASet","url"],"mappings":"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"}
|