@ztimson/ai-utils 0.1.19 → 0.1.20

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 CHANGED
@@ -1,20 +1,20 @@
1
- (function(p,b){typeof exports=="object"&&typeof module<"u"?b(exports,require("tesseract.js"),require("@ztimson/utils"),require("@anthropic-ai/sdk"),require("ollama"),require("openai"),require("node:fs/promises"),require("node:path"),require("@tensorflow/tfjs"),require("node:child_process"),require("@ztimson/node-utils")):typeof define=="function"&&define.amd?define(["exports","tesseract.js","@ztimson/utils","@anthropic-ai/sdk","ollama","openai","node:fs/promises","node:path","@tensorflow/tfjs","node:child_process","@ztimson/node-utils"],b):(p=typeof globalThis<"u"?globalThis:p||self,b(p.utils={},p.tesseract_js,p.utils,p.sdk,p.ollama,p.openai,p.fs,p.Path,p.tf,p.node_child_process,p.nodeUtils))})(this,(function(p,b,f,A,M,D,j,E,J,N,x){"use strict";function z(u){const t=Object.create(null,{[Symbol.toStringTag]:{value:"Module"}});if(u){for(const e in u)if(e!=="default"){const n=Object.getOwnPropertyDescriptor(u,e);Object.defineProperty(t,e,n.get?n:{enumerable:!0,get:()=>u[e]})}}return t.default=u,Object.freeze(t)}const S=z(J);class k{}class T extends k{constructor(t,e,n){super(),this.ai=t,this.apiToken=e,this.model=n,this.client=new A.Anthropic({apiKey:e})}client;toStandard(t){for(let e=0;e<t.length;e++){const n=e;typeof t[n].content!="string"&&(t[n].role=="assistant"?t[n].content.filter(s=>s.type=="tool_use").forEach(s=>{e++,t.splice(e,0,{role:"tool",id:s.id,name:s.name,args:s.input,timestamp:Date.now()})}):t[n].role=="user"&&t[n].content.filter(s=>s.type=="tool_result").forEach(s=>{const l=t.find(h=>h.id==s.tool_use_id);l[s.is_error?"error":"content"]=s.content}),t[n].content=t[n].content.filter(s=>s.type=="text").map(s=>s.text).join(`
1
+ (function(p,b){typeof exports=="object"&&typeof module<"u"?b(exports,require("tesseract.js"),require("@ztimson/utils"),require("@anthropic-ai/sdk"),require("ollama"),require("openai"),require("node:fs/promises"),require("node:path"),require("@tensorflow/tfjs"),require("node:child_process"),require("@ztimson/node-utils")):typeof define=="function"&&define.amd?define(["exports","tesseract.js","@ztimson/utils","@anthropic-ai/sdk","ollama","openai","node:fs/promises","node:path","@tensorflow/tfjs","node:child_process","@ztimson/node-utils"],b):(p=typeof globalThis<"u"?globalThis:p||self,b(p.utils={},p.tesseract_js,p.utils,p.sdk,p.ollama,p.openai,p.fs,p.Path,p.tf,p.node_child_process,p.nodeUtils))})(this,(function(p,b,f,A,M,E,j,D,J,N,x){"use strict";function z(d){const t=Object.create(null,{[Symbol.toStringTag]:{value:"Module"}});if(d){for(const e in d)if(e!=="default"){const n=Object.getOwnPropertyDescriptor(d,e);Object.defineProperty(t,e,n.get?n:{enumerable:!0,get:()=>d[e]})}}return t.default=d,Object.freeze(t)}const S=z(J);class k{}class T extends k{constructor(t,e,n){super(),this.ai=t,this.apiToken=e,this.model=n,this.client=new A.Anthropic({apiKey:e})}client;toStandard(t){for(let e=0;e<t.length;e++){const n=e;typeof t[n].content!="string"&&(t[n].role=="assistant"?t[n].content.filter(s=>s.type=="tool_use").forEach(s=>{e++,t.splice(e,0,{role:"tool",id:s.id,name:s.name,args:s.input,timestamp:Date.now()})}):t[n].role=="user"&&t[n].content.filter(s=>s.type=="tool_result").forEach(s=>{const c=t.find(g=>g.id==s.tool_use_id);c[s.is_error?"error":"content"]=s.content}),t[n].content=t[n].content.filter(s=>s.type=="text").map(s=>s.text).join(`
2
2
 
3
- `)),t[n].timestamp||(t[n].timestamp=Date.now())}return t.filter(e=>!!e.content)}fromStandard(t){for(let e=0;e<t.length;e++)if(t[e].role=="tool"){const n=t[e];t.splice(e,1,{role:"assistant",content:[{type:"tool_use",id:n.id,name:n.name,input:n.args}]},{role:"user",content:[{type:"tool_result",tool_use_id:n.id,is_error:!!n.error,content:n.error||n.content}]}),e++}return t.map(({timestamp:e,...n})=>n)}ask(t,e={}){const n=new AbortController,s=new Promise(async(l,h)=>{let m=this.fromStandard([...e.history||[],{role:"user",content:t,timestamp:Date.now()}]);e.compress&&(m=await this.ai.llm.compress(m,e.compress.max,e.compress.min,e));const d={model:e.model||this.model,max_tokens:e.max_tokens||this.ai.options.max_tokens||4096,system:e.system||this.ai.options.system||"",temperature:e.temperature||this.ai.options.temperature||.7,tools:(e.tools||this.ai.options.tools||[]).map(a=>({name:a.name,description:a.description,input_schema:{type:"object",properties:a.args?f.objectMap(a.args,(o,i)=>({...i,required:void 0})):{},required:a.args?Object.entries(a.args).filter(o=>o[1].required).map(o=>o[0]):[]},fn:void 0})),messages:m,stream:!!e.stream};let c;const r=[];do{if(c=await this.client.messages.create(d),e.stream){r.length&&e.stream({text:`
3
+ `)),t[n].timestamp||(t[n].timestamp=Date.now())}return t.filter(e=>!!e.content)}fromStandard(t){for(let e=0;e<t.length;e++)if(t[e].role=="tool"){const n=t[e];t.splice(e,1,{role:"assistant",content:[{type:"tool_use",id:n.id,name:n.name,input:n.args}]},{role:"user",content:[{type:"tool_result",tool_use_id:n.id,is_error:!!n.error,content:n.error||n.content}]}),e++}return t.map(({timestamp:e,...n})=>n)}ask(t,e={}){const n=new AbortController,s=new Promise(async(c,g)=>{let l=this.fromStandard([...e.history||[],{role:"user",content:t,timestamp:Date.now()}]);e.compress&&(l=await this.ai.llm.compress(l,e.compress.max,e.compress.min,e));const m={model:e.model||this.model,max_tokens:e.max_tokens||this.ai.options.max_tokens||4096,system:e.system||this.ai.options.system||"",temperature:e.temperature||this.ai.options.temperature||.7,tools:(e.tools||this.ai.options.tools||[]).map(h=>({name:h.name,description:h.description,input_schema:{type:"object",properties:h.args?f.objectMap(h.args,(u,o)=>({...o,required:void 0})):{},required:h.args?Object.entries(h.args).filter(u=>u[1].required).map(u=>u[0]):[]},fn:void 0})),messages:l,stream:!!e.stream};let i;const r=[];do{if(i=await this.client.messages.create(m),e.stream){r.length&&e.stream({text:`
4
4
 
5
- `}),c.content=[];for await(const o of c){if(n.signal.aborted)break;if(o.type==="content_block_start")o.content_block.type==="text"?c.content.push({type:"text",text:""}):o.content_block.type==="tool_use"&&c.content.push({type:"tool_use",id:o.content_block.id,name:o.content_block.name,input:""});else if(o.type==="content_block_delta")if(o.delta.type==="text_delta"){const i=o.delta.text;c.content.at(-1).text+=i,e.stream({text:i})}else o.delta.type==="input_json_delta"&&(c.content.at(-1).input+=o.delta.partial_json);else if(o.type==="content_block_stop"){const i=c.content.at(-1);i.input!=null&&(i.input=i.input?f.JSONAttemptParse(i.input,{}):{})}else if(o.type==="message_stop")break}}r.push({role:"assistant",content:c.content,timestamp:Date.now()});const a=c.content.filter(o=>o.type==="tool_use");if(a.length&&!n.signal.aborted){m.push({role:"assistant",content:c.content});const i={role:"user",content:await Promise.all(a.map(async g=>{const w=e.tools?.find(f.findByProp("name",g.name));if(!w)return{tool_use_id:g.id,is_error:!0,content:"Tool not found"};try{const _=await w.fn(g.input,this.ai);return{type:"tool_result",tool_use_id:g.id,content:f.JSONSanitize(_)}}catch(_){return{type:"tool_result",tool_use_id:g.id,is_error:!0,content:_?.message||_?.toString()||"Unknown"}}}))};m.push(i),r.push({...i,timestamp:Date.now()}),d.messages=m}}while(!n.signal.aborted&&c.content.some(a=>a.type==="tool_use"));const y=r.filter(a=>a.role==="assistant").map(a=>a.content.filter(o=>o.type=="text").map(o=>o.text).join(`
5
+ `}),i.content=[];for await(const o of i){if(n.signal.aborted)break;if(o.type==="content_block_start")o.content_block.type==="text"?i.content.push({type:"text",text:""}):o.content_block.type==="tool_use"&&i.content.push({type:"tool_use",id:o.content_block.id,name:o.content_block.name,input:""});else if(o.type==="content_block_delta")if(o.delta.type==="text_delta"){const a=o.delta.text;i.content.at(-1).text+=a,e.stream({text:a})}else o.delta.type==="input_json_delta"&&(i.content.at(-1).input+=o.delta.partial_json);else if(o.type==="content_block_stop"){const a=i.content.at(-1);a.input!=null&&(a.input=a.input?f.JSONAttemptParse(a.input,{}):{})}else if(o.type==="message_stop")break}}const h=i.content.filter(o=>o.type=="text").map(o=>o.text).join(`
6
6
 
7
- `)).filter(a=>a).join(`
7
+ `);h&&r.push(h);const u=i.content.filter(o=>o.type==="tool_use");if(u.length&&!n.signal.aborted){l.push({role:"assistant",content:i.content});const o=await Promise.all(u.map(async a=>{const _=e.tools?.find(f.findByProp("name",a.name));if(!_)return{tool_use_id:a.id,is_error:!0,content:"Tool not found"};try{const w=await _.fn(a.input,this.ai);return{type:"tool_result",tool_use_id:a.id,content:f.JSONSanitize(w)}}catch(w){return{type:"tool_result",tool_use_id:a.id,is_error:!0,content:w?.message||w?.toString()||"Unknown"}}}));l.push({role:"user",content:o}),m.messages=l}}while(!n.signal.aborted&&i.content.some(h=>h.type==="tool_use"));e.stream&&e.stream({done:!0}),c(this.toStandard([...l,{role:"assistant",content:r.join(`
8
8
 
9
- `);e.stream&&e.stream({done:!0}),l(this.toStandard([...m,{role:"assistant",content:y,timestamp:Date.now()}]))});return Object.assign(s,{abort:()=>n.abort()})}}class U extends k{constructor(t,e,n){super(),this.ai=t,this.host=e,this.model=n,this.client=new M.Ollama({host:e})}client;toStandard(t){for(let e=0;e<t.length;e++){if(t[e].role=="assistant"&&t[e].tool_calls)t[e].content?delete t[e].tool_calls:(t.splice(e,1),e--);else if(t[e].role=="tool"){const n=t[e].content.startsWith('{"error":');t[e]={role:"tool",name:t[e].tool_name,args:t[e].args,[n?"error":"content"]:t[e].content,timestamp:t[e].timestamp}}t[e]?.timestamp||(t[e].timestamp=Date.now())}return t}fromStandard(t){return t.map(e=>{const{timestamp:n,...s}=e;return e.role!="tool"?s:{role:"tool",tool_name:e.name,content:e.error||e.content}})}ask(t,e={}){const n=new AbortController,s=new Promise(async(l,h)=>{let m=e.system||this.ai.options.system,d=this.fromStandard([...e.history||[],{role:"user",content:t,timestamp:Date.now()}]);d[0].roll=="system"&&(m?d.shift():m=d.shift()),e.compress&&(d=await this.ai.llm.compress(d,e.compress.max,e.compress.min)),e.system&&d.unshift({role:"system",content:m});const c={model:e.model||this.model,messages:d,stream:!!e.stream,signal:n.signal,options:{temperature:e.temperature||this.ai.options.temperature||.7,num_predict:e.max_tokens||this.ai.options.max_tokens||4096},tools:(e.tools||this.ai.options.tools||[]).map(o=>({type:"function",function:{name:o.name,description:o.description,parameters:{type:"object",properties:o.args?f.objectMap(o.args,(i,g)=>({...g,required:void 0})):{},required:o.args?Object.entries(o.args).filter(i=>i[1].required).map(i=>i[0]):[]}}}))};let r;const y=[];do{if(r=await this.client.chat(c),e.stream){y.length&&e.stream({text:`
9
+ `),timestamp:Date.now()}]))});return Object.assign(s,{abort:()=>n.abort()})}}class U extends k{constructor(t,e,n){super(),this.ai=t,this.host=e,this.model=n,this.client=new M.Ollama({host:e})}client;toStandard(t){for(let e=0;e<t.length;e++){if(t[e].role=="assistant"&&t[e].tool_calls)t[e].content?delete t[e].tool_calls:(t.splice(e,1),e--);else if(t[e].role=="tool"){const n=t[e].content.startsWith('{"error":');t[e]={role:"tool",name:t[e].tool_name,args:t[e].args,[n?"error":"content"]:t[e].content,timestamp:t[e].timestamp}}t[e]?.timestamp||(t[e].timestamp=Date.now())}return t}fromStandard(t){return t.map(e=>{const{timestamp:n,...s}=e;return e.role!="tool"?s:{role:"tool",tool_name:e.name,content:e.error||e.content}})}ask(t,e={}){const n=new AbortController,s=new Promise(async(c,g)=>{let l=e.system||this.ai.options.system,m=this.fromStandard([...e.history||[],{role:"user",content:t,timestamp:Date.now()}]);m[0].roll=="system"&&(l?m.shift():l=m.shift()),e.compress&&(m=await this.ai.llm.compress(m,e.compress.max,e.compress.min)),e.system&&m.unshift({role:"system",content:l});const i={model:e.model||this.model,messages:m,stream:!!e.stream,signal:n.signal,options:{temperature:e.temperature||this.ai.options.temperature||.7,num_predict:e.max_tokens||this.ai.options.max_tokens||4096},tools:(e.tools||this.ai.options.tools||[]).map(o=>({type:"function",function:{name:o.name,description:o.description,parameters:{type:"object",properties:o.args?f.objectMap(o.args,(a,_)=>({..._,required:void 0})):{},required:o.args?Object.entries(o.args).filter(a=>a[1].required).map(a=>a[0]):[]}}}))};let r;const h=[];do{if(r=await this.client.chat(i),e.stream){h.length&&e.stream({text:`
10
10
 
11
- `}),r.message={role:"assistant",content:"",tool_calls:[]};for await(const o of r)if(n.signal.aborted||(o.message?.content&&(r.message.content+=o.message.content,e.stream({text:o.message.content})),o.message?.tool_calls&&(r.message.tool_calls=o.message.tool_calls),o.done))break}if(y.push({role:"assistant",content:r.message?.content,timestamp:Date.now()}),r.message?.tool_calls?.length&&!n.signal.aborted){d.push(r.message);const o=await Promise.all(r.message.tool_calls.map(async i=>{const g=(e.tools||this.ai.options.tools)?.find(f.findByProp("name",i.function.name));if(!g)return{role:"tool",tool_name:i.function.name,content:'{"error": "Tool not found"}'};const w=typeof i.function.arguments=="string"?f.JSONAttemptParse(i.function.arguments,{}):i.function.arguments;try{const _=await g.fn(w,this.ai);return{role:"tool",tool_name:i.function.name,args:w,content:f.JSONSanitize(_)}}catch(_){return{role:"tool",tool_name:i.function.name,args:w,content:f.JSONSanitize({error:_?.message||_?.toString()||"Unknown"})}}}));d.push(...o),y.push(...o.map(i=>({...i,timestamp:Date.now()}))),c.messages=d}}while(!n.signal.aborted&&r.message?.tool_calls?.length);const a=y.filter(o=>o.role==="assistant").map(o=>o.content).filter(o=>o).join(`
11
+ `}),r.message={role:"assistant",content:"",tool_calls:[]};for await(const o of r)if(n.signal.aborted||(o.message?.content&&(r.message.content+=o.message.content,e.stream({text:o.message.content})),o.message?.tool_calls&&(r.message.tool_calls=o.message.tool_calls),o.done))break}if(h.push({role:"assistant",content:r.message?.content,timestamp:Date.now()}),r.message?.tool_calls?.length&&!n.signal.aborted){m.push(r.message);const o=await Promise.all(r.message.tool_calls.map(async a=>{const _=(e.tools||this.ai.options.tools)?.find(f.findByProp("name",a.function.name));if(!_)return{role:"tool",tool_name:a.function.name,content:'{"error": "Tool not found"}'};const w=typeof a.function.arguments=="string"?f.JSONAttemptParse(a.function.arguments,{}):a.function.arguments;try{const y=await _.fn(w,this.ai);return{role:"tool",tool_name:a.function.name,args:w,content:f.JSONSanitize(y)}}catch(y){return{role:"tool",tool_name:a.function.name,args:w,content:f.JSONSanitize({error:y?.message||y?.toString()||"Unknown"})}}}));m.push(...o),h.push(...o.map(a=>({...a,timestamp:Date.now()}))),i.messages=m}}while(!n.signal.aborted&&r.message?.tool_calls?.length);const u=h.filter(o=>o.role==="assistant").map(o=>o.content).filter(o=>o).join(`
12
12
 
13
- `);e.stream&&e.stream({done:!0}),l(this.toStandard([...d,{role:"assistant",content:a,timestamp:Date.now()}]))});return Object.assign(s,{abort:()=>n.abort()})}}class L extends k{constructor(t,e,n){super(),this.ai=t,this.apiToken=e,this.model=n,this.client=new D.OpenAI({apiKey:e})}client;toStandard(t){for(let e=0;e<t.length;e++){const n=t[e];if(n.role==="assistant"&&n.tool_calls){const s=n.tool_calls.map(l=>({role:"tool",id:l.id,name:l.function.name,args:f.JSONAttemptParse(l.function.arguments,{}),timestamp:n.timestamp}));t.splice(e,1,...s),e+=s.length-1}else if(n.role==="tool"&&n.content){const s=t.find(l=>n.tool_call_id==l.id);s&&(n.content.includes('"error":')?s.error=n.content:s.content=n.content),t.splice(e,1),e--}t[e]?.timestamp||(t[e].timestamp=Date.now())}return t}fromStandard(t){return t.reduce((e,n)=>{if(n.role==="tool")e.push({role:"assistant",content:null,tool_calls:[{id:n.id,type:"function",function:{name:n.name,arguments:JSON.stringify(n.args)}}],refusal:null,annotations:[]},{role:"tool",tool_call_id:n.id,content:n.error||n.content});else{const{timestamp:s,...l}=n;e.push(l)}return e},[])}ask(t,e={}){const n=new AbortController,s=new Promise(async(l,h)=>{let m=this.fromStandard([...e.history||[],{role:"user",content:t,timestamp:Date.now()}]);e.compress&&(m=await this.ai.llm.compress(m,e.compress.max,e.compress.min,e));const d={model:e.model||this.model,messages:m,stream:!!e.stream,max_tokens:e.max_tokens||this.ai.options.max_tokens||4096,temperature:e.temperature||this.ai.options.temperature||.7,tools:(e.tools||this.ai.options.tools||[]).map(a=>({type:"function",function:{name:a.name,description:a.description,parameters:{type:"object",properties:a.args?f.objectMap(a.args,(o,i)=>({...i,required:void 0})):{},required:a.args?Object.entries(a.args).filter(o=>o[1].required).map(o=>o[0]):[]}}}))};let c;const r=[];do{if(c=await this.client.chat.completions.create(d),e.stream){r.length&&e.stream({text:`
13
+ `);e.stream&&e.stream({done:!0}),c(this.toStandard([...m,{role:"assistant",content:u,timestamp:Date.now()}]))});return Object.assign(s,{abort:()=>n.abort()})}}class L extends k{constructor(t,e,n){super(),this.ai=t,this.apiToken=e,this.model=n,this.client=new E.OpenAI({apiKey:e})}client;toStandard(t){for(let e=0;e<t.length;e++){const n=t[e];if(n.role==="assistant"&&n.tool_calls){const s=n.tool_calls.map(c=>({role:"tool",id:c.id,name:c.function.name,args:f.JSONAttemptParse(c.function.arguments,{}),timestamp:n.timestamp}));t.splice(e,1,...s),e+=s.length-1}else if(n.role==="tool"&&n.content){const s=t.find(c=>n.tool_call_id==c.id);s&&(n.content.includes('"error":')?s.error=n.content:s.content=n.content),t.splice(e,1),e--}t[e]?.timestamp||(t[e].timestamp=Date.now())}return t}fromStandard(t){return t.reduce((e,n)=>{if(n.role==="tool")e.push({role:"assistant",content:null,tool_calls:[{id:n.id,type:"function",function:{name:n.name,arguments:JSON.stringify(n.args)}}],refusal:null,annotations:[]},{role:"tool",tool_call_id:n.id,content:n.error||n.content});else{const{timestamp:s,...c}=n;e.push(c)}return e},[])}ask(t,e={}){const n=new AbortController,s=new Promise(async(c,g)=>{let l=this.fromStandard([...e.history||[],{role:"user",content:t,timestamp:Date.now()}]);e.compress&&(l=await this.ai.llm.compress(l,e.compress.max,e.compress.min,e));const m={model:e.model||this.model,messages:l,stream:!!e.stream,max_tokens:e.max_tokens||this.ai.options.max_tokens||4096,temperature:e.temperature||this.ai.options.temperature||.7,tools:(e.tools||this.ai.options.tools||[]).map(u=>({type:"function",function:{name:u.name,description:u.description,parameters:{type:"object",properties:u.args?f.objectMap(u.args,(o,a)=>({...a,required:void 0})):{},required:u.args?Object.entries(u.args).filter(o=>o[1].required).map(o=>o[0]):[]}}}))};let i;const r=[];do{if(i=await this.client.chat.completions.create(m),e.stream){r.length&&e.stream({text:`
14
14
 
15
- `}),c.choices=[{message:{content:"",tool_calls:[]}}];for await(const o of c){if(n.signal.aborted)break;o.choices[0].delta.content&&(c.choices[0].message.content+=o.choices[0].delta.content,e.stream({text:o.choices[0].delta.content})),o.choices[0].delta.tool_calls&&(c.choices[0].message.tool_calls=o.choices[0].delta.tool_calls)}}r.push({role:"assistant",content:c.choices[0].message.content||"",timestamp:Date.now()});const a=c.choices[0].message.tool_calls||[];if(a.length&&!n.signal.aborted){m.push(c.choices[0].message);const o=await Promise.all(a.map(async i=>{const g=e.tools?.find(f.findByProp("name",i.function.name));if(!g)return{role:"tool",tool_call_id:i.id,content:'{"error": "Tool not found"}'};try{const w=f.JSONAttemptParse(i.function.arguments,{}),_=await g.fn(w,this.ai);return{role:"tool",tool_call_id:i.id,content:f.JSONSanitize(_)}}catch(w){return{role:"tool",tool_call_id:i.id,content:f.JSONSanitize({error:w?.message||w?.toString()||"Unknown"})}}}));m.push(...o),r.push(...o.map(i=>({...i,timestamp:Date.now()}))),d.messages=m}}while(!n.signal.aborted&&c.choices?.[0]?.message?.tool_calls?.length);const y=r.filter(a=>a.role==="assistant").map(a=>a.content).filter(a=>a).join(`
15
+ `}),i.choices=[{message:{content:"",tool_calls:[]}}];for await(const o of i){if(n.signal.aborted)break;o.choices[0].delta.content&&(i.choices[0].message.content+=o.choices[0].delta.content,e.stream({text:o.choices[0].delta.content})),o.choices[0].delta.tool_calls&&(i.choices[0].message.tool_calls=o.choices[0].delta.tool_calls)}}r.push({role:"assistant",content:i.choices[0].message.content||"",timestamp:Date.now()});const u=i.choices[0].message.tool_calls||[];if(u.length&&!n.signal.aborted){l.push(i.choices[0].message);const o=await Promise.all(u.map(async a=>{const _=e.tools?.find(f.findByProp("name",a.function.name));if(!_)return{role:"tool",tool_call_id:a.id,content:'{"error": "Tool not found"}'};try{const w=f.JSONAttemptParse(a.function.arguments,{}),y=await _.fn(w,this.ai);return{role:"tool",tool_call_id:a.id,content:f.JSONSanitize(y)}}catch(w){return{role:"tool",tool_call_id:a.id,content:f.JSONSanitize({error:w?.message||w?.toString()||"Unknown"})}}}));l.push(...o),r.push(...o.map(a=>({...a,timestamp:Date.now()}))),m.messages=l}}while(!n.signal.aborted&&i.choices?.[0]?.message?.tool_calls?.length);const h=r.filter(u=>u.role==="assistant").map(u=>u.content).filter(u=>u).join(`
16
16
 
17
- `);e.stream&&e.stream({done:!0}),l(this.toStandard([...m,{role:"assistant",content:y,timestamp:Date.now()}]))});return Object.assign(s,{abort:()=>n.abort()})}}class q{constructor(t,e){this.ai=t,this.options=e,e.anthropic?.token&&(this.providers.anthropic=new T(this.ai,e.anthropic.token,e.anthropic.model)),e.ollama?.host&&(this.providers.ollama=new U(this.ai,e.ollama.host,e.ollama.model)),e.openAi?.token&&(this.providers.openAi=new L(this.ai,e.openAi.token,e.openAi.model))}providers={};ask(t,e={}){let n=[null,null];if(e.model&&(typeof e.model=="object"?n=e.model:n=[e.model,this.options[e.model]?.model]),(!e.model||n[1]==null)&&(typeof this.options.model=="object"?n=this.options.model:n=[this.options.model,this.options[this.options.model]?.model]),!n[0]||!n[1])throw new Error(`Unknown LLM provider or model: ${n[0]} / ${n[1]}`);return this.providers[n[0]].ask(t,{...e,model:n[1]})}async compress(t,e,n,s){if(this.estimateTokens(t)<e)return t;let l=0,h=0;for(let r of t.toReversed())if(h+=this.estimateTokens(r.content),h<n)l++;else break;if(t.length<=l)return t;const m=l==0?[]:t.slice(-l),d=(l==0?t:t.slice(0,-l)).filter(r=>r.role==="assistant"||r.role==="user");return[{role:"assistant",content:`Conversation Summary: ${await this.summarize(d.map(r=>`${r.role}: ${r.content}`).join(`
17
+ `);e.stream&&e.stream({done:!0}),c(this.toStandard([...l,{role:"assistant",content:h,timestamp:Date.now()}]))});return Object.assign(s,{abort:()=>n.abort()})}}class q{constructor(t,e){this.ai=t,this.options=e,e.anthropic?.token&&(this.providers.anthropic=new T(this.ai,e.anthropic.token,e.anthropic.model)),e.ollama?.host&&(this.providers.ollama=new U(this.ai,e.ollama.host,e.ollama.model)),e.openAi?.token&&(this.providers.openAi=new L(this.ai,e.openAi.token,e.openAi.model))}providers={};ask(t,e={}){let n=[null,null];if(e.model&&(typeof e.model=="object"?n=e.model:n=[e.model,this.options[e.model]?.model]),(!e.model||n[1]==null)&&(typeof this.options.model=="object"?n=this.options.model:n=[this.options.model,this.options[this.options.model]?.model]),!n[0]||!n[1])throw new Error(`Unknown LLM provider or model: ${n[0]} / ${n[1]}`);return this.providers[n[0]].ask(t,{...e,model:n[1]})}async compress(t,e,n,s){if(this.estimateTokens(t)<e)return t;let c=0,g=0;for(let r of t.toReversed())if(g+=this.estimateTokens(r.content),g<n)c++;else break;if(t.length<=c)return t;const l=c==0?[]:t.slice(-c),m=(c==0?t:t.slice(0,-c)).filter(r=>r.role==="assistant"||r.role==="user");return[{role:"assistant",content:`Conversation Summary: ${await this.summarize(m.map(r=>`${r.role}: ${r.content}`).join(`
18
18
 
19
- `),250,s)}`,timestamp:Date.now()},...m]}estimateTokens(t){const e=JSON.stringify(t);return Math.ceil(e.length/4*1.2)}async json(t,e){let n=await this.ask(t,{system:"Respond using a JSON blob",...e});return n?.[0]?.content?f.JSONAttemptParse(new RegExp("{[sS]*}").exec(n[0].content),{}):{}}summarize(t,e,n){return this.ask(t,{system:`Generate a brief summary <= ${e} tokens. Output nothing else`,temperature:.3,...n}).then(s=>s.pop()?.content||null)}}class ${constructor(t){this.options=t,this.llm=new q(this,t),this.options.whisper?.binary&&(this.whisperModel=this.options.whisper?.model.endsWith(".bin")?this.options.whisper?.model:this.options.whisper?.model+".bin",this.downloadAsrModel())}downloads={};whisperModel;llm;asr(t,e=this.whisperModel){if(!this.options.whisper?.binary)throw new Error("Whisper not configured");let n=()=>{};return{response:new Promise((l,h)=>{this.downloadAsrModel(e).then(m=>{let d="";const c=N.spawn(this.options.whisper?.binary,["-nt","-np","-m",m,"-f",t],{stdio:["ignore","pipe","ignore"]});n=()=>c.kill("SIGTERM"),c.on("error",r=>h(r)),c.stdout.on("data",r=>d+=r.toString()),c.on("close",r=>{r===0?l(d.trim()||null):h(new Error(`Exit code ${r}`))})})}),abort:n}}async downloadAsrModel(t=this.whisperModel){if(!this.options.whisper?.binary)throw new Error("Whisper not configured");t.endsWith(".bin")||(t+=".bin");const e=E.join(this.options.whisper.path,t);return await j.stat(e).then(()=>!0).catch(()=>!1)?e:this.downloads[t]?this.downloads[t]:(this.downloads[t]=fetch(`https://huggingface.co/ggerganov/whisper.cpp/resolve/main/${t}`).then(n=>n.arrayBuffer()).then(n=>Buffer.from(n)).then(async n=>(await j.writeFile(e,n),delete this.downloads[t],e)),this.downloads[t])}ocr(t){let e;return{abort:()=>{e?.terminate()},response:new Promise(async n=>{e=await b.createWorker("eng");const{data:s}=await e.recognize(t);await e.terminate(),n(s.text.trim()||null)})}}semanticSimilarity(t,...e){if(e.length<2)throw new Error("Requires at least 2 strings to compare");const n=(m,d=10)=>m.toLowerCase().split("").map((c,r)=>c.charCodeAt(0)*(r+1)%d/d).slice(0,d),s=(m,d)=>{if(m.length!==d.length)throw new Error("Vectors must be same length");const c=S.tensor1d(m),r=S.tensor1d(d),y=S.dot(c,r),a=S.norm(c),o=S.norm(r);return a.dataSync()[0]===0||o.dataSync()[0]===0?0:y.dataSync()[0]/(a.dataSync()[0]*o.dataSync()[0])},l=n(t),h=e.map(m=>n(m)).map(m=>s(l,m));return{avg:h.reduce((m,d)=>m+d,0)/h.length,max:Math.max(...h),similarities:h}}}const P={name:"cli",description:"Use the command line interface, returns any output",args:{command:{type:"string",description:"Command to run",required:!0}},fn:u=>x.$`${u.command}`},R={name:"get_datetime",description:"Get current date and time",args:{},fn:async()=>new Date().toISOString()},I={name:"exec",description:"Run code/scripts",args:{language:{type:"string",description:"Execution language",enum:["cli","node","python"],required:!0},code:{type:"string",description:"Code to execute",required:!0}},fn:async(u,t)=>{try{switch(u.type){case"bash":return await P.fn({command:u.code},t);case"node":return await O.fn({code:u.code},t);case"python":return await v.fn({code:u.code},t)}}catch(e){return{error:e?.message||e.toString()}}}},W={name:"fetch",description:"Make HTTP request to URL",args:{url:{type:"string",description:"URL to fetch",required:!0},method:{type:"string",description:"HTTP method to use",enum:["GET","POST","PUT","DELETE"],default:"GET"},headers:{type:"object",description:"HTTP headers to send",default:{}},body:{type:"object",description:"HTTP body to send"}},fn:u=>new f.Http({url:u.url,headers:u.headers}).request({method:u.method||"GET",body:u.body})},O={name:"exec_javascript",description:"Execute commonjs javascript",args:{code:{type:"string",description:"CommonJS javascript",required:!0}},fn:async u=>{const t=f.consoleInterceptor(null),e=await f.fn({console:t},u.code,!0).catch(n=>t.output.error.push(n));return{...t.output,return:e,stdout:void 0,stderr:void 0}}},v={name:"exec_javascript",description:"Execute commonjs javascript",args:{code:{type:"string",description:"CommonJS javascript",required:!0}},fn:async u=>({result:x.$Sync`python -c "${u.code}"`})},C={name:"search",description:"Use a search engine to find relevant URLs, should be changed with fetch to scrape sources",args:{query:{type:"string",description:"Search string",required:!0},length:{type:"string",description:"Number of results to return",default:5}},fn:async u=>{const t=await fetch(`https://html.duckduckgo.com/html/?q=${encodeURIComponent(u.query)}`,{headers:{"User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64)","Accept-Language":"en-US,en;q=0.9"}}).then(l=>l.text());let e,n=/<a .*?href="(.+?)".+?<\/a>/g;const s=new f.ASet;for(;(e=n.exec(t))!==null;){let l=/uddg=(.+)&amp?/.exec(decodeURIComponent(e[1]))?.[1];if(l&&(l=decodeURIComponent(l)),l&&s.add(l),s.size>=(u.length||5))break}return s}};p.Ai=$,p.Anthropic=T,p.CliTool=P,p.DateTimeTool=R,p.ExecTool=I,p.FetchTool=W,p.JSTool=O,p.LLM=q,p.PythonTool=v,p.SearchTool=C,Object.defineProperty(p,Symbol.toStringTag,{value:"Module"})}));
19
+ `),250,s)}`,timestamp:Date.now()},...l]}estimateTokens(t){const e=JSON.stringify(t);return Math.ceil(e.length/4*1.2)}async json(t,e){let n=await this.ask(t,{system:"Respond using a JSON blob",...e});return n?.[0]?.content?f.JSONAttemptParse(new RegExp("{[sS]*}").exec(n[0].content),{}):{}}summarize(t,e,n){return this.ask(t,{system:`Generate a brief summary <= ${e} tokens. Output nothing else`,temperature:.3,...n}).then(s=>s.pop()?.content||null)}}class ${constructor(t){this.options=t,this.llm=new q(this,t),this.options.whisper?.binary&&(this.whisperModel=this.options.whisper?.model.endsWith(".bin")?this.options.whisper?.model:this.options.whisper?.model+".bin",this.downloadAsrModel())}downloads={};whisperModel;llm;asr(t,e=this.whisperModel){if(!this.options.whisper?.binary)throw new Error("Whisper not configured");let n=()=>{};return{response:new Promise((c,g)=>{this.downloadAsrModel(e).then(l=>{let m="";const i=N.spawn(this.options.whisper?.binary,["-nt","-np","-m",l,"-f",t],{stdio:["ignore","pipe","ignore"]});n=()=>i.kill("SIGTERM"),i.on("error",r=>g(r)),i.stdout.on("data",r=>m+=r.toString()),i.on("close",r=>{r===0?c(m.trim()||null):g(new Error(`Exit code ${r}`))})})}),abort:n}}async downloadAsrModel(t=this.whisperModel){if(!this.options.whisper?.binary)throw new Error("Whisper not configured");t.endsWith(".bin")||(t+=".bin");const e=D.join(this.options.whisper.path,t);return await j.stat(e).then(()=>!0).catch(()=>!1)?e:this.downloads[t]?this.downloads[t]:(this.downloads[t]=fetch(`https://huggingface.co/ggerganov/whisper.cpp/resolve/main/${t}`).then(n=>n.arrayBuffer()).then(n=>Buffer.from(n)).then(async n=>(await j.writeFile(e,n),delete this.downloads[t],e)),this.downloads[t])}ocr(t){let e;return{abort:()=>{e?.terminate()},response:new Promise(async n=>{e=await b.createWorker("eng");const{data:s}=await e.recognize(t);await e.terminate(),n(s.text.trim()||null)})}}semanticSimilarity(t,...e){if(e.length<2)throw new Error("Requires at least 2 strings to compare");const n=(l,m=10)=>l.toLowerCase().split("").map((i,r)=>i.charCodeAt(0)*(r+1)%m/m).slice(0,m),s=(l,m)=>{if(l.length!==m.length)throw new Error("Vectors must be same length");const i=S.tensor1d(l),r=S.tensor1d(m),h=S.dot(i,r),u=S.norm(i),o=S.norm(r);return u.dataSync()[0]===0||o.dataSync()[0]===0?0:h.dataSync()[0]/(u.dataSync()[0]*o.dataSync()[0])},c=n(t),g=e.map(l=>n(l)).map(l=>s(c,l));return{avg:g.reduce((l,m)=>l+m,0)/g.length,max:Math.max(...g),similarities:g}}}const P={name:"cli",description:"Use the command line interface, returns any output",args:{command:{type:"string",description:"Command to run",required:!0}},fn:d=>x.$`${d.command}`},R={name:"get_datetime",description:"Get current date and time",args:{},fn:async()=>new Date().toISOString()},I={name:"exec",description:"Run code/scripts",args:{language:{type:"string",description:"Execution language",enum:["cli","node","python"],required:!0},code:{type:"string",description:"Code to execute",required:!0}},fn:async(d,t)=>{try{switch(d.type){case"bash":return await P.fn({command:d.code},t);case"node":return await O.fn({code:d.code},t);case"python":return await v.fn({code:d.code},t)}}catch(e){return{error:e?.message||e.toString()}}}},W={name:"fetch",description:"Make HTTP request to URL",args:{url:{type:"string",description:"URL to fetch",required:!0},method:{type:"string",description:"HTTP method to use",enum:["GET","POST","PUT","DELETE"],default:"GET"},headers:{type:"object",description:"HTTP headers to send",default:{}},body:{type:"object",description:"HTTP body to send"}},fn:d=>new f.Http({url:d.url,headers:d.headers}).request({method:d.method||"GET",body:d.body})},O={name:"exec_javascript",description:"Execute commonjs javascript",args:{code:{type:"string",description:"CommonJS javascript",required:!0}},fn:async d=>{const t=f.consoleInterceptor(null),e=await f.fn({console:t},d.code,!0).catch(n=>t.output.error.push(n));return{...t.output,return:e,stdout:void 0,stderr:void 0}}},v={name:"exec_javascript",description:"Execute commonjs javascript",args:{code:{type:"string",description:"CommonJS javascript",required:!0}},fn:async d=>({result:x.$Sync`python -c "${d.code}"`})},C={name:"search",description:"Use a search engine to find relevant URLs, should be changed with fetch to scrape sources",args:{query:{type:"string",description:"Search string",required:!0},length:{type:"string",description:"Number of results to return",default:5}},fn:async d=>{const t=await fetch(`https://html.duckduckgo.com/html/?q=${encodeURIComponent(d.query)}`,{headers:{"User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64)","Accept-Language":"en-US,en;q=0.9"}}).then(c=>c.text());let e,n=/<a .*?href="(.+?)".+?<\/a>/g;const s=new f.ASet;for(;(e=n.exec(t))!==null;){let c=/uddg=(.+)&amp?/.exec(decodeURIComponent(e[1]))?.[1];if(c&&(c=decodeURIComponent(c)),c&&s.add(c),s.size>=(d.length||5))break}return s}};p.Ai=$,p.Anthropic=T,p.CliTool=P,p.DateTimeTool=R,p.ExecTool=I,p.FetchTool=W,p.JSTool=O,p.LLM=q,p.PythonTool=v,p.SearchTool=C,Object.defineProperty(p,Symbol.toStringTag,{value:"Module"})}));
20
20
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../src/provider.ts","../src/antrhopic.ts","../src/ollama.ts","../src/open-ai.ts","../src/llm.ts","../src/ai.ts","../src/tools.ts"],"sourcesContent":["import {LLMMessage, LLMOptions, LLMRequest} from './llm.ts';\n\nexport type AbortablePromise<T> = Promise<T> & {abort: () => void};\n\nexport abstract class LLMProvider {\n\tabstract ask(message: string, options: LLMRequest): AbortablePromise<LLMMessage[]>;\n}\n","import {Anthropic as anthropic} from '@anthropic-ai/sdk';\nimport {findByProp, objectMap, JSONSanitize, JSONAttemptParse} from '@ztimson/utils';\nimport {Ai} from './ai.ts';\nimport {LLMMessage, LLMRequest} from './llm.ts';\nimport {AbortablePromise, LLMProvider} from './provider.ts';\n\nexport class Anthropic extends LLMProvider {\n\tclient!: anthropic;\n\n\tconstructor(public readonly ai: Ai, public readonly apiToken: string, public model: string) {\n\t\tsuper();\n\t\tthis.client = new anthropic({apiKey: apiToken});\n\t}\n\n\tprivate toStandard(history: any[]): LLMMessage[] {\n\t\tfor(let i = 0; i < history.length; i++) {\n\t\t\tconst orgI = i;\n\t\t\tif(typeof history[orgI].content != 'string') {\n\t\t\t\tif(history[orgI].role == 'assistant') {\n\t\t\t\t\thistory[orgI].content.filter((c: any) => c.type =='tool_use').forEach((c: any) => {\n\t\t\t\t\t\ti++;\n\t\t\t\t\t\thistory.splice(i, 0, {role: 'tool', id: c.id, name: c.name, args: c.input, timestamp: Date.now()});\n\t\t\t\t\t});\n\t\t\t\t} else if(history[orgI].role == 'user') {\n\t\t\t\t\thistory[orgI].content.filter((c: any) => c.type =='tool_result').forEach((c: any) => {\n\t\t\t\t\t\tconst h = history.find((h: any) => h.id == c.tool_use_id);\n\t\t\t\t\t\th[c.is_error ? 'error' : 'content'] = c.content;\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\thistory[orgI].content = history[orgI].content.filter((c: any) => c.type == 'text').map((c: any) => c.text).join('\\n\\n');\n\t\t\t}\n\t\t\tif(!history[orgI].timestamp) history[orgI].timestamp = Date.now();\n\t\t}\n\t\treturn history.filter(h => !!h.content);\n\t}\n\n\tprivate fromStandard(history: LLMMessage[]): any[] {\n\t\tfor(let i = 0; i < history.length; i++) {\n\t\t\tif(history[i].role == 'tool') {\n\t\t\t\tconst h: any = history[i];\n\t\t\t\thistory.splice(i, 1,\n\t\t\t\t\t{role: 'assistant', content: [{type: 'tool_use', id: h.id, name: h.name, input: h.args}]},\n\t\t\t\t\t{role: 'user', content: [{type: 'tool_result', tool_use_id: h.id, is_error: !!h.error, content: h.error || h.content}]}\n\t\t\t\t)\n\t\t\t\ti++;\n\t\t\t}\n\t\t}\n\t\treturn history.map(({timestamp, ...h}) => h);\n\t}\n\n\task(message: string, options: LLMRequest = {}): AbortablePromise<LLMMessage[]> {\n\t\tconst controller = new AbortController();\n\t\tconst response = new Promise<any>(async (res, rej) => {\n\t\t\tlet history = this.fromStandard([...options.history || [], {role: 'user', content: message, timestamp: Date.now()}]);\n\t\t\tif(options.compress) history = await this.ai.llm.compress(<any>history, options.compress.max, options.compress.min, options);\n\t\t\tconst requestParams: any = {\n\t\t\t\tmodel: options.model || this.model,\n\t\t\t\tmax_tokens: options.max_tokens || this.ai.options.max_tokens || 4096,\n\t\t\t\tsystem: options.system || this.ai.options.system || '',\n\t\t\t\ttemperature: options.temperature || this.ai.options.temperature || 0.7,\n\t\t\t\ttools: (options.tools || this.ai.options.tools || []).map(t => ({\n\t\t\t\t\tname: t.name,\n\t\t\t\t\tdescription: t.description,\n\t\t\t\t\tinput_schema: {\n\t\t\t\t\t\ttype: 'object',\n\t\t\t\t\t\tproperties: t.args ? objectMap(t.args, (key, value) => ({...value, required: undefined})) : {},\n\t\t\t\t\t\trequired: t.args ? Object.entries(t.args).filter(t => t[1].required).map(t => t[0]) : []\n\t\t\t\t\t},\n\t\t\t\t\tfn: undefined\n\t\t\t\t})),\n\t\t\t\tmessages: history,\n\t\t\t\tstream: !!options.stream,\n\t\t\t};\n\n\t\t\tlet resp: any;\n\t\t\tconst loopMessages: any[] = [];\n\t\t\tdo {\n\t\t\t\tresp = await this.client.messages.create(requestParams);\n\t\t\t\tif(options.stream) {\n\t\t\t\t\tif(loopMessages.length) options.stream({text: '\\n\\n'});\n\t\t\t\t\tresp.content = [];\n\t\t\t\t\tfor await (const chunk of resp) {\n\t\t\t\t\t\tif(controller.signal.aborted) break;\n\t\t\t\t\t\tif(chunk.type === 'content_block_start') {\n\t\t\t\t\t\t\tif(chunk.content_block.type === 'text') {\n\t\t\t\t\t\t\t\tresp.content.push({type: 'text', text: ''});\n\t\t\t\t\t\t\t} else if(chunk.content_block.type === 'tool_use') {\n\t\t\t\t\t\t\t\tresp.content.push({type: 'tool_use', id: chunk.content_block.id, name: chunk.content_block.name, input: <any>''});\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else if(chunk.type === 'content_block_delta') {\n\t\t\t\t\t\t\tif(chunk.delta.type === 'text_delta') {\n\t\t\t\t\t\t\t\tconst text = chunk.delta.text;\n\t\t\t\t\t\t\t\tresp.content.at(-1).text += text;\n\t\t\t\t\t\t\t\toptions.stream({text});\n\t\t\t\t\t\t\t} else if(chunk.delta.type === 'input_json_delta') {\n\t\t\t\t\t\t\t\tresp.content.at(-1).input += chunk.delta.partial_json;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else if(chunk.type === 'content_block_stop') {\n\t\t\t\t\t\t\tconst last = resp.content.at(-1);\n\t\t\t\t\t\t\tif(last.input != null) last.input = last.input ? JSONAttemptParse(last.input, {}) : {};\n\t\t\t\t\t\t} else if(chunk.type === 'message_stop') {\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tloopMessages.push({role: 'assistant', content: resp.content, timestamp: Date.now()});\n\t\t\t\tconst toolCalls = resp.content.filter((c: any) => c.type === 'tool_use');\n\t\t\t\tif(toolCalls.length && !controller.signal.aborted) {\n\t\t\t\t\thistory.push({role: 'assistant', content: resp.content});\n\t\t\t\t\tconst results = await Promise.all(toolCalls.map(async (toolCall: any) => {\n\t\t\t\t\t\tconst tool = options.tools?.find(findByProp('name', toolCall.name));\n\t\t\t\t\t\tif(!tool) return {tool_use_id: toolCall.id, is_error: true, content: 'Tool not found'};\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tconst result = await tool.fn(toolCall.input, this.ai);\n\t\t\t\t\t\t\treturn {type: 'tool_result', tool_use_id: toolCall.id, content: JSONSanitize(result)};\n\t\t\t\t\t\t} catch (err: any) {\n\t\t\t\t\t\t\treturn {type: 'tool_result', tool_use_id: toolCall.id, is_error: true, content: err?.message || err?.toString() || 'Unknown'};\n\t\t\t\t\t\t}\n\t\t\t\t\t}));\n\t\t\t\t\tconst userMsg = {role: 'user', content: results};\n\t\t\t\t\thistory.push(userMsg);\n\t\t\t\t\tloopMessages.push({...userMsg, timestamp: Date.now()});\n\t\t\t\t\trequestParams.messages = history;\n\t\t\t\t}\n\t\t\t} while (!controller.signal.aborted && resp.content.some((c: any) => c.type === 'tool_use'));\n\n\t\t\tconst combinedContent = loopMessages.filter(m => m.role === 'assistant')\n\t\t\t\t.map(m => m.content.filter((c: any) => c.type == 'text').map((c: any) => c.text).join('\\n\\n'))\n\t\t\t\t.filter(c => c).join('\\n\\n');\n\t\t\tif(options.stream) options.stream({done: true});\n\t\t\tres(this.toStandard([...history, {role: 'assistant', content: combinedContent, timestamp: Date.now()}]));\n\t\t});\n\n\t\treturn Object.assign(response, {abort: () => controller.abort()});\n\t}\n}\n","import {findByProp, objectMap, JSONSanitize, JSONAttemptParse} from '@ztimson/utils';\nimport {Ai} from './ai.ts';\nimport {LLMMessage, LLMRequest} from './llm.ts';\nimport {AbortablePromise, LLMProvider} from './provider.ts';\nimport {Ollama as ollama} from 'ollama';\n\nexport class Ollama extends LLMProvider {\n\tclient!: ollama;\n\n\tconstructor(public readonly ai: Ai, public host: string, public model: string) {\n\t\tsuper();\n\t\tthis.client = new ollama({host});\n\t}\n\n\tprivate toStandard(history: any[]): LLMMessage[] {\n\t\tfor(let i = 0; i < history.length; i++) {\n\t\t\tif(history[i].role == 'assistant' && history[i].tool_calls) {\n\t\t\t\tif(history[i].content) delete history[i].tool_calls;\n\t\t\t\telse {\n\t\t\t\t\thistory.splice(i, 1);\n\t\t\t\t\ti--;\n\t\t\t\t}\n\t\t\t} else if(history[i].role == 'tool') {\n\t\t\t\tconst error = history[i].content.startsWith('{\"error\":');\n\t\t\t\thistory[i] = {role: 'tool', name: history[i].tool_name, args: history[i].args, [error ? 'error' : 'content']: history[i].content, timestamp: history[i].timestamp};\n\t\t\t}\n\t\t\tif(!history[i]?.timestamp) history[i].timestamp = Date.now();\n\t\t}\n\t\treturn history;\n\t}\n\n\tprivate fromStandard(history: LLMMessage[]): any[] {\n\t\treturn history.map((h: any) => {\n\t\t\tconst {timestamp, ...rest} = h;\n\t\t\tif(h.role != 'tool') return rest;\n\t\t\treturn {role: 'tool', tool_name: h.name, content: h.error || h.content}\n\t\t});\n\t}\n\n\task(message: string, options: LLMRequest = {}): AbortablePromise<LLMMessage[]> {\n\t\tconst controller = new AbortController();\n\t\tconst response = new Promise<any>(async (res, rej) => {\n\t\t\tlet system = options.system || this.ai.options.system;\n\t\t\tlet history = this.fromStandard([...options.history || [], {role: 'user', content: message, timestamp: Date.now()}]);\n\t\t\tif(history[0].roll == 'system') {\n\t\t\t\tif(!system) system = history.shift();\n\t\t\t\telse history.shift();\n\t\t\t}\n\t\t\tif(options.compress) history = await this.ai.llm.compress(<any>history, options.compress.max, options.compress.min);\n\t\t\tif(options.system) history.unshift({role: 'system', content: system})\n\n\t\t\tconst requestParams: any = {\n\t\t\t\tmodel: options.model || this.model,\n\t\t\t\tmessages: history,\n\t\t\t\tstream: !!options.stream,\n\t\t\t\tsignal: controller.signal,\n\t\t\t\toptions: {\n\t\t\t\t\ttemperature: options.temperature || this.ai.options.temperature || 0.7,\n\t\t\t\t\tnum_predict: options.max_tokens || this.ai.options.max_tokens || 4096,\n\t\t\t\t},\n\t\t\t\ttools: (options.tools || this.ai.options.tools || []).map(t => ({\n\t\t\t\t\ttype: 'function',\n\t\t\t\t\tfunction: {\n\t\t\t\t\t\tname: t.name,\n\t\t\t\t\t\tdescription: t.description,\n\t\t\t\t\t\tparameters: {\n\t\t\t\t\t\t\ttype: 'object',\n\t\t\t\t\t\t\tproperties: t.args ? objectMap(t.args, (key, value) => ({...value, required: undefined})) : {},\n\t\t\t\t\t\t\trequired: t.args ? Object.entries(t.args).filter(t => t[1].required).map(t => t[0]) : []\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}))\n\t\t\t}\n\n\t\t\tlet resp: any;\n\t\t\tconst loopMessages: any[] = [];\n\t\t\tdo {\n\t\t\t\tresp = await this.client.chat(requestParams);\n\t\t\t\tif(options.stream) {\n\t\t\t\t\tif(loopMessages.length) options.stream({text: '\\n\\n'});\n\t\t\t\t\tresp.message = {role: 'assistant', content: '', tool_calls: []};\n\t\t\t\t\tfor await (const chunk of resp) {\n\t\t\t\t\t\tif(controller.signal.aborted) break;\n\t\t\t\t\t\tif(chunk.message?.content) {\n\t\t\t\t\t\t\tresp.message.content += chunk.message.content;\n\t\t\t\t\t\t\toptions.stream({text: chunk.message.content});\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif(chunk.message?.tool_calls) resp.message.tool_calls = chunk.message.tool_calls;\n\t\t\t\t\t\tif(chunk.done) break;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tloopMessages.push({role: 'assistant', content: resp.message?.content, timestamp: Date.now()});\n\t\t\t\tif(resp.message?.tool_calls?.length && !controller.signal.aborted) {\n\t\t\t\t\thistory.push(resp.message);\n\t\t\t\t\tconst results = await Promise.all(resp.message.tool_calls.map(async (toolCall: any) => {\n\t\t\t\t\t\tconst tool = (options.tools || this.ai.options.tools)?.find(findByProp('name', toolCall.function.name));\n\t\t\t\t\t\tif(!tool) return {role: 'tool', tool_name: toolCall.function.name, content: '{\"error\": \"Tool not found\"}'};\n\t\t\t\t\t\tconst args = typeof toolCall.function.arguments === 'string' ? JSONAttemptParse(toolCall.function.arguments, {}) : toolCall.function.arguments;\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tconst result = await tool.fn(args, this.ai);\n\t\t\t\t\t\t\treturn {role: 'tool', tool_name: toolCall.function.name, args, content: JSONSanitize(result)};\n\t\t\t\t\t\t} catch (err: any) {\n\t\t\t\t\t\t\treturn {role: 'tool', tool_name: toolCall.function.name, args, content: JSONSanitize({error: err?.message || err?.toString() || 'Unknown'})};\n\t\t\t\t\t\t}\n\t\t\t\t\t}));\n\t\t\t\t\thistory.push(...results);\n\t\t\t\t\tloopMessages.push(...results.map(r => ({...r, timestamp: Date.now()})));\n\t\t\t\t\trequestParams.messages = history;\n\t\t\t\t}\n\t\t\t} while (!controller.signal.aborted && resp.message?.tool_calls?.length);\n\n\t\t\tconst combinedContent = loopMessages.filter(m => m.role === 'assistant')\n\t\t\t\t.map(m => m.content).filter(c => c).join('\\n\\n');\n\t\t\tif(options.stream) options.stream({done: true});\n\t\t\tres(this.toStandard([...history, {role: 'assistant', content: combinedContent, timestamp: Date.now()}]));\n\t\t});\n\n\t\treturn Object.assign(response, {abort: () => controller.abort()});\n\t}\n}\n","import {OpenAI as openAI} from 'openai';\nimport {findByProp, objectMap, JSONSanitize, JSONAttemptParse} from '@ztimson/utils';\nimport {Ai} from './ai.ts';\nimport {LLMMessage, LLMRequest} from './llm.ts';\nimport {AbortablePromise, LLMProvider} from './provider.ts';\n\nexport class OpenAi extends LLMProvider {\n\tclient!: openAI;\n\n\tconstructor(public readonly ai: Ai, public readonly apiToken: string, public model: string) {\n\t\tsuper();\n\t\tthis.client = new openAI({apiKey: apiToken});\n\t}\n\n\tprivate toStandard(history: any[]): LLMMessage[] {\n\t\tfor(let i = 0; i < history.length; i++) {\n\t\t\tconst h = history[i];\n\t\t\tif(h.role === 'assistant' && h.tool_calls) {\n\t\t\t\tconst tools = h.tool_calls.map((tc: any) => ({\n\t\t\t\t\trole: 'tool',\n\t\t\t\t\tid: tc.id,\n\t\t\t\t\tname: tc.function.name,\n\t\t\t\t\targs: JSONAttemptParse(tc.function.arguments, {}),\n\t\t\t\t\ttimestamp: h.timestamp\n\t\t\t\t}));\n\t\t\t\thistory.splice(i, 1, ...tools);\n\t\t\t\ti += tools.length - 1;\n\t\t\t} else if(h.role === 'tool' && h.content) {\n\t\t\t\tconst record = history.find(h2 => h.tool_call_id == h2.id);\n\t\t\t\tif(record) {\n\t\t\t\t\tif(h.content.includes('\"error\":')) record.error = h.content;\n\t\t\t\t\telse record.content = h.content;\n\t\t\t\t}\n\t\t\t\thistory.splice(i, 1);\n\t\t\t\ti--;\n\t\t\t}\n\t\t\tif(!history[i]?.timestamp) history[i].timestamp = Date.now();\n\t\t}\n\t\treturn history;\n\t}\n\n\tprivate fromStandard(history: LLMMessage[]): any[] {\n\t\treturn history.reduce((result, h) => {\n\t\t\tif(h.role === 'tool') {\n\t\t\t\tresult.push({\n\t\t\t\t\trole: 'assistant',\n\t\t\t\t\tcontent: null,\n\t\t\t\t\ttool_calls: [{ id: h.id, type: 'function', function: { name: h.name, arguments: JSON.stringify(h.args) } }],\n\t\t\t\t\trefusal: null,\n\t\t\t\t\tannotations: []\n\t\t\t\t}, {\n\t\t\t\t\trole: 'tool',\n\t\t\t\t\ttool_call_id: h.id,\n\t\t\t\t\tcontent: h.error || h.content\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\tconst {timestamp, ...rest} = h;\n\t\t\t\tresult.push(rest);\n\t\t\t}\n\t\t\treturn result;\n\t\t}, [] as any[]);\n\t}\n\n\task(message: string, options: LLMRequest = {}): AbortablePromise<LLMMessage[]> {\n\t\tconst controller = new AbortController();\n\t\tconst response = new Promise<any>(async (res, rej) => {\n\t\t\tlet history = this.fromStandard([...options.history || [], {role: 'user', content: message, timestamp: Date.now()}]);\n\t\t\tif(options.compress) history = await this.ai.llm.compress(<any>history, options.compress.max, options.compress.min, options);\n\n\t\t\tconst requestParams: any = {\n\t\t\t\tmodel: options.model || this.model,\n\t\t\t\tmessages: history,\n\t\t\t\tstream: !!options.stream,\n\t\t\t\tmax_tokens: options.max_tokens || this.ai.options.max_tokens || 4096,\n\t\t\t\ttemperature: options.temperature || this.ai.options.temperature || 0.7,\n\t\t\t\ttools: (options.tools || this.ai.options.tools || []).map(t => ({\n\t\t\t\t\ttype: 'function',\n\t\t\t\t\tfunction: {\n\t\t\t\t\t\tname: t.name,\n\t\t\t\t\t\tdescription: t.description,\n\t\t\t\t\t\tparameters: {\n\t\t\t\t\t\t\ttype: 'object',\n\t\t\t\t\t\t\tproperties: t.args ? objectMap(t.args, (key, value) => ({...value, required: undefined})) : {},\n\t\t\t\t\t\t\trequired: t.args ? Object.entries(t.args).filter(t => t[1].required).map(t => t[0]) : []\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}))\n\t\t\t};\n\n\t\t\tlet resp: any;\n\t\t\tconst loopMessages: any[] = [];\n\t\t\tdo {\n\t\t\t\tresp = await this.client.chat.completions.create(requestParams);\n\t\t\t\tif(options.stream) {\n\t\t\t\t\tif(loopMessages.length) options.stream({text: '\\n\\n'});\n\t\t\t\t\tresp.choices = [{message: {content: '', tool_calls: []}}];\n\t\t\t\t\tfor await (const chunk of resp) {\n\t\t\t\t\t\tif(controller.signal.aborted) break;\n\t\t\t\t\t\tif(chunk.choices[0].delta.content) {\n\t\t\t\t\t\t\tresp.choices[0].message.content += chunk.choices[0].delta.content;\n\t\t\t\t\t\t\toptions.stream({text: chunk.choices[0].delta.content});\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif(chunk.choices[0].delta.tool_calls) {\n\t\t\t\t\t\t\tresp.choices[0].message.tool_calls = chunk.choices[0].delta.tool_calls;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tloopMessages.push({role: 'assistant', content: resp.choices[0].message.content || '', timestamp: Date.now()});\n\n\t\t\t\tconst toolCalls = resp.choices[0].message.tool_calls || [];\n\t\t\t\tif(toolCalls.length && !controller.signal.aborted) {\n\t\t\t\t\thistory.push(resp.choices[0].message);\n\t\t\t\t\tconst results = await Promise.all(toolCalls.map(async (toolCall: any) => {\n\t\t\t\t\t\tconst tool = options.tools?.find(findByProp('name', toolCall.function.name));\n\t\t\t\t\t\tif(!tool) return {role: 'tool', tool_call_id: toolCall.id, content: '{\"error\": \"Tool not found\"}'};\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tconst args = JSONAttemptParse(toolCall.function.arguments, {});\n\t\t\t\t\t\t\tconst result = await tool.fn(args, this.ai);\n\t\t\t\t\t\t\treturn {role: 'tool', tool_call_id: toolCall.id, content: JSONSanitize(result)};\n\t\t\t\t\t\t} catch (err: any) {\n\t\t\t\t\t\t\treturn {role: 'tool', tool_call_id: toolCall.id, content: JSONSanitize({error: err?.message || err?.toString() || 'Unknown'})};\n\t\t\t\t\t\t}\n\t\t\t\t\t}));\n\t\t\t\t\thistory.push(...results);\n\t\t\t\t\tloopMessages.push(...results.map(r => ({...r, timestamp: Date.now()})));\n\t\t\t\t\trequestParams.messages = history;\n\t\t\t\t}\n\t\t\t} while (!controller.signal.aborted && resp.choices?.[0]?.message?.tool_calls?.length);\n\n\t\t\tconst combinedContent = loopMessages.filter(m => m.role === 'assistant')\n\t\t\t\t.map(m => m.content).filter(c => c).join('\\n\\n');\n\t\t\tif(options.stream) options.stream({done: true});\n\t\t\tres(this.toStandard([...history, {role: 'assistant', content: combinedContent, timestamp: Date.now()}]));\n\t\t});\n\t\treturn Object.assign(response, {abort: () => controller.abort()});\n\t}\n}\n","import {JSONAttemptParse} from '@ztimson/utils';\nimport {Ai} from './ai.ts';\nimport {Anthropic} from './antrhopic.ts';\nimport {Ollama} from './ollama.ts';\nimport {OpenAi} from './open-ai.ts';\nimport {AbortablePromise, LLMProvider} from './provider.ts';\nimport {AiTool} from './tools.ts';\n\nexport type LLMMessage = {\n\t/** Message originator */\n\trole: 'assistant' | 'system' | 'user';\n\t/** Message content */\n\tcontent: string | any;\n\t/** Timestamp */\n\ttimestamp?: number;\n} | {\n\t/** Tool call */\n\trole: 'tool';\n\t/** Unique ID for call */\n\tid: string;\n\t/** Tool that was run */\n\tname: string;\n\t/** Tool arguments */\n\targs: any;\n\t/** Tool result */\n\tcontent: undefined | string;\n\t/** Tool error */\n\terror: undefined | string;\n\t/** Timestamp */\n\ttimestamp?: number;\n}\n\nexport type LLMOptions = {\n\t/** Anthropic settings */\n\tanthropic?: {\n\t\t/** API Token */\n\t\ttoken: string;\n\t\t/** Default model */\n\t\tmodel: string;\n\t},\n\t/** Ollama settings */\n\tollama?: {\n\t\t/** connection URL */\n\t\thost: string;\n\t\t/** Default model */\n\t\tmodel: string;\n\t},\n\t/** Open AI settings */\n\topenAi?: {\n\t\t/** API Token */\n\t\ttoken: string;\n\t\t/** Default model */\n\t\tmodel: string;\n\t},\n\t/** Default provider & model */\n\tmodel: string | [string, string];\n} & Omit<LLMRequest, 'model'>;\n\nexport type LLMRequest = {\n\t/** System prompt */\n\tsystem?: string;\n\t/** Message history */\n\thistory?: LLMMessage[];\n\t/** Max tokens for request */\n\tmax_tokens?: number;\n\t/** 0 = Rigid Logic, 1 = Balanced, 2 = Hyper Creative **/\n\ttemperature?: number;\n\t/** Available tools */\n\ttools?: AiTool[];\n\t/** LLM model */\n\tmodel?: string | [string, string];\n\t/** Stream response */\n\tstream?: (chunk: {text?: string, done?: true}) => any;\n\t/** Compress old messages in the chat to free up context */\n\tcompress?: {\n\t\t/** Trigger chat compression once context exceeds the token count */\n\t\tmax: number;\n\t\t/** Compress chat until context size smaller than */\n\t\tmin: number\n\t}\n}\n\nexport class LLM {\n\tprivate providers: {[key: string]: LLMProvider} = {};\n\n\tconstructor(public readonly ai: Ai, public readonly options: LLMOptions) {\n\t\tif(options.anthropic?.token) this.providers.anthropic = new Anthropic(this.ai, options.anthropic.token, options.anthropic.model);\n\t\tif(options.ollama?.host) this.providers.ollama = new Ollama(this.ai, options.ollama.host, options.ollama.model);\n\t\tif(options.openAi?.token) this.providers.openAi = new OpenAi(this.ai, options.openAi.token, options.openAi.model);\n\t}\n\n\t/**\n\t * Chat with LLM\n\t * @param {string} message Question\n\t * @param {LLMRequest} options Configuration options and chat history\n\t * @returns {{abort: () => void, response: Promise<LLMMessage[]>}} Function to abort response and chat history\n\t */\n\task(message: string, options: LLMRequest = {}): AbortablePromise<LLMMessage[]> {\n\t\tlet model: any = [null, null];\n\t\tif(options.model) {\n\t\t\tif(typeof options.model == 'object') model = options.model;\n\t\t\telse model = [options.model, (<any>this.options)[options.model]?.model];\n\t\t}\n\t\tif(!options.model || model[1] == null) {\n\t\t\tif(typeof this.options.model == 'object') model = this.options.model;\n\t\t\telse model = [this.options.model, (<any>this.options)[this.options.model]?.model];\n\t\t}\n\t\tif(!model[0] || !model[1]) throw new Error(`Unknown LLM provider or model: ${model[0]} / ${model[1]}`);\n\t\treturn this.providers[model[0]].ask(message, {...options, model: model[1]});\n\t}\n\n\t/**\n\t * Compress chat history to reduce context size\n\t * @param {LLMMessage[]} history Chatlog that will be compressed\n\t * @param max Trigger compression once context is larger than max\n\t * @param min Summarize until context size is less than min\n\t * @param {LLMRequest} options LLM options\n\t * @returns {Promise<LLMMessage[]>} New chat history will summary at index 0\n\t */\n\tasync compress(history: LLMMessage[], max: number, min: number, options?: LLMRequest): Promise<LLMMessage[]> {\n\t\tif(this.estimateTokens(history) < max) return history;\n\t\tlet keep = 0, tokens = 0;\n\t\tfor(let m of history.toReversed()) {\n\t\t\ttokens += this.estimateTokens(m.content);\n\t\t\tif(tokens < min) keep++;\n\t\t\telse break;\n\t\t}\n\t\tif(history.length <= keep) return history;\n\t\tconst recent = keep == 0 ? [] : history.slice(-keep),\n\t\t\tprocess = (keep == 0 ? history : history.slice(0, -keep)).filter(h => h.role === 'assistant' || h.role === 'user');\n\t\tconst summary = await this.summarize(process.map(m => `${m.role}: ${m.content}`).join('\\n\\n'), 250, options);\n\t\treturn [{role: 'assistant', content: `Conversation Summary: ${summary}`, timestamp: Date.now()}, ...recent];\n\t}\n\n\t/**\n\t * Estimate variable as tokens\n\t * @param history Object to size\n\t * @returns {number} Rough token count\n\t */\n\testimateTokens(history: any): number {\n\t\tconst text = JSON.stringify(history);\n\t\treturn Math.ceil((text.length / 4) * 1.2);\n\t}\n\n\t/**\n\t * Ask a question with JSON response\n\t * @param {string} message Question\n\t * @param {LLMRequest} options Configuration options and chat history\n\t * @returns {Promise<{} | {} | RegExpExecArray | null>}\n\t */\n\tasync json(message: string, options?: LLMRequest) {\n\t\tlet resp = await this.ask(message, {\n\t\t\tsystem: 'Respond using a JSON blob',\n\t\t\t...options\n\t\t});\n\t\tif(!resp?.[0]?.content) return {};\n\t\treturn JSONAttemptParse(new RegExp('\\{[\\s\\S]*\\}').exec(resp[0].content), {});\n\t}\n\n\t/**\n\t * Create a summary of some text\n\t * @param {string} text Text to summarize\n\t * @param {number} tokens Max number of tokens\n\t * @param options LLM request options\n\t * @returns {Promise<string>} Summary\n\t */\n\tsummarize(text: string, tokens: number, options?: LLMRequest): Promise<string | null> {\n\t\treturn this.ask(text, {system: `Generate a brief summary <= ${tokens} tokens. Output nothing else`, temperature: 0.3, ...options})\n\t\t\t.then(history => <string>history.pop()?.content || null);\n\t}\n}\n","import {createWorker} from 'tesseract.js';\nimport {LLM, LLMOptions} from './llm';\nimport fs from 'node:fs/promises';\nimport Path from 'node:path';\nimport * as tf from '@tensorflow/tfjs';\nimport {spawn} from 'node:child_process';\n\nexport type AiOptions = LLMOptions & {\n\twhisper?: {\n\t\t/** Whisper binary location */\n\t\tbinary: string;\n\t\t/** Model: `ggml-base.en.bin` */\n\t\tmodel: string;\n\t\t/** Path to models */\n\t\tpath: string;\n\t}\n}\n\nexport class Ai {\n\tprivate downloads: {[key: string]: Promise<string>} = {};\n\tprivate whisperModel!: string;\n\n\t/** Large Language Models */\n\tllm!: LLM;\n\n\tconstructor(public readonly options: AiOptions) {\n\t\tthis.llm = new LLM(this, options);\n\t\tif(this.options.whisper?.binary) {\n\t\t\tthis.whisperModel = this.options.whisper?.model.endsWith('.bin') ? this.options.whisper?.model : this.options.whisper?.model + '.bin';\n\t\t\tthis.downloadAsrModel();\n\t\t}\n\t}\n\n\t/**\n\t * Convert audio to text using Auditory Speech Recognition\n\t * @param {string} path Path to audio\n\t * @param model Whisper model\n\t * @returns {Promise<any>} Extracted text\n\t */\n\tasr(path: string, model: string = this.whisperModel): {abort: () => void, response: Promise<string | null>} {\n\t\tif(!this.options.whisper?.binary) throw new Error('Whisper not configured');\n\t\tlet abort: any = () => {};\n\t\tconst response = new Promise<string | null>((resolve, reject) => {\n\t\t\tthis.downloadAsrModel(model).then(m => {\n\t\t\t\tlet output = '';\n\t\t\t\tconst proc = spawn(<string>this.options.whisper?.binary, ['-nt', '-np', '-m', m, '-f', path], {stdio: ['ignore', 'pipe', 'ignore']});\n\t\t\t\tabort = () => proc.kill('SIGTERM');\n\t\t\t\tproc.on('error', (err: Error) => reject(err));\n\t\t\t\tproc.stdout.on('data', (data: Buffer) => output += data.toString());\n\t\t\t\tproc.on('close', (code: number) => {\n\t\t\t\t\tif(code === 0) resolve(output.trim() || null);\n\t\t\t\t\telse reject(new Error(`Exit code ${code}`));\n\t\t\t\t});\n\t\t\t});\n\t\t});\n\t\treturn {response, abort};\n\t}\n\n\t/**\n\t * Downloads the specified Whisper model if it is not already present locally.\n\t *\n\t * @param {string} model Whisper model that will be downloaded\n\t * @return {Promise<string>} Absolute path to model file, resolves once downloaded\n\t */\n\tasync downloadAsrModel(model: string = this.whisperModel): Promise<string> {\n\t\tif(!this.options.whisper?.binary) throw new Error('Whisper not configured');\n\t\tif(!model.endsWith('.bin')) model += '.bin';\n\t\tconst p = Path.join(this.options.whisper.path, model);\n\t\tif(await fs.stat(p).then(() => true).catch(() => false)) return p;\n\t\tif(!!this.downloads[model]) return this.downloads[model];\n\t\tthis.downloads[model] = fetch(`https://huggingface.co/ggerganov/whisper.cpp/resolve/main/${model}`)\n\t\t\t.then(resp => resp.arrayBuffer())\n\t\t\t.then(arr => Buffer.from(arr)).then(async buffer => {\n\t\t\t\tawait fs.writeFile(p, buffer);\n\t\t\t\tdelete this.downloads[model];\n\t\t\t\treturn p;\n\t\t\t});\n\t\treturn this.downloads[model];\n\t}\n\n\t/**\n\t * Convert image to text using Optical Character Recognition\n\t * @param {string} path Path to image\n\t * @returns {{abort: Function, response: Promise<string | null>}} Abort function & Promise of extracted text\n\t */\n\tocr(path: string): {abort: () => void, response: Promise<string | null>} {\n\t\tlet worker: any;\n\t\treturn {\n\t\t\tabort: () => { worker?.terminate(); },\n\t\t\tresponse: new Promise(async res => {\n\t\t\t\tworker = await createWorker('eng');\n\t\t\t\tconst {data} = await worker.recognize(path);\n\t\t\t\tawait worker.terminate();\n\t\t\t\tres(data.text.trim() || null);\n\t\t\t})\n\t\t}\n\t}\n\n\t/**\n\t * Compare the difference between two strings using tensor math\n\t * @param target Text that will checked\n\t * @param {string} searchTerms Multiple search terms to check against target\n\t * @returns {{avg: number, max: number, similarities: number[]}} Similarity values 0-1: 0 = unique, 1 = identical\n\t */\n\tsemanticSimilarity(target: string, ...searchTerms: string[]) {\n\t\tif(searchTerms.length < 2) throw new Error('Requires at least 2 strings to compare');\n\n\t\tconst vector = (text: string, dimensions: number = 10): number[] => {\n\t\t\treturn text.toLowerCase().split('').map((char, index) =>\n\t\t\t\t(char.charCodeAt(0) * (index + 1)) % dimensions / dimensions).slice(0, dimensions);\n\t\t}\n\n\t\tconst cosineSimilarity = (v1: number[], v2: number[]): number => {\n\t\t\tif (v1.length !== v2.length) throw new Error('Vectors must be same length');\n\t\t\tconst tensor1 = tf.tensor1d(v1), tensor2 = tf.tensor1d(v2)\n\t\t\tconst dotProduct = tf.dot(tensor1, tensor2)\n\t\t\tconst magnitude1 = tf.norm(tensor1)\n\t\t\tconst magnitude2 = tf.norm(tensor2)\n\t\t\tif(magnitude1.dataSync()[0] === 0 || magnitude2.dataSync()[0] === 0) return 0\n\t\t\treturn dotProduct.dataSync()[0] / (magnitude1.dataSync()[0] * magnitude2.dataSync()[0])\n\t\t}\n\n\t\tconst v = vector(target);\n\t\tconst similarities = searchTerms.map(t => vector(t)).map(refVector => cosineSimilarity(v, refVector))\n\t\treturn {avg: similarities.reduce((acc, s) => acc + s, 0) / similarities.length, max: Math.max(...similarities), similarities}\n\t}\n}\n","import {$, $Sync} from '@ztimson/node-utils';\nimport {ASet, consoleInterceptor, Http, fn as Fn} from '@ztimson/utils';\nimport {Ai} from './ai.ts';\n\nexport type AiToolArg = {[key: string]: {\n\t/** Argument type */\n\ttype: 'array' | 'boolean' | 'number' | 'object' | 'string',\n\t/** Argument description */\n\tdescription: string,\n\t/** Required argument */\n\trequired?: boolean;\n\t/** Default value */\n\tdefault?: any,\n\t/** Options */\n\tenum?: string[],\n\t/** Minimum value or length */\n\tmin?: number,\n\t/** Maximum value or length */\n\tmax?: number,\n\t/** Match pattern */\n\tpattern?: string,\n\t/** Child arguments */\n\titems?: {[key: string]: AiToolArg}\n}}\n\nexport type AiTool = {\n\t/** Tool ID / Name - Must be snail_case */\n\tname: string,\n\t/** Tool description / prompt */\n\tdescription: string,\n\t/** Tool arguments */\n\targs?: AiToolArg,\n\t/** Callback function */\n\tfn: (args: any, ai: Ai) => any | Promise<any>,\n};\n\nexport const CliTool: AiTool = {\n\tname: 'cli',\n\tdescription: 'Use the command line interface, returns any output',\n\targs: {command: {type: 'string', description: 'Command to run', required: true}},\n\tfn: (args: {command: string}) => $`${args.command}`\n}\n\nexport const DateTimeTool: AiTool = {\n\tname: 'get_datetime',\n\tdescription: 'Get current date and time',\n\targs: {},\n\tfn: async () => new Date().toISOString()\n}\n\nexport const ExecTool: AiTool = {\n\tname: 'exec',\n\tdescription: 'Run code/scripts',\n\targs: {\n\t\tlanguage: {type: 'string', description: 'Execution language', enum: ['cli', 'node', 'python'], required: true},\n\t\tcode: {type: 'string', description: 'Code to execute', required: true}\n\t},\n\tfn: async (args, ai) => {\n\t\ttry {\n\t\t\tswitch(args.type) {\n\t\t\t\tcase 'bash':\n\t\t\t\t\treturn await CliTool.fn({command: args.code}, ai);\n\t\t\t\tcase 'node':\n\t\t\t\t\treturn await JSTool.fn({code: args.code}, ai);\n\t\t\t\tcase 'python': {\n\t\t\t\t\treturn await PythonTool.fn({code: args.code}, ai);\n\t\t\t\t}\n\t\t\t}\n\t\t} catch(err: any) {\n\t\t\treturn {error: err?.message || err.toString()};\n\t\t}\n\t}\n}\n\nexport const FetchTool: AiTool = {\n\tname: 'fetch',\n\tdescription: 'Make HTTP request to URL',\n\targs: {\n\t\turl: {type: 'string', description: 'URL to fetch', required: true},\n\t\tmethod: {type: 'string', description: 'HTTP method to use', enum: ['GET', 'POST', 'PUT', 'DELETE'], default: 'GET'},\n\t\theaders: {type: 'object', description: 'HTTP headers to send', default: {}},\n\t\tbody: {type: 'object', description: 'HTTP body to send'},\n\t},\n\tfn: (args: {\n\t\turl: string;\n\t\tmethod: 'GET' | 'POST' | 'PUT' | 'DELETE';\n\t\theaders: {[key: string]: string};\n\t\tbody: any;\n\t}) => new Http({url: args.url, headers: args.headers}).request({method: args.method || 'GET', body: args.body})\n}\n\nexport const JSTool: AiTool = {\n\tname: 'exec_javascript',\n\tdescription: 'Execute commonjs javascript',\n\targs: {\n\t\tcode: {type: 'string', description: 'CommonJS javascript', required: true}\n\t},\n\tfn: async (args: {code: string}) => {\n\t\tconst console = consoleInterceptor(null);\n\t\tconst resp = await Fn<any>({console}, args.code, true).catch((err: any) => console.output.error.push(err));\n\t\treturn {...console.output, return: resp, stdout: undefined, stderr: undefined};\n\t}\n}\n\nexport const PythonTool: AiTool = {\n\tname: 'exec_javascript',\n\tdescription: 'Execute commonjs javascript',\n\targs: {\n\t\tcode: {type: 'string', description: 'CommonJS javascript', required: true}\n\t},\n\tfn: async (args: {code: string}) => ({result: $Sync`python -c \"${args.code}\"`})\n}\n\nexport const SearchTool: AiTool = {\n\tname: 'search',\n\tdescription: 'Use a search engine to find relevant URLs, should be changed with fetch to scrape sources',\n\targs: {\n\t\tquery: {type: 'string', description: 'Search string', required: true},\n\t\tlength: {type: 'string', description: 'Number of results to return', default: 5},\n\t},\n\tfn: async (args: {\n\t\tquery: string;\n\t\tlength: number;\n\t}) => {\n\t\tconst html = await fetch(`https://html.duckduckgo.com/html/?q=${encodeURIComponent(args.query)}`, {\n\t\t\theaders: {\"User-Agent\": \"Mozilla/5.0 (Windows NT 10.0; Win64; x64)\", \"Accept-Language\": \"en-US,en;q=0.9\"}\n\t\t}).then(resp => resp.text());\n\t\tlet match, regex = /<a .*?href=\"(.+?)\".+?<\\/a>/g;\n\t\tconst results = new ASet<string>();\n\t\twhile((match = regex.exec(html)) !== null) {\n\t\t\tlet url = /uddg=(.+)&amp?/.exec(decodeURIComponent(match[1]))?.[1];\n\t\t\tif(url) url = decodeURIComponent(url);\n\t\t\tif(url) results.add(url);\n\t\t\tif(results.size >= (args.length || 5)) break;\n\t\t}\n\t\treturn results;\n\t}\n}\n"],"names":["LLMProvider","Anthropic","ai","apiToken","model","anthropic","history","i","orgI","c","h","timestamp","message","options","controller","response","res","rej","requestParams","t","objectMap","key","value","resp","loopMessages","chunk","text","last","JSONAttemptParse","toolCalls","userMsg","toolCall","tool","findByProp","result","JSONSanitize","err","combinedContent","m","Ollama","host","ollama","error","rest","system","results","args","r","OpenAi","openAI","tools","tc","record","h2","LLM","max","min","keep","tokens","recent","process","Ai","path","abort","resolve","reject","output","proc","spawn","data","code","p","Path","fs","arr","buffer","worker","createWorker","target","searchTerms","vector","dimensions","char","index","cosineSimilarity","v1","v2","tensor1","tf","tensor2","dotProduct","magnitude1","magnitude2","v","similarities","refVector","acc","s","CliTool","$","DateTimeTool","ExecTool","JSTool","PythonTool","FetchTool","Http","console","consoleInterceptor","Fn","$Sync","SearchTool","html","match","regex","ASet","url"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sources":["../src/provider.ts","../src/antrhopic.ts","../src/ollama.ts","../src/open-ai.ts","../src/llm.ts","../src/ai.ts","../src/tools.ts"],"sourcesContent":["import {LLMMessage, LLMOptions, LLMRequest} from './llm.ts';\n\nexport type AbortablePromise<T> = Promise<T> & {abort: () => void};\n\nexport abstract class LLMProvider {\n\tabstract ask(message: string, options: LLMRequest): AbortablePromise<LLMMessage[]>;\n}\n","import {Anthropic as anthropic} from '@anthropic-ai/sdk';\nimport {findByProp, objectMap, JSONSanitize, JSONAttemptParse} from '@ztimson/utils';\nimport {Ai} from './ai.ts';\nimport {LLMMessage, LLMRequest} from './llm.ts';\nimport {AbortablePromise, LLMProvider} from './provider.ts';\n\nexport class Anthropic extends LLMProvider {\n\tclient!: anthropic;\n\n\tconstructor(public readonly ai: Ai, public readonly apiToken: string, public model: string) {\n\t\tsuper();\n\t\tthis.client = new anthropic({apiKey: apiToken});\n\t}\n\n\tprivate toStandard(history: any[]): LLMMessage[] {\n\t\tfor(let i = 0; i < history.length; i++) {\n\t\t\tconst orgI = i;\n\t\t\tif(typeof history[orgI].content != 'string') {\n\t\t\t\tif(history[orgI].role == 'assistant') {\n\t\t\t\t\thistory[orgI].content.filter((c: any) => c.type =='tool_use').forEach((c: any) => {\n\t\t\t\t\t\ti++;\n\t\t\t\t\t\thistory.splice(i, 0, {role: 'tool', id: c.id, name: c.name, args: c.input, timestamp: Date.now()});\n\t\t\t\t\t});\n\t\t\t\t} else if(history[orgI].role == 'user') {\n\t\t\t\t\thistory[orgI].content.filter((c: any) => c.type =='tool_result').forEach((c: any) => {\n\t\t\t\t\t\tconst h = history.find((h: any) => h.id == c.tool_use_id);\n\t\t\t\t\t\th[c.is_error ? 'error' : 'content'] = c.content;\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\thistory[orgI].content = history[orgI].content.filter((c: any) => c.type == 'text').map((c: any) => c.text).join('\\n\\n');\n\t\t\t}\n\t\t\tif(!history[orgI].timestamp) history[orgI].timestamp = Date.now();\n\t\t}\n\t\treturn history.filter(h => !!h.content);\n\t}\n\n\tprivate fromStandard(history: LLMMessage[]): any[] {\n\t\tfor(let i = 0; i < history.length; i++) {\n\t\t\tif(history[i].role == 'tool') {\n\t\t\t\tconst h: any = history[i];\n\t\t\t\thistory.splice(i, 1,\n\t\t\t\t\t{role: 'assistant', content: [{type: 'tool_use', id: h.id, name: h.name, input: h.args}]},\n\t\t\t\t\t{role: 'user', content: [{type: 'tool_result', tool_use_id: h.id, is_error: !!h.error, content: h.error || h.content}]}\n\t\t\t\t)\n\t\t\t\ti++;\n\t\t\t}\n\t\t}\n\t\treturn history.map(({timestamp, ...h}) => h);\n\t}\n\n\task(message: string, options: LLMRequest = {}): AbortablePromise<LLMMessage[]> {\n\t\tconst controller = new AbortController();\n\t\tconst response = new Promise<any>(async (res, rej) => {\n\t\t\tlet history = this.fromStandard([...options.history || [], {role: 'user', content: message, timestamp: Date.now()}]);\n\t\t\tif(options.compress) history = await this.ai.llm.compress(<any>history, options.compress.max, options.compress.min, options);\n\t\t\tconst requestParams: any = {\n\t\t\t\tmodel: options.model || this.model,\n\t\t\t\tmax_tokens: options.max_tokens || this.ai.options.max_tokens || 4096,\n\t\t\t\tsystem: options.system || this.ai.options.system || '',\n\t\t\t\ttemperature: options.temperature || this.ai.options.temperature || 0.7,\n\t\t\t\ttools: (options.tools || this.ai.options.tools || []).map(t => ({\n\t\t\t\t\tname: t.name,\n\t\t\t\t\tdescription: t.description,\n\t\t\t\t\tinput_schema: {\n\t\t\t\t\t\ttype: 'object',\n\t\t\t\t\t\tproperties: t.args ? objectMap(t.args, (key, value) => ({...value, required: undefined})) : {},\n\t\t\t\t\t\trequired: t.args ? Object.entries(t.args).filter(t => t[1].required).map(t => t[0]) : []\n\t\t\t\t\t},\n\t\t\t\t\tfn: undefined\n\t\t\t\t})),\n\t\t\t\tmessages: history,\n\t\t\t\tstream: !!options.stream,\n\t\t\t};\n\n\t\t\tlet resp: any;\n\t\t\tconst assistantMessages: string[] = [];\n\t\t\tdo {\n\t\t\t\tresp = await this.client.messages.create(requestParams);\n\t\t\t\tif(options.stream) {\n\t\t\t\t\tif(assistantMessages.length) options.stream({text: '\\n\\n'});\n\t\t\t\t\tresp.content = [];\n\t\t\t\t\tfor await (const chunk of resp) {\n\t\t\t\t\t\tif(controller.signal.aborted) break;\n\t\t\t\t\t\tif(chunk.type === 'content_block_start') {\n\t\t\t\t\t\t\tif(chunk.content_block.type === 'text') {\n\t\t\t\t\t\t\t\tresp.content.push({type: 'text', text: ''});\n\t\t\t\t\t\t\t} else if(chunk.content_block.type === 'tool_use') {\n\t\t\t\t\t\t\t\tresp.content.push({type: 'tool_use', id: chunk.content_block.id, name: chunk.content_block.name, input: <any>''});\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else if(chunk.type === 'content_block_delta') {\n\t\t\t\t\t\t\tif(chunk.delta.type === 'text_delta') {\n\t\t\t\t\t\t\t\tconst text = chunk.delta.text;\n\t\t\t\t\t\t\t\tresp.content.at(-1).text += text;\n\t\t\t\t\t\t\t\toptions.stream({text});\n\t\t\t\t\t\t\t} else if(chunk.delta.type === 'input_json_delta') {\n\t\t\t\t\t\t\t\tresp.content.at(-1).input += chunk.delta.partial_json;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else if(chunk.type === 'content_block_stop') {\n\t\t\t\t\t\t\tconst last = resp.content.at(-1);\n\t\t\t\t\t\t\tif(last.input != null) last.input = last.input ? JSONAttemptParse(last.input, {}) : {};\n\t\t\t\t\t\t} else if(chunk.type === 'message_stop') {\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tconst textContent = resp.content.filter((c: any) => c.type == 'text').map((c: any) => c.text).join('\\n\\n');\n\t\t\t\tif(textContent) assistantMessages.push(textContent);\n\t\t\t\tconst toolCalls = resp.content.filter((c: any) => c.type === 'tool_use');\n\t\t\t\tif(toolCalls.length && !controller.signal.aborted) {\n\t\t\t\t\thistory.push({role: 'assistant', content: resp.content});\n\t\t\t\t\tconst results = await Promise.all(toolCalls.map(async (toolCall: any) => {\n\t\t\t\t\t\tconst tool = options.tools?.find(findByProp('name', toolCall.name));\n\t\t\t\t\t\tif(!tool) return {tool_use_id: toolCall.id, is_error: true, content: 'Tool not found'};\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tconst result = await tool.fn(toolCall.input, this.ai);\n\t\t\t\t\t\t\treturn {type: 'tool_result', tool_use_id: toolCall.id, content: JSONSanitize(result)};\n\t\t\t\t\t\t} catch (err: any) {\n\t\t\t\t\t\t\treturn {type: 'tool_result', tool_use_id: toolCall.id, is_error: true, content: err?.message || err?.toString() || 'Unknown'};\n\t\t\t\t\t\t}\n\t\t\t\t\t}));\n\t\t\t\t\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\t\t\tif(options.stream) options.stream({done: true});\n\t\t\tres(this.toStandard([...history, {role: 'assistant', content: assistantMessages.join('\\n\\n'), timestamp: Date.now()}]));\n\t\t});\n\n\t\treturn Object.assign(response, {abort: () => controller.abort()});\n\t}\n}\n","import {findByProp, objectMap, JSONSanitize, JSONAttemptParse} from '@ztimson/utils';\nimport {Ai} from './ai.ts';\nimport {LLMMessage, LLMRequest} from './llm.ts';\nimport {AbortablePromise, LLMProvider} from './provider.ts';\nimport {Ollama as ollama} from 'ollama';\n\nexport class Ollama extends LLMProvider {\n\tclient!: ollama;\n\n\tconstructor(public readonly ai: Ai, public host: string, public model: string) {\n\t\tsuper();\n\t\tthis.client = new ollama({host});\n\t}\n\n\tprivate toStandard(history: any[]): LLMMessage[] {\n\t\tfor(let i = 0; i < history.length; i++) {\n\t\t\tif(history[i].role == 'assistant' && history[i].tool_calls) {\n\t\t\t\tif(history[i].content) delete history[i].tool_calls;\n\t\t\t\telse {\n\t\t\t\t\thistory.splice(i, 1);\n\t\t\t\t\ti--;\n\t\t\t\t}\n\t\t\t} else if(history[i].role == 'tool') {\n\t\t\t\tconst error = history[i].content.startsWith('{\"error\":');\n\t\t\t\thistory[i] = {role: 'tool', name: history[i].tool_name, args: history[i].args, [error ? 'error' : 'content']: history[i].content, timestamp: history[i].timestamp};\n\t\t\t}\n\t\t\tif(!history[i]?.timestamp) history[i].timestamp = Date.now();\n\t\t}\n\t\treturn history;\n\t}\n\n\tprivate fromStandard(history: LLMMessage[]): any[] {\n\t\treturn history.map((h: any) => {\n\t\t\tconst {timestamp, ...rest} = h;\n\t\t\tif(h.role != 'tool') return rest;\n\t\t\treturn {role: 'tool', tool_name: h.name, content: h.error || h.content}\n\t\t});\n\t}\n\n\task(message: string, options: LLMRequest = {}): AbortablePromise<LLMMessage[]> {\n\t\tconst controller = new AbortController();\n\t\tconst response = new Promise<any>(async (res, rej) => {\n\t\t\tlet system = options.system || this.ai.options.system;\n\t\t\tlet history = this.fromStandard([...options.history || [], {role: 'user', content: message, timestamp: Date.now()}]);\n\t\t\tif(history[0].roll == 'system') {\n\t\t\t\tif(!system) system = history.shift();\n\t\t\t\telse history.shift();\n\t\t\t}\n\t\t\tif(options.compress) history = await this.ai.llm.compress(<any>history, options.compress.max, options.compress.min);\n\t\t\tif(options.system) history.unshift({role: 'system', content: system})\n\n\t\t\tconst requestParams: any = {\n\t\t\t\tmodel: options.model || this.model,\n\t\t\t\tmessages: history,\n\t\t\t\tstream: !!options.stream,\n\t\t\t\tsignal: controller.signal,\n\t\t\t\toptions: {\n\t\t\t\t\ttemperature: options.temperature || this.ai.options.temperature || 0.7,\n\t\t\t\t\tnum_predict: options.max_tokens || this.ai.options.max_tokens || 4096,\n\t\t\t\t},\n\t\t\t\ttools: (options.tools || this.ai.options.tools || []).map(t => ({\n\t\t\t\t\ttype: 'function',\n\t\t\t\t\tfunction: {\n\t\t\t\t\t\tname: t.name,\n\t\t\t\t\t\tdescription: t.description,\n\t\t\t\t\t\tparameters: {\n\t\t\t\t\t\t\ttype: 'object',\n\t\t\t\t\t\t\tproperties: t.args ? objectMap(t.args, (key, value) => ({...value, required: undefined})) : {},\n\t\t\t\t\t\t\trequired: t.args ? Object.entries(t.args).filter(t => t[1].required).map(t => t[0]) : []\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}))\n\t\t\t}\n\n\t\t\tlet resp: any;\n\t\t\tconst loopMessages: any[] = [];\n\t\t\tdo {\n\t\t\t\tresp = await this.client.chat(requestParams);\n\t\t\t\tif(options.stream) {\n\t\t\t\t\tif(loopMessages.length) options.stream({text: '\\n\\n'});\n\t\t\t\t\tresp.message = {role: 'assistant', content: '', tool_calls: []};\n\t\t\t\t\tfor await (const chunk of resp) {\n\t\t\t\t\t\tif(controller.signal.aborted) break;\n\t\t\t\t\t\tif(chunk.message?.content) {\n\t\t\t\t\t\t\tresp.message.content += chunk.message.content;\n\t\t\t\t\t\t\toptions.stream({text: chunk.message.content});\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif(chunk.message?.tool_calls) resp.message.tool_calls = chunk.message.tool_calls;\n\t\t\t\t\t\tif(chunk.done) break;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tloopMessages.push({role: 'assistant', content: resp.message?.content, timestamp: Date.now()});\n\t\t\t\tif(resp.message?.tool_calls?.length && !controller.signal.aborted) {\n\t\t\t\t\thistory.push(resp.message);\n\t\t\t\t\tconst results = await Promise.all(resp.message.tool_calls.map(async (toolCall: any) => {\n\t\t\t\t\t\tconst tool = (options.tools || this.ai.options.tools)?.find(findByProp('name', toolCall.function.name));\n\t\t\t\t\t\tif(!tool) return {role: 'tool', tool_name: toolCall.function.name, content: '{\"error\": \"Tool not found\"}'};\n\t\t\t\t\t\tconst args = typeof toolCall.function.arguments === 'string' ? JSONAttemptParse(toolCall.function.arguments, {}) : toolCall.function.arguments;\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tconst result = await tool.fn(args, this.ai);\n\t\t\t\t\t\t\treturn {role: 'tool', tool_name: toolCall.function.name, args, content: JSONSanitize(result)};\n\t\t\t\t\t\t} catch (err: any) {\n\t\t\t\t\t\t\treturn {role: 'tool', tool_name: toolCall.function.name, args, content: JSONSanitize({error: err?.message || err?.toString() || 'Unknown'})};\n\t\t\t\t\t\t}\n\t\t\t\t\t}));\n\t\t\t\t\thistory.push(...results);\n\t\t\t\t\tloopMessages.push(...results.map(r => ({...r, timestamp: Date.now()})));\n\t\t\t\t\trequestParams.messages = history;\n\t\t\t\t}\n\t\t\t} while (!controller.signal.aborted && resp.message?.tool_calls?.length);\n\n\t\t\tconst combinedContent = loopMessages.filter(m => m.role === 'assistant')\n\t\t\t\t.map(m => m.content).filter(c => c).join('\\n\\n');\n\t\t\tif(options.stream) options.stream({done: true});\n\t\t\tres(this.toStandard([...history, {role: 'assistant', content: combinedContent, timestamp: Date.now()}]));\n\t\t});\n\n\t\treturn Object.assign(response, {abort: () => controller.abort()});\n\t}\n}\n","import {OpenAI as openAI} from 'openai';\nimport {findByProp, objectMap, JSONSanitize, JSONAttemptParse} from '@ztimson/utils';\nimport {Ai} from './ai.ts';\nimport {LLMMessage, LLMRequest} from './llm.ts';\nimport {AbortablePromise, LLMProvider} from './provider.ts';\n\nexport class OpenAi extends LLMProvider {\n\tclient!: openAI;\n\n\tconstructor(public readonly ai: Ai, public readonly apiToken: string, public model: string) {\n\t\tsuper();\n\t\tthis.client = new openAI({apiKey: apiToken});\n\t}\n\n\tprivate toStandard(history: any[]): LLMMessage[] {\n\t\tfor(let i = 0; i < history.length; i++) {\n\t\t\tconst h = history[i];\n\t\t\tif(h.role === 'assistant' && h.tool_calls) {\n\t\t\t\tconst tools = h.tool_calls.map((tc: any) => ({\n\t\t\t\t\trole: 'tool',\n\t\t\t\t\tid: tc.id,\n\t\t\t\t\tname: tc.function.name,\n\t\t\t\t\targs: JSONAttemptParse(tc.function.arguments, {}),\n\t\t\t\t\ttimestamp: h.timestamp\n\t\t\t\t}));\n\t\t\t\thistory.splice(i, 1, ...tools);\n\t\t\t\ti += tools.length - 1;\n\t\t\t} else if(h.role === 'tool' && h.content) {\n\t\t\t\tconst record = history.find(h2 => h.tool_call_id == h2.id);\n\t\t\t\tif(record) {\n\t\t\t\t\tif(h.content.includes('\"error\":')) record.error = h.content;\n\t\t\t\t\telse record.content = h.content;\n\t\t\t\t}\n\t\t\t\thistory.splice(i, 1);\n\t\t\t\ti--;\n\t\t\t}\n\t\t\tif(!history[i]?.timestamp) history[i].timestamp = Date.now();\n\t\t}\n\t\treturn history;\n\t}\n\n\tprivate fromStandard(history: LLMMessage[]): any[] {\n\t\treturn history.reduce((result, h) => {\n\t\t\tif(h.role === 'tool') {\n\t\t\t\tresult.push({\n\t\t\t\t\trole: 'assistant',\n\t\t\t\t\tcontent: null,\n\t\t\t\t\ttool_calls: [{ id: h.id, type: 'function', function: { name: h.name, arguments: JSON.stringify(h.args) } }],\n\t\t\t\t\trefusal: null,\n\t\t\t\t\tannotations: []\n\t\t\t\t}, {\n\t\t\t\t\trole: 'tool',\n\t\t\t\t\ttool_call_id: h.id,\n\t\t\t\t\tcontent: h.error || h.content\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\tconst {timestamp, ...rest} = h;\n\t\t\t\tresult.push(rest);\n\t\t\t}\n\t\t\treturn result;\n\t\t}, [] as any[]);\n\t}\n\n\task(message: string, options: LLMRequest = {}): AbortablePromise<LLMMessage[]> {\n\t\tconst controller = new AbortController();\n\t\tconst response = new Promise<any>(async (res, rej) => {\n\t\t\tlet history = this.fromStandard([...options.history || [], {role: 'user', content: message, timestamp: Date.now()}]);\n\t\t\tif(options.compress) history = await this.ai.llm.compress(<any>history, options.compress.max, options.compress.min, options);\n\n\t\t\tconst requestParams: any = {\n\t\t\t\tmodel: options.model || this.model,\n\t\t\t\tmessages: history,\n\t\t\t\tstream: !!options.stream,\n\t\t\t\tmax_tokens: options.max_tokens || this.ai.options.max_tokens || 4096,\n\t\t\t\ttemperature: options.temperature || this.ai.options.temperature || 0.7,\n\t\t\t\ttools: (options.tools || this.ai.options.tools || []).map(t => ({\n\t\t\t\t\ttype: 'function',\n\t\t\t\t\tfunction: {\n\t\t\t\t\t\tname: t.name,\n\t\t\t\t\t\tdescription: t.description,\n\t\t\t\t\t\tparameters: {\n\t\t\t\t\t\t\ttype: 'object',\n\t\t\t\t\t\t\tproperties: t.args ? objectMap(t.args, (key, value) => ({...value, required: undefined})) : {},\n\t\t\t\t\t\t\trequired: t.args ? Object.entries(t.args).filter(t => t[1].required).map(t => t[0]) : []\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}))\n\t\t\t};\n\n\t\t\tlet resp: any;\n\t\t\tconst loopMessages: any[] = [];\n\t\t\tdo {\n\t\t\t\tresp = await this.client.chat.completions.create(requestParams);\n\t\t\t\tif(options.stream) {\n\t\t\t\t\tif(loopMessages.length) options.stream({text: '\\n\\n'});\n\t\t\t\t\tresp.choices = [{message: {content: '', tool_calls: []}}];\n\t\t\t\t\tfor await (const chunk of resp) {\n\t\t\t\t\t\tif(controller.signal.aborted) break;\n\t\t\t\t\t\tif(chunk.choices[0].delta.content) {\n\t\t\t\t\t\t\tresp.choices[0].message.content += chunk.choices[0].delta.content;\n\t\t\t\t\t\t\toptions.stream({text: chunk.choices[0].delta.content});\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif(chunk.choices[0].delta.tool_calls) {\n\t\t\t\t\t\t\tresp.choices[0].message.tool_calls = chunk.choices[0].delta.tool_calls;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tloopMessages.push({role: 'assistant', content: resp.choices[0].message.content || '', timestamp: Date.now()});\n\n\t\t\t\tconst toolCalls = resp.choices[0].message.tool_calls || [];\n\t\t\t\tif(toolCalls.length && !controller.signal.aborted) {\n\t\t\t\t\thistory.push(resp.choices[0].message);\n\t\t\t\t\tconst results = await Promise.all(toolCalls.map(async (toolCall: any) => {\n\t\t\t\t\t\tconst tool = options.tools?.find(findByProp('name', toolCall.function.name));\n\t\t\t\t\t\tif(!tool) return {role: 'tool', tool_call_id: toolCall.id, content: '{\"error\": \"Tool not found\"}'};\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tconst args = JSONAttemptParse(toolCall.function.arguments, {});\n\t\t\t\t\t\t\tconst result = await tool.fn(args, this.ai);\n\t\t\t\t\t\t\treturn {role: 'tool', tool_call_id: toolCall.id, content: JSONSanitize(result)};\n\t\t\t\t\t\t} catch (err: any) {\n\t\t\t\t\t\t\treturn {role: 'tool', tool_call_id: toolCall.id, content: JSONSanitize({error: err?.message || err?.toString() || 'Unknown'})};\n\t\t\t\t\t\t}\n\t\t\t\t\t}));\n\t\t\t\t\thistory.push(...results);\n\t\t\t\t\tloopMessages.push(...results.map(r => ({...r, timestamp: Date.now()})));\n\t\t\t\t\trequestParams.messages = history;\n\t\t\t\t}\n\t\t\t} while (!controller.signal.aborted && resp.choices?.[0]?.message?.tool_calls?.length);\n\n\t\t\tconst combinedContent = loopMessages.filter(m => m.role === 'assistant')\n\t\t\t\t.map(m => m.content).filter(c => c).join('\\n\\n');\n\t\t\tif(options.stream) options.stream({done: true});\n\t\t\tres(this.toStandard([...history, {role: 'assistant', content: combinedContent, timestamp: Date.now()}]));\n\t\t});\n\t\treturn Object.assign(response, {abort: () => controller.abort()});\n\t}\n}\n","import {JSONAttemptParse} from '@ztimson/utils';\nimport {Ai} from './ai.ts';\nimport {Anthropic} from './antrhopic.ts';\nimport {Ollama} from './ollama.ts';\nimport {OpenAi} from './open-ai.ts';\nimport {AbortablePromise, LLMProvider} from './provider.ts';\nimport {AiTool} from './tools.ts';\n\nexport type LLMMessage = {\n\t/** Message originator */\n\trole: 'assistant' | 'system' | 'user';\n\t/** Message content */\n\tcontent: string | any;\n\t/** Timestamp */\n\ttimestamp?: number;\n} | {\n\t/** Tool call */\n\trole: 'tool';\n\t/** Unique ID for call */\n\tid: string;\n\t/** Tool that was run */\n\tname: string;\n\t/** Tool arguments */\n\targs: any;\n\t/** Tool result */\n\tcontent: undefined | string;\n\t/** Tool error */\n\terror: undefined | string;\n\t/** Timestamp */\n\ttimestamp?: number;\n}\n\nexport type LLMOptions = {\n\t/** Anthropic settings */\n\tanthropic?: {\n\t\t/** API Token */\n\t\ttoken: string;\n\t\t/** Default model */\n\t\tmodel: string;\n\t},\n\t/** Ollama settings */\n\tollama?: {\n\t\t/** connection URL */\n\t\thost: string;\n\t\t/** Default model */\n\t\tmodel: string;\n\t},\n\t/** Open AI settings */\n\topenAi?: {\n\t\t/** API Token */\n\t\ttoken: string;\n\t\t/** Default model */\n\t\tmodel: string;\n\t},\n\t/** Default provider & model */\n\tmodel: string | [string, string];\n} & Omit<LLMRequest, 'model'>;\n\nexport type LLMRequest = {\n\t/** System prompt */\n\tsystem?: string;\n\t/** Message history */\n\thistory?: LLMMessage[];\n\t/** Max tokens for request */\n\tmax_tokens?: number;\n\t/** 0 = Rigid Logic, 1 = Balanced, 2 = Hyper Creative **/\n\ttemperature?: number;\n\t/** Available tools */\n\ttools?: AiTool[];\n\t/** LLM model */\n\tmodel?: string | [string, string];\n\t/** Stream response */\n\tstream?: (chunk: {text?: string, done?: true}) => any;\n\t/** Compress old messages in the chat to free up context */\n\tcompress?: {\n\t\t/** Trigger chat compression once context exceeds the token count */\n\t\tmax: number;\n\t\t/** Compress chat until context size smaller than */\n\t\tmin: number\n\t}\n}\n\nexport class LLM {\n\tprivate providers: {[key: string]: LLMProvider} = {};\n\n\tconstructor(public readonly ai: Ai, public readonly options: LLMOptions) {\n\t\tif(options.anthropic?.token) this.providers.anthropic = new Anthropic(this.ai, options.anthropic.token, options.anthropic.model);\n\t\tif(options.ollama?.host) this.providers.ollama = new Ollama(this.ai, options.ollama.host, options.ollama.model);\n\t\tif(options.openAi?.token) this.providers.openAi = new OpenAi(this.ai, options.openAi.token, options.openAi.model);\n\t}\n\n\t/**\n\t * Chat with LLM\n\t * @param {string} message Question\n\t * @param {LLMRequest} options Configuration options and chat history\n\t * @returns {{abort: () => void, response: Promise<LLMMessage[]>}} Function to abort response and chat history\n\t */\n\task(message: string, options: LLMRequest = {}): AbortablePromise<LLMMessage[]> {\n\t\tlet model: any = [null, null];\n\t\tif(options.model) {\n\t\t\tif(typeof options.model == 'object') model = options.model;\n\t\t\telse model = [options.model, (<any>this.options)[options.model]?.model];\n\t\t}\n\t\tif(!options.model || model[1] == null) {\n\t\t\tif(typeof this.options.model == 'object') model = this.options.model;\n\t\t\telse model = [this.options.model, (<any>this.options)[this.options.model]?.model];\n\t\t}\n\t\tif(!model[0] || !model[1]) throw new Error(`Unknown LLM provider or model: ${model[0]} / ${model[1]}`);\n\t\treturn this.providers[model[0]].ask(message, {...options, model: model[1]});\n\t}\n\n\t/**\n\t * Compress chat history to reduce context size\n\t * @param {LLMMessage[]} history Chatlog that will be compressed\n\t * @param max Trigger compression once context is larger than max\n\t * @param min Summarize until context size is less than min\n\t * @param {LLMRequest} options LLM options\n\t * @returns {Promise<LLMMessage[]>} New chat history will summary at index 0\n\t */\n\tasync compress(history: LLMMessage[], max: number, min: number, options?: LLMRequest): Promise<LLMMessage[]> {\n\t\tif(this.estimateTokens(history) < max) return history;\n\t\tlet keep = 0, tokens = 0;\n\t\tfor(let m of history.toReversed()) {\n\t\t\ttokens += this.estimateTokens(m.content);\n\t\t\tif(tokens < min) keep++;\n\t\t\telse break;\n\t\t}\n\t\tif(history.length <= keep) return history;\n\t\tconst recent = keep == 0 ? [] : history.slice(-keep),\n\t\t\tprocess = (keep == 0 ? history : history.slice(0, -keep)).filter(h => h.role === 'assistant' || h.role === 'user');\n\t\tconst summary = await this.summarize(process.map(m => `${m.role}: ${m.content}`).join('\\n\\n'), 250, options);\n\t\treturn [{role: 'assistant', content: `Conversation Summary: ${summary}`, timestamp: Date.now()}, ...recent];\n\t}\n\n\t/**\n\t * Estimate variable as tokens\n\t * @param history Object to size\n\t * @returns {number} Rough token count\n\t */\n\testimateTokens(history: any): number {\n\t\tconst text = JSON.stringify(history);\n\t\treturn Math.ceil((text.length / 4) * 1.2);\n\t}\n\n\t/**\n\t * Ask a question with JSON response\n\t * @param {string} message Question\n\t * @param {LLMRequest} options Configuration options and chat history\n\t * @returns {Promise<{} | {} | RegExpExecArray | null>}\n\t */\n\tasync json(message: string, options?: LLMRequest) {\n\t\tlet resp = await this.ask(message, {\n\t\t\tsystem: 'Respond using a JSON blob',\n\t\t\t...options\n\t\t});\n\t\tif(!resp?.[0]?.content) return {};\n\t\treturn JSONAttemptParse(new RegExp('\\{[\\s\\S]*\\}').exec(resp[0].content), {});\n\t}\n\n\t/**\n\t * Create a summary of some text\n\t * @param {string} text Text to summarize\n\t * @param {number} tokens Max number of tokens\n\t * @param options LLM request options\n\t * @returns {Promise<string>} Summary\n\t */\n\tsummarize(text: string, tokens: number, options?: LLMRequest): Promise<string | null> {\n\t\treturn this.ask(text, {system: `Generate a brief summary <= ${tokens} tokens. Output nothing else`, temperature: 0.3, ...options})\n\t\t\t.then(history => <string>history.pop()?.content || null);\n\t}\n}\n","import {createWorker} from 'tesseract.js';\nimport {LLM, LLMOptions} from './llm';\nimport fs from 'node:fs/promises';\nimport Path from 'node:path';\nimport * as tf from '@tensorflow/tfjs';\nimport {spawn} from 'node:child_process';\n\nexport type AiOptions = LLMOptions & {\n\twhisper?: {\n\t\t/** Whisper binary location */\n\t\tbinary: string;\n\t\t/** Model: `ggml-base.en.bin` */\n\t\tmodel: string;\n\t\t/** Path to models */\n\t\tpath: string;\n\t}\n}\n\nexport class Ai {\n\tprivate downloads: {[key: string]: Promise<string>} = {};\n\tprivate whisperModel!: string;\n\n\t/** Large Language Models */\n\tllm!: LLM;\n\n\tconstructor(public readonly options: AiOptions) {\n\t\tthis.llm = new LLM(this, options);\n\t\tif(this.options.whisper?.binary) {\n\t\t\tthis.whisperModel = this.options.whisper?.model.endsWith('.bin') ? this.options.whisper?.model : this.options.whisper?.model + '.bin';\n\t\t\tthis.downloadAsrModel();\n\t\t}\n\t}\n\n\t/**\n\t * Convert audio to text using Auditory Speech Recognition\n\t * @param {string} path Path to audio\n\t * @param model Whisper model\n\t * @returns {Promise<any>} Extracted text\n\t */\n\tasr(path: string, model: string = this.whisperModel): {abort: () => void, response: Promise<string | null>} {\n\t\tif(!this.options.whisper?.binary) throw new Error('Whisper not configured');\n\t\tlet abort: any = () => {};\n\t\tconst response = new Promise<string | null>((resolve, reject) => {\n\t\t\tthis.downloadAsrModel(model).then(m => {\n\t\t\t\tlet output = '';\n\t\t\t\tconst proc = spawn(<string>this.options.whisper?.binary, ['-nt', '-np', '-m', m, '-f', path], {stdio: ['ignore', 'pipe', 'ignore']});\n\t\t\t\tabort = () => proc.kill('SIGTERM');\n\t\t\t\tproc.on('error', (err: Error) => reject(err));\n\t\t\t\tproc.stdout.on('data', (data: Buffer) => output += data.toString());\n\t\t\t\tproc.on('close', (code: number) => {\n\t\t\t\t\tif(code === 0) resolve(output.trim() || null);\n\t\t\t\t\telse reject(new Error(`Exit code ${code}`));\n\t\t\t\t});\n\t\t\t});\n\t\t});\n\t\treturn {response, abort};\n\t}\n\n\t/**\n\t * Downloads the specified Whisper model if it is not already present locally.\n\t *\n\t * @param {string} model Whisper model that will be downloaded\n\t * @return {Promise<string>} Absolute path to model file, resolves once downloaded\n\t */\n\tasync downloadAsrModel(model: string = this.whisperModel): Promise<string> {\n\t\tif(!this.options.whisper?.binary) throw new Error('Whisper not configured');\n\t\tif(!model.endsWith('.bin')) model += '.bin';\n\t\tconst p = Path.join(this.options.whisper.path, model);\n\t\tif(await fs.stat(p).then(() => true).catch(() => false)) return p;\n\t\tif(!!this.downloads[model]) return this.downloads[model];\n\t\tthis.downloads[model] = fetch(`https://huggingface.co/ggerganov/whisper.cpp/resolve/main/${model}`)\n\t\t\t.then(resp => resp.arrayBuffer())\n\t\t\t.then(arr => Buffer.from(arr)).then(async buffer => {\n\t\t\t\tawait fs.writeFile(p, buffer);\n\t\t\t\tdelete this.downloads[model];\n\t\t\t\treturn p;\n\t\t\t});\n\t\treturn this.downloads[model];\n\t}\n\n\t/**\n\t * Convert image to text using Optical Character Recognition\n\t * @param {string} path Path to image\n\t * @returns {{abort: Function, response: Promise<string | null>}} Abort function & Promise of extracted text\n\t */\n\tocr(path: string): {abort: () => void, response: Promise<string | null>} {\n\t\tlet worker: any;\n\t\treturn {\n\t\t\tabort: () => { worker?.terminate(); },\n\t\t\tresponse: new Promise(async res => {\n\t\t\t\tworker = await createWorker('eng');\n\t\t\t\tconst {data} = await worker.recognize(path);\n\t\t\t\tawait worker.terminate();\n\t\t\t\tres(data.text.trim() || null);\n\t\t\t})\n\t\t}\n\t}\n\n\t/**\n\t * Compare the difference between two strings using tensor math\n\t * @param target Text that will checked\n\t * @param {string} searchTerms Multiple search terms to check against target\n\t * @returns {{avg: number, max: number, similarities: number[]}} Similarity values 0-1: 0 = unique, 1 = identical\n\t */\n\tsemanticSimilarity(target: string, ...searchTerms: string[]) {\n\t\tif(searchTerms.length < 2) throw new Error('Requires at least 2 strings to compare');\n\n\t\tconst vector = (text: string, dimensions: number = 10): number[] => {\n\t\t\treturn text.toLowerCase().split('').map((char, index) =>\n\t\t\t\t(char.charCodeAt(0) * (index + 1)) % dimensions / dimensions).slice(0, dimensions);\n\t\t}\n\n\t\tconst cosineSimilarity = (v1: number[], v2: number[]): number => {\n\t\t\tif (v1.length !== v2.length) throw new Error('Vectors must be same length');\n\t\t\tconst tensor1 = tf.tensor1d(v1), tensor2 = tf.tensor1d(v2)\n\t\t\tconst dotProduct = tf.dot(tensor1, tensor2)\n\t\t\tconst magnitude1 = tf.norm(tensor1)\n\t\t\tconst magnitude2 = tf.norm(tensor2)\n\t\t\tif(magnitude1.dataSync()[0] === 0 || magnitude2.dataSync()[0] === 0) return 0\n\t\t\treturn dotProduct.dataSync()[0] / (magnitude1.dataSync()[0] * magnitude2.dataSync()[0])\n\t\t}\n\n\t\tconst v = vector(target);\n\t\tconst similarities = searchTerms.map(t => vector(t)).map(refVector => cosineSimilarity(v, refVector))\n\t\treturn {avg: similarities.reduce((acc, s) => acc + s, 0) / similarities.length, max: Math.max(...similarities), similarities}\n\t}\n}\n","import {$, $Sync} from '@ztimson/node-utils';\nimport {ASet, consoleInterceptor, Http, fn as Fn} from '@ztimson/utils';\nimport {Ai} from './ai.ts';\n\nexport type AiToolArg = {[key: string]: {\n\t/** Argument type */\n\ttype: 'array' | 'boolean' | 'number' | 'object' | 'string',\n\t/** Argument description */\n\tdescription: string,\n\t/** Required argument */\n\trequired?: boolean;\n\t/** Default value */\n\tdefault?: any,\n\t/** Options */\n\tenum?: string[],\n\t/** Minimum value or length */\n\tmin?: number,\n\t/** Maximum value or length */\n\tmax?: number,\n\t/** Match pattern */\n\tpattern?: string,\n\t/** Child arguments */\n\titems?: {[key: string]: AiToolArg}\n}}\n\nexport type AiTool = {\n\t/** Tool ID / Name - Must be snail_case */\n\tname: string,\n\t/** Tool description / prompt */\n\tdescription: string,\n\t/** Tool arguments */\n\targs?: AiToolArg,\n\t/** Callback function */\n\tfn: (args: any, ai: Ai) => any | Promise<any>,\n};\n\nexport const CliTool: AiTool = {\n\tname: 'cli',\n\tdescription: 'Use the command line interface, returns any output',\n\targs: {command: {type: 'string', description: 'Command to run', required: true}},\n\tfn: (args: {command: string}) => $`${args.command}`\n}\n\nexport const DateTimeTool: AiTool = {\n\tname: 'get_datetime',\n\tdescription: 'Get current date and time',\n\targs: {},\n\tfn: async () => new Date().toISOString()\n}\n\nexport const ExecTool: AiTool = {\n\tname: 'exec',\n\tdescription: 'Run code/scripts',\n\targs: {\n\t\tlanguage: {type: 'string', description: 'Execution language', enum: ['cli', 'node', 'python'], required: true},\n\t\tcode: {type: 'string', description: 'Code to execute', required: true}\n\t},\n\tfn: async (args, ai) => {\n\t\ttry {\n\t\t\tswitch(args.type) {\n\t\t\t\tcase 'bash':\n\t\t\t\t\treturn await CliTool.fn({command: args.code}, ai);\n\t\t\t\tcase 'node':\n\t\t\t\t\treturn await JSTool.fn({code: args.code}, ai);\n\t\t\t\tcase 'python': {\n\t\t\t\t\treturn await PythonTool.fn({code: args.code}, ai);\n\t\t\t\t}\n\t\t\t}\n\t\t} catch(err: any) {\n\t\t\treturn {error: err?.message || err.toString()};\n\t\t}\n\t}\n}\n\nexport const FetchTool: AiTool = {\n\tname: 'fetch',\n\tdescription: 'Make HTTP request to URL',\n\targs: {\n\t\turl: {type: 'string', description: 'URL to fetch', required: true},\n\t\tmethod: {type: 'string', description: 'HTTP method to use', enum: ['GET', 'POST', 'PUT', 'DELETE'], default: 'GET'},\n\t\theaders: {type: 'object', description: 'HTTP headers to send', default: {}},\n\t\tbody: {type: 'object', description: 'HTTP body to send'},\n\t},\n\tfn: (args: {\n\t\turl: string;\n\t\tmethod: 'GET' | 'POST' | 'PUT' | 'DELETE';\n\t\theaders: {[key: string]: string};\n\t\tbody: any;\n\t}) => new Http({url: args.url, headers: args.headers}).request({method: args.method || 'GET', body: args.body})\n}\n\nexport const JSTool: AiTool = {\n\tname: 'exec_javascript',\n\tdescription: 'Execute commonjs javascript',\n\targs: {\n\t\tcode: {type: 'string', description: 'CommonJS javascript', required: true}\n\t},\n\tfn: async (args: {code: string}) => {\n\t\tconst console = consoleInterceptor(null);\n\t\tconst resp = await Fn<any>({console}, args.code, true).catch((err: any) => console.output.error.push(err));\n\t\treturn {...console.output, return: resp, stdout: undefined, stderr: undefined};\n\t}\n}\n\nexport const PythonTool: AiTool = {\n\tname: 'exec_javascript',\n\tdescription: 'Execute commonjs javascript',\n\targs: {\n\t\tcode: {type: 'string', description: 'CommonJS javascript', required: true}\n\t},\n\tfn: async (args: {code: string}) => ({result: $Sync`python -c \"${args.code}\"`})\n}\n\nexport const SearchTool: AiTool = {\n\tname: 'search',\n\tdescription: 'Use a search engine to find relevant URLs, should be changed with fetch to scrape sources',\n\targs: {\n\t\tquery: {type: 'string', description: 'Search string', required: true},\n\t\tlength: {type: 'string', description: 'Number of results to return', default: 5},\n\t},\n\tfn: async (args: {\n\t\tquery: string;\n\t\tlength: number;\n\t}) => {\n\t\tconst html = await fetch(`https://html.duckduckgo.com/html/?q=${encodeURIComponent(args.query)}`, {\n\t\t\theaders: {\"User-Agent\": \"Mozilla/5.0 (Windows NT 10.0; Win64; x64)\", \"Accept-Language\": \"en-US,en;q=0.9\"}\n\t\t}).then(resp => resp.text());\n\t\tlet match, regex = /<a .*?href=\"(.+?)\".+?<\\/a>/g;\n\t\tconst results = new ASet<string>();\n\t\twhile((match = regex.exec(html)) !== null) {\n\t\t\tlet url = /uddg=(.+)&amp?/.exec(decodeURIComponent(match[1]))?.[1];\n\t\t\tif(url) url = decodeURIComponent(url);\n\t\t\tif(url) results.add(url);\n\t\t\tif(results.size >= (args.length || 5)) break;\n\t\t}\n\t\treturn results;\n\t}\n}\n"],"names":["LLMProvider","Anthropic","ai","apiToken","model","anthropic","history","i","orgI","c","h","timestamp","message","options","controller","response","res","rej","requestParams","t","objectMap","key","value","resp","assistantMessages","chunk","text","last","JSONAttemptParse","textContent","toolCalls","results","toolCall","tool","findByProp","result","JSONSanitize","err","Ollama","host","ollama","error","rest","system","loopMessages","args","r","combinedContent","m","OpenAi","openAI","tools","tc","record","h2","LLM","max","min","keep","tokens","recent","process","Ai","path","abort","resolve","reject","output","proc","spawn","data","code","p","Path","fs","arr","buffer","worker","createWorker","target","searchTerms","vector","dimensions","char","index","cosineSimilarity","v1","v2","tensor1","tf","tensor2","dotProduct","magnitude1","magnitude2","v","similarities","refVector","acc","s","CliTool","$","DateTimeTool","ExecTool","JSTool","PythonTool","FetchTool","Http","console","consoleInterceptor","Fn","$Sync","SearchTool","html","match","regex","ASet","url"],"mappings":"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"}
package/dist/index.mjs CHANGED
@@ -1,10 +1,10 @@
1
1
  import { createWorker as T } from "tesseract.js";
2
- import { objectMap as k, JSONAttemptParse as b, findByProp as x, JSONSanitize as y, Http as q, consoleInterceptor as v, fn as P, ASet as A } from "@ztimson/utils";
2
+ import { objectMap as k, JSONAttemptParse as y, findByProp as x, JSONSanitize as b, Http as q, consoleInterceptor as v, fn as P, ASet as A } from "@ztimson/utils";
3
3
  import { Anthropic as E } from "@anthropic-ai/sdk";
4
- import { Ollama as D } from "ollama";
5
- import { OpenAI as M } from "openai";
4
+ import { Ollama as M } from "ollama";
5
+ import { OpenAI as O } from "openai";
6
6
  import j from "node:fs/promises";
7
- import O from "node:path";
7
+ import D from "node:path";
8
8
  import * as _ from "@tensorflow/tfjs";
9
9
  import { spawn as U } from "node:child_process";
10
10
  import { $, $Sync as L } from "@ztimson/node-utils";
@@ -21,8 +21,8 @@ class R extends S {
21
21
  typeof t[n].content != "string" && (t[n].role == "assistant" ? t[n].content.filter((o) => o.type == "tool_use").forEach((o) => {
22
22
  e++, t.splice(e, 0, { role: "tool", id: o.id, name: o.name, args: o.input, timestamp: Date.now() });
23
23
  }) : t[n].role == "user" && t[n].content.filter((o) => o.type == "tool_result").forEach((o) => {
24
- const l = t.find((p) => p.id == o.tool_use_id);
25
- l[o.is_error ? "error" : "content"] = o.content;
24
+ const c = t.find((f) => f.id == o.tool_use_id);
25
+ c[o.is_error ? "error" : "content"] = o.content;
26
26
  }), t[n].content = t[n].content.filter((o) => o.type == "text").map((o) => o.text).join(`
27
27
 
28
28
  `)), t[n].timestamp || (t[n].timestamp = Date.now());
@@ -43,80 +43,80 @@ class R extends S {
43
43
  return t.map(({ timestamp: e, ...n }) => n);
44
44
  }
45
45
  ask(t, e = {}) {
46
- const n = new AbortController(), o = new Promise(async (l, p) => {
47
- let m = this.fromStandard([...e.history || [], { role: "user", content: t, timestamp: Date.now() }]);
48
- e.compress && (m = await this.ai.llm.compress(m, e.compress.max, e.compress.min, e));
49
- const d = {
46
+ const n = new AbortController(), o = new Promise(async (c, f) => {
47
+ let l = this.fromStandard([...e.history || [], { role: "user", content: t, timestamp: Date.now() }]);
48
+ e.compress && (l = await this.ai.llm.compress(l, e.compress.max, e.compress.min, e));
49
+ const m = {
50
50
  model: e.model || this.model,
51
51
  max_tokens: e.max_tokens || this.ai.options.max_tokens || 4096,
52
52
  system: e.system || this.ai.options.system || "",
53
53
  temperature: e.temperature || this.ai.options.temperature || 0.7,
54
- tools: (e.tools || this.ai.options.tools || []).map((a) => ({
55
- name: a.name,
56
- description: a.description,
54
+ tools: (e.tools || this.ai.options.tools || []).map((p) => ({
55
+ name: p.name,
56
+ description: p.description,
57
57
  input_schema: {
58
58
  type: "object",
59
- properties: a.args ? k(a.args, (s, i) => ({ ...i, required: void 0 })) : {},
60
- required: a.args ? Object.entries(a.args).filter((s) => s[1].required).map((s) => s[0]) : []
59
+ properties: p.args ? k(p.args, (d, s) => ({ ...s, required: void 0 })) : {},
60
+ required: p.args ? Object.entries(p.args).filter((d) => d[1].required).map((d) => d[0]) : []
61
61
  },
62
62
  fn: void 0
63
63
  })),
64
- messages: m,
64
+ messages: l,
65
65
  stream: !!e.stream
66
66
  };
67
- let c;
67
+ let i;
68
68
  const r = [];
69
69
  do {
70
- if (c = await this.client.messages.create(d), e.stream) {
70
+ if (i = await this.client.messages.create(m), e.stream) {
71
71
  r.length && e.stream({ text: `
72
72
 
73
- ` }), c.content = [];
74
- for await (const s of c) {
73
+ ` }), i.content = [];
74
+ for await (const s of i) {
75
75
  if (n.signal.aborted) break;
76
76
  if (s.type === "content_block_start")
77
- s.content_block.type === "text" ? c.content.push({ type: "text", text: "" }) : s.content_block.type === "tool_use" && c.content.push({ type: "tool_use", id: s.content_block.id, name: s.content_block.name, input: "" });
77
+ s.content_block.type === "text" ? i.content.push({ type: "text", text: "" }) : s.content_block.type === "tool_use" && i.content.push({ type: "tool_use", id: s.content_block.id, name: s.content_block.name, input: "" });
78
78
  else if (s.type === "content_block_delta")
79
79
  if (s.delta.type === "text_delta") {
80
- const i = s.delta.text;
81
- c.content.at(-1).text += i, e.stream({ text: i });
82
- } else s.delta.type === "input_json_delta" && (c.content.at(-1).input += s.delta.partial_json);
80
+ const a = s.delta.text;
81
+ i.content.at(-1).text += a, e.stream({ text: a });
82
+ } else s.delta.type === "input_json_delta" && (i.content.at(-1).input += s.delta.partial_json);
83
83
  else if (s.type === "content_block_stop") {
84
- const i = c.content.at(-1);
85
- i.input != null && (i.input = i.input ? b(i.input, {}) : {});
84
+ const a = i.content.at(-1);
85
+ a.input != null && (a.input = a.input ? y(a.input, {}) : {});
86
86
  } else if (s.type === "message_stop")
87
87
  break;
88
88
  }
89
89
  }
90
- r.push({ role: "assistant", content: c.content, timestamp: Date.now() });
91
- const a = c.content.filter((s) => s.type === "tool_use");
92
- if (a.length && !n.signal.aborted) {
93
- m.push({ role: "assistant", content: c.content });
94
- const i = { role: "user", content: await Promise.all(a.map(async (f) => {
95
- const h = e.tools?.find(x("name", f.name));
96
- if (!h) return { tool_use_id: f.id, is_error: !0, content: "Tool not found" };
90
+ const p = i.content.filter((s) => s.type == "text").map((s) => s.text).join(`
91
+
92
+ `);
93
+ p && r.push(p);
94
+ const d = i.content.filter((s) => s.type === "tool_use");
95
+ if (d.length && !n.signal.aborted) {
96
+ l.push({ role: "assistant", content: i.content });
97
+ const s = await Promise.all(d.map(async (a) => {
98
+ const g = e.tools?.find(x("name", a.name));
99
+ if (!g) return { tool_use_id: a.id, is_error: !0, content: "Tool not found" };
97
100
  try {
98
- const g = await h.fn(f.input, this.ai);
99
- return { type: "tool_result", tool_use_id: f.id, content: y(g) };
100
- } catch (g) {
101
- return { type: "tool_result", tool_use_id: f.id, is_error: !0, content: g?.message || g?.toString() || "Unknown" };
101
+ const h = await g.fn(a.input, this.ai);
102
+ return { type: "tool_result", tool_use_id: a.id, content: b(h) };
103
+ } catch (h) {
104
+ return { type: "tool_result", tool_use_id: a.id, is_error: !0, content: h?.message || h?.toString() || "Unknown" };
102
105
  }
103
- })) };
104
- m.push(i), r.push({ ...i, timestamp: Date.now() }), d.messages = m;
106
+ }));
107
+ l.push({ role: "user", content: s }), m.messages = l;
105
108
  }
106
- } while (!n.signal.aborted && c.content.some((a) => a.type === "tool_use"));
107
- const w = r.filter((a) => a.role === "assistant").map((a) => a.content.filter((s) => s.type == "text").map((s) => s.text).join(`
109
+ } while (!n.signal.aborted && i.content.some((p) => p.type === "tool_use"));
110
+ e.stream && e.stream({ done: !0 }), c(this.toStandard([...l, { role: "assistant", content: r.join(`
108
111
 
109
- `)).filter((a) => a).join(`
110
-
111
- `);
112
- e.stream && e.stream({ done: !0 }), l(this.toStandard([...m, { role: "assistant", content: w, timestamp: Date.now() }]));
112
+ `), timestamp: Date.now() }]));
113
113
  });
114
114
  return Object.assign(o, { abort: () => n.abort() });
115
115
  }
116
116
  }
117
117
  class I extends S {
118
118
  constructor(t, e, n) {
119
- super(), this.ai = t, this.host = e, this.model = n, this.client = new D({ host: e });
119
+ super(), this.ai = t, this.host = e, this.model = n, this.client = new M({ host: e });
120
120
  }
121
121
  client;
122
122
  toStandard(t) {
@@ -138,12 +138,12 @@ class I extends S {
138
138
  });
139
139
  }
140
140
  ask(t, e = {}) {
141
- const n = new AbortController(), o = new Promise(async (l, p) => {
142
- let m = e.system || this.ai.options.system, d = this.fromStandard([...e.history || [], { role: "user", content: t, timestamp: Date.now() }]);
143
- d[0].roll == "system" && (m ? d.shift() : m = d.shift()), e.compress && (d = await this.ai.llm.compress(d, e.compress.max, e.compress.min)), e.system && d.unshift({ role: "system", content: m });
144
- const c = {
141
+ const n = new AbortController(), o = new Promise(async (c, f) => {
142
+ let l = e.system || this.ai.options.system, m = this.fromStandard([...e.history || [], { role: "user", content: t, timestamp: Date.now() }]);
143
+ m[0].roll == "system" && (l ? m.shift() : l = m.shift()), e.compress && (m = await this.ai.llm.compress(m, e.compress.max, e.compress.min)), e.system && m.unshift({ role: "system", content: l });
144
+ const i = {
145
145
  model: e.model || this.model,
146
- messages: d,
146
+ messages: m,
147
147
  stream: !!e.stream,
148
148
  signal: n.signal,
149
149
  options: {
@@ -157,65 +157,65 @@ class I extends S {
157
157
  description: s.description,
158
158
  parameters: {
159
159
  type: "object",
160
- properties: s.args ? k(s.args, (i, f) => ({ ...f, required: void 0 })) : {},
161
- required: s.args ? Object.entries(s.args).filter((i) => i[1].required).map((i) => i[0]) : []
160
+ properties: s.args ? k(s.args, (a, g) => ({ ...g, required: void 0 })) : {},
161
+ required: s.args ? Object.entries(s.args).filter((a) => a[1].required).map((a) => a[0]) : []
162
162
  }
163
163
  }
164
164
  }))
165
165
  };
166
166
  let r;
167
- const w = [];
167
+ const p = [];
168
168
  do {
169
- if (r = await this.client.chat(c), e.stream) {
170
- w.length && e.stream({ text: `
169
+ if (r = await this.client.chat(i), e.stream) {
170
+ p.length && e.stream({ text: `
171
171
 
172
172
  ` }), r.message = { role: "assistant", content: "", tool_calls: [] };
173
173
  for await (const s of r)
174
174
  if (n.signal.aborted || (s.message?.content && (r.message.content += s.message.content, e.stream({ text: s.message.content })), s.message?.tool_calls && (r.message.tool_calls = s.message.tool_calls), s.done)) break;
175
175
  }
176
- if (w.push({ role: "assistant", content: r.message?.content, timestamp: Date.now() }), r.message?.tool_calls?.length && !n.signal.aborted) {
177
- d.push(r.message);
178
- const s = await Promise.all(r.message.tool_calls.map(async (i) => {
179
- const f = (e.tools || this.ai.options.tools)?.find(x("name", i.function.name));
180
- if (!f) return { role: "tool", tool_name: i.function.name, content: '{"error": "Tool not found"}' };
181
- const h = typeof i.function.arguments == "string" ? b(i.function.arguments, {}) : i.function.arguments;
176
+ if (p.push({ role: "assistant", content: r.message?.content, timestamp: Date.now() }), r.message?.tool_calls?.length && !n.signal.aborted) {
177
+ m.push(r.message);
178
+ const s = await Promise.all(r.message.tool_calls.map(async (a) => {
179
+ const g = (e.tools || this.ai.options.tools)?.find(x("name", a.function.name));
180
+ if (!g) return { role: "tool", tool_name: a.function.name, content: '{"error": "Tool not found"}' };
181
+ const h = typeof a.function.arguments == "string" ? y(a.function.arguments, {}) : a.function.arguments;
182
182
  try {
183
- const g = await f.fn(h, this.ai);
184
- return { role: "tool", tool_name: i.function.name, args: h, content: y(g) };
185
- } catch (g) {
186
- return { role: "tool", tool_name: i.function.name, args: h, content: y({ error: g?.message || g?.toString() || "Unknown" }) };
183
+ const w = await g.fn(h, this.ai);
184
+ return { role: "tool", tool_name: a.function.name, args: h, content: b(w) };
185
+ } catch (w) {
186
+ return { role: "tool", tool_name: a.function.name, args: h, content: b({ error: w?.message || w?.toString() || "Unknown" }) };
187
187
  }
188
188
  }));
189
- d.push(...s), w.push(...s.map((i) => ({ ...i, timestamp: Date.now() }))), c.messages = d;
189
+ m.push(...s), p.push(...s.map((a) => ({ ...a, timestamp: Date.now() }))), i.messages = m;
190
190
  }
191
191
  } while (!n.signal.aborted && r.message?.tool_calls?.length);
192
- const a = w.filter((s) => s.role === "assistant").map((s) => s.content).filter((s) => s).join(`
192
+ const d = p.filter((s) => s.role === "assistant").map((s) => s.content).filter((s) => s).join(`
193
193
 
194
194
  `);
195
- e.stream && e.stream({ done: !0 }), l(this.toStandard([...d, { role: "assistant", content: a, timestamp: Date.now() }]));
195
+ e.stream && e.stream({ done: !0 }), c(this.toStandard([...m, { role: "assistant", content: d, timestamp: Date.now() }]));
196
196
  });
197
197
  return Object.assign(o, { abort: () => n.abort() });
198
198
  }
199
199
  }
200
200
  class J extends S {
201
201
  constructor(t, e, n) {
202
- super(), this.ai = t, this.apiToken = e, this.model = n, this.client = new M({ apiKey: e });
202
+ super(), this.ai = t, this.apiToken = e, this.model = n, this.client = new O({ apiKey: e });
203
203
  }
204
204
  client;
205
205
  toStandard(t) {
206
206
  for (let e = 0; e < t.length; e++) {
207
207
  const n = t[e];
208
208
  if (n.role === "assistant" && n.tool_calls) {
209
- const o = n.tool_calls.map((l) => ({
209
+ const o = n.tool_calls.map((c) => ({
210
210
  role: "tool",
211
- id: l.id,
212
- name: l.function.name,
213
- args: b(l.function.arguments, {}),
211
+ id: c.id,
212
+ name: c.function.name,
213
+ args: y(c.function.arguments, {}),
214
214
  timestamp: n.timestamp
215
215
  }));
216
216
  t.splice(e, 1, ...o), e += o.length - 1;
217
217
  } else if (n.role === "tool" && n.content) {
218
- const o = t.find((l) => n.tool_call_id == l.id);
218
+ const o = t.find((c) => n.tool_call_id == c.id);
219
219
  o && (n.content.includes('"error":') ? o.error = n.content : o.content = n.content), t.splice(e, 1), e--;
220
220
  }
221
221
  t[e]?.timestamp || (t[e].timestamp = Date.now());
@@ -237,68 +237,68 @@ class J extends S {
237
237
  content: n.error || n.content
238
238
  });
239
239
  else {
240
- const { timestamp: o, ...l } = n;
241
- e.push(l);
240
+ const { timestamp: o, ...c } = n;
241
+ e.push(c);
242
242
  }
243
243
  return e;
244
244
  }, []);
245
245
  }
246
246
  ask(t, e = {}) {
247
- const n = new AbortController(), o = new Promise(async (l, p) => {
248
- let m = this.fromStandard([...e.history || [], { role: "user", content: t, timestamp: Date.now() }]);
249
- e.compress && (m = await this.ai.llm.compress(m, e.compress.max, e.compress.min, e));
250
- const d = {
247
+ const n = new AbortController(), o = new Promise(async (c, f) => {
248
+ let l = this.fromStandard([...e.history || [], { role: "user", content: t, timestamp: Date.now() }]);
249
+ e.compress && (l = await this.ai.llm.compress(l, e.compress.max, e.compress.min, e));
250
+ const m = {
251
251
  model: e.model || this.model,
252
- messages: m,
252
+ messages: l,
253
253
  stream: !!e.stream,
254
254
  max_tokens: e.max_tokens || this.ai.options.max_tokens || 4096,
255
255
  temperature: e.temperature || this.ai.options.temperature || 0.7,
256
- tools: (e.tools || this.ai.options.tools || []).map((a) => ({
256
+ tools: (e.tools || this.ai.options.tools || []).map((d) => ({
257
257
  type: "function",
258
258
  function: {
259
- name: a.name,
260
- description: a.description,
259
+ name: d.name,
260
+ description: d.description,
261
261
  parameters: {
262
262
  type: "object",
263
- properties: a.args ? k(a.args, (s, i) => ({ ...i, required: void 0 })) : {},
264
- required: a.args ? Object.entries(a.args).filter((s) => s[1].required).map((s) => s[0]) : []
263
+ properties: d.args ? k(d.args, (s, a) => ({ ...a, required: void 0 })) : {},
264
+ required: d.args ? Object.entries(d.args).filter((s) => s[1].required).map((s) => s[0]) : []
265
265
  }
266
266
  }
267
267
  }))
268
268
  };
269
- let c;
269
+ let i;
270
270
  const r = [];
271
271
  do {
272
- if (c = await this.client.chat.completions.create(d), e.stream) {
272
+ if (i = await this.client.chat.completions.create(m), e.stream) {
273
273
  r.length && e.stream({ text: `
274
274
 
275
- ` }), c.choices = [{ message: { content: "", tool_calls: [] } }];
276
- for await (const s of c) {
275
+ ` }), i.choices = [{ message: { content: "", tool_calls: [] } }];
276
+ for await (const s of i) {
277
277
  if (n.signal.aborted) break;
278
- s.choices[0].delta.content && (c.choices[0].message.content += s.choices[0].delta.content, e.stream({ text: s.choices[0].delta.content })), s.choices[0].delta.tool_calls && (c.choices[0].message.tool_calls = s.choices[0].delta.tool_calls);
278
+ s.choices[0].delta.content && (i.choices[0].message.content += s.choices[0].delta.content, e.stream({ text: s.choices[0].delta.content })), s.choices[0].delta.tool_calls && (i.choices[0].message.tool_calls = s.choices[0].delta.tool_calls);
279
279
  }
280
280
  }
281
- r.push({ role: "assistant", content: c.choices[0].message.content || "", timestamp: Date.now() });
282
- const a = c.choices[0].message.tool_calls || [];
283
- if (a.length && !n.signal.aborted) {
284
- m.push(c.choices[0].message);
285
- const s = await Promise.all(a.map(async (i) => {
286
- const f = e.tools?.find(x("name", i.function.name));
287
- if (!f) return { role: "tool", tool_call_id: i.id, content: '{"error": "Tool not found"}' };
281
+ r.push({ role: "assistant", content: i.choices[0].message.content || "", timestamp: Date.now() });
282
+ const d = i.choices[0].message.tool_calls || [];
283
+ if (d.length && !n.signal.aborted) {
284
+ l.push(i.choices[0].message);
285
+ const s = await Promise.all(d.map(async (a) => {
286
+ const g = e.tools?.find(x("name", a.function.name));
287
+ if (!g) return { role: "tool", tool_call_id: a.id, content: '{"error": "Tool not found"}' };
288
288
  try {
289
- const h = b(i.function.arguments, {}), g = await f.fn(h, this.ai);
290
- return { role: "tool", tool_call_id: i.id, content: y(g) };
289
+ const h = y(a.function.arguments, {}), w = await g.fn(h, this.ai);
290
+ return { role: "tool", tool_call_id: a.id, content: b(w) };
291
291
  } catch (h) {
292
- return { role: "tool", tool_call_id: i.id, content: y({ error: h?.message || h?.toString() || "Unknown" }) };
292
+ return { role: "tool", tool_call_id: a.id, content: b({ error: h?.message || h?.toString() || "Unknown" }) };
293
293
  }
294
294
  }));
295
- m.push(...s), r.push(...s.map((i) => ({ ...i, timestamp: Date.now() }))), d.messages = m;
295
+ l.push(...s), r.push(...s.map((a) => ({ ...a, timestamp: Date.now() }))), m.messages = l;
296
296
  }
297
- } while (!n.signal.aborted && c.choices?.[0]?.message?.tool_calls?.length);
298
- const w = r.filter((a) => a.role === "assistant").map((a) => a.content).filter((a) => a).join(`
297
+ } while (!n.signal.aborted && i.choices?.[0]?.message?.tool_calls?.length);
298
+ const p = r.filter((d) => d.role === "assistant").map((d) => d.content).filter((d) => d).join(`
299
299
 
300
300
  `);
301
- e.stream && e.stream({ done: !0 }), l(this.toStandard([...m, { role: "assistant", content: w, timestamp: Date.now() }]));
301
+ e.stream && e.stream({ done: !0 }), c(this.toStandard([...l, { role: "assistant", content: p, timestamp: Date.now() }]));
302
302
  });
303
303
  return Object.assign(o, { abort: () => n.abort() });
304
304
  }
@@ -329,15 +329,15 @@ class W {
329
329
  */
330
330
  async compress(t, e, n, o) {
331
331
  if (this.estimateTokens(t) < e) return t;
332
- let l = 0, p = 0;
332
+ let c = 0, f = 0;
333
333
  for (let r of t.toReversed())
334
- if (p += this.estimateTokens(r.content), p < n) l++;
334
+ if (f += this.estimateTokens(r.content), f < n) c++;
335
335
  else break;
336
- if (t.length <= l) return t;
337
- const m = l == 0 ? [] : t.slice(-l), d = (l == 0 ? t : t.slice(0, -l)).filter((r) => r.role === "assistant" || r.role === "user");
338
- return [{ role: "assistant", content: `Conversation Summary: ${await this.summarize(d.map((r) => `${r.role}: ${r.content}`).join(`
336
+ if (t.length <= c) return t;
337
+ const l = c == 0 ? [] : t.slice(-c), m = (c == 0 ? t : t.slice(0, -c)).filter((r) => r.role === "assistant" || r.role === "user");
338
+ return [{ role: "assistant", content: `Conversation Summary: ${await this.summarize(m.map((r) => `${r.role}: ${r.content}`).join(`
339
339
 
340
- `), 250, o)}`, timestamp: Date.now() }, ...m];
340
+ `), 250, o)}`, timestamp: Date.now() }, ...l];
341
341
  }
342
342
  /**
343
343
  * Estimate variable as tokens
@@ -359,7 +359,7 @@ class W {
359
359
  system: "Respond using a JSON blob",
360
360
  ...e
361
361
  });
362
- return n?.[0]?.content ? b(new RegExp("{[sS]*}").exec(n[0].content), {}) : {};
362
+ return n?.[0]?.content ? y(new RegExp("{[sS]*}").exec(n[0].content), {}) : {};
363
363
  }
364
364
  /**
365
365
  * Create a summary of some text
@@ -390,12 +390,12 @@ class Z {
390
390
  if (!this.options.whisper?.binary) throw new Error("Whisper not configured");
391
391
  let n = () => {
392
392
  };
393
- return { response: new Promise((l, p) => {
394
- this.downloadAsrModel(e).then((m) => {
395
- let d = "";
396
- const c = U(this.options.whisper?.binary, ["-nt", "-np", "-m", m, "-f", t], { stdio: ["ignore", "pipe", "ignore"] });
397
- n = () => c.kill("SIGTERM"), c.on("error", (r) => p(r)), c.stdout.on("data", (r) => d += r.toString()), c.on("close", (r) => {
398
- r === 0 ? l(d.trim() || null) : p(new Error(`Exit code ${r}`));
393
+ return { response: new Promise((c, f) => {
394
+ this.downloadAsrModel(e).then((l) => {
395
+ let m = "";
396
+ const i = U(this.options.whisper?.binary, ["-nt", "-np", "-m", l, "-f", t], { stdio: ["ignore", "pipe", "ignore"] });
397
+ n = () => i.kill("SIGTERM"), i.on("error", (r) => f(r)), i.stdout.on("data", (r) => m += r.toString()), i.on("close", (r) => {
398
+ r === 0 ? c(m.trim() || null) : f(new Error(`Exit code ${r}`));
399
399
  });
400
400
  });
401
401
  }), abort: n };
@@ -409,7 +409,7 @@ class Z {
409
409
  async downloadAsrModel(t = this.whisperModel) {
410
410
  if (!this.options.whisper?.binary) throw new Error("Whisper not configured");
411
411
  t.endsWith(".bin") || (t += ".bin");
412
- const e = O.join(this.options.whisper.path, t);
412
+ const e = D.join(this.options.whisper.path, t);
413
413
  return await j.stat(e).then(() => !0).catch(() => !1) ? e : this.downloads[t] ? this.downloads[t] : (this.downloads[t] = fetch(`https://huggingface.co/ggerganov/whisper.cpp/resolve/main/${t}`).then((n) => n.arrayBuffer()).then((n) => Buffer.from(n)).then(async (n) => (await j.writeFile(e, n), delete this.downloads[t], e)), this.downloads[t]);
414
414
  }
415
415
  /**
@@ -438,12 +438,12 @@ class Z {
438
438
  */
439
439
  semanticSimilarity(t, ...e) {
440
440
  if (e.length < 2) throw new Error("Requires at least 2 strings to compare");
441
- const n = (m, d = 10) => m.toLowerCase().split("").map((c, r) => c.charCodeAt(0) * (r + 1) % d / d).slice(0, d), o = (m, d) => {
442
- if (m.length !== d.length) throw new Error("Vectors must be same length");
443
- const c = _.tensor1d(m), r = _.tensor1d(d), w = _.dot(c, r), a = _.norm(c), s = _.norm(r);
444
- return a.dataSync()[0] === 0 || s.dataSync()[0] === 0 ? 0 : w.dataSync()[0] / (a.dataSync()[0] * s.dataSync()[0]);
445
- }, l = n(t), p = e.map((m) => n(m)).map((m) => o(l, m));
446
- return { avg: p.reduce((m, d) => m + d, 0) / p.length, max: Math.max(...p), similarities: p };
441
+ const n = (l, m = 10) => l.toLowerCase().split("").map((i, r) => i.charCodeAt(0) * (r + 1) % m / m).slice(0, m), o = (l, m) => {
442
+ if (l.length !== m.length) throw new Error("Vectors must be same length");
443
+ const i = _.tensor1d(l), r = _.tensor1d(m), p = _.dot(i, r), d = _.norm(i), s = _.norm(r);
444
+ return d.dataSync()[0] === 0 || s.dataSync()[0] === 0 ? 0 : p.dataSync()[0] / (d.dataSync()[0] * s.dataSync()[0]);
445
+ }, c = n(t), f = e.map((l) => n(l)).map((l) => o(c, l));
446
+ return { avg: f.reduce((l, m) => l + m, 0) / f.length, max: Math.max(...f), similarities: f };
447
447
  }
448
448
  }
449
449
  const N = {
@@ -514,12 +514,12 @@ const N = {
514
514
  fn: async (u) => {
515
515
  const t = await fetch(`https://html.duckduckgo.com/html/?q=${encodeURIComponent(u.query)}`, {
516
516
  headers: { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64)", "Accept-Language": "en-US,en;q=0.9" }
517
- }).then((l) => l.text());
517
+ }).then((c) => c.text());
518
518
  let e, n = /<a .*?href="(.+?)".+?<\/a>/g;
519
519
  const o = new A();
520
520
  for (; (e = n.exec(t)) !== null; ) {
521
- let l = /uddg=(.+)&amp?/.exec(decodeURIComponent(e[1]))?.[1];
522
- if (l && (l = decodeURIComponent(l)), l && o.add(l), o.size >= (u.length || 5)) break;
521
+ let c = /uddg=(.+)&amp?/.exec(decodeURIComponent(e[1]))?.[1];
522
+ if (c && (c = decodeURIComponent(c)), c && o.add(c), o.size >= (u.length || 5)) break;
523
523
  }
524
524
  return o;
525
525
  }
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","sources":["../src/provider.ts","../src/antrhopic.ts","../src/ollama.ts","../src/open-ai.ts","../src/llm.ts","../src/ai.ts","../src/tools.ts"],"sourcesContent":["import {LLMMessage, LLMOptions, LLMRequest} from './llm.ts';\n\nexport type AbortablePromise<T> = Promise<T> & {abort: () => void};\n\nexport abstract class LLMProvider {\n\tabstract ask(message: string, options: LLMRequest): AbortablePromise<LLMMessage[]>;\n}\n","import {Anthropic as anthropic} from '@anthropic-ai/sdk';\nimport {findByProp, objectMap, JSONSanitize, JSONAttemptParse} from '@ztimson/utils';\nimport {Ai} from './ai.ts';\nimport {LLMMessage, LLMRequest} from './llm.ts';\nimport {AbortablePromise, LLMProvider} from './provider.ts';\n\nexport class Anthropic extends LLMProvider {\n\tclient!: anthropic;\n\n\tconstructor(public readonly ai: Ai, public readonly apiToken: string, public model: string) {\n\t\tsuper();\n\t\tthis.client = new anthropic({apiKey: apiToken});\n\t}\n\n\tprivate toStandard(history: any[]): LLMMessage[] {\n\t\tfor(let i = 0; i < history.length; i++) {\n\t\t\tconst orgI = i;\n\t\t\tif(typeof history[orgI].content != 'string') {\n\t\t\t\tif(history[orgI].role == 'assistant') {\n\t\t\t\t\thistory[orgI].content.filter((c: any) => c.type =='tool_use').forEach((c: any) => {\n\t\t\t\t\t\ti++;\n\t\t\t\t\t\thistory.splice(i, 0, {role: 'tool', id: c.id, name: c.name, args: c.input, timestamp: Date.now()});\n\t\t\t\t\t});\n\t\t\t\t} else if(history[orgI].role == 'user') {\n\t\t\t\t\thistory[orgI].content.filter((c: any) => c.type =='tool_result').forEach((c: any) => {\n\t\t\t\t\t\tconst h = history.find((h: any) => h.id == c.tool_use_id);\n\t\t\t\t\t\th[c.is_error ? 'error' : 'content'] = c.content;\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\thistory[orgI].content = history[orgI].content.filter((c: any) => c.type == 'text').map((c: any) => c.text).join('\\n\\n');\n\t\t\t}\n\t\t\tif(!history[orgI].timestamp) history[orgI].timestamp = Date.now();\n\t\t}\n\t\treturn history.filter(h => !!h.content);\n\t}\n\n\tprivate fromStandard(history: LLMMessage[]): any[] {\n\t\tfor(let i = 0; i < history.length; i++) {\n\t\t\tif(history[i].role == 'tool') {\n\t\t\t\tconst h: any = history[i];\n\t\t\t\thistory.splice(i, 1,\n\t\t\t\t\t{role: 'assistant', content: [{type: 'tool_use', id: h.id, name: h.name, input: h.args}]},\n\t\t\t\t\t{role: 'user', content: [{type: 'tool_result', tool_use_id: h.id, is_error: !!h.error, content: h.error || h.content}]}\n\t\t\t\t)\n\t\t\t\ti++;\n\t\t\t}\n\t\t}\n\t\treturn history.map(({timestamp, ...h}) => h);\n\t}\n\n\task(message: string, options: LLMRequest = {}): AbortablePromise<LLMMessage[]> {\n\t\tconst controller = new AbortController();\n\t\tconst response = new Promise<any>(async (res, rej) => {\n\t\t\tlet history = this.fromStandard([...options.history || [], {role: 'user', content: message, timestamp: Date.now()}]);\n\t\t\tif(options.compress) history = await this.ai.llm.compress(<any>history, options.compress.max, options.compress.min, options);\n\t\t\tconst requestParams: any = {\n\t\t\t\tmodel: options.model || this.model,\n\t\t\t\tmax_tokens: options.max_tokens || this.ai.options.max_tokens || 4096,\n\t\t\t\tsystem: options.system || this.ai.options.system || '',\n\t\t\t\ttemperature: options.temperature || this.ai.options.temperature || 0.7,\n\t\t\t\ttools: (options.tools || this.ai.options.tools || []).map(t => ({\n\t\t\t\t\tname: t.name,\n\t\t\t\t\tdescription: t.description,\n\t\t\t\t\tinput_schema: {\n\t\t\t\t\t\ttype: 'object',\n\t\t\t\t\t\tproperties: t.args ? objectMap(t.args, (key, value) => ({...value, required: undefined})) : {},\n\t\t\t\t\t\trequired: t.args ? Object.entries(t.args).filter(t => t[1].required).map(t => t[0]) : []\n\t\t\t\t\t},\n\t\t\t\t\tfn: undefined\n\t\t\t\t})),\n\t\t\t\tmessages: history,\n\t\t\t\tstream: !!options.stream,\n\t\t\t};\n\n\t\t\tlet resp: any;\n\t\t\tconst loopMessages: any[] = [];\n\t\t\tdo {\n\t\t\t\tresp = await this.client.messages.create(requestParams);\n\t\t\t\tif(options.stream) {\n\t\t\t\t\tif(loopMessages.length) options.stream({text: '\\n\\n'});\n\t\t\t\t\tresp.content = [];\n\t\t\t\t\tfor await (const chunk of resp) {\n\t\t\t\t\t\tif(controller.signal.aborted) break;\n\t\t\t\t\t\tif(chunk.type === 'content_block_start') {\n\t\t\t\t\t\t\tif(chunk.content_block.type === 'text') {\n\t\t\t\t\t\t\t\tresp.content.push({type: 'text', text: ''});\n\t\t\t\t\t\t\t} else if(chunk.content_block.type === 'tool_use') {\n\t\t\t\t\t\t\t\tresp.content.push({type: 'tool_use', id: chunk.content_block.id, name: chunk.content_block.name, input: <any>''});\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else if(chunk.type === 'content_block_delta') {\n\t\t\t\t\t\t\tif(chunk.delta.type === 'text_delta') {\n\t\t\t\t\t\t\t\tconst text = chunk.delta.text;\n\t\t\t\t\t\t\t\tresp.content.at(-1).text += text;\n\t\t\t\t\t\t\t\toptions.stream({text});\n\t\t\t\t\t\t\t} else if(chunk.delta.type === 'input_json_delta') {\n\t\t\t\t\t\t\t\tresp.content.at(-1).input += chunk.delta.partial_json;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else if(chunk.type === 'content_block_stop') {\n\t\t\t\t\t\t\tconst last = resp.content.at(-1);\n\t\t\t\t\t\t\tif(last.input != null) last.input = last.input ? JSONAttemptParse(last.input, {}) : {};\n\t\t\t\t\t\t} else if(chunk.type === 'message_stop') {\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tloopMessages.push({role: 'assistant', content: resp.content, timestamp: Date.now()});\n\t\t\t\tconst toolCalls = resp.content.filter((c: any) => c.type === 'tool_use');\n\t\t\t\tif(toolCalls.length && !controller.signal.aborted) {\n\t\t\t\t\thistory.push({role: 'assistant', content: resp.content});\n\t\t\t\t\tconst results = await Promise.all(toolCalls.map(async (toolCall: any) => {\n\t\t\t\t\t\tconst tool = options.tools?.find(findByProp('name', toolCall.name));\n\t\t\t\t\t\tif(!tool) return {tool_use_id: toolCall.id, is_error: true, content: 'Tool not found'};\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tconst result = await tool.fn(toolCall.input, this.ai);\n\t\t\t\t\t\t\treturn {type: 'tool_result', tool_use_id: toolCall.id, content: JSONSanitize(result)};\n\t\t\t\t\t\t} catch (err: any) {\n\t\t\t\t\t\t\treturn {type: 'tool_result', tool_use_id: toolCall.id, is_error: true, content: err?.message || err?.toString() || 'Unknown'};\n\t\t\t\t\t\t}\n\t\t\t\t\t}));\n\t\t\t\t\tconst userMsg = {role: 'user', content: results};\n\t\t\t\t\thistory.push(userMsg);\n\t\t\t\t\tloopMessages.push({...userMsg, timestamp: Date.now()});\n\t\t\t\t\trequestParams.messages = history;\n\t\t\t\t}\n\t\t\t} while (!controller.signal.aborted && resp.content.some((c: any) => c.type === 'tool_use'));\n\n\t\t\tconst combinedContent = loopMessages.filter(m => m.role === 'assistant')\n\t\t\t\t.map(m => m.content.filter((c: any) => c.type == 'text').map((c: any) => c.text).join('\\n\\n'))\n\t\t\t\t.filter(c => c).join('\\n\\n');\n\t\t\tif(options.stream) options.stream({done: true});\n\t\t\tres(this.toStandard([...history, {role: 'assistant', content: combinedContent, timestamp: Date.now()}]));\n\t\t});\n\n\t\treturn Object.assign(response, {abort: () => controller.abort()});\n\t}\n}\n","import {findByProp, objectMap, JSONSanitize, JSONAttemptParse} from '@ztimson/utils';\nimport {Ai} from './ai.ts';\nimport {LLMMessage, LLMRequest} from './llm.ts';\nimport {AbortablePromise, LLMProvider} from './provider.ts';\nimport {Ollama as ollama} from 'ollama';\n\nexport class Ollama extends LLMProvider {\n\tclient!: ollama;\n\n\tconstructor(public readonly ai: Ai, public host: string, public model: string) {\n\t\tsuper();\n\t\tthis.client = new ollama({host});\n\t}\n\n\tprivate toStandard(history: any[]): LLMMessage[] {\n\t\tfor(let i = 0; i < history.length; i++) {\n\t\t\tif(history[i].role == 'assistant' && history[i].tool_calls) {\n\t\t\t\tif(history[i].content) delete history[i].tool_calls;\n\t\t\t\telse {\n\t\t\t\t\thistory.splice(i, 1);\n\t\t\t\t\ti--;\n\t\t\t\t}\n\t\t\t} else if(history[i].role == 'tool') {\n\t\t\t\tconst error = history[i].content.startsWith('{\"error\":');\n\t\t\t\thistory[i] = {role: 'tool', name: history[i].tool_name, args: history[i].args, [error ? 'error' : 'content']: history[i].content, timestamp: history[i].timestamp};\n\t\t\t}\n\t\t\tif(!history[i]?.timestamp) history[i].timestamp = Date.now();\n\t\t}\n\t\treturn history;\n\t}\n\n\tprivate fromStandard(history: LLMMessage[]): any[] {\n\t\treturn history.map((h: any) => {\n\t\t\tconst {timestamp, ...rest} = h;\n\t\t\tif(h.role != 'tool') return rest;\n\t\t\treturn {role: 'tool', tool_name: h.name, content: h.error || h.content}\n\t\t});\n\t}\n\n\task(message: string, options: LLMRequest = {}): AbortablePromise<LLMMessage[]> {\n\t\tconst controller = new AbortController();\n\t\tconst response = new Promise<any>(async (res, rej) => {\n\t\t\tlet system = options.system || this.ai.options.system;\n\t\t\tlet history = this.fromStandard([...options.history || [], {role: 'user', content: message, timestamp: Date.now()}]);\n\t\t\tif(history[0].roll == 'system') {\n\t\t\t\tif(!system) system = history.shift();\n\t\t\t\telse history.shift();\n\t\t\t}\n\t\t\tif(options.compress) history = await this.ai.llm.compress(<any>history, options.compress.max, options.compress.min);\n\t\t\tif(options.system) history.unshift({role: 'system', content: system})\n\n\t\t\tconst requestParams: any = {\n\t\t\t\tmodel: options.model || this.model,\n\t\t\t\tmessages: history,\n\t\t\t\tstream: !!options.stream,\n\t\t\t\tsignal: controller.signal,\n\t\t\t\toptions: {\n\t\t\t\t\ttemperature: options.temperature || this.ai.options.temperature || 0.7,\n\t\t\t\t\tnum_predict: options.max_tokens || this.ai.options.max_tokens || 4096,\n\t\t\t\t},\n\t\t\t\ttools: (options.tools || this.ai.options.tools || []).map(t => ({\n\t\t\t\t\ttype: 'function',\n\t\t\t\t\tfunction: {\n\t\t\t\t\t\tname: t.name,\n\t\t\t\t\t\tdescription: t.description,\n\t\t\t\t\t\tparameters: {\n\t\t\t\t\t\t\ttype: 'object',\n\t\t\t\t\t\t\tproperties: t.args ? objectMap(t.args, (key, value) => ({...value, required: undefined})) : {},\n\t\t\t\t\t\t\trequired: t.args ? Object.entries(t.args).filter(t => t[1].required).map(t => t[0]) : []\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}))\n\t\t\t}\n\n\t\t\tlet resp: any;\n\t\t\tconst loopMessages: any[] = [];\n\t\t\tdo {\n\t\t\t\tresp = await this.client.chat(requestParams);\n\t\t\t\tif(options.stream) {\n\t\t\t\t\tif(loopMessages.length) options.stream({text: '\\n\\n'});\n\t\t\t\t\tresp.message = {role: 'assistant', content: '', tool_calls: []};\n\t\t\t\t\tfor await (const chunk of resp) {\n\t\t\t\t\t\tif(controller.signal.aborted) break;\n\t\t\t\t\t\tif(chunk.message?.content) {\n\t\t\t\t\t\t\tresp.message.content += chunk.message.content;\n\t\t\t\t\t\t\toptions.stream({text: chunk.message.content});\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif(chunk.message?.tool_calls) resp.message.tool_calls = chunk.message.tool_calls;\n\t\t\t\t\t\tif(chunk.done) break;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tloopMessages.push({role: 'assistant', content: resp.message?.content, timestamp: Date.now()});\n\t\t\t\tif(resp.message?.tool_calls?.length && !controller.signal.aborted) {\n\t\t\t\t\thistory.push(resp.message);\n\t\t\t\t\tconst results = await Promise.all(resp.message.tool_calls.map(async (toolCall: any) => {\n\t\t\t\t\t\tconst tool = (options.tools || this.ai.options.tools)?.find(findByProp('name', toolCall.function.name));\n\t\t\t\t\t\tif(!tool) return {role: 'tool', tool_name: toolCall.function.name, content: '{\"error\": \"Tool not found\"}'};\n\t\t\t\t\t\tconst args = typeof toolCall.function.arguments === 'string' ? JSONAttemptParse(toolCall.function.arguments, {}) : toolCall.function.arguments;\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tconst result = await tool.fn(args, this.ai);\n\t\t\t\t\t\t\treturn {role: 'tool', tool_name: toolCall.function.name, args, content: JSONSanitize(result)};\n\t\t\t\t\t\t} catch (err: any) {\n\t\t\t\t\t\t\treturn {role: 'tool', tool_name: toolCall.function.name, args, content: JSONSanitize({error: err?.message || err?.toString() || 'Unknown'})};\n\t\t\t\t\t\t}\n\t\t\t\t\t}));\n\t\t\t\t\thistory.push(...results);\n\t\t\t\t\tloopMessages.push(...results.map(r => ({...r, timestamp: Date.now()})));\n\t\t\t\t\trequestParams.messages = history;\n\t\t\t\t}\n\t\t\t} while (!controller.signal.aborted && resp.message?.tool_calls?.length);\n\n\t\t\tconst combinedContent = loopMessages.filter(m => m.role === 'assistant')\n\t\t\t\t.map(m => m.content).filter(c => c).join('\\n\\n');\n\t\t\tif(options.stream) options.stream({done: true});\n\t\t\tres(this.toStandard([...history, {role: 'assistant', content: combinedContent, timestamp: Date.now()}]));\n\t\t});\n\n\t\treturn Object.assign(response, {abort: () => controller.abort()});\n\t}\n}\n","import {OpenAI as openAI} from 'openai';\nimport {findByProp, objectMap, JSONSanitize, JSONAttemptParse} from '@ztimson/utils';\nimport {Ai} from './ai.ts';\nimport {LLMMessage, LLMRequest} from './llm.ts';\nimport {AbortablePromise, LLMProvider} from './provider.ts';\n\nexport class OpenAi extends LLMProvider {\n\tclient!: openAI;\n\n\tconstructor(public readonly ai: Ai, public readonly apiToken: string, public model: string) {\n\t\tsuper();\n\t\tthis.client = new openAI({apiKey: apiToken});\n\t}\n\n\tprivate toStandard(history: any[]): LLMMessage[] {\n\t\tfor(let i = 0; i < history.length; i++) {\n\t\t\tconst h = history[i];\n\t\t\tif(h.role === 'assistant' && h.tool_calls) {\n\t\t\t\tconst tools = h.tool_calls.map((tc: any) => ({\n\t\t\t\t\trole: 'tool',\n\t\t\t\t\tid: tc.id,\n\t\t\t\t\tname: tc.function.name,\n\t\t\t\t\targs: JSONAttemptParse(tc.function.arguments, {}),\n\t\t\t\t\ttimestamp: h.timestamp\n\t\t\t\t}));\n\t\t\t\thistory.splice(i, 1, ...tools);\n\t\t\t\ti += tools.length - 1;\n\t\t\t} else if(h.role === 'tool' && h.content) {\n\t\t\t\tconst record = history.find(h2 => h.tool_call_id == h2.id);\n\t\t\t\tif(record) {\n\t\t\t\t\tif(h.content.includes('\"error\":')) record.error = h.content;\n\t\t\t\t\telse record.content = h.content;\n\t\t\t\t}\n\t\t\t\thistory.splice(i, 1);\n\t\t\t\ti--;\n\t\t\t}\n\t\t\tif(!history[i]?.timestamp) history[i].timestamp = Date.now();\n\t\t}\n\t\treturn history;\n\t}\n\n\tprivate fromStandard(history: LLMMessage[]): any[] {\n\t\treturn history.reduce((result, h) => {\n\t\t\tif(h.role === 'tool') {\n\t\t\t\tresult.push({\n\t\t\t\t\trole: 'assistant',\n\t\t\t\t\tcontent: null,\n\t\t\t\t\ttool_calls: [{ id: h.id, type: 'function', function: { name: h.name, arguments: JSON.stringify(h.args) } }],\n\t\t\t\t\trefusal: null,\n\t\t\t\t\tannotations: []\n\t\t\t\t}, {\n\t\t\t\t\trole: 'tool',\n\t\t\t\t\ttool_call_id: h.id,\n\t\t\t\t\tcontent: h.error || h.content\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\tconst {timestamp, ...rest} = h;\n\t\t\t\tresult.push(rest);\n\t\t\t}\n\t\t\treturn result;\n\t\t}, [] as any[]);\n\t}\n\n\task(message: string, options: LLMRequest = {}): AbortablePromise<LLMMessage[]> {\n\t\tconst controller = new AbortController();\n\t\tconst response = new Promise<any>(async (res, rej) => {\n\t\t\tlet history = this.fromStandard([...options.history || [], {role: 'user', content: message, timestamp: Date.now()}]);\n\t\t\tif(options.compress) history = await this.ai.llm.compress(<any>history, options.compress.max, options.compress.min, options);\n\n\t\t\tconst requestParams: any = {\n\t\t\t\tmodel: options.model || this.model,\n\t\t\t\tmessages: history,\n\t\t\t\tstream: !!options.stream,\n\t\t\t\tmax_tokens: options.max_tokens || this.ai.options.max_tokens || 4096,\n\t\t\t\ttemperature: options.temperature || this.ai.options.temperature || 0.7,\n\t\t\t\ttools: (options.tools || this.ai.options.tools || []).map(t => ({\n\t\t\t\t\ttype: 'function',\n\t\t\t\t\tfunction: {\n\t\t\t\t\t\tname: t.name,\n\t\t\t\t\t\tdescription: t.description,\n\t\t\t\t\t\tparameters: {\n\t\t\t\t\t\t\ttype: 'object',\n\t\t\t\t\t\t\tproperties: t.args ? objectMap(t.args, (key, value) => ({...value, required: undefined})) : {},\n\t\t\t\t\t\t\trequired: t.args ? Object.entries(t.args).filter(t => t[1].required).map(t => t[0]) : []\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}))\n\t\t\t};\n\n\t\t\tlet resp: any;\n\t\t\tconst loopMessages: any[] = [];\n\t\t\tdo {\n\t\t\t\tresp = await this.client.chat.completions.create(requestParams);\n\t\t\t\tif(options.stream) {\n\t\t\t\t\tif(loopMessages.length) options.stream({text: '\\n\\n'});\n\t\t\t\t\tresp.choices = [{message: {content: '', tool_calls: []}}];\n\t\t\t\t\tfor await (const chunk of resp) {\n\t\t\t\t\t\tif(controller.signal.aborted) break;\n\t\t\t\t\t\tif(chunk.choices[0].delta.content) {\n\t\t\t\t\t\t\tresp.choices[0].message.content += chunk.choices[0].delta.content;\n\t\t\t\t\t\t\toptions.stream({text: chunk.choices[0].delta.content});\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif(chunk.choices[0].delta.tool_calls) {\n\t\t\t\t\t\t\tresp.choices[0].message.tool_calls = chunk.choices[0].delta.tool_calls;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tloopMessages.push({role: 'assistant', content: resp.choices[0].message.content || '', timestamp: Date.now()});\n\n\t\t\t\tconst toolCalls = resp.choices[0].message.tool_calls || [];\n\t\t\t\tif(toolCalls.length && !controller.signal.aborted) {\n\t\t\t\t\thistory.push(resp.choices[0].message);\n\t\t\t\t\tconst results = await Promise.all(toolCalls.map(async (toolCall: any) => {\n\t\t\t\t\t\tconst tool = options.tools?.find(findByProp('name', toolCall.function.name));\n\t\t\t\t\t\tif(!tool) return {role: 'tool', tool_call_id: toolCall.id, content: '{\"error\": \"Tool not found\"}'};\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tconst args = JSONAttemptParse(toolCall.function.arguments, {});\n\t\t\t\t\t\t\tconst result = await tool.fn(args, this.ai);\n\t\t\t\t\t\t\treturn {role: 'tool', tool_call_id: toolCall.id, content: JSONSanitize(result)};\n\t\t\t\t\t\t} catch (err: any) {\n\t\t\t\t\t\t\treturn {role: 'tool', tool_call_id: toolCall.id, content: JSONSanitize({error: err?.message || err?.toString() || 'Unknown'})};\n\t\t\t\t\t\t}\n\t\t\t\t\t}));\n\t\t\t\t\thistory.push(...results);\n\t\t\t\t\tloopMessages.push(...results.map(r => ({...r, timestamp: Date.now()})));\n\t\t\t\t\trequestParams.messages = history;\n\t\t\t\t}\n\t\t\t} while (!controller.signal.aborted && resp.choices?.[0]?.message?.tool_calls?.length);\n\n\t\t\tconst combinedContent = loopMessages.filter(m => m.role === 'assistant')\n\t\t\t\t.map(m => m.content).filter(c => c).join('\\n\\n');\n\t\t\tif(options.stream) options.stream({done: true});\n\t\t\tres(this.toStandard([...history, {role: 'assistant', content: combinedContent, timestamp: Date.now()}]));\n\t\t});\n\t\treturn Object.assign(response, {abort: () => controller.abort()});\n\t}\n}\n","import {JSONAttemptParse} from '@ztimson/utils';\nimport {Ai} from './ai.ts';\nimport {Anthropic} from './antrhopic.ts';\nimport {Ollama} from './ollama.ts';\nimport {OpenAi} from './open-ai.ts';\nimport {AbortablePromise, LLMProvider} from './provider.ts';\nimport {AiTool} from './tools.ts';\n\nexport type LLMMessage = {\n\t/** Message originator */\n\trole: 'assistant' | 'system' | 'user';\n\t/** Message content */\n\tcontent: string | any;\n\t/** Timestamp */\n\ttimestamp?: number;\n} | {\n\t/** Tool call */\n\trole: 'tool';\n\t/** Unique ID for call */\n\tid: string;\n\t/** Tool that was run */\n\tname: string;\n\t/** Tool arguments */\n\targs: any;\n\t/** Tool result */\n\tcontent: undefined | string;\n\t/** Tool error */\n\terror: undefined | string;\n\t/** Timestamp */\n\ttimestamp?: number;\n}\n\nexport type LLMOptions = {\n\t/** Anthropic settings */\n\tanthropic?: {\n\t\t/** API Token */\n\t\ttoken: string;\n\t\t/** Default model */\n\t\tmodel: string;\n\t},\n\t/** Ollama settings */\n\tollama?: {\n\t\t/** connection URL */\n\t\thost: string;\n\t\t/** Default model */\n\t\tmodel: string;\n\t},\n\t/** Open AI settings */\n\topenAi?: {\n\t\t/** API Token */\n\t\ttoken: string;\n\t\t/** Default model */\n\t\tmodel: string;\n\t},\n\t/** Default provider & model */\n\tmodel: string | [string, string];\n} & Omit<LLMRequest, 'model'>;\n\nexport type LLMRequest = {\n\t/** System prompt */\n\tsystem?: string;\n\t/** Message history */\n\thistory?: LLMMessage[];\n\t/** Max tokens for request */\n\tmax_tokens?: number;\n\t/** 0 = Rigid Logic, 1 = Balanced, 2 = Hyper Creative **/\n\ttemperature?: number;\n\t/** Available tools */\n\ttools?: AiTool[];\n\t/** LLM model */\n\tmodel?: string | [string, string];\n\t/** Stream response */\n\tstream?: (chunk: {text?: string, done?: true}) => any;\n\t/** Compress old messages in the chat to free up context */\n\tcompress?: {\n\t\t/** Trigger chat compression once context exceeds the token count */\n\t\tmax: number;\n\t\t/** Compress chat until context size smaller than */\n\t\tmin: number\n\t}\n}\n\nexport class LLM {\n\tprivate providers: {[key: string]: LLMProvider} = {};\n\n\tconstructor(public readonly ai: Ai, public readonly options: LLMOptions) {\n\t\tif(options.anthropic?.token) this.providers.anthropic = new Anthropic(this.ai, options.anthropic.token, options.anthropic.model);\n\t\tif(options.ollama?.host) this.providers.ollama = new Ollama(this.ai, options.ollama.host, options.ollama.model);\n\t\tif(options.openAi?.token) this.providers.openAi = new OpenAi(this.ai, options.openAi.token, options.openAi.model);\n\t}\n\n\t/**\n\t * Chat with LLM\n\t * @param {string} message Question\n\t * @param {LLMRequest} options Configuration options and chat history\n\t * @returns {{abort: () => void, response: Promise<LLMMessage[]>}} Function to abort response and chat history\n\t */\n\task(message: string, options: LLMRequest = {}): AbortablePromise<LLMMessage[]> {\n\t\tlet model: any = [null, null];\n\t\tif(options.model) {\n\t\t\tif(typeof options.model == 'object') model = options.model;\n\t\t\telse model = [options.model, (<any>this.options)[options.model]?.model];\n\t\t}\n\t\tif(!options.model || model[1] == null) {\n\t\t\tif(typeof this.options.model == 'object') model = this.options.model;\n\t\t\telse model = [this.options.model, (<any>this.options)[this.options.model]?.model];\n\t\t}\n\t\tif(!model[0] || !model[1]) throw new Error(`Unknown LLM provider or model: ${model[0]} / ${model[1]}`);\n\t\treturn this.providers[model[0]].ask(message, {...options, model: model[1]});\n\t}\n\n\t/**\n\t * Compress chat history to reduce context size\n\t * @param {LLMMessage[]} history Chatlog that will be compressed\n\t * @param max Trigger compression once context is larger than max\n\t * @param min Summarize until context size is less than min\n\t * @param {LLMRequest} options LLM options\n\t * @returns {Promise<LLMMessage[]>} New chat history will summary at index 0\n\t */\n\tasync compress(history: LLMMessage[], max: number, min: number, options?: LLMRequest): Promise<LLMMessage[]> {\n\t\tif(this.estimateTokens(history) < max) return history;\n\t\tlet keep = 0, tokens = 0;\n\t\tfor(let m of history.toReversed()) {\n\t\t\ttokens += this.estimateTokens(m.content);\n\t\t\tif(tokens < min) keep++;\n\t\t\telse break;\n\t\t}\n\t\tif(history.length <= keep) return history;\n\t\tconst recent = keep == 0 ? [] : history.slice(-keep),\n\t\t\tprocess = (keep == 0 ? history : history.slice(0, -keep)).filter(h => h.role === 'assistant' || h.role === 'user');\n\t\tconst summary = await this.summarize(process.map(m => `${m.role}: ${m.content}`).join('\\n\\n'), 250, options);\n\t\treturn [{role: 'assistant', content: `Conversation Summary: ${summary}`, timestamp: Date.now()}, ...recent];\n\t}\n\n\t/**\n\t * Estimate variable as tokens\n\t * @param history Object to size\n\t * @returns {number} Rough token count\n\t */\n\testimateTokens(history: any): number {\n\t\tconst text = JSON.stringify(history);\n\t\treturn Math.ceil((text.length / 4) * 1.2);\n\t}\n\n\t/**\n\t * Ask a question with JSON response\n\t * @param {string} message Question\n\t * @param {LLMRequest} options Configuration options and chat history\n\t * @returns {Promise<{} | {} | RegExpExecArray | null>}\n\t */\n\tasync json(message: string, options?: LLMRequest) {\n\t\tlet resp = await this.ask(message, {\n\t\t\tsystem: 'Respond using a JSON blob',\n\t\t\t...options\n\t\t});\n\t\tif(!resp?.[0]?.content) return {};\n\t\treturn JSONAttemptParse(new RegExp('\\{[\\s\\S]*\\}').exec(resp[0].content), {});\n\t}\n\n\t/**\n\t * Create a summary of some text\n\t * @param {string} text Text to summarize\n\t * @param {number} tokens Max number of tokens\n\t * @param options LLM request options\n\t * @returns {Promise<string>} Summary\n\t */\n\tsummarize(text: string, tokens: number, options?: LLMRequest): Promise<string | null> {\n\t\treturn this.ask(text, {system: `Generate a brief summary <= ${tokens} tokens. Output nothing else`, temperature: 0.3, ...options})\n\t\t\t.then(history => <string>history.pop()?.content || null);\n\t}\n}\n","import {createWorker} from 'tesseract.js';\nimport {LLM, LLMOptions} from './llm';\nimport fs from 'node:fs/promises';\nimport Path from 'node:path';\nimport * as tf from '@tensorflow/tfjs';\nimport {spawn} from 'node:child_process';\n\nexport type AiOptions = LLMOptions & {\n\twhisper?: {\n\t\t/** Whisper binary location */\n\t\tbinary: string;\n\t\t/** Model: `ggml-base.en.bin` */\n\t\tmodel: string;\n\t\t/** Path to models */\n\t\tpath: string;\n\t}\n}\n\nexport class Ai {\n\tprivate downloads: {[key: string]: Promise<string>} = {};\n\tprivate whisperModel!: string;\n\n\t/** Large Language Models */\n\tllm!: LLM;\n\n\tconstructor(public readonly options: AiOptions) {\n\t\tthis.llm = new LLM(this, options);\n\t\tif(this.options.whisper?.binary) {\n\t\t\tthis.whisperModel = this.options.whisper?.model.endsWith('.bin') ? this.options.whisper?.model : this.options.whisper?.model + '.bin';\n\t\t\tthis.downloadAsrModel();\n\t\t}\n\t}\n\n\t/**\n\t * Convert audio to text using Auditory Speech Recognition\n\t * @param {string} path Path to audio\n\t * @param model Whisper model\n\t * @returns {Promise<any>} Extracted text\n\t */\n\tasr(path: string, model: string = this.whisperModel): {abort: () => void, response: Promise<string | null>} {\n\t\tif(!this.options.whisper?.binary) throw new Error('Whisper not configured');\n\t\tlet abort: any = () => {};\n\t\tconst response = new Promise<string | null>((resolve, reject) => {\n\t\t\tthis.downloadAsrModel(model).then(m => {\n\t\t\t\tlet output = '';\n\t\t\t\tconst proc = spawn(<string>this.options.whisper?.binary, ['-nt', '-np', '-m', m, '-f', path], {stdio: ['ignore', 'pipe', 'ignore']});\n\t\t\t\tabort = () => proc.kill('SIGTERM');\n\t\t\t\tproc.on('error', (err: Error) => reject(err));\n\t\t\t\tproc.stdout.on('data', (data: Buffer) => output += data.toString());\n\t\t\t\tproc.on('close', (code: number) => {\n\t\t\t\t\tif(code === 0) resolve(output.trim() || null);\n\t\t\t\t\telse reject(new Error(`Exit code ${code}`));\n\t\t\t\t});\n\t\t\t});\n\t\t});\n\t\treturn {response, abort};\n\t}\n\n\t/**\n\t * Downloads the specified Whisper model if it is not already present locally.\n\t *\n\t * @param {string} model Whisper model that will be downloaded\n\t * @return {Promise<string>} Absolute path to model file, resolves once downloaded\n\t */\n\tasync downloadAsrModel(model: string = this.whisperModel): Promise<string> {\n\t\tif(!this.options.whisper?.binary) throw new Error('Whisper not configured');\n\t\tif(!model.endsWith('.bin')) model += '.bin';\n\t\tconst p = Path.join(this.options.whisper.path, model);\n\t\tif(await fs.stat(p).then(() => true).catch(() => false)) return p;\n\t\tif(!!this.downloads[model]) return this.downloads[model];\n\t\tthis.downloads[model] = fetch(`https://huggingface.co/ggerganov/whisper.cpp/resolve/main/${model}`)\n\t\t\t.then(resp => resp.arrayBuffer())\n\t\t\t.then(arr => Buffer.from(arr)).then(async buffer => {\n\t\t\t\tawait fs.writeFile(p, buffer);\n\t\t\t\tdelete this.downloads[model];\n\t\t\t\treturn p;\n\t\t\t});\n\t\treturn this.downloads[model];\n\t}\n\n\t/**\n\t * Convert image to text using Optical Character Recognition\n\t * @param {string} path Path to image\n\t * @returns {{abort: Function, response: Promise<string | null>}} Abort function & Promise of extracted text\n\t */\n\tocr(path: string): {abort: () => void, response: Promise<string | null>} {\n\t\tlet worker: any;\n\t\treturn {\n\t\t\tabort: () => { worker?.terminate(); },\n\t\t\tresponse: new Promise(async res => {\n\t\t\t\tworker = await createWorker('eng');\n\t\t\t\tconst {data} = await worker.recognize(path);\n\t\t\t\tawait worker.terminate();\n\t\t\t\tres(data.text.trim() || null);\n\t\t\t})\n\t\t}\n\t}\n\n\t/**\n\t * Compare the difference between two strings using tensor math\n\t * @param target Text that will checked\n\t * @param {string} searchTerms Multiple search terms to check against target\n\t * @returns {{avg: number, max: number, similarities: number[]}} Similarity values 0-1: 0 = unique, 1 = identical\n\t */\n\tsemanticSimilarity(target: string, ...searchTerms: string[]) {\n\t\tif(searchTerms.length < 2) throw new Error('Requires at least 2 strings to compare');\n\n\t\tconst vector = (text: string, dimensions: number = 10): number[] => {\n\t\t\treturn text.toLowerCase().split('').map((char, index) =>\n\t\t\t\t(char.charCodeAt(0) * (index + 1)) % dimensions / dimensions).slice(0, dimensions);\n\t\t}\n\n\t\tconst cosineSimilarity = (v1: number[], v2: number[]): number => {\n\t\t\tif (v1.length !== v2.length) throw new Error('Vectors must be same length');\n\t\t\tconst tensor1 = tf.tensor1d(v1), tensor2 = tf.tensor1d(v2)\n\t\t\tconst dotProduct = tf.dot(tensor1, tensor2)\n\t\t\tconst magnitude1 = tf.norm(tensor1)\n\t\t\tconst magnitude2 = tf.norm(tensor2)\n\t\t\tif(magnitude1.dataSync()[0] === 0 || magnitude2.dataSync()[0] === 0) return 0\n\t\t\treturn dotProduct.dataSync()[0] / (magnitude1.dataSync()[0] * magnitude2.dataSync()[0])\n\t\t}\n\n\t\tconst v = vector(target);\n\t\tconst similarities = searchTerms.map(t => vector(t)).map(refVector => cosineSimilarity(v, refVector))\n\t\treturn {avg: similarities.reduce((acc, s) => acc + s, 0) / similarities.length, max: Math.max(...similarities), similarities}\n\t}\n}\n","import {$, $Sync} from '@ztimson/node-utils';\nimport {ASet, consoleInterceptor, Http, fn as Fn} from '@ztimson/utils';\nimport {Ai} from './ai.ts';\n\nexport type AiToolArg = {[key: string]: {\n\t/** Argument type */\n\ttype: 'array' | 'boolean' | 'number' | 'object' | 'string',\n\t/** Argument description */\n\tdescription: string,\n\t/** Required argument */\n\trequired?: boolean;\n\t/** Default value */\n\tdefault?: any,\n\t/** Options */\n\tenum?: string[],\n\t/** Minimum value or length */\n\tmin?: number,\n\t/** Maximum value or length */\n\tmax?: number,\n\t/** Match pattern */\n\tpattern?: string,\n\t/** Child arguments */\n\titems?: {[key: string]: AiToolArg}\n}}\n\nexport type AiTool = {\n\t/** Tool ID / Name - Must be snail_case */\n\tname: string,\n\t/** Tool description / prompt */\n\tdescription: string,\n\t/** Tool arguments */\n\targs?: AiToolArg,\n\t/** Callback function */\n\tfn: (args: any, ai: Ai) => any | Promise<any>,\n};\n\nexport const CliTool: AiTool = {\n\tname: 'cli',\n\tdescription: 'Use the command line interface, returns any output',\n\targs: {command: {type: 'string', description: 'Command to run', required: true}},\n\tfn: (args: {command: string}) => $`${args.command}`\n}\n\nexport const DateTimeTool: AiTool = {\n\tname: 'get_datetime',\n\tdescription: 'Get current date and time',\n\targs: {},\n\tfn: async () => new Date().toISOString()\n}\n\nexport const ExecTool: AiTool = {\n\tname: 'exec',\n\tdescription: 'Run code/scripts',\n\targs: {\n\t\tlanguage: {type: 'string', description: 'Execution language', enum: ['cli', 'node', 'python'], required: true},\n\t\tcode: {type: 'string', description: 'Code to execute', required: true}\n\t},\n\tfn: async (args, ai) => {\n\t\ttry {\n\t\t\tswitch(args.type) {\n\t\t\t\tcase 'bash':\n\t\t\t\t\treturn await CliTool.fn({command: args.code}, ai);\n\t\t\t\tcase 'node':\n\t\t\t\t\treturn await JSTool.fn({code: args.code}, ai);\n\t\t\t\tcase 'python': {\n\t\t\t\t\treturn await PythonTool.fn({code: args.code}, ai);\n\t\t\t\t}\n\t\t\t}\n\t\t} catch(err: any) {\n\t\t\treturn {error: err?.message || err.toString()};\n\t\t}\n\t}\n}\n\nexport const FetchTool: AiTool = {\n\tname: 'fetch',\n\tdescription: 'Make HTTP request to URL',\n\targs: {\n\t\turl: {type: 'string', description: 'URL to fetch', required: true},\n\t\tmethod: {type: 'string', description: 'HTTP method to use', enum: ['GET', 'POST', 'PUT', 'DELETE'], default: 'GET'},\n\t\theaders: {type: 'object', description: 'HTTP headers to send', default: {}},\n\t\tbody: {type: 'object', description: 'HTTP body to send'},\n\t},\n\tfn: (args: {\n\t\turl: string;\n\t\tmethod: 'GET' | 'POST' | 'PUT' | 'DELETE';\n\t\theaders: {[key: string]: string};\n\t\tbody: any;\n\t}) => new Http({url: args.url, headers: args.headers}).request({method: args.method || 'GET', body: args.body})\n}\n\nexport const JSTool: AiTool = {\n\tname: 'exec_javascript',\n\tdescription: 'Execute commonjs javascript',\n\targs: {\n\t\tcode: {type: 'string', description: 'CommonJS javascript', required: true}\n\t},\n\tfn: async (args: {code: string}) => {\n\t\tconst console = consoleInterceptor(null);\n\t\tconst resp = await Fn<any>({console}, args.code, true).catch((err: any) => console.output.error.push(err));\n\t\treturn {...console.output, return: resp, stdout: undefined, stderr: undefined};\n\t}\n}\n\nexport const PythonTool: AiTool = {\n\tname: 'exec_javascript',\n\tdescription: 'Execute commonjs javascript',\n\targs: {\n\t\tcode: {type: 'string', description: 'CommonJS javascript', required: true}\n\t},\n\tfn: async (args: {code: string}) => ({result: $Sync`python -c \"${args.code}\"`})\n}\n\nexport const SearchTool: AiTool = {\n\tname: 'search',\n\tdescription: 'Use a search engine to find relevant URLs, should be changed with fetch to scrape sources',\n\targs: {\n\t\tquery: {type: 'string', description: 'Search string', required: true},\n\t\tlength: {type: 'string', description: 'Number of results to return', default: 5},\n\t},\n\tfn: async (args: {\n\t\tquery: string;\n\t\tlength: number;\n\t}) => {\n\t\tconst html = await fetch(`https://html.duckduckgo.com/html/?q=${encodeURIComponent(args.query)}`, {\n\t\t\theaders: {\"User-Agent\": \"Mozilla/5.0 (Windows NT 10.0; Win64; x64)\", \"Accept-Language\": \"en-US,en;q=0.9\"}\n\t\t}).then(resp => resp.text());\n\t\tlet match, regex = /<a .*?href=\"(.+?)\".+?<\\/a>/g;\n\t\tconst results = new ASet<string>();\n\t\twhile((match = regex.exec(html)) !== null) {\n\t\t\tlet url = /uddg=(.+)&amp?/.exec(decodeURIComponent(match[1]))?.[1];\n\t\t\tif(url) url = decodeURIComponent(url);\n\t\t\tif(url) results.add(url);\n\t\t\tif(results.size >= (args.length || 5)) break;\n\t\t}\n\t\treturn results;\n\t}\n}\n"],"names":["LLMProvider","Anthropic","ai","apiToken","model","anthropic","history","i","orgI","c","h","timestamp","message","options","controller","response","res","rej","requestParams","t","objectMap","key","value","resp","loopMessages","chunk","text","last","JSONAttemptParse","toolCalls","userMsg","toolCall","tool","findByProp","result","JSONSanitize","err","combinedContent","m","Ollama","host","ollama","error","rest","system","results","args","r","OpenAi","openAI","tools","tc","record","h2","LLM","max","min","keep","tokens","recent","process","Ai","path","abort","resolve","reject","output","proc","spawn","data","code","p","Path","fs","arr","buffer","worker","createWorker","target","searchTerms","vector","dimensions","char","index","cosineSimilarity","v1","v2","tensor1","tf","tensor2","dotProduct","magnitude1","magnitude2","v","similarities","refVector","acc","s","CliTool","DateTimeTool","ExecTool","JSTool","PythonTool","FetchTool","Http","console","consoleInterceptor","Fn","$Sync","SearchTool","html","match","regex","ASet","url"],"mappings":"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"}
1
+ {"version":3,"file":"index.mjs","sources":["../src/provider.ts","../src/antrhopic.ts","../src/ollama.ts","../src/open-ai.ts","../src/llm.ts","../src/ai.ts","../src/tools.ts"],"sourcesContent":["import {LLMMessage, LLMOptions, LLMRequest} from './llm.ts';\n\nexport type AbortablePromise<T> = Promise<T> & {abort: () => void};\n\nexport abstract class LLMProvider {\n\tabstract ask(message: string, options: LLMRequest): AbortablePromise<LLMMessage[]>;\n}\n","import {Anthropic as anthropic} from '@anthropic-ai/sdk';\nimport {findByProp, objectMap, JSONSanitize, JSONAttemptParse} from '@ztimson/utils';\nimport {Ai} from './ai.ts';\nimport {LLMMessage, LLMRequest} from './llm.ts';\nimport {AbortablePromise, LLMProvider} from './provider.ts';\n\nexport class Anthropic extends LLMProvider {\n\tclient!: anthropic;\n\n\tconstructor(public readonly ai: Ai, public readonly apiToken: string, public model: string) {\n\t\tsuper();\n\t\tthis.client = new anthropic({apiKey: apiToken});\n\t}\n\n\tprivate toStandard(history: any[]): LLMMessage[] {\n\t\tfor(let i = 0; i < history.length; i++) {\n\t\t\tconst orgI = i;\n\t\t\tif(typeof history[orgI].content != 'string') {\n\t\t\t\tif(history[orgI].role == 'assistant') {\n\t\t\t\t\thistory[orgI].content.filter((c: any) => c.type =='tool_use').forEach((c: any) => {\n\t\t\t\t\t\ti++;\n\t\t\t\t\t\thistory.splice(i, 0, {role: 'tool', id: c.id, name: c.name, args: c.input, timestamp: Date.now()});\n\t\t\t\t\t});\n\t\t\t\t} else if(history[orgI].role == 'user') {\n\t\t\t\t\thistory[orgI].content.filter((c: any) => c.type =='tool_result').forEach((c: any) => {\n\t\t\t\t\t\tconst h = history.find((h: any) => h.id == c.tool_use_id);\n\t\t\t\t\t\th[c.is_error ? 'error' : 'content'] = c.content;\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\thistory[orgI].content = history[orgI].content.filter((c: any) => c.type == 'text').map((c: any) => c.text).join('\\n\\n');\n\t\t\t}\n\t\t\tif(!history[orgI].timestamp) history[orgI].timestamp = Date.now();\n\t\t}\n\t\treturn history.filter(h => !!h.content);\n\t}\n\n\tprivate fromStandard(history: LLMMessage[]): any[] {\n\t\tfor(let i = 0; i < history.length; i++) {\n\t\t\tif(history[i].role == 'tool') {\n\t\t\t\tconst h: any = history[i];\n\t\t\t\thistory.splice(i, 1,\n\t\t\t\t\t{role: 'assistant', content: [{type: 'tool_use', id: h.id, name: h.name, input: h.args}]},\n\t\t\t\t\t{role: 'user', content: [{type: 'tool_result', tool_use_id: h.id, is_error: !!h.error, content: h.error || h.content}]}\n\t\t\t\t)\n\t\t\t\ti++;\n\t\t\t}\n\t\t}\n\t\treturn history.map(({timestamp, ...h}) => h);\n\t}\n\n\task(message: string, options: LLMRequest = {}): AbortablePromise<LLMMessage[]> {\n\t\tconst controller = new AbortController();\n\t\tconst response = new Promise<any>(async (res, rej) => {\n\t\t\tlet history = this.fromStandard([...options.history || [], {role: 'user', content: message, timestamp: Date.now()}]);\n\t\t\tif(options.compress) history = await this.ai.llm.compress(<any>history, options.compress.max, options.compress.min, options);\n\t\t\tconst requestParams: any = {\n\t\t\t\tmodel: options.model || this.model,\n\t\t\t\tmax_tokens: options.max_tokens || this.ai.options.max_tokens || 4096,\n\t\t\t\tsystem: options.system || this.ai.options.system || '',\n\t\t\t\ttemperature: options.temperature || this.ai.options.temperature || 0.7,\n\t\t\t\ttools: (options.tools || this.ai.options.tools || []).map(t => ({\n\t\t\t\t\tname: t.name,\n\t\t\t\t\tdescription: t.description,\n\t\t\t\t\tinput_schema: {\n\t\t\t\t\t\ttype: 'object',\n\t\t\t\t\t\tproperties: t.args ? objectMap(t.args, (key, value) => ({...value, required: undefined})) : {},\n\t\t\t\t\t\trequired: t.args ? Object.entries(t.args).filter(t => t[1].required).map(t => t[0]) : []\n\t\t\t\t\t},\n\t\t\t\t\tfn: undefined\n\t\t\t\t})),\n\t\t\t\tmessages: history,\n\t\t\t\tstream: !!options.stream,\n\t\t\t};\n\n\t\t\tlet resp: any;\n\t\t\tconst assistantMessages: string[] = [];\n\t\t\tdo {\n\t\t\t\tresp = await this.client.messages.create(requestParams);\n\t\t\t\tif(options.stream) {\n\t\t\t\t\tif(assistantMessages.length) options.stream({text: '\\n\\n'});\n\t\t\t\t\tresp.content = [];\n\t\t\t\t\tfor await (const chunk of resp) {\n\t\t\t\t\t\tif(controller.signal.aborted) break;\n\t\t\t\t\t\tif(chunk.type === 'content_block_start') {\n\t\t\t\t\t\t\tif(chunk.content_block.type === 'text') {\n\t\t\t\t\t\t\t\tresp.content.push({type: 'text', text: ''});\n\t\t\t\t\t\t\t} else if(chunk.content_block.type === 'tool_use') {\n\t\t\t\t\t\t\t\tresp.content.push({type: 'tool_use', id: chunk.content_block.id, name: chunk.content_block.name, input: <any>''});\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else if(chunk.type === 'content_block_delta') {\n\t\t\t\t\t\t\tif(chunk.delta.type === 'text_delta') {\n\t\t\t\t\t\t\t\tconst text = chunk.delta.text;\n\t\t\t\t\t\t\t\tresp.content.at(-1).text += text;\n\t\t\t\t\t\t\t\toptions.stream({text});\n\t\t\t\t\t\t\t} else if(chunk.delta.type === 'input_json_delta') {\n\t\t\t\t\t\t\t\tresp.content.at(-1).input += chunk.delta.partial_json;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else if(chunk.type === 'content_block_stop') {\n\t\t\t\t\t\t\tconst last = resp.content.at(-1);\n\t\t\t\t\t\t\tif(last.input != null) last.input = last.input ? JSONAttemptParse(last.input, {}) : {};\n\t\t\t\t\t\t} else if(chunk.type === 'message_stop') {\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tconst textContent = resp.content.filter((c: any) => c.type == 'text').map((c: any) => c.text).join('\\n\\n');\n\t\t\t\tif(textContent) assistantMessages.push(textContent);\n\t\t\t\tconst toolCalls = resp.content.filter((c: any) => c.type === 'tool_use');\n\t\t\t\tif(toolCalls.length && !controller.signal.aborted) {\n\t\t\t\t\thistory.push({role: 'assistant', content: resp.content});\n\t\t\t\t\tconst results = await Promise.all(toolCalls.map(async (toolCall: any) => {\n\t\t\t\t\t\tconst tool = options.tools?.find(findByProp('name', toolCall.name));\n\t\t\t\t\t\tif(!tool) return {tool_use_id: toolCall.id, is_error: true, content: 'Tool not found'};\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tconst result = await tool.fn(toolCall.input, this.ai);\n\t\t\t\t\t\t\treturn {type: 'tool_result', tool_use_id: toolCall.id, content: JSONSanitize(result)};\n\t\t\t\t\t\t} catch (err: any) {\n\t\t\t\t\t\t\treturn {type: 'tool_result', tool_use_id: toolCall.id, is_error: true, content: err?.message || err?.toString() || 'Unknown'};\n\t\t\t\t\t\t}\n\t\t\t\t\t}));\n\t\t\t\t\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\t\t\tif(options.stream) options.stream({done: true});\n\t\t\tres(this.toStandard([...history, {role: 'assistant', content: assistantMessages.join('\\n\\n'), timestamp: Date.now()}]));\n\t\t});\n\n\t\treturn Object.assign(response, {abort: () => controller.abort()});\n\t}\n}\n","import {findByProp, objectMap, JSONSanitize, JSONAttemptParse} from '@ztimson/utils';\nimport {Ai} from './ai.ts';\nimport {LLMMessage, LLMRequest} from './llm.ts';\nimport {AbortablePromise, LLMProvider} from './provider.ts';\nimport {Ollama as ollama} from 'ollama';\n\nexport class Ollama extends LLMProvider {\n\tclient!: ollama;\n\n\tconstructor(public readonly ai: Ai, public host: string, public model: string) {\n\t\tsuper();\n\t\tthis.client = new ollama({host});\n\t}\n\n\tprivate toStandard(history: any[]): LLMMessage[] {\n\t\tfor(let i = 0; i < history.length; i++) {\n\t\t\tif(history[i].role == 'assistant' && history[i].tool_calls) {\n\t\t\t\tif(history[i].content) delete history[i].tool_calls;\n\t\t\t\telse {\n\t\t\t\t\thistory.splice(i, 1);\n\t\t\t\t\ti--;\n\t\t\t\t}\n\t\t\t} else if(history[i].role == 'tool') {\n\t\t\t\tconst error = history[i].content.startsWith('{\"error\":');\n\t\t\t\thistory[i] = {role: 'tool', name: history[i].tool_name, args: history[i].args, [error ? 'error' : 'content']: history[i].content, timestamp: history[i].timestamp};\n\t\t\t}\n\t\t\tif(!history[i]?.timestamp) history[i].timestamp = Date.now();\n\t\t}\n\t\treturn history;\n\t}\n\n\tprivate fromStandard(history: LLMMessage[]): any[] {\n\t\treturn history.map((h: any) => {\n\t\t\tconst {timestamp, ...rest} = h;\n\t\t\tif(h.role != 'tool') return rest;\n\t\t\treturn {role: 'tool', tool_name: h.name, content: h.error || h.content}\n\t\t});\n\t}\n\n\task(message: string, options: LLMRequest = {}): AbortablePromise<LLMMessage[]> {\n\t\tconst controller = new AbortController();\n\t\tconst response = new Promise<any>(async (res, rej) => {\n\t\t\tlet system = options.system || this.ai.options.system;\n\t\t\tlet history = this.fromStandard([...options.history || [], {role: 'user', content: message, timestamp: Date.now()}]);\n\t\t\tif(history[0].roll == 'system') {\n\t\t\t\tif(!system) system = history.shift();\n\t\t\t\telse history.shift();\n\t\t\t}\n\t\t\tif(options.compress) history = await this.ai.llm.compress(<any>history, options.compress.max, options.compress.min);\n\t\t\tif(options.system) history.unshift({role: 'system', content: system})\n\n\t\t\tconst requestParams: any = {\n\t\t\t\tmodel: options.model || this.model,\n\t\t\t\tmessages: history,\n\t\t\t\tstream: !!options.stream,\n\t\t\t\tsignal: controller.signal,\n\t\t\t\toptions: {\n\t\t\t\t\ttemperature: options.temperature || this.ai.options.temperature || 0.7,\n\t\t\t\t\tnum_predict: options.max_tokens || this.ai.options.max_tokens || 4096,\n\t\t\t\t},\n\t\t\t\ttools: (options.tools || this.ai.options.tools || []).map(t => ({\n\t\t\t\t\ttype: 'function',\n\t\t\t\t\tfunction: {\n\t\t\t\t\t\tname: t.name,\n\t\t\t\t\t\tdescription: t.description,\n\t\t\t\t\t\tparameters: {\n\t\t\t\t\t\t\ttype: 'object',\n\t\t\t\t\t\t\tproperties: t.args ? objectMap(t.args, (key, value) => ({...value, required: undefined})) : {},\n\t\t\t\t\t\t\trequired: t.args ? Object.entries(t.args).filter(t => t[1].required).map(t => t[0]) : []\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}))\n\t\t\t}\n\n\t\t\tlet resp: any;\n\t\t\tconst loopMessages: any[] = [];\n\t\t\tdo {\n\t\t\t\tresp = await this.client.chat(requestParams);\n\t\t\t\tif(options.stream) {\n\t\t\t\t\tif(loopMessages.length) options.stream({text: '\\n\\n'});\n\t\t\t\t\tresp.message = {role: 'assistant', content: '', tool_calls: []};\n\t\t\t\t\tfor await (const chunk of resp) {\n\t\t\t\t\t\tif(controller.signal.aborted) break;\n\t\t\t\t\t\tif(chunk.message?.content) {\n\t\t\t\t\t\t\tresp.message.content += chunk.message.content;\n\t\t\t\t\t\t\toptions.stream({text: chunk.message.content});\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif(chunk.message?.tool_calls) resp.message.tool_calls = chunk.message.tool_calls;\n\t\t\t\t\t\tif(chunk.done) break;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tloopMessages.push({role: 'assistant', content: resp.message?.content, timestamp: Date.now()});\n\t\t\t\tif(resp.message?.tool_calls?.length && !controller.signal.aborted) {\n\t\t\t\t\thistory.push(resp.message);\n\t\t\t\t\tconst results = await Promise.all(resp.message.tool_calls.map(async (toolCall: any) => {\n\t\t\t\t\t\tconst tool = (options.tools || this.ai.options.tools)?.find(findByProp('name', toolCall.function.name));\n\t\t\t\t\t\tif(!tool) return {role: 'tool', tool_name: toolCall.function.name, content: '{\"error\": \"Tool not found\"}'};\n\t\t\t\t\t\tconst args = typeof toolCall.function.arguments === 'string' ? JSONAttemptParse(toolCall.function.arguments, {}) : toolCall.function.arguments;\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tconst result = await tool.fn(args, this.ai);\n\t\t\t\t\t\t\treturn {role: 'tool', tool_name: toolCall.function.name, args, content: JSONSanitize(result)};\n\t\t\t\t\t\t} catch (err: any) {\n\t\t\t\t\t\t\treturn {role: 'tool', tool_name: toolCall.function.name, args, content: JSONSanitize({error: err?.message || err?.toString() || 'Unknown'})};\n\t\t\t\t\t\t}\n\t\t\t\t\t}));\n\t\t\t\t\thistory.push(...results);\n\t\t\t\t\tloopMessages.push(...results.map(r => ({...r, timestamp: Date.now()})));\n\t\t\t\t\trequestParams.messages = history;\n\t\t\t\t}\n\t\t\t} while (!controller.signal.aborted && resp.message?.tool_calls?.length);\n\n\t\t\tconst combinedContent = loopMessages.filter(m => m.role === 'assistant')\n\t\t\t\t.map(m => m.content).filter(c => c).join('\\n\\n');\n\t\t\tif(options.stream) options.stream({done: true});\n\t\t\tres(this.toStandard([...history, {role: 'assistant', content: combinedContent, timestamp: Date.now()}]));\n\t\t});\n\n\t\treturn Object.assign(response, {abort: () => controller.abort()});\n\t}\n}\n","import {OpenAI as openAI} from 'openai';\nimport {findByProp, objectMap, JSONSanitize, JSONAttemptParse} from '@ztimson/utils';\nimport {Ai} from './ai.ts';\nimport {LLMMessage, LLMRequest} from './llm.ts';\nimport {AbortablePromise, LLMProvider} from './provider.ts';\n\nexport class OpenAi extends LLMProvider {\n\tclient!: openAI;\n\n\tconstructor(public readonly ai: Ai, public readonly apiToken: string, public model: string) {\n\t\tsuper();\n\t\tthis.client = new openAI({apiKey: apiToken});\n\t}\n\n\tprivate toStandard(history: any[]): LLMMessage[] {\n\t\tfor(let i = 0; i < history.length; i++) {\n\t\t\tconst h = history[i];\n\t\t\tif(h.role === 'assistant' && h.tool_calls) {\n\t\t\t\tconst tools = h.tool_calls.map((tc: any) => ({\n\t\t\t\t\trole: 'tool',\n\t\t\t\t\tid: tc.id,\n\t\t\t\t\tname: tc.function.name,\n\t\t\t\t\targs: JSONAttemptParse(tc.function.arguments, {}),\n\t\t\t\t\ttimestamp: h.timestamp\n\t\t\t\t}));\n\t\t\t\thistory.splice(i, 1, ...tools);\n\t\t\t\ti += tools.length - 1;\n\t\t\t} else if(h.role === 'tool' && h.content) {\n\t\t\t\tconst record = history.find(h2 => h.tool_call_id == h2.id);\n\t\t\t\tif(record) {\n\t\t\t\t\tif(h.content.includes('\"error\":')) record.error = h.content;\n\t\t\t\t\telse record.content = h.content;\n\t\t\t\t}\n\t\t\t\thistory.splice(i, 1);\n\t\t\t\ti--;\n\t\t\t}\n\t\t\tif(!history[i]?.timestamp) history[i].timestamp = Date.now();\n\t\t}\n\t\treturn history;\n\t}\n\n\tprivate fromStandard(history: LLMMessage[]): any[] {\n\t\treturn history.reduce((result, h) => {\n\t\t\tif(h.role === 'tool') {\n\t\t\t\tresult.push({\n\t\t\t\t\trole: 'assistant',\n\t\t\t\t\tcontent: null,\n\t\t\t\t\ttool_calls: [{ id: h.id, type: 'function', function: { name: h.name, arguments: JSON.stringify(h.args) } }],\n\t\t\t\t\trefusal: null,\n\t\t\t\t\tannotations: []\n\t\t\t\t}, {\n\t\t\t\t\trole: 'tool',\n\t\t\t\t\ttool_call_id: h.id,\n\t\t\t\t\tcontent: h.error || h.content\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\tconst {timestamp, ...rest} = h;\n\t\t\t\tresult.push(rest);\n\t\t\t}\n\t\t\treturn result;\n\t\t}, [] as any[]);\n\t}\n\n\task(message: string, options: LLMRequest = {}): AbortablePromise<LLMMessage[]> {\n\t\tconst controller = new AbortController();\n\t\tconst response = new Promise<any>(async (res, rej) => {\n\t\t\tlet history = this.fromStandard([...options.history || [], {role: 'user', content: message, timestamp: Date.now()}]);\n\t\t\tif(options.compress) history = await this.ai.llm.compress(<any>history, options.compress.max, options.compress.min, options);\n\n\t\t\tconst requestParams: any = {\n\t\t\t\tmodel: options.model || this.model,\n\t\t\t\tmessages: history,\n\t\t\t\tstream: !!options.stream,\n\t\t\t\tmax_tokens: options.max_tokens || this.ai.options.max_tokens || 4096,\n\t\t\t\ttemperature: options.temperature || this.ai.options.temperature || 0.7,\n\t\t\t\ttools: (options.tools || this.ai.options.tools || []).map(t => ({\n\t\t\t\t\ttype: 'function',\n\t\t\t\t\tfunction: {\n\t\t\t\t\t\tname: t.name,\n\t\t\t\t\t\tdescription: t.description,\n\t\t\t\t\t\tparameters: {\n\t\t\t\t\t\t\ttype: 'object',\n\t\t\t\t\t\t\tproperties: t.args ? objectMap(t.args, (key, value) => ({...value, required: undefined})) : {},\n\t\t\t\t\t\t\trequired: t.args ? Object.entries(t.args).filter(t => t[1].required).map(t => t[0]) : []\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}))\n\t\t\t};\n\n\t\t\tlet resp: any;\n\t\t\tconst loopMessages: any[] = [];\n\t\t\tdo {\n\t\t\t\tresp = await this.client.chat.completions.create(requestParams);\n\t\t\t\tif(options.stream) {\n\t\t\t\t\tif(loopMessages.length) options.stream({text: '\\n\\n'});\n\t\t\t\t\tresp.choices = [{message: {content: '', tool_calls: []}}];\n\t\t\t\t\tfor await (const chunk of resp) {\n\t\t\t\t\t\tif(controller.signal.aborted) break;\n\t\t\t\t\t\tif(chunk.choices[0].delta.content) {\n\t\t\t\t\t\t\tresp.choices[0].message.content += chunk.choices[0].delta.content;\n\t\t\t\t\t\t\toptions.stream({text: chunk.choices[0].delta.content});\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif(chunk.choices[0].delta.tool_calls) {\n\t\t\t\t\t\t\tresp.choices[0].message.tool_calls = chunk.choices[0].delta.tool_calls;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tloopMessages.push({role: 'assistant', content: resp.choices[0].message.content || '', timestamp: Date.now()});\n\n\t\t\t\tconst toolCalls = resp.choices[0].message.tool_calls || [];\n\t\t\t\tif(toolCalls.length && !controller.signal.aborted) {\n\t\t\t\t\thistory.push(resp.choices[0].message);\n\t\t\t\t\tconst results = await Promise.all(toolCalls.map(async (toolCall: any) => {\n\t\t\t\t\t\tconst tool = options.tools?.find(findByProp('name', toolCall.function.name));\n\t\t\t\t\t\tif(!tool) return {role: 'tool', tool_call_id: toolCall.id, content: '{\"error\": \"Tool not found\"}'};\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tconst args = JSONAttemptParse(toolCall.function.arguments, {});\n\t\t\t\t\t\t\tconst result = await tool.fn(args, this.ai);\n\t\t\t\t\t\t\treturn {role: 'tool', tool_call_id: toolCall.id, content: JSONSanitize(result)};\n\t\t\t\t\t\t} catch (err: any) {\n\t\t\t\t\t\t\treturn {role: 'tool', tool_call_id: toolCall.id, content: JSONSanitize({error: err?.message || err?.toString() || 'Unknown'})};\n\t\t\t\t\t\t}\n\t\t\t\t\t}));\n\t\t\t\t\thistory.push(...results);\n\t\t\t\t\tloopMessages.push(...results.map(r => ({...r, timestamp: Date.now()})));\n\t\t\t\t\trequestParams.messages = history;\n\t\t\t\t}\n\t\t\t} while (!controller.signal.aborted && resp.choices?.[0]?.message?.tool_calls?.length);\n\n\t\t\tconst combinedContent = loopMessages.filter(m => m.role === 'assistant')\n\t\t\t\t.map(m => m.content).filter(c => c).join('\\n\\n');\n\t\t\tif(options.stream) options.stream({done: true});\n\t\t\tres(this.toStandard([...history, {role: 'assistant', content: combinedContent, timestamp: Date.now()}]));\n\t\t});\n\t\treturn Object.assign(response, {abort: () => controller.abort()});\n\t}\n}\n","import {JSONAttemptParse} from '@ztimson/utils';\nimport {Ai} from './ai.ts';\nimport {Anthropic} from './antrhopic.ts';\nimport {Ollama} from './ollama.ts';\nimport {OpenAi} from './open-ai.ts';\nimport {AbortablePromise, LLMProvider} from './provider.ts';\nimport {AiTool} from './tools.ts';\n\nexport type LLMMessage = {\n\t/** Message originator */\n\trole: 'assistant' | 'system' | 'user';\n\t/** Message content */\n\tcontent: string | any;\n\t/** Timestamp */\n\ttimestamp?: number;\n} | {\n\t/** Tool call */\n\trole: 'tool';\n\t/** Unique ID for call */\n\tid: string;\n\t/** Tool that was run */\n\tname: string;\n\t/** Tool arguments */\n\targs: any;\n\t/** Tool result */\n\tcontent: undefined | string;\n\t/** Tool error */\n\terror: undefined | string;\n\t/** Timestamp */\n\ttimestamp?: number;\n}\n\nexport type LLMOptions = {\n\t/** Anthropic settings */\n\tanthropic?: {\n\t\t/** API Token */\n\t\ttoken: string;\n\t\t/** Default model */\n\t\tmodel: string;\n\t},\n\t/** Ollama settings */\n\tollama?: {\n\t\t/** connection URL */\n\t\thost: string;\n\t\t/** Default model */\n\t\tmodel: string;\n\t},\n\t/** Open AI settings */\n\topenAi?: {\n\t\t/** API Token */\n\t\ttoken: string;\n\t\t/** Default model */\n\t\tmodel: string;\n\t},\n\t/** Default provider & model */\n\tmodel: string | [string, string];\n} & Omit<LLMRequest, 'model'>;\n\nexport type LLMRequest = {\n\t/** System prompt */\n\tsystem?: string;\n\t/** Message history */\n\thistory?: LLMMessage[];\n\t/** Max tokens for request */\n\tmax_tokens?: number;\n\t/** 0 = Rigid Logic, 1 = Balanced, 2 = Hyper Creative **/\n\ttemperature?: number;\n\t/** Available tools */\n\ttools?: AiTool[];\n\t/** LLM model */\n\tmodel?: string | [string, string];\n\t/** Stream response */\n\tstream?: (chunk: {text?: string, done?: true}) => any;\n\t/** Compress old messages in the chat to free up context */\n\tcompress?: {\n\t\t/** Trigger chat compression once context exceeds the token count */\n\t\tmax: number;\n\t\t/** Compress chat until context size smaller than */\n\t\tmin: number\n\t}\n}\n\nexport class LLM {\n\tprivate providers: {[key: string]: LLMProvider} = {};\n\n\tconstructor(public readonly ai: Ai, public readonly options: LLMOptions) {\n\t\tif(options.anthropic?.token) this.providers.anthropic = new Anthropic(this.ai, options.anthropic.token, options.anthropic.model);\n\t\tif(options.ollama?.host) this.providers.ollama = new Ollama(this.ai, options.ollama.host, options.ollama.model);\n\t\tif(options.openAi?.token) this.providers.openAi = new OpenAi(this.ai, options.openAi.token, options.openAi.model);\n\t}\n\n\t/**\n\t * Chat with LLM\n\t * @param {string} message Question\n\t * @param {LLMRequest} options Configuration options and chat history\n\t * @returns {{abort: () => void, response: Promise<LLMMessage[]>}} Function to abort response and chat history\n\t */\n\task(message: string, options: LLMRequest = {}): AbortablePromise<LLMMessage[]> {\n\t\tlet model: any = [null, null];\n\t\tif(options.model) {\n\t\t\tif(typeof options.model == 'object') model = options.model;\n\t\t\telse model = [options.model, (<any>this.options)[options.model]?.model];\n\t\t}\n\t\tif(!options.model || model[1] == null) {\n\t\t\tif(typeof this.options.model == 'object') model = this.options.model;\n\t\t\telse model = [this.options.model, (<any>this.options)[this.options.model]?.model];\n\t\t}\n\t\tif(!model[0] || !model[1]) throw new Error(`Unknown LLM provider or model: ${model[0]} / ${model[1]}`);\n\t\treturn this.providers[model[0]].ask(message, {...options, model: model[1]});\n\t}\n\n\t/**\n\t * Compress chat history to reduce context size\n\t * @param {LLMMessage[]} history Chatlog that will be compressed\n\t * @param max Trigger compression once context is larger than max\n\t * @param min Summarize until context size is less than min\n\t * @param {LLMRequest} options LLM options\n\t * @returns {Promise<LLMMessage[]>} New chat history will summary at index 0\n\t */\n\tasync compress(history: LLMMessage[], max: number, min: number, options?: LLMRequest): Promise<LLMMessage[]> {\n\t\tif(this.estimateTokens(history) < max) return history;\n\t\tlet keep = 0, tokens = 0;\n\t\tfor(let m of history.toReversed()) {\n\t\t\ttokens += this.estimateTokens(m.content);\n\t\t\tif(tokens < min) keep++;\n\t\t\telse break;\n\t\t}\n\t\tif(history.length <= keep) return history;\n\t\tconst recent = keep == 0 ? [] : history.slice(-keep),\n\t\t\tprocess = (keep == 0 ? history : history.slice(0, -keep)).filter(h => h.role === 'assistant' || h.role === 'user');\n\t\tconst summary = await this.summarize(process.map(m => `${m.role}: ${m.content}`).join('\\n\\n'), 250, options);\n\t\treturn [{role: 'assistant', content: `Conversation Summary: ${summary}`, timestamp: Date.now()}, ...recent];\n\t}\n\n\t/**\n\t * Estimate variable as tokens\n\t * @param history Object to size\n\t * @returns {number} Rough token count\n\t */\n\testimateTokens(history: any): number {\n\t\tconst text = JSON.stringify(history);\n\t\treturn Math.ceil((text.length / 4) * 1.2);\n\t}\n\n\t/**\n\t * Ask a question with JSON response\n\t * @param {string} message Question\n\t * @param {LLMRequest} options Configuration options and chat history\n\t * @returns {Promise<{} | {} | RegExpExecArray | null>}\n\t */\n\tasync json(message: string, options?: LLMRequest) {\n\t\tlet resp = await this.ask(message, {\n\t\t\tsystem: 'Respond using a JSON blob',\n\t\t\t...options\n\t\t});\n\t\tif(!resp?.[0]?.content) return {};\n\t\treturn JSONAttemptParse(new RegExp('\\{[\\s\\S]*\\}').exec(resp[0].content), {});\n\t}\n\n\t/**\n\t * Create a summary of some text\n\t * @param {string} text Text to summarize\n\t * @param {number} tokens Max number of tokens\n\t * @param options LLM request options\n\t * @returns {Promise<string>} Summary\n\t */\n\tsummarize(text: string, tokens: number, options?: LLMRequest): Promise<string | null> {\n\t\treturn this.ask(text, {system: `Generate a brief summary <= ${tokens} tokens. Output nothing else`, temperature: 0.3, ...options})\n\t\t\t.then(history => <string>history.pop()?.content || null);\n\t}\n}\n","import {createWorker} from 'tesseract.js';\nimport {LLM, LLMOptions} from './llm';\nimport fs from 'node:fs/promises';\nimport Path from 'node:path';\nimport * as tf from '@tensorflow/tfjs';\nimport {spawn} from 'node:child_process';\n\nexport type AiOptions = LLMOptions & {\n\twhisper?: {\n\t\t/** Whisper binary location */\n\t\tbinary: string;\n\t\t/** Model: `ggml-base.en.bin` */\n\t\tmodel: string;\n\t\t/** Path to models */\n\t\tpath: string;\n\t}\n}\n\nexport class Ai {\n\tprivate downloads: {[key: string]: Promise<string>} = {};\n\tprivate whisperModel!: string;\n\n\t/** Large Language Models */\n\tllm!: LLM;\n\n\tconstructor(public readonly options: AiOptions) {\n\t\tthis.llm = new LLM(this, options);\n\t\tif(this.options.whisper?.binary) {\n\t\t\tthis.whisperModel = this.options.whisper?.model.endsWith('.bin') ? this.options.whisper?.model : this.options.whisper?.model + '.bin';\n\t\t\tthis.downloadAsrModel();\n\t\t}\n\t}\n\n\t/**\n\t * Convert audio to text using Auditory Speech Recognition\n\t * @param {string} path Path to audio\n\t * @param model Whisper model\n\t * @returns {Promise<any>} Extracted text\n\t */\n\tasr(path: string, model: string = this.whisperModel): {abort: () => void, response: Promise<string | null>} {\n\t\tif(!this.options.whisper?.binary) throw new Error('Whisper not configured');\n\t\tlet abort: any = () => {};\n\t\tconst response = new Promise<string | null>((resolve, reject) => {\n\t\t\tthis.downloadAsrModel(model).then(m => {\n\t\t\t\tlet output = '';\n\t\t\t\tconst proc = spawn(<string>this.options.whisper?.binary, ['-nt', '-np', '-m', m, '-f', path], {stdio: ['ignore', 'pipe', 'ignore']});\n\t\t\t\tabort = () => proc.kill('SIGTERM');\n\t\t\t\tproc.on('error', (err: Error) => reject(err));\n\t\t\t\tproc.stdout.on('data', (data: Buffer) => output += data.toString());\n\t\t\t\tproc.on('close', (code: number) => {\n\t\t\t\t\tif(code === 0) resolve(output.trim() || null);\n\t\t\t\t\telse reject(new Error(`Exit code ${code}`));\n\t\t\t\t});\n\t\t\t});\n\t\t});\n\t\treturn {response, abort};\n\t}\n\n\t/**\n\t * Downloads the specified Whisper model if it is not already present locally.\n\t *\n\t * @param {string} model Whisper model that will be downloaded\n\t * @return {Promise<string>} Absolute path to model file, resolves once downloaded\n\t */\n\tasync downloadAsrModel(model: string = this.whisperModel): Promise<string> {\n\t\tif(!this.options.whisper?.binary) throw new Error('Whisper not configured');\n\t\tif(!model.endsWith('.bin')) model += '.bin';\n\t\tconst p = Path.join(this.options.whisper.path, model);\n\t\tif(await fs.stat(p).then(() => true).catch(() => false)) return p;\n\t\tif(!!this.downloads[model]) return this.downloads[model];\n\t\tthis.downloads[model] = fetch(`https://huggingface.co/ggerganov/whisper.cpp/resolve/main/${model}`)\n\t\t\t.then(resp => resp.arrayBuffer())\n\t\t\t.then(arr => Buffer.from(arr)).then(async buffer => {\n\t\t\t\tawait fs.writeFile(p, buffer);\n\t\t\t\tdelete this.downloads[model];\n\t\t\t\treturn p;\n\t\t\t});\n\t\treturn this.downloads[model];\n\t}\n\n\t/**\n\t * Convert image to text using Optical Character Recognition\n\t * @param {string} path Path to image\n\t * @returns {{abort: Function, response: Promise<string | null>}} Abort function & Promise of extracted text\n\t */\n\tocr(path: string): {abort: () => void, response: Promise<string | null>} {\n\t\tlet worker: any;\n\t\treturn {\n\t\t\tabort: () => { worker?.terminate(); },\n\t\t\tresponse: new Promise(async res => {\n\t\t\t\tworker = await createWorker('eng');\n\t\t\t\tconst {data} = await worker.recognize(path);\n\t\t\t\tawait worker.terminate();\n\t\t\t\tres(data.text.trim() || null);\n\t\t\t})\n\t\t}\n\t}\n\n\t/**\n\t * Compare the difference between two strings using tensor math\n\t * @param target Text that will checked\n\t * @param {string} searchTerms Multiple search terms to check against target\n\t * @returns {{avg: number, max: number, similarities: number[]}} Similarity values 0-1: 0 = unique, 1 = identical\n\t */\n\tsemanticSimilarity(target: string, ...searchTerms: string[]) {\n\t\tif(searchTerms.length < 2) throw new Error('Requires at least 2 strings to compare');\n\n\t\tconst vector = (text: string, dimensions: number = 10): number[] => {\n\t\t\treturn text.toLowerCase().split('').map((char, index) =>\n\t\t\t\t(char.charCodeAt(0) * (index + 1)) % dimensions / dimensions).slice(0, dimensions);\n\t\t}\n\n\t\tconst cosineSimilarity = (v1: number[], v2: number[]): number => {\n\t\t\tif (v1.length !== v2.length) throw new Error('Vectors must be same length');\n\t\t\tconst tensor1 = tf.tensor1d(v1), tensor2 = tf.tensor1d(v2)\n\t\t\tconst dotProduct = tf.dot(tensor1, tensor2)\n\t\t\tconst magnitude1 = tf.norm(tensor1)\n\t\t\tconst magnitude2 = tf.norm(tensor2)\n\t\t\tif(magnitude1.dataSync()[0] === 0 || magnitude2.dataSync()[0] === 0) return 0\n\t\t\treturn dotProduct.dataSync()[0] / (magnitude1.dataSync()[0] * magnitude2.dataSync()[0])\n\t\t}\n\n\t\tconst v = vector(target);\n\t\tconst similarities = searchTerms.map(t => vector(t)).map(refVector => cosineSimilarity(v, refVector))\n\t\treturn {avg: similarities.reduce((acc, s) => acc + s, 0) / similarities.length, max: Math.max(...similarities), similarities}\n\t}\n}\n","import {$, $Sync} from '@ztimson/node-utils';\nimport {ASet, consoleInterceptor, Http, fn as Fn} from '@ztimson/utils';\nimport {Ai} from './ai.ts';\n\nexport type AiToolArg = {[key: string]: {\n\t/** Argument type */\n\ttype: 'array' | 'boolean' | 'number' | 'object' | 'string',\n\t/** Argument description */\n\tdescription: string,\n\t/** Required argument */\n\trequired?: boolean;\n\t/** Default value */\n\tdefault?: any,\n\t/** Options */\n\tenum?: string[],\n\t/** Minimum value or length */\n\tmin?: number,\n\t/** Maximum value or length */\n\tmax?: number,\n\t/** Match pattern */\n\tpattern?: string,\n\t/** Child arguments */\n\titems?: {[key: string]: AiToolArg}\n}}\n\nexport type AiTool = {\n\t/** Tool ID / Name - Must be snail_case */\n\tname: string,\n\t/** Tool description / prompt */\n\tdescription: string,\n\t/** Tool arguments */\n\targs?: AiToolArg,\n\t/** Callback function */\n\tfn: (args: any, ai: Ai) => any | Promise<any>,\n};\n\nexport const CliTool: AiTool = {\n\tname: 'cli',\n\tdescription: 'Use the command line interface, returns any output',\n\targs: {command: {type: 'string', description: 'Command to run', required: true}},\n\tfn: (args: {command: string}) => $`${args.command}`\n}\n\nexport const DateTimeTool: AiTool = {\n\tname: 'get_datetime',\n\tdescription: 'Get current date and time',\n\targs: {},\n\tfn: async () => new Date().toISOString()\n}\n\nexport const ExecTool: AiTool = {\n\tname: 'exec',\n\tdescription: 'Run code/scripts',\n\targs: {\n\t\tlanguage: {type: 'string', description: 'Execution language', enum: ['cli', 'node', 'python'], required: true},\n\t\tcode: {type: 'string', description: 'Code to execute', required: true}\n\t},\n\tfn: async (args, ai) => {\n\t\ttry {\n\t\t\tswitch(args.type) {\n\t\t\t\tcase 'bash':\n\t\t\t\t\treturn await CliTool.fn({command: args.code}, ai);\n\t\t\t\tcase 'node':\n\t\t\t\t\treturn await JSTool.fn({code: args.code}, ai);\n\t\t\t\tcase 'python': {\n\t\t\t\t\treturn await PythonTool.fn({code: args.code}, ai);\n\t\t\t\t}\n\t\t\t}\n\t\t} catch(err: any) {\n\t\t\treturn {error: err?.message || err.toString()};\n\t\t}\n\t}\n}\n\nexport const FetchTool: AiTool = {\n\tname: 'fetch',\n\tdescription: 'Make HTTP request to URL',\n\targs: {\n\t\turl: {type: 'string', description: 'URL to fetch', required: true},\n\t\tmethod: {type: 'string', description: 'HTTP method to use', enum: ['GET', 'POST', 'PUT', 'DELETE'], default: 'GET'},\n\t\theaders: {type: 'object', description: 'HTTP headers to send', default: {}},\n\t\tbody: {type: 'object', description: 'HTTP body to send'},\n\t},\n\tfn: (args: {\n\t\turl: string;\n\t\tmethod: 'GET' | 'POST' | 'PUT' | 'DELETE';\n\t\theaders: {[key: string]: string};\n\t\tbody: any;\n\t}) => new Http({url: args.url, headers: args.headers}).request({method: args.method || 'GET', body: args.body})\n}\n\nexport const JSTool: AiTool = {\n\tname: 'exec_javascript',\n\tdescription: 'Execute commonjs javascript',\n\targs: {\n\t\tcode: {type: 'string', description: 'CommonJS javascript', required: true}\n\t},\n\tfn: async (args: {code: string}) => {\n\t\tconst console = consoleInterceptor(null);\n\t\tconst resp = await Fn<any>({console}, args.code, true).catch((err: any) => console.output.error.push(err));\n\t\treturn {...console.output, return: resp, stdout: undefined, stderr: undefined};\n\t}\n}\n\nexport const PythonTool: AiTool = {\n\tname: 'exec_javascript',\n\tdescription: 'Execute commonjs javascript',\n\targs: {\n\t\tcode: {type: 'string', description: 'CommonJS javascript', required: true}\n\t},\n\tfn: async (args: {code: string}) => ({result: $Sync`python -c \"${args.code}\"`})\n}\n\nexport const SearchTool: AiTool = {\n\tname: 'search',\n\tdescription: 'Use a search engine to find relevant URLs, should be changed with fetch to scrape sources',\n\targs: {\n\t\tquery: {type: 'string', description: 'Search string', required: true},\n\t\tlength: {type: 'string', description: 'Number of results to return', default: 5},\n\t},\n\tfn: async (args: {\n\t\tquery: string;\n\t\tlength: number;\n\t}) => {\n\t\tconst html = await fetch(`https://html.duckduckgo.com/html/?q=${encodeURIComponent(args.query)}`, {\n\t\t\theaders: {\"User-Agent\": \"Mozilla/5.0 (Windows NT 10.0; Win64; x64)\", \"Accept-Language\": \"en-US,en;q=0.9\"}\n\t\t}).then(resp => resp.text());\n\t\tlet match, regex = /<a .*?href=\"(.+?)\".+?<\\/a>/g;\n\t\tconst results = new ASet<string>();\n\t\twhile((match = regex.exec(html)) !== null) {\n\t\t\tlet url = /uddg=(.+)&amp?/.exec(decodeURIComponent(match[1]))?.[1];\n\t\t\tif(url) url = decodeURIComponent(url);\n\t\t\tif(url) results.add(url);\n\t\t\tif(results.size >= (args.length || 5)) break;\n\t\t}\n\t\treturn results;\n\t}\n}\n"],"names":["LLMProvider","Anthropic","ai","apiToken","model","anthropic","history","i","orgI","c","h","timestamp","message","options","controller","response","res","rej","requestParams","t","objectMap","key","value","resp","assistantMessages","chunk","text","last","JSONAttemptParse","textContent","toolCalls","results","toolCall","tool","findByProp","result","JSONSanitize","err","Ollama","host","ollama","error","rest","system","loopMessages","args","r","combinedContent","m","OpenAi","openAI","tools","tc","record","h2","LLM","max","min","keep","tokens","recent","process","Ai","path","abort","resolve","reject","output","proc","spawn","data","code","p","Path","fs","arr","buffer","worker","createWorker","target","searchTerms","vector","dimensions","char","index","cosineSimilarity","v1","v2","tensor1","tf","tensor2","dotProduct","magnitude1","magnitude2","v","similarities","refVector","acc","s","CliTool","DateTimeTool","ExecTool","JSTool","PythonTool","FetchTool","Http","console","consoleInterceptor","Fn","$Sync","SearchTool","html","match","regex","ASet","url"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ztimson/ai-utils",
3
- "version": "0.1.19",
3
+ "version": "0.1.20",
4
4
  "description": "AI Utility library",
5
5
  "author": "Zak Timson",
6
6
  "license": "MIT",