@ztimson/ai-utils 0.6.1 → 0.6.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/README.md CHANGED
@@ -75,6 +75,7 @@ A TypeScript library that provides a unified interface for working with multiple
75
75
 
76
76
  #### Instructions
77
77
  1. Install the package: `npm i @ztimson/ai-utils`
78
+ 2. For speaker diarization: `pip install pyannote.audio`
78
79
 
79
80
  </details>
80
81
 
@@ -90,8 +91,9 @@ A TypeScript library that provides a unified interface for working with multiple
90
91
 
91
92
  #### Instructions
92
93
  1. Install the dependencies: `npm i`
93
- 2. Build library: `npm build`
94
- 3. Run unit tests: `npm test`
94
+ 2. For speaker diarization: `pip install pyannote.audio`
95
+ 3. Build library: `npm build`
96
+ 4. Run unit tests: `npm test`
95
97
 
96
98
  </details>
97
99
 
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const A=require("node:os"),f=require("@ztimson/utils"),E=require("@anthropic-ai/sdk"),R=require("openai"),U=require("worker_threads"),v=require("url"),k=require("path"),S=require("node:child_process"),N=require("@xenova/transformers"),z=require("tesseract.js");require("./embedder.js");const L=require("cheerio"),x=require("@ztimson/node-utils");var b=typeof document<"u"?document.currentScript:null;function T(d){const r=Object.create(null,{[Symbol.toStringTag]:{value:"Module"}});if(d){for(const e in d)if(e!=="default"){const t=Object.getOwnPropertyDescriptor(d,e);Object.defineProperty(r,e,t.get?t:{enumerable:!0,get:()=>d[e]})}}return r.default=d,Object.freeze(r)}const C=T(A),D=T(L);class _{}class j extends _{constructor(r,e,t){super(),this.ai=r,this.apiToken=e,this.model=t,this.client=new E.Anthropic({apiKey:e})}client;toStandard(r){const e=Date.now(),t=[];for(let i of r)if(typeof i.content=="string")t.push({timestamp:e,...i});else{const s=i.content?.filter(n=>n.type=="text").map(n=>n.text).join(`
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const E=require("node:os"),f=require("@ztimson/utils"),R=require("@anthropic-ai/sdk"),U=require("openai"),v=require("worker_threads"),N=require("url"),k=require("path"),S=require("node:child_process"),x=require("@xenova/transformers"),z=require("tesseract.js");require("./embedder.js");const L=require("cheerio"),T=require("@ztimson/node-utils");var b=typeof document<"u"?document.currentScript:null;function j(d){const r=Object.create(null,{[Symbol.toStringTag]:{value:"Module"}});if(d){for(const e in d)if(e!=="default"){const t=Object.getOwnPropertyDescriptor(d,e);Object.defineProperty(r,e,t.get?t:{enumerable:!0,get:()=>d[e]})}}return r.default=d,Object.freeze(r)}const C=j(E),D=j(L);class _{}class P extends _{constructor(r,e,t){super(),this.ai=r,this.apiToken=e,this.model=t,this.client=new R.Anthropic({apiKey:e})}client;toStandard(r){const e=Date.now(),t=[];for(let i of r)if(typeof i.content=="string")t.push({timestamp:e,...i});else{const s=i.content?.filter(n=>n.type=="text").map(n=>n.text).join(`
2
2
 
3
3
  `);s&&t.push({timestamp:e,role:i.role,content:s}),i.content.forEach(n=>{if(n.type=="tool_use")t.push({timestamp:e,role:"tool",id:n.id,name:n.name,args:n.input,content:void 0});else if(n.type=="tool_result"){const o=t.findLast(a=>a.id==n.tool_use_id);o&&(o[n.is_error?"error":"content"]=n.content)}})}return t}fromStandard(r){for(let e=0;e<r.length;e++)if(r[e].role=="tool"){const t=r[e];r.splice(e,1,{role:"assistant",content:[{type:"tool_use",id:t.id,name:t.name,input:t.args}]},{role:"user",content:[{type:"tool_result",tool_use_id:t.id,is_error:!!t.error,content:t.error||t.content}]}),e++}return r.map(({timestamp:e,...t})=>t)}ask(r,e={}){const t=new AbortController;return Object.assign(new Promise(async i=>{let s=this.fromStandard([...e.history||[],{role:"user",content:r,timestamp:Date.now()}]);const n=e.tools||this.ai.options.llm?.tools||[],o={model:e.model||this.model,max_tokens:e.max_tokens||this.ai.options.llm?.max_tokens||4096,system:e.system||this.ai.options.llm?.system||"",temperature:e.temperature||this.ai.options.llm?.temperature||.7,tools:n.map(u=>({name:u.name,description:u.description,input_schema:{type:"object",properties:u.args?f.objectMap(u.args,(c,m)=>({...m,required:void 0})):{},required:u.args?Object.entries(u.args).filter(c=>c[1].required).map(c=>c[0]):[]},fn:void 0})),messages:s,stream:!!e.stream};let a,l=!0;do{if(a=await this.client.messages.create(o).catch(c=>{throw c.message+=`
4
4
 
@@ -7,12 +7,12 @@ ${JSON.stringify(s,null,2)}`,c}),e.stream){l?l=!1:e.stream({text:`
7
7
 
8
8
  `}),a.content=[];for await(const c of a){if(t.signal.aborted)break;if(c.type==="content_block_start")c.content_block.type==="text"?a.content.push({type:"text",text:""}):c.content_block.type==="tool_use"&&a.content.push({type:"tool_use",id:c.content_block.id,name:c.content_block.name,input:""});else if(c.type==="content_block_delta")if(c.delta.type==="text_delta"){const m=c.delta.text;a.content.at(-1).text+=m,e.stream({text:m})}else c.delta.type==="input_json_delta"&&(a.content.at(-1).input+=c.delta.partial_json);else if(c.type==="content_block_stop"){const m=a.content.at(-1);m.input!=null&&(m.input=m.input?f.JSONAttemptParse(m.input,{}):{})}else if(c.type==="message_stop")break}}const u=a.content.filter(c=>c.type==="tool_use");if(u.length&&!t.signal.aborted){s.push({role:"assistant",content:a.content});const c=await Promise.all(u.map(async m=>{const h=n.find(f.findByProp("name",m.name));if(e.stream&&e.stream({tool:m.name}),!h)return{tool_use_id:m.id,is_error:!0,content:"Tool not found"};try{const p=await h.fn(m.input,e?.stream,this.ai);return{type:"tool_result",tool_use_id:m.id,content:f.JSONSanitize(p)}}catch(p){return{type:"tool_result",tool_use_id:m.id,is_error:!0,content:p?.message||p?.toString()||"Unknown"}}}));s.push({role:"user",content:c}),o.messages=s}}while(!t.signal.aborted&&a.content.some(u=>u.type==="tool_use"));s.push({role:"assistant",content:a.content.filter(u=>u.type=="text").map(u=>u.text).join(`
9
9
 
10
- `)}),s=this.toStandard(s),e.stream&&e.stream({done:!0}),e.history&&e.history.splice(0,e.history.length,...s),i(s.at(-1)?.content)}),{abort:()=>t.abort()})}}class w extends _{constructor(r,e,t,i){super(),this.ai=r,this.host=e,this.token=t,this.model=i,this.client=new R.OpenAI(f.clean({baseURL:e,apiKey:t}))}client;toStandard(r){for(let e=0;e<r.length;e++){const t=r[e];if(t.role==="assistant"&&t.tool_calls){const i=t.tool_calls.map(s=>({role:"tool",id:s.id,name:s.function.name,args:f.JSONAttemptParse(s.function.arguments,{}),timestamp:t.timestamp}));r.splice(e,1,...i),e+=i.length-1}else if(t.role==="tool"&&t.content){const i=r.find(s=>t.tool_call_id==s.id);i&&(t.content.includes('"error":')?i.error=t.content:i.content=t.content),r.splice(e,1),e--}r[e]?.timestamp||(r[e].timestamp=Date.now())}return r}fromStandard(r){return r.reduce((e,t)=>{if(t.role==="tool")e.push({role:"assistant",content:null,tool_calls:[{id:t.id,type:"function",function:{name:t.name,arguments:JSON.stringify(t.args)}}],refusal:null,annotations:[]},{role:"tool",tool_call_id:t.id,content:t.error||t.content});else{const{timestamp:i,...s}=t;e.push(s)}return e},[])}ask(r,e={}){const t=new AbortController;return Object.assign(new Promise(async(i,s)=>{e.system&&e.history?.[0]?.role!="system"&&e.history?.splice(0,0,{role:"system",content:e.system,timestamp:Date.now()});let n=this.fromStandard([...e.history||[],{role:"user",content:r,timestamp:Date.now()}]);const o=e.tools||this.ai.options.llm?.tools||[],a={model:e.model||this.model,messages:n,stream:!!e.stream,max_tokens:e.max_tokens||this.ai.options.llm?.max_tokens||4096,temperature:e.temperature||this.ai.options.llm?.temperature||.7,tools:o.map(c=>({type:"function",function:{name:c.name,description:c.description,parameters:{type:"object",properties:c.args?f.objectMap(c.args,(m,h)=>({...h,required:void 0})):{},required:c.args?Object.entries(c.args).filter(m=>m[1].required).map(m=>m[0]):[]}}}))};let l,u=!0;do{if(l=await this.client.chat.completions.create(a).catch(m=>{throw m.message+=`
10
+ `)}),s=this.toStandard(s),e.stream&&e.stream({done:!0}),e.history&&e.history.splice(0,e.history.length,...s),i(s.at(-1)?.content)}),{abort:()=>t.abort()})}}class w extends _{constructor(r,e,t,i){super(),this.ai=r,this.host=e,this.token=t,this.model=i,this.client=new U.OpenAI(f.clean({baseURL:e,apiKey:t}))}client;toStandard(r){for(let e=0;e<r.length;e++){const t=r[e];if(t.role==="assistant"&&t.tool_calls){const i=t.tool_calls.map(s=>({role:"tool",id:s.id,name:s.function.name,args:f.JSONAttemptParse(s.function.arguments,{}),timestamp:t.timestamp}));r.splice(e,1,...i),e+=i.length-1}else if(t.role==="tool"&&t.content){const i=r.find(s=>t.tool_call_id==s.id);i&&(t.content.includes('"error":')?i.error=t.content:i.content=t.content),r.splice(e,1),e--}r[e]?.timestamp||(r[e].timestamp=Date.now())}return r}fromStandard(r){return r.reduce((e,t)=>{if(t.role==="tool")e.push({role:"assistant",content:null,tool_calls:[{id:t.id,type:"function",function:{name:t.name,arguments:JSON.stringify(t.args)}}],refusal:null,annotations:[]},{role:"tool",tool_call_id:t.id,content:t.error||t.content});else{const{timestamp:i,...s}=t;e.push(s)}return e},[])}ask(r,e={}){const t=new AbortController;return Object.assign(new Promise(async(i,s)=>{e.system&&e.history?.[0]?.role!="system"&&e.history?.splice(0,0,{role:"system",content:e.system,timestamp:Date.now()});let n=this.fromStandard([...e.history||[],{role:"user",content:r,timestamp:Date.now()}]);const o=e.tools||this.ai.options.llm?.tools||[],a={model:e.model||this.model,messages:n,stream:!!e.stream,max_tokens:e.max_tokens||this.ai.options.llm?.max_tokens||4096,temperature:e.temperature||this.ai.options.llm?.temperature||.7,tools:o.map(c=>({type:"function",function:{name:c.name,description:c.description,parameters:{type:"object",properties:c.args?f.objectMap(c.args,(m,h)=>({...h,required:void 0})):{},required:c.args?Object.entries(c.args).filter(m=>m[1].required).map(m=>m[0]):[]}}}))};let l,u=!0;do{if(l=await this.client.chat.completions.create(a).catch(m=>{throw m.message+=`
11
11
 
12
12
  Messages:
13
13
  ${JSON.stringify(n,null,2)}`,m}),e.stream){u?u=!1:e.stream({text:`
14
14
 
15
- `}),l.choices=[{message:{content:"",tool_calls:[]}}];for await(const m of l){if(t.signal.aborted)break;m.choices[0].delta.content&&(l.choices[0].message.content+=m.choices[0].delta.content,e.stream({text:m.choices[0].delta.content})),m.choices[0].delta.tool_calls&&(l.choices[0].message.tool_calls=m.choices[0].delta.tool_calls)}}const c=l.choices[0].message.tool_calls||[];if(c.length&&!t.signal.aborted){n.push(l.choices[0].message);const m=await Promise.all(c.map(async h=>{const p=o?.find(f.findByProp("name",h.function.name));if(e.stream&&e.stream({tool:h.function.name}),!p)return{role:"tool",tool_call_id:h.id,content:'{"error": "Tool not found"}'};try{const y=f.JSONAttemptParse(h.function.arguments,{}),g=await p.fn(y,e.stream,this.ai);return{role:"tool",tool_call_id:h.id,content:f.JSONSanitize(g)}}catch(y){return{role:"tool",tool_call_id:h.id,content:f.JSONSanitize({error:y?.message||y?.toString()||"Unknown"})}}}));n.push(...m),a.messages=n}}while(!t.signal.aborted&&l.choices?.[0]?.message?.tool_calls?.length);n.push({role:"assistant",content:l.choices[0].message.content||""}),n=this.toStandard(n),e.stream&&e.stream({done:!0}),e.history&&e.history.splice(0,e.history.length,...n),i(n.at(-1)?.content)}),{abort:()=>t.abort()})}}class J{constructor(r){this.ai=r,this.embedWorker=new U.Worker(k.join(k.dirname(v.fileURLToPath(typeof document>"u"?require("url").pathToFileURL(__filename).href:b&&b.tagName.toUpperCase()==="SCRIPT"&&b.src||new URL("index.js",document.baseURI).href)),"embedder.js")),this.embedWorker.on("message",({id:e,embedding:t})=>{const i=this.embedQueue.get(e);i&&(i.resolve(t),this.embedQueue.delete(e))}),r.options.llm?.models&&Object.entries(r.options.llm.models).forEach(([e,t])=>{this.defaultModel||(this.defaultModel=e),t.proto=="anthropic"?this.models[e]=new j(this.ai,t.token,e):t.proto=="ollama"?this.models[e]=new w(this.ai,t.host,"not-needed",e):t.proto=="openai"&&(this.models[e]=new w(this.ai,t.host||null,t.token,e))})}embedWorker=null;embedQueue=new Map;embedId=0;models={};defaultModel;ask(r,e={}){const t=e.model||this.defaultModel;if(!this.models[t])throw new Error(`Model does not exist: ${t}`);let i=()=>{};return Object.assign(new Promise(async s=>{if(e.history||(e.history=[]),e.memory){e.system=(e.system||"")+`
15
+ `}),l.choices=[{message:{content:"",tool_calls:[]}}];for await(const m of l){if(t.signal.aborted)break;m.choices[0].delta.content&&(l.choices[0].message.content+=m.choices[0].delta.content,e.stream({text:m.choices[0].delta.content})),m.choices[0].delta.tool_calls&&(l.choices[0].message.tool_calls=m.choices[0].delta.tool_calls)}}const c=l.choices[0].message.tool_calls||[];if(c.length&&!t.signal.aborted){n.push(l.choices[0].message);const m=await Promise.all(c.map(async h=>{const p=o?.find(f.findByProp("name",h.function.name));if(e.stream&&e.stream({tool:h.function.name}),!p)return{role:"tool",tool_call_id:h.id,content:'{"error": "Tool not found"}'};try{const y=f.JSONAttemptParse(h.function.arguments,{}),g=await p.fn(y,e.stream,this.ai);return{role:"tool",tool_call_id:h.id,content:f.JSONSanitize(g)}}catch(y){return{role:"tool",tool_call_id:h.id,content:f.JSONSanitize({error:y?.message||y?.toString()||"Unknown"})}}}));n.push(...m),a.messages=n}}while(!t.signal.aborted&&l.choices?.[0]?.message?.tool_calls?.length);n.push({role:"assistant",content:l.choices[0].message.content||""}),n=this.toStandard(n),e.stream&&e.stream({done:!0}),e.history&&e.history.splice(0,e.history.length,...n),i(n.at(-1)?.content)}),{abort:()=>t.abort()})}}class J{constructor(r){this.ai=r,this.embedWorker=new v.Worker(k.join(k.dirname(N.fileURLToPath(typeof document>"u"?require("url").pathToFileURL(__filename).href:b&&b.tagName.toUpperCase()==="SCRIPT"&&b.src||new URL("index.js",document.baseURI).href)),"embedder.js")),this.embedWorker.on("message",({id:e,embedding:t})=>{const i=this.embedQueue.get(e);i&&(i.resolve(t),this.embedQueue.delete(e))}),r.options.llm?.models&&Object.entries(r.options.llm.models).forEach(([e,t])=>{this.defaultModel||(this.defaultModel=e),t.proto=="anthropic"?this.models[e]=new P(this.ai,t.token,e):t.proto=="ollama"?this.models[e]=new w(this.ai,t.host,"not-needed",e):t.proto=="openai"&&(this.models[e]=new w(this.ai,t.host||null,t.token,e))})}embedWorker=null;embedQueue=new Map;embedId=0;models={};defaultModel;ask(r,e={}){const t=e.model||this.defaultModel;if(!this.models[t])throw new Error(`Model does not exist: ${t}`);let i=()=>{};return Object.assign(new Promise(async s=>{if(e.history||(e.history=[]),e.memory){e.system=(e.system||"")+`
16
16
  You have passive persistent memory never make any mention of your memory capabilities and what you can/cannot remember
17
17
  `;const o=async(l,u,c=50)=>{const[m,h]=await Promise.all([u?this.embedding(u):Promise.resolve(null),l?this.embedding(l):Promise.resolve(null)]);return(e.memory||[]).map(p=>({...p,score:m?this.cosineSimilarity(p.embeddings[0],m[0].embedding):1})).filter(p=>p.score>=.8).map(p=>({...p,score:h?this.cosineSimilarity(p.embeddings[1],h[0].embedding):p.score})).filter(p=>p.score>=.2).toSorted((p,y)=>p.score-y.score).slice(0,c)},a=await o(r);a.length&&e.history.push({role:"assistant",content:`Things I remembered:
18
18
  `+a.map(l=>`${l.owner}: ${l.fact}`).join(`
@@ -24,7 +24,7 @@ ${l.map(p=>`${p.role}: ${p.content}`).join(`
24
24
  `)).flatMap(a=>[...a.split(/\s+/).filter(Boolean),`
25
25
  `]),o=[];for(let a=0;a<n.length;){let l="",u=a;for(;u<n.length;){const m=l+(l?" ":"")+n[u];if(this.estimateTokens(m.replace(/\s*\n\s*/g,`
26
26
  `))>e&&l)break;l=m,u++}const c=l.replace(/\s*\n\s*/g,`
27
- `).trim();c&&o.push(c),a=Math.max(u-t,u===a?a+1:u)}return o}embedding(r,e=500,t=50){const i=n=>new Promise((o,a)=>{const l=this.embedId++;this.embedQueue.set(l,{resolve:o,reject:a}),this.embedWorker?.postMessage({id:l,text:n,model:this.ai.options?.embedder||"bge-small-en-v1.5",path:this.ai.options.path})}),s=this.chunk(r,e,t);return Promise.all(s.map(async(n,o)=>({index:o,embedding:await i(n),text:n,tokens:this.estimateTokens(n)})))}estimateTokens(r){const e=JSON.stringify(r);return Math.ceil(e.length/4*1.2)}fuzzyMatch(r,...e){if(e.length<2)throw new Error("Requires at least 2 strings to compare");const t=(n,o=10)=>n.toLowerCase().split("").map((a,l)=>a.charCodeAt(0)*(l+1)%o/o).slice(0,o),i=t(r),s=e.map(n=>t(n)).map(n=>this.cosineSimilarity(i,n));return{avg:s.reduce((n,o)=>n+o,0)/s.length,max:Math.max(...s),similarities:s}}async json(r,e){let t=await this.ask(r,{system:"Respond using a JSON blob matching any provided examples",...e});if(!t)return{};const i=/```(?:.+)?\s*([\s\S]*?)```/.exec(t),s=i?i[1].trim():t;return f.JSONAttemptParse(s,{})}summarize(r,e,t){return this.ask(r,{system:`Generate a brief summary <= ${e} tokens. Output nothing else`,temperature:.3,...t})}}class P{constructor(r){this.ai=r}whisperPipeline;combineSpeakerTranscript(r,e){const t=new Map;let i=0;e.forEach(a=>{t.has(a.speaker)||t.set(a.speaker,++i)});const s=[];let n=-1,o="";return r.forEach(a=>{const l=a.timestamp[0],u=e.find(m=>l>=m.start&&l<=m.end),c=u?t.get(u.speaker):1;c!==n?(o&&s.push(`[speaker ${n}]: ${o.trim()}`),n=c,o=a.text):o+=a.text}),o&&s.push(`[speaker ${n}]: ${o.trim()}`),s.join(`
27
+ `).trim();c&&o.push(c),a=Math.max(u-t,u===a?a+1:u)}return o}embedding(r,e=500,t=50){const i=n=>new Promise((o,a)=>{const l=this.embedId++;this.embedQueue.set(l,{resolve:o,reject:a}),this.embedWorker?.postMessage({id:l,text:n,model:this.ai.options?.embedder||"bge-small-en-v1.5",path:this.ai.options.path})}),s=this.chunk(r,e,t);return Promise.all(s.map(async(n,o)=>({index:o,embedding:await i(n),text:n,tokens:this.estimateTokens(n)})))}estimateTokens(r){const e=JSON.stringify(r);return Math.ceil(e.length/4*1.2)}fuzzyMatch(r,...e){if(e.length<2)throw new Error("Requires at least 2 strings to compare");const t=(n,o=10)=>n.toLowerCase().split("").map((a,l)=>a.charCodeAt(0)*(l+1)%o/o).slice(0,o),i=t(r),s=e.map(n=>t(n)).map(n=>this.cosineSimilarity(i,n));return{avg:s.reduce((n,o)=>n+o,0)/s.length,max:Math.max(...s),similarities:s}}async json(r,e){let t=await this.ask(r,{system:"Respond using a JSON blob matching any provided examples",...e});if(!t)return{};const i=/```(?:.+)?\s*([\s\S]*?)```/.exec(t),s=i?i[1].trim():t;return f.JSONAttemptParse(s,{})}summarize(r,e,t){return this.ask(r,{system:`Generate a brief summary <= ${e} tokens. Output nothing else`,temperature:.3,...t})}}class q{constructor(r){this.ai=r}whisperPipeline;combineSpeakerTranscript(r,e){const t=new Map;let i=0;e.forEach(a=>{t.has(a.speaker)||t.set(a.speaker,++i)});const s=[];let n=-1,o="";return r.forEach(a=>{const l=a.timestamp[0],u=e.find(m=>l>=m.start&&l<=m.end),c=u?t.get(u.speaker):1;c!==n?(o&&s.push(`[speaker ${n}]: ${o.trim()}`),n=c,o=a.text):o+=a.text}),o&&s.push(`[speaker ${n}]: ${o.trim()}`),s.join(`
28
28
  `)}async canDiarization(){return new Promise(r=>{const e=S.spawn("python3",["-c","import pyannote.audio"]);e.on("close",t=>r(t===0)),e.on("error",()=>r(!1))})}async runDiarization(r){if(!await this.canDiarization())throw new Error("Pyannote is not installed: pip install pyannote.audio");const e=`
29
29
  import sys
30
30
  import json
@@ -43,5 +43,5 @@ for turn, _, speaker in diarization.itertracks(yield_label=True):
43
43
  })
44
44
 
45
45
  print(json.dumps(segments))
46
- `;return new Promise((t,i)=>{let s="";const n=S.spawn("python3",["-c",e,r]);n.stdout.on("data",o=>s+=o.toString()),n.stderr.on("data",o=>console.error(o.toString())),n.on("close",o=>{if(o===0)try{t(JSON.parse(s))}catch{i(new Error("Failed to parse diarization output"))}else i(new Error(`Python process exited with code ${o}`))}),n.on("error",i)})}asr(r,e={}){const{model:t=this.ai.options.asr||"whisper-base",speaker:i=!1}=e;let s=!1;const n=()=>{s=!0},o=new Promise(async(a,l)=>{try{if(s||(this.whisperPipeline||(this.whisperPipeline=await N.pipeline("automatic-speech-recognition",`Xenova/${t}`,{cache_dir:this.ai.options.path,quantized:!0})),s))return a(null);const u=await this.whisperPipeline(r,{return_timestamps:i?"word":!1,chunk_length_s:30});if(!i)return a(u.text?.trim()||null);if(s)return a(null);const c=await this.runDiarization(r);if(s)return a(null);const m=this.combineSpeakerTranscript(u.chunks||[],c);a(m)}catch(u){l(u)}});return Object.assign(o,{abort:n})}}class q{constructor(r){this.ai=r}ocr(r){let e;const t=new Promise(async i=>{e=await z.createWorker(this.ai.options.ocr||"eng",2,{cachePath:this.ai.options.path});const{data:s}=await e.recognize(r);await e.terminate(),i(s.text.trim()||null)});return Object.assign(t,{abort:()=>e?.terminate()})}}class W{constructor(r){this.options=r,r.path||(r.path=C.tmpdir()),process.env.TRANSFORMERS_CACHE=r.path,this.audio=new P(this),this.language=new J(this),this.vision=new q(this)}audio;language;vision}const O={name:"cli",description:"Use the command line interface, returns any output",args:{command:{type:"string",description:"Command to run",required:!0}},fn:d=>x.$`${d.command}`},I={name:"get_datetime",description:"Get current UTC date / time",args:{},fn:async()=>new Date().toUTCString()},H={name:"exec",description:"Run code/scripts",args:{language:{type:"string",description:"Execution language",enum:["cli","node","python"],required:!0},code:{type:"string",description:"Code to execute",required:!0}},fn:async(d,r,e)=>{try{switch(d.type){case"bash":return await O.fn({command:d.code},r,e);case"node":return await M.fn({code:d.code},r,e);case"python":return await $.fn({code:d.code},r,e)}}catch(t){return{error:t?.message||t.toString()}}}},F={name:"fetch",description:"Make HTTP request to URL",args:{url:{type:"string",description:"URL to fetch",required:!0},method:{type:"string",description:"HTTP method to use",enum:["GET","POST","PUT","DELETE"],default:"GET"},headers:{type:"object",description:"HTTP headers to send",default:{}},body:{type:"object",description:"HTTP body to send"}},fn:d=>new f.Http({url:d.url,headers:d.headers}).request({method:d.method||"GET",body:d.body})},M={name:"exec_javascript",description:"Execute commonjs javascript",args:{code:{type:"string",description:"CommonJS javascript",required:!0}},fn:async d=>{const r=f.consoleInterceptor(null),e=await f.fn({console:r},d.code,!0).catch(t=>r.output.error.push(t));return{...r.output,return:e,stdout:void 0,stderr:void 0}}},$={name:"exec_javascript",description:"Execute commonjs javascript",args:{code:{type:"string",description:"CommonJS javascript",required:!0}},fn:async d=>({result:x.$Sync`python -c "${d.code}"`})},B={name:"read_webpage",description:"Extract clean, structured content from a webpage. Use after web_search to read specific URLs",args:{url:{type:"string",description:"URL to extract content from",required:!0},focus:{type:"string",description:'Optional: What aspect to focus on (e.g., "pricing", "features", "contact info")'}},fn:async d=>{const r=await fetch(d.url,{headers:{"User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64)"}}).then(n=>n.text()).catch(n=>{throw new Error(`Failed to fetch: ${n.message}`)}),e=D.load(r);e('script, style, nav, footer, header, aside, iframe, noscript, [role="navigation"], [role="banner"], .ad, .ads, .cookie, .popup').remove();const t={title:e('meta[property="og:title"]').attr("content")||e("title").text()||"",description:e('meta[name="description"]').attr("content")||e('meta[property="og:description"]').attr("content")||""};let i="";const s=["article","main",'[role="main"]',".content",".post",".entry","body"];for(const n of s){const o=e(n).first();if(o.length&&o.text().trim().length>200){i=o.text();break}}return i||(i=e("body").text()),i=i.replace(/\s+/g," ").trim().slice(0,8e3),{url:d.url,title:t.title.trim(),description:t.description.trim(),content:i,focus:d.focus}}},G={name:"web_search",description:"Use duckduckgo (anonymous) to find find relevant online resources. Returns a list of URLs that works great with the `read_webpage` tool",args:{query:{type:"string",description:"Search string",required:!0},length:{type:"string",description:"Number of results to return",default:5}},fn:async d=>{const r=await fetch(`https://html.duckduckgo.com/html/?q=${encodeURIComponent(d.query)}`,{headers:{"User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64)","Accept-Language":"en-US,en;q=0.9"}}).then(s=>s.text());let e,t=/<a .*?href="(.+?)".+?<\/a>/g;const i=new f.ASet;for(;(e=t.exec(r))!==null;){let s=/uddg=(.+)&amp?/.exec(decodeURIComponent(e[1]))?.[1];if(s&&(s=decodeURIComponent(s)),s&&i.add(s),i.size>=(d.length||5))break}return i}};exports.Ai=W;exports.Anthropic=j;exports.Audio=P;exports.CliTool=O;exports.DateTimeTool=I;exports.ExecTool=H;exports.FetchTool=F;exports.JSTool=M;exports.LLMProvider=_;exports.OpenAi=w;exports.PythonTool=$;exports.ReadWebpageTool=B;exports.Vision=q;exports.WebSearchTool=G;
46
+ `;return new Promise((t,i)=>{let s="";const n=S.spawn("python3",["-c",e,r]);n.stdout.on("data",o=>s+=o.toString()),n.stderr.on("data",o=>console.error(o.toString())),n.on("close",o=>{if(o===0)try{t(JSON.parse(s))}catch{i(new Error("Failed to parse diarization output"))}else i(new Error(`Python process exited with code ${o}`))}),n.on("error",i)})}asr(r,e={}){const{model:t=this.ai.options.asr||"whisper-base",speaker:i=!1}=e;let s=!1;const n=()=>{s=!0},o=new Promise(async(a,l)=>{try{if(s||(this.whisperPipeline||(this.whisperPipeline=await x.pipeline("automatic-speech-recognition",`Xenova/${t}`,{cache_dir:this.ai.options.path,quantized:!0})),s))return a(null);const u=await x.read_audio(r,16e3),c=await this.whisperPipeline(u,{return_timestamps:i?"word":!1,chunk_length_s:30});if(!i)return a(c.text?.trim()||null);if(s)return a(null);const m=await this.runDiarization(r);if(s)return a(null);const h=this.combineSpeakerTranscript(c.chunks||[],m);a(h)}catch(u){l(u)}});return Object.assign(o,{abort:n})}}class O{constructor(r){this.ai=r}ocr(r){let e;const t=new Promise(async i=>{e=await z.createWorker(this.ai.options.ocr||"eng",2,{cachePath:this.ai.options.path});const{data:s}=await e.recognize(r);await e.terminate(),i(s.text.trim()||null)});return Object.assign(t,{abort:()=>e?.terminate()})}}class W{constructor(r){this.options=r,r.path||(r.path=C.tmpdir()),process.env.TRANSFORMERS_CACHE=r.path,this.audio=new q(this),this.language=new J(this),this.vision=new O(this)}audio;language;vision}const M={name:"cli",description:"Use the command line interface, returns any output",args:{command:{type:"string",description:"Command to run",required:!0}},fn:d=>T.$`${d.command}`},I={name:"get_datetime",description:"Get current UTC date / time",args:{},fn:async()=>new Date().toUTCString()},H={name:"exec",description:"Run code/scripts",args:{language:{type:"string",description:"Execution language",enum:["cli","node","python"],required:!0},code:{type:"string",description:"Code to execute",required:!0}},fn:async(d,r,e)=>{try{switch(d.type){case"bash":return await M.fn({command:d.code},r,e);case"node":return await $.fn({code:d.code},r,e);case"python":return await A.fn({code:d.code},r,e)}}catch(t){return{error:t?.message||t.toString()}}}},F={name:"fetch",description:"Make HTTP request to URL",args:{url:{type:"string",description:"URL to fetch",required:!0},method:{type:"string",description:"HTTP method to use",enum:["GET","POST","PUT","DELETE"],default:"GET"},headers:{type:"object",description:"HTTP headers to send",default:{}},body:{type:"object",description:"HTTP body to send"}},fn:d=>new f.Http({url:d.url,headers:d.headers}).request({method:d.method||"GET",body:d.body})},$={name:"exec_javascript",description:"Execute commonjs javascript",args:{code:{type:"string",description:"CommonJS javascript",required:!0}},fn:async d=>{const r=f.consoleInterceptor(null),e=await f.fn({console:r},d.code,!0).catch(t=>r.output.error.push(t));return{...r.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 d=>({result:T.$Sync`python -c "${d.code}"`})},B={name:"read_webpage",description:"Extract clean, structured content from a webpage. Use after web_search to read specific URLs",args:{url:{type:"string",description:"URL to extract content from",required:!0},focus:{type:"string",description:'Optional: What aspect to focus on (e.g., "pricing", "features", "contact info")'}},fn:async d=>{const r=await fetch(d.url,{headers:{"User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64)"}}).then(n=>n.text()).catch(n=>{throw new Error(`Failed to fetch: ${n.message}`)}),e=D.load(r);e('script, style, nav, footer, header, aside, iframe, noscript, [role="navigation"], [role="banner"], .ad, .ads, .cookie, .popup').remove();const t={title:e('meta[property="og:title"]').attr("content")||e("title").text()||"",description:e('meta[name="description"]').attr("content")||e('meta[property="og:description"]').attr("content")||""};let i="";const s=["article","main",'[role="main"]',".content",".post",".entry","body"];for(const n of s){const o=e(n).first();if(o.length&&o.text().trim().length>200){i=o.text();break}}return i||(i=e("body").text()),i=i.replace(/\s+/g," ").trim().slice(0,8e3),{url:d.url,title:t.title.trim(),description:t.description.trim(),content:i,focus:d.focus}}},G={name:"web_search",description:"Use duckduckgo (anonymous) to find find relevant online resources. Returns a list of URLs that works great with the `read_webpage` tool",args:{query:{type:"string",description:"Search string",required:!0},length:{type:"string",description:"Number of results to return",default:5}},fn:async d=>{const r=await fetch(`https://html.duckduckgo.com/html/?q=${encodeURIComponent(d.query)}`,{headers:{"User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64)","Accept-Language":"en-US,en;q=0.9"}}).then(s=>s.text());let e,t=/<a .*?href="(.+?)".+?<\/a>/g;const i=new f.ASet;for(;(e=t.exec(r))!==null;){let s=/uddg=(.+)&amp?/.exec(decodeURIComponent(e[1]))?.[1];if(s&&(s=decodeURIComponent(s)),s&&i.add(s),i.size>=(d.length||5))break}return i}};exports.Ai=W;exports.Anthropic=P;exports.Audio=q;exports.CliTool=M;exports.DateTimeTool=I;exports.ExecTool=H;exports.FetchTool=F;exports.JSTool=$;exports.LLMProvider=_;exports.OpenAi=w;exports.PythonTool=A;exports.ReadWebpageTool=B;exports.Vision=O;exports.WebSearchTool=G;
47
47
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../src/provider.ts","../src/antrhopic.ts","../src/open-ai.ts","../src/llm.ts","../src/audio.ts","../src/vision.ts","../src/ai.ts","../src/tools.ts"],"sourcesContent":["import {AbortablePromise} from './ai.ts';\nimport {LLMMessage, LLMRequest} from './llm.ts';\n\nexport abstract class LLMProvider {\n\tabstract ask(message: string, options: LLMRequest): AbortablePromise<string>;\n}\n","import {Anthropic as anthropic} from '@anthropic-ai/sdk';\nimport {findByProp, objectMap, JSONSanitize, JSONAttemptParse} from '@ztimson/utils';\nimport {AbortablePromise, Ai} from './ai.ts';\nimport {LLMMessage, LLMRequest} from './llm.ts';\nimport {LLMProvider} from './provider.ts';\n\nexport class Anthropic extends LLMProvider {\n\tclient!: anthropic;\n\n\tconstructor(public readonly ai: Ai, public readonly apiToken: string, public model: string) {\n\t\tsuper();\n\t\tthis.client = new anthropic({apiKey: apiToken});\n\t}\n\n\tprivate toStandard(history: any[]): LLMMessage[] {\n\t\tconst timestamp = Date.now();\n\t\tconst messages: LLMMessage[] = [];\n\t\tfor(let h of history) {\n\t\t\tif(typeof h.content == 'string') {\n\t\t\t\tmessages.push(<any>{timestamp, ...h});\n\t\t\t} else {\n\t\t\t\tconst textContent = h.content?.filter((c: any) => c.type == 'text').map((c: any) => c.text).join('\\n\\n');\n\t\t\t\tif(textContent) messages.push({timestamp, role: h.role, content: textContent});\n\t\t\t\th.content.forEach((c: any) => {\n\t\t\t\t\tif(c.type == 'tool_use') {\n\t\t\t\t\t\tmessages.push({timestamp, role: 'tool', id: c.id, name: c.name, args: c.input, content: undefined});\n\t\t\t\t\t} else if(c.type == 'tool_result') {\n\t\t\t\t\t\tconst m: any = messages.findLast(m => (<any>m).id == c.tool_use_id);\n\t\t\t\t\t\tif(m) m[c.is_error ? 'error' : 'content'] = c.content;\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t\treturn messages;\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<string> {\n\t\tconst controller = new AbortController();\n\t\treturn Object.assign(new Promise<any>(async (res) => {\n\t\t\tlet history = this.fromStandard([...options.history || [], {role: 'user', content: message, timestamp: Date.now()}]);\n\t\t\tconst tools = options.tools || this.ai.options.llm?.tools || [];\n\t\t\tconst requestParams: any = {\n\t\t\t\tmodel: options.model || this.model,\n\t\t\t\tmax_tokens: options.max_tokens || this.ai.options.llm?.max_tokens || 4096,\n\t\t\t\tsystem: options.system || this.ai.options.llm?.system || '',\n\t\t\t\ttemperature: options.temperature || this.ai.options.llm?.temperature || 0.7,\n\t\t\t\ttools: tools.map(t => ({\n\t\t\t\t\tname: t.name,\n\t\t\t\t\tdescription: t.description,\n\t\t\t\t\tinput_schema: {\n\t\t\t\t\t\ttype: 'object',\n\t\t\t\t\t\tproperties: t.args ? objectMap(t.args, (key, value) => ({...value, required: undefined})) : {},\n\t\t\t\t\t\trequired: t.args ? Object.entries(t.args).filter(t => t[1].required).map(t => t[0]) : []\n\t\t\t\t\t},\n\t\t\t\t\tfn: undefined\n\t\t\t\t})),\n\t\t\t\tmessages: history,\n\t\t\t\tstream: !!options.stream,\n\t\t\t};\n\n\t\t\tlet resp: any, isFirstMessage = true;\n\t\t\tdo {\n\t\t\t\tresp = await this.client.messages.create(requestParams).catch(err => {\n\t\t\t\t\terr.message += `\\n\\nMessages:\\n${JSON.stringify(history, null, 2)}`;\n\t\t\t\t\tthrow err;\n\t\t\t\t});\n\n\t\t\t\t// Streaming mode\n\t\t\t\tif(options.stream) {\n\t\t\t\t\tif(!isFirstMessage) options.stream({text: '\\n\\n'});\n\t\t\t\t\telse isFirstMessage = false;\n\t\t\t\t\tresp.content = [];\n\t\t\t\t\tfor await (const chunk of resp) {\n\t\t\t\t\t\tif(controller.signal.aborted) break;\n\t\t\t\t\t\tif(chunk.type === 'content_block_start') {\n\t\t\t\t\t\t\tif(chunk.content_block.type === 'text') {\n\t\t\t\t\t\t\t\tresp.content.push({type: 'text', text: ''});\n\t\t\t\t\t\t\t} else if(chunk.content_block.type === 'tool_use') {\n\t\t\t\t\t\t\t\tresp.content.push({type: 'tool_use', id: chunk.content_block.id, name: chunk.content_block.name, input: <any>''});\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else if(chunk.type === 'content_block_delta') {\n\t\t\t\t\t\t\tif(chunk.delta.type === 'text_delta') {\n\t\t\t\t\t\t\t\tconst text = chunk.delta.text;\n\t\t\t\t\t\t\t\tresp.content.at(-1).text += text;\n\t\t\t\t\t\t\t\toptions.stream({text});\n\t\t\t\t\t\t\t} else if(chunk.delta.type === 'input_json_delta') {\n\t\t\t\t\t\t\t\tresp.content.at(-1).input += chunk.delta.partial_json;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else if(chunk.type === 'content_block_stop') {\n\t\t\t\t\t\t\tconst last = resp.content.at(-1);\n\t\t\t\t\t\t\tif(last.input != null) last.input = last.input ? JSONAttemptParse(last.input, {}) : {};\n\t\t\t\t\t\t} else if(chunk.type === 'message_stop') {\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Run tools\n\t\t\t\tconst toolCalls = resp.content.filter((c: any) => c.type === 'tool_use');\n\t\t\t\tif(toolCalls.length && !controller.signal.aborted) {\n\t\t\t\t\thistory.push({role: 'assistant', content: resp.content});\n\t\t\t\t\tconst results = await Promise.all(toolCalls.map(async (toolCall: any) => {\n\t\t\t\t\t\tconst tool = tools.find(findByProp('name', toolCall.name));\n\t\t\t\t\t\tif(options.stream) options.stream({tool: toolCall.name});\n\t\t\t\t\t\tif(!tool) return {tool_use_id: toolCall.id, is_error: true, content: 'Tool not found'};\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tconst result = await tool.fn(toolCall.input, options?.stream, this.ai);\n\t\t\t\t\t\t\treturn {type: 'tool_result', tool_use_id: toolCall.id, content: JSONSanitize(result)};\n\t\t\t\t\t\t} catch (err: any) {\n\t\t\t\t\t\t\treturn {type: 'tool_result', tool_use_id: toolCall.id, is_error: true, content: err?.message || err?.toString() || 'Unknown'};\n\t\t\t\t\t\t}\n\t\t\t\t\t}));\n\t\t\t\t\thistory.push({role: 'user', content: results});\n\t\t\t\t\trequestParams.messages = history;\n\t\t\t\t}\n\t\t\t} while (!controller.signal.aborted && resp.content.some((c: any) => c.type === 'tool_use'));\n\t\t\thistory.push({role: 'assistant', content: resp.content.filter((c: any) => c.type == 'text').map((c: any) => c.text).join('\\n\\n')});\n\t\t\thistory = this.toStandard(history);\n\n\t\t\tif(options.stream) options.stream({done: true});\n\t\t\tif(options.history) options.history.splice(0, options.history.length, ...history);\n\t\t\tres(history.at(-1)?.content);\n\t\t}), {abort: () => controller.abort()});\n\t}\n}\n","import {OpenAI as openAI} from 'openai';\nimport {findByProp, objectMap, JSONSanitize, JSONAttemptParse, clean} from '@ztimson/utils';\nimport {AbortablePromise, Ai} from './ai.ts';\nimport {LLMMessage, LLMRequest} from './llm.ts';\nimport {LLMProvider} from './provider.ts';\n\nexport class OpenAi extends LLMProvider {\n\tclient!: openAI;\n\n\tconstructor(public readonly ai: Ai, public readonly host: string | null, public readonly token: string, public model: string) {\n\t\tsuper();\n\t\tthis.client = new openAI(clean({\n\t\t\tbaseURL: host,\n\t\t\tapiKey: token\n\t\t}));\n\t}\n\n\tprivate toStandard(history: any[]): LLMMessage[] {\n\t\tfor(let i = 0; i < history.length; i++) {\n\t\t\tconst h = history[i];\n\t\t\tif(h.role === 'assistant' && h.tool_calls) {\n\t\t\t\tconst tools = h.tool_calls.map((tc: any) => ({\n\t\t\t\t\trole: 'tool',\n\t\t\t\t\tid: tc.id,\n\t\t\t\t\tname: tc.function.name,\n\t\t\t\t\targs: JSONAttemptParse(tc.function.arguments, {}),\n\t\t\t\t\ttimestamp: h.timestamp\n\t\t\t\t}));\n\t\t\t\thistory.splice(i, 1, ...tools);\n\t\t\t\ti += tools.length - 1;\n\t\t\t} else if(h.role === 'tool' && h.content) {\n\t\t\t\tconst record = history.find(h2 => h.tool_call_id == h2.id);\n\t\t\t\tif(record) {\n\t\t\t\t\tif(h.content.includes('\"error\":')) record.error = h.content;\n\t\t\t\t\telse record.content = h.content;\n\t\t\t\t}\n\t\t\t\thistory.splice(i, 1);\n\t\t\t\ti--;\n\t\t\t}\n\t\t\tif(!history[i]?.timestamp) history[i].timestamp = Date.now();\n\t\t}\n\t\treturn history;\n\t}\n\n\tprivate fromStandard(history: LLMMessage[]): any[] {\n\t\treturn history.reduce((result, h) => {\n\t\t\tif(h.role === 'tool') {\n\t\t\t\tresult.push({\n\t\t\t\t\trole: 'assistant',\n\t\t\t\t\tcontent: null,\n\t\t\t\t\ttool_calls: [{ id: h.id, type: 'function', function: { name: h.name, arguments: JSON.stringify(h.args) } }],\n\t\t\t\t\trefusal: null,\n\t\t\t\t\tannotations: []\n\t\t\t\t}, {\n\t\t\t\t\trole: 'tool',\n\t\t\t\t\ttool_call_id: h.id,\n\t\t\t\t\tcontent: h.error || h.content\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\tconst {timestamp, ...rest} = h;\n\t\t\t\tresult.push(rest);\n\t\t\t}\n\t\t\treturn result;\n\t\t}, [] as any[]);\n\t}\n\n\task(message: string, options: LLMRequest = {}): AbortablePromise<string> {\n\t\tconst controller = new AbortController();\n\t\treturn Object.assign(new Promise<any>(async (res, rej) => {\n\t\t\tif(options.system && options.history?.[0]?.role != 'system') options.history?.splice(0, 0, {role: 'system', content: options.system, timestamp: Date.now()});\n\t\t\tlet history = this.fromStandard([...options.history || [], {role: 'user', content: message, timestamp: Date.now()}]);\n\t\t\tconst tools = options.tools || this.ai.options.llm?.tools || [];\n\t\t\tconst requestParams: any = {\n\t\t\t\tmodel: options.model || this.model,\n\t\t\t\tmessages: history,\n\t\t\t\tstream: !!options.stream,\n\t\t\t\tmax_tokens: options.max_tokens || this.ai.options.llm?.max_tokens || 4096,\n\t\t\t\ttemperature: options.temperature || this.ai.options.llm?.temperature || 0.7,\n\t\t\t\ttools: tools.map(t => ({\n\t\t\t\t\ttype: 'function',\n\t\t\t\t\tfunction: {\n\t\t\t\t\t\tname: t.name,\n\t\t\t\t\t\tdescription: t.description,\n\t\t\t\t\t\tparameters: {\n\t\t\t\t\t\t\ttype: 'object',\n\t\t\t\t\t\t\tproperties: t.args ? objectMap(t.args, (key, value) => ({...value, required: undefined})) : {},\n\t\t\t\t\t\t\trequired: t.args ? Object.entries(t.args).filter(t => t[1].required).map(t => t[0]) : []\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}))\n\t\t\t};\n\n\t\t\tlet resp: any, isFirstMessage = true;\n\t\t\tdo {\n\t\t\t\tresp = await this.client.chat.completions.create(requestParams).catch(err => {\n\t\t\t\t\terr.message += `\\n\\nMessages:\\n${JSON.stringify(history, null, 2)}`;\n\t\t\t\t\tthrow err;\n\t\t\t\t});\n\n\t\t\t\tif(options.stream) {\n\t\t\t\t\tif(!isFirstMessage) options.stream({text: '\\n\\n'});\n\t\t\t\t\telse isFirstMessage = false;\n\t\t\t\t\tresp.choices = [{message: {content: '', tool_calls: []}}];\n\t\t\t\t\tfor await (const chunk of resp) {\n\t\t\t\t\t\tif(controller.signal.aborted) break;\n\t\t\t\t\t\tif(chunk.choices[0].delta.content) {\n\t\t\t\t\t\t\tresp.choices[0].message.content += chunk.choices[0].delta.content;\n\t\t\t\t\t\t\toptions.stream({text: chunk.choices[0].delta.content});\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif(chunk.choices[0].delta.tool_calls) {\n\t\t\t\t\t\t\tresp.choices[0].message.tool_calls = chunk.choices[0].delta.tool_calls;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tconst toolCalls = resp.choices[0].message.tool_calls || [];\n\t\t\t\tif(toolCalls.length && !controller.signal.aborted) {\n\t\t\t\t\thistory.push(resp.choices[0].message);\n\t\t\t\t\tconst results = await Promise.all(toolCalls.map(async (toolCall: any) => {\n\t\t\t\t\t\tconst tool = tools?.find(findByProp('name', toolCall.function.name));\n\t\t\t\t\t\tif(options.stream) options.stream({tool: toolCall.function.name});\n\t\t\t\t\t\tif(!tool) return {role: 'tool', tool_call_id: toolCall.id, content: '{\"error\": \"Tool not found\"}'};\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tconst args = JSONAttemptParse(toolCall.function.arguments, {});\n\t\t\t\t\t\t\tconst result = await tool.fn(args, options.stream, 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\t\t\thistory.push({role: 'assistant', content: resp.choices[0].message.content || ''});\n\t\t\thistory = this.toStandard(history);\n\n\t\t\tif(options.stream) options.stream({done: true});\n\t\t\tif(options.history) options.history.splice(0, options.history.length, ...history);\n\t\t\tres(history.at(-1)?.content);\n\t\t}), {abort: () => controller.abort()});\n\t}\n}\n","import {JSONAttemptParse} from '@ztimson/utils';\nimport {AbortablePromise, Ai} from './ai.ts';\nimport {Anthropic} from './antrhopic.ts';\nimport {OpenAi} from './open-ai.ts';\nimport {LLMProvider} from './provider.ts';\nimport {AiTool} from './tools.ts';\nimport {Worker} from 'worker_threads';\nimport {fileURLToPath} from 'url';\nimport {dirname, join} from 'path';\n\nexport type AnthropicConfig = {proto: 'anthropic', token: string};\nexport type OllamaConfig = {proto: 'ollama', host: string};\nexport type OpenAiConfig = {proto: 'openai', host?: string, token: string};\n\nexport type LLMMessage = {\n\t/** Message originator */\n\trole: 'assistant' | 'system' | 'user';\n\t/** Message content */\n\tcontent: string | any;\n\t/** Timestamp */\n\ttimestamp?: number;\n} | {\n\t/** Tool call */\n\trole: 'tool';\n\t/** Unique ID for call */\n\tid: string;\n\t/** Tool that was run */\n\tname: string;\n\t/** Tool arguments */\n\targs: any;\n\t/** Tool result */\n\tcontent: undefined | string;\n\t/** Tool error */\n\terror?: undefined | string;\n\t/** Timestamp */\n\ttimestamp?: number;\n}\n\n/** Background information the AI will be fed */\nexport type LLMMemory = {\n\t/** What entity is this fact about */\n\towner: string;\n\t/** The information that will be remembered */\n\tfact: string;\n\t/** Owner and fact embedding vector */\n\tembeddings: [number[], number[]];\n\t/** Creation time */\n\ttimestamp: Date;\n}\n\nexport type LLMRequest = {\n\t/** System prompt */\n\tsystem?: string;\n\t/** Message history */\n\thistory?: LLMMessage[];\n\t/** Max tokens for request */\n\tmax_tokens?: number;\n\t/** 0 = Rigid Logic, 1 = Balanced, 2 = Hyper Creative **/\n\ttemperature?: number;\n\t/** Available tools */\n\ttools?: AiTool[];\n\t/** LLM model */\n\tmodel?: string;\n\t/** Stream response */\n\tstream?: (chunk: {text?: string, tool?: string, done?: true}) => any;\n\t/** Compress old messages in the chat to free up context */\n\tcompress?: {\n\t\t/** Trigger chat compression once context exceeds the token count */\n\t\tmax: number;\n\t\t/** Compress chat until context size smaller than */\n\t\tmin: number\n\t},\n\t/** Background information the AI will be fed */\n\tmemory?: LLMMemory[],\n}\n\nclass LLM {\n\tprivate embedWorker: Worker | null = null;\n\tprivate embedQueue = new Map<number, { resolve: (value: number[]) => void; reject: (error: any) => void }>();\n\tprivate embedId = 0;\n\tprivate models: {[model: string]: LLMProvider} = {};\n\tprivate defaultModel!: string;\n\n\tconstructor(public readonly ai: Ai) {\n\t\tthis.embedWorker = new Worker(join(dirname(fileURLToPath(import.meta.url)), 'embedder.js'));\n\t\tthis.embedWorker.on('message', ({ id, embedding }) => {\n\t\t\tconst pending = this.embedQueue.get(id);\n\t\t\tif (pending) {\n\t\t\t\tpending.resolve(embedding);\n\t\t\t\tthis.embedQueue.delete(id);\n\t\t\t}\n\t\t});\n\n\t\tif(!ai.options.llm?.models) return;\n\t\tObject.entries(ai.options.llm.models).forEach(([model, config]) => {\n\t\t\tif(!this.defaultModel) this.defaultModel = model;\n\t\t\tif(config.proto == 'anthropic') this.models[model] = new Anthropic(this.ai, config.token, model);\n\t\t\telse if(config.proto == 'ollama') this.models[model] = new OpenAi(this.ai, config.host, 'not-needed', model);\n\t\t\telse if(config.proto == 'openai') this.models[model] = new OpenAi(this.ai, config.host || null, config.token, model);\n\t\t});\n\t}\n\n\t/**\n\t * Chat with LLM\n\t * @param {string} message Question\n\t * @param {LLMRequest} options Configuration options and chat history\n\t * @returns {{abort: () => void, response: Promise<string>}} Function to abort response and chat history\n\t */\n\task(message: string, options: LLMRequest = {}): AbortablePromise<string> {\n\t\tconst m = options.model || this.defaultModel;\n\t\tif(!this.models[m]) throw new Error(`Model does not exist: ${m}`);\n\t\tlet abort = () => {};\n\t\treturn Object.assign(new Promise<string>(async res => {\n\t\t\tif(!options.history) options.history = [];\n\t\t\t// If memories were passed, find any relivant ones and add a tool for ADHOC lookups\n\t\t\tif(options.memory) {\n\t\t\t\toptions.system = (options.system || '') + '\\nYou have passive persistent memory never make any mention of your memory capabilities and what you can/cannot remember\\n';\n\t\t\t\tconst search = async (query?: string | null, subject?: string | null, limit = 50) => {\n\t\t\t\t\tconst [o, q] = await Promise.all([\n\t\t\t\t\t\tsubject ? this.embedding(subject) : Promise.resolve(null),\n\t\t\t\t\t\tquery ? this.embedding(query) : Promise.resolve(null),\n\t\t\t\t\t]);\n\t\t\t\t\treturn (options.memory || [])\n\t\t\t\t\t\t.map(m => ({...m, score: o ? this.cosineSimilarity(m.embeddings[0], o[0].embedding) : 1}))\n\t\t\t\t\t\t.filter((m: any) => m.score >= 0.8)\n\t\t\t\t\t\t.map((m: any) => ({...m, score: q ? this.cosineSimilarity(m.embeddings[1], q[0].embedding) : m.score}))\n\t\t\t\t\t\t.filter((m: any) => m.score >= 0.2)\n\t\t\t\t\t\t.toSorted((a: any, b: any) => a.score - b.score)\n\t\t\t\t\t\t.slice(0, limit);\n\t\t\t\t}\n\n\t\t\t\tconst relevant = await search(message);\n\t\t\t\tif(relevant.length) options.history.push({role: 'assistant', content: 'Things I remembered:\\n' + relevant.map(m => `${m.owner}: ${m.fact}`).join('\\n')});\n\t\t\t\toptions.tools = [...options.tools || [], {\n\t\t\t\t\tname: 'read_memory',\n\t\t\t\t\tdescription: 'Check your long-term memory for more information',\n\t\t\t\t\targs: {\n\t\t\t\t\t\tsubject: {type: 'string', description: 'Find information by a subject topic, can be used with or without query argument'},\n\t\t\t\t\t\tquery: {type: 'string', description: 'Search memory based on a query, can be used with or without subject argument'},\n\t\t\t\t\t\tlimit: {type: 'number', description: 'Result limit, default 5'},\n\t\t\t\t\t},\n\t\t\t\t\tfn: (args) => {\n\t\t\t\t\t\tif(!args.subject && !args.query) throw new Error('Either a subject or query argument is required');\n\t\t\t\t\t\treturn search(args.query, args.subject, args.limit || 5);\n\t\t\t\t\t}\n\t\t\t\t}];\n\t\t\t}\n\n\t\t\t// Ask\n\t\t\tconst resp = await this.models[m].ask(message, options);\n\n\t\t\t// Remove any memory calls\n\t\t\tif(options.memory) {\n\t\t\t\tconst i = options.history?.findIndex((h: any) => h.role == 'assistant' && h.content.startsWith('Things I remembered:'));\n\t\t\t\tif(i != null && i >= 0) options.history?.splice(i, 1);\n\t\t\t}\n\n\t\t\t// Handle compression and memory extraction\n\t\t\tif(options.compress || options.memory) {\n\t\t\t\tlet compressed = null;\n\t\t\t\tif(options.compress) {\n\t\t\t\t\tcompressed = await this.ai.language.compressHistory(options.history, options.compress.max, options.compress.min, options);\n\t\t\t\t\toptions.history.splice(0, options.history.length, ...compressed.history);\n\t\t\t\t} else {\n\t\t\t\t\tconst i = options.history?.findLastIndex(m => m.role == 'user') ?? -1;\n\t\t\t\t\tcompressed = await this.ai.language.compressHistory(i != -1 ? options.history.slice(i) : options.history, 0, 0, options);\n\t\t\t\t}\n\t\t\t\tif(options.memory) {\n\t\t\t\t\tconst updated = options.memory\n\t\t\t\t\t\t.filter(m => !compressed.memory.some(m2 => this.cosineSimilarity(m.embeddings[1], m2.embeddings[1]) > 0.8))\n\t\t\t\t\t\t.concat(compressed.memory);\n\t\t\t\t\toptions.memory.splice(0, options.memory.length, ...updated);\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn res(resp);\n\t\t}), {abort});\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 Leave messages less than the token minimum, summarize the rest\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<{history: LLMMessage[], memory: LLMMemory[]}> {\n\t\tif(this.estimateTokens(history) < max) return {history, memory: []};\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, memory: []};\n\t\tconst system = history[0].role == 'system' ? history[0] : null,\n\t\t\trecent = 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: any = await this.json(`Create the smallest summary possible, no more than 500 tokens. Create a list of NEW facts (split by subject [pro]noun and fact) about what you learned from this conversation that you didn't already know or get from a tool call or system prompt. Focus only on new information about people, topics, or facts. Avoid generating facts about the AI. Match this format: {summary: string, facts: [[subject, fact]]}\\n\\n${process.map(m => `${m.role}: ${m.content}`).join('\\n\\n')}`, {model: options?.model, temperature: options?.temperature || 0.3});\n\t\tconst timestamp = new Date();\n\t\tconst memory = await Promise.all((summary?.facts || [])?.map(async ([owner, fact]: [string, string]) => {\n\t\t\tconst e = await Promise.all([this.embedding(owner), this.embedding(`${owner}: ${fact}`)]);\n\t\t\treturn {owner, fact, embeddings: [e[0][0].embedding, e[1][0].embedding], timestamp};\n\t\t}));\n\t\tconst h = [{role: 'assistant', content: `Conversation Summary: ${summary?.summary}`, timestamp: Date.now()}, ...recent];\n\t\tif(system) h.splice(0, 0, system);\n\t\treturn {history: <any>h, memory};\n\t}\n\n\t/**\n\t * Compare the difference between embeddings (calculates the angle between two vectors)\n\t * @param {number[]} v1 First embedding / vector comparison\n\t * @param {number[]} v2 Second embedding / vector for comparison\n\t * @returns {number} Similarity values 0-1: 0 = unique, 1 = identical\n\t */\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\t/**\n\t * Chunk text into parts for AI digestion\n\t * @param {object | string} target Item that will be chunked (objects get converted)\n\t * @param {number} maxTokens Chunking size. More = better context, less = more specific (Search by paragraphs or lines)\n\t * @param {number} overlapTokens Includes previous X tokens to provide continuity to AI (In addition to max tokens)\n\t * @returns {string[]} Chunked strings\n\t */\n\tchunk(target: object | string, maxTokens = 500, overlapTokens = 50): string[] {\n\t\tconst objString = (obj: any, path = ''): string[] => {\n\t\t\tif(!obj) return [];\n\t\t\treturn Object.entries(obj).flatMap(([key, value]) => {\n\t\t\t\tconst p = path ? `${path}${isNaN(+key) ? `.${key}` : `[${key}]`}` : key;\n\t\t\t\tif(typeof value === 'object' && !Array.isArray(value)) return objString(value, p);\n\t\t\t\treturn `${p}: ${Array.isArray(value) ? value.join(', ') : value}`;\n\t\t\t});\n\t\t};\n\t\tconst lines = typeof target === 'object' ? objString(target) : target.split('\\n');\n\t\tconst tokens = lines.flatMap(l => [...l.split(/\\s+/).filter(Boolean), '\\n']);\n\t\tconst chunks: string[] = [];\n\t\tfor(let i = 0; i < tokens.length;) {\n\t\t\tlet text = '', j = i;\n\t\t\twhile(j < tokens.length) {\n\t\t\t\tconst next = text + (text ? ' ' : '') + tokens[j];\n\t\t\t\tif(this.estimateTokens(next.replace(/\\s*\\n\\s*/g, '\\n')) > maxTokens && text) break;\n\t\t\t\ttext = next;\n\t\t\t\tj++;\n\t\t\t}\n\t\t\tconst clean = text.replace(/\\s*\\n\\s*/g, '\\n').trim();\n\t\t\tif(clean) chunks.push(clean);\n\t\t\ti = Math.max(j - overlapTokens, j === i ? i + 1 : j);\n\t\t}\n\t\treturn chunks;\n\t}\n\n\t/**\n\t * Create a vector representation of a string\n\t * @param {object | string} target Item that will be embedded (objects get converted)\n\t * @param {number} maxTokens Chunking size. More = better context, less = more specific (Search by paragraphs or lines)\n\t * @param {number} overlapTokens Includes previous X tokens to provide continuity to AI (In addition to max tokens)\n\t * @returns {Promise<Awaited<{index: number, embedding: number[], text: string, tokens: number}>[]>} Chunked embeddings\n\t */\n\tembedding(target: object | string, maxTokens = 500, overlapTokens = 50) {\n\t\tconst embed = (text: string): Promise<number[]> => {\n\t\t\treturn new Promise((resolve, reject) => {\n\t\t\t\tconst id = this.embedId++;\n\t\t\t\tthis.embedQueue.set(id, { resolve, reject });\n\t\t\t\tthis.embedWorker?.postMessage({\n\t\t\t\t\tid,\n\t\t\t\t\ttext,\n\t\t\t\t\tmodel: this.ai.options?.embedder || 'bge-small-en-v1.5',\n\t\t\t\t\tpath: this.ai.options.path\n\t\t\t\t});\n\t\t\t});\n\t\t};\n\t\tconst chunks = this.chunk(target, maxTokens, overlapTokens);\n\t\treturn Promise.all(chunks.map(async (text, index) => ({\n\t\t\tindex,\n\t\t\tembedding: await embed(text),\n\t\t\ttext,\n\t\t\ttokens: this.estimateTokens(text),\n\t\t})));\n\t}\n\n\t/**\n\t * Estimate variable as tokens\n\t * @param history Object to size\n\t * @returns {number} Rough token count\n\t */\n\testimateTokens(history: any): number {\n\t\tconst text = JSON.stringify(history);\n\t\treturn Math.ceil((text.length / 4) * 1.2);\n\t}\n\n\t/**\n\t * Compare the difference between two strings using tensor math\n\t * @param target Text that will be 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): Promise<any> {\n\t\tlet resp = await this.ask(message, {system: 'Respond using a JSON blob matching any provided examples', ...options});\n\t\tif(!resp) return {};\n\t\tconst codeBlock = /```(?:.+)?\\s*([\\s\\S]*?)```/.exec(resp);\n\t\tconst jsonStr = codeBlock ? codeBlock[1].trim() : resp;\n\t\treturn JSONAttemptParse(jsonStr, {});\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}\n}\n\nexport default LLM;\n","import { spawn } from 'node:child_process';\nimport { pipeline } from '@xenova/transformers';\nimport { AbortablePromise, Ai } from './ai.ts';\n\nexport class Audio {\n\tprivate whisperPipeline: any;\n\n\tconstructor(private ai: Ai) {}\n\n\tprivate combineSpeakerTranscript(chunks: any[], speakers: any[]): string {\n\t\tconst speakerMap = new Map();\n\t\tlet speakerCount = 0;\n\t\tspeakers.forEach((seg: any) => {\n\t\t\tif(!speakerMap.has(seg.speaker)) speakerMap.set(seg.speaker, ++speakerCount);\n\t\t});\n\n\t\tconst lines: string[] = [];\n\t\tlet currentSpeaker = -1;\n\t\tlet currentText = '';\n\t\tchunks.forEach((chunk: any) => {\n\t\t\tconst time = chunk.timestamp[0];\n\t\t\tconst speaker = speakers.find((s: any) => time >= s.start && time <= s.end);\n\t\t\tconst speakerNum = speaker ? speakerMap.get(speaker.speaker) : 1;\n\t\t\tif (speakerNum !== currentSpeaker) {\n\t\t\t\tif(currentText) lines.push(`[speaker ${currentSpeaker}]: ${currentText.trim()}`);\n\t\t\t\tcurrentSpeaker = speakerNum;\n\t\t\t\tcurrentText = chunk.text;\n\t\t\t} else {\n\t\t\t\tcurrentText += chunk.text;\n\t\t\t}\n\t\t});\n\t\tif(currentText) lines.push(`[speaker ${currentSpeaker}]: ${currentText.trim()}`);\n\t\treturn lines.join('\\n');\n\t}\n\n\tasync canDiarization(): Promise<boolean> {\n\t\treturn new Promise((resolve) => {\n\t\t\tconst proc = spawn('python3', ['-c', 'import pyannote.audio']);\n\t\t\tproc.on('close', (code: number) => resolve(code === 0));\n\t\t\tproc.on('error', () => resolve(false));\n\t\t});\n\t}\n\n\tprivate async runDiarization(audioPath: string): Promise<any[]> {\n\t\tif(!await this.canDiarization()) throw new Error('Pyannote is not installed: pip install pyannote.audio');\n\t\tconst script = `\nimport sys\nimport json\nfrom pyannote.audio import Pipeline\n\nos.environ['TORCH_HOME'] = \"${this.ai.options.path}\"\npipeline = Pipeline.from_pretrained(\"pyannote/speaker-diarization-3.1\")\ndiarization = pipeline(sys.argv[1])\n\nsegments = []\nfor turn, _, speaker in diarization.itertracks(yield_label=True):\n segments.append({\n \"start\": turn.start,\n \"end\": turn.end,\n \"speaker\": speaker\n })\n\nprint(json.dumps(segments))\n`;\n\n\t\treturn new Promise((resolve, reject) => {\n\t\t\tlet output = '';\n\t\t\tconst proc = spawn('python3', ['-c', script, audioPath]);\n\t\t\tproc.stdout.on('data', (data: Buffer) => output += data.toString());\n\t\t\tproc.stderr.on('data', (data: Buffer) => console.error(data.toString()));\n\t\t\tproc.on('close', (code: number) => {\n\t\t\t\tif(code === 0) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tresolve(JSON.parse(output));\n\t\t\t\t\t} catch (err) {\n\t\t\t\t\t\treject(new Error('Failed to parse diarization output'));\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\treject(new Error(`Python process exited with code ${code}`));\n\t\t\t\t}\n\t\t\t});\n\n\t\t\tproc.on('error', reject);\n\t\t});\n\t}\n\n\tasr(path: string, options: { model?: string; speaker?: boolean } = {}): AbortablePromise<string | null> {\n\t\tconst { model = this.ai.options.asr || 'whisper-base', speaker = false } = options;\n\t\tlet aborted = false;\n\t\tconst abort = () => { aborted = true; };\n\n\t\tconst p = new Promise<string | null>(async (resolve, reject) => {\n\t\t\ttry {\n\t\t\t\tif(aborted) return resolve(null);\n\t\t\t\tif(!this.whisperPipeline) this.whisperPipeline = await pipeline('automatic-speech-recognition', `Xenova/${model}`, { cache_dir: this.ai.options.path, quantized: true });\n\n\t\t\t\t// Transcript\n\t\t\t\tif(aborted) return resolve(null);\n\t\t\t\tconst transcriptResult = await this.whisperPipeline(path, {return_timestamps: speaker ? 'word' : false, chunk_length_s: 30,});\n\t\t\t\tif(!speaker) return resolve(transcriptResult.text?.trim() || null);\n\n\t\t\t\t// Speaker Diarization\n\t\t\t\tif(aborted) return resolve(null);\n\t\t\t\tconst speakers = await this.runDiarization(path);\n\t\t\t\tif(aborted) return resolve(null);\n\t\t\t\tconst combined = this.combineSpeakerTranscript(transcriptResult.chunks || [], speakers);\n\t\t\t\tresolve(combined);\n\t\t\t} catch (err) {\n\t\t\t\treject(err);\n\t\t\t}\n\t\t});\n\n\t\treturn Object.assign(p, { abort });\n\t}\n}\n","import {createWorker} from 'tesseract.js';\nimport {AbortablePromise, Ai} from './ai.ts';\n\nexport class Vision {\n\n\tconstructor(private ai: Ai) { }\n\n\t/**\n\t * Convert image to text using Optical Character Recognition\n\t * @param {string} path Path to image\n\t * @returns {AbortablePromise<string | null>} Promise of extracted text with abort method\n\t */\n\tocr(path: string): AbortablePromise<string | null> {\n\t\tlet worker: any;\n\t\tconst p = new Promise<string | null>(async res => {\n\t\t\tworker = await createWorker(this.ai.options.ocr || 'eng', 2, {cachePath: this.ai.options.path});\n\t\t\tconst {data} = await worker.recognize(path);\n\t\t\tawait worker.terminate();\n\t\t\tres(data.text.trim() || null);\n\t\t});\n\t\treturn Object.assign(p, {abort: () => worker?.terminate()});\n\t}\n}\n","import * as os from 'node:os';\nimport LLM, {AnthropicConfig, OllamaConfig, OpenAiConfig, LLMRequest} from './llm';\nimport { Audio } from './audio.ts';\nimport {Vision} from './vision.ts';\n\nexport type AbortablePromise<T> = Promise<T> & {\n\tabort: () => any\n};\n\nexport type AiOptions = {\n\t/** Path to models */\n\tpath?: string;\n\t/** ASR model: whisper-tiny, whisper-base */\n\tasr?: string;\n\t/** Embedding model: all-MiniLM-L6-v2, bge-small-en-v1.5, bge-large-en-v1.5 */\n\tembedder?: string;\n\t/** Large language models, first is default */\n\tllm?: Omit<LLMRequest, 'model'> & {\n\t\tmodels: {[model: string]: AnthropicConfig | OllamaConfig | OpenAiConfig};\n\t}\n\t/** OCR model: eng, eng_best, eng_fast */\n\tocr?: string;\n}\n\nexport class Ai {\n\t/** Audio processing AI */\n\taudio!: Audio;\n\t/** Language processing AI */\n\tlanguage!: LLM;\n\t/** Vision processing AI */\n\tvision!: Vision;\n\n\tconstructor(public readonly options: AiOptions) {\n\t\tif(!options.path) options.path = os.tmpdir();\n\t\tprocess.env.TRANSFORMERS_CACHE = options.path;\n\t\tthis.audio = new Audio(this);\n\t\tthis.language = new LLM(this);\n\t\tthis.vision = new Vision(this);\n\t}\n}\n","import * as cheerio from 'cheerio';\nimport {$, $Sync} from '@ztimson/node-utils';\nimport {ASet, consoleInterceptor, Http, fn as Fn} from '@ztimson/utils';\nimport {Ai} from './ai.ts';\nimport {LLMRequest} from './llm.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, stream: LLMRequest['stream'], ai: Ai) => any | Promise<any>,\n};\n\nexport const CliTool: AiTool = {\n\tname: 'cli',\n\tdescription: 'Use the command line interface, returns any output',\n\targs: {command: {type: 'string', description: 'Command to run', required: true}},\n\tfn: (args: {command: string}) => $`${args.command}`\n}\n\nexport const DateTimeTool: AiTool = {\n\tname: 'get_datetime',\n\tdescription: 'Get current UTC date / time',\n\targs: {},\n\tfn: async () => new Date().toUTCString()\n}\n\nexport const ExecTool: AiTool = {\n\tname: 'exec',\n\tdescription: 'Run code/scripts',\n\targs: {\n\t\tlanguage: {type: 'string', description: 'Execution language', enum: ['cli', 'node', 'python'], required: true},\n\t\tcode: {type: 'string', description: 'Code to execute', required: true}\n\t},\n\tfn: async (args, stream, 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}, stream, ai);\n\t\t\t\tcase 'node':\n\t\t\t\t\treturn await JSTool.fn({code: args.code}, stream, ai);\n\t\t\t\tcase 'python': {\n\t\t\t\t\treturn await PythonTool.fn({code: args.code}, stream, ai);\n\t\t\t\t}\n\t\t\t}\n\t\t} catch(err: any) {\n\t\t\treturn {error: err?.message || err.toString()};\n\t\t}\n\t}\n}\n\nexport const FetchTool: AiTool = {\n\tname: 'fetch',\n\tdescription: 'Make HTTP request to URL',\n\targs: {\n\t\turl: {type: 'string', description: 'URL to fetch', required: true},\n\t\tmethod: {type: 'string', description: 'HTTP method to use', enum: ['GET', 'POST', 'PUT', 'DELETE'], default: 'GET'},\n\t\theaders: {type: 'object', description: 'HTTP headers to send', default: {}},\n\t\tbody: {type: 'object', description: 'HTTP body to send'},\n\t},\n\tfn: (args: {\n\t\turl: string;\n\t\tmethod: 'GET' | 'POST' | 'PUT' | 'DELETE';\n\t\theaders: {[key: string]: string};\n\t\tbody: any;\n\t}) => new Http({url: args.url, headers: args.headers}).request({method: args.method || 'GET', body: args.body})\n}\n\nexport const JSTool: AiTool = {\n\tname: 'exec_javascript',\n\tdescription: 'Execute commonjs javascript',\n\targs: {\n\t\tcode: {type: 'string', description: 'CommonJS javascript', required: true}\n\t},\n\tfn: async (args: {code: string}) => {\n\t\tconst console = consoleInterceptor(null);\n\t\tconst resp = await Fn<any>({console}, args.code, true).catch((err: any) => console.output.error.push(err));\n\t\treturn {...console.output, return: resp, stdout: undefined, stderr: undefined};\n\t}\n}\n\nexport const PythonTool: AiTool = {\n\tname: 'exec_javascript',\n\tdescription: 'Execute commonjs javascript',\n\targs: {\n\t\tcode: {type: 'string', description: 'CommonJS javascript', required: true}\n\t},\n\tfn: async (args: {code: string}) => ({result: $Sync`python -c \"${args.code}\"`})\n}\n\nexport const ReadWebpageTool: AiTool = {\n\tname: 'read_webpage',\n\tdescription: 'Extract clean, structured content from a webpage. Use after web_search to read specific URLs',\n\targs: {\n\t\turl: {type: 'string', description: 'URL to extract content from', required: true},\n\t\tfocus: {type: 'string', description: 'Optional: What aspect to focus on (e.g., \"pricing\", \"features\", \"contact info\")'}\n\t},\n\tfn: async (args: {url: string; focus?: string}) => {\n\t\tconst html = await fetch(args.url, {headers: {\"User-Agent\": \"Mozilla/5.0 (Windows NT 10.0; Win64; x64)\"}})\n\t\t\t.then(r => r.text()).catch(err => {throw new Error(`Failed to fetch: ${err.message}`)});\n\n\t\tconst $ = cheerio.load(html);\n\t\t$('script, style, nav, footer, header, aside, iframe, noscript, [role=\"navigation\"], [role=\"banner\"], .ad, .ads, .cookie, .popup').remove();\n\t\tconst metadata = {\n\t\t\ttitle: $('meta[property=\"og:title\"]').attr('content') || $('title').text() || '',\n\t\t\tdescription: $('meta[name=\"description\"]').attr('content') || $('meta[property=\"og:description\"]').attr('content') || '',\n\t\t};\n\n\t\tlet content = '';\n\t\tconst contentSelectors = ['article', 'main', '[role=\"main\"]', '.content', '.post', '.entry', 'body'];\n\t\tfor (const selector of contentSelectors) {\n\t\t\tconst el = $(selector).first();\n\t\t\tif (el.length && el.text().trim().length > 200) {\n\t\t\t\tcontent = el.text();\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tif (!content) content = $('body').text();\n\t\tcontent = content.replace(/\\s+/g, ' ').trim().slice(0, 8000);\n\n\t\treturn {url: args.url, title: metadata.title.trim(), description: metadata.description.trim(), content, focus: args.focus};\n\t}\n}\n\nexport const WebSearchTool: AiTool = {\n\tname: 'web_search',\n\tdescription: 'Use duckduckgo (anonymous) to find find relevant online resources. Returns a list of URLs that works great with the `read_webpage` tool',\n\targs: {\n\t\tquery: {type: 'string', description: 'Search string', required: true},\n\t\tlength: {type: 'string', description: 'Number of results to return', default: 5},\n\t},\n\tfn: async (args: {\n\t\tquery: string;\n\t\tlength: number;\n\t}) => {\n\t\tconst html = await fetch(`https://html.duckduckgo.com/html/?q=${encodeURIComponent(args.query)}`, {\n\t\t\theaders: {\"User-Agent\": \"Mozilla/5.0 (Windows NT 10.0; Win64; x64)\", \"Accept-Language\": \"en-US,en;q=0.9\"}\n\t\t}).then(resp => resp.text());\n\t\tlet match, regex = /<a .*?href=\"(.+?)\".+?<\\/a>/g;\n\t\tconst results = new ASet<string>();\n\t\twhile((match = regex.exec(html)) !== null) {\n\t\t\tlet url = /uddg=(.+)&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","timestamp","messages","h","textContent","c","m","i","message","options","controller","res","tools","requestParams","t","objectMap","key","value","resp","isFirstMessage","err","chunk","text","last","JSONAttemptParse","toolCalls","results","toolCall","tool","findByProp","result","JSONSanitize","OpenAi","host","token","openAI","clean","tc","record","h2","rest","rej","args","LLM","Worker","join","dirname","fileURLToPath","_documentCurrentScript","id","embedding","pending","config","abort","search","query","subject","limit","o","q","a","b","relevant","compressed","updated","m2","max","min","keep","tokens","system","recent","process","summary","memory","owner","fact","e","v1","v2","dotProduct","normA","normB","denominator","target","maxTokens","overlapTokens","objString","obj","path","p","l","chunks","j","next","embed","resolve","reject","index","searchTerms","vector","dimensions","char","v","similarities","refVector","acc","s","codeBlock","jsonStr","Audio","speakers","speakerMap","speakerCount","seg","lines","currentSpeaker","currentText","time","speaker","speakerNum","proc","spawn","code","audioPath","script","output","data","aborted","pipeline","transcriptResult","combined","Vision","worker","createWorker","Ai","os","CliTool","$","DateTimeTool","ExecTool","stream","JSTool","PythonTool","FetchTool","Http","console","consoleInterceptor","Fn","$Sync","ReadWebpageTool","html","r","cheerio","metadata","content","contentSelectors","selector","el","WebSearchTool","match","regex","ASet","url"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sources":["../src/provider.ts","../src/antrhopic.ts","../src/open-ai.ts","../src/llm.ts","../src/audio.ts","../src/vision.ts","../src/ai.ts","../src/tools.ts"],"sourcesContent":["import {AbortablePromise} from './ai.ts';\nimport {LLMMessage, LLMRequest} from './llm.ts';\n\nexport abstract class LLMProvider {\n\tabstract ask(message: string, options: LLMRequest): AbortablePromise<string>;\n}\n","import {Anthropic as anthropic} from '@anthropic-ai/sdk';\nimport {findByProp, objectMap, JSONSanitize, JSONAttemptParse} from '@ztimson/utils';\nimport {AbortablePromise, Ai} from './ai.ts';\nimport {LLMMessage, LLMRequest} from './llm.ts';\nimport {LLMProvider} from './provider.ts';\n\nexport class Anthropic extends LLMProvider {\n\tclient!: anthropic;\n\n\tconstructor(public readonly ai: Ai, public readonly apiToken: string, public model: string) {\n\t\tsuper();\n\t\tthis.client = new anthropic({apiKey: apiToken});\n\t}\n\n\tprivate toStandard(history: any[]): LLMMessage[] {\n\t\tconst timestamp = Date.now();\n\t\tconst messages: LLMMessage[] = [];\n\t\tfor(let h of history) {\n\t\t\tif(typeof h.content == 'string') {\n\t\t\t\tmessages.push(<any>{timestamp, ...h});\n\t\t\t} else {\n\t\t\t\tconst textContent = h.content?.filter((c: any) => c.type == 'text').map((c: any) => c.text).join('\\n\\n');\n\t\t\t\tif(textContent) messages.push({timestamp, role: h.role, content: textContent});\n\t\t\t\th.content.forEach((c: any) => {\n\t\t\t\t\tif(c.type == 'tool_use') {\n\t\t\t\t\t\tmessages.push({timestamp, role: 'tool', id: c.id, name: c.name, args: c.input, content: undefined});\n\t\t\t\t\t} else if(c.type == 'tool_result') {\n\t\t\t\t\t\tconst m: any = messages.findLast(m => (<any>m).id == c.tool_use_id);\n\t\t\t\t\t\tif(m) m[c.is_error ? 'error' : 'content'] = c.content;\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t\treturn messages;\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<string> {\n\t\tconst controller = new AbortController();\n\t\treturn Object.assign(new Promise<any>(async (res) => {\n\t\t\tlet history = this.fromStandard([...options.history || [], {role: 'user', content: message, timestamp: Date.now()}]);\n\t\t\tconst tools = options.tools || this.ai.options.llm?.tools || [];\n\t\t\tconst requestParams: any = {\n\t\t\t\tmodel: options.model || this.model,\n\t\t\t\tmax_tokens: options.max_tokens || this.ai.options.llm?.max_tokens || 4096,\n\t\t\t\tsystem: options.system || this.ai.options.llm?.system || '',\n\t\t\t\ttemperature: options.temperature || this.ai.options.llm?.temperature || 0.7,\n\t\t\t\ttools: tools.map(t => ({\n\t\t\t\t\tname: t.name,\n\t\t\t\t\tdescription: t.description,\n\t\t\t\t\tinput_schema: {\n\t\t\t\t\t\ttype: 'object',\n\t\t\t\t\t\tproperties: t.args ? objectMap(t.args, (key, value) => ({...value, required: undefined})) : {},\n\t\t\t\t\t\trequired: t.args ? Object.entries(t.args).filter(t => t[1].required).map(t => t[0]) : []\n\t\t\t\t\t},\n\t\t\t\t\tfn: undefined\n\t\t\t\t})),\n\t\t\t\tmessages: history,\n\t\t\t\tstream: !!options.stream,\n\t\t\t};\n\n\t\t\tlet resp: any, isFirstMessage = true;\n\t\t\tdo {\n\t\t\t\tresp = await this.client.messages.create(requestParams).catch(err => {\n\t\t\t\t\terr.message += `\\n\\nMessages:\\n${JSON.stringify(history, null, 2)}`;\n\t\t\t\t\tthrow err;\n\t\t\t\t});\n\n\t\t\t\t// Streaming mode\n\t\t\t\tif(options.stream) {\n\t\t\t\t\tif(!isFirstMessage) options.stream({text: '\\n\\n'});\n\t\t\t\t\telse isFirstMessage = false;\n\t\t\t\t\tresp.content = [];\n\t\t\t\t\tfor await (const chunk of resp) {\n\t\t\t\t\t\tif(controller.signal.aborted) break;\n\t\t\t\t\t\tif(chunk.type === 'content_block_start') {\n\t\t\t\t\t\t\tif(chunk.content_block.type === 'text') {\n\t\t\t\t\t\t\t\tresp.content.push({type: 'text', text: ''});\n\t\t\t\t\t\t\t} else if(chunk.content_block.type === 'tool_use') {\n\t\t\t\t\t\t\t\tresp.content.push({type: 'tool_use', id: chunk.content_block.id, name: chunk.content_block.name, input: <any>''});\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else if(chunk.type === 'content_block_delta') {\n\t\t\t\t\t\t\tif(chunk.delta.type === 'text_delta') {\n\t\t\t\t\t\t\t\tconst text = chunk.delta.text;\n\t\t\t\t\t\t\t\tresp.content.at(-1).text += text;\n\t\t\t\t\t\t\t\toptions.stream({text});\n\t\t\t\t\t\t\t} else if(chunk.delta.type === 'input_json_delta') {\n\t\t\t\t\t\t\t\tresp.content.at(-1).input += chunk.delta.partial_json;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else if(chunk.type === 'content_block_stop') {\n\t\t\t\t\t\t\tconst last = resp.content.at(-1);\n\t\t\t\t\t\t\tif(last.input != null) last.input = last.input ? JSONAttemptParse(last.input, {}) : {};\n\t\t\t\t\t\t} else if(chunk.type === 'message_stop') {\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Run tools\n\t\t\t\tconst toolCalls = resp.content.filter((c: any) => c.type === 'tool_use');\n\t\t\t\tif(toolCalls.length && !controller.signal.aborted) {\n\t\t\t\t\thistory.push({role: 'assistant', content: resp.content});\n\t\t\t\t\tconst results = await Promise.all(toolCalls.map(async (toolCall: any) => {\n\t\t\t\t\t\tconst tool = tools.find(findByProp('name', toolCall.name));\n\t\t\t\t\t\tif(options.stream) options.stream({tool: toolCall.name});\n\t\t\t\t\t\tif(!tool) return {tool_use_id: toolCall.id, is_error: true, content: 'Tool not found'};\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tconst result = await tool.fn(toolCall.input, options?.stream, this.ai);\n\t\t\t\t\t\t\treturn {type: 'tool_result', tool_use_id: toolCall.id, content: JSONSanitize(result)};\n\t\t\t\t\t\t} catch (err: any) {\n\t\t\t\t\t\t\treturn {type: 'tool_result', tool_use_id: toolCall.id, is_error: true, content: err?.message || err?.toString() || 'Unknown'};\n\t\t\t\t\t\t}\n\t\t\t\t\t}));\n\t\t\t\t\thistory.push({role: 'user', content: results});\n\t\t\t\t\trequestParams.messages = history;\n\t\t\t\t}\n\t\t\t} while (!controller.signal.aborted && resp.content.some((c: any) => c.type === 'tool_use'));\n\t\t\thistory.push({role: 'assistant', content: resp.content.filter((c: any) => c.type == 'text').map((c: any) => c.text).join('\\n\\n')});\n\t\t\thistory = this.toStandard(history);\n\n\t\t\tif(options.stream) options.stream({done: true});\n\t\t\tif(options.history) options.history.splice(0, options.history.length, ...history);\n\t\t\tres(history.at(-1)?.content);\n\t\t}), {abort: () => controller.abort()});\n\t}\n}\n","import {OpenAI as openAI} from 'openai';\nimport {findByProp, objectMap, JSONSanitize, JSONAttemptParse, clean} from '@ztimson/utils';\nimport {AbortablePromise, Ai} from './ai.ts';\nimport {LLMMessage, LLMRequest} from './llm.ts';\nimport {LLMProvider} from './provider.ts';\n\nexport class OpenAi extends LLMProvider {\n\tclient!: openAI;\n\n\tconstructor(public readonly ai: Ai, public readonly host: string | null, public readonly token: string, public model: string) {\n\t\tsuper();\n\t\tthis.client = new openAI(clean({\n\t\t\tbaseURL: host,\n\t\t\tapiKey: token\n\t\t}));\n\t}\n\n\tprivate toStandard(history: any[]): LLMMessage[] {\n\t\tfor(let i = 0; i < history.length; i++) {\n\t\t\tconst h = history[i];\n\t\t\tif(h.role === 'assistant' && h.tool_calls) {\n\t\t\t\tconst tools = h.tool_calls.map((tc: any) => ({\n\t\t\t\t\trole: 'tool',\n\t\t\t\t\tid: tc.id,\n\t\t\t\t\tname: tc.function.name,\n\t\t\t\t\targs: JSONAttemptParse(tc.function.arguments, {}),\n\t\t\t\t\ttimestamp: h.timestamp\n\t\t\t\t}));\n\t\t\t\thistory.splice(i, 1, ...tools);\n\t\t\t\ti += tools.length - 1;\n\t\t\t} else if(h.role === 'tool' && h.content) {\n\t\t\t\tconst record = history.find(h2 => h.tool_call_id == h2.id);\n\t\t\t\tif(record) {\n\t\t\t\t\tif(h.content.includes('\"error\":')) record.error = h.content;\n\t\t\t\t\telse record.content = h.content;\n\t\t\t\t}\n\t\t\t\thistory.splice(i, 1);\n\t\t\t\ti--;\n\t\t\t}\n\t\t\tif(!history[i]?.timestamp) history[i].timestamp = Date.now();\n\t\t}\n\t\treturn history;\n\t}\n\n\tprivate fromStandard(history: LLMMessage[]): any[] {\n\t\treturn history.reduce((result, h) => {\n\t\t\tif(h.role === 'tool') {\n\t\t\t\tresult.push({\n\t\t\t\t\trole: 'assistant',\n\t\t\t\t\tcontent: null,\n\t\t\t\t\ttool_calls: [{ id: h.id, type: 'function', function: { name: h.name, arguments: JSON.stringify(h.args) } }],\n\t\t\t\t\trefusal: null,\n\t\t\t\t\tannotations: []\n\t\t\t\t}, {\n\t\t\t\t\trole: 'tool',\n\t\t\t\t\ttool_call_id: h.id,\n\t\t\t\t\tcontent: h.error || h.content\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\tconst {timestamp, ...rest} = h;\n\t\t\t\tresult.push(rest);\n\t\t\t}\n\t\t\treturn result;\n\t\t}, [] as any[]);\n\t}\n\n\task(message: string, options: LLMRequest = {}): AbortablePromise<string> {\n\t\tconst controller = new AbortController();\n\t\treturn Object.assign(new Promise<any>(async (res, rej) => {\n\t\t\tif(options.system && options.history?.[0]?.role != 'system') options.history?.splice(0, 0, {role: 'system', content: options.system, timestamp: Date.now()});\n\t\t\tlet history = this.fromStandard([...options.history || [], {role: 'user', content: message, timestamp: Date.now()}]);\n\t\t\tconst tools = options.tools || this.ai.options.llm?.tools || [];\n\t\t\tconst requestParams: any = {\n\t\t\t\tmodel: options.model || this.model,\n\t\t\t\tmessages: history,\n\t\t\t\tstream: !!options.stream,\n\t\t\t\tmax_tokens: options.max_tokens || this.ai.options.llm?.max_tokens || 4096,\n\t\t\t\ttemperature: options.temperature || this.ai.options.llm?.temperature || 0.7,\n\t\t\t\ttools: tools.map(t => ({\n\t\t\t\t\ttype: 'function',\n\t\t\t\t\tfunction: {\n\t\t\t\t\t\tname: t.name,\n\t\t\t\t\t\tdescription: t.description,\n\t\t\t\t\t\tparameters: {\n\t\t\t\t\t\t\ttype: 'object',\n\t\t\t\t\t\t\tproperties: t.args ? objectMap(t.args, (key, value) => ({...value, required: undefined})) : {},\n\t\t\t\t\t\t\trequired: t.args ? Object.entries(t.args).filter(t => t[1].required).map(t => t[0]) : []\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}))\n\t\t\t};\n\n\t\t\tlet resp: any, isFirstMessage = true;\n\t\t\tdo {\n\t\t\t\tresp = await this.client.chat.completions.create(requestParams).catch(err => {\n\t\t\t\t\terr.message += `\\n\\nMessages:\\n${JSON.stringify(history, null, 2)}`;\n\t\t\t\t\tthrow err;\n\t\t\t\t});\n\n\t\t\t\tif(options.stream) {\n\t\t\t\t\tif(!isFirstMessage) options.stream({text: '\\n\\n'});\n\t\t\t\t\telse isFirstMessage = false;\n\t\t\t\t\tresp.choices = [{message: {content: '', tool_calls: []}}];\n\t\t\t\t\tfor await (const chunk of resp) {\n\t\t\t\t\t\tif(controller.signal.aborted) break;\n\t\t\t\t\t\tif(chunk.choices[0].delta.content) {\n\t\t\t\t\t\t\tresp.choices[0].message.content += chunk.choices[0].delta.content;\n\t\t\t\t\t\t\toptions.stream({text: chunk.choices[0].delta.content});\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif(chunk.choices[0].delta.tool_calls) {\n\t\t\t\t\t\t\tresp.choices[0].message.tool_calls = chunk.choices[0].delta.tool_calls;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tconst toolCalls = resp.choices[0].message.tool_calls || [];\n\t\t\t\tif(toolCalls.length && !controller.signal.aborted) {\n\t\t\t\t\thistory.push(resp.choices[0].message);\n\t\t\t\t\tconst results = await Promise.all(toolCalls.map(async (toolCall: any) => {\n\t\t\t\t\t\tconst tool = tools?.find(findByProp('name', toolCall.function.name));\n\t\t\t\t\t\tif(options.stream) options.stream({tool: toolCall.function.name});\n\t\t\t\t\t\tif(!tool) return {role: 'tool', tool_call_id: toolCall.id, content: '{\"error\": \"Tool not found\"}'};\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tconst args = JSONAttemptParse(toolCall.function.arguments, {});\n\t\t\t\t\t\t\tconst result = await tool.fn(args, options.stream, 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\t\t\thistory.push({role: 'assistant', content: resp.choices[0].message.content || ''});\n\t\t\thistory = this.toStandard(history);\n\n\t\t\tif(options.stream) options.stream({done: true});\n\t\t\tif(options.history) options.history.splice(0, options.history.length, ...history);\n\t\t\tres(history.at(-1)?.content);\n\t\t}), {abort: () => controller.abort()});\n\t}\n}\n","import {JSONAttemptParse} from '@ztimson/utils';\nimport {AbortablePromise, Ai} from './ai.ts';\nimport {Anthropic} from './antrhopic.ts';\nimport {OpenAi} from './open-ai.ts';\nimport {LLMProvider} from './provider.ts';\nimport {AiTool} from './tools.ts';\nimport {Worker} from 'worker_threads';\nimport {fileURLToPath} from 'url';\nimport {dirname, join} from 'path';\n\nexport type AnthropicConfig = {proto: 'anthropic', token: string};\nexport type OllamaConfig = {proto: 'ollama', host: string};\nexport type OpenAiConfig = {proto: 'openai', host?: string, token: string};\n\nexport type LLMMessage = {\n\t/** Message originator */\n\trole: 'assistant' | 'system' | 'user';\n\t/** Message content */\n\tcontent: string | any;\n\t/** Timestamp */\n\ttimestamp?: number;\n} | {\n\t/** Tool call */\n\trole: 'tool';\n\t/** Unique ID for call */\n\tid: string;\n\t/** Tool that was run */\n\tname: string;\n\t/** Tool arguments */\n\targs: any;\n\t/** Tool result */\n\tcontent: undefined | string;\n\t/** Tool error */\n\terror?: undefined | string;\n\t/** Timestamp */\n\ttimestamp?: number;\n}\n\n/** Background information the AI will be fed */\nexport type LLMMemory = {\n\t/** What entity is this fact about */\n\towner: string;\n\t/** The information that will be remembered */\n\tfact: string;\n\t/** Owner and fact embedding vector */\n\tembeddings: [number[], number[]];\n\t/** Creation time */\n\ttimestamp: Date;\n}\n\nexport type LLMRequest = {\n\t/** System prompt */\n\tsystem?: string;\n\t/** Message history */\n\thistory?: LLMMessage[];\n\t/** Max tokens for request */\n\tmax_tokens?: number;\n\t/** 0 = Rigid Logic, 1 = Balanced, 2 = Hyper Creative **/\n\ttemperature?: number;\n\t/** Available tools */\n\ttools?: AiTool[];\n\t/** LLM model */\n\tmodel?: string;\n\t/** Stream response */\n\tstream?: (chunk: {text?: string, tool?: string, done?: true}) => any;\n\t/** Compress old messages in the chat to free up context */\n\tcompress?: {\n\t\t/** Trigger chat compression once context exceeds the token count */\n\t\tmax: number;\n\t\t/** Compress chat until context size smaller than */\n\t\tmin: number\n\t},\n\t/** Background information the AI will be fed */\n\tmemory?: LLMMemory[],\n}\n\nclass LLM {\n\tprivate embedWorker: Worker | null = null;\n\tprivate embedQueue = new Map<number, { resolve: (value: number[]) => void; reject: (error: any) => void }>();\n\tprivate embedId = 0;\n\tprivate models: {[model: string]: LLMProvider} = {};\n\tprivate defaultModel!: string;\n\n\tconstructor(public readonly ai: Ai) {\n\t\tthis.embedWorker = new Worker(join(dirname(fileURLToPath(import.meta.url)), 'embedder.js'));\n\t\tthis.embedWorker.on('message', ({ id, embedding }) => {\n\t\t\tconst pending = this.embedQueue.get(id);\n\t\t\tif (pending) {\n\t\t\t\tpending.resolve(embedding);\n\t\t\t\tthis.embedQueue.delete(id);\n\t\t\t}\n\t\t});\n\n\t\tif(!ai.options.llm?.models) return;\n\t\tObject.entries(ai.options.llm.models).forEach(([model, config]) => {\n\t\t\tif(!this.defaultModel) this.defaultModel = model;\n\t\t\tif(config.proto == 'anthropic') this.models[model] = new Anthropic(this.ai, config.token, model);\n\t\t\telse if(config.proto == 'ollama') this.models[model] = new OpenAi(this.ai, config.host, 'not-needed', model);\n\t\t\telse if(config.proto == 'openai') this.models[model] = new OpenAi(this.ai, config.host || null, config.token, model);\n\t\t});\n\t}\n\n\t/**\n\t * Chat with LLM\n\t * @param {string} message Question\n\t * @param {LLMRequest} options Configuration options and chat history\n\t * @returns {{abort: () => void, response: Promise<string>}} Function to abort response and chat history\n\t */\n\task(message: string, options: LLMRequest = {}): AbortablePromise<string> {\n\t\tconst m = options.model || this.defaultModel;\n\t\tif(!this.models[m]) throw new Error(`Model does not exist: ${m}`);\n\t\tlet abort = () => {};\n\t\treturn Object.assign(new Promise<string>(async res => {\n\t\t\tif(!options.history) options.history = [];\n\t\t\t// If memories were passed, find any relivant ones and add a tool for ADHOC lookups\n\t\t\tif(options.memory) {\n\t\t\t\toptions.system = (options.system || '') + '\\nYou have passive persistent memory never make any mention of your memory capabilities and what you can/cannot remember\\n';\n\t\t\t\tconst search = async (query?: string | null, subject?: string | null, limit = 50) => {\n\t\t\t\t\tconst [o, q] = await Promise.all([\n\t\t\t\t\t\tsubject ? this.embedding(subject) : Promise.resolve(null),\n\t\t\t\t\t\tquery ? this.embedding(query) : Promise.resolve(null),\n\t\t\t\t\t]);\n\t\t\t\t\treturn (options.memory || [])\n\t\t\t\t\t\t.map(m => ({...m, score: o ? this.cosineSimilarity(m.embeddings[0], o[0].embedding) : 1}))\n\t\t\t\t\t\t.filter((m: any) => m.score >= 0.8)\n\t\t\t\t\t\t.map((m: any) => ({...m, score: q ? this.cosineSimilarity(m.embeddings[1], q[0].embedding) : m.score}))\n\t\t\t\t\t\t.filter((m: any) => m.score >= 0.2)\n\t\t\t\t\t\t.toSorted((a: any, b: any) => a.score - b.score)\n\t\t\t\t\t\t.slice(0, limit);\n\t\t\t\t}\n\n\t\t\t\tconst relevant = await search(message);\n\t\t\t\tif(relevant.length) options.history.push({role: 'assistant', content: 'Things I remembered:\\n' + relevant.map(m => `${m.owner}: ${m.fact}`).join('\\n')});\n\t\t\t\toptions.tools = [...options.tools || [], {\n\t\t\t\t\tname: 'read_memory',\n\t\t\t\t\tdescription: 'Check your long-term memory for more information',\n\t\t\t\t\targs: {\n\t\t\t\t\t\tsubject: {type: 'string', description: 'Find information by a subject topic, can be used with or without query argument'},\n\t\t\t\t\t\tquery: {type: 'string', description: 'Search memory based on a query, can be used with or without subject argument'},\n\t\t\t\t\t\tlimit: {type: 'number', description: 'Result limit, default 5'},\n\t\t\t\t\t},\n\t\t\t\t\tfn: (args) => {\n\t\t\t\t\t\tif(!args.subject && !args.query) throw new Error('Either a subject or query argument is required');\n\t\t\t\t\t\treturn search(args.query, args.subject, args.limit || 5);\n\t\t\t\t\t}\n\t\t\t\t}];\n\t\t\t}\n\n\t\t\t// Ask\n\t\t\tconst resp = await this.models[m].ask(message, options);\n\n\t\t\t// Remove any memory calls\n\t\t\tif(options.memory) {\n\t\t\t\tconst i = options.history?.findIndex((h: any) => h.role == 'assistant' && h.content.startsWith('Things I remembered:'));\n\t\t\t\tif(i != null && i >= 0) options.history?.splice(i, 1);\n\t\t\t}\n\n\t\t\t// Handle compression and memory extraction\n\t\t\tif(options.compress || options.memory) {\n\t\t\t\tlet compressed = null;\n\t\t\t\tif(options.compress) {\n\t\t\t\t\tcompressed = await this.ai.language.compressHistory(options.history, options.compress.max, options.compress.min, options);\n\t\t\t\t\toptions.history.splice(0, options.history.length, ...compressed.history);\n\t\t\t\t} else {\n\t\t\t\t\tconst i = options.history?.findLastIndex(m => m.role == 'user') ?? -1;\n\t\t\t\t\tcompressed = await this.ai.language.compressHistory(i != -1 ? options.history.slice(i) : options.history, 0, 0, options);\n\t\t\t\t}\n\t\t\t\tif(options.memory) {\n\t\t\t\t\tconst updated = options.memory\n\t\t\t\t\t\t.filter(m => !compressed.memory.some(m2 => this.cosineSimilarity(m.embeddings[1], m2.embeddings[1]) > 0.8))\n\t\t\t\t\t\t.concat(compressed.memory);\n\t\t\t\t\toptions.memory.splice(0, options.memory.length, ...updated);\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn res(resp);\n\t\t}), {abort});\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 Leave messages less than the token minimum, summarize the rest\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<{history: LLMMessage[], memory: LLMMemory[]}> {\n\t\tif(this.estimateTokens(history) < max) return {history, memory: []};\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, memory: []};\n\t\tconst system = history[0].role == 'system' ? history[0] : null,\n\t\t\trecent = 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: any = await this.json(`Create the smallest summary possible, no more than 500 tokens. Create a list of NEW facts (split by subject [pro]noun and fact) about what you learned from this conversation that you didn't already know or get from a tool call or system prompt. Focus only on new information about people, topics, or facts. Avoid generating facts about the AI. Match this format: {summary: string, facts: [[subject, fact]]}\\n\\n${process.map(m => `${m.role}: ${m.content}`).join('\\n\\n')}`, {model: options?.model, temperature: options?.temperature || 0.3});\n\t\tconst timestamp = new Date();\n\t\tconst memory = await Promise.all((summary?.facts || [])?.map(async ([owner, fact]: [string, string]) => {\n\t\t\tconst e = await Promise.all([this.embedding(owner), this.embedding(`${owner}: ${fact}`)]);\n\t\t\treturn {owner, fact, embeddings: [e[0][0].embedding, e[1][0].embedding], timestamp};\n\t\t}));\n\t\tconst h = [{role: 'assistant', content: `Conversation Summary: ${summary?.summary}`, timestamp: Date.now()}, ...recent];\n\t\tif(system) h.splice(0, 0, system);\n\t\treturn {history: <any>h, memory};\n\t}\n\n\t/**\n\t * Compare the difference between embeddings (calculates the angle between two vectors)\n\t * @param {number[]} v1 First embedding / vector comparison\n\t * @param {number[]} v2 Second embedding / vector for comparison\n\t * @returns {number} Similarity values 0-1: 0 = unique, 1 = identical\n\t */\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\t/**\n\t * Chunk text into parts for AI digestion\n\t * @param {object | string} target Item that will be chunked (objects get converted)\n\t * @param {number} maxTokens Chunking size. More = better context, less = more specific (Search by paragraphs or lines)\n\t * @param {number} overlapTokens Includes previous X tokens to provide continuity to AI (In addition to max tokens)\n\t * @returns {string[]} Chunked strings\n\t */\n\tchunk(target: object | string, maxTokens = 500, overlapTokens = 50): string[] {\n\t\tconst objString = (obj: any, path = ''): string[] => {\n\t\t\tif(!obj) return [];\n\t\t\treturn Object.entries(obj).flatMap(([key, value]) => {\n\t\t\t\tconst p = path ? `${path}${isNaN(+key) ? `.${key}` : `[${key}]`}` : key;\n\t\t\t\tif(typeof value === 'object' && !Array.isArray(value)) return objString(value, p);\n\t\t\t\treturn `${p}: ${Array.isArray(value) ? value.join(', ') : value}`;\n\t\t\t});\n\t\t};\n\t\tconst lines = typeof target === 'object' ? objString(target) : target.split('\\n');\n\t\tconst tokens = lines.flatMap(l => [...l.split(/\\s+/).filter(Boolean), '\\n']);\n\t\tconst chunks: string[] = [];\n\t\tfor(let i = 0; i < tokens.length;) {\n\t\t\tlet text = '', j = i;\n\t\t\twhile(j < tokens.length) {\n\t\t\t\tconst next = text + (text ? ' ' : '') + tokens[j];\n\t\t\t\tif(this.estimateTokens(next.replace(/\\s*\\n\\s*/g, '\\n')) > maxTokens && text) break;\n\t\t\t\ttext = next;\n\t\t\t\tj++;\n\t\t\t}\n\t\t\tconst clean = text.replace(/\\s*\\n\\s*/g, '\\n').trim();\n\t\t\tif(clean) chunks.push(clean);\n\t\t\ti = Math.max(j - overlapTokens, j === i ? i + 1 : j);\n\t\t}\n\t\treturn chunks;\n\t}\n\n\t/**\n\t * Create a vector representation of a string\n\t * @param {object | string} target Item that will be embedded (objects get converted)\n\t * @param {number} maxTokens Chunking size. More = better context, less = more specific (Search by paragraphs or lines)\n\t * @param {number} overlapTokens Includes previous X tokens to provide continuity to AI (In addition to max tokens)\n\t * @returns {Promise<Awaited<{index: number, embedding: number[], text: string, tokens: number}>[]>} Chunked embeddings\n\t */\n\tembedding(target: object | string, maxTokens = 500, overlapTokens = 50) {\n\t\tconst embed = (text: string): Promise<number[]> => {\n\t\t\treturn new Promise((resolve, reject) => {\n\t\t\t\tconst id = this.embedId++;\n\t\t\t\tthis.embedQueue.set(id, { resolve, reject });\n\t\t\t\tthis.embedWorker?.postMessage({\n\t\t\t\t\tid,\n\t\t\t\t\ttext,\n\t\t\t\t\tmodel: this.ai.options?.embedder || 'bge-small-en-v1.5',\n\t\t\t\t\tpath: this.ai.options.path\n\t\t\t\t});\n\t\t\t});\n\t\t};\n\t\tconst chunks = this.chunk(target, maxTokens, overlapTokens);\n\t\treturn Promise.all(chunks.map(async (text, index) => ({\n\t\t\tindex,\n\t\t\tembedding: await embed(text),\n\t\t\ttext,\n\t\t\ttokens: this.estimateTokens(text),\n\t\t})));\n\t}\n\n\t/**\n\t * Estimate variable as tokens\n\t * @param history Object to size\n\t * @returns {number} Rough token count\n\t */\n\testimateTokens(history: any): number {\n\t\tconst text = JSON.stringify(history);\n\t\treturn Math.ceil((text.length / 4) * 1.2);\n\t}\n\n\t/**\n\t * Compare the difference between two strings using tensor math\n\t * @param target Text that will be 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): Promise<any> {\n\t\tlet resp = await this.ask(message, {system: 'Respond using a JSON blob matching any provided examples', ...options});\n\t\tif(!resp) return {};\n\t\tconst codeBlock = /```(?:.+)?\\s*([\\s\\S]*?)```/.exec(resp);\n\t\tconst jsonStr = codeBlock ? codeBlock[1].trim() : resp;\n\t\treturn JSONAttemptParse(jsonStr, {});\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}\n}\n\nexport default LLM;\n","import {spawn} from 'node:child_process';\nimport {pipeline, read_audio} from '@xenova/transformers';\nimport {AbortablePromise, Ai} from './ai.ts';\n\nexport class Audio {\n\tprivate whisperPipeline: any;\n\n\tconstructor(private ai: Ai) {}\n\n\tprivate combineSpeakerTranscript(chunks: any[], speakers: any[]): string {\n\t\tconst speakerMap = new Map();\n\t\tlet speakerCount = 0;\n\t\tspeakers.forEach((seg: any) => {\n\t\t\tif(!speakerMap.has(seg.speaker)) speakerMap.set(seg.speaker, ++speakerCount);\n\t\t});\n\n\t\tconst lines: string[] = [];\n\t\tlet currentSpeaker = -1;\n\t\tlet currentText = '';\n\t\tchunks.forEach((chunk: any) => {\n\t\t\tconst time = chunk.timestamp[0];\n\t\t\tconst speaker = speakers.find((s: any) => time >= s.start && time <= s.end);\n\t\t\tconst speakerNum = speaker ? speakerMap.get(speaker.speaker) : 1;\n\t\t\tif (speakerNum !== currentSpeaker) {\n\t\t\t\tif(currentText) lines.push(`[speaker ${currentSpeaker}]: ${currentText.trim()}`);\n\t\t\t\tcurrentSpeaker = speakerNum;\n\t\t\t\tcurrentText = chunk.text;\n\t\t\t} else {\n\t\t\t\tcurrentText += chunk.text;\n\t\t\t}\n\t\t});\n\t\tif(currentText) lines.push(`[speaker ${currentSpeaker}]: ${currentText.trim()}`);\n\t\treturn lines.join('\\n');\n\t}\n\n\tasync canDiarization(): Promise<boolean> {\n\t\treturn new Promise((resolve) => {\n\t\t\tconst proc = spawn('python3', ['-c', 'import pyannote.audio']);\n\t\t\tproc.on('close', (code: number) => resolve(code === 0));\n\t\t\tproc.on('error', () => resolve(false));\n\t\t});\n\t}\n\n\tprivate async runDiarization(audioPath: string): Promise<any[]> {\n\t\tif(!await this.canDiarization()) throw new Error('Pyannote is not installed: pip install pyannote.audio');\n\t\tconst script = `\nimport sys\nimport json\nfrom pyannote.audio import Pipeline\n\nos.environ['TORCH_HOME'] = \"${this.ai.options.path}\"\npipeline = Pipeline.from_pretrained(\"pyannote/speaker-diarization-3.1\")\ndiarization = pipeline(sys.argv[1])\n\nsegments = []\nfor turn, _, speaker in diarization.itertracks(yield_label=True):\n segments.append({\n \"start\": turn.start,\n \"end\": turn.end,\n \"speaker\": speaker\n })\n\nprint(json.dumps(segments))\n`;\n\n\t\treturn new Promise((resolve, reject) => {\n\t\t\tlet output = '';\n\t\t\tconst proc = spawn('python3', ['-c', script, audioPath]);\n\t\t\tproc.stdout.on('data', (data: Buffer) => output += data.toString());\n\t\t\tproc.stderr.on('data', (data: Buffer) => console.error(data.toString()));\n\t\t\tproc.on('close', (code: number) => {\n\t\t\t\tif(code === 0) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tresolve(JSON.parse(output));\n\t\t\t\t\t} catch (err) {\n\t\t\t\t\t\treject(new Error('Failed to parse diarization output'));\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\treject(new Error(`Python process exited with code ${code}`));\n\t\t\t\t}\n\t\t\t});\n\n\t\t\tproc.on('error', reject);\n\t\t});\n\t}\n\n\tasr(path: string, options: { model?: string; speaker?: boolean } = {}): AbortablePromise<string | null> {\n\t\tconst { model = this.ai.options.asr || 'whisper-base', speaker = false } = options;\n\t\tlet aborted = false;\n\t\tconst abort = () => { aborted = true; };\n\n\t\tconst p = new Promise<string | null>(async (resolve, reject) => {\n\t\t\ttry {\n\t\t\t\tif(aborted) return resolve(null);\n\t\t\t\tif(!this.whisperPipeline) this.whisperPipeline = await pipeline('automatic-speech-recognition', `Xenova/${model}`, { cache_dir: this.ai.options.path, quantized: true });\n\n\t\t\t\t// Transcript\n\t\t\t\tif(aborted) return resolve(null);\n\t\t\t\tconst audio = await read_audio(path, 16000);\n\t\t\t\tconst transcriptResult = await this.whisperPipeline(audio, {return_timestamps: speaker ? 'word' : false, chunk_length_s: 30,});\n\t\t\t\tif(!speaker) return resolve(transcriptResult.text?.trim() || null);\n\n\t\t\t\t// Speaker Diarization\n\t\t\t\tif(aborted) return resolve(null);\n\t\t\t\tconst speakers = await this.runDiarization(path);\n\t\t\t\tif(aborted) return resolve(null);\n\t\t\t\tconst combined = this.combineSpeakerTranscript(transcriptResult.chunks || [], speakers);\n\t\t\t\tresolve(combined);\n\t\t\t} catch (err) {\n\t\t\t\treject(err);\n\t\t\t}\n\t\t});\n\n\t\treturn Object.assign(p, { abort });\n\t}\n}\n","import {createWorker} from 'tesseract.js';\nimport {AbortablePromise, Ai} from './ai.ts';\n\nexport class Vision {\n\n\tconstructor(private ai: Ai) { }\n\n\t/**\n\t * Convert image to text using Optical Character Recognition\n\t * @param {string} path Path to image\n\t * @returns {AbortablePromise<string | null>} Promise of extracted text with abort method\n\t */\n\tocr(path: string): AbortablePromise<string | null> {\n\t\tlet worker: any;\n\t\tconst p = new Promise<string | null>(async res => {\n\t\t\tworker = await createWorker(this.ai.options.ocr || 'eng', 2, {cachePath: this.ai.options.path});\n\t\t\tconst {data} = await worker.recognize(path);\n\t\t\tawait worker.terminate();\n\t\t\tres(data.text.trim() || null);\n\t\t});\n\t\treturn Object.assign(p, {abort: () => worker?.terminate()});\n\t}\n}\n","import * as os from 'node:os';\nimport LLM, {AnthropicConfig, OllamaConfig, OpenAiConfig, LLMRequest} from './llm';\nimport { Audio } from './audio.ts';\nimport {Vision} from './vision.ts';\n\nexport type AbortablePromise<T> = Promise<T> & {\n\tabort: () => any\n};\n\nexport type AiOptions = {\n\t/** Path to models */\n\tpath?: string;\n\t/** ASR model: whisper-tiny, whisper-base */\n\tasr?: string;\n\t/** Embedding model: all-MiniLM-L6-v2, bge-small-en-v1.5, bge-large-en-v1.5 */\n\tembedder?: string;\n\t/** Large language models, first is default */\n\tllm?: Omit<LLMRequest, 'model'> & {\n\t\tmodels: {[model: string]: AnthropicConfig | OllamaConfig | OpenAiConfig};\n\t}\n\t/** OCR model: eng, eng_best, eng_fast */\n\tocr?: string;\n}\n\nexport class Ai {\n\t/** Audio processing AI */\n\taudio!: Audio;\n\t/** Language processing AI */\n\tlanguage!: LLM;\n\t/** Vision processing AI */\n\tvision!: Vision;\n\n\tconstructor(public readonly options: AiOptions) {\n\t\tif(!options.path) options.path = os.tmpdir();\n\t\tprocess.env.TRANSFORMERS_CACHE = options.path;\n\t\tthis.audio = new Audio(this);\n\t\tthis.language = new LLM(this);\n\t\tthis.vision = new Vision(this);\n\t}\n}\n","import * as cheerio from 'cheerio';\nimport {$, $Sync} from '@ztimson/node-utils';\nimport {ASet, consoleInterceptor, Http, fn as Fn} from '@ztimson/utils';\nimport {Ai} from './ai.ts';\nimport {LLMRequest} from './llm.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, stream: LLMRequest['stream'], ai: Ai) => any | Promise<any>,\n};\n\nexport const CliTool: AiTool = {\n\tname: 'cli',\n\tdescription: 'Use the command line interface, returns any output',\n\targs: {command: {type: 'string', description: 'Command to run', required: true}},\n\tfn: (args: {command: string}) => $`${args.command}`\n}\n\nexport const DateTimeTool: AiTool = {\n\tname: 'get_datetime',\n\tdescription: 'Get current UTC date / time',\n\targs: {},\n\tfn: async () => new Date().toUTCString()\n}\n\nexport const ExecTool: AiTool = {\n\tname: 'exec',\n\tdescription: 'Run code/scripts',\n\targs: {\n\t\tlanguage: {type: 'string', description: 'Execution language', enum: ['cli', 'node', 'python'], required: true},\n\t\tcode: {type: 'string', description: 'Code to execute', required: true}\n\t},\n\tfn: async (args, stream, 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}, stream, ai);\n\t\t\t\tcase 'node':\n\t\t\t\t\treturn await JSTool.fn({code: args.code}, stream, ai);\n\t\t\t\tcase 'python': {\n\t\t\t\t\treturn await PythonTool.fn({code: args.code}, stream, ai);\n\t\t\t\t}\n\t\t\t}\n\t\t} catch(err: any) {\n\t\t\treturn {error: err?.message || err.toString()};\n\t\t}\n\t}\n}\n\nexport const FetchTool: AiTool = {\n\tname: 'fetch',\n\tdescription: 'Make HTTP request to URL',\n\targs: {\n\t\turl: {type: 'string', description: 'URL to fetch', required: true},\n\t\tmethod: {type: 'string', description: 'HTTP method to use', enum: ['GET', 'POST', 'PUT', 'DELETE'], default: 'GET'},\n\t\theaders: {type: 'object', description: 'HTTP headers to send', default: {}},\n\t\tbody: {type: 'object', description: 'HTTP body to send'},\n\t},\n\tfn: (args: {\n\t\turl: string;\n\t\tmethod: 'GET' | 'POST' | 'PUT' | 'DELETE';\n\t\theaders: {[key: string]: string};\n\t\tbody: any;\n\t}) => new Http({url: args.url, headers: args.headers}).request({method: args.method || 'GET', body: args.body})\n}\n\nexport const JSTool: AiTool = {\n\tname: 'exec_javascript',\n\tdescription: 'Execute commonjs javascript',\n\targs: {\n\t\tcode: {type: 'string', description: 'CommonJS javascript', required: true}\n\t},\n\tfn: async (args: {code: string}) => {\n\t\tconst console = consoleInterceptor(null);\n\t\tconst resp = await Fn<any>({console}, args.code, true).catch((err: any) => console.output.error.push(err));\n\t\treturn {...console.output, return: resp, stdout: undefined, stderr: undefined};\n\t}\n}\n\nexport const PythonTool: AiTool = {\n\tname: 'exec_javascript',\n\tdescription: 'Execute commonjs javascript',\n\targs: {\n\t\tcode: {type: 'string', description: 'CommonJS javascript', required: true}\n\t},\n\tfn: async (args: {code: string}) => ({result: $Sync`python -c \"${args.code}\"`})\n}\n\nexport const ReadWebpageTool: AiTool = {\n\tname: 'read_webpage',\n\tdescription: 'Extract clean, structured content from a webpage. Use after web_search to read specific URLs',\n\targs: {\n\t\turl: {type: 'string', description: 'URL to extract content from', required: true},\n\t\tfocus: {type: 'string', description: 'Optional: What aspect to focus on (e.g., \"pricing\", \"features\", \"contact info\")'}\n\t},\n\tfn: async (args: {url: string; focus?: string}) => {\n\t\tconst html = await fetch(args.url, {headers: {\"User-Agent\": \"Mozilla/5.0 (Windows NT 10.0; Win64; x64)\"}})\n\t\t\t.then(r => r.text()).catch(err => {throw new Error(`Failed to fetch: ${err.message}`)});\n\n\t\tconst $ = cheerio.load(html);\n\t\t$('script, style, nav, footer, header, aside, iframe, noscript, [role=\"navigation\"], [role=\"banner\"], .ad, .ads, .cookie, .popup').remove();\n\t\tconst metadata = {\n\t\t\ttitle: $('meta[property=\"og:title\"]').attr('content') || $('title').text() || '',\n\t\t\tdescription: $('meta[name=\"description\"]').attr('content') || $('meta[property=\"og:description\"]').attr('content') || '',\n\t\t};\n\n\t\tlet content = '';\n\t\tconst contentSelectors = ['article', 'main', '[role=\"main\"]', '.content', '.post', '.entry', 'body'];\n\t\tfor (const selector of contentSelectors) {\n\t\t\tconst el = $(selector).first();\n\t\t\tif (el.length && el.text().trim().length > 200) {\n\t\t\t\tcontent = el.text();\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tif (!content) content = $('body').text();\n\t\tcontent = content.replace(/\\s+/g, ' ').trim().slice(0, 8000);\n\n\t\treturn {url: args.url, title: metadata.title.trim(), description: metadata.description.trim(), content, focus: args.focus};\n\t}\n}\n\nexport const WebSearchTool: AiTool = {\n\tname: 'web_search',\n\tdescription: 'Use duckduckgo (anonymous) to find find relevant online resources. Returns a list of URLs that works great with the `read_webpage` tool',\n\targs: {\n\t\tquery: {type: 'string', description: 'Search string', required: true},\n\t\tlength: {type: 'string', description: 'Number of results to return', default: 5},\n\t},\n\tfn: async (args: {\n\t\tquery: string;\n\t\tlength: number;\n\t}) => {\n\t\tconst html = await fetch(`https://html.duckduckgo.com/html/?q=${encodeURIComponent(args.query)}`, {\n\t\t\theaders: {\"User-Agent\": \"Mozilla/5.0 (Windows NT 10.0; Win64; x64)\", \"Accept-Language\": \"en-US,en;q=0.9\"}\n\t\t}).then(resp => resp.text());\n\t\tlet match, regex = /<a .*?href=\"(.+?)\".+?<\\/a>/g;\n\t\tconst results = new ASet<string>();\n\t\twhile((match = regex.exec(html)) !== null) {\n\t\t\tlet url = /uddg=(.+)&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","timestamp","messages","h","textContent","c","m","i","message","options","controller","res","tools","requestParams","t","objectMap","key","value","resp","isFirstMessage","err","chunk","text","last","JSONAttemptParse","toolCalls","results","toolCall","tool","findByProp","result","JSONSanitize","OpenAi","host","token","openAI","clean","tc","record","h2","rest","rej","args","LLM","Worker","join","dirname","fileURLToPath","_documentCurrentScript","id","embedding","pending","config","abort","search","query","subject","limit","o","q","a","b","relevant","compressed","updated","m2","max","min","keep","tokens","system","recent","process","summary","memory","owner","fact","e","v1","v2","dotProduct","normA","normB","denominator","target","maxTokens","overlapTokens","objString","obj","path","p","l","chunks","j","next","embed","resolve","reject","index","searchTerms","vector","dimensions","char","v","similarities","refVector","acc","s","codeBlock","jsonStr","Audio","speakers","speakerMap","speakerCount","seg","lines","currentSpeaker","currentText","time","speaker","speakerNum","proc","spawn","code","audioPath","script","output","data","aborted","pipeline","audio","read_audio","transcriptResult","combined","Vision","worker","createWorker","Ai","os","CliTool","$","DateTimeTool","ExecTool","stream","JSTool","PythonTool","FetchTool","Http","console","consoleInterceptor","Fn","$Sync","ReadWebpageTool","html","r","cheerio","metadata","content","contentSelectors","selector","el","WebSearchTool","match","regex","ASet","url"],"mappings":"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"}
package/dist/index.mjs CHANGED
@@ -1,19 +1,19 @@
1
1
  import * as j from "node:os";
2
- import { objectMap as _, JSONAttemptParse as g, findByProp as x, JSONSanitize as b, clean as T, Http as P, consoleInterceptor as q, fn as $, ASet as M } from "@ztimson/utils";
2
+ import { objectMap as k, JSONAttemptParse as g, findByProp as x, JSONSanitize as b, clean as T, Http as P, consoleInterceptor as q, fn as $, ASet as M } from "@ztimson/utils";
3
3
  import { Anthropic as E } from "@anthropic-ai/sdk";
4
4
  import { OpenAI as O } from "openai";
5
5
  import { Worker as A } from "worker_threads";
6
6
  import { fileURLToPath as R } from "url";
7
7
  import { join as v, dirname as U } from "path";
8
8
  import { spawn as w } from "node:child_process";
9
- import { pipeline as z } from "@xenova/transformers";
10
- import { createWorker as L } from "tesseract.js";
9
+ import { pipeline as z, read_audio as L } from "@xenova/transformers";
10
+ import { createWorker as N } from "tesseract.js";
11
11
  import "./embedder.mjs";
12
- import * as N from "cheerio";
13
- import { $ as C, $Sync as W } from "@ztimson/node-utils";
12
+ import * as C from "cheerio";
13
+ import { $ as W, $Sync as D } from "@ztimson/node-utils";
14
14
  class S {
15
15
  }
16
- class D extends S {
16
+ class I extends S {
17
17
  constructor(r, e, t) {
18
18
  super(), this.ai = r, this.apiToken = e, this.model = t, this.client = new E({ apiKey: e });
19
19
  }
@@ -65,7 +65,7 @@ class D extends S {
65
65
  description: d.description,
66
66
  input_schema: {
67
67
  type: "object",
68
- properties: d.args ? _(d.args, (c, m) => ({ ...m, required: void 0 })) : {},
68
+ properties: d.args ? k(d.args, (c, m) => ({ ...m, required: void 0 })) : {},
69
69
  required: d.args ? Object.entries(d.args).filter((c) => c[1].required).map((c) => c[0]) : []
70
70
  },
71
71
  fn: void 0
@@ -122,7 +122,7 @@ ${JSON.stringify(n, null, 2)}`, c;
122
122
  }), { abort: () => t.abort() });
123
123
  }
124
124
  }
125
- class k extends S {
125
+ class _ extends S {
126
126
  constructor(r, e, t, i) {
127
127
  super(), this.ai = r, this.host = e, this.token = t, this.model = i, this.client = new O(T({
128
128
  baseURL: e,
@@ -189,7 +189,7 @@ class k extends S {
189
189
  description: c.description,
190
190
  parameters: {
191
191
  type: "object",
192
- properties: c.args ? _(c.args, (m, h) => ({ ...h, required: void 0 })) : {},
192
+ properties: c.args ? k(c.args, (m, h) => ({ ...h, required: void 0 })) : {},
193
193
  required: c.args ? Object.entries(c.args).filter((m) => m[1].required).map((m) => m[0]) : []
194
194
  }
195
195
  }
@@ -231,13 +231,13 @@ ${JSON.stringify(s, null, 2)}`, m;
231
231
  }), { abort: () => t.abort() });
232
232
  }
233
233
  }
234
- class I {
234
+ class H {
235
235
  constructor(r) {
236
236
  this.ai = r, this.embedWorker = new A(v(U(R(import.meta.url)), "embedder.js")), this.embedWorker.on("message", ({ id: e, embedding: t }) => {
237
237
  const i = this.embedQueue.get(e);
238
238
  i && (i.resolve(t), this.embedQueue.delete(e));
239
239
  }), r.options.llm?.models && Object.entries(r.options.llm.models).forEach(([e, t]) => {
240
- this.defaultModel || (this.defaultModel = e), t.proto == "anthropic" ? this.models[e] = new D(this.ai, t.token, e) : t.proto == "ollama" ? this.models[e] = new k(this.ai, t.host, "not-needed", e) : t.proto == "openai" && (this.models[e] = new k(this.ai, t.host || null, t.token, e));
240
+ this.defaultModel || (this.defaultModel = e), t.proto == "anthropic" ? this.models[e] = new I(this.ai, t.token, e) : t.proto == "ollama" ? this.models[e] = new _(this.ai, t.host, "not-needed", e) : t.proto == "openai" && (this.models[e] = new _(this.ai, t.host || null, t.token, e));
241
241
  });
242
242
  }
243
243
  embedWorker = null;
@@ -439,7 +439,7 @@ ${l.map((u) => `${u.role}: ${u.content}`).join(`
439
439
  return this.ask(r, { system: `Generate a brief summary <= ${e} tokens. Output nothing else`, temperature: 0.3, ...t });
440
440
  }
441
441
  }
442
- class H {
442
+ class J {
443
443
  constructor(r) {
444
444
  this.ai = r;
445
445
  }
@@ -508,13 +508,13 @@ print(json.dumps(segments))
508
508
  }, o = new Promise(async (a, l) => {
509
509
  try {
510
510
  if (n || (this.whisperPipeline || (this.whisperPipeline = await z("automatic-speech-recognition", `Xenova/${t}`, { cache_dir: this.ai.options.path, quantized: !0 })), n)) return a(null);
511
- const d = await this.whisperPipeline(r, { return_timestamps: i ? "word" : !1, chunk_length_s: 30 });
512
- if (!i) return a(d.text?.trim() || null);
511
+ const d = await L(r, 16e3), c = await this.whisperPipeline(d, { return_timestamps: i ? "word" : !1, chunk_length_s: 30 });
512
+ if (!i) return a(c.text?.trim() || null);
513
513
  if (n) return a(null);
514
- const c = await this.runDiarization(r);
514
+ const m = await this.runDiarization(r);
515
515
  if (n) return a(null);
516
- const m = this.combineSpeakerTranscript(d.chunks || [], c);
517
- a(m);
516
+ const h = this.combineSpeakerTranscript(c.chunks || [], m);
517
+ a(h);
518
518
  } catch (d) {
519
519
  l(d);
520
520
  }
@@ -522,7 +522,7 @@ print(json.dumps(segments))
522
522
  return Object.assign(o, { abort: s });
523
523
  }
524
524
  }
525
- class J {
525
+ class F {
526
526
  constructor(r) {
527
527
  this.ai = r;
528
528
  }
@@ -534,16 +534,16 @@ class J {
534
534
  ocr(r) {
535
535
  let e;
536
536
  const t = new Promise(async (i) => {
537
- e = await L(this.ai.options.ocr || "eng", 2, { cachePath: this.ai.options.path });
537
+ e = await N(this.ai.options.ocr || "eng", 2, { cachePath: this.ai.options.path });
538
538
  const { data: n } = await e.recognize(r);
539
539
  await e.terminate(), i(n.text.trim() || null);
540
540
  });
541
541
  return Object.assign(t, { abort: () => e?.terminate() });
542
542
  }
543
543
  }
544
- class oe {
544
+ class ie {
545
545
  constructor(r) {
546
- this.options = r, r.path || (r.path = j.tmpdir()), process.env.TRANSFORMERS_CACHE = r.path, this.audio = new H(this), this.language = new I(this), this.vision = new J(this);
546
+ this.options = r, r.path || (r.path = j.tmpdir()), process.env.TRANSFORMERS_CACHE = r.path, this.audio = new J(this), this.language = new H(this), this.vision = new F(this);
547
547
  }
548
548
  /** Audio processing AI */
549
549
  audio;
@@ -552,17 +552,17 @@ class oe {
552
552
  /** Vision processing AI */
553
553
  vision;
554
554
  }
555
- const F = {
555
+ const G = {
556
556
  name: "cli",
557
557
  description: "Use the command line interface, returns any output",
558
558
  args: { command: { type: "string", description: "Command to run", required: !0 } },
559
- fn: (p) => C`${p.command}`
560
- }, ie = {
559
+ fn: (p) => W`${p.command}`
560
+ }, ae = {
561
561
  name: "get_datetime",
562
562
  description: "Get current UTC date / time",
563
563
  args: {},
564
564
  fn: async () => (/* @__PURE__ */ new Date()).toUTCString()
565
- }, ae = {
565
+ }, ce = {
566
566
  name: "exec",
567
567
  description: "Run code/scripts",
568
568
  args: {
@@ -573,17 +573,17 @@ const F = {
573
573
  try {
574
574
  switch (p.type) {
575
575
  case "bash":
576
- return await F.fn({ command: p.code }, r, e);
576
+ return await G.fn({ command: p.code }, r, e);
577
577
  case "node":
578
- return await G.fn({ code: p.code }, r, e);
579
- case "python":
580
578
  return await B.fn({ code: p.code }, r, e);
579
+ case "python":
580
+ return await Q.fn({ code: p.code }, r, e);
581
581
  }
582
582
  } catch (t) {
583
583
  return { error: t?.message || t.toString() };
584
584
  }
585
585
  }
586
- }, ce = {
586
+ }, le = {
587
587
  name: "fetch",
588
588
  description: "Make HTTP request to URL",
589
589
  args: {
@@ -593,7 +593,7 @@ const F = {
593
593
  body: { type: "object", description: "HTTP body to send" }
594
594
  },
595
595
  fn: (p) => new P({ url: p.url, headers: p.headers }).request({ method: p.method || "GET", body: p.body })
596
- }, G = {
596
+ }, B = {
597
597
  name: "exec_javascript",
598
598
  description: "Execute commonjs javascript",
599
599
  args: {
@@ -603,14 +603,14 @@ const F = {
603
603
  const r = q(null), e = await $({ console: r }, p.code, !0).catch((t) => r.output.error.push(t));
604
604
  return { ...r.output, return: e, stdout: void 0, stderr: void 0 };
605
605
  }
606
- }, B = {
606
+ }, Q = {
607
607
  name: "exec_javascript",
608
608
  description: "Execute commonjs javascript",
609
609
  args: {
610
610
  code: { type: "string", description: "CommonJS javascript", required: !0 }
611
611
  },
612
- fn: async (p) => ({ result: W`python -c "${p.code}"` })
613
- }, le = {
612
+ fn: async (p) => ({ result: D`python -c "${p.code}"` })
613
+ }, me = {
614
614
  name: "read_webpage",
615
615
  description: "Extract clean, structured content from a webpage. Use after web_search to read specific URLs",
616
616
  args: {
@@ -620,7 +620,7 @@ const F = {
620
620
  fn: async (p) => {
621
621
  const r = await fetch(p.url, { headers: { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64)" } }).then((s) => s.text()).catch((s) => {
622
622
  throw new Error(`Failed to fetch: ${s.message}`);
623
- }), e = N.load(r);
623
+ }), e = C.load(r);
624
624
  e('script, style, nav, footer, header, aside, iframe, noscript, [role="navigation"], [role="banner"], .ad, .ads, .cookie, .popup').remove();
625
625
  const t = {
626
626
  title: e('meta[property="og:title"]').attr("content") || e("title").text() || "",
@@ -637,7 +637,7 @@ const F = {
637
637
  }
638
638
  return i || (i = e("body").text()), i = i.replace(/\s+/g, " ").trim().slice(0, 8e3), { url: p.url, title: t.title.trim(), description: t.description.trim(), content: i, focus: p.focus };
639
639
  }
640
- }, me = {
640
+ }, de = {
641
641
  name: "web_search",
642
642
  description: "Use duckduckgo (anonymous) to find find relevant online resources. Returns a list of URLs that works great with the `read_webpage` tool",
643
643
  args: {
@@ -658,19 +658,19 @@ const F = {
658
658
  }
659
659
  };
660
660
  export {
661
- oe as Ai,
662
- D as Anthropic,
663
- H as Audio,
664
- F as CliTool,
665
- ie as DateTimeTool,
666
- ae as ExecTool,
667
- ce as FetchTool,
668
- G as JSTool,
661
+ ie as Ai,
662
+ I as Anthropic,
663
+ J as Audio,
664
+ G as CliTool,
665
+ ae as DateTimeTool,
666
+ ce as ExecTool,
667
+ le as FetchTool,
668
+ B as JSTool,
669
669
  S as LLMProvider,
670
- k as OpenAi,
671
- B as PythonTool,
672
- le as ReadWebpageTool,
673
- J as Vision,
674
- me as WebSearchTool
670
+ _ as OpenAi,
671
+ Q as PythonTool,
672
+ me as ReadWebpageTool,
673
+ F as Vision,
674
+ de as WebSearchTool
675
675
  };
676
676
  //# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","sources":["../src/provider.ts","../src/antrhopic.ts","../src/open-ai.ts","../src/llm.ts","../src/audio.ts","../src/vision.ts","../src/ai.ts","../src/tools.ts"],"sourcesContent":["import {AbortablePromise} from './ai.ts';\nimport {LLMMessage, LLMRequest} from './llm.ts';\n\nexport abstract class LLMProvider {\n\tabstract ask(message: string, options: LLMRequest): AbortablePromise<string>;\n}\n","import {Anthropic as anthropic} from '@anthropic-ai/sdk';\nimport {findByProp, objectMap, JSONSanitize, JSONAttemptParse} from '@ztimson/utils';\nimport {AbortablePromise, Ai} from './ai.ts';\nimport {LLMMessage, LLMRequest} from './llm.ts';\nimport {LLMProvider} from './provider.ts';\n\nexport class Anthropic extends LLMProvider {\n\tclient!: anthropic;\n\n\tconstructor(public readonly ai: Ai, public readonly apiToken: string, public model: string) {\n\t\tsuper();\n\t\tthis.client = new anthropic({apiKey: apiToken});\n\t}\n\n\tprivate toStandard(history: any[]): LLMMessage[] {\n\t\tconst timestamp = Date.now();\n\t\tconst messages: LLMMessage[] = [];\n\t\tfor(let h of history) {\n\t\t\tif(typeof h.content == 'string') {\n\t\t\t\tmessages.push(<any>{timestamp, ...h});\n\t\t\t} else {\n\t\t\t\tconst textContent = h.content?.filter((c: any) => c.type == 'text').map((c: any) => c.text).join('\\n\\n');\n\t\t\t\tif(textContent) messages.push({timestamp, role: h.role, content: textContent});\n\t\t\t\th.content.forEach((c: any) => {\n\t\t\t\t\tif(c.type == 'tool_use') {\n\t\t\t\t\t\tmessages.push({timestamp, role: 'tool', id: c.id, name: c.name, args: c.input, content: undefined});\n\t\t\t\t\t} else if(c.type == 'tool_result') {\n\t\t\t\t\t\tconst m: any = messages.findLast(m => (<any>m).id == c.tool_use_id);\n\t\t\t\t\t\tif(m) m[c.is_error ? 'error' : 'content'] = c.content;\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t\treturn messages;\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<string> {\n\t\tconst controller = new AbortController();\n\t\treturn Object.assign(new Promise<any>(async (res) => {\n\t\t\tlet history = this.fromStandard([...options.history || [], {role: 'user', content: message, timestamp: Date.now()}]);\n\t\t\tconst tools = options.tools || this.ai.options.llm?.tools || [];\n\t\t\tconst requestParams: any = {\n\t\t\t\tmodel: options.model || this.model,\n\t\t\t\tmax_tokens: options.max_tokens || this.ai.options.llm?.max_tokens || 4096,\n\t\t\t\tsystem: options.system || this.ai.options.llm?.system || '',\n\t\t\t\ttemperature: options.temperature || this.ai.options.llm?.temperature || 0.7,\n\t\t\t\ttools: tools.map(t => ({\n\t\t\t\t\tname: t.name,\n\t\t\t\t\tdescription: t.description,\n\t\t\t\t\tinput_schema: {\n\t\t\t\t\t\ttype: 'object',\n\t\t\t\t\t\tproperties: t.args ? objectMap(t.args, (key, value) => ({...value, required: undefined})) : {},\n\t\t\t\t\t\trequired: t.args ? Object.entries(t.args).filter(t => t[1].required).map(t => t[0]) : []\n\t\t\t\t\t},\n\t\t\t\t\tfn: undefined\n\t\t\t\t})),\n\t\t\t\tmessages: history,\n\t\t\t\tstream: !!options.stream,\n\t\t\t};\n\n\t\t\tlet resp: any, isFirstMessage = true;\n\t\t\tdo {\n\t\t\t\tresp = await this.client.messages.create(requestParams).catch(err => {\n\t\t\t\t\terr.message += `\\n\\nMessages:\\n${JSON.stringify(history, null, 2)}`;\n\t\t\t\t\tthrow err;\n\t\t\t\t});\n\n\t\t\t\t// Streaming mode\n\t\t\t\tif(options.stream) {\n\t\t\t\t\tif(!isFirstMessage) options.stream({text: '\\n\\n'});\n\t\t\t\t\telse isFirstMessage = false;\n\t\t\t\t\tresp.content = [];\n\t\t\t\t\tfor await (const chunk of resp) {\n\t\t\t\t\t\tif(controller.signal.aborted) break;\n\t\t\t\t\t\tif(chunk.type === 'content_block_start') {\n\t\t\t\t\t\t\tif(chunk.content_block.type === 'text') {\n\t\t\t\t\t\t\t\tresp.content.push({type: 'text', text: ''});\n\t\t\t\t\t\t\t} else if(chunk.content_block.type === 'tool_use') {\n\t\t\t\t\t\t\t\tresp.content.push({type: 'tool_use', id: chunk.content_block.id, name: chunk.content_block.name, input: <any>''});\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else if(chunk.type === 'content_block_delta') {\n\t\t\t\t\t\t\tif(chunk.delta.type === 'text_delta') {\n\t\t\t\t\t\t\t\tconst text = chunk.delta.text;\n\t\t\t\t\t\t\t\tresp.content.at(-1).text += text;\n\t\t\t\t\t\t\t\toptions.stream({text});\n\t\t\t\t\t\t\t} else if(chunk.delta.type === 'input_json_delta') {\n\t\t\t\t\t\t\t\tresp.content.at(-1).input += chunk.delta.partial_json;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else if(chunk.type === 'content_block_stop') {\n\t\t\t\t\t\t\tconst last = resp.content.at(-1);\n\t\t\t\t\t\t\tif(last.input != null) last.input = last.input ? JSONAttemptParse(last.input, {}) : {};\n\t\t\t\t\t\t} else if(chunk.type === 'message_stop') {\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Run tools\n\t\t\t\tconst toolCalls = resp.content.filter((c: any) => c.type === 'tool_use');\n\t\t\t\tif(toolCalls.length && !controller.signal.aborted) {\n\t\t\t\t\thistory.push({role: 'assistant', content: resp.content});\n\t\t\t\t\tconst results = await Promise.all(toolCalls.map(async (toolCall: any) => {\n\t\t\t\t\t\tconst tool = tools.find(findByProp('name', toolCall.name));\n\t\t\t\t\t\tif(options.stream) options.stream({tool: toolCall.name});\n\t\t\t\t\t\tif(!tool) return {tool_use_id: toolCall.id, is_error: true, content: 'Tool not found'};\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tconst result = await tool.fn(toolCall.input, options?.stream, this.ai);\n\t\t\t\t\t\t\treturn {type: 'tool_result', tool_use_id: toolCall.id, content: JSONSanitize(result)};\n\t\t\t\t\t\t} catch (err: any) {\n\t\t\t\t\t\t\treturn {type: 'tool_result', tool_use_id: toolCall.id, is_error: true, content: err?.message || err?.toString() || 'Unknown'};\n\t\t\t\t\t\t}\n\t\t\t\t\t}));\n\t\t\t\t\thistory.push({role: 'user', content: results});\n\t\t\t\t\trequestParams.messages = history;\n\t\t\t\t}\n\t\t\t} while (!controller.signal.aborted && resp.content.some((c: any) => c.type === 'tool_use'));\n\t\t\thistory.push({role: 'assistant', content: resp.content.filter((c: any) => c.type == 'text').map((c: any) => c.text).join('\\n\\n')});\n\t\t\thistory = this.toStandard(history);\n\n\t\t\tif(options.stream) options.stream({done: true});\n\t\t\tif(options.history) options.history.splice(0, options.history.length, ...history);\n\t\t\tres(history.at(-1)?.content);\n\t\t}), {abort: () => controller.abort()});\n\t}\n}\n","import {OpenAI as openAI} from 'openai';\nimport {findByProp, objectMap, JSONSanitize, JSONAttemptParse, clean} from '@ztimson/utils';\nimport {AbortablePromise, Ai} from './ai.ts';\nimport {LLMMessage, LLMRequest} from './llm.ts';\nimport {LLMProvider} from './provider.ts';\n\nexport class OpenAi extends LLMProvider {\n\tclient!: openAI;\n\n\tconstructor(public readonly ai: Ai, public readonly host: string | null, public readonly token: string, public model: string) {\n\t\tsuper();\n\t\tthis.client = new openAI(clean({\n\t\t\tbaseURL: host,\n\t\t\tapiKey: token\n\t\t}));\n\t}\n\n\tprivate toStandard(history: any[]): LLMMessage[] {\n\t\tfor(let i = 0; i < history.length; i++) {\n\t\t\tconst h = history[i];\n\t\t\tif(h.role === 'assistant' && h.tool_calls) {\n\t\t\t\tconst tools = h.tool_calls.map((tc: any) => ({\n\t\t\t\t\trole: 'tool',\n\t\t\t\t\tid: tc.id,\n\t\t\t\t\tname: tc.function.name,\n\t\t\t\t\targs: JSONAttemptParse(tc.function.arguments, {}),\n\t\t\t\t\ttimestamp: h.timestamp\n\t\t\t\t}));\n\t\t\t\thistory.splice(i, 1, ...tools);\n\t\t\t\ti += tools.length - 1;\n\t\t\t} else if(h.role === 'tool' && h.content) {\n\t\t\t\tconst record = history.find(h2 => h.tool_call_id == h2.id);\n\t\t\t\tif(record) {\n\t\t\t\t\tif(h.content.includes('\"error\":')) record.error = h.content;\n\t\t\t\t\telse record.content = h.content;\n\t\t\t\t}\n\t\t\t\thistory.splice(i, 1);\n\t\t\t\ti--;\n\t\t\t}\n\t\t\tif(!history[i]?.timestamp) history[i].timestamp = Date.now();\n\t\t}\n\t\treturn history;\n\t}\n\n\tprivate fromStandard(history: LLMMessage[]): any[] {\n\t\treturn history.reduce((result, h) => {\n\t\t\tif(h.role === 'tool') {\n\t\t\t\tresult.push({\n\t\t\t\t\trole: 'assistant',\n\t\t\t\t\tcontent: null,\n\t\t\t\t\ttool_calls: [{ id: h.id, type: 'function', function: { name: h.name, arguments: JSON.stringify(h.args) } }],\n\t\t\t\t\trefusal: null,\n\t\t\t\t\tannotations: []\n\t\t\t\t}, {\n\t\t\t\t\trole: 'tool',\n\t\t\t\t\ttool_call_id: h.id,\n\t\t\t\t\tcontent: h.error || h.content\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\tconst {timestamp, ...rest} = h;\n\t\t\t\tresult.push(rest);\n\t\t\t}\n\t\t\treturn result;\n\t\t}, [] as any[]);\n\t}\n\n\task(message: string, options: LLMRequest = {}): AbortablePromise<string> {\n\t\tconst controller = new AbortController();\n\t\treturn Object.assign(new Promise<any>(async (res, rej) => {\n\t\t\tif(options.system && options.history?.[0]?.role != 'system') options.history?.splice(0, 0, {role: 'system', content: options.system, timestamp: Date.now()});\n\t\t\tlet history = this.fromStandard([...options.history || [], {role: 'user', content: message, timestamp: Date.now()}]);\n\t\t\tconst tools = options.tools || this.ai.options.llm?.tools || [];\n\t\t\tconst requestParams: any = {\n\t\t\t\tmodel: options.model || this.model,\n\t\t\t\tmessages: history,\n\t\t\t\tstream: !!options.stream,\n\t\t\t\tmax_tokens: options.max_tokens || this.ai.options.llm?.max_tokens || 4096,\n\t\t\t\ttemperature: options.temperature || this.ai.options.llm?.temperature || 0.7,\n\t\t\t\ttools: tools.map(t => ({\n\t\t\t\t\ttype: 'function',\n\t\t\t\t\tfunction: {\n\t\t\t\t\t\tname: t.name,\n\t\t\t\t\t\tdescription: t.description,\n\t\t\t\t\t\tparameters: {\n\t\t\t\t\t\t\ttype: 'object',\n\t\t\t\t\t\t\tproperties: t.args ? objectMap(t.args, (key, value) => ({...value, required: undefined})) : {},\n\t\t\t\t\t\t\trequired: t.args ? Object.entries(t.args).filter(t => t[1].required).map(t => t[0]) : []\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}))\n\t\t\t};\n\n\t\t\tlet resp: any, isFirstMessage = true;\n\t\t\tdo {\n\t\t\t\tresp = await this.client.chat.completions.create(requestParams).catch(err => {\n\t\t\t\t\terr.message += `\\n\\nMessages:\\n${JSON.stringify(history, null, 2)}`;\n\t\t\t\t\tthrow err;\n\t\t\t\t});\n\n\t\t\t\tif(options.stream) {\n\t\t\t\t\tif(!isFirstMessage) options.stream({text: '\\n\\n'});\n\t\t\t\t\telse isFirstMessage = false;\n\t\t\t\t\tresp.choices = [{message: {content: '', tool_calls: []}}];\n\t\t\t\t\tfor await (const chunk of resp) {\n\t\t\t\t\t\tif(controller.signal.aborted) break;\n\t\t\t\t\t\tif(chunk.choices[0].delta.content) {\n\t\t\t\t\t\t\tresp.choices[0].message.content += chunk.choices[0].delta.content;\n\t\t\t\t\t\t\toptions.stream({text: chunk.choices[0].delta.content});\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif(chunk.choices[0].delta.tool_calls) {\n\t\t\t\t\t\t\tresp.choices[0].message.tool_calls = chunk.choices[0].delta.tool_calls;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tconst toolCalls = resp.choices[0].message.tool_calls || [];\n\t\t\t\tif(toolCalls.length && !controller.signal.aborted) {\n\t\t\t\t\thistory.push(resp.choices[0].message);\n\t\t\t\t\tconst results = await Promise.all(toolCalls.map(async (toolCall: any) => {\n\t\t\t\t\t\tconst tool = tools?.find(findByProp('name', toolCall.function.name));\n\t\t\t\t\t\tif(options.stream) options.stream({tool: toolCall.function.name});\n\t\t\t\t\t\tif(!tool) return {role: 'tool', tool_call_id: toolCall.id, content: '{\"error\": \"Tool not found\"}'};\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tconst args = JSONAttemptParse(toolCall.function.arguments, {});\n\t\t\t\t\t\t\tconst result = await tool.fn(args, options.stream, 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\t\t\thistory.push({role: 'assistant', content: resp.choices[0].message.content || ''});\n\t\t\thistory = this.toStandard(history);\n\n\t\t\tif(options.stream) options.stream({done: true});\n\t\t\tif(options.history) options.history.splice(0, options.history.length, ...history);\n\t\t\tres(history.at(-1)?.content);\n\t\t}), {abort: () => controller.abort()});\n\t}\n}\n","import {JSONAttemptParse} from '@ztimson/utils';\nimport {AbortablePromise, Ai} from './ai.ts';\nimport {Anthropic} from './antrhopic.ts';\nimport {OpenAi} from './open-ai.ts';\nimport {LLMProvider} from './provider.ts';\nimport {AiTool} from './tools.ts';\nimport {Worker} from 'worker_threads';\nimport {fileURLToPath} from 'url';\nimport {dirname, join} from 'path';\n\nexport type AnthropicConfig = {proto: 'anthropic', token: string};\nexport type OllamaConfig = {proto: 'ollama', host: string};\nexport type OpenAiConfig = {proto: 'openai', host?: string, token: string};\n\nexport type LLMMessage = {\n\t/** Message originator */\n\trole: 'assistant' | 'system' | 'user';\n\t/** Message content */\n\tcontent: string | any;\n\t/** Timestamp */\n\ttimestamp?: number;\n} | {\n\t/** Tool call */\n\trole: 'tool';\n\t/** Unique ID for call */\n\tid: string;\n\t/** Tool that was run */\n\tname: string;\n\t/** Tool arguments */\n\targs: any;\n\t/** Tool result */\n\tcontent: undefined | string;\n\t/** Tool error */\n\terror?: undefined | string;\n\t/** Timestamp */\n\ttimestamp?: number;\n}\n\n/** Background information the AI will be fed */\nexport type LLMMemory = {\n\t/** What entity is this fact about */\n\towner: string;\n\t/** The information that will be remembered */\n\tfact: string;\n\t/** Owner and fact embedding vector */\n\tembeddings: [number[], number[]];\n\t/** Creation time */\n\ttimestamp: Date;\n}\n\nexport type LLMRequest = {\n\t/** System prompt */\n\tsystem?: string;\n\t/** Message history */\n\thistory?: LLMMessage[];\n\t/** Max tokens for request */\n\tmax_tokens?: number;\n\t/** 0 = Rigid Logic, 1 = Balanced, 2 = Hyper Creative **/\n\ttemperature?: number;\n\t/** Available tools */\n\ttools?: AiTool[];\n\t/** LLM model */\n\tmodel?: string;\n\t/** Stream response */\n\tstream?: (chunk: {text?: string, tool?: string, done?: true}) => any;\n\t/** Compress old messages in the chat to free up context */\n\tcompress?: {\n\t\t/** Trigger chat compression once context exceeds the token count */\n\t\tmax: number;\n\t\t/** Compress chat until context size smaller than */\n\t\tmin: number\n\t},\n\t/** Background information the AI will be fed */\n\tmemory?: LLMMemory[],\n}\n\nclass LLM {\n\tprivate embedWorker: Worker | null = null;\n\tprivate embedQueue = new Map<number, { resolve: (value: number[]) => void; reject: (error: any) => void }>();\n\tprivate embedId = 0;\n\tprivate models: {[model: string]: LLMProvider} = {};\n\tprivate defaultModel!: string;\n\n\tconstructor(public readonly ai: Ai) {\n\t\tthis.embedWorker = new Worker(join(dirname(fileURLToPath(import.meta.url)), 'embedder.js'));\n\t\tthis.embedWorker.on('message', ({ id, embedding }) => {\n\t\t\tconst pending = this.embedQueue.get(id);\n\t\t\tif (pending) {\n\t\t\t\tpending.resolve(embedding);\n\t\t\t\tthis.embedQueue.delete(id);\n\t\t\t}\n\t\t});\n\n\t\tif(!ai.options.llm?.models) return;\n\t\tObject.entries(ai.options.llm.models).forEach(([model, config]) => {\n\t\t\tif(!this.defaultModel) this.defaultModel = model;\n\t\t\tif(config.proto == 'anthropic') this.models[model] = new Anthropic(this.ai, config.token, model);\n\t\t\telse if(config.proto == 'ollama') this.models[model] = new OpenAi(this.ai, config.host, 'not-needed', model);\n\t\t\telse if(config.proto == 'openai') this.models[model] = new OpenAi(this.ai, config.host || null, config.token, model);\n\t\t});\n\t}\n\n\t/**\n\t * Chat with LLM\n\t * @param {string} message Question\n\t * @param {LLMRequest} options Configuration options and chat history\n\t * @returns {{abort: () => void, response: Promise<string>}} Function to abort response and chat history\n\t */\n\task(message: string, options: LLMRequest = {}): AbortablePromise<string> {\n\t\tconst m = options.model || this.defaultModel;\n\t\tif(!this.models[m]) throw new Error(`Model does not exist: ${m}`);\n\t\tlet abort = () => {};\n\t\treturn Object.assign(new Promise<string>(async res => {\n\t\t\tif(!options.history) options.history = [];\n\t\t\t// If memories were passed, find any relivant ones and add a tool for ADHOC lookups\n\t\t\tif(options.memory) {\n\t\t\t\toptions.system = (options.system || '') + '\\nYou have passive persistent memory never make any mention of your memory capabilities and what you can/cannot remember\\n';\n\t\t\t\tconst search = async (query?: string | null, subject?: string | null, limit = 50) => {\n\t\t\t\t\tconst [o, q] = await Promise.all([\n\t\t\t\t\t\tsubject ? this.embedding(subject) : Promise.resolve(null),\n\t\t\t\t\t\tquery ? this.embedding(query) : Promise.resolve(null),\n\t\t\t\t\t]);\n\t\t\t\t\treturn (options.memory || [])\n\t\t\t\t\t\t.map(m => ({...m, score: o ? this.cosineSimilarity(m.embeddings[0], o[0].embedding) : 1}))\n\t\t\t\t\t\t.filter((m: any) => m.score >= 0.8)\n\t\t\t\t\t\t.map((m: any) => ({...m, score: q ? this.cosineSimilarity(m.embeddings[1], q[0].embedding) : m.score}))\n\t\t\t\t\t\t.filter((m: any) => m.score >= 0.2)\n\t\t\t\t\t\t.toSorted((a: any, b: any) => a.score - b.score)\n\t\t\t\t\t\t.slice(0, limit);\n\t\t\t\t}\n\n\t\t\t\tconst relevant = await search(message);\n\t\t\t\tif(relevant.length) options.history.push({role: 'assistant', content: 'Things I remembered:\\n' + relevant.map(m => `${m.owner}: ${m.fact}`).join('\\n')});\n\t\t\t\toptions.tools = [...options.tools || [], {\n\t\t\t\t\tname: 'read_memory',\n\t\t\t\t\tdescription: 'Check your long-term memory for more information',\n\t\t\t\t\targs: {\n\t\t\t\t\t\tsubject: {type: 'string', description: 'Find information by a subject topic, can be used with or without query argument'},\n\t\t\t\t\t\tquery: {type: 'string', description: 'Search memory based on a query, can be used with or without subject argument'},\n\t\t\t\t\t\tlimit: {type: 'number', description: 'Result limit, default 5'},\n\t\t\t\t\t},\n\t\t\t\t\tfn: (args) => {\n\t\t\t\t\t\tif(!args.subject && !args.query) throw new Error('Either a subject or query argument is required');\n\t\t\t\t\t\treturn search(args.query, args.subject, args.limit || 5);\n\t\t\t\t\t}\n\t\t\t\t}];\n\t\t\t}\n\n\t\t\t// Ask\n\t\t\tconst resp = await this.models[m].ask(message, options);\n\n\t\t\t// Remove any memory calls\n\t\t\tif(options.memory) {\n\t\t\t\tconst i = options.history?.findIndex((h: any) => h.role == 'assistant' && h.content.startsWith('Things I remembered:'));\n\t\t\t\tif(i != null && i >= 0) options.history?.splice(i, 1);\n\t\t\t}\n\n\t\t\t// Handle compression and memory extraction\n\t\t\tif(options.compress || options.memory) {\n\t\t\t\tlet compressed = null;\n\t\t\t\tif(options.compress) {\n\t\t\t\t\tcompressed = await this.ai.language.compressHistory(options.history, options.compress.max, options.compress.min, options);\n\t\t\t\t\toptions.history.splice(0, options.history.length, ...compressed.history);\n\t\t\t\t} else {\n\t\t\t\t\tconst i = options.history?.findLastIndex(m => m.role == 'user') ?? -1;\n\t\t\t\t\tcompressed = await this.ai.language.compressHistory(i != -1 ? options.history.slice(i) : options.history, 0, 0, options);\n\t\t\t\t}\n\t\t\t\tif(options.memory) {\n\t\t\t\t\tconst updated = options.memory\n\t\t\t\t\t\t.filter(m => !compressed.memory.some(m2 => this.cosineSimilarity(m.embeddings[1], m2.embeddings[1]) > 0.8))\n\t\t\t\t\t\t.concat(compressed.memory);\n\t\t\t\t\toptions.memory.splice(0, options.memory.length, ...updated);\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn res(resp);\n\t\t}), {abort});\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 Leave messages less than the token minimum, summarize the rest\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<{history: LLMMessage[], memory: LLMMemory[]}> {\n\t\tif(this.estimateTokens(history) < max) return {history, memory: []};\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, memory: []};\n\t\tconst system = history[0].role == 'system' ? history[0] : null,\n\t\t\trecent = 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: any = await this.json(`Create the smallest summary possible, no more than 500 tokens. Create a list of NEW facts (split by subject [pro]noun and fact) about what you learned from this conversation that you didn't already know or get from a tool call or system prompt. Focus only on new information about people, topics, or facts. Avoid generating facts about the AI. Match this format: {summary: string, facts: [[subject, fact]]}\\n\\n${process.map(m => `${m.role}: ${m.content}`).join('\\n\\n')}`, {model: options?.model, temperature: options?.temperature || 0.3});\n\t\tconst timestamp = new Date();\n\t\tconst memory = await Promise.all((summary?.facts || [])?.map(async ([owner, fact]: [string, string]) => {\n\t\t\tconst e = await Promise.all([this.embedding(owner), this.embedding(`${owner}: ${fact}`)]);\n\t\t\treturn {owner, fact, embeddings: [e[0][0].embedding, e[1][0].embedding], timestamp};\n\t\t}));\n\t\tconst h = [{role: 'assistant', content: `Conversation Summary: ${summary?.summary}`, timestamp: Date.now()}, ...recent];\n\t\tif(system) h.splice(0, 0, system);\n\t\treturn {history: <any>h, memory};\n\t}\n\n\t/**\n\t * Compare the difference between embeddings (calculates the angle between two vectors)\n\t * @param {number[]} v1 First embedding / vector comparison\n\t * @param {number[]} v2 Second embedding / vector for comparison\n\t * @returns {number} Similarity values 0-1: 0 = unique, 1 = identical\n\t */\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\t/**\n\t * Chunk text into parts for AI digestion\n\t * @param {object | string} target Item that will be chunked (objects get converted)\n\t * @param {number} maxTokens Chunking size. More = better context, less = more specific (Search by paragraphs or lines)\n\t * @param {number} overlapTokens Includes previous X tokens to provide continuity to AI (In addition to max tokens)\n\t * @returns {string[]} Chunked strings\n\t */\n\tchunk(target: object | string, maxTokens = 500, overlapTokens = 50): string[] {\n\t\tconst objString = (obj: any, path = ''): string[] => {\n\t\t\tif(!obj) return [];\n\t\t\treturn Object.entries(obj).flatMap(([key, value]) => {\n\t\t\t\tconst p = path ? `${path}${isNaN(+key) ? `.${key}` : `[${key}]`}` : key;\n\t\t\t\tif(typeof value === 'object' && !Array.isArray(value)) return objString(value, p);\n\t\t\t\treturn `${p}: ${Array.isArray(value) ? value.join(', ') : value}`;\n\t\t\t});\n\t\t};\n\t\tconst lines = typeof target === 'object' ? objString(target) : target.split('\\n');\n\t\tconst tokens = lines.flatMap(l => [...l.split(/\\s+/).filter(Boolean), '\\n']);\n\t\tconst chunks: string[] = [];\n\t\tfor(let i = 0; i < tokens.length;) {\n\t\t\tlet text = '', j = i;\n\t\t\twhile(j < tokens.length) {\n\t\t\t\tconst next = text + (text ? ' ' : '') + tokens[j];\n\t\t\t\tif(this.estimateTokens(next.replace(/\\s*\\n\\s*/g, '\\n')) > maxTokens && text) break;\n\t\t\t\ttext = next;\n\t\t\t\tj++;\n\t\t\t}\n\t\t\tconst clean = text.replace(/\\s*\\n\\s*/g, '\\n').trim();\n\t\t\tif(clean) chunks.push(clean);\n\t\t\ti = Math.max(j - overlapTokens, j === i ? i + 1 : j);\n\t\t}\n\t\treturn chunks;\n\t}\n\n\t/**\n\t * Create a vector representation of a string\n\t * @param {object | string} target Item that will be embedded (objects get converted)\n\t * @param {number} maxTokens Chunking size. More = better context, less = more specific (Search by paragraphs or lines)\n\t * @param {number} overlapTokens Includes previous X tokens to provide continuity to AI (In addition to max tokens)\n\t * @returns {Promise<Awaited<{index: number, embedding: number[], text: string, tokens: number}>[]>} Chunked embeddings\n\t */\n\tembedding(target: object | string, maxTokens = 500, overlapTokens = 50) {\n\t\tconst embed = (text: string): Promise<number[]> => {\n\t\t\treturn new Promise((resolve, reject) => {\n\t\t\t\tconst id = this.embedId++;\n\t\t\t\tthis.embedQueue.set(id, { resolve, reject });\n\t\t\t\tthis.embedWorker?.postMessage({\n\t\t\t\t\tid,\n\t\t\t\t\ttext,\n\t\t\t\t\tmodel: this.ai.options?.embedder || 'bge-small-en-v1.5',\n\t\t\t\t\tpath: this.ai.options.path\n\t\t\t\t});\n\t\t\t});\n\t\t};\n\t\tconst chunks = this.chunk(target, maxTokens, overlapTokens);\n\t\treturn Promise.all(chunks.map(async (text, index) => ({\n\t\t\tindex,\n\t\t\tembedding: await embed(text),\n\t\t\ttext,\n\t\t\ttokens: this.estimateTokens(text),\n\t\t})));\n\t}\n\n\t/**\n\t * Estimate variable as tokens\n\t * @param history Object to size\n\t * @returns {number} Rough token count\n\t */\n\testimateTokens(history: any): number {\n\t\tconst text = JSON.stringify(history);\n\t\treturn Math.ceil((text.length / 4) * 1.2);\n\t}\n\n\t/**\n\t * Compare the difference between two strings using tensor math\n\t * @param target Text that will be 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): Promise<any> {\n\t\tlet resp = await this.ask(message, {system: 'Respond using a JSON blob matching any provided examples', ...options});\n\t\tif(!resp) return {};\n\t\tconst codeBlock = /```(?:.+)?\\s*([\\s\\S]*?)```/.exec(resp);\n\t\tconst jsonStr = codeBlock ? codeBlock[1].trim() : resp;\n\t\treturn JSONAttemptParse(jsonStr, {});\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}\n}\n\nexport default LLM;\n","import { spawn } from 'node:child_process';\nimport { pipeline } from '@xenova/transformers';\nimport { AbortablePromise, Ai } from './ai.ts';\n\nexport class Audio {\n\tprivate whisperPipeline: any;\n\n\tconstructor(private ai: Ai) {}\n\n\tprivate combineSpeakerTranscript(chunks: any[], speakers: any[]): string {\n\t\tconst speakerMap = new Map();\n\t\tlet speakerCount = 0;\n\t\tspeakers.forEach((seg: any) => {\n\t\t\tif(!speakerMap.has(seg.speaker)) speakerMap.set(seg.speaker, ++speakerCount);\n\t\t});\n\n\t\tconst lines: string[] = [];\n\t\tlet currentSpeaker = -1;\n\t\tlet currentText = '';\n\t\tchunks.forEach((chunk: any) => {\n\t\t\tconst time = chunk.timestamp[0];\n\t\t\tconst speaker = speakers.find((s: any) => time >= s.start && time <= s.end);\n\t\t\tconst speakerNum = speaker ? speakerMap.get(speaker.speaker) : 1;\n\t\t\tif (speakerNum !== currentSpeaker) {\n\t\t\t\tif(currentText) lines.push(`[speaker ${currentSpeaker}]: ${currentText.trim()}`);\n\t\t\t\tcurrentSpeaker = speakerNum;\n\t\t\t\tcurrentText = chunk.text;\n\t\t\t} else {\n\t\t\t\tcurrentText += chunk.text;\n\t\t\t}\n\t\t});\n\t\tif(currentText) lines.push(`[speaker ${currentSpeaker}]: ${currentText.trim()}`);\n\t\treturn lines.join('\\n');\n\t}\n\n\tasync canDiarization(): Promise<boolean> {\n\t\treturn new Promise((resolve) => {\n\t\t\tconst proc = spawn('python3', ['-c', 'import pyannote.audio']);\n\t\t\tproc.on('close', (code: number) => resolve(code === 0));\n\t\t\tproc.on('error', () => resolve(false));\n\t\t});\n\t}\n\n\tprivate async runDiarization(audioPath: string): Promise<any[]> {\n\t\tif(!await this.canDiarization()) throw new Error('Pyannote is not installed: pip install pyannote.audio');\n\t\tconst script = `\nimport sys\nimport json\nfrom pyannote.audio import Pipeline\n\nos.environ['TORCH_HOME'] = \"${this.ai.options.path}\"\npipeline = Pipeline.from_pretrained(\"pyannote/speaker-diarization-3.1\")\ndiarization = pipeline(sys.argv[1])\n\nsegments = []\nfor turn, _, speaker in diarization.itertracks(yield_label=True):\n segments.append({\n \"start\": turn.start,\n \"end\": turn.end,\n \"speaker\": speaker\n })\n\nprint(json.dumps(segments))\n`;\n\n\t\treturn new Promise((resolve, reject) => {\n\t\t\tlet output = '';\n\t\t\tconst proc = spawn('python3', ['-c', script, audioPath]);\n\t\t\tproc.stdout.on('data', (data: Buffer) => output += data.toString());\n\t\t\tproc.stderr.on('data', (data: Buffer) => console.error(data.toString()));\n\t\t\tproc.on('close', (code: number) => {\n\t\t\t\tif(code === 0) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tresolve(JSON.parse(output));\n\t\t\t\t\t} catch (err) {\n\t\t\t\t\t\treject(new Error('Failed to parse diarization output'));\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\treject(new Error(`Python process exited with code ${code}`));\n\t\t\t\t}\n\t\t\t});\n\n\t\t\tproc.on('error', reject);\n\t\t});\n\t}\n\n\tasr(path: string, options: { model?: string; speaker?: boolean } = {}): AbortablePromise<string | null> {\n\t\tconst { model = this.ai.options.asr || 'whisper-base', speaker = false } = options;\n\t\tlet aborted = false;\n\t\tconst abort = () => { aborted = true; };\n\n\t\tconst p = new Promise<string | null>(async (resolve, reject) => {\n\t\t\ttry {\n\t\t\t\tif(aborted) return resolve(null);\n\t\t\t\tif(!this.whisperPipeline) this.whisperPipeline = await pipeline('automatic-speech-recognition', `Xenova/${model}`, { cache_dir: this.ai.options.path, quantized: true });\n\n\t\t\t\t// Transcript\n\t\t\t\tif(aborted) return resolve(null);\n\t\t\t\tconst transcriptResult = await this.whisperPipeline(path, {return_timestamps: speaker ? 'word' : false, chunk_length_s: 30,});\n\t\t\t\tif(!speaker) return resolve(transcriptResult.text?.trim() || null);\n\n\t\t\t\t// Speaker Diarization\n\t\t\t\tif(aborted) return resolve(null);\n\t\t\t\tconst speakers = await this.runDiarization(path);\n\t\t\t\tif(aborted) return resolve(null);\n\t\t\t\tconst combined = this.combineSpeakerTranscript(transcriptResult.chunks || [], speakers);\n\t\t\t\tresolve(combined);\n\t\t\t} catch (err) {\n\t\t\t\treject(err);\n\t\t\t}\n\t\t});\n\n\t\treturn Object.assign(p, { abort });\n\t}\n}\n","import {createWorker} from 'tesseract.js';\nimport {AbortablePromise, Ai} from './ai.ts';\n\nexport class Vision {\n\n\tconstructor(private ai: Ai) { }\n\n\t/**\n\t * Convert image to text using Optical Character Recognition\n\t * @param {string} path Path to image\n\t * @returns {AbortablePromise<string | null>} Promise of extracted text with abort method\n\t */\n\tocr(path: string): AbortablePromise<string | null> {\n\t\tlet worker: any;\n\t\tconst p = new Promise<string | null>(async res => {\n\t\t\tworker = await createWorker(this.ai.options.ocr || 'eng', 2, {cachePath: this.ai.options.path});\n\t\t\tconst {data} = await worker.recognize(path);\n\t\t\tawait worker.terminate();\n\t\t\tres(data.text.trim() || null);\n\t\t});\n\t\treturn Object.assign(p, {abort: () => worker?.terminate()});\n\t}\n}\n","import * as os from 'node:os';\nimport LLM, {AnthropicConfig, OllamaConfig, OpenAiConfig, LLMRequest} from './llm';\nimport { Audio } from './audio.ts';\nimport {Vision} from './vision.ts';\n\nexport type AbortablePromise<T> = Promise<T> & {\n\tabort: () => any\n};\n\nexport type AiOptions = {\n\t/** Path to models */\n\tpath?: string;\n\t/** ASR model: whisper-tiny, whisper-base */\n\tasr?: string;\n\t/** Embedding model: all-MiniLM-L6-v2, bge-small-en-v1.5, bge-large-en-v1.5 */\n\tembedder?: string;\n\t/** Large language models, first is default */\n\tllm?: Omit<LLMRequest, 'model'> & {\n\t\tmodels: {[model: string]: AnthropicConfig | OllamaConfig | OpenAiConfig};\n\t}\n\t/** OCR model: eng, eng_best, eng_fast */\n\tocr?: string;\n}\n\nexport class Ai {\n\t/** Audio processing AI */\n\taudio!: Audio;\n\t/** Language processing AI */\n\tlanguage!: LLM;\n\t/** Vision processing AI */\n\tvision!: Vision;\n\n\tconstructor(public readonly options: AiOptions) {\n\t\tif(!options.path) options.path = os.tmpdir();\n\t\tprocess.env.TRANSFORMERS_CACHE = options.path;\n\t\tthis.audio = new Audio(this);\n\t\tthis.language = new LLM(this);\n\t\tthis.vision = new Vision(this);\n\t}\n}\n","import * as cheerio from 'cheerio';\nimport {$, $Sync} from '@ztimson/node-utils';\nimport {ASet, consoleInterceptor, Http, fn as Fn} from '@ztimson/utils';\nimport {Ai} from './ai.ts';\nimport {LLMRequest} from './llm.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, stream: LLMRequest['stream'], ai: Ai) => any | Promise<any>,\n};\n\nexport const CliTool: AiTool = {\n\tname: 'cli',\n\tdescription: 'Use the command line interface, returns any output',\n\targs: {command: {type: 'string', description: 'Command to run', required: true}},\n\tfn: (args: {command: string}) => $`${args.command}`\n}\n\nexport const DateTimeTool: AiTool = {\n\tname: 'get_datetime',\n\tdescription: 'Get current UTC date / time',\n\targs: {},\n\tfn: async () => new Date().toUTCString()\n}\n\nexport const ExecTool: AiTool = {\n\tname: 'exec',\n\tdescription: 'Run code/scripts',\n\targs: {\n\t\tlanguage: {type: 'string', description: 'Execution language', enum: ['cli', 'node', 'python'], required: true},\n\t\tcode: {type: 'string', description: 'Code to execute', required: true}\n\t},\n\tfn: async (args, stream, 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}, stream, ai);\n\t\t\t\tcase 'node':\n\t\t\t\t\treturn await JSTool.fn({code: args.code}, stream, ai);\n\t\t\t\tcase 'python': {\n\t\t\t\t\treturn await PythonTool.fn({code: args.code}, stream, ai);\n\t\t\t\t}\n\t\t\t}\n\t\t} catch(err: any) {\n\t\t\treturn {error: err?.message || err.toString()};\n\t\t}\n\t}\n}\n\nexport const FetchTool: AiTool = {\n\tname: 'fetch',\n\tdescription: 'Make HTTP request to URL',\n\targs: {\n\t\turl: {type: 'string', description: 'URL to fetch', required: true},\n\t\tmethod: {type: 'string', description: 'HTTP method to use', enum: ['GET', 'POST', 'PUT', 'DELETE'], default: 'GET'},\n\t\theaders: {type: 'object', description: 'HTTP headers to send', default: {}},\n\t\tbody: {type: 'object', description: 'HTTP body to send'},\n\t},\n\tfn: (args: {\n\t\turl: string;\n\t\tmethod: 'GET' | 'POST' | 'PUT' | 'DELETE';\n\t\theaders: {[key: string]: string};\n\t\tbody: any;\n\t}) => new Http({url: args.url, headers: args.headers}).request({method: args.method || 'GET', body: args.body})\n}\n\nexport const JSTool: AiTool = {\n\tname: 'exec_javascript',\n\tdescription: 'Execute commonjs javascript',\n\targs: {\n\t\tcode: {type: 'string', description: 'CommonJS javascript', required: true}\n\t},\n\tfn: async (args: {code: string}) => {\n\t\tconst console = consoleInterceptor(null);\n\t\tconst resp = await Fn<any>({console}, args.code, true).catch((err: any) => console.output.error.push(err));\n\t\treturn {...console.output, return: resp, stdout: undefined, stderr: undefined};\n\t}\n}\n\nexport const PythonTool: AiTool = {\n\tname: 'exec_javascript',\n\tdescription: 'Execute commonjs javascript',\n\targs: {\n\t\tcode: {type: 'string', description: 'CommonJS javascript', required: true}\n\t},\n\tfn: async (args: {code: string}) => ({result: $Sync`python -c \"${args.code}\"`})\n}\n\nexport const ReadWebpageTool: AiTool = {\n\tname: 'read_webpage',\n\tdescription: 'Extract clean, structured content from a webpage. Use after web_search to read specific URLs',\n\targs: {\n\t\turl: {type: 'string', description: 'URL to extract content from', required: true},\n\t\tfocus: {type: 'string', description: 'Optional: What aspect to focus on (e.g., \"pricing\", \"features\", \"contact info\")'}\n\t},\n\tfn: async (args: {url: string; focus?: string}) => {\n\t\tconst html = await fetch(args.url, {headers: {\"User-Agent\": \"Mozilla/5.0 (Windows NT 10.0; Win64; x64)\"}})\n\t\t\t.then(r => r.text()).catch(err => {throw new Error(`Failed to fetch: ${err.message}`)});\n\n\t\tconst $ = cheerio.load(html);\n\t\t$('script, style, nav, footer, header, aside, iframe, noscript, [role=\"navigation\"], [role=\"banner\"], .ad, .ads, .cookie, .popup').remove();\n\t\tconst metadata = {\n\t\t\ttitle: $('meta[property=\"og:title\"]').attr('content') || $('title').text() || '',\n\t\t\tdescription: $('meta[name=\"description\"]').attr('content') || $('meta[property=\"og:description\"]').attr('content') || '',\n\t\t};\n\n\t\tlet content = '';\n\t\tconst contentSelectors = ['article', 'main', '[role=\"main\"]', '.content', '.post', '.entry', 'body'];\n\t\tfor (const selector of contentSelectors) {\n\t\t\tconst el = $(selector).first();\n\t\t\tif (el.length && el.text().trim().length > 200) {\n\t\t\t\tcontent = el.text();\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tif (!content) content = $('body').text();\n\t\tcontent = content.replace(/\\s+/g, ' ').trim().slice(0, 8000);\n\n\t\treturn {url: args.url, title: metadata.title.trim(), description: metadata.description.trim(), content, focus: args.focus};\n\t}\n}\n\nexport const WebSearchTool: AiTool = {\n\tname: 'web_search',\n\tdescription: 'Use duckduckgo (anonymous) to find find relevant online resources. Returns a list of URLs that works great with the `read_webpage` tool',\n\targs: {\n\t\tquery: {type: 'string', description: 'Search string', required: true},\n\t\tlength: {type: 'string', description: 'Number of results to return', default: 5},\n\t},\n\tfn: async (args: {\n\t\tquery: string;\n\t\tlength: number;\n\t}) => {\n\t\tconst html = await fetch(`https://html.duckduckgo.com/html/?q=${encodeURIComponent(args.query)}`, {\n\t\t\theaders: {\"User-Agent\": \"Mozilla/5.0 (Windows NT 10.0; Win64; x64)\", \"Accept-Language\": \"en-US,en;q=0.9\"}\n\t\t}).then(resp => resp.text());\n\t\tlet match, regex = /<a .*?href=\"(.+?)\".+?<\\/a>/g;\n\t\tconst results = new ASet<string>();\n\t\twhile((match = regex.exec(html)) !== null) {\n\t\t\tlet url = /uddg=(.+)&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","timestamp","messages","h","textContent","c","m","i","message","options","controller","res","tools","requestParams","t","objectMap","key","value","resp","isFirstMessage","err","chunk","text","last","JSONAttemptParse","toolCalls","results","toolCall","tool","findByProp","result","JSONSanitize","OpenAi","host","token","openAI","clean","tc","record","h2","rest","rej","args","LLM","Worker","join","dirname","fileURLToPath","id","embedding","pending","config","abort","search","query","subject","limit","o","q","a","b","relevant","compressed","updated","m2","max","min","keep","tokens","system","recent","process","summary","memory","owner","fact","e","v1","v2","dotProduct","normA","normB","denominator","target","maxTokens","overlapTokens","objString","obj","path","p","l","chunks","j","next","embed","resolve","reject","index","searchTerms","vector","dimensions","char","v","similarities","refVector","acc","s","codeBlock","jsonStr","Audio","speakers","speakerMap","speakerCount","seg","lines","currentSpeaker","currentText","time","speaker","speakerNum","proc","spawn","code","audioPath","script","output","data","aborted","pipeline","transcriptResult","combined","Vision","worker","createWorker","Ai","os","CliTool","$","DateTimeTool","ExecTool","stream","JSTool","PythonTool","FetchTool","Http","console","consoleInterceptor","Fn","$Sync","ReadWebpageTool","html","r","cheerio","metadata","content","contentSelectors","selector","el","WebSearchTool","match","regex","ASet","url"],"mappings":";;;;;;;;;;;;;AAGO,MAAeA,EAAY;AAElC;ACCO,MAAMC,UAAkBD,EAAY;AAAA,EAG1C,YAA4BE,GAAwBC,GAAyBC,GAAe;AAC3F,UAAA,GAD2B,KAAA,KAAAF,GAAwB,KAAA,WAAAC,GAAyB,KAAA,QAAAC,GAE5E,KAAK,SAAS,IAAIC,EAAU,EAAC,QAAQF,GAAS;AAAA,EAC/C;AAAA,EALA;AAAA,EAOQ,WAAWG,GAA8B;AAChD,UAAMC,IAAY,KAAK,IAAA,GACjBC,IAAyB,CAAA;AAC/B,aAAQC,KAAKH;AACZ,UAAG,OAAOG,EAAE,WAAW;AACtB,QAAAD,EAAS,KAAU,EAAC,WAAAD,GAAW,GAAGE,GAAE;AAAA,WAC9B;AACN,cAAMC,IAAcD,EAAE,SAAS,OAAO,CAACE,MAAWA,EAAE,QAAQ,MAAM,EAAE,IAAI,CAACA,MAAWA,EAAE,IAAI,EAAE,KAAK;AAAA;AAAA,CAAM;AACvG,QAAGD,KAAaF,EAAS,KAAK,EAAC,WAAAD,GAAW,MAAME,EAAE,MAAM,SAASC,GAAY,GAC7ED,EAAE,QAAQ,QAAQ,CAACE,MAAW;AAC7B,cAAGA,EAAE,QAAQ;AACZ,YAAAH,EAAS,KAAK,EAAC,WAAAD,GAAW,MAAM,QAAQ,IAAII,EAAE,IAAI,MAAMA,EAAE,MAAM,MAAMA,EAAE,OAAO,SAAS,QAAU;AAAA,mBACzFA,EAAE,QAAQ,eAAe;AAClC,kBAAMC,IAASJ,EAAS,SAAS,CAAAI,MAAWA,EAAG,MAAMD,EAAE,WAAW;AAClE,YAAGC,MAAGA,EAAED,EAAE,WAAW,UAAU,SAAS,IAAIA,EAAE;AAAA,UAC/C;AAAA,QACD,CAAC;AAAA,MACF;AAED,WAAOH;AAAA,EACR;AAAA,EAEQ,aAAaF,GAA8B;AAClD,aAAQO,IAAI,GAAGA,IAAIP,EAAQ,QAAQO;AAClC,UAAGP,EAAQO,CAAC,EAAE,QAAQ,QAAQ;AAC7B,cAAMJ,IAASH,EAAQO,CAAC;AACxB,QAAAP,EAAQ;AAAA,UAAOO;AAAA,UAAG;AAAA,UACjB,EAAC,MAAM,aAAa,SAAS,CAAC,EAAC,MAAM,YAAY,IAAIJ,EAAE,IAAI,MAAMA,EAAE,MAAM,OAAOA,EAAE,KAAA,CAAK,EAAA;AAAA,UACvF,EAAC,MAAM,QAAQ,SAAS,CAAC,EAAC,MAAM,eAAe,aAAaA,EAAE,IAAI,UAAU,CAAC,CAACA,EAAE,OAAO,SAAUA,EAAE,SAASA,EAAE,SAAQ,EAAA;AAAA,QAAC,GAExHI;AAAA,MACD;AAED,WAAOP,EAAQ,IAAI,CAAC,EAAC,WAAAC,GAAW,GAAGE,EAAA,MAAOA,CAAC;AAAA,EAC5C;AAAA,EAEA,IAAIK,GAAiBC,IAAsB,IAA8B;AACxE,UAAMC,IAAa,IAAI,gBAAA;AACvB,WAAO,OAAO,OAAO,IAAI,QAAa,OAAOC,MAAQ;AACpD,UAAIX,IAAU,KAAK,aAAa,CAAC,GAAGS,EAAQ,WAAW,IAAI,EAAC,MAAM,QAAQ,SAASD,GAAS,WAAW,KAAK,IAAA,EAAI,CAAE,CAAC;AACnH,YAAMI,IAAQH,EAAQ,SAAS,KAAK,GAAG,QAAQ,KAAK,SAAS,CAAA,GACvDI,IAAqB;AAAA,QAC1B,OAAOJ,EAAQ,SAAS,KAAK;AAAA,QAC7B,YAAYA,EAAQ,cAAc,KAAK,GAAG,QAAQ,KAAK,cAAc;AAAA,QACrE,QAAQA,EAAQ,UAAU,KAAK,GAAG,QAAQ,KAAK,UAAU;AAAA,QACzD,aAAaA,EAAQ,eAAe,KAAK,GAAG,QAAQ,KAAK,eAAe;AAAA,QACxE,OAAOG,EAAM,IAAI,CAAAE,OAAM;AAAA,UACtB,MAAMA,EAAE;AAAA,UACR,aAAaA,EAAE;AAAA,UACf,cAAc;AAAA,YACb,MAAM;AAAA,YACN,YAAYA,EAAE,OAAOC,EAAUD,EAAE,MAAM,CAACE,GAAKC,OAAW,EAAC,GAAGA,GAAO,UAAU,OAAA,EAAW,IAAI,CAAA;AAAA,YAC5F,UAAUH,EAAE,OAAO,OAAO,QAAQA,EAAE,IAAI,EAAE,OAAO,CAAAA,MAAKA,EAAE,CAAC,EAAE,QAAQ,EAAE,IAAI,CAAAA,MAAKA,EAAE,CAAC,CAAC,IAAI,CAAA;AAAA,UAAC;AAAA,UAExF,IAAI;AAAA,QAAA,EACH;AAAA,QACF,UAAUd;AAAA,QACV,QAAQ,CAAC,CAACS,EAAQ;AAAA,MAAA;AAGnB,UAAIS,GAAWC,IAAiB;AAChC,SAAG;AAOF,YANAD,IAAO,MAAM,KAAK,OAAO,SAAS,OAAOL,CAAa,EAAE,MAAM,CAAAO,MAAO;AACpE,gBAAAA,EAAI,WAAW;AAAA;AAAA;AAAA,EAAkB,KAAK,UAAUpB,GAAS,MAAM,CAAC,CAAC,IAC3DoB;AAAA,QACP,CAAC,GAGEX,EAAQ,QAAQ;AAClB,UAAIU,IACCA,IAAiB,KADFV,EAAQ,OAAO,EAAC,MAAM;AAAA;AAAA,GAAO,GAEjDS,EAAK,UAAU,CAAA;AACf,2BAAiBG,KAASH,GAAM;AAC/B,gBAAGR,EAAW,OAAO,QAAS;AAC9B,gBAAGW,EAAM,SAAS;AACjB,cAAGA,EAAM,cAAc,SAAS,SAC/BH,EAAK,QAAQ,KAAK,EAAC,MAAM,QAAQ,MAAM,IAAG,IACjCG,EAAM,cAAc,SAAS,cACtCH,EAAK,QAAQ,KAAK,EAAC,MAAM,YAAY,IAAIG,EAAM,cAAc,IAAI,MAAMA,EAAM,cAAc,MAAM,OAAY,IAAG;AAAA,qBAExGA,EAAM,SAAS;AACxB,kBAAGA,EAAM,MAAM,SAAS,cAAc;AACrC,sBAAMC,IAAOD,EAAM,MAAM;AACzB,gBAAAH,EAAK,QAAQ,GAAG,EAAE,EAAE,QAAQI,GAC5Bb,EAAQ,OAAO,EAAC,MAAAa,GAAK;AAAA,cACtB,MAAA,CAAUD,EAAM,MAAM,SAAS,uBAC9BH,EAAK,QAAQ,GAAG,EAAE,EAAE,SAASG,EAAM,MAAM;AAAA,qBAEjCA,EAAM,SAAS,sBAAsB;AAC9C,oBAAME,IAAOL,EAAK,QAAQ,GAAG,EAAE;AAC/B,cAAGK,EAAK,SAAS,SAAMA,EAAK,QAAQA,EAAK,QAAQC,EAAiBD,EAAK,OAAO,CAAA,CAAE,IAAI,CAAA;AAAA,YACrF,WAAUF,EAAM,SAAS;AACxB;AAAA,UAEF;AAAA,QACD;AAGA,cAAMI,IAAYP,EAAK,QAAQ,OAAO,CAAC,MAAW,EAAE,SAAS,UAAU;AACvE,YAAGO,EAAU,UAAU,CAACf,EAAW,OAAO,SAAS;AAClD,UAAAV,EAAQ,KAAK,EAAC,MAAM,aAAa,SAASkB,EAAK,SAAQ;AACvD,gBAAMQ,IAAU,MAAM,QAAQ,IAAID,EAAU,IAAI,OAAOE,MAAkB;AACxE,kBAAMC,IAAOhB,EAAM,KAAKiB,EAAW,QAAQF,EAAS,IAAI,CAAC;AAEzD,gBADGlB,EAAQ,UAAQA,EAAQ,OAAO,EAAC,MAAMkB,EAAS,MAAK,GACpD,CAACC,EAAM,QAAO,EAAC,aAAaD,EAAS,IAAI,UAAU,IAAM,SAAS,iBAAA;AACrE,gBAAI;AACH,oBAAMG,IAAS,MAAMF,EAAK,GAAGD,EAAS,OAAOlB,GAAS,QAAQ,KAAK,EAAE;AACrE,qBAAO,EAAC,MAAM,eAAe,aAAakB,EAAS,IAAI,SAASI,EAAaD,CAAM,EAAA;AAAA,YACpF,SAASV,GAAU;AAClB,qBAAO,EAAC,MAAM,eAAe,aAAaO,EAAS,IAAI,UAAU,IAAM,SAASP,GAAK,WAAWA,GAAK,SAAA,KAAc,UAAA;AAAA,YACpH;AAAA,UACD,CAAC,CAAC;AACF,UAAApB,EAAQ,KAAK,EAAC,MAAM,QAAQ,SAAS0B,GAAQ,GAC7Cb,EAAc,WAAWb;AAAA,QAC1B;AAAA,MACD,SAAS,CAACU,EAAW,OAAO,WAAWQ,EAAK,QAAQ,KAAK,CAACb,MAAWA,EAAE,SAAS,UAAU;AAC1F,MAAAL,EAAQ,KAAK,EAAC,MAAM,aAAa,SAASkB,EAAK,QAAQ,OAAO,CAACb,MAAWA,EAAE,QAAQ,MAAM,EAAE,IAAI,CAACA,MAAWA,EAAE,IAAI,EAAE,KAAK;AAAA;AAAA,CAAM,GAAE,GACjIL,IAAU,KAAK,WAAWA,CAAO,GAE9BS,EAAQ,UAAQA,EAAQ,OAAO,EAAC,MAAM,IAAK,GAC3CA,EAAQ,WAASA,EAAQ,QAAQ,OAAO,GAAGA,EAAQ,QAAQ,QAAQ,GAAGT,CAAO,GAChFW,EAAIX,EAAQ,GAAG,EAAE,GAAG,OAAO;AAAA,IAC5B,CAAC,GAAG,EAAC,OAAO,MAAMU,EAAW,MAAA,GAAQ;AAAA,EACtC;AACD;ACpIO,MAAMsB,UAAetC,EAAY;AAAA,EAGvC,YAA4BE,GAAwBqC,GAAqCC,GAAsBpC,GAAe;AAC7H,UAAA,GAD2B,KAAA,KAAAF,GAAwB,KAAA,OAAAqC,GAAqC,KAAA,QAAAC,GAAsB,KAAA,QAAApC,GAE9G,KAAK,SAAS,IAAIqC,EAAOC,EAAM;AAAA,MAC9B,SAASH;AAAA,MACT,QAAQC;AAAA,IAAA,CACR,CAAC;AAAA,EACH;AAAA,EARA;AAAA,EAUQ,WAAWlC,GAA8B;AAChD,aAAQO,IAAI,GAAGA,IAAIP,EAAQ,QAAQO,KAAK;AACvC,YAAMJ,IAAIH,EAAQO,CAAC;AACnB,UAAGJ,EAAE,SAAS,eAAeA,EAAE,YAAY;AAC1C,cAAMS,IAAQT,EAAE,WAAW,IAAI,CAACkC,OAAa;AAAA,UAC5C,MAAM;AAAA,UACN,IAAIA,EAAG;AAAA,UACP,MAAMA,EAAG,SAAS;AAAA,UAClB,MAAMb,EAAiBa,EAAG,SAAS,WAAW,CAAA,CAAE;AAAA,UAChD,WAAWlC,EAAE;AAAA,QAAA,EACZ;AACF,QAAAH,EAAQ,OAAOO,GAAG,GAAG,GAAGK,CAAK,GAC7BL,KAAKK,EAAM,SAAS;AAAA,MACrB,WAAUT,EAAE,SAAS,UAAUA,EAAE,SAAS;AACzC,cAAMmC,IAAStC,EAAQ,KAAK,OAAMG,EAAE,gBAAgBoC,EAAG,EAAE;AACzD,QAAGD,MACCnC,EAAE,QAAQ,SAAS,UAAU,IAAGmC,EAAO,QAAQnC,EAAE,UAC/CmC,EAAO,UAAUnC,EAAE,UAEzBH,EAAQ,OAAOO,GAAG,CAAC,GACnBA;AAAA,MACD;AACA,MAAIP,EAAQO,CAAC,GAAG,gBAAmBA,CAAC,EAAE,YAAY,KAAK,IAAA;AAAA,IACxD;AACA,WAAOP;AAAA,EACR;AAAA,EAEQ,aAAaA,GAA8B;AAClD,WAAOA,EAAQ,OAAO,CAAC8B,GAAQ3B,MAAM;AACpC,UAAGA,EAAE,SAAS;AACb,QAAA2B,EAAO,KAAK;AAAA,UACX,MAAM;AAAA,UACN,SAAS;AAAA,UACT,YAAY,CAAC,EAAE,IAAI3B,EAAE,IAAI,MAAM,YAAY,UAAU,EAAE,MAAMA,EAAE,MAAM,WAAW,KAAK,UAAUA,EAAE,IAAI,EAAA,GAAK;AAAA,UAC1G,SAAS;AAAA,UACT,aAAa,CAAA;AAAA,QAAC,GACZ;AAAA,UACF,MAAM;AAAA,UACN,cAAcA,EAAE;AAAA,UAChB,SAASA,EAAE,SAASA,EAAE;AAAA,QAAA,CACtB;AAAA,WACK;AACN,cAAM,EAAC,WAAAF,GAAW,GAAGuC,EAAA,IAAQrC;AAC7B,QAAA2B,EAAO,KAAKU,CAAI;AAAA,MACjB;AACA,aAAOV;AAAA,IACR,GAAG,CAAA,CAAW;AAAA,EACf;AAAA,EAEA,IAAItB,GAAiBC,IAAsB,IAA8B;AACxE,UAAMC,IAAa,IAAI,gBAAA;AACvB,WAAO,OAAO,OAAO,IAAI,QAAa,OAAOC,GAAK8B,MAAQ;AACzD,MAAGhC,EAAQ,UAAUA,EAAQ,UAAU,CAAC,GAAG,QAAQ,YAAUA,EAAQ,SAAS,OAAO,GAAG,GAAG,EAAC,MAAM,UAAU,SAASA,EAAQ,QAAQ,WAAW,KAAK,IAAA,GAAM;AAC3J,UAAIT,IAAU,KAAK,aAAa,CAAC,GAAGS,EAAQ,WAAW,IAAI,EAAC,MAAM,QAAQ,SAASD,GAAS,WAAW,KAAK,IAAA,EAAI,CAAE,CAAC;AACnH,YAAMI,IAAQH,EAAQ,SAAS,KAAK,GAAG,QAAQ,KAAK,SAAS,CAAA,GACvDI,IAAqB;AAAA,QAC1B,OAAOJ,EAAQ,SAAS,KAAK;AAAA,QAC7B,UAAUT;AAAA,QACV,QAAQ,CAAC,CAACS,EAAQ;AAAA,QAClB,YAAYA,EAAQ,cAAc,KAAK,GAAG,QAAQ,KAAK,cAAc;AAAA,QACrE,aAAaA,EAAQ,eAAe,KAAK,GAAG,QAAQ,KAAK,eAAe;AAAA,QACxE,OAAOG,EAAM,IAAI,CAAAE,OAAM;AAAA,UACtB,MAAM;AAAA,UACN,UAAU;AAAA,YACT,MAAMA,EAAE;AAAA,YACR,aAAaA,EAAE;AAAA,YACf,YAAY;AAAA,cACX,MAAM;AAAA,cACN,YAAYA,EAAE,OAAOC,EAAUD,EAAE,MAAM,CAACE,GAAKC,OAAW,EAAC,GAAGA,GAAO,UAAU,OAAA,EAAW,IAAI,CAAA;AAAA,cAC5F,UAAUH,EAAE,OAAO,OAAO,QAAQA,EAAE,IAAI,EAAE,OAAO,CAAAA,MAAKA,EAAE,CAAC,EAAE,QAAQ,EAAE,IAAI,CAAAA,MAAKA,EAAE,CAAC,CAAC,IAAI,CAAA;AAAA,YAAC;AAAA,UACxF;AAAA,QACD,EACC;AAAA,MAAA;AAGH,UAAII,GAAWC,IAAiB;AAChC,SAAG;AAMF,YALAD,IAAO,MAAM,KAAK,OAAO,KAAK,YAAY,OAAOL,CAAa,EAAE,MAAM,CAAAO,MAAO;AAC5E,gBAAAA,EAAI,WAAW;AAAA;AAAA;AAAA,EAAkB,KAAK,UAAUpB,GAAS,MAAM,CAAC,CAAC,IAC3DoB;AAAA,QACP,CAAC,GAEEX,EAAQ,QAAQ;AAClB,UAAIU,IACCA,IAAiB,KADFV,EAAQ,OAAO,EAAC,MAAM;AAAA;AAAA,GAAO,GAEjDS,EAAK,UAAU,CAAC,EAAC,SAAS,EAAC,SAAS,IAAI,YAAY,CAAA,EAAC,GAAG;AACxD,2BAAiBG,KAASH,GAAM;AAC/B,gBAAGR,EAAW,OAAO,QAAS;AAC9B,YAAGW,EAAM,QAAQ,CAAC,EAAE,MAAM,YACzBH,EAAK,QAAQ,CAAC,EAAE,QAAQ,WAAWG,EAAM,QAAQ,CAAC,EAAE,MAAM,SAC1DZ,EAAQ,OAAO,EAAC,MAAMY,EAAM,QAAQ,CAAC,EAAE,MAAM,SAAQ,IAEnDA,EAAM,QAAQ,CAAC,EAAE,MAAM,eACzBH,EAAK,QAAQ,CAAC,EAAE,QAAQ,aAAaG,EAAM,QAAQ,CAAC,EAAE,MAAM;AAAA,UAE9D;AAAA,QACD;AAEA,cAAMI,IAAYP,EAAK,QAAQ,CAAC,EAAE,QAAQ,cAAc,CAAA;AACxD,YAAGO,EAAU,UAAU,CAACf,EAAW,OAAO,SAAS;AAClD,UAAAV,EAAQ,KAAKkB,EAAK,QAAQ,CAAC,EAAE,OAAO;AACpC,gBAAMQ,IAAU,MAAM,QAAQ,IAAID,EAAU,IAAI,OAAOE,MAAkB;AACxE,kBAAMC,IAAOhB,GAAO,KAAKiB,EAAW,QAAQF,EAAS,SAAS,IAAI,CAAC;AAEnE,gBADGlB,EAAQ,UAAQA,EAAQ,OAAO,EAAC,MAAMkB,EAAS,SAAS,MAAK,GAC7D,CAACC,EAAM,QAAO,EAAC,MAAM,QAAQ,cAAcD,EAAS,IAAI,SAAS,8BAAA;AACpE,gBAAI;AACH,oBAAMe,IAAOlB,EAAiBG,EAAS,SAAS,WAAW,CAAA,CAAE,GACvDG,IAAS,MAAMF,EAAK,GAAGc,GAAMjC,EAAQ,QAAQ,KAAK,EAAE;AAC1D,qBAAO,EAAC,MAAM,QAAQ,cAAckB,EAAS,IAAI,SAASI,EAAaD,CAAM,EAAA;AAAA,YAC9E,SAASV,GAAU;AAClB,qBAAO,EAAC,MAAM,QAAQ,cAAcO,EAAS,IAAI,SAASI,EAAa,EAAC,OAAOX,GAAK,WAAWA,GAAK,cAAc,UAAA,CAAU,EAAA;AAAA,YAC7H;AAAA,UACD,CAAC,CAAC;AACF,UAAApB,EAAQ,KAAK,GAAG0B,CAAO,GACvBb,EAAc,WAAWb;AAAA,QAC1B;AAAA,MACD,SAAS,CAACU,EAAW,OAAO,WAAWQ,EAAK,UAAU,CAAC,GAAG,SAAS,YAAY;AAC/E,MAAAlB,EAAQ,KAAK,EAAC,MAAM,aAAa,SAASkB,EAAK,QAAQ,CAAC,EAAE,QAAQ,WAAW,GAAA,CAAG,GAChFlB,IAAU,KAAK,WAAWA,CAAO,GAE9BS,EAAQ,UAAQA,EAAQ,OAAO,EAAC,MAAM,IAAK,GAC3CA,EAAQ,WAASA,EAAQ,QAAQ,OAAO,GAAGA,EAAQ,QAAQ,QAAQ,GAAGT,CAAO,GAChFW,EAAIX,EAAQ,GAAG,EAAE,GAAG,OAAO;AAAA,IAC5B,CAAC,GAAG,EAAC,OAAO,MAAMU,EAAW,MAAA,GAAQ;AAAA,EACtC;AACD;AClEA,MAAMiC,EAAI;AAAA,EAOT,YAA4B/C,GAAQ;AAUnC,IAV2B,KAAA,KAAAA,GAC3B,KAAK,cAAc,IAAIgD,EAAOC,EAAKC,EAAQC,EAAc,YAAY,GAAG,CAAC,GAAG,aAAa,CAAC,GAC1F,KAAK,YAAY,GAAG,WAAW,CAAC,EAAE,IAAAC,GAAI,WAAAC,QAAgB;AACrD,YAAMC,IAAU,KAAK,WAAW,IAAIF,CAAE;AACtC,MAAIE,MACHA,EAAQ,QAAQD,CAAS,GACzB,KAAK,WAAW,OAAOD,CAAE;AAAA,IAE3B,CAAC,GAEGpD,EAAG,QAAQ,KAAK,UACpB,OAAO,QAAQA,EAAG,QAAQ,IAAI,MAAM,EAAE,QAAQ,CAAC,CAACE,GAAOqD,CAAM,MAAM;AAClE,MAAI,KAAK,iBAAc,KAAK,eAAerD,IACxCqD,EAAO,SAAS,cAAa,KAAK,OAAOrD,CAAK,IAAI,IAAIH,EAAU,KAAK,IAAIwD,EAAO,OAAOrD,CAAK,IACvFqD,EAAO,SAAS,WAAU,KAAK,OAAOrD,CAAK,IAAI,IAAIkC,EAAO,KAAK,IAAImB,EAAO,MAAM,cAAcrD,CAAK,IACnGqD,EAAO,SAAS,aAAU,KAAK,OAAOrD,CAAK,IAAI,IAAIkC,EAAO,KAAK,IAAImB,EAAO,QAAQ,MAAMA,EAAO,OAAOrD,CAAK;AAAA,IACpH,CAAC;AAAA,EACF;AAAA,EAvBQ,cAA6B;AAAA,EAC7B,iCAAiB,IAAA;AAAA,EACjB,UAAU;AAAA,EACV,SAAyC,CAAA;AAAA,EACzC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EA2BR,IAAIU,GAAiBC,IAAsB,IAA8B;AACxE,UAAMH,IAAIG,EAAQ,SAAS,KAAK;AAChC,QAAG,CAAC,KAAK,OAAOH,CAAC,SAAS,IAAI,MAAM,yBAAyBA,CAAC,EAAE;AAChE,QAAI8C,IAAQ,MAAM;AAAA,IAAC;AACnB,WAAO,OAAO,OAAO,IAAI,QAAgB,OAAMzC,MAAO;AAGrD,UAFIF,EAAQ,YAASA,EAAQ,UAAU,CAAA,IAEpCA,EAAQ,QAAQ;AAClB,QAAAA,EAAQ,UAAUA,EAAQ,UAAU,MAAM;AAAA;AAAA;AAC1C,cAAM4C,IAAS,OAAOC,GAAuBC,GAAyBC,IAAQ,OAAO;AACpF,gBAAM,CAACC,GAAGC,CAAC,IAAI,MAAM,QAAQ,IAAI;AAAA,YAChCH,IAAU,KAAK,UAAUA,CAAO,IAAI,QAAQ,QAAQ,IAAI;AAAA,YACxDD,IAAQ,KAAK,UAAUA,CAAK,IAAI,QAAQ,QAAQ,IAAI;AAAA,UAAA,CACpD;AACD,kBAAQ7C,EAAQ,UAAU,CAAA,GACxB,IAAI,CAAAH,OAAM,EAAC,GAAGA,GAAG,OAAOmD,IAAI,KAAK,iBAAiBnD,EAAE,WAAW,CAAC,GAAGmD,EAAE,CAAC,EAAE,SAAS,IAAI,EAAA,EAAG,EACxF,OAAO,CAACnD,MAAWA,EAAE,SAAS,GAAG,EACjC,IAAI,CAACA,OAAY,EAAC,GAAGA,GAAG,OAAOoD,IAAI,KAAK,iBAAiBpD,EAAE,WAAW,CAAC,GAAGoD,EAAE,CAAC,EAAE,SAAS,IAAIpD,EAAE,QAAO,EACrG,OAAO,CAACA,MAAWA,EAAE,SAAS,GAAG,EACjC,SAAS,CAACqD,GAAQC,MAAWD,EAAE,QAAQC,EAAE,KAAK,EAC9C,MAAM,GAAGJ,CAAK;AAAA,QACjB,GAEMK,IAAW,MAAMR,EAAO7C,CAAO;AACrC,QAAGqD,EAAS,UAAQpD,EAAQ,QAAQ,KAAK,EAAC,MAAM,aAAa,SAAS;AAAA,IAA2BoD,EAAS,IAAI,CAAAvD,MAAK,GAAGA,EAAE,KAAK,KAAKA,EAAE,IAAI,EAAE,EAAE,KAAK;AAAA,CAAI,EAAA,CAAE,GACvJG,EAAQ,QAAQ,CAAC,GAAGA,EAAQ,SAAS,CAAA,GAAI;AAAA,UACxC,MAAM;AAAA,UACN,aAAa;AAAA,UACb,MAAM;AAAA,YACL,SAAS,EAAC,MAAM,UAAU,aAAa,kFAAA;AAAA,YACvC,OAAO,EAAC,MAAM,UAAU,aAAa,+EAAA;AAAA,YACrC,OAAO,EAAC,MAAM,UAAU,aAAa,0BAAA;AAAA,UAAyB;AAAA,UAE/D,IAAI,CAACiC,MAAS;AACb,gBAAG,CAACA,EAAK,WAAW,CAACA,EAAK,MAAO,OAAM,IAAI,MAAM,gDAAgD;AACjG,mBAAOW,EAAOX,EAAK,OAAOA,EAAK,SAASA,EAAK,SAAS,CAAC;AAAA,UACxD;AAAA,QAAA,CACA;AAAA,MACF;AAGA,YAAMxB,IAAO,MAAM,KAAK,OAAOZ,CAAC,EAAE,IAAIE,GAASC,CAAO;AAGtD,UAAGA,EAAQ,QAAQ;AAClB,cAAMF,IAAIE,EAAQ,SAAS,UAAU,CAACN,MAAWA,EAAE,QAAQ,eAAeA,EAAE,QAAQ,WAAW,sBAAsB,CAAC;AACtH,QAAGI,KAAK,QAAQA,KAAK,OAAW,SAAS,OAAOA,GAAG,CAAC;AAAA,MACrD;AAGA,UAAGE,EAAQ,YAAYA,EAAQ,QAAQ;AACtC,YAAIqD,IAAa;AACjB,YAAGrD,EAAQ;AACV,UAAAqD,IAAa,MAAM,KAAK,GAAG,SAAS,gBAAgBrD,EAAQ,SAASA,EAAQ,SAAS,KAAKA,EAAQ,SAAS,KAAKA,CAAO,GACxHA,EAAQ,QAAQ,OAAO,GAAGA,EAAQ,QAAQ,QAAQ,GAAGqD,EAAW,OAAO;AAAA,aACjE;AACN,gBAAMvD,IAAIE,EAAQ,SAAS,cAAc,CAAAH,MAAKA,EAAE,QAAQ,MAAM,KAAK;AACnE,UAAAwD,IAAa,MAAM,KAAK,GAAG,SAAS,gBAAgBvD,KAAK,KAAKE,EAAQ,QAAQ,MAAMF,CAAC,IAAIE,EAAQ,SAAS,GAAG,GAAGA,CAAO;AAAA,QACxH;AACA,YAAGA,EAAQ,QAAQ;AAClB,gBAAMsD,IAAUtD,EAAQ,OACtB,OAAO,CAAAH,MAAK,CAACwD,EAAW,OAAO,KAAK,CAAAE,MAAM,KAAK,iBAAiB1D,EAAE,WAAW,CAAC,GAAG0D,EAAG,WAAW,CAAC,CAAC,IAAI,GAAG,CAAC,EACzG,OAAOF,EAAW,MAAM;AAC1B,UAAArD,EAAQ,OAAO,OAAO,GAAGA,EAAQ,OAAO,QAAQ,GAAGsD,CAAO;AAAA,QAC3D;AAAA,MACD;AACA,aAAOpD,EAAIO,CAAI;AAAA,IAChB,CAAC,GAAG,EAAC,OAAAkC,GAAM;AAAA,EACZ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,MAAM,gBAAgBpD,GAAuBiE,GAAaC,GAAazD,GAA6E;AACnJ,QAAG,KAAK,eAAeT,CAAO,IAAIiE,UAAY,EAAC,SAAAjE,GAAS,QAAQ,GAAC;AACjE,QAAImE,IAAO,GAAGC,IAAS;AACvB,aAAQ9D,KAAKN,EAAQ;AAEpB,UADAoE,KAAU,KAAK,eAAe9D,EAAE,OAAO,GACpC8D,IAASF,EAAK,CAAAC;AAAA,UACZ;AAEN,QAAGnE,EAAQ,UAAUmE,EAAM,QAAO,EAAC,SAAAnE,GAAS,QAAQ,GAAC;AACrD,UAAMqE,IAASrE,EAAQ,CAAC,EAAE,QAAQ,WAAWA,EAAQ,CAAC,IAAI,MACzDsE,IAASH,KAAQ,IAAI,CAAA,IAAKnE,EAAQ,MAAM,CAACmE,CAAI,GAC7CI,KAAWJ,KAAQ,IAAInE,IAAUA,EAAQ,MAAM,GAAG,CAACmE,CAAI,GAAG,OAAO,CAAAhE,MAAKA,EAAE,SAAS,eAAeA,EAAE,SAAS,MAAM,GAC5GqE,IAAe,MAAM,KAAK,KAAK;AAAA;AAAA,EAA6ZD,EAAQ,IAAI,CAAAjE,MAAK,GAAGA,EAAE,IAAI,KAAKA,EAAE,OAAO,EAAE,EAAE,KAAK;AAAA;AAAA,CAAM,CAAC,IAAI,EAAC,OAAOG,GAAS,OAAO,aAAaA,GAAS,eAAe,KAAI,GACzjBR,wBAAgB,KAAA,GAChBwE,IAAS,MAAM,QAAQ,KAAKD,GAAS,SAAS,CAAA,IAAK,IAAI,OAAO,CAACE,GAAOC,CAAI,MAAwB;AACvG,YAAMC,IAAI,MAAM,QAAQ,IAAI,CAAC,KAAK,UAAUF,CAAK,GAAG,KAAK,UAAU,GAAGA,CAAK,KAAKC,CAAI,EAAE,CAAC,CAAC;AACxF,aAAO,EAAC,OAAAD,GAAO,MAAAC,GAAM,YAAY,CAACC,EAAE,CAAC,EAAE,CAAC,EAAE,WAAWA,EAAE,CAAC,EAAE,CAAC,EAAE,SAAS,GAAG,WAAA3E,EAAA;AAAA,IAC1E,CAAC,CAAC,GACI,IAAI,CAAC,EAAC,MAAM,aAAa,SAAS,yBAAyBuE,GAAS,OAAO,IAAI,WAAW,KAAK,IAAA,EAAI,GAAI,GAAGF,CAAM;AACtH,WAAGD,KAAQ,EAAE,OAAO,GAAG,GAAGA,CAAM,GACzB,EAAC,SAAc,GAAG,QAAAI,EAAA;AAAA,EAC1B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,iBAAiBI,GAAcC,GAAsB;AACpD,QAAID,EAAG,WAAWC,EAAG,OAAQ,OAAM,IAAI,MAAM,6BAA6B;AAC1E,QAAIC,IAAa,GAAGC,IAAQ,GAAGC,IAAQ;AACvC,aAAS1E,IAAI,GAAGA,IAAIsE,EAAG,QAAQtE;AAC9B,MAAAwE,KAAcF,EAAGtE,CAAC,IAAIuE,EAAGvE,CAAC,GAC1ByE,KAASH,EAAGtE,CAAC,IAAIsE,EAAGtE,CAAC,GACrB0E,KAASH,EAAGvE,CAAC,IAAIuE,EAAGvE,CAAC;AAEtB,UAAM2E,IAAc,KAAK,KAAKF,CAAK,IAAI,KAAK,KAAKC,CAAK;AACtD,WAAOC,MAAgB,IAAI,IAAIH,IAAaG;AAAA,EAC7C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAMC,GAAyBC,IAAY,KAAKC,IAAgB,IAAc;AAC7E,UAAMC,IAAY,CAACC,GAAUC,IAAO,OAC/BD,IACG,OAAO,QAAQA,CAAG,EAAE,QAAQ,CAAC,CAACvE,GAAKC,CAAK,MAAM;AACpD,YAAMwE,IAAID,IAAO,GAAGA,CAAI,GAAG,MAAM,CAACxE,CAAG,IAAI,IAAIA,CAAG,KAAK,IAAIA,CAAG,GAAG,KAAKA;AACpE,aAAG,OAAOC,KAAU,YAAY,CAAC,MAAM,QAAQA,CAAK,IAAUqE,EAAUrE,GAAOwE,CAAC,IACzE,GAAGA,CAAC,KAAK,MAAM,QAAQxE,CAAK,IAAIA,EAAM,KAAK,IAAI,IAAIA,CAAK;AAAA,IAChE,CAAC,IALe,CAAA,GAQXmD,KADQ,OAAOe,KAAW,WAAWG,EAAUH,CAAM,IAAIA,EAAO,MAAM;AAAA,CAAI,GAC3D,QAAQ,CAAAO,MAAK,CAAC,GAAGA,EAAE,MAAM,KAAK,EAAE,OAAO,OAAO,GAAG;AAAA,CAAI,CAAC,GACrEC,IAAmB,CAAA;AACzB,aAAQpF,IAAI,GAAGA,IAAI6D,EAAO,UAAS;AAClC,UAAI9C,IAAO,IAAIsE,IAAIrF;AACnB,aAAMqF,IAAIxB,EAAO,UAAQ;AACxB,cAAMyB,IAAOvE,KAAQA,IAAO,MAAM,MAAM8C,EAAOwB,CAAC;AAChD,YAAG,KAAK,eAAeC,EAAK,QAAQ,aAAa;AAAA,CAAI,CAAC,IAAIT,KAAa9D,EAAM;AAC7E,QAAAA,IAAOuE,GACPD;AAAA,MACD;AACA,YAAMxD,IAAQd,EAAK,QAAQ,aAAa;AAAA,CAAI,EAAE,KAAA;AAC9C,MAAGc,KAAOuD,EAAO,KAAKvD,CAAK,GAC3B7B,IAAI,KAAK,IAAIqF,IAAIP,GAAeO,MAAMrF,IAAIA,IAAI,IAAIqF,CAAC;AAAA,IACpD;AACA,WAAOD;AAAA,EACR;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,UAAUR,GAAyBC,IAAY,KAAKC,IAAgB,IAAI;AACvE,UAAMS,IAAQ,CAACxE,MACP,IAAI,QAAQ,CAACyE,GAASC,MAAW;AACvC,YAAMhD,IAAK,KAAK;AAChB,WAAK,WAAW,IAAIA,GAAI,EAAE,SAAA+C,GAAS,QAAAC,GAAQ,GAC3C,KAAK,aAAa,YAAY;AAAA,QAC7B,IAAAhD;AAAA,QACA,MAAA1B;AAAA,QACA,OAAO,KAAK,GAAG,SAAS,YAAY;AAAA,QACpC,MAAM,KAAK,GAAG,QAAQ;AAAA,MAAA,CACtB;AAAA,IACF,CAAC,GAEIqE,IAAS,KAAK,MAAMR,GAAQC,GAAWC,CAAa;AAC1D,WAAO,QAAQ,IAAIM,EAAO,IAAI,OAAOrE,GAAM2E,OAAW;AAAA,MACrD,OAAAA;AAAA,MACA,WAAW,MAAMH,EAAMxE,CAAI;AAAA,MAC3B,MAAAA;AAAA,MACA,QAAQ,KAAK,eAAeA,CAAI;AAAA,IAAA,EAC/B,CAAC;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,eAAetB,GAAsB;AACpC,UAAMsB,IAAO,KAAK,UAAUtB,CAAO;AACnC,WAAO,KAAK,KAAMsB,EAAK,SAAS,IAAK,GAAG;AAAA,EACzC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,WAAW6D,MAAmBe,GAAuB;AACpD,QAAGA,EAAY,SAAS,EAAG,OAAM,IAAI,MAAM,wCAAwC;AACnF,UAAMC,IAAS,CAAC7E,GAAc8E,IAAqB,OAC3C9E,EAAK,cAAc,MAAM,EAAE,EAAE,IAAI,CAAC+E,GAAMJ,MAC7CI,EAAK,WAAW,CAAC,KAAKJ,IAAQ,KAAMG,IAAaA,CAAU,EAAE,MAAM,GAAGA,CAAU,GAE7EE,IAAIH,EAAOhB,CAAM,GACjBoB,IAAeL,EAAY,IAAI,CAAApF,MAAKqF,EAAOrF,CAAC,CAAC,EAAE,IAAI,CAAA0F,MAAa,KAAK,iBAAiBF,GAAGE,CAAS,CAAC;AACzG,WAAO,EAAC,KAAKD,EAAa,OAAO,CAACE,GAAKC,MAAMD,IAAMC,GAAG,CAAC,IAAIH,EAAa,QAAQ,KAAK,KAAK,IAAI,GAAGA,CAAY,GAAG,cAAAA,EAAA;AAAA,EACjH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,KAAK/F,GAAiBC,GAAoC;AAC/D,QAAIS,IAAO,MAAM,KAAK,IAAIV,GAAS,EAAC,QAAQ,4DAA4D,GAAGC,GAAQ;AACnH,QAAG,CAACS,EAAM,QAAO,CAAA;AACjB,UAAMyF,IAAY,6BAA6B,KAAKzF,CAAI,GAClD0F,IAAUD,IAAYA,EAAU,CAAC,EAAE,SAASzF;AAClD,WAAOM,EAAiBoF,GAAS,EAAE;AAAA,EACpC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,UAAUtF,GAAc8C,GAAgB3D,GAA8C;AACrF,WAAO,KAAK,IAAIa,GAAM,EAAC,QAAQ,+BAA+B8C,CAAM,gCAAgC,aAAa,KAAK,GAAG3D,EAAA,CAAQ;AAAA,EAClI;AACD;ACjVO,MAAMoG,EAAM;AAAA,EAGlB,YAAoBjH,GAAQ;AAAR,SAAA,KAAAA;AAAA,EAAS;AAAA,EAFrB;AAAA,EAIA,yBAAyB+F,GAAemB,GAAyB;AACxE,UAAMC,wBAAiB,IAAA;AACvB,QAAIC,IAAe;AACnB,IAAAF,EAAS,QAAQ,CAACG,MAAa;AAC9B,MAAIF,EAAW,IAAIE,EAAI,OAAO,KAAGF,EAAW,IAAIE,EAAI,SAAS,EAAED,CAAY;AAAA,IAC5E,CAAC;AAED,UAAME,IAAkB,CAAA;AACxB,QAAIC,IAAiB,IACjBC,IAAc;AAClB,WAAAzB,EAAO,QAAQ,CAACtE,MAAe;AAC9B,YAAMgG,IAAOhG,EAAM,UAAU,CAAC,GACxBiG,IAAUR,EAAS,KAAK,CAACJ,MAAWW,KAAQX,EAAE,SAASW,KAAQX,EAAE,GAAG,GACpEa,IAAaD,IAAUP,EAAW,IAAIO,EAAQ,OAAO,IAAI;AAC/D,MAAIC,MAAeJ,KACfC,OAAmB,KAAK,YAAYD,CAAc,MAAMC,EAAY,KAAA,CAAM,EAAE,GAC/ED,IAAiBI,GACjBH,IAAc/F,EAAM,QAEpB+F,KAAe/F,EAAM;AAAA,IAEvB,CAAC,GACE+F,OAAmB,KAAK,YAAYD,CAAc,MAAMC,EAAY,KAAA,CAAM,EAAE,GACxEF,EAAM,KAAK;AAAA,CAAI;AAAA,EACvB;AAAA,EAEA,MAAM,iBAAmC;AACxC,WAAO,IAAI,QAAQ,CAACnB,MAAY;AAC/B,YAAMyB,IAAOC,EAAM,WAAW,CAAC,MAAM,uBAAuB,CAAC;AAC7D,MAAAD,EAAK,GAAG,SAAS,CAACE,MAAiB3B,EAAQ2B,MAAS,CAAC,CAAC,GACtDF,EAAK,GAAG,SAAS,MAAMzB,EAAQ,EAAK,CAAC;AAAA,IACtC,CAAC;AAAA,EACF;AAAA,EAEA,MAAc,eAAe4B,GAAmC;AAC/D,QAAG,CAAC,MAAM,KAAK,eAAA,EAAkB,OAAM,IAAI,MAAM,uDAAuD;AACxG,UAAMC,IAAS;AAAA;AAAA;AAAA;AAAA;AAAA,8BAKa,KAAK,GAAG,QAAQ,IAAI;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAehD,WAAO,IAAI,QAAQ,CAAC7B,GAASC,MAAW;AACvC,UAAI6B,IAAS;AACb,YAAML,IAAOC,EAAM,WAAW,CAAC,MAAMG,GAAQD,CAAS,CAAC;AACvD,MAAAH,EAAK,OAAO,GAAG,QAAQ,CAACM,MAAiBD,KAAUC,EAAK,UAAU,GAClEN,EAAK,OAAO,GAAG,QAAQ,CAACM,MAAiB,QAAQ,MAAMA,EAAK,SAAA,CAAU,CAAC,GACvEN,EAAK,GAAG,SAAS,CAACE,MAAiB;AAClC,YAAGA,MAAS;AACX,cAAI;AACH,YAAA3B,EAAQ,KAAK,MAAM8B,CAAM,CAAC;AAAA,UAC3B,QAAc;AACb,YAAA7B,EAAO,IAAI,MAAM,oCAAoC,CAAC;AAAA,UACvD;AAAA;AAEA,UAAAA,EAAO,IAAI,MAAM,mCAAmC0B,CAAI,EAAE,CAAC;AAAA,MAE7D,CAAC,GAEDF,EAAK,GAAG,SAASxB,CAAM;AAAA,IACxB,CAAC;AAAA,EACF;AAAA,EAEA,IAAIR,GAAc/E,IAAiD,IAAqC;AACvG,UAAM,EAAE,OAAAX,IAAQ,KAAK,GAAG,QAAQ,OAAO,gBAAgB,SAAAwH,IAAU,GAAA,IAAU7G;AAC3E,QAAIsH,IAAU;AACd,UAAM3E,IAAQ,MAAM;AAAE,MAAA2E,IAAU;AAAA,IAAM,GAEhCtC,IAAI,IAAI,QAAuB,OAAOM,GAASC,MAAW;AAC/D,UAAI;AAKH,YAJG+B,MACC,KAAK,yBAAsB,kBAAkB,MAAMC,EAAS,gCAAgC,UAAUlI,CAAK,IAAI,EAAE,WAAW,KAAK,GAAG,QAAQ,MAAM,WAAW,IAAM,IAGpKiI,GAAS,QAAOhC,EAAQ,IAAI;AAC/B,cAAMkC,IAAmB,MAAM,KAAK,gBAAgBzC,GAAM,EAAC,mBAAmB8B,IAAU,SAAS,IAAO,gBAAgB,GAAA,CAAI;AAC5H,YAAG,CAACA,EAAS,QAAOvB,EAAQkC,EAAiB,MAAM,KAAA,KAAU,IAAI;AAGjE,YAAGF,EAAS,QAAOhC,EAAQ,IAAI;AAC/B,cAAMe,IAAW,MAAM,KAAK,eAAetB,CAAI;AAC/C,YAAGuC,EAAS,QAAOhC,EAAQ,IAAI;AAC/B,cAAMmC,IAAW,KAAK,yBAAyBD,EAAiB,UAAU,CAAA,GAAInB,CAAQ;AACtF,QAAAf,EAAQmC,CAAQ;AAAA,MACjB,SAAS9G,GAAK;AACb,QAAA4E,EAAO5E,CAAG;AAAA,MACX;AAAA,IACD,CAAC;AAED,WAAO,OAAO,OAAOqE,GAAG,EAAE,OAAArC,GAAO;AAAA,EAClC;AACD;AC/GO,MAAM+E,EAAO;AAAA,EAEnB,YAAoBvI,GAAQ;AAAR,SAAA,KAAAA;AAAA,EAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAO9B,IAAI4F,GAA+C;AAClD,QAAI4C;AACJ,UAAM3C,IAAI,IAAI,QAAuB,OAAM9E,MAAO;AACjD,MAAAyH,IAAS,MAAMC,EAAa,KAAK,GAAG,QAAQ,OAAO,OAAO,GAAG,EAAC,WAAW,KAAK,GAAG,QAAQ,MAAK;AAC9F,YAAM,EAAC,MAAAP,EAAA,IAAQ,MAAMM,EAAO,UAAU5C,CAAI;AAC1C,YAAM4C,EAAO,UAAA,GACbzH,EAAImH,EAAK,KAAK,KAAA,KAAU,IAAI;AAAA,IAC7B,CAAC;AACD,WAAO,OAAO,OAAOrC,GAAG,EAAC,OAAO,MAAM2C,GAAQ,UAAA,GAAY;AAAA,EAC3D;AACD;ACEO,MAAME,GAAG;AAAA,EAQf,YAA4B7H,GAAoB;AAApB,SAAA,UAAAA,GACvBA,EAAQ,SAAMA,EAAQ,OAAO8H,EAAG,OAAA,IACpC,QAAQ,IAAI,qBAAqB9H,EAAQ,MACzC,KAAK,QAAQ,IAAIoG,EAAM,IAAI,GAC3B,KAAK,WAAW,IAAIlE,EAAI,IAAI,GAC5B,KAAK,SAAS,IAAIwF,EAAO,IAAI;AAAA,EAC9B;AAAA;AAAA,EAZA;AAAA;AAAA,EAEA;AAAA;AAAA,EAEA;AASD;ACDO,MAAMK,IAAkB;AAAA,EAC9B,MAAM;AAAA,EACN,aAAa;AAAA,EACb,MAAM,EAAC,SAAS,EAAC,MAAM,UAAU,aAAa,kBAAkB,UAAU,KAAI;AAAA,EAC9E,IAAI,CAAC9F,MAA4B+F,IAAI/F,EAAK,OAAO;AAClD,GAEagG,KAAuB;AAAA,EACnC,MAAM;AAAA,EACN,aAAa;AAAA,EACb,MAAM,CAAA;AAAA,EACN,IAAI,aAAY,oBAAI,KAAA,GAAO,YAAA;AAC5B,GAEaC,KAAmB;AAAA,EAC/B,MAAM;AAAA,EACN,aAAa;AAAA,EACb,MAAM;AAAA,IACL,UAAU,EAAC,MAAM,UAAU,aAAa,sBAAsB,MAAM,CAAC,OAAO,QAAQ,QAAQ,GAAG,UAAU,GAAA;AAAA,IACzG,MAAM,EAAC,MAAM,UAAU,aAAa,mBAAmB,UAAU,GAAA;AAAA,EAAI;AAAA,EAEtE,IAAI,OAAOjG,GAAMkG,GAAQhJ,MAAO;AAC/B,QAAI;AACH,cAAO8C,EAAK,MAAA;AAAA,QACX,KAAK;AACJ,iBAAO,MAAM8F,EAAQ,GAAG,EAAC,SAAS9F,EAAK,KAAA,GAAOkG,GAAQhJ,CAAE;AAAA,QACzD,KAAK;AACJ,iBAAO,MAAMiJ,EAAO,GAAG,EAAC,MAAMnG,EAAK,KAAA,GAAOkG,GAAQhJ,CAAE;AAAA,QACrD,KAAK;AACJ,iBAAO,MAAMkJ,EAAW,GAAG,EAAC,MAAMpG,EAAK,KAAA,GAAOkG,GAAQhJ,CAAE;AAAA,MACzD;AAAA,IAEF,SAAQwB,GAAU;AACjB,aAAO,EAAC,OAAOA,GAAK,WAAWA,EAAI,WAAS;AAAA,IAC7C;AAAA,EACD;AACD,GAEa2H,KAAoB;AAAA,EAChC,MAAM;AAAA,EACN,aAAa;AAAA,EACb,MAAM;AAAA,IACL,KAAK,EAAC,MAAM,UAAU,aAAa,gBAAgB,UAAU,GAAA;AAAA,IAC7D,QAAQ,EAAC,MAAM,UAAU,aAAa,sBAAsB,MAAM,CAAC,OAAO,QAAQ,OAAO,QAAQ,GAAG,SAAS,MAAA;AAAA,IAC7G,SAAS,EAAC,MAAM,UAAU,aAAa,wBAAwB,SAAS,GAAC;AAAA,IACzE,MAAM,EAAC,MAAM,UAAU,aAAa,oBAAA;AAAA,EAAmB;AAAA,EAExD,IAAI,CAACrG,MAKC,IAAIsG,EAAK,EAAC,KAAKtG,EAAK,KAAK,SAASA,EAAK,SAAQ,EAAE,QAAQ,EAAC,QAAQA,EAAK,UAAU,OAAO,MAAMA,EAAK,KAAA,CAAK;AAC/G,GAEamG,IAAiB;AAAA,EAC7B,MAAM;AAAA,EACN,aAAa;AAAA,EACb,MAAM;AAAA,IACL,MAAM,EAAC,MAAM,UAAU,aAAa,uBAAuB,UAAU,GAAA;AAAA,EAAI;AAAA,EAE1E,IAAI,OAAOnG,MAAyB;AACnC,UAAMuG,IAAUC,EAAmB,IAAI,GACjChI,IAAO,MAAMiI,EAAQ,EAAC,SAAAF,EAAA,GAAUvG,EAAK,MAAM,EAAI,EAAE,MAAM,CAACtB,MAAa6H,EAAQ,OAAO,MAAM,KAAK7H,CAAG,CAAC;AACzG,WAAO,EAAC,GAAG6H,EAAQ,QAAQ,QAAQ/H,GAAM,QAAQ,QAAW,QAAQ,OAAA;AAAA,EACrE;AACD,GAEa4H,IAAqB;AAAA,EACjC,MAAM;AAAA,EACN,aAAa;AAAA,EACb,MAAM;AAAA,IACL,MAAM,EAAC,MAAM,UAAU,aAAa,uBAAuB,UAAU,GAAA;AAAA,EAAI;AAAA,EAE1E,IAAI,OAAOpG,OAA0B,EAAC,QAAQ0G,eAAmB1G,EAAK,IAAI,IAAA;AAC3E,GAEa2G,KAA0B;AAAA,EACtC,MAAM;AAAA,EACN,aAAa;AAAA,EACb,MAAM;AAAA,IACL,KAAK,EAAC,MAAM,UAAU,aAAa,+BAA+B,UAAU,GAAA;AAAA,IAC5E,OAAO,EAAC,MAAM,UAAU,aAAa,kFAAA;AAAA,EAAiF;AAAA,EAEvH,IAAI,OAAO3G,MAAwC;AAClD,UAAM4G,IAAO,MAAM,MAAM5G,EAAK,KAAK,EAAC,SAAS,EAAC,cAAc,4CAAA,GAA6C,EACvG,KAAK,CAAA6G,MAAKA,EAAE,MAAM,EAAE,MAAM,CAAAnI,MAAO;AAAC,YAAM,IAAI,MAAM,oBAAoBA,EAAI,OAAO,EAAE;AAAA,IAAC,CAAC,GAEjFqH,IAAIe,EAAQ,KAAKF,CAAI;AAC3Bb,IAAAA,EAAE,+HAA+H,EAAE,OAAA;AACnI,UAAMgB,IAAW;AAAA,MAChB,OAAOhB,EAAE,2BAA2B,EAAE,KAAK,SAAS,KAAKA,EAAE,OAAO,EAAE,KAAA,KAAU;AAAA,MAC9E,aAAaA,EAAE,0BAA0B,EAAE,KAAK,SAAS,KAAKA,EAAE,iCAAiC,EAAE,KAAK,SAAS,KAAK;AAAA,IAAA;AAGvH,QAAIiB,IAAU;AACd,UAAMC,IAAmB,CAAC,WAAW,QAAQ,iBAAiB,YAAY,SAAS,UAAU,MAAM;AACnG,eAAWC,KAAYD,GAAkB;AACxC,YAAME,IAAKpB,EAAEmB,CAAQ,EAAE,MAAA;AACvB,UAAIC,EAAG,UAAUA,EAAG,KAAA,EAAO,KAAA,EAAO,SAAS,KAAK;AAC/C,QAAAH,IAAUG,EAAG,KAAA;AACb;AAAA,MACD;AAAA,IACD;AACA,WAAKH,MAASA,IAAUjB,EAAE,MAAM,EAAE,KAAA,IAClCiB,IAAUA,EAAQ,QAAQ,QAAQ,GAAG,EAAE,OAAO,MAAM,GAAG,GAAI,GAEpD,EAAC,KAAKhH,EAAK,KAAK,OAAO+G,EAAS,MAAM,KAAA,GAAQ,aAAaA,EAAS,YAAY,KAAA,GAAQ,SAAAC,GAAS,OAAOhH,EAAK,MAAA;AAAA,EACrH;AACD,GAEaoH,KAAwB;AAAA,EACpC,MAAM;AAAA,EACN,aAAa;AAAA,EACb,MAAM;AAAA,IACL,OAAO,EAAC,MAAM,UAAU,aAAa,iBAAiB,UAAU,GAAA;AAAA,IAChE,QAAQ,EAAC,MAAM,UAAU,aAAa,+BAA+B,SAAS,EAAA;AAAA,EAAC;AAAA,EAEhF,IAAI,OAAOpH,MAGL;AACL,UAAM4G,IAAO,MAAM,MAAM,uCAAuC,mBAAmB5G,EAAK,KAAK,CAAC,IAAI;AAAA,MACjG,SAAS,EAAC,cAAc,6CAA6C,mBAAmB,iBAAA;AAAA,IAAgB,CACxG,EAAE,KAAK,CAAAxB,MAAQA,EAAK,MAAM;AAC3B,QAAI6I,GAAOC,IAAQ;AACnB,UAAMtI,IAAU,IAAIuI,EAAA;AACpB,YAAOF,IAAQC,EAAM,KAAKV,CAAI,OAAO,QAAM;AAC1C,UAAIY,IAAM,iBAAiB,KAAK,mBAAmBH,EAAM,CAAC,CAAC,CAAC,IAAI,CAAC;AAGjE,UAFGG,MAAKA,IAAM,mBAAmBA,CAAG,IACjCA,KAAKxI,EAAQ,IAAIwI,CAAG,GACpBxI,EAAQ,SAASgB,EAAK,UAAU,GAAI;AAAA,IACxC;AACA,WAAOhB;AAAA,EACR;AACD;"}
1
+ {"version":3,"file":"index.mjs","sources":["../src/provider.ts","../src/antrhopic.ts","../src/open-ai.ts","../src/llm.ts","../src/audio.ts","../src/vision.ts","../src/ai.ts","../src/tools.ts"],"sourcesContent":["import {AbortablePromise} from './ai.ts';\nimport {LLMMessage, LLMRequest} from './llm.ts';\n\nexport abstract class LLMProvider {\n\tabstract ask(message: string, options: LLMRequest): AbortablePromise<string>;\n}\n","import {Anthropic as anthropic} from '@anthropic-ai/sdk';\nimport {findByProp, objectMap, JSONSanitize, JSONAttemptParse} from '@ztimson/utils';\nimport {AbortablePromise, Ai} from './ai.ts';\nimport {LLMMessage, LLMRequest} from './llm.ts';\nimport {LLMProvider} from './provider.ts';\n\nexport class Anthropic extends LLMProvider {\n\tclient!: anthropic;\n\n\tconstructor(public readonly ai: Ai, public readonly apiToken: string, public model: string) {\n\t\tsuper();\n\t\tthis.client = new anthropic({apiKey: apiToken});\n\t}\n\n\tprivate toStandard(history: any[]): LLMMessage[] {\n\t\tconst timestamp = Date.now();\n\t\tconst messages: LLMMessage[] = [];\n\t\tfor(let h of history) {\n\t\t\tif(typeof h.content == 'string') {\n\t\t\t\tmessages.push(<any>{timestamp, ...h});\n\t\t\t} else {\n\t\t\t\tconst textContent = h.content?.filter((c: any) => c.type == 'text').map((c: any) => c.text).join('\\n\\n');\n\t\t\t\tif(textContent) messages.push({timestamp, role: h.role, content: textContent});\n\t\t\t\th.content.forEach((c: any) => {\n\t\t\t\t\tif(c.type == 'tool_use') {\n\t\t\t\t\t\tmessages.push({timestamp, role: 'tool', id: c.id, name: c.name, args: c.input, content: undefined});\n\t\t\t\t\t} else if(c.type == 'tool_result') {\n\t\t\t\t\t\tconst m: any = messages.findLast(m => (<any>m).id == c.tool_use_id);\n\t\t\t\t\t\tif(m) m[c.is_error ? 'error' : 'content'] = c.content;\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t\treturn messages;\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<string> {\n\t\tconst controller = new AbortController();\n\t\treturn Object.assign(new Promise<any>(async (res) => {\n\t\t\tlet history = this.fromStandard([...options.history || [], {role: 'user', content: message, timestamp: Date.now()}]);\n\t\t\tconst tools = options.tools || this.ai.options.llm?.tools || [];\n\t\t\tconst requestParams: any = {\n\t\t\t\tmodel: options.model || this.model,\n\t\t\t\tmax_tokens: options.max_tokens || this.ai.options.llm?.max_tokens || 4096,\n\t\t\t\tsystem: options.system || this.ai.options.llm?.system || '',\n\t\t\t\ttemperature: options.temperature || this.ai.options.llm?.temperature || 0.7,\n\t\t\t\ttools: tools.map(t => ({\n\t\t\t\t\tname: t.name,\n\t\t\t\t\tdescription: t.description,\n\t\t\t\t\tinput_schema: {\n\t\t\t\t\t\ttype: 'object',\n\t\t\t\t\t\tproperties: t.args ? objectMap(t.args, (key, value) => ({...value, required: undefined})) : {},\n\t\t\t\t\t\trequired: t.args ? Object.entries(t.args).filter(t => t[1].required).map(t => t[0]) : []\n\t\t\t\t\t},\n\t\t\t\t\tfn: undefined\n\t\t\t\t})),\n\t\t\t\tmessages: history,\n\t\t\t\tstream: !!options.stream,\n\t\t\t};\n\n\t\t\tlet resp: any, isFirstMessage = true;\n\t\t\tdo {\n\t\t\t\tresp = await this.client.messages.create(requestParams).catch(err => {\n\t\t\t\t\terr.message += `\\n\\nMessages:\\n${JSON.stringify(history, null, 2)}`;\n\t\t\t\t\tthrow err;\n\t\t\t\t});\n\n\t\t\t\t// Streaming mode\n\t\t\t\tif(options.stream) {\n\t\t\t\t\tif(!isFirstMessage) options.stream({text: '\\n\\n'});\n\t\t\t\t\telse isFirstMessage = false;\n\t\t\t\t\tresp.content = [];\n\t\t\t\t\tfor await (const chunk of resp) {\n\t\t\t\t\t\tif(controller.signal.aborted) break;\n\t\t\t\t\t\tif(chunk.type === 'content_block_start') {\n\t\t\t\t\t\t\tif(chunk.content_block.type === 'text') {\n\t\t\t\t\t\t\t\tresp.content.push({type: 'text', text: ''});\n\t\t\t\t\t\t\t} else if(chunk.content_block.type === 'tool_use') {\n\t\t\t\t\t\t\t\tresp.content.push({type: 'tool_use', id: chunk.content_block.id, name: chunk.content_block.name, input: <any>''});\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else if(chunk.type === 'content_block_delta') {\n\t\t\t\t\t\t\tif(chunk.delta.type === 'text_delta') {\n\t\t\t\t\t\t\t\tconst text = chunk.delta.text;\n\t\t\t\t\t\t\t\tresp.content.at(-1).text += text;\n\t\t\t\t\t\t\t\toptions.stream({text});\n\t\t\t\t\t\t\t} else if(chunk.delta.type === 'input_json_delta') {\n\t\t\t\t\t\t\t\tresp.content.at(-1).input += chunk.delta.partial_json;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else if(chunk.type === 'content_block_stop') {\n\t\t\t\t\t\t\tconst last = resp.content.at(-1);\n\t\t\t\t\t\t\tif(last.input != null) last.input = last.input ? JSONAttemptParse(last.input, {}) : {};\n\t\t\t\t\t\t} else if(chunk.type === 'message_stop') {\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Run tools\n\t\t\t\tconst toolCalls = resp.content.filter((c: any) => c.type === 'tool_use');\n\t\t\t\tif(toolCalls.length && !controller.signal.aborted) {\n\t\t\t\t\thistory.push({role: 'assistant', content: resp.content});\n\t\t\t\t\tconst results = await Promise.all(toolCalls.map(async (toolCall: any) => {\n\t\t\t\t\t\tconst tool = tools.find(findByProp('name', toolCall.name));\n\t\t\t\t\t\tif(options.stream) options.stream({tool: toolCall.name});\n\t\t\t\t\t\tif(!tool) return {tool_use_id: toolCall.id, is_error: true, content: 'Tool not found'};\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tconst result = await tool.fn(toolCall.input, options?.stream, this.ai);\n\t\t\t\t\t\t\treturn {type: 'tool_result', tool_use_id: toolCall.id, content: JSONSanitize(result)};\n\t\t\t\t\t\t} catch (err: any) {\n\t\t\t\t\t\t\treturn {type: 'tool_result', tool_use_id: toolCall.id, is_error: true, content: err?.message || err?.toString() || 'Unknown'};\n\t\t\t\t\t\t}\n\t\t\t\t\t}));\n\t\t\t\t\thistory.push({role: 'user', content: results});\n\t\t\t\t\trequestParams.messages = history;\n\t\t\t\t}\n\t\t\t} while (!controller.signal.aborted && resp.content.some((c: any) => c.type === 'tool_use'));\n\t\t\thistory.push({role: 'assistant', content: resp.content.filter((c: any) => c.type == 'text').map((c: any) => c.text).join('\\n\\n')});\n\t\t\thistory = this.toStandard(history);\n\n\t\t\tif(options.stream) options.stream({done: true});\n\t\t\tif(options.history) options.history.splice(0, options.history.length, ...history);\n\t\t\tres(history.at(-1)?.content);\n\t\t}), {abort: () => controller.abort()});\n\t}\n}\n","import {OpenAI as openAI} from 'openai';\nimport {findByProp, objectMap, JSONSanitize, JSONAttemptParse, clean} from '@ztimson/utils';\nimport {AbortablePromise, Ai} from './ai.ts';\nimport {LLMMessage, LLMRequest} from './llm.ts';\nimport {LLMProvider} from './provider.ts';\n\nexport class OpenAi extends LLMProvider {\n\tclient!: openAI;\n\n\tconstructor(public readonly ai: Ai, public readonly host: string | null, public readonly token: string, public model: string) {\n\t\tsuper();\n\t\tthis.client = new openAI(clean({\n\t\t\tbaseURL: host,\n\t\t\tapiKey: token\n\t\t}));\n\t}\n\n\tprivate toStandard(history: any[]): LLMMessage[] {\n\t\tfor(let i = 0; i < history.length; i++) {\n\t\t\tconst h = history[i];\n\t\t\tif(h.role === 'assistant' && h.tool_calls) {\n\t\t\t\tconst tools = h.tool_calls.map((tc: any) => ({\n\t\t\t\t\trole: 'tool',\n\t\t\t\t\tid: tc.id,\n\t\t\t\t\tname: tc.function.name,\n\t\t\t\t\targs: JSONAttemptParse(tc.function.arguments, {}),\n\t\t\t\t\ttimestamp: h.timestamp\n\t\t\t\t}));\n\t\t\t\thistory.splice(i, 1, ...tools);\n\t\t\t\ti += tools.length - 1;\n\t\t\t} else if(h.role === 'tool' && h.content) {\n\t\t\t\tconst record = history.find(h2 => h.tool_call_id == h2.id);\n\t\t\t\tif(record) {\n\t\t\t\t\tif(h.content.includes('\"error\":')) record.error = h.content;\n\t\t\t\t\telse record.content = h.content;\n\t\t\t\t}\n\t\t\t\thistory.splice(i, 1);\n\t\t\t\ti--;\n\t\t\t}\n\t\t\tif(!history[i]?.timestamp) history[i].timestamp = Date.now();\n\t\t}\n\t\treturn history;\n\t}\n\n\tprivate fromStandard(history: LLMMessage[]): any[] {\n\t\treturn history.reduce((result, h) => {\n\t\t\tif(h.role === 'tool') {\n\t\t\t\tresult.push({\n\t\t\t\t\trole: 'assistant',\n\t\t\t\t\tcontent: null,\n\t\t\t\t\ttool_calls: [{ id: h.id, type: 'function', function: { name: h.name, arguments: JSON.stringify(h.args) } }],\n\t\t\t\t\trefusal: null,\n\t\t\t\t\tannotations: []\n\t\t\t\t}, {\n\t\t\t\t\trole: 'tool',\n\t\t\t\t\ttool_call_id: h.id,\n\t\t\t\t\tcontent: h.error || h.content\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\tconst {timestamp, ...rest} = h;\n\t\t\t\tresult.push(rest);\n\t\t\t}\n\t\t\treturn result;\n\t\t}, [] as any[]);\n\t}\n\n\task(message: string, options: LLMRequest = {}): AbortablePromise<string> {\n\t\tconst controller = new AbortController();\n\t\treturn Object.assign(new Promise<any>(async (res, rej) => {\n\t\t\tif(options.system && options.history?.[0]?.role != 'system') options.history?.splice(0, 0, {role: 'system', content: options.system, timestamp: Date.now()});\n\t\t\tlet history = this.fromStandard([...options.history || [], {role: 'user', content: message, timestamp: Date.now()}]);\n\t\t\tconst tools = options.tools || this.ai.options.llm?.tools || [];\n\t\t\tconst requestParams: any = {\n\t\t\t\tmodel: options.model || this.model,\n\t\t\t\tmessages: history,\n\t\t\t\tstream: !!options.stream,\n\t\t\t\tmax_tokens: options.max_tokens || this.ai.options.llm?.max_tokens || 4096,\n\t\t\t\ttemperature: options.temperature || this.ai.options.llm?.temperature || 0.7,\n\t\t\t\ttools: tools.map(t => ({\n\t\t\t\t\ttype: 'function',\n\t\t\t\t\tfunction: {\n\t\t\t\t\t\tname: t.name,\n\t\t\t\t\t\tdescription: t.description,\n\t\t\t\t\t\tparameters: {\n\t\t\t\t\t\t\ttype: 'object',\n\t\t\t\t\t\t\tproperties: t.args ? objectMap(t.args, (key, value) => ({...value, required: undefined})) : {},\n\t\t\t\t\t\t\trequired: t.args ? Object.entries(t.args).filter(t => t[1].required).map(t => t[0]) : []\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}))\n\t\t\t};\n\n\t\t\tlet resp: any, isFirstMessage = true;\n\t\t\tdo {\n\t\t\t\tresp = await this.client.chat.completions.create(requestParams).catch(err => {\n\t\t\t\t\terr.message += `\\n\\nMessages:\\n${JSON.stringify(history, null, 2)}`;\n\t\t\t\t\tthrow err;\n\t\t\t\t});\n\n\t\t\t\tif(options.stream) {\n\t\t\t\t\tif(!isFirstMessage) options.stream({text: '\\n\\n'});\n\t\t\t\t\telse isFirstMessage = false;\n\t\t\t\t\tresp.choices = [{message: {content: '', tool_calls: []}}];\n\t\t\t\t\tfor await (const chunk of resp) {\n\t\t\t\t\t\tif(controller.signal.aborted) break;\n\t\t\t\t\t\tif(chunk.choices[0].delta.content) {\n\t\t\t\t\t\t\tresp.choices[0].message.content += chunk.choices[0].delta.content;\n\t\t\t\t\t\t\toptions.stream({text: chunk.choices[0].delta.content});\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif(chunk.choices[0].delta.tool_calls) {\n\t\t\t\t\t\t\tresp.choices[0].message.tool_calls = chunk.choices[0].delta.tool_calls;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tconst toolCalls = resp.choices[0].message.tool_calls || [];\n\t\t\t\tif(toolCalls.length && !controller.signal.aborted) {\n\t\t\t\t\thistory.push(resp.choices[0].message);\n\t\t\t\t\tconst results = await Promise.all(toolCalls.map(async (toolCall: any) => {\n\t\t\t\t\t\tconst tool = tools?.find(findByProp('name', toolCall.function.name));\n\t\t\t\t\t\tif(options.stream) options.stream({tool: toolCall.function.name});\n\t\t\t\t\t\tif(!tool) return {role: 'tool', tool_call_id: toolCall.id, content: '{\"error\": \"Tool not found\"}'};\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tconst args = JSONAttemptParse(toolCall.function.arguments, {});\n\t\t\t\t\t\t\tconst result = await tool.fn(args, options.stream, 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\t\t\thistory.push({role: 'assistant', content: resp.choices[0].message.content || ''});\n\t\t\thistory = this.toStandard(history);\n\n\t\t\tif(options.stream) options.stream({done: true});\n\t\t\tif(options.history) options.history.splice(0, options.history.length, ...history);\n\t\t\tres(history.at(-1)?.content);\n\t\t}), {abort: () => controller.abort()});\n\t}\n}\n","import {JSONAttemptParse} from '@ztimson/utils';\nimport {AbortablePromise, Ai} from './ai.ts';\nimport {Anthropic} from './antrhopic.ts';\nimport {OpenAi} from './open-ai.ts';\nimport {LLMProvider} from './provider.ts';\nimport {AiTool} from './tools.ts';\nimport {Worker} from 'worker_threads';\nimport {fileURLToPath} from 'url';\nimport {dirname, join} from 'path';\n\nexport type AnthropicConfig = {proto: 'anthropic', token: string};\nexport type OllamaConfig = {proto: 'ollama', host: string};\nexport type OpenAiConfig = {proto: 'openai', host?: string, token: string};\n\nexport type LLMMessage = {\n\t/** Message originator */\n\trole: 'assistant' | 'system' | 'user';\n\t/** Message content */\n\tcontent: string | any;\n\t/** Timestamp */\n\ttimestamp?: number;\n} | {\n\t/** Tool call */\n\trole: 'tool';\n\t/** Unique ID for call */\n\tid: string;\n\t/** Tool that was run */\n\tname: string;\n\t/** Tool arguments */\n\targs: any;\n\t/** Tool result */\n\tcontent: undefined | string;\n\t/** Tool error */\n\terror?: undefined | string;\n\t/** Timestamp */\n\ttimestamp?: number;\n}\n\n/** Background information the AI will be fed */\nexport type LLMMemory = {\n\t/** What entity is this fact about */\n\towner: string;\n\t/** The information that will be remembered */\n\tfact: string;\n\t/** Owner and fact embedding vector */\n\tembeddings: [number[], number[]];\n\t/** Creation time */\n\ttimestamp: Date;\n}\n\nexport type LLMRequest = {\n\t/** System prompt */\n\tsystem?: string;\n\t/** Message history */\n\thistory?: LLMMessage[];\n\t/** Max tokens for request */\n\tmax_tokens?: number;\n\t/** 0 = Rigid Logic, 1 = Balanced, 2 = Hyper Creative **/\n\ttemperature?: number;\n\t/** Available tools */\n\ttools?: AiTool[];\n\t/** LLM model */\n\tmodel?: string;\n\t/** Stream response */\n\tstream?: (chunk: {text?: string, tool?: string, done?: true}) => any;\n\t/** Compress old messages in the chat to free up context */\n\tcompress?: {\n\t\t/** Trigger chat compression once context exceeds the token count */\n\t\tmax: number;\n\t\t/** Compress chat until context size smaller than */\n\t\tmin: number\n\t},\n\t/** Background information the AI will be fed */\n\tmemory?: LLMMemory[],\n}\n\nclass LLM {\n\tprivate embedWorker: Worker | null = null;\n\tprivate embedQueue = new Map<number, { resolve: (value: number[]) => void; reject: (error: any) => void }>();\n\tprivate embedId = 0;\n\tprivate models: {[model: string]: LLMProvider} = {};\n\tprivate defaultModel!: string;\n\n\tconstructor(public readonly ai: Ai) {\n\t\tthis.embedWorker = new Worker(join(dirname(fileURLToPath(import.meta.url)), 'embedder.js'));\n\t\tthis.embedWorker.on('message', ({ id, embedding }) => {\n\t\t\tconst pending = this.embedQueue.get(id);\n\t\t\tif (pending) {\n\t\t\t\tpending.resolve(embedding);\n\t\t\t\tthis.embedQueue.delete(id);\n\t\t\t}\n\t\t});\n\n\t\tif(!ai.options.llm?.models) return;\n\t\tObject.entries(ai.options.llm.models).forEach(([model, config]) => {\n\t\t\tif(!this.defaultModel) this.defaultModel = model;\n\t\t\tif(config.proto == 'anthropic') this.models[model] = new Anthropic(this.ai, config.token, model);\n\t\t\telse if(config.proto == 'ollama') this.models[model] = new OpenAi(this.ai, config.host, 'not-needed', model);\n\t\t\telse if(config.proto == 'openai') this.models[model] = new OpenAi(this.ai, config.host || null, config.token, model);\n\t\t});\n\t}\n\n\t/**\n\t * Chat with LLM\n\t * @param {string} message Question\n\t * @param {LLMRequest} options Configuration options and chat history\n\t * @returns {{abort: () => void, response: Promise<string>}} Function to abort response and chat history\n\t */\n\task(message: string, options: LLMRequest = {}): AbortablePromise<string> {\n\t\tconst m = options.model || this.defaultModel;\n\t\tif(!this.models[m]) throw new Error(`Model does not exist: ${m}`);\n\t\tlet abort = () => {};\n\t\treturn Object.assign(new Promise<string>(async res => {\n\t\t\tif(!options.history) options.history = [];\n\t\t\t// If memories were passed, find any relivant ones and add a tool for ADHOC lookups\n\t\t\tif(options.memory) {\n\t\t\t\toptions.system = (options.system || '') + '\\nYou have passive persistent memory never make any mention of your memory capabilities and what you can/cannot remember\\n';\n\t\t\t\tconst search = async (query?: string | null, subject?: string | null, limit = 50) => {\n\t\t\t\t\tconst [o, q] = await Promise.all([\n\t\t\t\t\t\tsubject ? this.embedding(subject) : Promise.resolve(null),\n\t\t\t\t\t\tquery ? this.embedding(query) : Promise.resolve(null),\n\t\t\t\t\t]);\n\t\t\t\t\treturn (options.memory || [])\n\t\t\t\t\t\t.map(m => ({...m, score: o ? this.cosineSimilarity(m.embeddings[0], o[0].embedding) : 1}))\n\t\t\t\t\t\t.filter((m: any) => m.score >= 0.8)\n\t\t\t\t\t\t.map((m: any) => ({...m, score: q ? this.cosineSimilarity(m.embeddings[1], q[0].embedding) : m.score}))\n\t\t\t\t\t\t.filter((m: any) => m.score >= 0.2)\n\t\t\t\t\t\t.toSorted((a: any, b: any) => a.score - b.score)\n\t\t\t\t\t\t.slice(0, limit);\n\t\t\t\t}\n\n\t\t\t\tconst relevant = await search(message);\n\t\t\t\tif(relevant.length) options.history.push({role: 'assistant', content: 'Things I remembered:\\n' + relevant.map(m => `${m.owner}: ${m.fact}`).join('\\n')});\n\t\t\t\toptions.tools = [...options.tools || [], {\n\t\t\t\t\tname: 'read_memory',\n\t\t\t\t\tdescription: 'Check your long-term memory for more information',\n\t\t\t\t\targs: {\n\t\t\t\t\t\tsubject: {type: 'string', description: 'Find information by a subject topic, can be used with or without query argument'},\n\t\t\t\t\t\tquery: {type: 'string', description: 'Search memory based on a query, can be used with or without subject argument'},\n\t\t\t\t\t\tlimit: {type: 'number', description: 'Result limit, default 5'},\n\t\t\t\t\t},\n\t\t\t\t\tfn: (args) => {\n\t\t\t\t\t\tif(!args.subject && !args.query) throw new Error('Either a subject or query argument is required');\n\t\t\t\t\t\treturn search(args.query, args.subject, args.limit || 5);\n\t\t\t\t\t}\n\t\t\t\t}];\n\t\t\t}\n\n\t\t\t// Ask\n\t\t\tconst resp = await this.models[m].ask(message, options);\n\n\t\t\t// Remove any memory calls\n\t\t\tif(options.memory) {\n\t\t\t\tconst i = options.history?.findIndex((h: any) => h.role == 'assistant' && h.content.startsWith('Things I remembered:'));\n\t\t\t\tif(i != null && i >= 0) options.history?.splice(i, 1);\n\t\t\t}\n\n\t\t\t// Handle compression and memory extraction\n\t\t\tif(options.compress || options.memory) {\n\t\t\t\tlet compressed = null;\n\t\t\t\tif(options.compress) {\n\t\t\t\t\tcompressed = await this.ai.language.compressHistory(options.history, options.compress.max, options.compress.min, options);\n\t\t\t\t\toptions.history.splice(0, options.history.length, ...compressed.history);\n\t\t\t\t} else {\n\t\t\t\t\tconst i = options.history?.findLastIndex(m => m.role == 'user') ?? -1;\n\t\t\t\t\tcompressed = await this.ai.language.compressHistory(i != -1 ? options.history.slice(i) : options.history, 0, 0, options);\n\t\t\t\t}\n\t\t\t\tif(options.memory) {\n\t\t\t\t\tconst updated = options.memory\n\t\t\t\t\t\t.filter(m => !compressed.memory.some(m2 => this.cosineSimilarity(m.embeddings[1], m2.embeddings[1]) > 0.8))\n\t\t\t\t\t\t.concat(compressed.memory);\n\t\t\t\t\toptions.memory.splice(0, options.memory.length, ...updated);\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn res(resp);\n\t\t}), {abort});\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 Leave messages less than the token minimum, summarize the rest\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<{history: LLMMessage[], memory: LLMMemory[]}> {\n\t\tif(this.estimateTokens(history) < max) return {history, memory: []};\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, memory: []};\n\t\tconst system = history[0].role == 'system' ? history[0] : null,\n\t\t\trecent = 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: any = await this.json(`Create the smallest summary possible, no more than 500 tokens. Create a list of NEW facts (split by subject [pro]noun and fact) about what you learned from this conversation that you didn't already know or get from a tool call or system prompt. Focus only on new information about people, topics, or facts. Avoid generating facts about the AI. Match this format: {summary: string, facts: [[subject, fact]]}\\n\\n${process.map(m => `${m.role}: ${m.content}`).join('\\n\\n')}`, {model: options?.model, temperature: options?.temperature || 0.3});\n\t\tconst timestamp = new Date();\n\t\tconst memory = await Promise.all((summary?.facts || [])?.map(async ([owner, fact]: [string, string]) => {\n\t\t\tconst e = await Promise.all([this.embedding(owner), this.embedding(`${owner}: ${fact}`)]);\n\t\t\treturn {owner, fact, embeddings: [e[0][0].embedding, e[1][0].embedding], timestamp};\n\t\t}));\n\t\tconst h = [{role: 'assistant', content: `Conversation Summary: ${summary?.summary}`, timestamp: Date.now()}, ...recent];\n\t\tif(system) h.splice(0, 0, system);\n\t\treturn {history: <any>h, memory};\n\t}\n\n\t/**\n\t * Compare the difference between embeddings (calculates the angle between two vectors)\n\t * @param {number[]} v1 First embedding / vector comparison\n\t * @param {number[]} v2 Second embedding / vector for comparison\n\t * @returns {number} Similarity values 0-1: 0 = unique, 1 = identical\n\t */\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\t/**\n\t * Chunk text into parts for AI digestion\n\t * @param {object | string} target Item that will be chunked (objects get converted)\n\t * @param {number} maxTokens Chunking size. More = better context, less = more specific (Search by paragraphs or lines)\n\t * @param {number} overlapTokens Includes previous X tokens to provide continuity to AI (In addition to max tokens)\n\t * @returns {string[]} Chunked strings\n\t */\n\tchunk(target: object | string, maxTokens = 500, overlapTokens = 50): string[] {\n\t\tconst objString = (obj: any, path = ''): string[] => {\n\t\t\tif(!obj) return [];\n\t\t\treturn Object.entries(obj).flatMap(([key, value]) => {\n\t\t\t\tconst p = path ? `${path}${isNaN(+key) ? `.${key}` : `[${key}]`}` : key;\n\t\t\t\tif(typeof value === 'object' && !Array.isArray(value)) return objString(value, p);\n\t\t\t\treturn `${p}: ${Array.isArray(value) ? value.join(', ') : value}`;\n\t\t\t});\n\t\t};\n\t\tconst lines = typeof target === 'object' ? objString(target) : target.split('\\n');\n\t\tconst tokens = lines.flatMap(l => [...l.split(/\\s+/).filter(Boolean), '\\n']);\n\t\tconst chunks: string[] = [];\n\t\tfor(let i = 0; i < tokens.length;) {\n\t\t\tlet text = '', j = i;\n\t\t\twhile(j < tokens.length) {\n\t\t\t\tconst next = text + (text ? ' ' : '') + tokens[j];\n\t\t\t\tif(this.estimateTokens(next.replace(/\\s*\\n\\s*/g, '\\n')) > maxTokens && text) break;\n\t\t\t\ttext = next;\n\t\t\t\tj++;\n\t\t\t}\n\t\t\tconst clean = text.replace(/\\s*\\n\\s*/g, '\\n').trim();\n\t\t\tif(clean) chunks.push(clean);\n\t\t\ti = Math.max(j - overlapTokens, j === i ? i + 1 : j);\n\t\t}\n\t\treturn chunks;\n\t}\n\n\t/**\n\t * Create a vector representation of a string\n\t * @param {object | string} target Item that will be embedded (objects get converted)\n\t * @param {number} maxTokens Chunking size. More = better context, less = more specific (Search by paragraphs or lines)\n\t * @param {number} overlapTokens Includes previous X tokens to provide continuity to AI (In addition to max tokens)\n\t * @returns {Promise<Awaited<{index: number, embedding: number[], text: string, tokens: number}>[]>} Chunked embeddings\n\t */\n\tembedding(target: object | string, maxTokens = 500, overlapTokens = 50) {\n\t\tconst embed = (text: string): Promise<number[]> => {\n\t\t\treturn new Promise((resolve, reject) => {\n\t\t\t\tconst id = this.embedId++;\n\t\t\t\tthis.embedQueue.set(id, { resolve, reject });\n\t\t\t\tthis.embedWorker?.postMessage({\n\t\t\t\t\tid,\n\t\t\t\t\ttext,\n\t\t\t\t\tmodel: this.ai.options?.embedder || 'bge-small-en-v1.5',\n\t\t\t\t\tpath: this.ai.options.path\n\t\t\t\t});\n\t\t\t});\n\t\t};\n\t\tconst chunks = this.chunk(target, maxTokens, overlapTokens);\n\t\treturn Promise.all(chunks.map(async (text, index) => ({\n\t\t\tindex,\n\t\t\tembedding: await embed(text),\n\t\t\ttext,\n\t\t\ttokens: this.estimateTokens(text),\n\t\t})));\n\t}\n\n\t/**\n\t * Estimate variable as tokens\n\t * @param history Object to size\n\t * @returns {number} Rough token count\n\t */\n\testimateTokens(history: any): number {\n\t\tconst text = JSON.stringify(history);\n\t\treturn Math.ceil((text.length / 4) * 1.2);\n\t}\n\n\t/**\n\t * Compare the difference between two strings using tensor math\n\t * @param target Text that will be 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): Promise<any> {\n\t\tlet resp = await this.ask(message, {system: 'Respond using a JSON blob matching any provided examples', ...options});\n\t\tif(!resp) return {};\n\t\tconst codeBlock = /```(?:.+)?\\s*([\\s\\S]*?)```/.exec(resp);\n\t\tconst jsonStr = codeBlock ? codeBlock[1].trim() : resp;\n\t\treturn JSONAttemptParse(jsonStr, {});\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}\n}\n\nexport default LLM;\n","import {spawn} from 'node:child_process';\nimport {pipeline, read_audio} from '@xenova/transformers';\nimport {AbortablePromise, Ai} from './ai.ts';\n\nexport class Audio {\n\tprivate whisperPipeline: any;\n\n\tconstructor(private ai: Ai) {}\n\n\tprivate combineSpeakerTranscript(chunks: any[], speakers: any[]): string {\n\t\tconst speakerMap = new Map();\n\t\tlet speakerCount = 0;\n\t\tspeakers.forEach((seg: any) => {\n\t\t\tif(!speakerMap.has(seg.speaker)) speakerMap.set(seg.speaker, ++speakerCount);\n\t\t});\n\n\t\tconst lines: string[] = [];\n\t\tlet currentSpeaker = -1;\n\t\tlet currentText = '';\n\t\tchunks.forEach((chunk: any) => {\n\t\t\tconst time = chunk.timestamp[0];\n\t\t\tconst speaker = speakers.find((s: any) => time >= s.start && time <= s.end);\n\t\t\tconst speakerNum = speaker ? speakerMap.get(speaker.speaker) : 1;\n\t\t\tif (speakerNum !== currentSpeaker) {\n\t\t\t\tif(currentText) lines.push(`[speaker ${currentSpeaker}]: ${currentText.trim()}`);\n\t\t\t\tcurrentSpeaker = speakerNum;\n\t\t\t\tcurrentText = chunk.text;\n\t\t\t} else {\n\t\t\t\tcurrentText += chunk.text;\n\t\t\t}\n\t\t});\n\t\tif(currentText) lines.push(`[speaker ${currentSpeaker}]: ${currentText.trim()}`);\n\t\treturn lines.join('\\n');\n\t}\n\n\tasync canDiarization(): Promise<boolean> {\n\t\treturn new Promise((resolve) => {\n\t\t\tconst proc = spawn('python3', ['-c', 'import pyannote.audio']);\n\t\t\tproc.on('close', (code: number) => resolve(code === 0));\n\t\t\tproc.on('error', () => resolve(false));\n\t\t});\n\t}\n\n\tprivate async runDiarization(audioPath: string): Promise<any[]> {\n\t\tif(!await this.canDiarization()) throw new Error('Pyannote is not installed: pip install pyannote.audio');\n\t\tconst script = `\nimport sys\nimport json\nfrom pyannote.audio import Pipeline\n\nos.environ['TORCH_HOME'] = \"${this.ai.options.path}\"\npipeline = Pipeline.from_pretrained(\"pyannote/speaker-diarization-3.1\")\ndiarization = pipeline(sys.argv[1])\n\nsegments = []\nfor turn, _, speaker in diarization.itertracks(yield_label=True):\n segments.append({\n \"start\": turn.start,\n \"end\": turn.end,\n \"speaker\": speaker\n })\n\nprint(json.dumps(segments))\n`;\n\n\t\treturn new Promise((resolve, reject) => {\n\t\t\tlet output = '';\n\t\t\tconst proc = spawn('python3', ['-c', script, audioPath]);\n\t\t\tproc.stdout.on('data', (data: Buffer) => output += data.toString());\n\t\t\tproc.stderr.on('data', (data: Buffer) => console.error(data.toString()));\n\t\t\tproc.on('close', (code: number) => {\n\t\t\t\tif(code === 0) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tresolve(JSON.parse(output));\n\t\t\t\t\t} catch (err) {\n\t\t\t\t\t\treject(new Error('Failed to parse diarization output'));\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\treject(new Error(`Python process exited with code ${code}`));\n\t\t\t\t}\n\t\t\t});\n\n\t\t\tproc.on('error', reject);\n\t\t});\n\t}\n\n\tasr(path: string, options: { model?: string; speaker?: boolean } = {}): AbortablePromise<string | null> {\n\t\tconst { model = this.ai.options.asr || 'whisper-base', speaker = false } = options;\n\t\tlet aborted = false;\n\t\tconst abort = () => { aborted = true; };\n\n\t\tconst p = new Promise<string | null>(async (resolve, reject) => {\n\t\t\ttry {\n\t\t\t\tif(aborted) return resolve(null);\n\t\t\t\tif(!this.whisperPipeline) this.whisperPipeline = await pipeline('automatic-speech-recognition', `Xenova/${model}`, { cache_dir: this.ai.options.path, quantized: true });\n\n\t\t\t\t// Transcript\n\t\t\t\tif(aborted) return resolve(null);\n\t\t\t\tconst audio = await read_audio(path, 16000);\n\t\t\t\tconst transcriptResult = await this.whisperPipeline(audio, {return_timestamps: speaker ? 'word' : false, chunk_length_s: 30,});\n\t\t\t\tif(!speaker) return resolve(transcriptResult.text?.trim() || null);\n\n\t\t\t\t// Speaker Diarization\n\t\t\t\tif(aborted) return resolve(null);\n\t\t\t\tconst speakers = await this.runDiarization(path);\n\t\t\t\tif(aborted) return resolve(null);\n\t\t\t\tconst combined = this.combineSpeakerTranscript(transcriptResult.chunks || [], speakers);\n\t\t\t\tresolve(combined);\n\t\t\t} catch (err) {\n\t\t\t\treject(err);\n\t\t\t}\n\t\t});\n\n\t\treturn Object.assign(p, { abort });\n\t}\n}\n","import {createWorker} from 'tesseract.js';\nimport {AbortablePromise, Ai} from './ai.ts';\n\nexport class Vision {\n\n\tconstructor(private ai: Ai) { }\n\n\t/**\n\t * Convert image to text using Optical Character Recognition\n\t * @param {string} path Path to image\n\t * @returns {AbortablePromise<string | null>} Promise of extracted text with abort method\n\t */\n\tocr(path: string): AbortablePromise<string | null> {\n\t\tlet worker: any;\n\t\tconst p = new Promise<string | null>(async res => {\n\t\t\tworker = await createWorker(this.ai.options.ocr || 'eng', 2, {cachePath: this.ai.options.path});\n\t\t\tconst {data} = await worker.recognize(path);\n\t\t\tawait worker.terminate();\n\t\t\tres(data.text.trim() || null);\n\t\t});\n\t\treturn Object.assign(p, {abort: () => worker?.terminate()});\n\t}\n}\n","import * as os from 'node:os';\nimport LLM, {AnthropicConfig, OllamaConfig, OpenAiConfig, LLMRequest} from './llm';\nimport { Audio } from './audio.ts';\nimport {Vision} from './vision.ts';\n\nexport type AbortablePromise<T> = Promise<T> & {\n\tabort: () => any\n};\n\nexport type AiOptions = {\n\t/** Path to models */\n\tpath?: string;\n\t/** ASR model: whisper-tiny, whisper-base */\n\tasr?: string;\n\t/** Embedding model: all-MiniLM-L6-v2, bge-small-en-v1.5, bge-large-en-v1.5 */\n\tembedder?: string;\n\t/** Large language models, first is default */\n\tllm?: Omit<LLMRequest, 'model'> & {\n\t\tmodels: {[model: string]: AnthropicConfig | OllamaConfig | OpenAiConfig};\n\t}\n\t/** OCR model: eng, eng_best, eng_fast */\n\tocr?: string;\n}\n\nexport class Ai {\n\t/** Audio processing AI */\n\taudio!: Audio;\n\t/** Language processing AI */\n\tlanguage!: LLM;\n\t/** Vision processing AI */\n\tvision!: Vision;\n\n\tconstructor(public readonly options: AiOptions) {\n\t\tif(!options.path) options.path = os.tmpdir();\n\t\tprocess.env.TRANSFORMERS_CACHE = options.path;\n\t\tthis.audio = new Audio(this);\n\t\tthis.language = new LLM(this);\n\t\tthis.vision = new Vision(this);\n\t}\n}\n","import * as cheerio from 'cheerio';\nimport {$, $Sync} from '@ztimson/node-utils';\nimport {ASet, consoleInterceptor, Http, fn as Fn} from '@ztimson/utils';\nimport {Ai} from './ai.ts';\nimport {LLMRequest} from './llm.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, stream: LLMRequest['stream'], ai: Ai) => any | Promise<any>,\n};\n\nexport const CliTool: AiTool = {\n\tname: 'cli',\n\tdescription: 'Use the command line interface, returns any output',\n\targs: {command: {type: 'string', description: 'Command to run', required: true}},\n\tfn: (args: {command: string}) => $`${args.command}`\n}\n\nexport const DateTimeTool: AiTool = {\n\tname: 'get_datetime',\n\tdescription: 'Get current UTC date / time',\n\targs: {},\n\tfn: async () => new Date().toUTCString()\n}\n\nexport const ExecTool: AiTool = {\n\tname: 'exec',\n\tdescription: 'Run code/scripts',\n\targs: {\n\t\tlanguage: {type: 'string', description: 'Execution language', enum: ['cli', 'node', 'python'], required: true},\n\t\tcode: {type: 'string', description: 'Code to execute', required: true}\n\t},\n\tfn: async (args, stream, 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}, stream, ai);\n\t\t\t\tcase 'node':\n\t\t\t\t\treturn await JSTool.fn({code: args.code}, stream, ai);\n\t\t\t\tcase 'python': {\n\t\t\t\t\treturn await PythonTool.fn({code: args.code}, stream, ai);\n\t\t\t\t}\n\t\t\t}\n\t\t} catch(err: any) {\n\t\t\treturn {error: err?.message || err.toString()};\n\t\t}\n\t}\n}\n\nexport const FetchTool: AiTool = {\n\tname: 'fetch',\n\tdescription: 'Make HTTP request to URL',\n\targs: {\n\t\turl: {type: 'string', description: 'URL to fetch', required: true},\n\t\tmethod: {type: 'string', description: 'HTTP method to use', enum: ['GET', 'POST', 'PUT', 'DELETE'], default: 'GET'},\n\t\theaders: {type: 'object', description: 'HTTP headers to send', default: {}},\n\t\tbody: {type: 'object', description: 'HTTP body to send'},\n\t},\n\tfn: (args: {\n\t\turl: string;\n\t\tmethod: 'GET' | 'POST' | 'PUT' | 'DELETE';\n\t\theaders: {[key: string]: string};\n\t\tbody: any;\n\t}) => new Http({url: args.url, headers: args.headers}).request({method: args.method || 'GET', body: args.body})\n}\n\nexport const JSTool: AiTool = {\n\tname: 'exec_javascript',\n\tdescription: 'Execute commonjs javascript',\n\targs: {\n\t\tcode: {type: 'string', description: 'CommonJS javascript', required: true}\n\t},\n\tfn: async (args: {code: string}) => {\n\t\tconst console = consoleInterceptor(null);\n\t\tconst resp = await Fn<any>({console}, args.code, true).catch((err: any) => console.output.error.push(err));\n\t\treturn {...console.output, return: resp, stdout: undefined, stderr: undefined};\n\t}\n}\n\nexport const PythonTool: AiTool = {\n\tname: 'exec_javascript',\n\tdescription: 'Execute commonjs javascript',\n\targs: {\n\t\tcode: {type: 'string', description: 'CommonJS javascript', required: true}\n\t},\n\tfn: async (args: {code: string}) => ({result: $Sync`python -c \"${args.code}\"`})\n}\n\nexport const ReadWebpageTool: AiTool = {\n\tname: 'read_webpage',\n\tdescription: 'Extract clean, structured content from a webpage. Use after web_search to read specific URLs',\n\targs: {\n\t\turl: {type: 'string', description: 'URL to extract content from', required: true},\n\t\tfocus: {type: 'string', description: 'Optional: What aspect to focus on (e.g., \"pricing\", \"features\", \"contact info\")'}\n\t},\n\tfn: async (args: {url: string; focus?: string}) => {\n\t\tconst html = await fetch(args.url, {headers: {\"User-Agent\": \"Mozilla/5.0 (Windows NT 10.0; Win64; x64)\"}})\n\t\t\t.then(r => r.text()).catch(err => {throw new Error(`Failed to fetch: ${err.message}`)});\n\n\t\tconst $ = cheerio.load(html);\n\t\t$('script, style, nav, footer, header, aside, iframe, noscript, [role=\"navigation\"], [role=\"banner\"], .ad, .ads, .cookie, .popup').remove();\n\t\tconst metadata = {\n\t\t\ttitle: $('meta[property=\"og:title\"]').attr('content') || $('title').text() || '',\n\t\t\tdescription: $('meta[name=\"description\"]').attr('content') || $('meta[property=\"og:description\"]').attr('content') || '',\n\t\t};\n\n\t\tlet content = '';\n\t\tconst contentSelectors = ['article', 'main', '[role=\"main\"]', '.content', '.post', '.entry', 'body'];\n\t\tfor (const selector of contentSelectors) {\n\t\t\tconst el = $(selector).first();\n\t\t\tif (el.length && el.text().trim().length > 200) {\n\t\t\t\tcontent = el.text();\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tif (!content) content = $('body').text();\n\t\tcontent = content.replace(/\\s+/g, ' ').trim().slice(0, 8000);\n\n\t\treturn {url: args.url, title: metadata.title.trim(), description: metadata.description.trim(), content, focus: args.focus};\n\t}\n}\n\nexport const WebSearchTool: AiTool = {\n\tname: 'web_search',\n\tdescription: 'Use duckduckgo (anonymous) to find find relevant online resources. Returns a list of URLs that works great with the `read_webpage` tool',\n\targs: {\n\t\tquery: {type: 'string', description: 'Search string', required: true},\n\t\tlength: {type: 'string', description: 'Number of results to return', default: 5},\n\t},\n\tfn: async (args: {\n\t\tquery: string;\n\t\tlength: number;\n\t}) => {\n\t\tconst html = await fetch(`https://html.duckduckgo.com/html/?q=${encodeURIComponent(args.query)}`, {\n\t\t\theaders: {\"User-Agent\": \"Mozilla/5.0 (Windows NT 10.0; Win64; x64)\", \"Accept-Language\": \"en-US,en;q=0.9\"}\n\t\t}).then(resp => resp.text());\n\t\tlet match, regex = /<a .*?href=\"(.+?)\".+?<\\/a>/g;\n\t\tconst results = new ASet<string>();\n\t\twhile((match = regex.exec(html)) !== null) {\n\t\t\tlet url = /uddg=(.+)&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","timestamp","messages","h","textContent","c","m","i","message","options","controller","res","tools","requestParams","t","objectMap","key","value","resp","isFirstMessage","err","chunk","text","last","JSONAttemptParse","toolCalls","results","toolCall","tool","findByProp","result","JSONSanitize","OpenAi","host","token","openAI","clean","tc","record","h2","rest","rej","args","LLM","Worker","join","dirname","fileURLToPath","id","embedding","pending","config","abort","search","query","subject","limit","o","q","a","b","relevant","compressed","updated","m2","max","min","keep","tokens","system","recent","process","summary","memory","owner","fact","e","v1","v2","dotProduct","normA","normB","denominator","target","maxTokens","overlapTokens","objString","obj","path","p","l","chunks","j","next","embed","resolve","reject","index","searchTerms","vector","dimensions","char","v","similarities","refVector","acc","s","codeBlock","jsonStr","Audio","speakers","speakerMap","speakerCount","seg","lines","currentSpeaker","currentText","time","speaker","speakerNum","proc","spawn","code","audioPath","script","output","data","aborted","pipeline","audio","read_audio","transcriptResult","combined","Vision","worker","createWorker","Ai","os","CliTool","$","DateTimeTool","ExecTool","stream","JSTool","PythonTool","FetchTool","Http","console","consoleInterceptor","Fn","$Sync","ReadWebpageTool","html","r","cheerio","metadata","content","contentSelectors","selector","el","WebSearchTool","match","regex","ASet","url"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ztimson/ai-utils",
3
- "version": "0.6.1",
3
+ "version": "0.6.2",
4
4
  "description": "AI Utility library",
5
5
  "author": "Zak Timson",
6
6
  "license": "MIT",