@ztimson/ai-utils 0.2.1 → 0.2.2

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/ai.d.ts CHANGED
@@ -7,9 +7,9 @@ export type AiOptions = LLMOptions & {
7
7
  binary: string;
8
8
  /** Model: `ggml-base.en.bin` */
9
9
  model: string;
10
- /** Path to models */
11
- path: string;
12
10
  };
11
+ /** Path to models */
12
+ path: string;
13
13
  };
14
14
  export declare class Ai {
15
15
  readonly options: AiOptions;
package/dist/index.js CHANGED
@@ -1,18 +1,18 @@
1
- (function(f,y){typeof exports=="object"&&typeof module<"u"?y(exports,require("@xenova/transformers"),require("@ztimson/utils"),require("@anthropic-ai/sdk"),require("ollama"),require("openai"),require("node:child_process"),require("node:fs/promises"),require("node:path"),require("tesseract.js"),require("@ztimson/node-utils")):typeof define=="function"&&define.amd?define(["exports","@xenova/transformers","@ztimson/utils","@anthropic-ai/sdk","ollama","openai","node:child_process","node:fs/promises","node:path","tesseract.js","@ztimson/node-utils"],y):(f=typeof globalThis<"u"?globalThis:f||self,y(f.utils={},f.transformers,f.utils,f.sdk,f.ollama,f.openai,f.node_child_process,f.fs,f.Path,f.tesseract_js,f.nodeUtils))})(this,(function(f,y,g,A,P,O,v,k,E,$,S){"use strict";class b{}class x extends b{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(i=>i.type=="tool_use").forEach(i=>{e++,t.splice(e,0,{role:"tool",id:i.id,name:i.name,args:i.input,timestamp:Date.now()})}):t[n].role=="user"&&t[n].content.filter(i=>i.type=="tool_result").forEach(i=>{const c=t.find(h=>h.id==i.tool_use_id);c[i.is_error?"error":"content"]=i.content}),t[n].content=t[n].content.filter(i=>i.type=="text").map(i=>i.text).join(`
1
+ (function(f,y){typeof exports=="object"&&typeof module<"u"?y(exports,require("@xenova/transformers"),require("@ztimson/utils"),require("@anthropic-ai/sdk"),require("ollama"),require("openai"),require("node:child_process"),require("node:fs/promises"),require("node:path"),require("tesseract.js"),require("@ztimson/node-utils")):typeof define=="function"&&define.amd?define(["exports","@xenova/transformers","@ztimson/utils","@anthropic-ai/sdk","ollama","openai","node:child_process","node:fs/promises","node:path","tesseract.js","@ztimson/node-utils"],y):(f=typeof globalThis<"u"?globalThis:f||self,y(f.utils={},f.transformers,f.utils,f.sdk,f.ollama,f.openai,f.node_child_process,f.fs,f.Path,f.tesseract_js,f.nodeUtils))})(this,(function(f,y,g,M,P,O,v,k,E,$,S){"use strict";class b{}class x extends b{constructor(t,e,n){super(),this.ai=t,this.apiToken=e,this.model=n,this.client=new M.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(a=>a.type=="tool_use").forEach(a=>{e++,t.splice(e,0,{role:"tool",id:a.id,name:a.name,args:a.input,timestamp:Date.now()})}):t[n].role=="user"&&t[n].content.filter(a=>a.type=="tool_result").forEach(a=>{const c=t.find(h=>h.id==a.tool_use_id);c[a.is_error?"error":"content"]=a.content}),t[n].content=t[n].content.filter(a=>a.type=="text").map(a=>a.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,i=new Promise(async(c,h)=>{let a=this.fromStandard([...e.history||[],{role:"user",content:t,timestamp:Date.now()}]);const p=g.deepCopy(a);e.compress&&(a=await this.ai.language.compressHistory(a,e.compress.max,e.compress.min,e));const l={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(s=>({name:s.name,description:s.description,input_schema:{type:"object",properties:s.args?g.objectMap(s.args,(r,d)=>({...d,required:void 0})):{},required:s.args?Object.entries(s.args).filter(r=>r[1].required).map(r=>r[0]):[]},fn:void 0})),messages:a,stream:!!e.stream};let o,m=!0;do{if(o=await this.client.messages.create(l),e.stream){m?m=!1: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,a=new Promise(async(c,h)=>{let i=this.fromStandard([...e.history||[],{role:"user",content:t,timestamp:Date.now()}]);const u=g.deepCopy(i);e.compress&&(i=await this.ai.language.compressHistory(i,e.compress.max,e.compress.min,e));const l={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(s=>({name:s.name,description:s.description,input_schema:{type:"object",properties:s.args?g.objectMap(s.args,(r,d)=>({...d,required:void 0})):{},required:s.args?Object.entries(s.args).filter(r=>r[1].required).map(r=>r[0]):[]},fn:void 0})),messages:i,stream:!!e.stream};let o,m=!0;do{if(o=await this.client.messages.create(l),e.stream){m?m=!1:e.stream({text:`
4
4
 
5
- `}),o.content=[];for await(const r of o){if(n.signal.aborted)break;if(r.type==="content_block_start")r.content_block.type==="text"?o.content.push({type:"text",text:""}):r.content_block.type==="tool_use"&&o.content.push({type:"tool_use",id:r.content_block.id,name:r.content_block.name,input:""});else if(r.type==="content_block_delta")if(r.delta.type==="text_delta"){const d=r.delta.text;o.content.at(-1).text+=d,e.stream({text:d})}else r.delta.type==="input_json_delta"&&(o.content.at(-1).input+=r.delta.partial_json);else if(r.type==="content_block_stop"){const d=o.content.at(-1);d.input!=null&&(d.input=d.input?g.JSONAttemptParse(d.input,{}):{})}else if(r.type==="message_stop")break}}const s=o.content.filter(r=>r.type==="tool_use");if(s.length&&!n.signal.aborted){a.push({role:"assistant",content:o.content}),p.push({role:"assistant",content:o.content});const r=await Promise.all(s.map(async d=>{const w=e.tools?.find(g.findByProp("name",d.name));if(!w)return{tool_use_id:d.id,is_error:!0,content:"Tool not found"};try{const _=await w.fn(d.input,this.ai);return{type:"tool_result",tool_use_id:d.id,content:g.JSONSanitize(_)}}catch(_){return{type:"tool_result",tool_use_id:d.id,is_error:!0,content:_?.message||_?.toString()||"Unknown"}}}));a.push({role:"user",content:r}),l.messages=a}}while(!n.signal.aborted&&o.content.some(s=>s.type==="tool_use"));e.stream&&e.stream({done:!0}),c(this.toStandard([...a,{role:"assistant",content:o.content.filter(s=>s.type=="text").map(s=>s.text).join(`
5
+ `}),o.content=[];for await(const r of o){if(n.signal.aborted)break;if(r.type==="content_block_start")r.content_block.type==="text"?o.content.push({type:"text",text:""}):r.content_block.type==="tool_use"&&o.content.push({type:"tool_use",id:r.content_block.id,name:r.content_block.name,input:""});else if(r.type==="content_block_delta")if(r.delta.type==="text_delta"){const d=r.delta.text;o.content.at(-1).text+=d,e.stream({text:d})}else r.delta.type==="input_json_delta"&&(o.content.at(-1).input+=r.delta.partial_json);else if(r.type==="content_block_stop"){const d=o.content.at(-1);d.input!=null&&(d.input=d.input?g.JSONAttemptParse(d.input,{}):{})}else if(r.type==="message_stop")break}}const s=o.content.filter(r=>r.type==="tool_use");if(s.length&&!n.signal.aborted){i.push({role:"assistant",content:o.content}),u.push({role:"assistant",content:o.content});const r=await Promise.all(s.map(async d=>{const w=e.tools?.find(g.findByProp("name",d.name));if(!w)return{tool_use_id:d.id,is_error:!0,content:"Tool not found"};try{const _=await w.fn(d.input,this.ai);return{type:"tool_result",tool_use_id:d.id,content:g.JSONSanitize(_)}}catch(_){return{type:"tool_result",tool_use_id:d.id,is_error:!0,content:_?.message||_?.toString()||"Unknown"}}}));i.push({role:"user",content:r}),l.messages=i}}while(!n.signal.aborted&&o.content.some(s=>s.type==="tool_use"));e.stream&&e.stream({done:!0}),c(this.toStandard([...i,{role:"assistant",content:o.content.filter(s=>s.type=="text").map(s=>s.text).join(`
6
6
 
7
- `)}]))});return Object.assign(i,{abort:()=>n.abort()})}}class z extends b{constructor(t,e,n){super(),this.ai=t,this.host=e,this.model=n,this.client=new P.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,...i}=e;return e.role!="tool"?i:{role:"tool",tool_name:e.name,content:e.error||e.content}})}ask(t,e={}){const n=new AbortController,i=new Promise(async(c,h)=>{let a=e.system||this.ai.options.system,p=this.fromStandard([...e.history||[],{role:"user",content:t,timestamp:Date.now()}]);p[0].roll=="system"&&(a?p.shift():a=p.shift()),e.compress&&(p=await this.ai.language.compressHistory(p,e.compress.max,e.compress.min)),e.system&&p.unshift({role:"system",content:a});const l={model:e.model||this.model,messages:p,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(s=>({type:"function",function:{name:s.name,description:s.description,parameters:{type:"object",properties:s.args?g.objectMap(s.args,(r,d)=>({...d,required:void 0})):{},required:s.args?Object.entries(s.args).filter(r=>r[1].required).map(r=>r[0]):[]}}}))};let o,m=!0;do{if(o=await this.client.chat(l),e.stream){m?m=!1:e.stream({text:`
7
+ `)}]))});return Object.assign(a,{abort:()=>n.abort()})}}class N extends b{constructor(t,e,n){super(),this.ai=t,this.host=e,this.model=n,this.client=new P.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,...a}=e;return e.role!="tool"?a:{role:"tool",tool_name:e.name,content:e.error||e.content}})}ask(t,e={}){const n=new AbortController,a=new Promise(async(c,h)=>{let i=e.system||this.ai.options.system,u=this.fromStandard([...e.history||[],{role:"user",content:t,timestamp:Date.now()}]);u[0].roll=="system"&&(i?u.shift():i=u.shift()),e.compress&&(u=await this.ai.language.compressHistory(u,e.compress.max,e.compress.min)),e.system&&u.unshift({role:"system",content:i});const l={model:e.model||this.model,messages:u,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(s=>({type:"function",function:{name:s.name,description:s.description,parameters:{type:"object",properties:s.args?g.objectMap(s.args,(r,d)=>({...d,required:void 0})):{},required:s.args?Object.entries(s.args).filter(r=>r[1].required).map(r=>r[0]):[]}}}))};let o,m=!0;do{if(o=await this.client.chat(l),e.stream){m?m=!1:e.stream({text:`
8
8
 
9
- `}),o.message={role:"assistant",content:"",tool_calls:[]};for await(const s of o)if(n.signal.aborted||(s.message?.content&&(o.message.content+=s.message.content,e.stream({text:s.message.content})),s.message?.tool_calls&&(o.message.tool_calls=s.message.tool_calls),s.done))break}if(o.message?.tool_calls?.length&&!n.signal.aborted){p.push(o.message);const s=await Promise.all(o.message.tool_calls.map(async r=>{const d=(e.tools||this.ai.options.tools)?.find(g.findByProp("name",r.function.name));if(!d)return{role:"tool",tool_name:r.function.name,content:'{"error": "Tool not found"}'};const w=typeof r.function.arguments=="string"?g.JSONAttemptParse(r.function.arguments,{}):r.function.arguments;try{const _=await d.fn(w,this.ai);return{role:"tool",tool_name:r.function.name,args:w,content:g.JSONSanitize(_)}}catch(_){return{role:"tool",tool_name:r.function.name,args:w,content:g.JSONSanitize({error:_?.message||_?.toString()||"Unknown"})}}}));p.push(...s),l.messages=p}}while(!n.signal.aborted&&o.message?.tool_calls?.length);e.stream&&e.stream({done:!0}),c(this.toStandard([...p,{role:"assistant",content:o.message?.content}]))});return Object.assign(i,{abort:()=>n.abort()})}}class J extends b{constructor(t,e,n){super(),this.ai=t,this.apiToken=e,this.model=n,this.client=new O.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 i=n.tool_calls.map(c=>({role:"tool",id:c.id,name:c.function.name,args:g.JSONAttemptParse(c.function.arguments,{}),timestamp:n.timestamp}));t.splice(e,1,...i),e+=i.length-1}else if(n.role==="tool"&&n.content){const i=t.find(c=>n.tool_call_id==c.id);i&&(n.content.includes('"error":')?i.error=n.content:i.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:i,...c}=n;e.push(c)}return e},[])}ask(t,e={}){const n=new AbortController,i=new Promise(async(c,h)=>{let a=this.fromStandard([...e.history||[],{role:"user",content:t,timestamp:Date.now()}]);e.compress&&(a=await this.ai.language.compressHistory(a,e.compress.max,e.compress.min,e));const p={model:e.model||this.model,messages:a,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(m=>({type:"function",function:{name:m.name,description:m.description,parameters:{type:"object",properties:m.args?g.objectMap(m.args,(s,r)=>({...r,required:void 0})):{},required:m.args?Object.entries(m.args).filter(s=>s[1].required).map(s=>s[0]):[]}}}))};let l,o=!0;do{if(l=await this.client.chat.completions.create(p),e.stream){o?o=!1:e.stream({text:`
9
+ `}),o.message={role:"assistant",content:"",tool_calls:[]};for await(const s of o)if(n.signal.aborted||(s.message?.content&&(o.message.content+=s.message.content,e.stream({text:s.message.content})),s.message?.tool_calls&&(o.message.tool_calls=s.message.tool_calls),s.done))break}if(o.message?.tool_calls?.length&&!n.signal.aborted){u.push(o.message);const s=await Promise.all(o.message.tool_calls.map(async r=>{const d=(e.tools||this.ai.options.tools)?.find(g.findByProp("name",r.function.name));if(!d)return{role:"tool",tool_name:r.function.name,content:'{"error": "Tool not found"}'};const w=typeof r.function.arguments=="string"?g.JSONAttemptParse(r.function.arguments,{}):r.function.arguments;try{const _=await d.fn(w,this.ai);return{role:"tool",tool_name:r.function.name,args:w,content:g.JSONSanitize(_)}}catch(_){return{role:"tool",tool_name:r.function.name,args:w,content:g.JSONSanitize({error:_?.message||_?.toString()||"Unknown"})}}}));u.push(...s),l.messages=u}}while(!n.signal.aborted&&o.message?.tool_calls?.length);e.stream&&e.stream({done:!0}),c(this.toStandard([...u,{role:"assistant",content:o.message?.content}]))});return Object.assign(a,{abort:()=>n.abort()})}}class z extends b{constructor(t,e,n){super(),this.ai=t,this.apiToken=e,this.model=n,this.client=new O.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 a=n.tool_calls.map(c=>({role:"tool",id:c.id,name:c.function.name,args:g.JSONAttemptParse(c.function.arguments,{}),timestamp:n.timestamp}));t.splice(e,1,...a),e+=a.length-1}else if(n.role==="tool"&&n.content){const a=t.find(c=>n.tool_call_id==c.id);a&&(n.content.includes('"error":')?a.error=n.content:a.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:a,...c}=n;e.push(c)}return e},[])}ask(t,e={}){const n=new AbortController,a=new Promise(async(c,h)=>{let i=this.fromStandard([...e.history||[],{role:"user",content:t,timestamp:Date.now()}]);e.compress&&(i=await this.ai.language.compressHistory(i,e.compress.max,e.compress.min,e));const u={model:e.model||this.model,messages:i,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(m=>({type:"function",function:{name:m.name,description:m.description,parameters:{type:"object",properties:m.args?g.objectMap(m.args,(s,r)=>({...r,required:void 0})):{},required:m.args?Object.entries(m.args).filter(s=>s[1].required).map(s=>s[0]):[]}}}))};let l,o=!0;do{if(l=await this.client.chat.completions.create(u),e.stream){o?o=!1:e.stream({text:`
10
10
 
11
- `}),l.choices=[{message:{content:"",tool_calls:[]}}];for await(const s of l){if(n.signal.aborted)break;s.choices[0].delta.content&&(l.choices[0].message.content+=s.choices[0].delta.content,e.stream({text:s.choices[0].delta.content})),s.choices[0].delta.tool_calls&&(l.choices[0].message.tool_calls=s.choices[0].delta.tool_calls)}}const m=l.choices[0].message.tool_calls||[];if(m.length&&!n.signal.aborted){a.push(l.choices[0].message);const s=await Promise.all(m.map(async r=>{const d=e.tools?.find(g.findByProp("name",r.function.name));if(!d)return{role:"tool",tool_call_id:r.id,content:'{"error": "Tool not found"}'};try{const w=g.JSONAttemptParse(r.function.arguments,{}),_=await d.fn(w,this.ai);return{role:"tool",tool_call_id:r.id,content:g.JSONSanitize(_)}}catch(w){return{role:"tool",tool_call_id:r.id,content:g.JSONSanitize({error:w?.message||w?.toString()||"Unknown"})}}}));a.push(...s),p.messages=a}}while(!n.signal.aborted&&l.choices?.[0]?.message?.tool_calls?.length);e.stream&&e.stream({done:!0}),c(this.toStandard([...a,{role:"assistant",content:l.choices[0].message.content||""}]))});return Object.assign(i,{abort:()=>n.abort()})}}class T{constructor(t){this.ai=t,this.embedModel=y.pipeline("feature-extraction","Xenova/all-MiniLM-L6-v2"),t.options.anthropic?.token&&(this.providers.anthropic=new x(this.ai,t.options.anthropic.token,t.options.anthropic.model)),t.options.ollama?.host&&(this.providers.ollama=new z(this.ai,t.options.ollama.host,t.options.ollama.model)),t.options.openAi?.token&&(this.providers.openAi=new J(this.ai,t.options.openAi.token,t.options.openAi.model))}embedModel;providers={};ask(t,e={}){let n=[null,null];if(e.model&&(typeof e.model=="object"?n=e.model:n=[e.model,this.ai.options[e.model]?.model]),(!e.model||n[1]==null)&&(typeof this.ai.options.model=="object"?n=this.ai.options.model:n=[this.ai.options.model,this.ai.options[this.ai.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 compressHistory(t,e,n,i){if(this.estimateTokens(t)<e)return t;let c=0,h=0;for(let o of t.toReversed())if(h+=this.estimateTokens(o.content),h<n)c++;else break;if(t.length<=c)return t;const a=c==0?[]:t.slice(-c),p=(c==0?t:t.slice(0,-c)).filter(o=>o.role==="assistant"||o.role==="user");return[{role:"assistant",content:`Conversation Summary: ${await this.summarize(p.map(o=>`${o.role}: ${o.content}`).join(`
11
+ `}),l.choices=[{message:{content:"",tool_calls:[]}}];for await(const s of l){if(n.signal.aborted)break;s.choices[0].delta.content&&(l.choices[0].message.content+=s.choices[0].delta.content,e.stream({text:s.choices[0].delta.content})),s.choices[0].delta.tool_calls&&(l.choices[0].message.tool_calls=s.choices[0].delta.tool_calls)}}const m=l.choices[0].message.tool_calls||[];if(m.length&&!n.signal.aborted){i.push(l.choices[0].message);const s=await Promise.all(m.map(async r=>{const d=e.tools?.find(g.findByProp("name",r.function.name));if(!d)return{role:"tool",tool_call_id:r.id,content:'{"error": "Tool not found"}'};try{const w=g.JSONAttemptParse(r.function.arguments,{}),_=await d.fn(w,this.ai);return{role:"tool",tool_call_id:r.id,content:g.JSONSanitize(_)}}catch(w){return{role:"tool",tool_call_id:r.id,content:g.JSONSanitize({error:w?.message||w?.toString()||"Unknown"})}}}));i.push(...s),u.messages=i}}while(!n.signal.aborted&&l.choices?.[0]?.message?.tool_calls?.length);e.stream&&e.stream({done:!0}),c(this.toStandard([...i,{role:"assistant",content:l.choices[0].message.content||""}]))});return Object.assign(a,{abort:()=>n.abort()})}}class T{constructor(t){this.ai=t,this.embedModel=y.pipeline("feature-extraction","Xenova/all-MiniLM-L6-v2"),t.options.anthropic?.token&&(this.providers.anthropic=new x(this.ai,t.options.anthropic.token,t.options.anthropic.model)),t.options.ollama?.host&&(this.providers.ollama=new N(this.ai,t.options.ollama.host,t.options.ollama.model)),t.options.openAi?.token&&(this.providers.openAi=new z(this.ai,t.options.openAi.token,t.options.openAi.model))}embedModel;providers={};ask(t,e={}){let n=[null,null];if(e.model&&(typeof e.model=="object"?n=e.model:n=[e.model,this.ai.options[e.model]?.model]),(!e.model||n[1]==null)&&(typeof this.ai.options.model=="object"?n=this.ai.options.model:n=[this.ai.options.model,this.ai.options[this.ai.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 compressHistory(t,e,n,a){if(this.estimateTokens(t)<e)return t;let c=0,h=0;for(let o of t.toReversed())if(h+=this.estimateTokens(o.content),h<n)c++;else break;if(t.length<=c)return t;const i=c==0?[]:t.slice(-c),u=(c==0?t:t.slice(0,-c)).filter(o=>o.role==="assistant"||o.role==="user");return[{role:"assistant",content:`Conversation Summary: ${await this.summarize(u.map(o=>`${o.role}: ${o.content}`).join(`
12
12
 
13
- `),250,i)}`,timestamp:Date.now()},...a]}cosineSimilarity(t,e){if(t.length!==e.length)throw new Error("Vectors must be same length");let n=0,i=0,c=0;for(let a=0;a<t.length;a++)n+=t[a]*e[a],i+=t[a]*t[a],c+=e[a]*e[a];const h=Math.sqrt(i)*Math.sqrt(c);return h===0?0:n/h}embedding(t,e=500,n=50){const i=(o,m="")=>o==null?[]:Object.entries(o).flatMap(([s,r])=>{const d=m?`${m}${isNaN(+s)?`.${s}`:`[${s}]`}`:s;if(typeof r=="object"&&r!==null&&!Array.isArray(r))return i(r,d);const w=Array.isArray(r)?r.join(", "):String(r);return`${d}: ${w}`}),c=async o=>{const s=await(await this.embedModel)(o,{pooling:"mean",normalize:!0});return Array.from(s.data)},a=(typeof t=="object"?i(t):t.split(`
13
+ `),250,a)}`,timestamp:Date.now()},...i]}cosineSimilarity(t,e){if(t.length!==e.length)throw new Error("Vectors must be same length");let n=0,a=0,c=0;for(let i=0;i<t.length;i++)n+=t[i]*e[i],a+=t[i]*t[i],c+=e[i]*e[i];const h=Math.sqrt(a)*Math.sqrt(c);return h===0?0:n/h}embedding(t,e=500,n=50){const a=(o,m="")=>o==null?[]:Object.entries(o).flatMap(([s,r])=>{const d=m?`${m}${isNaN(+s)?`.${s}`:`[${s}]`}`:s;if(typeof r=="object"&&r!==null&&!Array.isArray(r))return a(r,d);const w=Array.isArray(r)?r.join(", "):String(r);return`${d}: ${w}`}),c=async o=>{const s=await(await this.embedModel)(o,{pooling:"mean",normalize:!0});return Array.from(s.data)},i=(typeof t=="object"?a(t):t.split(`
14
14
  `)).flatMap(o=>[...o.split(/\s+/).filter(m=>m.trim()),`
15
- `]),p=[];let l=0;for(;l<a.length;){let o=l,m="";for(;o<a.length;){const r=a[o],d=m+(m?" ":"")+r;if(this.estimateTokens(d.replace(/\s*\n\s*/g,`
15
+ `]),u=[];let l=0;for(;l<i.length;){let o=l,m="";for(;o<i.length;){const r=i[o],d=m+(m?" ":"")+r;if(this.estimateTokens(d.replace(/\s*\n\s*/g,`
16
16
  `))>e&&m)break;m=d,o++}const s=m.replace(/\s*\n\s*/g,`
17
- `).trim();s&&p.push(s),l=o-n,l<=o-a.length+o&&(l=o)}return Promise.all(p.map(async(o,m)=>({index:m,embedding:await c(o),text:o,tokens:this.estimateTokens(o)})))}estimateTokens(t){const e=JSON.stringify(t);return Math.ceil(e.length/4*1.2)}fuzzyMatch(t,...e){if(e.length<2)throw new Error("Requires at least 2 strings to compare");const n=(h,a=10)=>h.toLowerCase().split("").map((p,l)=>p.charCodeAt(0)*(l+1)%a/a).slice(0,a),i=n(t),c=e.map(h=>n(h)).map(h=>this.cosineSimilarity(i,h));return{avg:c.reduce((h,a)=>h+a,0)/c.length,max:Math.max(...c),similarities:c}}async json(t,e){let n=await this.ask(t,{system:"Respond using a JSON blob",...e});return n?.[0]?.content?g.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(i=>i.pop()?.content||null)}}class N{constructor(t){this.ai=t,t.options.whisper?.binary&&(this.whisperModel=t.options.whisper?.model.endsWith(".bin")?t.options.whisper?.model:t.options.whisper?.model+".bin",this.downloadAsrModel())}downloads={};whisperModel;asr(t,e=this.whisperModel){if(!this.ai.options.whisper?.binary)throw new Error("Whisper not configured");let n=()=>{};return{response:new Promise((c,h)=>{this.downloadAsrModel(e).then(a=>{let p="";const l=v.spawn(this.ai.options.whisper?.binary,["-nt","-np","-m",a,"-f",t],{stdio:["ignore","pipe","ignore"]});n=()=>l.kill("SIGTERM"),l.on("error",o=>h(o)),l.stdout.on("data",o=>p+=o.toString()),l.on("close",o=>{o===0?c(p.trim()||null):h(new Error(`Exit code ${o}`))})})}),abort:n}}async downloadAsrModel(t=this.whisperModel){if(!this.ai.options.whisper?.binary)throw new Error("Whisper not configured");t.endsWith(".bin")||(t+=".bin");const e=E.join(this.ai.options.whisper.path,t);return await k.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 k.writeFile(e,n),delete this.downloads[t],e)),this.downloads[t])}}class L{constructor(t){this.ai=t}ocr(t){let e;return{abort:()=>{e?.terminate()},response:new Promise(async n=>{e=await $.createWorker("eng");const{data:i}=await e.recognize(t);await e.terminate(),n(i.text.trim()||null)})}}}class U{constructor(t){this.options=t,this.audio=new N(this),this.language=new T(this),this.vision=new L(this)}downloads={};whisperModel;audio;language;vision}const j={name:"cli",description:"Use the command line interface, returns any output",args:{command:{type:"string",description:"Command to run",required:!0}},fn:u=>S.$`${u.command}`},D={name:"get_datetime",description:"Get current date and time",args:{},fn:async()=>new Date().toISOString()},R={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 j.fn({command:u.code},t);case"node":return await q.fn({code:u.code},t);case"python":return await M.fn({code:u.code},t)}}catch(e){return{error:e?.message||e.toString()}}}},H={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 g.Http({url:u.url,headers:u.headers}).request({method:u.method||"GET",body:u.body})},q={name:"exec_javascript",description:"Execute commonjs javascript",args:{code:{type:"string",description:"CommonJS javascript",required:!0}},fn:async u=>{const t=g.consoleInterceptor(null),e=await g.fn({console:t},u.code,!0).catch(n=>t.output.error.push(n));return{...t.output,return:e,stdout:void 0,stderr:void 0}}},M={name:"exec_javascript",description:"Execute commonjs javascript",args:{code:{type:"string",description:"CommonJS javascript",required:!0}},fn:async u=>({result:S.$Sync`python -c "${u.code}"`})},I={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(c=>c.text());let e,n=/<a .*?href="(.+?)".+?<\/a>/g;const i=new g.ASet;for(;(e=n.exec(t))!==null;){let c=/uddg=(.+)&amp?/.exec(decodeURIComponent(e[1]))?.[1];if(c&&(c=decodeURIComponent(c)),c&&i.add(c),i.size>=(u.length||5))break}return i}};f.Ai=U,f.Anthropic=x,f.CliTool=j,f.DateTimeTool=D,f.ExecTool=R,f.FetchTool=H,f.JSTool=q,f.LLM=T,f.PythonTool=M,f.SearchTool=I,Object.defineProperty(f,Symbol.toStringTag,{value:"Module"})}));
17
+ `).trim();s&&u.push(s),l=o-n,l<=o-i.length+o&&(l=o)}return Promise.all(u.map(async(o,m)=>({index:m,embedding:await c(o),text:o,tokens:this.estimateTokens(o)})))}estimateTokens(t){const e=JSON.stringify(t);return Math.ceil(e.length/4*1.2)}fuzzyMatch(t,...e){if(e.length<2)throw new Error("Requires at least 2 strings to compare");const n=(h,i=10)=>h.toLowerCase().split("").map((u,l)=>u.charCodeAt(0)*(l+1)%i/i).slice(0,i),a=n(t),c=e.map(h=>n(h)).map(h=>this.cosineSimilarity(a,h));return{avg:c.reduce((h,i)=>h+i,0)/c.length,max:Math.max(...c),similarities:c}}async json(t,e){let n=await this.ask(t,{system:"Respond using a JSON blob",...e});return n?.[0]?.content?g.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(a=>a.pop()?.content||null)}}class J{constructor(t){this.ai=t,t.options.whisper?.binary&&(this.whisperModel=t.options.whisper?.model.endsWith(".bin")?t.options.whisper?.model:t.options.whisper?.model+".bin",this.downloadAsrModel())}downloads={};whisperModel;asr(t,e=this.whisperModel){if(!this.ai.options.whisper?.binary)throw new Error("Whisper not configured");let n=()=>{};return{response:new Promise((c,h)=>{this.downloadAsrModel(e).then(i=>{let u="";const l=v.spawn(this.ai.options.whisper?.binary,["-nt","-np","-m",i,"-f",t],{stdio:["ignore","pipe","ignore"]});n=()=>l.kill("SIGTERM"),l.on("error",o=>h(o)),l.stdout.on("data",o=>u+=o.toString()),l.on("close",o=>{o===0?c(u.trim()||null):h(new Error(`Exit code ${o}`))})})}),abort:n}}async downloadAsrModel(t=this.whisperModel){if(!this.ai.options.whisper?.binary)throw new Error("Whisper not configured");t.endsWith(".bin")||(t+=".bin");const e=E.join(this.ai.options.path,t);return await k.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 k.writeFile(e,n),delete this.downloads[t],e)),this.downloads[t])}}class L{constructor(t){this.ai=t}ocr(t){let e;return{abort:()=>{e?.terminate()},response:new Promise(async n=>{e=await $.createWorker("eng",1,{langPath:this.ai.options.path});const{data:a}=await e.recognize(t);await e.terminate(),n(a.text.trim()||null)})}}}class R{constructor(t){this.options=t,process.env.TRANSFORMERS_CACHE=t.path,this.audio=new J(this),this.language=new T(this),this.vision=new L(this)}downloads={};whisperModel;audio;language;vision}const j={name:"cli",description:"Use the command line interface, returns any output",args:{command:{type:"string",description:"Command to run",required:!0}},fn:p=>S.$`${p.command}`},U={name:"get_datetime",description:"Get current date and time",args:{},fn:async()=>new Date().toISOString()},D={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(p,t)=>{try{switch(p.type){case"bash":return await j.fn({command:p.code},t);case"node":return await q.fn({code:p.code},t);case"python":return await A.fn({code:p.code},t)}}catch(e){return{error:e?.message||e.toString()}}}},H={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:p=>new g.Http({url:p.url,headers:p.headers}).request({method:p.method||"GET",body:p.body})},q={name:"exec_javascript",description:"Execute commonjs javascript",args:{code:{type:"string",description:"CommonJS javascript",required:!0}},fn:async p=>{const t=g.consoleInterceptor(null),e=await g.fn({console:t},p.code,!0).catch(n=>t.output.error.push(n));return{...t.output,return:e,stdout:void 0,stderr:void 0}}},A={name:"exec_javascript",description:"Execute commonjs javascript",args:{code:{type:"string",description:"CommonJS javascript",required:!0}},fn:async p=>({result:S.$Sync`python -c "${p.code}"`})},I={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 p=>{const t=await fetch(`https://html.duckduckgo.com/html/?q=${encodeURIComponent(p.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 a=new g.ASet;for(;(e=n.exec(t))!==null;){let c=/uddg=(.+)&amp?/.exec(decodeURIComponent(e[1]))?.[1];if(c&&(c=decodeURIComponent(c)),c&&a.add(c),a.size>=(p.length||5))break}return a}};f.Ai=R,f.Anthropic=x,f.CliTool=j,f.DateTimeTool=U,f.ExecTool=D,f.FetchTool=H,f.JSTool=q,f.LLM=T,f.PythonTool=A,f.SearchTool=I,Object.defineProperty(f,Symbol.toStringTag,{value:"Module"})}));
18
18
  //# 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/audio.ts","../src/vision.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, deepCopy} 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\tconst original = deepCopy(history);\n\t\t\tif(options.compress) history = await this.ai.language.compressHistory(<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, isFirstMessage = true;\n\t\t\tconst assistantMessages: string[] = [];\n\t\t\tdo {\n\t\t\t\tresp = await this.client.messages.create(requestParams);\n\n\t\t\t\t// Streaming mode\n\t\t\t\tif(options.stream) {\n\t\t\t\t\tif(!isFirstMessage) options.stream({text: '\\n\\n'});\n\t\t\t\t\telse isFirstMessage = false;\n\t\t\t\t\tresp.content = [];\n\t\t\t\t\tfor await (const chunk of resp) {\n\t\t\t\t\t\tif(controller.signal.aborted) break;\n\t\t\t\t\t\tif(chunk.type === 'content_block_start') {\n\t\t\t\t\t\t\tif(chunk.content_block.type === 'text') {\n\t\t\t\t\t\t\t\tresp.content.push({type: 'text', text: ''});\n\t\t\t\t\t\t\t} else if(chunk.content_block.type === 'tool_use') {\n\t\t\t\t\t\t\t\tresp.content.push({type: 'tool_use', id: chunk.content_block.id, name: chunk.content_block.name, input: <any>''});\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else if(chunk.type === 'content_block_delta') {\n\t\t\t\t\t\t\tif(chunk.delta.type === 'text_delta') {\n\t\t\t\t\t\t\t\tconst text = chunk.delta.text;\n\t\t\t\t\t\t\t\tresp.content.at(-1).text += text;\n\t\t\t\t\t\t\t\toptions.stream({text});\n\t\t\t\t\t\t\t} else if(chunk.delta.type === 'input_json_delta') {\n\t\t\t\t\t\t\t\tresp.content.at(-1).input += chunk.delta.partial_json;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else if(chunk.type === 'content_block_stop') {\n\t\t\t\t\t\t\tconst last = resp.content.at(-1);\n\t\t\t\t\t\t\tif(last.input != null) last.input = last.input ? JSONAttemptParse(last.input, {}) : {};\n\t\t\t\t\t\t} else if(chunk.type === 'message_stop') {\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Run tools\n\t\t\t\tconst toolCalls = resp.content.filter((c: any) => c.type === 'tool_use');\n\t\t\t\tif(toolCalls.length && !controller.signal.aborted) {\n\t\t\t\t\thistory.push({role: 'assistant', content: resp.content});\n\t\t\t\t\toriginal.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\n\t\t\tif(options.stream) options.stream({done: true});\n\t\t\tres(this.toStandard([...history, {role: 'assistant', content: resp.content.filter((c: any) => c.type == 'text').map((c: any) => c.text).join('\\n\\n')}]));\n\t\t});\n\n\t\treturn Object.assign(response, {abort: () => controller.abort()});\n\t}\n}\n","import {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.language.compressHistory(<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, isFirstMessage = true;\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(!isFirstMessage) options.stream({text: '\\n\\n'});\n\t\t\t\t\telse isFirstMessage = false;\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\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\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\tif(options.stream) options.stream({done: true});\n\t\t\tres(this.toStandard([...history, {role: 'assistant', content: resp.message?.content}]));\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.language.compressHistory(<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, isFirstMessage = true;\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(!isFirstMessage) options.stream({text: '\\n\\n'});\n\t\t\t\t\telse isFirstMessage = false;\n\t\t\t\t\tresp.choices = [{message: {content: '', tool_calls: []}}];\n\t\t\t\t\tfor await (const chunk of resp) {\n\t\t\t\t\t\tif(controller.signal.aborted) break;\n\t\t\t\t\t\tif(chunk.choices[0].delta.content) {\n\t\t\t\t\t\t\tresp.choices[0].message.content += chunk.choices[0].delta.content;\n\t\t\t\t\t\t\toptions.stream({text: chunk.choices[0].delta.content});\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif(chunk.choices[0].delta.tool_calls) {\n\t\t\t\t\t\t\tresp.choices[0].message.tool_calls = chunk.choices[0].delta.tool_calls;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tconst toolCalls = resp.choices[0].message.tool_calls || [];\n\t\t\t\tif(toolCalls.length && !controller.signal.aborted) {\n\t\t\t\t\thistory.push(resp.choices[0].message);\n\t\t\t\t\tconst results = await Promise.all(toolCalls.map(async (toolCall: any) => {\n\t\t\t\t\t\tconst tool = 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\trequestParams.messages = history;\n\t\t\t\t}\n\t\t\t} while (!controller.signal.aborted && resp.choices?.[0]?.message?.tool_calls?.length);\n\n\t\t\tif(options.stream) options.stream({done: true});\n\t\t\tres(this.toStandard([...history, {role: 'assistant', content: resp.choices[0].message.content || ''}]));\n\t\t});\n\t\treturn Object.assign(response, {abort: () => controller.abort()});\n\t}\n}\n","import {pipeline} from '@xenova/transformers';\nimport {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';\nimport * as tf from '@tensorflow/tfjs';\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 embedModel: any;\n\tprivate providers: {[key: string]: LLMProvider} = {};\n\n\tconstructor(public readonly ai: Ai) {\n\t\tthis.embedModel = pipeline('feature-extraction', 'Xenova/all-MiniLM-L6-v2');\n\t\tif(ai.options.anthropic?.token) this.providers.anthropic = new Anthropic(this.ai, ai.options.anthropic.token, ai.options.anthropic.model);\n\t\tif(ai.options.ollama?.host) this.providers.ollama = new Ollama(this.ai, ai.options.ollama.host, ai.options.ollama.model);\n\t\tif(ai.options.openAi?.token) this.providers.openAi = new OpenAi(this.ai, ai.options.openAi.token, ai.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.ai.options)[options.model]?.model];\n\t\t}\n\t\tif(!options.model || model[1] == null) {\n\t\t\tif(typeof this.ai.options.model == 'object') model = this.ai.options.model;\n\t\t\telse model = [this.ai.options.model, (<any>this.ai.options)[this.ai.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 compressHistory(history: LLMMessage[], max: number, min: number, options?: LLMRequest): Promise<LLMMessage[]> {\n\t\tif(this.estimateTokens(history) < max) return history;\n\t\tlet keep = 0, tokens = 0;\n\t\tfor(let m of history.toReversed()) {\n\t\t\ttokens += this.estimateTokens(m.content);\n\t\t\tif(tokens < min) keep++;\n\t\t\telse break;\n\t\t}\n\t\tif(history.length <= keep) return history;\n\t\tconst recent = keep == 0 ? [] : history.slice(-keep),\n\t\t\tprocess = (keep == 0 ? history : history.slice(0, -keep)).filter(h => h.role === 'assistant' || h.role === 'user');\n\t\tconst summary = await this.summarize(process.map(m => `${m.role}: ${m.content}`).join('\\n\\n'), 250, options);\n\t\treturn [{role: 'assistant', content: `Conversation Summary: ${summary}`, timestamp: Date.now()}, ...recent];\n\t}\n\n\tcosineSimilarity(v1: number[], v2: number[]): number {\n\t\tif (v1.length !== v2.length) throw new Error('Vectors must be same length');\n\t\tlet dotProduct = 0, normA = 0, normB = 0;\n\t\tfor (let i = 0; i < v1.length; i++) {\n\t\t\tdotProduct += v1[i] * v2[i];\n\t\t\tnormA += v1[i] * v1[i];\n\t\t\tnormB += v2[i] * v2[i];\n\t\t}\n\t\tconst denominator = Math.sqrt(normA) * Math.sqrt(normB);\n\t\treturn denominator === 0 ? 0 : dotProduct / denominator;\n\t}\n\n\tembedding(target: object | string, maxTokens = 500, overlapTokens = 50) {\n\t\tconst objString = (obj: any, path = ''): string[] => {\n\t\t\tif(obj === null || obj === undefined) return [];\n\t\t\treturn Object.entries(obj).flatMap(([key, value]) => {\n\t\t\t\tconst p = path ? `${path}${isNaN(+key) ? `.${key}` : `[${key}]`}` : key;\n\t\t\t\tif(typeof value === 'object' && value !== null && !Array.isArray(value)) return objString(value, p);\n\t\t\t\tconst valueStr = Array.isArray(value) ? value.join(', ') : String(value);\n\t\t\t\treturn `${p}: ${valueStr}`;\n\t\t\t});\n\t\t};\n\n\t\tconst embed = async (text: string): Promise<number[]> => {\n\t\t\tconst model = await this.embedModel;\n\t\t\tconst output = await model(text, {pooling: 'mean', normalize: true});\n\t\t\treturn Array.from(output.data);\n\t\t};\n\n\t\t// Tokenize\n\t\tconst lines = typeof target === 'object' ? objString(target) : target.split('\\n');\n\t\tconst tokens = lines.flatMap(line => [...line.split(/\\s+/).filter(w => w.trim()), '\\n']);\n\n\t\t// Chunk\n\t\tconst chunks: string[] = [];\n\t\tlet start = 0;\n\t\twhile (start < tokens.length) {\n\t\t\tlet end = start;\n\t\t\tlet text = '';\n\t\t\t// Build chunk\n\t\t\twhile (end < tokens.length) {\n\t\t\t\tconst nextToken = tokens[end];\n\t\t\t\tconst testText = text + (text ? ' ' : '') + nextToken;\n\t\t\t\tconst testTokens = this.estimateTokens(testText.replace(/\\s*\\n\\s*/g, '\\n'));\n\t\t\t\tif (testTokens > maxTokens && text) break;\n\t\t\t\ttext = testText;\n\t\t\t\tend++;\n\t\t\t}\n\t\t\t// Save chunk\n\t\t\tconst cleanText = text.replace(/\\s*\\n\\s*/g, '\\n').trim();\n\t\t\tif(cleanText) chunks.push(cleanText);\n\t\t\tstart = end - overlapTokens;\n\t\t\tif (start <= end - tokens.length + end) start = end; // Safety: prevent infinite loop\n\t\t}\n\n\t\treturn Promise.all(chunks.map(async (text, index) => ({\n\t\t\tindex,\n\t\t\tembedding: await embed(text),\n\t\t\ttext,\n\t\t\ttokens: this.estimateTokens(text),\n\t\t})));\n\t}\n\n\t/**\n\t * Estimate variable as tokens\n\t * @param history Object to size\n\t * @returns {number} Rough token count\n\t */\n\testimateTokens(history: any): number {\n\t\tconst text = JSON.stringify(history);\n\t\treturn Math.ceil((text.length / 4) * 1.2);\n\t}\n\n\t/**\n\t * Compare the difference between two strings using tensor math\n\t * @param target Text that will checked\n\t * @param {string} searchTerms Multiple search terms to check against target\n\t * @returns {{avg: number, max: number, similarities: number[]}} Similarity values 0-1: 0 = unique, 1 = identical\n\t */\n\tfuzzyMatch(target: string, ...searchTerms: string[]) {\n\t\tif(searchTerms.length < 2) throw new Error('Requires at least 2 strings to compare');\n\t\tconst vector = (text: string, dimensions: number = 10): number[] => {\n\t\t\treturn text.toLowerCase().split('').map((char, index) =>\n\t\t\t\t(char.charCodeAt(0) * (index + 1)) % dimensions / dimensions).slice(0, dimensions);\n\t\t}\n\t\tconst v = vector(target);\n\t\tconst similarities = searchTerms.map(t => vector(t)).map(refVector => this.cosineSimilarity(v, refVector))\n\t\treturn {avg: similarities.reduce((acc, s) => acc + s, 0) / similarities.length, max: Math.max(...similarities), similarities}\n\t}\n\n\t/**\n\t * Ask a question with JSON response\n\t * @param {string} message Question\n\t * @param {LLMRequest} options Configuration options and chat history\n\t * @returns {Promise<{} | {} | RegExpExecArray | null>}\n\t */\n\tasync json(message: string, options?: LLMRequest) {\n\t\tlet resp = await this.ask(message, {\n\t\t\tsystem: 'Respond using a JSON blob',\n\t\t\t...options\n\t\t});\n\t\tif(!resp?.[0]?.content) return {};\n\t\treturn JSONAttemptParse(new RegExp('\\{[\\s\\S]*\\}').exec(resp[0].content), {});\n\t}\n\n\t/**\n\t * Create a summary of some text\n\t * @param {string} text Text to summarize\n\t * @param {number} tokens Max number of tokens\n\t * @param options LLM request options\n\t * @returns {Promise<string>} Summary\n\t */\n\tsummarize(text: string, tokens: number, options?: LLMRequest): Promise<string | null> {\n\t\treturn this.ask(text, {system: `Generate a brief summary <= ${tokens} tokens. Output nothing else`, temperature: 0.3, ...options})\n\t\t\t.then(history => <string>history.pop()?.content || null);\n\t}\n}\n","import {spawn} from 'node:child_process';\nimport fs from 'node:fs/promises';\nimport Path from 'node:path';\nimport {Ai} from './ai.ts';\n\nexport class Audio {\n\tprivate downloads: {[key: string]: Promise<string>} = {};\n\tprivate whisperModel!: string;\n\n\tconstructor(private ai: Ai) {\n\t\tif(ai.options.whisper?.binary) {\n\t\t\tthis.whisperModel = ai.options.whisper?.model.endsWith('.bin') ? ai.options.whisper?.model : ai.options.whisper?.model + '.bin';\n\t\t\tthis.downloadAsrModel();\n\t\t}\n\t}\n\n\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.ai.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.ai.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.ai.options.whisper?.binary) throw new Error('Whisper not configured');\n\t\tif(!model.endsWith('.bin')) model += '.bin';\n\t\tconst p = Path.join(this.ai.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","import {createWorker} from 'tesseract.js';\nimport {Ai} from './ai.ts';\n\nexport class Vision {\n\n\tconstructor(private ai: Ai) { }\n\n\t/**\n\t * Convert image to text using Optical Character Recognition\n\t * @param {string} path Path to image\n\t * @returns {{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","import {LLM, LLMOptions} from './llm';\nimport { Audio } from './audio.ts';\nimport {Vision} from './vision.ts';\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/** Audio processing AI */\n\taudio!: Audio;\n\t/** Language processing AI */\n\tlanguage!: LLM;\n\t/** Vision processing AI */\n\tvision!: Vision;\n\n\tconstructor(public readonly options: AiOptions) {\n\t\tthis.audio = new Audio(this);\n\t\tthis.language = new LLM(this);\n\t\tthis.vision = new Vision(this);\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","original","deepCopy","requestParams","t","objectMap","key","value","resp","isFirstMessage","chunk","text","last","JSONAttemptParse","toolCalls","results","toolCall","tool","findByProp","result","JSONSanitize","err","Ollama","host","ollama","error","rest","system","args","OpenAi","openAI","tools","tc","record","h2","LLM","pipeline","max","min","keep","tokens","m","recent","process","v1","v2","dotProduct","normA","normB","denominator","target","maxTokens","overlapTokens","objString","obj","path","p","valueStr","embed","output","line","w","chunks","start","end","nextToken","testText","cleanText","index","searchTerms","vector","dimensions","char","v","similarities","refVector","acc","s","Audio","abort","resolve","reject","proc","spawn","data","code","Path","fs","arr","buffer","Vision","worker","createWorker","Ai","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/audio.ts","../src/vision.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, deepCopy} 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\tconst original = deepCopy(history);\n\t\t\tif(options.compress) history = await this.ai.language.compressHistory(<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, isFirstMessage = true;\n\t\t\tconst assistantMessages: string[] = [];\n\t\t\tdo {\n\t\t\t\tresp = await this.client.messages.create(requestParams);\n\n\t\t\t\t// Streaming mode\n\t\t\t\tif(options.stream) {\n\t\t\t\t\tif(!isFirstMessage) options.stream({text: '\\n\\n'});\n\t\t\t\t\telse isFirstMessage = false;\n\t\t\t\t\tresp.content = [];\n\t\t\t\t\tfor await (const chunk of resp) {\n\t\t\t\t\t\tif(controller.signal.aborted) break;\n\t\t\t\t\t\tif(chunk.type === 'content_block_start') {\n\t\t\t\t\t\t\tif(chunk.content_block.type === 'text') {\n\t\t\t\t\t\t\t\tresp.content.push({type: 'text', text: ''});\n\t\t\t\t\t\t\t} else if(chunk.content_block.type === 'tool_use') {\n\t\t\t\t\t\t\t\tresp.content.push({type: 'tool_use', id: chunk.content_block.id, name: chunk.content_block.name, input: <any>''});\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else if(chunk.type === 'content_block_delta') {\n\t\t\t\t\t\t\tif(chunk.delta.type === 'text_delta') {\n\t\t\t\t\t\t\t\tconst text = chunk.delta.text;\n\t\t\t\t\t\t\t\tresp.content.at(-1).text += text;\n\t\t\t\t\t\t\t\toptions.stream({text});\n\t\t\t\t\t\t\t} else if(chunk.delta.type === 'input_json_delta') {\n\t\t\t\t\t\t\t\tresp.content.at(-1).input += chunk.delta.partial_json;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else if(chunk.type === 'content_block_stop') {\n\t\t\t\t\t\t\tconst last = resp.content.at(-1);\n\t\t\t\t\t\t\tif(last.input != null) last.input = last.input ? JSONAttemptParse(last.input, {}) : {};\n\t\t\t\t\t\t} else if(chunk.type === 'message_stop') {\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Run tools\n\t\t\t\tconst toolCalls = resp.content.filter((c: any) => c.type === 'tool_use');\n\t\t\t\tif(toolCalls.length && !controller.signal.aborted) {\n\t\t\t\t\thistory.push({role: 'assistant', content: resp.content});\n\t\t\t\t\toriginal.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\n\t\t\tif(options.stream) options.stream({done: true});\n\t\t\tres(this.toStandard([...history, {role: 'assistant', content: resp.content.filter((c: any) => c.type == 'text').map((c: any) => c.text).join('\\n\\n')}]));\n\t\t});\n\n\t\treturn Object.assign(response, {abort: () => controller.abort()});\n\t}\n}\n","import {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.language.compressHistory(<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, isFirstMessage = true;\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(!isFirstMessage) options.stream({text: '\\n\\n'});\n\t\t\t\t\telse isFirstMessage = false;\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\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\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\tif(options.stream) options.stream({done: true});\n\t\t\tres(this.toStandard([...history, {role: 'assistant', content: resp.message?.content}]));\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.language.compressHistory(<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, isFirstMessage = true;\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(!isFirstMessage) options.stream({text: '\\n\\n'});\n\t\t\t\t\telse isFirstMessage = false;\n\t\t\t\t\tresp.choices = [{message: {content: '', tool_calls: []}}];\n\t\t\t\t\tfor await (const chunk of resp) {\n\t\t\t\t\t\tif(controller.signal.aborted) break;\n\t\t\t\t\t\tif(chunk.choices[0].delta.content) {\n\t\t\t\t\t\t\tresp.choices[0].message.content += chunk.choices[0].delta.content;\n\t\t\t\t\t\t\toptions.stream({text: chunk.choices[0].delta.content});\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif(chunk.choices[0].delta.tool_calls) {\n\t\t\t\t\t\t\tresp.choices[0].message.tool_calls = chunk.choices[0].delta.tool_calls;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tconst toolCalls = resp.choices[0].message.tool_calls || [];\n\t\t\t\tif(toolCalls.length && !controller.signal.aborted) {\n\t\t\t\t\thistory.push(resp.choices[0].message);\n\t\t\t\t\tconst results = await Promise.all(toolCalls.map(async (toolCall: any) => {\n\t\t\t\t\t\tconst tool = 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\trequestParams.messages = history;\n\t\t\t\t}\n\t\t\t} while (!controller.signal.aborted && resp.choices?.[0]?.message?.tool_calls?.length);\n\n\t\t\tif(options.stream) options.stream({done: true});\n\t\t\tres(this.toStandard([...history, {role: 'assistant', content: resp.choices[0].message.content || ''}]));\n\t\t});\n\t\treturn Object.assign(response, {abort: () => controller.abort()});\n\t}\n}\n","import {pipeline} from '@xenova/transformers';\nimport {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';\nimport * as tf from '@tensorflow/tfjs';\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 embedModel: any;\n\tprivate providers: {[key: string]: LLMProvider} = {};\n\n\tconstructor(public readonly ai: Ai) {\n\t\tthis.embedModel = pipeline('feature-extraction', 'Xenova/all-MiniLM-L6-v2');\n\t\tif(ai.options.anthropic?.token) this.providers.anthropic = new Anthropic(this.ai, ai.options.anthropic.token, ai.options.anthropic.model);\n\t\tif(ai.options.ollama?.host) this.providers.ollama = new Ollama(this.ai, ai.options.ollama.host, ai.options.ollama.model);\n\t\tif(ai.options.openAi?.token) this.providers.openAi = new OpenAi(this.ai, ai.options.openAi.token, ai.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.ai.options)[options.model]?.model];\n\t\t}\n\t\tif(!options.model || model[1] == null) {\n\t\t\tif(typeof this.ai.options.model == 'object') model = this.ai.options.model;\n\t\t\telse model = [this.ai.options.model, (<any>this.ai.options)[this.ai.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 compressHistory(history: LLMMessage[], max: number, min: number, options?: LLMRequest): Promise<LLMMessage[]> {\n\t\tif(this.estimateTokens(history) < max) return history;\n\t\tlet keep = 0, tokens = 0;\n\t\tfor(let m of history.toReversed()) {\n\t\t\ttokens += this.estimateTokens(m.content);\n\t\t\tif(tokens < min) keep++;\n\t\t\telse break;\n\t\t}\n\t\tif(history.length <= keep) return history;\n\t\tconst recent = keep == 0 ? [] : history.slice(-keep),\n\t\t\tprocess = (keep == 0 ? history : history.slice(0, -keep)).filter(h => h.role === 'assistant' || h.role === 'user');\n\t\tconst summary = await this.summarize(process.map(m => `${m.role}: ${m.content}`).join('\\n\\n'), 250, options);\n\t\treturn [{role: 'assistant', content: `Conversation Summary: ${summary}`, timestamp: Date.now()}, ...recent];\n\t}\n\n\tcosineSimilarity(v1: number[], v2: number[]): number {\n\t\tif (v1.length !== v2.length) throw new Error('Vectors must be same length');\n\t\tlet dotProduct = 0, normA = 0, normB = 0;\n\t\tfor (let i = 0; i < v1.length; i++) {\n\t\t\tdotProduct += v1[i] * v2[i];\n\t\t\tnormA += v1[i] * v1[i];\n\t\t\tnormB += v2[i] * v2[i];\n\t\t}\n\t\tconst denominator = Math.sqrt(normA) * Math.sqrt(normB);\n\t\treturn denominator === 0 ? 0 : dotProduct / denominator;\n\t}\n\n\tembedding(target: object | string, maxTokens = 500, overlapTokens = 50) {\n\t\tconst objString = (obj: any, path = ''): string[] => {\n\t\t\tif(obj === null || obj === undefined) return [];\n\t\t\treturn Object.entries(obj).flatMap(([key, value]) => {\n\t\t\t\tconst p = path ? `${path}${isNaN(+key) ? `.${key}` : `[${key}]`}` : key;\n\t\t\t\tif(typeof value === 'object' && value !== null && !Array.isArray(value)) return objString(value, p);\n\t\t\t\tconst valueStr = Array.isArray(value) ? value.join(', ') : String(value);\n\t\t\t\treturn `${p}: ${valueStr}`;\n\t\t\t});\n\t\t};\n\n\t\tconst embed = async (text: string): Promise<number[]> => {\n\t\t\tconst model = await this.embedModel;\n\t\t\tconst output = await model(text, {pooling: 'mean', normalize: true});\n\t\t\treturn Array.from(output.data);\n\t\t};\n\n\t\t// Tokenize\n\t\tconst lines = typeof target === 'object' ? objString(target) : target.split('\\n');\n\t\tconst tokens = lines.flatMap(line => [...line.split(/\\s+/).filter(w => w.trim()), '\\n']);\n\n\t\t// Chunk\n\t\tconst chunks: string[] = [];\n\t\tlet start = 0;\n\t\twhile (start < tokens.length) {\n\t\t\tlet end = start;\n\t\t\tlet text = '';\n\t\t\t// Build chunk\n\t\t\twhile (end < tokens.length) {\n\t\t\t\tconst nextToken = tokens[end];\n\t\t\t\tconst testText = text + (text ? ' ' : '') + nextToken;\n\t\t\t\tconst testTokens = this.estimateTokens(testText.replace(/\\s*\\n\\s*/g, '\\n'));\n\t\t\t\tif (testTokens > maxTokens && text) break;\n\t\t\t\ttext = testText;\n\t\t\t\tend++;\n\t\t\t}\n\t\t\t// Save chunk\n\t\t\tconst cleanText = text.replace(/\\s*\\n\\s*/g, '\\n').trim();\n\t\t\tif(cleanText) chunks.push(cleanText);\n\t\t\tstart = end - overlapTokens;\n\t\t\tif (start <= end - tokens.length + end) start = end; // Safety: prevent infinite loop\n\t\t}\n\n\t\treturn Promise.all(chunks.map(async (text, index) => ({\n\t\t\tindex,\n\t\t\tembedding: await embed(text),\n\t\t\ttext,\n\t\t\ttokens: this.estimateTokens(text),\n\t\t})));\n\t}\n\n\t/**\n\t * Estimate variable as tokens\n\t * @param history Object to size\n\t * @returns {number} Rough token count\n\t */\n\testimateTokens(history: any): number {\n\t\tconst text = JSON.stringify(history);\n\t\treturn Math.ceil((text.length / 4) * 1.2);\n\t}\n\n\t/**\n\t * Compare the difference between two strings using tensor math\n\t * @param target Text that will checked\n\t * @param {string} searchTerms Multiple search terms to check against target\n\t * @returns {{avg: number, max: number, similarities: number[]}} Similarity values 0-1: 0 = unique, 1 = identical\n\t */\n\tfuzzyMatch(target: string, ...searchTerms: string[]) {\n\t\tif(searchTerms.length < 2) throw new Error('Requires at least 2 strings to compare');\n\t\tconst vector = (text: string, dimensions: number = 10): number[] => {\n\t\t\treturn text.toLowerCase().split('').map((char, index) =>\n\t\t\t\t(char.charCodeAt(0) * (index + 1)) % dimensions / dimensions).slice(0, dimensions);\n\t\t}\n\t\tconst v = vector(target);\n\t\tconst similarities = searchTerms.map(t => vector(t)).map(refVector => this.cosineSimilarity(v, refVector))\n\t\treturn {avg: similarities.reduce((acc, s) => acc + s, 0) / similarities.length, max: Math.max(...similarities), similarities}\n\t}\n\n\t/**\n\t * Ask a question with JSON response\n\t * @param {string} message Question\n\t * @param {LLMRequest} options Configuration options and chat history\n\t * @returns {Promise<{} | {} | RegExpExecArray | null>}\n\t */\n\tasync json(message: string, options?: LLMRequest) {\n\t\tlet resp = await this.ask(message, {\n\t\t\tsystem: 'Respond using a JSON blob',\n\t\t\t...options\n\t\t});\n\t\tif(!resp?.[0]?.content) return {};\n\t\treturn JSONAttemptParse(new RegExp('\\{[\\s\\S]*\\}').exec(resp[0].content), {});\n\t}\n\n\t/**\n\t * Create a summary of some text\n\t * @param {string} text Text to summarize\n\t * @param {number} tokens Max number of tokens\n\t * @param options LLM request options\n\t * @returns {Promise<string>} Summary\n\t */\n\tsummarize(text: string, tokens: number, options?: LLMRequest): Promise<string | null> {\n\t\treturn this.ask(text, {system: `Generate a brief summary <= ${tokens} tokens. Output nothing else`, temperature: 0.3, ...options})\n\t\t\t.then(history => <string>history.pop()?.content || null);\n\t}\n}\n","import {spawn} from 'node:child_process';\nimport fs from 'node:fs/promises';\nimport Path from 'node:path';\nimport {Ai} from './ai.ts';\n\nexport class Audio {\n\tprivate downloads: {[key: string]: Promise<string>} = {};\n\tprivate whisperModel!: string;\n\n\tconstructor(private ai: Ai) {\n\t\tif(ai.options.whisper?.binary) {\n\t\t\tthis.whisperModel = ai.options.whisper?.model.endsWith('.bin') ? ai.options.whisper?.model : ai.options.whisper?.model + '.bin';\n\t\t\tthis.downloadAsrModel();\n\t\t}\n\t}\n\n\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.ai.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.ai.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.ai.options.whisper?.binary) throw new Error('Whisper not configured');\n\t\tif(!model.endsWith('.bin')) model += '.bin';\n\t\tconst p = Path.join(this.ai.options.path, model);\n\t\tif(await fs.stat(p).then(() => true).catch(() => false)) return p;\n\t\tif(!!this.downloads[model]) return this.downloads[model];\n\t\tthis.downloads[model] = fetch(`https://huggingface.co/ggerganov/whisper.cpp/resolve/main/${model}`)\n\t\t\t.then(resp => resp.arrayBuffer())\n\t\t\t.then(arr => Buffer.from(arr)).then(async buffer => {\n\t\t\t\tawait fs.writeFile(p, buffer);\n\t\t\t\tdelete this.downloads[model];\n\t\t\t\treturn p;\n\t\t\t});\n\t\treturn this.downloads[model];\n\t}\n}\n","import {createWorker} from 'tesseract.js';\nimport {Ai} from './ai.ts';\n\nexport class Vision {\n\n\tconstructor(private ai: Ai) { }\n\n\t/**\n\t * Convert image to text using Optical Character Recognition\n\t * @param {string} path Path to image\n\t * @returns {{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', 1, {langPath: this.ai.options.path});\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","import {LLM, LLMOptions} from './llm';\nimport { Audio } from './audio.ts';\nimport {Vision} from './vision.ts';\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}\n\t/** Path to models */\n\tpath: string;\n}\n\nexport class Ai {\n\tprivate downloads: {[key: string]: Promise<string>} = {};\n\tprivate whisperModel!: string;\n\n\t/** Audio processing AI */\n\taudio!: Audio;\n\t/** Language processing AI */\n\tlanguage!: LLM;\n\t/** Vision processing AI */\n\tvision!: Vision;\n\n\tconstructor(public readonly options: AiOptions) {\n\t\tprocess.env.TRANSFORMERS_CACHE = options.path;\n\t\tthis.audio = new Audio(this);\n\t\tthis.language = new LLM(this);\n\t\tthis.vision = new Vision(this);\n\t}\n}\n","import {$, $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","original","deepCopy","requestParams","t","objectMap","key","value","resp","isFirstMessage","chunk","text","last","JSONAttemptParse","toolCalls","results","toolCall","tool","findByProp","result","JSONSanitize","err","Ollama","host","ollama","error","rest","system","args","OpenAi","openAI","tools","tc","record","h2","LLM","pipeline","max","min","keep","tokens","m","recent","process","v1","v2","dotProduct","normA","normB","denominator","target","maxTokens","overlapTokens","objString","obj","path","p","valueStr","embed","output","line","w","chunks","start","end","nextToken","testText","cleanText","index","searchTerms","vector","dimensions","char","v","similarities","refVector","acc","s","Audio","abort","resolve","reject","proc","spawn","data","code","Path","fs","arr","buffer","Vision","worker","createWorker","Ai","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,13 +1,13 @@
1
1
  import { pipeline as S } from "@xenova/transformers";
2
- import { deepCopy as T, objectMap as y, JSONAttemptParse as w, findByProp as b, JSONSanitize as _, Http as j, consoleInterceptor as M, fn as q, ASet as A } from "@ztimson/utils";
2
+ import { deepCopy as T, objectMap as y, JSONAttemptParse as w, findByProp as b, JSONSanitize as _, Http as j, consoleInterceptor as M, fn as A, ASet as q } from "@ztimson/utils";
3
3
  import { Anthropic as P } from "@anthropic-ai/sdk";
4
4
  import { Ollama as E } from "ollama";
5
- import { OpenAI as $ } from "openai";
6
- import { spawn as v } from "node:child_process";
5
+ import { OpenAI as v } from "openai";
6
+ import { spawn as O } from "node:child_process";
7
7
  import x from "node:fs/promises";
8
- import O from "node:path";
9
- import { createWorker as U } from "tesseract.js";
10
- import { $ as L, $Sync as R } from "@ztimson/node-utils";
8
+ import $ from "node:path";
9
+ import { createWorker as R } from "tesseract.js";
10
+ import { $ as U, $Sync as L } from "@ztimson/node-utils";
11
11
  class k {
12
12
  }
13
13
  class D extends k {
@@ -110,7 +110,7 @@ class D extends k {
110
110
  return Object.assign(a, { abort: () => n.abort() });
111
111
  }
112
112
  }
113
- class z extends k {
113
+ class H extends k {
114
114
  constructor(t, e, n) {
115
115
  super(), this.ai = t, this.host = e, this.model = n, this.client = new E({ host: e });
116
116
  }
@@ -189,9 +189,9 @@ class z extends k {
189
189
  return Object.assign(a, { abort: () => n.abort() });
190
190
  }
191
191
  }
192
- class H extends k {
192
+ class N extends k {
193
193
  constructor(t, e, n) {
194
- super(), this.ai = t, this.apiToken = e, this.model = n, this.client = new $({ apiKey: e });
194
+ super(), this.ai = t, this.apiToken = e, this.model = n, this.client = new v({ apiKey: e });
195
195
  }
196
196
  client;
197
197
  toStandard(t) {
@@ -290,9 +290,9 @@ class H extends k {
290
290
  return Object.assign(a, { abort: () => n.abort() });
291
291
  }
292
292
  }
293
- class N {
293
+ class z {
294
294
  constructor(t) {
295
- this.ai = t, this.embedModel = S("feature-extraction", "Xenova/all-MiniLM-L6-v2"), t.options.anthropic?.token && (this.providers.anthropic = new D(this.ai, t.options.anthropic.token, t.options.anthropic.model)), t.options.ollama?.host && (this.providers.ollama = new z(this.ai, t.options.ollama.host, t.options.ollama.model)), t.options.openAi?.token && (this.providers.openAi = new H(this.ai, t.options.openAi.token, t.options.openAi.model));
295
+ this.ai = t, this.embedModel = S("feature-extraction", "Xenova/all-MiniLM-L6-v2"), t.options.anthropic?.token && (this.providers.anthropic = new D(this.ai, t.options.anthropic.token, t.options.anthropic.model)), t.options.ollama?.host && (this.providers.ollama = new H(this.ai, t.options.ollama.host, t.options.ollama.model)), t.options.openAi?.token && (this.providers.openAi = new N(this.ai, t.options.openAi.token, t.options.openAi.model));
296
296
  }
297
297
  embedModel;
298
298
  providers = {};
@@ -430,7 +430,7 @@ class I {
430
430
  return { response: new Promise((c, f) => {
431
431
  this.downloadAsrModel(e).then((i) => {
432
432
  let p = "";
433
- const l = v(this.ai.options.whisper?.binary, ["-nt", "-np", "-m", i, "-f", t], { stdio: ["ignore", "pipe", "ignore"] });
433
+ const l = O(this.ai.options.whisper?.binary, ["-nt", "-np", "-m", i, "-f", t], { stdio: ["ignore", "pipe", "ignore"] });
434
434
  n = () => l.kill("SIGTERM"), l.on("error", (o) => f(o)), l.stdout.on("data", (o) => p += o.toString()), l.on("close", (o) => {
435
435
  o === 0 ? c(p.trim() || null) : f(new Error(`Exit code ${o}`));
436
436
  });
@@ -446,7 +446,7 @@ class I {
446
446
  async downloadAsrModel(t = this.whisperModel) {
447
447
  if (!this.ai.options.whisper?.binary) throw new Error("Whisper not configured");
448
448
  t.endsWith(".bin") || (t += ".bin");
449
- const e = O.join(this.ai.options.whisper.path, t);
449
+ const e = $.join(this.ai.options.path, t);
450
450
  return await x.stat(e).then(() => !0).catch(() => !1) ? e : this.downloads[t] ? this.downloads[t] : (this.downloads[t] = fetch(`https://huggingface.co/ggerganov/whisper.cpp/resolve/main/${t}`).then((n) => n.arrayBuffer()).then((n) => Buffer.from(n)).then(async (n) => (await x.writeFile(e, n), delete this.downloads[t], e)), this.downloads[t]);
451
451
  }
452
452
  }
@@ -466,7 +466,7 @@ class J {
466
466
  e?.terminate();
467
467
  },
468
468
  response: new Promise(async (n) => {
469
- e = await U("eng");
469
+ e = await R("eng", 1, { langPath: this.ai.options.path });
470
470
  const { data: a } = await e.recognize(t);
471
471
  await e.terminate(), n(a.text.trim() || null);
472
472
  })
@@ -475,7 +475,7 @@ class J {
475
475
  }
476
476
  class ne {
477
477
  constructor(t) {
478
- this.options = t, this.audio = new I(this), this.language = new N(this), this.vision = new J(this);
478
+ this.options = t, process.env.TRANSFORMERS_CACHE = t.path, this.audio = new I(this), this.language = new z(this), this.vision = new J(this);
479
479
  }
480
480
  downloads = {};
481
481
  whisperModel;
@@ -490,7 +490,7 @@ const W = {
490
490
  name: "cli",
491
491
  description: "Use the command line interface, returns any output",
492
492
  args: { command: { type: "string", description: "Command to run", required: !0 } },
493
- fn: (u) => L`${u.command}`
493
+ fn: (u) => U`${u.command}`
494
494
  }, oe = {
495
495
  name: "get_datetime",
496
496
  description: "Get current date and time",
@@ -509,9 +509,9 @@ const W = {
509
509
  case "bash":
510
510
  return await W.fn({ command: u.code }, t);
511
511
  case "node":
512
- return await G.fn({ code: u.code }, t);
513
- case "python":
514
512
  return await F.fn({ code: u.code }, t);
513
+ case "python":
514
+ return await G.fn({ code: u.code }, t);
515
515
  }
516
516
  } catch (e) {
517
517
  return { error: e?.message || e.toString() };
@@ -527,23 +527,23 @@ const W = {
527
527
  body: { type: "object", description: "HTTP body to send" }
528
528
  },
529
529
  fn: (u) => new j({ url: u.url, headers: u.headers }).request({ method: u.method || "GET", body: u.body })
530
- }, G = {
530
+ }, F = {
531
531
  name: "exec_javascript",
532
532
  description: "Execute commonjs javascript",
533
533
  args: {
534
534
  code: { type: "string", description: "CommonJS javascript", required: !0 }
535
535
  },
536
536
  fn: async (u) => {
537
- const t = M(null), e = await q({ console: t }, u.code, !0).catch((n) => t.output.error.push(n));
537
+ const t = M(null), e = await A({ console: t }, u.code, !0).catch((n) => t.output.error.push(n));
538
538
  return { ...t.output, return: e, stdout: void 0, stderr: void 0 };
539
539
  }
540
- }, F = {
540
+ }, G = {
541
541
  name: "exec_javascript",
542
542
  description: "Execute commonjs javascript",
543
543
  args: {
544
544
  code: { type: "string", description: "CommonJS javascript", required: !0 }
545
545
  },
546
- fn: async (u) => ({ result: R`python -c "${u.code}"` })
546
+ fn: async (u) => ({ result: L`python -c "${u.code}"` })
547
547
  }, ae = {
548
548
  name: "search",
549
549
  description: "Use a search engine to find relevant URLs, should be changed with fetch to scrape sources",
@@ -556,7 +556,7 @@ const W = {
556
556
  headers: { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64)", "Accept-Language": "en-US,en;q=0.9" }
557
557
  }).then((c) => c.text());
558
558
  let e, n = /<a .*?href="(.+?)".+?<\/a>/g;
559
- const a = new A();
559
+ const a = new q();
560
560
  for (; (e = n.exec(t)) !== null; ) {
561
561
  let c = /uddg=(.+)&amp?/.exec(decodeURIComponent(e[1]))?.[1];
562
562
  if (c && (c = decodeURIComponent(c)), c && a.add(c), a.size >= (u.length || 5)) break;
@@ -571,9 +571,9 @@ export {
571
571
  oe as DateTimeTool,
572
572
  se as ExecTool,
573
573
  re as FetchTool,
574
- G as JSTool,
575
- N as LLM,
576
- F as PythonTool,
574
+ F as JSTool,
575
+ z as LLM,
576
+ G as PythonTool,
577
577
  ae as SearchTool
578
578
  };
579
579
  //# sourceMappingURL=index.mjs.map
@@ -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/audio.ts","../src/vision.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, deepCopy} 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\tconst original = deepCopy(history);\n\t\t\tif(options.compress) history = await this.ai.language.compressHistory(<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, isFirstMessage = true;\n\t\t\tconst assistantMessages: string[] = [];\n\t\t\tdo {\n\t\t\t\tresp = await this.client.messages.create(requestParams);\n\n\t\t\t\t// Streaming mode\n\t\t\t\tif(options.stream) {\n\t\t\t\t\tif(!isFirstMessage) options.stream({text: '\\n\\n'});\n\t\t\t\t\telse isFirstMessage = false;\n\t\t\t\t\tresp.content = [];\n\t\t\t\t\tfor await (const chunk of resp) {\n\t\t\t\t\t\tif(controller.signal.aborted) break;\n\t\t\t\t\t\tif(chunk.type === 'content_block_start') {\n\t\t\t\t\t\t\tif(chunk.content_block.type === 'text') {\n\t\t\t\t\t\t\t\tresp.content.push({type: 'text', text: ''});\n\t\t\t\t\t\t\t} else if(chunk.content_block.type === 'tool_use') {\n\t\t\t\t\t\t\t\tresp.content.push({type: 'tool_use', id: chunk.content_block.id, name: chunk.content_block.name, input: <any>''});\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else if(chunk.type === 'content_block_delta') {\n\t\t\t\t\t\t\tif(chunk.delta.type === 'text_delta') {\n\t\t\t\t\t\t\t\tconst text = chunk.delta.text;\n\t\t\t\t\t\t\t\tresp.content.at(-1).text += text;\n\t\t\t\t\t\t\t\toptions.stream({text});\n\t\t\t\t\t\t\t} else if(chunk.delta.type === 'input_json_delta') {\n\t\t\t\t\t\t\t\tresp.content.at(-1).input += chunk.delta.partial_json;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else if(chunk.type === 'content_block_stop') {\n\t\t\t\t\t\t\tconst last = resp.content.at(-1);\n\t\t\t\t\t\t\tif(last.input != null) last.input = last.input ? JSONAttemptParse(last.input, {}) : {};\n\t\t\t\t\t\t} else if(chunk.type === 'message_stop') {\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Run tools\n\t\t\t\tconst toolCalls = resp.content.filter((c: any) => c.type === 'tool_use');\n\t\t\t\tif(toolCalls.length && !controller.signal.aborted) {\n\t\t\t\t\thistory.push({role: 'assistant', content: resp.content});\n\t\t\t\t\toriginal.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\n\t\t\tif(options.stream) options.stream({done: true});\n\t\t\tres(this.toStandard([...history, {role: 'assistant', content: resp.content.filter((c: any) => c.type == 'text').map((c: any) => c.text).join('\\n\\n')}]));\n\t\t});\n\n\t\treturn Object.assign(response, {abort: () => controller.abort()});\n\t}\n}\n","import {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.language.compressHistory(<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, isFirstMessage = true;\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(!isFirstMessage) options.stream({text: '\\n\\n'});\n\t\t\t\t\telse isFirstMessage = false;\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\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\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\tif(options.stream) options.stream({done: true});\n\t\t\tres(this.toStandard([...history, {role: 'assistant', content: resp.message?.content}]));\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.language.compressHistory(<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, isFirstMessage = true;\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(!isFirstMessage) options.stream({text: '\\n\\n'});\n\t\t\t\t\telse isFirstMessage = false;\n\t\t\t\t\tresp.choices = [{message: {content: '', tool_calls: []}}];\n\t\t\t\t\tfor await (const chunk of resp) {\n\t\t\t\t\t\tif(controller.signal.aborted) break;\n\t\t\t\t\t\tif(chunk.choices[0].delta.content) {\n\t\t\t\t\t\t\tresp.choices[0].message.content += chunk.choices[0].delta.content;\n\t\t\t\t\t\t\toptions.stream({text: chunk.choices[0].delta.content});\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif(chunk.choices[0].delta.tool_calls) {\n\t\t\t\t\t\t\tresp.choices[0].message.tool_calls = chunk.choices[0].delta.tool_calls;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tconst toolCalls = resp.choices[0].message.tool_calls || [];\n\t\t\t\tif(toolCalls.length && !controller.signal.aborted) {\n\t\t\t\t\thistory.push(resp.choices[0].message);\n\t\t\t\t\tconst results = await Promise.all(toolCalls.map(async (toolCall: any) => {\n\t\t\t\t\t\tconst tool = 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\trequestParams.messages = history;\n\t\t\t\t}\n\t\t\t} while (!controller.signal.aborted && resp.choices?.[0]?.message?.tool_calls?.length);\n\n\t\t\tif(options.stream) options.stream({done: true});\n\t\t\tres(this.toStandard([...history, {role: 'assistant', content: resp.choices[0].message.content || ''}]));\n\t\t});\n\t\treturn Object.assign(response, {abort: () => controller.abort()});\n\t}\n}\n","import {pipeline} from '@xenova/transformers';\nimport {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';\nimport * as tf from '@tensorflow/tfjs';\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 embedModel: any;\n\tprivate providers: {[key: string]: LLMProvider} = {};\n\n\tconstructor(public readonly ai: Ai) {\n\t\tthis.embedModel = pipeline('feature-extraction', 'Xenova/all-MiniLM-L6-v2');\n\t\tif(ai.options.anthropic?.token) this.providers.anthropic = new Anthropic(this.ai, ai.options.anthropic.token, ai.options.anthropic.model);\n\t\tif(ai.options.ollama?.host) this.providers.ollama = new Ollama(this.ai, ai.options.ollama.host, ai.options.ollama.model);\n\t\tif(ai.options.openAi?.token) this.providers.openAi = new OpenAi(this.ai, ai.options.openAi.token, ai.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.ai.options)[options.model]?.model];\n\t\t}\n\t\tif(!options.model || model[1] == null) {\n\t\t\tif(typeof this.ai.options.model == 'object') model = this.ai.options.model;\n\t\t\telse model = [this.ai.options.model, (<any>this.ai.options)[this.ai.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 compressHistory(history: LLMMessage[], max: number, min: number, options?: LLMRequest): Promise<LLMMessage[]> {\n\t\tif(this.estimateTokens(history) < max) return history;\n\t\tlet keep = 0, tokens = 0;\n\t\tfor(let m of history.toReversed()) {\n\t\t\ttokens += this.estimateTokens(m.content);\n\t\t\tif(tokens < min) keep++;\n\t\t\telse break;\n\t\t}\n\t\tif(history.length <= keep) return history;\n\t\tconst recent = keep == 0 ? [] : history.slice(-keep),\n\t\t\tprocess = (keep == 0 ? history : history.slice(0, -keep)).filter(h => h.role === 'assistant' || h.role === 'user');\n\t\tconst summary = await this.summarize(process.map(m => `${m.role}: ${m.content}`).join('\\n\\n'), 250, options);\n\t\treturn [{role: 'assistant', content: `Conversation Summary: ${summary}`, timestamp: Date.now()}, ...recent];\n\t}\n\n\tcosineSimilarity(v1: number[], v2: number[]): number {\n\t\tif (v1.length !== v2.length) throw new Error('Vectors must be same length');\n\t\tlet dotProduct = 0, normA = 0, normB = 0;\n\t\tfor (let i = 0; i < v1.length; i++) {\n\t\t\tdotProduct += v1[i] * v2[i];\n\t\t\tnormA += v1[i] * v1[i];\n\t\t\tnormB += v2[i] * v2[i];\n\t\t}\n\t\tconst denominator = Math.sqrt(normA) * Math.sqrt(normB);\n\t\treturn denominator === 0 ? 0 : dotProduct / denominator;\n\t}\n\n\tembedding(target: object | string, maxTokens = 500, overlapTokens = 50) {\n\t\tconst objString = (obj: any, path = ''): string[] => {\n\t\t\tif(obj === null || obj === undefined) return [];\n\t\t\treturn Object.entries(obj).flatMap(([key, value]) => {\n\t\t\t\tconst p = path ? `${path}${isNaN(+key) ? `.${key}` : `[${key}]`}` : key;\n\t\t\t\tif(typeof value === 'object' && value !== null && !Array.isArray(value)) return objString(value, p);\n\t\t\t\tconst valueStr = Array.isArray(value) ? value.join(', ') : String(value);\n\t\t\t\treturn `${p}: ${valueStr}`;\n\t\t\t});\n\t\t};\n\n\t\tconst embed = async (text: string): Promise<number[]> => {\n\t\t\tconst model = await this.embedModel;\n\t\t\tconst output = await model(text, {pooling: 'mean', normalize: true});\n\t\t\treturn Array.from(output.data);\n\t\t};\n\n\t\t// Tokenize\n\t\tconst lines = typeof target === 'object' ? objString(target) : target.split('\\n');\n\t\tconst tokens = lines.flatMap(line => [...line.split(/\\s+/).filter(w => w.trim()), '\\n']);\n\n\t\t// Chunk\n\t\tconst chunks: string[] = [];\n\t\tlet start = 0;\n\t\twhile (start < tokens.length) {\n\t\t\tlet end = start;\n\t\t\tlet text = '';\n\t\t\t// Build chunk\n\t\t\twhile (end < tokens.length) {\n\t\t\t\tconst nextToken = tokens[end];\n\t\t\t\tconst testText = text + (text ? ' ' : '') + nextToken;\n\t\t\t\tconst testTokens = this.estimateTokens(testText.replace(/\\s*\\n\\s*/g, '\\n'));\n\t\t\t\tif (testTokens > maxTokens && text) break;\n\t\t\t\ttext = testText;\n\t\t\t\tend++;\n\t\t\t}\n\t\t\t// Save chunk\n\t\t\tconst cleanText = text.replace(/\\s*\\n\\s*/g, '\\n').trim();\n\t\t\tif(cleanText) chunks.push(cleanText);\n\t\t\tstart = end - overlapTokens;\n\t\t\tif (start <= end - tokens.length + end) start = end; // Safety: prevent infinite loop\n\t\t}\n\n\t\treturn Promise.all(chunks.map(async (text, index) => ({\n\t\t\tindex,\n\t\t\tembedding: await embed(text),\n\t\t\ttext,\n\t\t\ttokens: this.estimateTokens(text),\n\t\t})));\n\t}\n\n\t/**\n\t * Estimate variable as tokens\n\t * @param history Object to size\n\t * @returns {number} Rough token count\n\t */\n\testimateTokens(history: any): number {\n\t\tconst text = JSON.stringify(history);\n\t\treturn Math.ceil((text.length / 4) * 1.2);\n\t}\n\n\t/**\n\t * Compare the difference between two strings using tensor math\n\t * @param target Text that will checked\n\t * @param {string} searchTerms Multiple search terms to check against target\n\t * @returns {{avg: number, max: number, similarities: number[]}} Similarity values 0-1: 0 = unique, 1 = identical\n\t */\n\tfuzzyMatch(target: string, ...searchTerms: string[]) {\n\t\tif(searchTerms.length < 2) throw new Error('Requires at least 2 strings to compare');\n\t\tconst vector = (text: string, dimensions: number = 10): number[] => {\n\t\t\treturn text.toLowerCase().split('').map((char, index) =>\n\t\t\t\t(char.charCodeAt(0) * (index + 1)) % dimensions / dimensions).slice(0, dimensions);\n\t\t}\n\t\tconst v = vector(target);\n\t\tconst similarities = searchTerms.map(t => vector(t)).map(refVector => this.cosineSimilarity(v, refVector))\n\t\treturn {avg: similarities.reduce((acc, s) => acc + s, 0) / similarities.length, max: Math.max(...similarities), similarities}\n\t}\n\n\t/**\n\t * Ask a question with JSON response\n\t * @param {string} message Question\n\t * @param {LLMRequest} options Configuration options and chat history\n\t * @returns {Promise<{} | {} | RegExpExecArray | null>}\n\t */\n\tasync json(message: string, options?: LLMRequest) {\n\t\tlet resp = await this.ask(message, {\n\t\t\tsystem: 'Respond using a JSON blob',\n\t\t\t...options\n\t\t});\n\t\tif(!resp?.[0]?.content) return {};\n\t\treturn JSONAttemptParse(new RegExp('\\{[\\s\\S]*\\}').exec(resp[0].content), {});\n\t}\n\n\t/**\n\t * Create a summary of some text\n\t * @param {string} text Text to summarize\n\t * @param {number} tokens Max number of tokens\n\t * @param options LLM request options\n\t * @returns {Promise<string>} Summary\n\t */\n\tsummarize(text: string, tokens: number, options?: LLMRequest): Promise<string | null> {\n\t\treturn this.ask(text, {system: `Generate a brief summary <= ${tokens} tokens. Output nothing else`, temperature: 0.3, ...options})\n\t\t\t.then(history => <string>history.pop()?.content || null);\n\t}\n}\n","import {spawn} from 'node:child_process';\nimport fs from 'node:fs/promises';\nimport Path from 'node:path';\nimport {Ai} from './ai.ts';\n\nexport class Audio {\n\tprivate downloads: {[key: string]: Promise<string>} = {};\n\tprivate whisperModel!: string;\n\n\tconstructor(private ai: Ai) {\n\t\tif(ai.options.whisper?.binary) {\n\t\t\tthis.whisperModel = ai.options.whisper?.model.endsWith('.bin') ? ai.options.whisper?.model : ai.options.whisper?.model + '.bin';\n\t\t\tthis.downloadAsrModel();\n\t\t}\n\t}\n\n\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.ai.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.ai.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.ai.options.whisper?.binary) throw new Error('Whisper not configured');\n\t\tif(!model.endsWith('.bin')) model += '.bin';\n\t\tconst p = Path.join(this.ai.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","import {createWorker} from 'tesseract.js';\nimport {Ai} from './ai.ts';\n\nexport class Vision {\n\n\tconstructor(private ai: Ai) { }\n\n\t/**\n\t * Convert image to text using Optical Character Recognition\n\t * @param {string} path Path to image\n\t * @returns {{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","import {LLM, LLMOptions} from './llm';\nimport { Audio } from './audio.ts';\nimport {Vision} from './vision.ts';\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/** Audio processing AI */\n\taudio!: Audio;\n\t/** Language processing AI */\n\tlanguage!: LLM;\n\t/** Vision processing AI */\n\tvision!: Vision;\n\n\tconstructor(public readonly options: AiOptions) {\n\t\tthis.audio = new Audio(this);\n\t\tthis.language = new LLM(this);\n\t\tthis.vision = new Vision(this);\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","original","deepCopy","requestParams","t","objectMap","key","value","resp","isFirstMessage","chunk","text","last","JSONAttemptParse","toolCalls","results","toolCall","tool","findByProp","result","JSONSanitize","err","Ollama","host","ollama","error","rest","system","args","OpenAi","openAI","tools","tc","record","h2","LLM","pipeline","max","min","keep","tokens","m","recent","process","v1","v2","dotProduct","normA","normB","denominator","target","maxTokens","overlapTokens","objString","obj","path","p","valueStr","embed","output","line","w","chunks","start","end","nextToken","testText","cleanText","index","searchTerms","vector","dimensions","char","v","similarities","refVector","acc","s","Audio","abort","resolve","reject","proc","spawn","data","code","Path","fs","arr","buffer","Vision","worker","createWorker","Ai","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/audio.ts","../src/vision.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, deepCopy} 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\tconst original = deepCopy(history);\n\t\t\tif(options.compress) history = await this.ai.language.compressHistory(<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, isFirstMessage = true;\n\t\t\tconst assistantMessages: string[] = [];\n\t\t\tdo {\n\t\t\t\tresp = await this.client.messages.create(requestParams);\n\n\t\t\t\t// Streaming mode\n\t\t\t\tif(options.stream) {\n\t\t\t\t\tif(!isFirstMessage) options.stream({text: '\\n\\n'});\n\t\t\t\t\telse isFirstMessage = false;\n\t\t\t\t\tresp.content = [];\n\t\t\t\t\tfor await (const chunk of resp) {\n\t\t\t\t\t\tif(controller.signal.aborted) break;\n\t\t\t\t\t\tif(chunk.type === 'content_block_start') {\n\t\t\t\t\t\t\tif(chunk.content_block.type === 'text') {\n\t\t\t\t\t\t\t\tresp.content.push({type: 'text', text: ''});\n\t\t\t\t\t\t\t} else if(chunk.content_block.type === 'tool_use') {\n\t\t\t\t\t\t\t\tresp.content.push({type: 'tool_use', id: chunk.content_block.id, name: chunk.content_block.name, input: <any>''});\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else if(chunk.type === 'content_block_delta') {\n\t\t\t\t\t\t\tif(chunk.delta.type === 'text_delta') {\n\t\t\t\t\t\t\t\tconst text = chunk.delta.text;\n\t\t\t\t\t\t\t\tresp.content.at(-1).text += text;\n\t\t\t\t\t\t\t\toptions.stream({text});\n\t\t\t\t\t\t\t} else if(chunk.delta.type === 'input_json_delta') {\n\t\t\t\t\t\t\t\tresp.content.at(-1).input += chunk.delta.partial_json;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else if(chunk.type === 'content_block_stop') {\n\t\t\t\t\t\t\tconst last = resp.content.at(-1);\n\t\t\t\t\t\t\tif(last.input != null) last.input = last.input ? JSONAttemptParse(last.input, {}) : {};\n\t\t\t\t\t\t} else if(chunk.type === 'message_stop') {\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Run tools\n\t\t\t\tconst toolCalls = resp.content.filter((c: any) => c.type === 'tool_use');\n\t\t\t\tif(toolCalls.length && !controller.signal.aborted) {\n\t\t\t\t\thistory.push({role: 'assistant', content: resp.content});\n\t\t\t\t\toriginal.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\n\t\t\tif(options.stream) options.stream({done: true});\n\t\t\tres(this.toStandard([...history, {role: 'assistant', content: resp.content.filter((c: any) => c.type == 'text').map((c: any) => c.text).join('\\n\\n')}]));\n\t\t});\n\n\t\treturn Object.assign(response, {abort: () => controller.abort()});\n\t}\n}\n","import {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.language.compressHistory(<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, isFirstMessage = true;\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(!isFirstMessage) options.stream({text: '\\n\\n'});\n\t\t\t\t\telse isFirstMessage = false;\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\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\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\tif(options.stream) options.stream({done: true});\n\t\t\tres(this.toStandard([...history, {role: 'assistant', content: resp.message?.content}]));\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.language.compressHistory(<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, isFirstMessage = true;\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(!isFirstMessage) options.stream({text: '\\n\\n'});\n\t\t\t\t\telse isFirstMessage = false;\n\t\t\t\t\tresp.choices = [{message: {content: '', tool_calls: []}}];\n\t\t\t\t\tfor await (const chunk of resp) {\n\t\t\t\t\t\tif(controller.signal.aborted) break;\n\t\t\t\t\t\tif(chunk.choices[0].delta.content) {\n\t\t\t\t\t\t\tresp.choices[0].message.content += chunk.choices[0].delta.content;\n\t\t\t\t\t\t\toptions.stream({text: chunk.choices[0].delta.content});\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif(chunk.choices[0].delta.tool_calls) {\n\t\t\t\t\t\t\tresp.choices[0].message.tool_calls = chunk.choices[0].delta.tool_calls;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tconst toolCalls = resp.choices[0].message.tool_calls || [];\n\t\t\t\tif(toolCalls.length && !controller.signal.aborted) {\n\t\t\t\t\thistory.push(resp.choices[0].message);\n\t\t\t\t\tconst results = await Promise.all(toolCalls.map(async (toolCall: any) => {\n\t\t\t\t\t\tconst tool = 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\trequestParams.messages = history;\n\t\t\t\t}\n\t\t\t} while (!controller.signal.aborted && resp.choices?.[0]?.message?.tool_calls?.length);\n\n\t\t\tif(options.stream) options.stream({done: true});\n\t\t\tres(this.toStandard([...history, {role: 'assistant', content: resp.choices[0].message.content || ''}]));\n\t\t});\n\t\treturn Object.assign(response, {abort: () => controller.abort()});\n\t}\n}\n","import {pipeline} from '@xenova/transformers';\nimport {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';\nimport * as tf from '@tensorflow/tfjs';\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 embedModel: any;\n\tprivate providers: {[key: string]: LLMProvider} = {};\n\n\tconstructor(public readonly ai: Ai) {\n\t\tthis.embedModel = pipeline('feature-extraction', 'Xenova/all-MiniLM-L6-v2');\n\t\tif(ai.options.anthropic?.token) this.providers.anthropic = new Anthropic(this.ai, ai.options.anthropic.token, ai.options.anthropic.model);\n\t\tif(ai.options.ollama?.host) this.providers.ollama = new Ollama(this.ai, ai.options.ollama.host, ai.options.ollama.model);\n\t\tif(ai.options.openAi?.token) this.providers.openAi = new OpenAi(this.ai, ai.options.openAi.token, ai.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.ai.options)[options.model]?.model];\n\t\t}\n\t\tif(!options.model || model[1] == null) {\n\t\t\tif(typeof this.ai.options.model == 'object') model = this.ai.options.model;\n\t\t\telse model = [this.ai.options.model, (<any>this.ai.options)[this.ai.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 compressHistory(history: LLMMessage[], max: number, min: number, options?: LLMRequest): Promise<LLMMessage[]> {\n\t\tif(this.estimateTokens(history) < max) return history;\n\t\tlet keep = 0, tokens = 0;\n\t\tfor(let m of history.toReversed()) {\n\t\t\ttokens += this.estimateTokens(m.content);\n\t\t\tif(tokens < min) keep++;\n\t\t\telse break;\n\t\t}\n\t\tif(history.length <= keep) return history;\n\t\tconst recent = keep == 0 ? [] : history.slice(-keep),\n\t\t\tprocess = (keep == 0 ? history : history.slice(0, -keep)).filter(h => h.role === 'assistant' || h.role === 'user');\n\t\tconst summary = await this.summarize(process.map(m => `${m.role}: ${m.content}`).join('\\n\\n'), 250, options);\n\t\treturn [{role: 'assistant', content: `Conversation Summary: ${summary}`, timestamp: Date.now()}, ...recent];\n\t}\n\n\tcosineSimilarity(v1: number[], v2: number[]): number {\n\t\tif (v1.length !== v2.length) throw new Error('Vectors must be same length');\n\t\tlet dotProduct = 0, normA = 0, normB = 0;\n\t\tfor (let i = 0; i < v1.length; i++) {\n\t\t\tdotProduct += v1[i] * v2[i];\n\t\t\tnormA += v1[i] * v1[i];\n\t\t\tnormB += v2[i] * v2[i];\n\t\t}\n\t\tconst denominator = Math.sqrt(normA) * Math.sqrt(normB);\n\t\treturn denominator === 0 ? 0 : dotProduct / denominator;\n\t}\n\n\tembedding(target: object | string, maxTokens = 500, overlapTokens = 50) {\n\t\tconst objString = (obj: any, path = ''): string[] => {\n\t\t\tif(obj === null || obj === undefined) return [];\n\t\t\treturn Object.entries(obj).flatMap(([key, value]) => {\n\t\t\t\tconst p = path ? `${path}${isNaN(+key) ? `.${key}` : `[${key}]`}` : key;\n\t\t\t\tif(typeof value === 'object' && value !== null && !Array.isArray(value)) return objString(value, p);\n\t\t\t\tconst valueStr = Array.isArray(value) ? value.join(', ') : String(value);\n\t\t\t\treturn `${p}: ${valueStr}`;\n\t\t\t});\n\t\t};\n\n\t\tconst embed = async (text: string): Promise<number[]> => {\n\t\t\tconst model = await this.embedModel;\n\t\t\tconst output = await model(text, {pooling: 'mean', normalize: true});\n\t\t\treturn Array.from(output.data);\n\t\t};\n\n\t\t// Tokenize\n\t\tconst lines = typeof target === 'object' ? objString(target) : target.split('\\n');\n\t\tconst tokens = lines.flatMap(line => [...line.split(/\\s+/).filter(w => w.trim()), '\\n']);\n\n\t\t// Chunk\n\t\tconst chunks: string[] = [];\n\t\tlet start = 0;\n\t\twhile (start < tokens.length) {\n\t\t\tlet end = start;\n\t\t\tlet text = '';\n\t\t\t// Build chunk\n\t\t\twhile (end < tokens.length) {\n\t\t\t\tconst nextToken = tokens[end];\n\t\t\t\tconst testText = text + (text ? ' ' : '') + nextToken;\n\t\t\t\tconst testTokens = this.estimateTokens(testText.replace(/\\s*\\n\\s*/g, '\\n'));\n\t\t\t\tif (testTokens > maxTokens && text) break;\n\t\t\t\ttext = testText;\n\t\t\t\tend++;\n\t\t\t}\n\t\t\t// Save chunk\n\t\t\tconst cleanText = text.replace(/\\s*\\n\\s*/g, '\\n').trim();\n\t\t\tif(cleanText) chunks.push(cleanText);\n\t\t\tstart = end - overlapTokens;\n\t\t\tif (start <= end - tokens.length + end) start = end; // Safety: prevent infinite loop\n\t\t}\n\n\t\treturn Promise.all(chunks.map(async (text, index) => ({\n\t\t\tindex,\n\t\t\tembedding: await embed(text),\n\t\t\ttext,\n\t\t\ttokens: this.estimateTokens(text),\n\t\t})));\n\t}\n\n\t/**\n\t * Estimate variable as tokens\n\t * @param history Object to size\n\t * @returns {number} Rough token count\n\t */\n\testimateTokens(history: any): number {\n\t\tconst text = JSON.stringify(history);\n\t\treturn Math.ceil((text.length / 4) * 1.2);\n\t}\n\n\t/**\n\t * Compare the difference between two strings using tensor math\n\t * @param target Text that will checked\n\t * @param {string} searchTerms Multiple search terms to check against target\n\t * @returns {{avg: number, max: number, similarities: number[]}} Similarity values 0-1: 0 = unique, 1 = identical\n\t */\n\tfuzzyMatch(target: string, ...searchTerms: string[]) {\n\t\tif(searchTerms.length < 2) throw new Error('Requires at least 2 strings to compare');\n\t\tconst vector = (text: string, dimensions: number = 10): number[] => {\n\t\t\treturn text.toLowerCase().split('').map((char, index) =>\n\t\t\t\t(char.charCodeAt(0) * (index + 1)) % dimensions / dimensions).slice(0, dimensions);\n\t\t}\n\t\tconst v = vector(target);\n\t\tconst similarities = searchTerms.map(t => vector(t)).map(refVector => this.cosineSimilarity(v, refVector))\n\t\treturn {avg: similarities.reduce((acc, s) => acc + s, 0) / similarities.length, max: Math.max(...similarities), similarities}\n\t}\n\n\t/**\n\t * Ask a question with JSON response\n\t * @param {string} message Question\n\t * @param {LLMRequest} options Configuration options and chat history\n\t * @returns {Promise<{} | {} | RegExpExecArray | null>}\n\t */\n\tasync json(message: string, options?: LLMRequest) {\n\t\tlet resp = await this.ask(message, {\n\t\t\tsystem: 'Respond using a JSON blob',\n\t\t\t...options\n\t\t});\n\t\tif(!resp?.[0]?.content) return {};\n\t\treturn JSONAttemptParse(new RegExp('\\{[\\s\\S]*\\}').exec(resp[0].content), {});\n\t}\n\n\t/**\n\t * Create a summary of some text\n\t * @param {string} text Text to summarize\n\t * @param {number} tokens Max number of tokens\n\t * @param options LLM request options\n\t * @returns {Promise<string>} Summary\n\t */\n\tsummarize(text: string, tokens: number, options?: LLMRequest): Promise<string | null> {\n\t\treturn this.ask(text, {system: `Generate a brief summary <= ${tokens} tokens. Output nothing else`, temperature: 0.3, ...options})\n\t\t\t.then(history => <string>history.pop()?.content || null);\n\t}\n}\n","import {spawn} from 'node:child_process';\nimport fs from 'node:fs/promises';\nimport Path from 'node:path';\nimport {Ai} from './ai.ts';\n\nexport class Audio {\n\tprivate downloads: {[key: string]: Promise<string>} = {};\n\tprivate whisperModel!: string;\n\n\tconstructor(private ai: Ai) {\n\t\tif(ai.options.whisper?.binary) {\n\t\t\tthis.whisperModel = ai.options.whisper?.model.endsWith('.bin') ? ai.options.whisper?.model : ai.options.whisper?.model + '.bin';\n\t\t\tthis.downloadAsrModel();\n\t\t}\n\t}\n\n\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.ai.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.ai.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.ai.options.whisper?.binary) throw new Error('Whisper not configured');\n\t\tif(!model.endsWith('.bin')) model += '.bin';\n\t\tconst p = Path.join(this.ai.options.path, model);\n\t\tif(await fs.stat(p).then(() => true).catch(() => false)) return p;\n\t\tif(!!this.downloads[model]) return this.downloads[model];\n\t\tthis.downloads[model] = fetch(`https://huggingface.co/ggerganov/whisper.cpp/resolve/main/${model}`)\n\t\t\t.then(resp => resp.arrayBuffer())\n\t\t\t.then(arr => Buffer.from(arr)).then(async buffer => {\n\t\t\t\tawait fs.writeFile(p, buffer);\n\t\t\t\tdelete this.downloads[model];\n\t\t\t\treturn p;\n\t\t\t});\n\t\treturn this.downloads[model];\n\t}\n}\n","import {createWorker} from 'tesseract.js';\nimport {Ai} from './ai.ts';\n\nexport class Vision {\n\n\tconstructor(private ai: Ai) { }\n\n\t/**\n\t * Convert image to text using Optical Character Recognition\n\t * @param {string} path Path to image\n\t * @returns {{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', 1, {langPath: this.ai.options.path});\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","import {LLM, LLMOptions} from './llm';\nimport { Audio } from './audio.ts';\nimport {Vision} from './vision.ts';\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}\n\t/** Path to models */\n\tpath: string;\n}\n\nexport class Ai {\n\tprivate downloads: {[key: string]: Promise<string>} = {};\n\tprivate whisperModel!: string;\n\n\t/** Audio processing AI */\n\taudio!: Audio;\n\t/** Language processing AI */\n\tlanguage!: LLM;\n\t/** Vision processing AI */\n\tvision!: Vision;\n\n\tconstructor(public readonly options: AiOptions) {\n\t\tprocess.env.TRANSFORMERS_CACHE = options.path;\n\t\tthis.audio = new Audio(this);\n\t\tthis.language = new LLM(this);\n\t\tthis.vision = new Vision(this);\n\t}\n}\n","import {$, $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","original","deepCopy","requestParams","t","objectMap","key","value","resp","isFirstMessage","chunk","text","last","JSONAttemptParse","toolCalls","results","toolCall","tool","findByProp","result","JSONSanitize","err","Ollama","host","ollama","error","rest","system","args","OpenAi","openAI","tools","tc","record","h2","LLM","pipeline","max","min","keep","tokens","m","recent","process","v1","v2","dotProduct","normA","normB","denominator","target","maxTokens","overlapTokens","objString","obj","path","p","valueStr","embed","output","line","w","chunks","start","end","nextToken","testText","cleanText","index","searchTerms","vector","dimensions","char","v","similarities","refVector","acc","s","Audio","abort","resolve","reject","proc","spawn","data","code","Path","fs","arr","buffer","Vision","worker","createWorker","Ai","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.2.1",
3
+ "version": "0.2.2",
4
4
  "description": "AI Utility library",
5
5
  "author": "Zak Timson",
6
6
  "license": "MIT",