{"version":3,"file":"index.mjs","names":[],"sources":["../src/provider.ts","../src/token-pool.ts","../src/tools.ts","../src/antrhopic.ts","../src/memory/graph.ts","../src/utils.ts","../src/memory/kd-tree.ts","../src/memory/memory-state.ts","../src/memory/memory.ts","../src/open-ai.ts","../src/llm.ts","../src/audio.ts","../src/vision.ts","../src/ai.ts"],"sourcesContent":["import {AbortablePromise} from './ai.ts';\nimport {LLMRequest} from './llm.ts';\n\nexport abstract class LLMProvider {\n\tabstract ask(message: string, options: LLMRequest): AbortablePromise<string>;\n}\n","const DEFAULT_COOLDOWN = 15 * 60 * 1000;\n\ntype TokenState = {\n\ttoken: string;\n\tcooldownUntil: number; // 0 = available now\n\tlastError?: {code: number, message: string};\n};\n\nexport class TokenPoolExhaustedError extends Error {\n\tconstructor(public tokens: Record<string, {code: number, message: string}>) {\n\t\tsuper(`All tokens exhausted:\\n${Object.entries(tokens).map(([t, e]) => `${t}: [${e.code}] ${e.message}`).join('\\n')}`);\n\t\tthis.name = 'TokenPoolExhaustedError';\n\t}\n}\n\nexport class TokenPool {\n\tprivate states: TokenState[];\n\n\tconstructor(...tokens: string[]) {\n\t\tthis.states = tokens.map(token => ({token, cooldownUntil: 0}));\n\t}\n\n\tprivate preview(token: string): string {\n\t\treturn token.length <= 8 ? '****' : `${token.slice(0, 4)}...${token.slice(-4)}`;\n\t}\n\n\t/** Anthropic & OpenAI SDKs both attach `status` to thrown errors */\n\tprivate statusCode(err: any): number {\n\t\treturn err?.status ?? err?.response?.status ?? err?.statusCode;\n\t}\n\n\tprivate retryAfter(err: any): number {\n\t\tconst headers = err?.headers || err?.response?.headers;\n\t\tconst raw = headers?.get?.('retry-after') ?? headers?.['retry-after'];\n\t\tif(raw) {\n\t\t\tconst seconds = Number(raw);\n\t\t\tif(!isNaN(seconds)) return Date.now() + seconds * 1000;\n\t\t\tconst date = new Date(raw).getTime();\n\t\t\tif(!isNaN(date)) return date;\n\t\t}\n\t\treturn Date.now() + DEFAULT_COOLDOWN;\n\t}\n\n\tasync run<T>(fn: (token: string) => Promise<T>): Promise<T> {\n\t\tconst now = Date.now();\n\t\tfor(const state of this.states) {\n\t\t\tif(state.cooldownUntil > now) continue;\n\t\t\ttry {\n\t\t\t\tconst result = await fn(state.token);\n\t\t\t\tstate.cooldownUntil = 0;\n\t\t\t\tstate.lastError = undefined;\n\t\t\t\treturn result;\n\t\t\t} catch(err: any) {\n\t\t\t\tconst code = this.statusCode(err);\n\t\t\t\tif(![401, 403, 429].includes(code)) throw err;\n\t\t\t\tstate.cooldownUntil = code === 429 ? this.retryAfter(err) : Date.now() + DEFAULT_COOLDOWN;\n\t\t\t\tstate.lastError = {code, message: err?.message || 'Unknown error'};\n\t\t\t}\n\t\t}\n\n\t\tconst failures: Record<string, {code: number, message: string}> = {};\n\t\tthis.states.forEach(s => { if(s.lastError) failures[this.preview(s.token)] = s.lastError; });\n\t\tthrow new TokenPoolExhaustedError(failures);\n\t}\n}\n","import  * as cheerio from 'cheerio';\nimport {$Sync} from '@ztimson/node-utils';\nimport {ASet, consoleInterceptor, Http, fn as Fn, decodeHtml, objectMap} from '@ztimson/utils';\nimport * as os from 'node:os';\nimport {Ai} from './ai.ts';\nimport {LLMRequest} from './llm.ts';\n\nconst UA = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64)';\n\nconst getShell = () => {\n\tif(os.platform() == 'win32') return 'cmd';\n\treturn $Sync`echo $SHELL`?.split('/').pop() || 'bash';\n}\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, toolId?: string) => any | Promise<any>,\n};\n\nexport function convertSchema(schema: any): any {\n\tif(!schema) return null;\n\n\tconst convertProp = (prop: any): any => {\n\t\tconst converted: any = {\n\t\t\ttype: prop.type || 'string',\n\t\t};\n\n\t\tif(prop.description) converted.description = prop.description;\n\t\tif(prop.default !== undefined) converted.default = prop.default;\n\t\tif(prop.enum) converted.enum = prop.enum;\n\t\tif(prop.pattern) converted.pattern = prop.pattern;\n\n\t\t// Handle array items\n\t\tif(prop.type === 'array' && prop.items) {\n\t\t\tconverted.items = convertProp(prop.items);\n\t\t}\n\n\t\t// Handle object properties\n\t\tif(prop.type === 'object' && prop.items) {\n\t\t\tconverted.properties = objectMap(prop.items, (key, value) => convertProp(value));\n\t\t\tconst required = Object.entries(prop.items).filter(([_, v]: any) => v.required).map(([k]) => k);\n\t\t\tif(required.length) converted.required = required;\n\t\t\tconverted.additionalProperties = false;\n\t\t}\n\n\t\t// Handle min/max based on type\n\t\tif(prop.min !== undefined) {\n\t\t\tif(prop.type === 'string' || prop.type === 'array') converted.minLength = prop.min;\n\t\t\telse converted.minimum = prop.min;\n\t\t}\n\t\tif(prop.max !== undefined) {\n\t\t\tif(prop.type === 'string' || prop.type === 'array') converted.maxLength = prop.max;\n\t\t\telse converted.maximum = prop.max;\n\t\t}\n\n\t\treturn converted;\n\t};\n\n\treturn {\n\t\ttype: 'object',\n\t\tproperties: objectMap(schema, (key, value) => convertProp(value)),\n\t\trequired: Object.entries(schema).filter(([_, v]: any) => v.required).map(([k]) => k),\n\t\tadditionalProperties: false\n\t};\n}\n\nexport const ExecCliTool: 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}) => $Sync`${args.command}`\n}\n\nexport const ExecJSTool: 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 c = consoleInterceptor(null);\n\t\tconst resp = await Fn<any>({console: c}, args.code, true).catch((err: any) => c.output.error.push(err));\n\t\treturn {...c.output, return: resp, stdout: undefined, stderr: undefined};\n\t}\n}\n\nexport const ExecPythonTool: AiTool = {\n\tname: 'exec_python',\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 ExecTool: AiTool = {\n\tname: 'exec',\n\tdescription: 'Run code/scripts',\n\targs: {\n\t\tlanguage: {type: 'string', description: `Execution language (CLI: ${getShell()})`, 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.language) {\n\t\t\t\tcase 'cli':\n\t\t\t\t\treturn await ExecCliTool.fn({command: args.code}, stream, ai);\n\t\t\t\tcase 'node':\n\t\t\t\t\treturn await ExecJSTool.fn({code: args.code}, stream, ai);\n\t\t\t\tcase 'python':\n\t\t\t\t\treturn await ExecPythonTool.fn({code: args.code}, stream, ai);\n\t\t\t\tdefault:\n\t\t\t\t\tthrow new Error(`Unsupported language: ${args.language}`);\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 FsDeleteTool = (whitelist: null | string[] = null): AiTool => {\n\treturn {\n\t\tname: 'fs_delete',\n\t\tdescription: 'Delete a file or directory',\n\t\targs: {\n\t\t\tpath: {type: 'string', description: 'Path to file or directory', required: true},\n\t\t\trecursive: {type: 'boolean', description: 'Delete all children', required: false}\n\t\t},\n\t\tfn: async ({path, recursive = false}) => {\n\t\t\tconst {existsSync, rmSync} = await import('fs');\n\t\t\tconst normalizePath = p => p.replace(/\\\\/g, '/');\n\n\t\t\tpath = normalizePath(path);\n\t\t\tif(whitelist && !whitelist.some(p => path.startsWith(p))) return {error: 'Permission denied'};\n\t\t\tif(!existsSync(path)) return {error: 'Path does not exist'};\n\n\t\t\trmSync(path, {recursive, force: true});\n\t\t\treturn {success: true, path};\n\t\t}\n\t}\n}\n\nexport const FsMoveTool = (whitelist: null | string[] = null): AiTool => {\n\treturn {\n\t\tname: 'fs_move',\n\t\tdescription: 'Move or rename a file or directory',\n\t\targs: {\n\t\t\tsource: {type: 'string', description: 'Path to source file or directory', required: true},\n\t\t\tdestination: {type: 'string', description: 'Path to destination file or directory', required: true}\n\t\t},\n\t\tfn: async ({source, destination}) => {\n\t\t\tconst {existsSync, renameSync} = await import('fs');\n\t\t\tconst normalizePath = p => p.replace(/\\\\/g, '/');\n\n\t\t\tsource = normalizePath(source);\n\t\t\tdestination = normalizePath(destination);\n\t\t\tif(whitelist && !whitelist.some(p => source.startsWith(p) && destination.startsWith(p))) return {error: 'Permission denied'};\n\n\t\t\tif(!existsSync(source)) return {error: 'Source path does not exist'};\n\t\t\tif(existsSync(destination)) return {error: 'Destination path already exists'};\n\n\t\t\trenameSync(source, destination);\n\t\t\treturn {success: true, source, destination};\n\t\t}\n\t}\n}\n\nexport const FsReadTool = (whitelist: null | string[] = null): AiTool => {\n\treturn {\n\t\tname: 'fs_read',\n\t\tdescription: 'Read the contents of a provided path. Works with files and directories',\n\t\targs: {path: {type: 'string', description: 'Path to file or directory', required: true}},\n\t\tfn: async ({path}) => {\n\t\t\tconst {existsSync, lstatSync, readdirSync, readFileSync} = await import('fs');\n\t\t\tconst {join} = await import('path');\n\t\t\tconst normalizePath = p => p.replace(/\\\\/g, '/');\n\n\t\t\tpath = normalizePath(path);\n\t\t\tif(whitelist && !whitelist.some(p => path.startsWith(p))) return {error: 'Permission denied'};\n\n\t\t\tif(!existsSync(path)) return {error: 'Path does not exist'};\n\t\t\tconst stats = lstatSync(path);\n\t\t\tif(stats.isDirectory()) {\n\t\t\t\tconst children = readdirSync(path).map(name => {\n\t\t\t\t\tconst childPath = normalizePath(join(path, name));\n\t\t\t\t\tconst childStats = lstatSync(childPath);\n\t\t\t\t\treturn {name, type: childStats.isDirectory() ? 'directory' : 'file', size: childStats.size};\n\t\t\t\t});\n\t\t\t\treturn {type: 'directory', children};\n\t\t\t}\n\t\t\tconst content = readFileSync(path, 'utf-8');\n\t\t\treturn {type: 'file', content};\n\t\t}\n\t}\n}\n\nexport const FsSearchTool = (whitelist: null | string[] = null): AiTool => {\n\treturn {\n\t\tname: 'fs_search',\n\t\tdescription: 'Scan a directory for matching glob patterns (e.g. \"**/*.js\", \"src/**/*.test.ts\")',\n\t\targs: {\n\t\t\tpattern: {type: 'string', description: 'Glob pattern to match against paths', required: true},\n\t\t\troot: {type: 'string', description: 'Directory to search from', required: false, default: '.'}\n\t\t},\n\t\tfn: async ({pattern, root = '.'}) => {\n\t\t\tconst {existsSync, lstatSync, readdirSync} = await import('fs');\n\t\t\tconst {join, relative} = await import('path');\n\t\t\tconst normalizePath = p => p.replace(/\\\\/g, '/');\n\n\t\t\troot = normalizePath(root);\n\t\t\tif(!existsSync(root)) return {error: 'Root path does not exist'};\n\t\t\tif(!lstatSync(root).isDirectory()) return {error: 'Root path is not a directory'};\n\n\t\t\tif(whitelist && !whitelist.some(p => root.startsWith(p))) return {error: 'Permission denied'};\n\n\t\t\tconst globToRegex = (glob) => {\n\t\t\t\tlet re = '';\n\t\t\t\tfor(let i = 0; i < glob.length; i++) {\n\t\t\t\t\tconst c = glob[i];\n\t\t\t\t\tif(c === '*') {\n\t\t\t\t\t\tif(glob[i + 1] === '*') {\n\t\t\t\t\t\t\tconst isSlash = glob[i + 2] === '/';\n\t\t\t\t\t\t\tre += '.*';\n\t\t\t\t\t\t\ti += isSlash ? 2 : 1;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tre += '[^/]*';\n\t\t\t\t\t\t}\n\t\t\t\t\t} else if(c === '?') {\n\t\t\t\t\t\tre += '[^/]';\n\t\t\t\t\t} else if('.+^$(){}|[]\\\\'.includes(c)) {\n\t\t\t\t\t\tre += '\\\\' + c;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tre += c;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn new RegExp('^' + re + '$');\n\t\t\t};\n\t\t\tconst regex = globToRegex(pattern);\n\n\t\t\tconst results: any = [];\n\t\t\tconst walk = (dir) => {\n\t\t\t\tfor(const name of readdirSync(dir)) {\n\t\t\t\t\tconst fullPath = normalizePath(join(dir, name));\n\t\t\t\t\tconst stats = lstatSync(fullPath);\n\t\t\t\t\tconst relPath = normalizePath(relative(root, fullPath));\n\t\t\t\t\tif(regex.test(relPath)) {\n\t\t\t\t\t\tresults.push({path: relPath, type: stats.isDirectory() ? 'directory' : 'file', size: stats.size});\n\t\t\t\t\t}\n\t\t\t\t\tif(stats.isDirectory()) walk(fullPath);\n\t\t\t\t}\n\t\t\t};\n\t\t\twalk(root);\n\n\t\t\treturn results;\n\t\t}\n\t}\n}\n\nexport const FsWriteTool = (whitelist: null | string[] = null): AiTool => {\n\treturn {\n\t\tname: 'fs_write',\n\t\tdescription: 'Create a directory, write content to a file or preform a find & replace',\n\t\targs: {\n\t\t\tpath: {type: 'string', description: 'Path to file or directory', required: true},\n\t\t\tcontent: {type: 'string', description: 'Content to write or replace (Omit to create a directory)'},\n\t\t\tfind: {type: 'string', description: 'Text or regex pattern to match (regex must match pattern: \"/pattern/g\")'}\n\t\t},\n\t\tfn: async ({path, content, find}) => {\n\t\t\tconst {existsSync, mkdirSync, readFileSync, writeFileSync} = await import('fs');\n\t\t\tconst {dirname} = await import('path');\n\t\t\tconst normalizePath = p => p.replace(/\\\\/g, '/');\n\n\t\t\tpath = normalizePath(path);\n\t\t\tif(whitelist && !whitelist.some(p => path.startsWith(p))) return {error: 'Permission denied'};\n\n\t\t\tif(content === undefined) {\n\t\t\t\tmkdirSync(path, {recursive: true});\n\t\t\t\treturn {success: true, type: 'directory', path};\n\t\t\t}\n\n\t\t\tconst dir = normalizePath(dirname(path));\n\t\t\tif(!existsSync(dir)) mkdirSync(dir, {recursive: true});\n\n\t\t\tif(find && existsSync(path)) {\n\t\t\t\tconst existing = readFileSync(path, 'utf-8');\n\t\t\t\tconst regexMatch = find.match(/^\\/(.+)\\/([gimuy]*)$/);\n\t\t\t\tconst pattern = regexMatch ? new RegExp(regexMatch[1], regexMatch[2]) : find;\n\n\t\t\t\tif(!existing.match(pattern)) return {error: 'Find pattern not found in file'};\n\n\t\t\t\tconst updated = existing.replace(pattern, content);\n\t\t\t\twriteFileSync(path, updated, 'utf-8');\n\t\t\t\treturn {success: true, type: 'file', path, replaced: true, content: updated};\n\t\t\t}\n\n\t\t\twriteFileSync(path, content, 'utf-8');\n\t\t\treturn {success: true, type: 'file', path, content};\n\t\t}\n\t}\n}\n\nexport const GetPathsTool: AiTool = {\n\tname: 'get_paths',\n\tdescription: 'Get the current working directory, and paths to the users home directory',\n\tfn: async () => {\n\t\treturn {\n\t\t\thome: os.homedir(),\n\t\t\tcwd: process.cwd()\n\t\t};\n\t}\n}\n\nexport const GetDatetimeTool: AiTool = {\n\tname: 'get_datetime',\n\tdescription: 'Get local/UTC timestamp',\n\targs: {\n\t\ttimezone: {type: 'string', description: 'Which timezone to return, defaults to local', enum: ['local', 'utc'], default: 'local'}\n\t},\n\tfn: ({timezone}) => new Date()[timezone === 'local' ? 'toString' : 'toUTCString']()\n}\n\nexport const GetDevice: AiTool = {\n\tname: 'get_device',\n\tdescription: 'Get comprehensive system information including hostname, specs, load, storage, and network status',\n\targs: {},\n\tfn: async () => {\n\t\tconst platform = os.platform();\n\t\tconst hostname = os.hostname();\n\n\t\t// CPU Info\n\t\tconst cpus = os.cpus();\n\t\tconst cpuModel = cpus[0].model;\n\t\tconst cpuCores = cpus.length;\n\n\t\t// Memory Info\n\t\tconst totalMem: any = (os.totalmem() / 1024 / 1024 / 1024).toFixed(2);\n\t\tconst freeMem: any = (os.freemem() / 1024 / 1024 / 1024).toFixed(2);\n\t\tconst usedMem: any = (totalMem - freeMem).toFixed(2);\n\t\tconst memUsage: any = ((usedMem / totalMem) * 100).toFixed(1);\n\n\t\t// Load Average (not available on Windows)\n\t\tconst loadAvg = platform === 'win32' ? ['N/A', 'N/A', 'N/A'] : os.loadavg().map(l => l.toFixed(2));\n\n\t\t// Storage Usage\n\t\tlet storage = {};\n\t\tif(platform === 'win32') {\n\t\t\tconst ps = $Sync`powershell \"Get-PSDrive C | Select-Object Used,Free | ConvertTo-Json\"`.trim();\n\t\t\tconst drive = JSON.parse(ps);\n\t\t\tconst used: any = (drive.Used / 1024 / 1024 / 1024).toFixed(2);\n\t\t\tconst free: any = (drive.Free / 1024 / 1024 / 1024).toFixed(2);\n\t\t\tconst total: any = (parseFloat(used) + parseFloat(free)).toFixed(2);\n\t\t\tconst usage: any = ((used / total) * 100).toFixed(1);\n\t\t\tstorage = {\n\t\t\t\tfilesystem: 'C:',\n\t\t\t\tsize: `${total} GB`,\n\t\t\t\tused: `${used} GB`,\n\t\t\t\tavailable: `${free} GB`,\n\t\t\t\tusage: `${usage}%`\n\t\t\t};\n\t\t} else {\n\t\t\tconst df = $Sync`df -h / | tail -1`.trim();\n\t\t\tconst s = df.split(/\\s+/);\n\t\t\tstorage = {\n\t\t\t\tfilesystem: s[0],\n\t\t\t\tsize: s[1],\n\t\t\t\tused: s[2],\n\t\t\t\tavailable: s[3],\n\t\t\t\tusage: s[4]\n\t\t\t};\n\t\t}\n\n\t\t// Network Status\n\t\tconst interfaces = os.networkInterfaces();\n\t\tconst activeIfaces = Object.entries(interfaces)\n\t\t\t.filter(([name]) => name !== 'lo' && !name.includes('Loopback'))\n\t\t\t.map(([name, addrs]) => {\n\t\t\t\tconst ipv4 = addrs?.find(a => a.family === 'IPv4');\n\t\t\t\treturn ipv4 ? {name, ip: ipv4.address} : null;\n\t\t\t})\n\t\t\t.filter(Boolean);\n\n\t\t// Internet connectivity check\n\t\tlet internet = false;\n\t\ttry {\n\t\t\tif(platform === 'win32') {\n\t\t\t\t$Sync`powershell \"Test-Connection -ComputerName 8.8.8.8 -Count 1 -Quiet\"`;\n\t\t\t} else {\n\t\t\t\t$Sync`ping -c 1 -W 2 8.8.8.8 > /dev/null 2>&1`;\n\t\t\t}\n\t\t\tinternet = true;\n\t\t} catch {}\n\n\t\t// Uptime\n\t\tconst uptime = os.uptime();\n\t\tconst days = Math.floor(uptime / 86400);\n\t\tconst hours = Math.floor((uptime % 86400) / 3600);\n\t\tconst minutes = Math.floor((uptime % 3600) / 60);\n\n\t\treturn {\n\t\t\thostname,\n\t\t\tcpu: {\n\t\t\t\tmodel: cpuModel,\n\t\t\t\tcores: cpuCores\n\t\t\t},\n\t\t\tmemory: {\n\t\t\t\ttotal: `${totalMem} GB`,\n\t\t\t\tused: `${usedMem} GB`,\n\t\t\t\tfree: `${freeMem} GB`,\n\t\t\t\tusage: `${memUsage}%`\n\t\t\t},\n\t\t\tload: {\n\t\t\t\t'1min': loadAvg[0],\n\t\t\t\t'5min': loadAvg[1],\n\t\t\t\t'15min': loadAvg[2]\n\t\t\t},\n\t\t\tstorage,\n\t\t\tnetwork: {\n\t\t\t\tinterfaces: activeIfaces,\n\t\t\t\tinternet: internet ? 'connected' : 'disconnected'\n\t\t\t},\n\t\t\tuptime: `${days}d ${hours}h ${minutes}m`,\n\t\t\tplatform: `${os.type()} ${os.release()}`\n\t\t};\n\t}\n}\n\nexport const GetWikipediaTool: AiTool = {\n\tname: 'get_wikipedia',\n\tdescription: 'Search Wikipedia for matching articles',\n\targs: {\n\t\tquery: {type: 'string', description: 'Search term or article title', required: true},\n\t\tmode: {type: 'string', description: 'search - look for articles, summary - intro of first found article (default), full - complete first found article', enum: ['search', 'summary', 'full'], default: 'summary'},\n\t\tua: {type: 'string', description: 'User Agent'},\n\t},\n\tfn: async ({query, mode, ua}) => {\n\t\tclass WikipediaClient {\n\t\t\tuseragent = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64)';\n\n\t\t\tconstructor(useragent: string) {\n\t\t\t\tthis.useragent = useragent;\n\t\t\t}\n\n\t\t\tasync get(url) {\n\t\t\t\tconst resp = await fetch(url, {headers: {'User-Agent': this.useragent}});\n\t\t\t\treturn resp.json();\n\t\t\t}\n\n\t\t\tapi(params) {\n\t\t\t\tconst qs = new URLSearchParams({...params, format: 'json', utf8: '1'}).toString();\n\t\t\t\treturn this.get(`https://en.wikipedia.org/w/api.php?${qs}`);\n\t\t\t}\n\n\t\t\tclean(text) {\n\t\t\t\tconst cutoffs = ['== See also ==', '== References ==', '== Bibliography ==', '== External links =='];\n\t\t\t\tfor (const marker of cutoffs) {\n\t\t\t\t\tconst idx = text.indexOf(marker);\n\t\t\t\t\tif (idx !== -1) text = text.slice(0, idx);\n\t\t\t\t}\n\n\t\t\t\treturn text\n\t\t\t\t\t.replace(/^={4}\\s*(.+?)\\s*={4}$/gm, '#### $1')\n\t\t\t\t\t.replace(/^={3}\\s*(.+?)\\s*={3}$/gm, '### $1')\n\t\t\t\t\t.replace(/^={2}\\s*(.+?)\\s*={2}$/gm, '## $1')\n\t\t\t\t\t.replace(/\\n{3,}/g, '\\n\\n')\n\t\t\t\t\t.replace(/ {2,}/g, ' ')\n\t\t\t\t\t.replace(/\\[\\d+]/g, '')\n\t\t\t\t\t.trim();\n\t\t\t}\n\n\t\t\tasync searchTitles(query: string, limit = 6) {\n\t\t\t\tconst data = await this.api({action: 'query', list: 'search', srsearch: query, srlimit: limit, srprop: 'snippet'});\n\t\t\t\treturn data.query?.search || [];\n\t\t\t}\n\n\t\t\tasync fetchExtract(title: string, introOnly = false) {\n\t\t\t\tconst params: any = {action: 'query', prop: 'extracts', titles: title, explaintext: 1, redirects: 1};\n\t\t\t\tif(introOnly) params.exintro = 1;\n\t\t\t\tconst data = await this.api(params);\n\t\t\t\tconst page: any = Object.values(data.query?.pages || {})[0];\n\t\t\t\treturn this.clean(page?.extract || '');\n\t\t\t}\n\n\t\t\tpageUrl(title: string) {\n\t\t\t\treturn `https://en.wikipedia.org/wiki/${encodeURIComponent(title.replace(/ /g, '_'))}`;\n\t\t\t}\n\n\t\t\tstripHtml(text: string) {\n\t\t\t\treturn text.replace(/<[^>]+>/g, '');\n\t\t\t}\n\n\t\t\tasync lookup(query: string, detail = 'summary') {\n\t\t\t\tconst results = await this.searchTitles(query, 6);\n\t\t\t\tif(!results.length) return `❌ No Wikipedia articles found for \"${query}\"`;\n\t\t\t\tconst title = results[0].title;\n\t\t\t\tconst url = this.pageUrl(title);\n\t\t\t\tconst introOnly = detail !== 'full';\n\t\t\t\tconst content = await this.fetchExtract(title, introOnly);\n\t\t\t\treturn `## ${title}\\n🔗 ${url}\\n\\n${content}`;\n\t\t\t}\n\n\t\t\tasync search(query: string) {\n\t\t\t\tconst results = await this.searchTitles(query, 8);\n\t\t\t\tif(!results.length) return `❌ No results for \"${query}\"`;\n\t\t\t\tconst lines = [`### Search results for \"${query}\"\\n`];\n\t\t\t\tfor(let i = 0; i < results.length; i++) {\n\t\t\t\t\tconst r = results[i];\n\t\t\t\t\tconst snippet = this.stripHtml(r.snippet || '').trim();\n\t\t\t\t\tlines.push(`**${i + 1}. ${r.title}**\\n${snippet}\\n${this.pageUrl(r.title)}`);\n\t\t\t\t}\n\t\t\t\treturn lines.join('\\n\\n');\n\t\t\t}\n\t\t}\n\n\t\tconst wiki = new WikipediaClient(ua);\n\t\tif(mode === 'search') return wiki.search(query);\n\t\treturn wiki.lookup(query, mode || 'summary');\n\t}\n};\n\nexport const GeoCodeTool: AiTool = {\n\tname: 'geo_code',\n\tdescription: 'Converts coordinates to address OR vice versa',\n\targs: {\n\t\tquery: {type: 'string', description: 'Search query - coordinates (lat,lon) or address string', required: true},\n\t},\n\tfn: async ({query}) => {\n\t\tconst coordinates = /(-?\\d+(?:\\.\\d+)?).*?,.*?(-?\\d+(?:\\.\\d+)?)/.exec(query);\n\t\tif(coordinates) { // Geolocate\n\t\t\tconst url = `https://nominatim.openstreetmap.org/reverse?format=json&lat=${encodeURIComponent(coordinates[1])}&lon=${encodeURIComponent(coordinates[2])}`;\n\t\t\tconst response = await fetch(url, {headers: {'User-Agent': 'OpenSight/1.0', 'Accept-Language': 'en'}});\n\t\t\tconst data = await response.json();\n\t\t\tif(data.display_name) return {address: data.display_name, mode: 'geolocate'};\n\t\t} else { // Geocode\n\t\t\tconst url = `https://nominatim.openstreetmap.org/search?format=json&q=${encodeURIComponent(query)}`;\n\t\t\tconst response = await fetch(url, {headers: {'User-Agent': 'OpenSight/1.0'}});\n\t\t\tconst data = await response.json();\n\t\t\tif(data[0]) return {latitude: parseFloat(data[0].lat), longitude: parseFloat(data[0].lon), mode: 'geocode'};\n\t\t}\n\t\treturn {error: 'Not found'};\n\t},\n}\n\nexport const GeoWeatherTool: AiTool = {\n\tname: 'geo_weather',\n\tdescription: 'Gets weather and air quality info for a location and time',\n\targs: {\n\t\tquery: {type: 'string', description: 'Location - address or place name', required: true},\n\t\tday: {type: 'string', description: 'Date to retrieve (YYYY-MM-DD), defaults to today'},\n\t},\n\tfn: async ({query, day}) => {\n\t\tday = day || new Date().toISOString().slice(0, 10);\n\n\t\tconst geoUrl = `https://nominatim.openstreetmap.org/search?format=json&q=${encodeURIComponent(query)}`;\n\t\tconst geoResponse = await fetch(geoUrl, {headers: {'User-Agent': 'OpenSight/1.0'}});\n\t\tconst geoData = await geoResponse.json();\n\t\tif(!geoData[0]) return {error: 'Location not found'};\n\n\t\tconst lat = parseFloat(geoData[0].lat);\n\t\tconst lon = parseFloat(geoData[0].lon);\n\n\t\tconst weatherUrl = `https://api.open-meteo.com/v1/forecast?latitude=${lat}&longitude=${lon}&start_date=${day}&end_date=${day}&daily=weathercode,temperature_2m_max,temperature_2m_min,apparent_temperature_max,apparent_temperature_min,precipitation_sum,precipitation_probability_max,windspeed_10m_max,winddirection_10m_dominant,uv_index_max,sunrise,sunset&timezone=auto`;\n\t\tconst airUrl = `https://air-quality-api.open-meteo.com/v1/air-quality?latitude=${lat}&longitude=${lon}&start_date=${day}&end_date=${day}&hourly=us_aqi,european_aqi,pm10,pm2_5&timezone=auto`;\n\n\t\tconst [weatherResponse, airResponse] = await Promise.all([fetch(weatherUrl), fetch(airUrl)]);\n\t\tconst weatherData = await weatherResponse.json();\n\t\tconst airData = await airResponse.json();\n\n\t\tconst avg = arr => (arr && arr.length) ? arr.reduce((a, b) => a + b, 0) / arr.length : null;\n\n\t\treturn {\n\t\t\tlocation: geoData[0].display_name,\n\t\t\tlatitude: lat,\n\t\t\tlongitude: lon,\n\t\t\televation: weatherData.elevation,\n\t\t\tdate: day,\n\t\t\tweatherCode: weatherData.daily?.weathercode?.[0],\n\t\t\ttempMax: weatherData.daily?.temperature_2m_max?.[0],\n\t\t\ttempMin: weatherData.daily?.temperature_2m_min?.[0],\n\t\t\tfeelsLikeMax: weatherData.daily?.apparent_temperature_max?.[0],\n\t\t\tfeelsLikeMin: weatherData.daily?.apparent_temperature_min?.[0],\n\t\t\tprecipitation: weatherData.daily?.precipitation_sum?.[0],\n\t\t\tprecipitationChance: weatherData.daily?.precipitation_probability_max?.[0],\n\t\t\twindSpeedMax: weatherData.daily?.windspeed_10m_max?.[0],\n\t\t\twindDirection: weatherData.daily?.winddirection_10m_dominant?.[0],\n\t\t\tuvIndexMax: weatherData.daily?.uv_index_max?.[0],\n\t\t\tsunrise: weatherData.daily?.sunrise?.[0],\n\t\t\tsunset: weatherData.daily?.sunset?.[0],\n\t\t\tusAqi: avg(airData.hourly?.us_aqi),\n\t\t\teuropeanAqi: avg(airData.hourly?.european_aqi),\n\t\t\tpm10: avg(airData.hourly?.pm10),\n\t\t\tpm2_5: avg(airData.hourly?.pm2_5),\n\t\t};\n\t},\n}\n\nexport const WebFetchTool: AiTool = {\n\tname: 'web_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 WebFlareSolverTool = (host: string) => {\n\treturn {\n\t\tname: 'web_flaresolverr',\n\t\tdescription: 'Use a flaresolverr proxy to bypass cloudflare bot detection',\n\t\targs: {\n\t\t\turl: {type: 'string', description: 'URL to fetch', required: true},\n\t\t\tcmd: {type: 'string', description: 'Flaresolverr cmd', enum: ['request.get', 'request.post'], default: 'request.get'},\n\t\t\tmaxTimeout: {type: 'number', description: 'Fetch time limit', default: 60_000},\n\t\t\tpostData: {type: 'object', description: 'Data to send during request.post requests'},\n\t\t},\n\t\tfn: async ({url, cmd, maxTimeout, postData}) => {\n\t\t\tfunction toFormUrlEncoded(obj, prefix = '') {\n\t\t\t\tconst pairs: any = [];\n\t\t\t\tfor (const key in obj) {\n\t\t\t\t\tif (!obj.hasOwnProperty(key)) continue;\n\n\t\t\t\t\tconst value = obj[key];\n\t\t\t\t\tconst encodedKey = prefix\n\t\t\t\t\t\t? `${prefix}[${encodeURIComponent(key)}]`\n\t\t\t\t\t\t: encodeURIComponent(key);\n\n\t\t\t\t\tif (value === null || value === undefined) {\n\t\t\t\t\t\tpairs.push(`${encodedKey}=`);\n\t\t\t\t\t} else if (typeof value === 'object' && !Array.isArray(value)) {\n\t\t\t\t\t\tpairs.push(toFormUrlEncoded(value, encodedKey));\n\t\t\t\t\t} else if (Array.isArray(value)) {\n\t\t\t\t\t\tvalue.forEach(item => {\n\t\t\t\t\t\t\tpairs.push(`${encodedKey}[]=${encodeURIComponent(item)}`);\n\t\t\t\t\t\t});\n\t\t\t\t\t} else {\n\t\t\t\t\t\tpairs.push(`${encodedKey}=${encodeURIComponent(value)}`);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn pairs.join('&');\n\t\t\t}\n\n\t\t\tconst res = await fetch(host + '/v1', {\n\t\t\t\tmethod: 'POST',\n\t\t\t\theaders: {'Content-Type': 'application/json'},\n\t\t\t\tbody: JSON.stringify({cmd, url, maxTimeout, postData: postData ? toFormUrlEncoded(postData) : undefined}),\n\t\t\t});\n\n\t\t\tif(!res.ok) throw new Error(`FlareSolverr HTTP error: ${res.status} ${res.statusText}`);\n\t\t\tconst data = await res.json();\n\t\t\tif(data.status !== 'ok') throw new Error(`FlareSolverr error: ${data.message ?? data.status}`);\n\t\t\treturn data.solution.response;\n\t\t}\n\t}\n}\n\nexport const WebReadTool: AiTool = {\n\tname: 'web_read',\n\tdescription: 'Extract clean content from webpages, or convert media/documents to accessible formats',\n\targs: {\n\t\turl: {type: 'string', description: 'URL to read', required: true},\n\t\tmimeRegex: {type: 'string', description: 'Optional regex to filter MIME types (e.g., \"^image/\", \"text/\")'}\n\t},\n\tfn: async (args: {url: string; mimeRegex?: string}) => {\n\t\tconst ua = 'AiTools-Webpage/1.0';\n\t\tconst maxSize = 10 * 1024 * 1024;\n\n\t\tconst response = await fetch(args.url, {\n\t\t\theaders: {\n\t\t\t\t'User-Agent': ua,\n\t\t\t\t'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8',\n\t\t\t\t'Accept-Language': 'en-US,en;q=0.5'\n\t\t\t},\n\t\t\tredirect: 'follow'\n\t\t}).catch(err => {throw new Error(`Failed to fetch: ${err.message}`)});\n\n\t\tconst contentType = response.headers.get('content-type') || '';\n\t\tconst mimeType = contentType.split(';')[0].trim().toLowerCase();\n\n\t\tif(args.mimeRegex && !new RegExp(args.mimeRegex, 'i').test(mimeType)) {\n\t\t\treturn `❌ MIME type rejected: ${mimeType} (filter: ${args.mimeRegex})`;\n\t\t}\n\n\t\tif(mimeType.match(/^(image|audio|video)\\//)) {\n\t\t\tconst buffer = await response.arrayBuffer();\n\t\t\tif(buffer.byteLength > maxSize) {\n\t\t\t\treturn `❌ File too large: ${(buffer.byteLength / 1024 / 1024).toFixed(1)}MB (max 10MB)\\nType: ${mimeType}`;\n\t\t\t}\n\t\t\tconst base64 = Buffer.from(buffer).toString('base64');\n\t\t\treturn `## Media File\\n**Type:** ${mimeType}\\n**Size:** ${(buffer.byteLength / 1024).toFixed(1)}KB\\n**Data URL:** \\`data:${mimeType};base64,${base64.slice(0, 100)}...\\``;\n\t\t}\n\n\t\tif(mimeType.match(/^text\\/(plain|csv|xml)/) || args.url.match(/\\.(txt|csv|xml|md|yaml|yml)$/i)) {\n\t\t\tconst text = await response.text();\n\t\t\tconst truncated = text.length > 50000 ? text.slice(0, 50000) : text;\n\t\t\treturn `## Text File\\n**Type:** ${mimeType}\\n**URL:** ${args.url}\\n\\n${truncated}`;\n\t\t}\n\n\t\tif(mimeType.match(/application\\/(json|xml|csv)/)) {\n\t\t\tconst text = await response.text();\n\t\t\tconst truncated = text.length > 50000 ? text.slice(0, 50000) : text;\n\t\t\treturn `## Structured Data\\n**Type:** ${mimeType}\\n**URL:** ${args.url}\\n\\n\\`\\`\\`\\n${truncated}\\n\\`\\`\\``;\n\t\t}\n\n\t\tif(mimeType === 'application/pdf' || (mimeType.startsWith('application/') && !mimeType.includes('html'))) {\n\t\t\tconst buffer = await response.arrayBuffer();\n\t\t\tif(buffer.byteLength > maxSize) {\n\t\t\t\treturn `❌ File too large: ${(buffer.byteLength / 1024 / 1024).toFixed(1)}MB (max 10MB)\\nType: ${mimeType}`;\n\t\t\t}\n\t\t\tconst base64 = Buffer.from(buffer).toString('base64');\n\t\t\treturn `## Binary File\\n**Type:** ${mimeType}\\n**Size:** ${(buffer.byteLength / 1024).toFixed(1)}KB\\n**Data URL:** \\`data:${mimeType};base64,${base64.slice(0, 100)}...\\``;\n\t\t}\n\n\t\t// HTML\n\t\tconst html = await response.text();\n\t\tconst $ = cheerio.load(html);\n\t\t$('script, style, nav, footer, header, aside, iframe, noscript, svg').remove();\n\t\t$('[role=\"navigation\"], [role=\"banner\"], [role=\"complementary\"]').remove();\n\t\t$('[aria-hidden=\"true\"], [hidden], .visually-hidden, .sr-only, .screen-reader-text').remove();\n\t\t$('.ad, .ads, .advertisement, .cookie, .popup, .modal, .sidebar, .related, .comments, .social-share').remove();\n\t\t$('button, [class*=\"share\"], [class*=\"follow\"], [class*=\"social\"]').remove();\n\t\tconst title = $('meta[property=\"og:title\"]').attr('content') || $('title').text().trim() || '';\n\t\tconst description = $('meta[name=\"description\"]').attr('content') || $('meta[property=\"og:description\"]').attr('content') || '';\n\t\tconst author = $('meta[name=\"author\"]').attr('content') || '';\n\t\tlet content = '';\n\t\tconst selectors = ['article', 'main', '[role=\"main\"]', '.content', '.post-content', '.entry-content', '.article-content'];\n\t\tfor(const sel of selectors) {\n\t\t\tconst el = $(sel).first();\n\t\t\tif(el.length && el.text().trim().length > 200) {\n\t\t\t\tconst paragraphs: string[] = [];\n\t\t\t\tel.find('p').each((_, p) => {\n\t\t\t\t\tconst text = $(p).text().trim();\n\t\t\t\t\tif(text.length > 80) paragraphs.push(text);\n\t\t\t\t});\n\t\t\t\tif(paragraphs.length > 2) {\n\t\t\t\t\tcontent = paragraphs.join('\\n\\n');\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif(!content) {\n\t\t\tconst paragraphs: string[] = [];\n\t\t\t$('body p').each((_, p) => {\n\t\t\t\tconst text = $(p).text().trim();\n\t\t\t\tif(text.length > 80) paragraphs.push(text);\n\t\t\t});\n\t\t\tcontent = paragraphs.slice(0, 30).join('\\n\\n');\n\t\t}\n\n\t\t// Decode escaped newlines and clean\n\t\tconst parts = [`## ${title || 'Webpage'}`];\n\t\tif(description) parts.push(`_${description}_`);\n\t\tif(author) parts.push(`👤 ${author}`);\n\t\tparts.push(`🔗 ${args.url}\\n`);\n\t\tparts.push(content);\n\t\treturn decodeHtml(parts.join('\\n\\n').replaceAll(/\\n{3,}/g, '\\n\\n'));\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\": UA, \"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","import {Anthropic as anthropic} from '@anthropic-ai/sdk';\nimport {findByProp, objectMap, JSONSanitize, JSONAttemptParse, makeArray} from '@ztimson/utils';\nimport {AbortablePromise, Ai} from './ai.ts';\nimport {LLMMessage, LLMRequest} from './llm.ts';\nimport {LLMProvider} from './provider.ts';\nimport {TokenPool} from './token-pool.ts';\nimport {convertSchema} from './tools.ts';\n\nexport class Anthropic extends LLMProvider {\n\tprivate clients = new Map<string, anthropic>();\n\ttokenPool!: TokenPool;\n\n\tconstructor(public readonly ai: Ai, public readonly apiToken: string | string[], public model: string) {\n\t\tsuper();\n\t\tthis.tokenPool = new TokenPool(...makeArray(apiToken).filter(Boolean));\n\t}\n\n\tprivate getClient(token: string): anthropic {\n\t\tlet client = this.clients.get(token);\n\t\tif(!client) {\n\t\t\tclient = new anthropic({apiKey: token});\n\t\t\tthis.clients.set(token, client);\n\t\t}\n\t\treturn client;\n\t}\n\n\tprivate toWireContent(content: any): any {\n\t\tif(!Array.isArray(content)) return content;\n\t\treturn content.map(c => c.type === 'image'\n\t\t\t? {type: 'image', source: {type: 'base64', media_type: c.mime, data: c.data}}\n\t\t\t: {type: 'text', text: c.text});\n\t}\n\n\t/** Convert standard history -> Anthropic wire format */\n\tprivate toWire(history: LLMMessage[]): any[] {\n\t\tconst wire: any[] = [];\n\t\tfor(const h of history) {\n\t\t\tif(h.role === 'tool') {\n\t\t\t\twire.push(\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} else {\n\t\t\t\twire.push({role: h.role, content: this.toWireContent(h.content)});\n\t\t\t}\n\t\t}\n\t\treturn wire;\n\t}\n\n\task(message: string, options: LLMRequest = {}): AbortablePromise<string | any> {\n\t\tconst controller = new AbortController();\n\t\treturn Object.assign(new Promise<any>(async (res, rej) => {\n\t\t\tif(!options.history) options.history = [];\n\t\t\tconst history = options.history;\n\t\t\tif(message) history.push({role: 'user', content: message, timestamp: Date.now()});\n\n\t\t\tconst tools = options.tools || this.ai.options.llm?.tools || [];\n\t\t\tconst requestParams: any = {\n\t\t\t\tmodel: options.model || this.model,\n\t\t\t\tmax_tokens: options.maxTokens || this.ai.options.llm?.maxTokens || 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 || undefined,\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})),\n\t\t\t\tstream: !!options.stream,\n\t\t\t};\n\n\t\t\tif(options.schema) {\n\t\t\t\trequestParams.output_config = {format: {type: 'json_schema', schema: convertSchema(options.schema)}};\n\t\t\t}\n\n\t\t\ttry {\n\t\t\t\tlet terminal = false;\n\t\t\t\tdo {\n\t\t\t\t\trequestParams.messages = this.toWire(history.filter(h => h.role !== 'system'));\n\n\t\t\t\t\tconst callStart = Date.now();\n\t\t\t\t\tconst resp: any = await this.tokenPool.run(token => this.getClient(token).messages.create(requestParams)).catch(err => {\n\t\t\t\t\t\terr.message += `\\n\\nMessages:\\n${JSON.stringify(requestParams.messages, null, 2)}`;\n\t\t\t\t\t\tthrow err;\n\t\t\t\t\t});\n\n\t\t\t\t\tlet usage: any, content: any[] = [];\n\t\t\t\t\tif(options.stream) {\n\t\t\t\t\t\tfor await (const chunk of resp) {\n\t\t\t\t\t\t\tif(controller.signal.aborted) break;\n\t\t\t\t\t\t\tif(chunk.type === 'content_block_start') {\n\t\t\t\t\t\t\t\tif(chunk.content_block.type === 'text') content.push({type: 'text', text: ''});\n\t\t\t\t\t\t\t\telse if(chunk.content_block.type === 'tool_use') content.push({type: 'tool_use', id: chunk.content_block.id, name: chunk.content_block.name, input: ''});\n\t\t\t\t\t\t\t} else if(chunk.type === 'content_block_delta') {\n\t\t\t\t\t\t\t\tif(chunk.delta.type === 'text_delta') {\n\t\t\t\t\t\t\t\t\tcontent.at(-1).text += chunk.delta.text;\n\t\t\t\t\t\t\t\t\toptions.stream({text: chunk.delta.text});\n\t\t\t\t\t\t\t\t} else if(chunk.delta.type === 'input_json_delta') {\n\t\t\t\t\t\t\t\t\tcontent.at(-1).input += chunk.delta.partial_json;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} else if(chunk.type === 'content_block_stop') {\n\t\t\t\t\t\t\t\tconst last = content.at(-1);\n\t\t\t\t\t\t\t\tif(last?.type === 'tool_use') last.input = last.input ? JSONAttemptParse(last.input, {}) : {};\n\t\t\t\t\t\t\t} else if(chunk.type === 'message_delta') {\n\t\t\t\t\t\t\t\tif(chunk.usage) usage = chunk.usage;\n\t\t\t\t\t\t\t} else if(chunk.type === 'message_stop') {\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tusage = resp.usage;\n\t\t\t\t\t\tcontent = resp.content;\n\t\t\t\t\t}\n\t\t\t\t\tconst duration = Date.now() - callStart;\n\t\t\t\t\tconst tps = usage?.output_tokens && duration > 0 ? usage.output_tokens / (duration / 1000) : 0;\n\n\t\t\t\t\tconst toolCalls = content.filter((c: any) => c.type === 'tool_use');\n\t\t\t\t\tif(toolCalls.length && !controller.signal.aborted) {\n\t\t\t\t\t\tconst text = content.filter((c: any) => c.type === 'text').map((c: any) => c.text).join('\\n\\n').trim();\n\t\t\t\t\t\tif(text) history.push({role: 'assistant', content: text, timestamp: Date.now(), duration, tps});\n\n\t\t\t\t\t\tconst entries = toolCalls.map((tc: any) => {\n\t\t\t\t\t\t\tconst entry: any = {role: 'tool', id: tc.id, name: tc.name, args: tc.input, content: undefined, timestamp: Date.now()};\n\t\t\t\t\t\t\thistory.push(entry);\n\t\t\t\t\t\t\treturn {tc, entry};\n\t\t\t\t\t\t});\n\n\t\t\t\t\t\tawait Promise.all(entries.map(async ({tc, entry}: any) => {\n\t\t\t\t\t\t\tconst tool = tools.find(findByProp('name', tc.name));\n\t\t\t\t\t\t\tif(options.stream) options.stream({tool: tc.name});\n\t\t\t\t\t\t\tif(!tool) { entry.error = 'Tool not found'; return; }\n\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\tconst toolStream = options.stream && ((chunk: any) => {\n\t\t\t\t\t\t\t\t\tif(chunk.done) { terminal = true; return; }\n\t\t\t\t\t\t\t\t\toptions.stream!(chunk);\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\tconst result = await tool.fn(entry.args, toolStream, this.ai, tc.id);\n\t\t\t\t\t\t\t\tentry.content = typeof result === 'object' ? JSONSanitize(result) : result;\n\t\t\t\t\t\t\t} catch(err: any) {\n\t\t\t\t\t\t\t\tentry.error = err?.message || err?.toString() || 'Unknown';\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}));\n\t\t\t\t\t} else {\n\t\t\t\t\t\tterminal = true;\n\t\t\t\t\t\tconst text = content.filter((c: any) => c.type === 'text').map((c: any) => c.text).join('\\n\\n').trim();\n\t\t\t\t\t\tif(text) history.push({role: 'assistant', content: text, timestamp: Date.now(), duration, tps});\n\t\t\t\t\t}\n\t\t\t\t} while(!terminal && !controller.signal.aborted);\n\n\t\t\t\tif(options.stream) options.stream({done: true});\n\n\t\t\t\tconst turnStart = history.map(h => h.role).lastIndexOf('user');\n\t\t\t\tconst finalContent = history.slice(turnStart + 1).reduce((str, h) => h.role === 'assistant' ? str + (h.content || '') : str, '').trim();\n\t\t\t\tres(options.schema ? JSONAttemptParse(finalContent, finalContent) : finalContent);\n\t\t\t} catch(err) {\n\t\t\t\trej(err);\n\t\t\t}\n\t\t}), {abort: () => controller.abort()});\n\t}\n}\n","import {MemoryCache} from './memory-state.ts';\nimport type {Memory} from './memory.ts';\n\nexport type MemoryNode = {\n\tname: string;\n\tmissing: boolean;\n\tlinks: string[];\n\tbacklinks: string[];\n}\n\nexport function extractLinks(content: string): string[] {\n\tif (!content) return [];\n\tconst matches = content.matchAll(/\\[\\[([^\\]|]+)(?:\\|[^\\]]*)?\\]\\]/g);\n\treturn [...new Set([...matches].map(m => m[1].trim()))];\n}\n\nexport function patchGraph(mems: Memory[], nodes: MemoryNode[], changed: Memory[]): MemoryNode[] {\n\tconst nameSet = new Set(mems.map(m => m.name));\n\tconst byName = new Map(nodes.map(n => [n.name, n]));\n\n\tconst ensureNode = (name: string): MemoryNode => {\n\t\tlet n = byName.get(name);\n\t\tif (!n) {\n\t\t\tn = {name, missing: !nameSet.has(name), links: [], backlinks: []};\n\t\t\tbyName.set(name, n);\n\t\t}\n\t\treturn n;\n\t};\n\n\tfor (const m of changed) {\n\t\tconst node = ensureNode(m.name);\n\t\tnode.missing = false; // real memory, promotes any pre-existing ghost entry\n\t\tconst oldLinks = m.links ?? [];\n\t\tconst newLinks = extractLinks(m.content).filter(l => l !== m.name);\n\n\t\tfor (const target of oldLinks.filter(l => !newLinks.includes(l))) {\n\t\t\tconst t = byName.get(target);\n\t\t\tif (!t) continue;\n\t\t\tt.backlinks = t.backlinks.filter(n => n !== m.name);\n\t\t\tif (t.missing && !t.backlinks.length) byName.delete(target); // fully dereferenced ghost\n\t\t}\n\t\tfor (const target of newLinks.filter(l => !oldLinks.includes(l))) {\n\t\t\tconst t = ensureNode(target);\n\t\t\tif (!t.backlinks.includes(m.name)) t.backlinks.push(m.name);\n\t\t}\n\n\t\tm.links = newLinks;\n\t\tnode.links = newLinks;\n\t}\n\n\tfor (const m of mems) {\n\t\tconst n = byName.get(m.name);\n\t\tif (n) m.backlinks = n.backlinks;\n\t}\n\n\treturn [...byName.values()];\n}\n\nexport function rebuildGraph(memories: Memory[] | MemoryCache): MemoryNode[] {\n\tconst mems = memories instanceof MemoryCache ? memories.memories : memories;\n\tconst nameSet = new Set(mems.map(m => m.name));\n\n\tfor (const m of mems) m.links = extractLinks(m.content).filter(l => l !== m.name);\n\tfor (const m of mems) m.backlinks = [];\n\tfor (const m of mems) {\n\t\tfor (const link of m.links) {\n\t\t\tconst target = mems.find(t => t.name === link);\n\t\t\tif (target) target.backlinks.push(m.name);\n\t\t}\n\t}\n\n\tconst nodes: MemoryNode[] = mems.map(m => ({\n\t\tname: m.name,\n\t\tmissing: false,\n\t\tlinks: m.links,\n\t\tbacklinks: m.backlinks,\n\t}));\n\n\tconst ghosts = new Set<string>();\n\tfor (const node of nodes) {\n\t\tfor (const link of node.links) {\n\t\t\tif (!nameSet.has(link)) ghosts.add(link);\n\t\t}\n\t}\n\n\treturn [\n\t\t...nodes,\n\t\t...[...ghosts].map(name => ({\n\t\t\tname,\n\t\t\tmissing: true,\n\t\t\tlinks: [],\n\t\t\tbacklinks: nodes.filter(n => n.links.includes(name)).map(n => n.name),\n\t\t})),\n\t];\n}\n\nexport function renderMemoryGraph(nodes: MemoryNode[]): string {\n\tif (!nodes.length) return 'No memories yet.';\n\n\tconst groups = new Map<string, (MemoryNode & {label: string})[]>();\n\tfor (const node of nodes) {\n\t\tconst [prefix, ...rest] = node.name.split('/');\n\t\tconst group = rest.length ? prefix : 'Root';\n\t\tconst label = rest.length ? rest.join('/') : node.name;\n\t\tif (!groups.has(group)) groups.set(group, []);\n\t\tgroups.get(group)!.push({...node, label});\n\t}\n\n\tconst ghostCount = nodes.filter(n => n.missing).length;\n\tconst lines = [`Memory Graph (${nodes.length} nodes, ${ghostCount} ghost${ghostCount === 1 ? '' : 's'})`, ''];\n\n\tfor (const group of [...groups.keys()].sort()) {\n\t\tconst items = groups.get(group)!.sort((a, b) => a.label.localeCompare(b.label));\n\t\tlines.push(`${group}/`);\n\t\titems.forEach((n, i) => {\n\t\t\tconst last = i === items.length - 1;\n\t\t\tconst branch = last ? '└─' : '├─';\n\t\t\tconst pad = last ? '  ' : '│ ';\n\t\t\tconst tag = n.missing ? ' (ghost)' : '';\n\t\t\tlines.push(`  ${branch} ${n.label}${tag}`);\n\t\t\tif (n.links.length) lines.push(`  ${pad}   → ${n.links.join(', ')}`);\n\t\t\tif (n.backlinks.length) lines.push(`  ${pad}   ← ${n.backlinks.join(', ')}`);\n\t\t});\n\t\tlines.push('');\n\t}\n\n\treturn lines.join('\\n').trimEnd();\n}\n","import {Memory} from './memory/memory.ts';\n\nexport function cosineDistance(a: number[], b: number[]): number {\n\tlet dot = 0, normA = 0, normB = 0;\n\tfor(let i = 0; i < a.length; i++) {\n\t\tdot += a[i] * b[i];\n\t\tnormA += a[i] * a[i];\n\t\tnormB += b[i] * b[i];\n\t}\n\tconst denom = Math.sqrt(normA) * Math.sqrt(normB);\n\treturn denom === 0 ? 1 : 1 - dot / denom;\n}\n\nexport async function embedMemoryFields(node: Memory, llm: any): Promise<void> {\n\tconst body = stripHeader(node.content);\n\tconst [titleE] = await llm.embedding(node.name.split('/').pop() || node.name);\n\tconst [descE] = await llm.embedding(node.description || '');\n\tconst bodyChunks = body ? await llm.embedding(body) : [];\n\tif(titleE) node.titleEmbedding = titleE.embedding;\n\tif(descE) node.embedding = descE.embedding;\n\tnode.bodyEmbeddings = bodyChunks.map((c: any) => c.embedding).filter(Boolean);\n}\n\nexport function euclideanDistance(a: number[], b: number[]): number {\n\tlet sum = 0;\n\tfor(let i = 0; i < a.length; i++) {\n\t\tconst d = a[i] - b[i];\n\t\tsum += d * d;\n\t}\n\treturn Math.sqrt(sum);\n}\n\nexport function getWeekStart(date: Date = new Date()): string {\n\tconst d = new Date(Date.UTC(date.getFullYear(), date.getMonth(), date.getDate()));\n\tconst day = d.getUTCDay();\n\tconst diff = day === 0 ? -6 : 1 - day;\n\td.setUTCDate(d.getUTCDate() + diff);\n\treturn d.toISOString().slice(0, 10);\n}\n\nexport function journalDescription(journalName?: string): string {\n\tconst start = journalName?.split('/').pop() || getWeekStart();\n\tconst d = new Date(`${start}T00:00:00Z`);\n\td.setUTCDate(d.getUTCDate() + 6);\n\tconst end = d.toISOString().slice(0, 10);\n\treturn `Log from ${start} - ${end}`;\n}\n\nfunction parseFrontmatter(content: string): {fm: Map<string, string>, body: string} {\n\tconst match = content.match(/^---\\n([\\s\\S]*?)\\n---\\n?([\\s\\S]*)$/);\n\tif(!match) return {fm: new Map(), body: content};\n\tconst fm = new Map<string, string>();\n\tfor(const line of match[1].split('\\n')) {\n\t\tconst i = line.indexOf(':');\n\t\tif(i === -1) continue;\n\t\tconst key = line.slice(0, i).trim();\n\t\tconst raw = line.slice(i + 1).trim();\n\t\tlet value = raw;\n\t\ttry { value = JSON.parse(raw); } catch { }\n\t\tfm.set(key, value);\n\t}\n\treturn {fm, body: match[2]};\n}\n\nexport function writeFrontmatter(fm: Map<string, string>, body: string): string {\n\tconst lines = [...fm.entries()].map(([k, v]) =>\n\t\t`${k}: ${JSON.stringify(String(v).replace(/\\s+/g, ' ').trim())}`);\n\treturn `---\\n${lines.join('\\n')}\\n---\\n\\n${body.trimStart()}`;\n}\n\nexport function stripHeader(content: string): string {\n\treturn content.replace(/^---[\\s\\S]*?\\n---\\n?/, '').trimStart();\n}\n\nexport function updateMemory(node: Memory, body: string): string {\n\tconst {fm} = parseFrontmatter(node.content);\n\tfm.set('name', node.name);\n\tfm.set('description', (node.name.startsWith('Journal/') ? journalDescription(node.name) : node.description)\n\t\t|| 'Persistent memory document');\n\tfm.set('modified', new Date().toISOString());\n\treturn writeFrontmatter(fm, stripHeader(body));\n}\n","import {cosineDistance, euclideanDistance} from '../utils.ts';\n\nexport type DistanceMetric = \"euclidean\" | \"cosine\";\n\nexport interface KDPoint<T = unknown> {\n\tvector: number[];\n\tpayload: T;\n}\n\nexport interface KNNResult<T = unknown> {\n\tpoint: KDPoint<T>;\n\tdistance: number;\n}\n\ninterface KDNode<T> {\n\tpoint: KDPoint<T>;\n\taxis: number;\n\tleft: KDNode<T> | null;\n\tright: KDNode<T> | null;\n\tdeleted?: boolean;\n}\n\n/**\n * Keeps the k closest candidates in memory, evicts the furthest when full\n */\nclass BoundedMaxHeap<T> {\n\tprivate heap: KNNResult<T>[] = [];\n\n\tconstructor(private readonly k: number) {}\n\n\tget size(): number { return this.heap.length; }\n\n\tget worstDistance(): number {\n\t\treturn this.heap.length < this.k ? Infinity : this.heap[0].distance;\n\t}\n\n\tpush(item: KNNResult<T>): void {\n\t\tif (this.heap.length < this.k) {\n\t\t\tthis.heap.push(item);\n\t\t\tthis.bubbleUp(this.heap.length - 1);\n\t\t} else if (item.distance < this.heap[0].distance) {\n\t\t\tthis.heap[0] = item;\n\t\t\tthis.sinkDown(0);\n\t\t}\n\t}\n\n\ttoSortedArray(): KNNResult<T>[] {\n\t\treturn [...this.heap].sort((a, b) => a.distance - b.distance);\n\t}\n\n\tprivate bubbleUp(i: number): void {\n\t\twhile (i > 0) {\n\t\t\tconst parent = (i - 1) >> 1;\n\t\t\tif (this.heap[parent].distance >= this.heap[i].distance) break;\n\t\t\t[this.heap[parent], this.heap[i]] = [this.heap[i], this.heap[parent]];\n\t\t\ti = parent;\n\t\t}\n\t}\n\n\tprivate sinkDown(i: number): void {\n\t\tconst n = this.heap.length;\n\t\twhile (true) {\n\t\t\tlet largest = i;\n\t\t\tconst l = 2 * i + 1, r = 2 * i + 2;\n\t\t\tif (l < n && this.heap[l].distance > this.heap[largest].distance) largest = l;\n\t\t\tif (r < n && this.heap[r].distance > this.heap[largest].distance) largest = r;\n\t\t\tif (largest === i) break;\n\t\t\t[this.heap[largest], this.heap[i]] = [this.heap[i], this.heap[largest]];\n\t\t\ti = largest;\n\t\t}\n\t}\n}\n\n/**\n * K-D Tree for efficient nearest-neighbor search over high-dimensional vectors / embeddings.\n *\n * Supports:\n *  - Insertion of labeled points\n *  - Lazy (tombstone) removal, physically purged on rebalance()\n *  - k-nearest-neighbor (KNN) search\n *  - Radius search (all points within a given distance)\n *  - Euclidean and cosine distance metrics\n *  - Bulk construction (balanced tree) for best query performance\n */\nexport class KDTree<T = unknown> {\n\tprivate root: KDNode<T> | null = null;\n\tprivate _size = 0;\n\tprivate _tombstones = 0;\n\tprivate readonly distanceFn: (a: number[], b: number[]) => number;\n\n\treadonly dims: number;\n\n\t/**\n\t * @param dims           Dimensionality of all vectors (must be consistent).\n\t * @param metric         Distance metric to use. Default: \"euclidean\".\n\t * @param points         Optional initial set of points. Builds a balanced tree\n\t *                       in O(n log² n) — prefer this over inserting one-by-one\n\t *                       when you have a large corpus.\n\t */\n\tconstructor(\n\t\tdims: number,\n\t\tmetric: DistanceMetric = \"euclidean\",\n\t\tpoints?: KDPoint<T>[]\n\t) {\n\t\tthis.dims = dims;\n\t\tthis.distanceFn = metric === \"cosine\" ? cosineDistance : euclideanDistance;\n\n\t\tif (points && points.length > 0) {\n\t\t\tthis.validateAll(points);\n\t\t\tthis.root = this.buildBalanced([...points], 0);\n\t\t\tthis._size = points.length;\n\t\t}\n\t}\n\n\t/** Total number of live points stored in the tree (excludes tombstoned). */\n\tget size(): number { return this._size; }\n\n\t/** Fraction of physical nodes that are tombstoned (pending removal on next rebalance). */\n\tget tombstoneRatio(): number {\n\t\tconst total = this._size + this._tombstones;\n\t\treturn total ? this._tombstones / total : 0;\n\t}\n\n\t// ── Insertion ──────────────────────────────────────────────────────────────\n\n\t/**\n\t * Insert a single point. O(log n) average, O(n) worst case on skewed data.\n\t * For bulk loading prefer passing points to the constructor.\n\t */\n\tinsert(point: KDPoint<T>): void {\n\t\tthis.validate(point);\n\t\tthis.root = this.insertNode(this.root, point, 0);\n\t\tthis._size++;\n\t}\n\n\t// ── Removal ────────────────────────────────────────────────────────────────\n\n\t/**\n\t * Lazily remove all live points whose payload matches `predicate`.\n\t * O(n) traversal, but avoids a full tree rebuild. Call `rebalance()`\n\t * periodically (e.g. once tombstoneRatio crosses ~0.25) to reclaim space\n\t * and restore optimal query depth.\n\t * @returns number of points removed\n\t */\n\tremove(predicate: (payload: T) => boolean): number {\n\t\tlet removed = 0;\n\t\tconst visit = (node: KDNode<T> | null): void => {\n\t\t\tif (!node) return;\n\t\t\tif (!node.deleted && predicate(node.point.payload)) {\n\t\t\t\tnode.deleted = true;\n\t\t\t\tremoved++;\n\t\t\t}\n\t\t\tvisit(node.left);\n\t\t\tvisit(node.right);\n\t\t};\n\t\tvisit(this.root);\n\t\tthis._size -= removed;\n\t\tthis._tombstones += removed;\n\t\treturn removed;\n\t}\n\n\t// ── KNN search ─────────────────────────────────────────────────────────────\n\n\t/**\n\t * Find the k nearest live neighbors to `query`.\n\t * Returns results sorted by distance ascending.\n\t */\n\tknn(query: number[], k: number): KNNResult<T>[] {\n\t\tif (k <= 0) throw new RangeError(\"k must be a positive integer\");\n\t\tthis.validateVector(query);\n\n\t\tconst heap = new BoundedMaxHeap<T>(k);\n\t\tthis.searchKNN(this.root, query, k, heap, 0);\n\t\treturn heap.toSortedArray();\n\t}\n\n\t/**\n\t * Nearest single neighbor. Convenience wrapper around knn(query, 1).\n\t * Returns null if the tree is empty.\n\t */\n\tnearest(query: number[]): KNNResult<T> | null {\n\t\tconst results = this.knn(query, 1);\n\t\treturn results[0] ?? null;\n\t}\n\n\t// ── Radius search ──────────────────────────────────────────────────────────\n\n\t/**\n\t * Return all live points whose distance to `query` is ≤ `radius`,\n\t * sorted by distance ascending.\n\t */\n\tradiusSearch(query: number[], radius: number): KNNResult<T>[] {\n\t\tif (radius < 0) throw new RangeError(\"radius must be non-negative\");\n\t\tthis.validateVector(query);\n\n\t\tconst results: KNNResult<T>[] = [];\n\t\tthis.searchRadius(this.root, query, radius, results, 0);\n\t\tresults.sort((a, b) => a.distance - b.distance);\n\t\treturn results;\n\t}\n\n\t// ── Conversion ─────────────────────────────────────────────────────────────\n\n\t/** Collect all live points in the tree (order not guaranteed). */\n\ttoArray(): KDPoint<T>[] {\n\t\tconst out: KDPoint<T>[] = [];\n\t\tthis.collect(this.root, out);\n\t\treturn out;\n\t}\n\n\t/**\n\t * Rebuild the tree from its current live points as a balanced tree.\n\t * Physically purges tombstones and restores O(log n) query time.\n\t */\n\trebalance(): void {\n\t\tconst points = this.toArray();\n\t\tthis.root = points.length ? this.buildBalanced(points, 0) : null;\n\t\tthis._size = points.length;\n\t\tthis._tombstones = 0;\n\t}\n\n\t// ── Private: build ─────────────────────────────────────────────────────────\n\n\tprivate buildBalanced(points: KDPoint<T>[], depth: number): KDNode<T> {\n\t\tconst axis = depth % this.dims;\n\t\tpoints.sort((a, b) => a.vector[axis] - b.vector[axis]);\n\n\t\tconst mid = Math.floor(points.length / 2);\n\t\treturn {\n\t\t\tpoint: points[mid],\n\t\t\taxis,\n\t\t\tleft:  points.slice(0, mid).length\n\t\t\t\t? this.buildBalanced(points.slice(0, mid), depth + 1)\n\t\t\t\t: null,\n\t\t\tright: points.slice(mid + 1).length\n\t\t\t\t? this.buildBalanced(points.slice(mid + 1), depth + 1)\n\t\t\t\t: null,\n\t\t};\n\t}\n\n\t// ── Private: insert ────────────────────────────────────────────────────────\n\n\tprivate insertNode(\n\t\tnode: KDNode<T> | null,\n\t\tpoint: KDPoint<T>,\n\t\tdepth: number\n\t): KDNode<T> {\n\t\tif (node === null) {\n\t\t\treturn { point, axis: depth % this.dims, left: null, right: null };\n\t\t}\n\t\tconst axis = depth % this.dims;\n\t\tif (point.vector[axis] < node.point.vector[axis]) {\n\t\t\tnode.left = this.insertNode(node.left, point, depth + 1);\n\t\t} else {\n\t\t\tnode.right = this.insertNode(node.right, point, depth + 1);\n\t\t}\n\t\treturn node;\n\t}\n\n\t// ── Private: KNN traversal ─────────────────────────────────────────────────\n\n\tprivate searchKNN(\n\t\tnode: KDNode<T> | null,\n\t\tquery: number[],\n\t\tk: number,\n\t\theap: BoundedMaxHeap<T>,\n\t\tdepth: number\n\t): void {\n\t\tif (node === null) return;\n\n\t\tif (!node.deleted) {\n\t\t\tconst dist = this.distanceFn(query, node.point.vector);\n\t\t\theap.push({ point: node.point, distance: dist });\n\t\t}\n\n\t\tconst axis = node.axis;\n\t\tconst diff = query[axis] - node.point.vector[axis];\n\t\tconst [near, far] = diff <= 0\n\t\t\t? [node.left, node.right]\n\t\t\t: [node.right, node.left];\n\n\t\tthis.searchKNN(near, query, k, heap, depth + 1);\n\t\tconst shouldExplore =\n\t\t\tthis.distanceFn === cosineDistance\n\t\t\t\t? true\n\t\t\t\t: Math.abs(diff) < heap.worstDistance;\n\n\t\tif (shouldExplore) {\n\t\t\tthis.searchKNN(far, query, k, heap, depth + 1);\n\t\t}\n\t}\n\n\t// ── Private: radius traversal ──────────────────────────────────────────────\n\n\tprivate searchRadius(\n\t\tnode: KDNode<T> | null,\n\t\tquery: number[],\n\t\tradius: number,\n\t\tresults: KNNResult<T>[],\n\t\tdepth: number\n\t): void {\n\t\tif (node === null) return;\n\n\t\tif (!node.deleted) {\n\t\t\tconst dist = this.distanceFn(query, node.point.vector);\n\t\t\tif (dist <= radius) {\n\t\t\t\tresults.push({ point: node.point, distance: dist });\n\t\t\t}\n\t\t}\n\n\t\tconst axis = node.axis;\n\t\tconst diff = query[axis] - node.point.vector[axis];\n\t\tconst [near, far] = diff <= 0\n\t\t\t? [node.left, node.right]\n\t\t\t: [node.right, node.left];\n\n\t\tthis.searchRadius(near, query, radius, results, depth + 1);\n\n\t\tconst shouldExplore =\n\t\t\tthis.distanceFn === cosineDistance ? true : Math.abs(diff) <= radius;\n\n\t\tif (shouldExplore) {\n\t\t\tthis.searchRadius(far, query, radius, results, depth + 1);\n\t\t}\n\t}\n\n\t// ── Private: collect ───────────────────────────────────────────────────────\n\n\tprivate collect(node: KDNode<T> | null, out: KDPoint<T>[]): void {\n\t\tif (node === null) return;\n\t\tif (!node.deleted) out.push(node.point);\n\t\tthis.collect(node.left, out);\n\t\tthis.collect(node.right, out);\n\t}\n\n\t// ── Private: validation ────────────────────────────────────────────────────\n\n\tprivate validateVector(v: number[]): void {\n\t\tif (v.length !== this.dims) {\n\t\t\tthrow new TypeError(\n\t\t\t\t`Vector length ${v.length} does not match tree dimensionality ${this.dims}`\n\t\t\t);\n\t\t}\n\t}\n\n\tprivate validate(point: KDPoint<T>): void {\n\t\tthis.validateVector(point.vector);\n\t}\n\n\tprivate validateAll(points: KDPoint<T>[]): void {\n\t\tfor (const p of points) this.validate(p);\n\t}\n}\n","import {MemoryNode, patchGraph, rebuildGraph} from './graph.ts';\nimport {KDTree} from './kd-tree.ts';\nimport type {Memory, MemoryRef, MemoryStore} from './memory.ts';\nimport {cosineDistance, embedMemoryFields} from '../utils.ts';\n\nconst TREE_TOMBSTONE_LIMIT = 0.25;\n\nexport function memoryStore(memories: MemoryStore): {\n\tlist: Memory[];\n\tcache: MemoryCache | null;\n\tfind: (name: string) => Memory | undefined;\n\tghosts: () => string[];\n\tsearch: (vector: number[], limit: number) => MemoryRef[];\n\tforget: (name: string) => boolean;\n\trebuild: (changed?: Memory[]) => MemoryNode[];\n\tbackfillEmbeddings: (llm: any) => Promise<number>;\n} {\n\tif(memories instanceof MemoryCache) {\n\t\treturn {\n\t\t\tlist: memories.memories,\n\t\t\tcache: memories,\n\t\t\tfind: name => memories.find(name),\n\t\t\tghosts: () => memories.ghosts(),\n\t\t\tsearch: (vector, limit) => memories.search(vector, limit),\n\t\t\tforget: name => memories.remove(name),\n\t\t\trebuild: changed => memories.rebuild(changed),\n\t\t\tbackfillEmbeddings: llm => memories.backfillEmbeddings(llm),\n\t\t};\n\t}\n\n\treturn {\n\t\tlist: memories,\n\t\tcache: null,\n\t\tfind: name => memories.find(m => m.name === name),\n\t\tghosts: () => rebuildGraph(memories).filter(n => n.missing).map(n => n.name),\n\t\tsearch: (vector, limit) => memories\n\t\t\t.filter(m => m.embedding?.length)\n\t\t\t.map(m => ({\n\t\t\t\tname: m.name,\n\t\t\t\tdescription: m.description,\n\t\t\t\tdistance: cosineDistance(vector, m.embedding),\n\t\t\t}))\n\t\t\t.sort((a, b) => a.distance - b.distance)\n\t\t\t.slice(0, limit),\n\t\tforget: name => {\n\t\t\tconst idx = memories.findIndex(m => m.name === name);\n\t\t\tif(idx === -1) return false;\n\n\t\t\tmemories.splice(idx, 1);\n\t\t\treturn true;\n\t\t},\n\t\trebuild: changed => rebuildGraph(memories),\n\t\tbackfillEmbeddings: async llm => {\n\t\t\tconst missing = memories.filter(m => !m.embedding?.length);\n\t\t\tif(!missing.length) return 0;\n\n\t\t\tawait Promise.all(missing.map(async node => {\n\t\t\t\tawait embedMemoryFields(node, llm);\n\t\t\t}));\n\n\t\t\treturn missing.length;\n\t\t},\n\t};\n}\n\nexport class MemoryCache {\n\tprivate tree!: KDTree<MemoryRef>;\n\tprivate indexed = new Map<string, number[]>();\n\tpublic memories: Memory[];\n\tpublic nodes: MemoryNode[] = [];\n\n\tget length() {\n\t\treturn this.memories.length;\n\t}\n\n\tconstructor(memories: Memory[]) {\n\t\tthis.memories = memories;\n\t\tthis.tree = new KDTree<MemoryRef>(0);\n\t\tthis.rebuild();\n\t}\n\n\tfind(name: string): Memory | undefined {\n\t\treturn this.memories.find(m => m.name === name);\n\t}\n\n\tprivate syncTree(): void {\n\t\tconst current = new Set(this.memories.map(m => m.name));\n\n\t\tfor(const [name, emb] of [...this.indexed]) {\n\t\t\tconst mem = this.memories.find(m => m.name === name);\n\n\t\t\tif(!mem || !current.has(name) || mem.embedding !== emb) {\n\t\t\t\tthis.tree.remove(p => p.name === name);\n\t\t\t\tthis.indexed.delete(name);\n\t\t\t}\n\t\t}\n\n\t\tfor(const mem of this.memories) {\n\t\t\tif(!mem.embedding?.length || this.indexed.has(mem.name)) continue;\n\n\t\t\tif(this.tree.dims === 0) {\n\t\t\t\tthis.tree = new KDTree<MemoryRef>(mem.embedding.length, 'cosine');\n\t\t\t}\n\n\t\t\tif(mem.embedding.length !== this.tree.dims) continue;\n\n\t\t\tthis.tree.insert({\n\t\t\t\tvector: mem.embedding,\n\t\t\t\tpayload: {\n\t\t\t\t\tname: mem.name,\n\t\t\t\t\tdescription: mem.description,\n\t\t\t\t},\n\t\t\t});\n\n\t\t\tthis.indexed.set(mem.name, mem.embedding);\n\t\t}\n\n\t\tif(this.tree.tombstoneRatio > TREE_TOMBSTONE_LIMIT) {\n\t\t\tthis.tree.rebalance();\n\t\t}\n\t}\n\n\tsearch(query: number[], limit: number): MemoryRef[] {\n\t\tif(!this.tree || this.tree.dims === 0) return [];\n\n\t\treturn this.tree.knn(query, limit).map(r => ({\n\t\t\t...r.point.payload,\n\t\t\tdistance: r.distance,\n\t\t}));\n\t}\n\n\tadd(memory: Memory): void {\n\t\tthis.memories.push(memory);\n\t\tthis.rebuild([memory]);\n\t}\n\n\tupdate(memory: Memory): void {\n\t\tconst existing = this.find(memory.name);\n\n\t\tif(existing) Object.assign(existing, memory);\n\t\telse this.memories.push(memory);\n\n\t\tthis.rebuild([existing ?? memory]);\n\t}\n\n\tremove(name: string): boolean {\n\t\tconst idx = this.memories.findIndex(m => m.name === name);\n\t\tif(idx === -1) return false;\n\n\t\tthis.memories.splice(idx, 1);\n\t\tthis.rebuild();\n\t\treturn true;\n\t}\n\n\tghosts(): string[] {\n\t\treturn this.nodes.filter(n => n.missing).map(n => n.name);\n\t}\n\n\trebuild(changed?: Memory[]): MemoryNode[] {\n\t\tthis.nodes = changed?.length && this.nodes.length\n\t\t\t? patchGraph(this.memories, this.nodes, changed)\n\t\t\t: rebuildGraph(this.memories);\n\n\t\tthis.syncTree();\n\t\treturn this.nodes;\n\t}\n\n\tcommit(changed?: Memory[]): MemoryNode[] {\n\t\treturn this.rebuild(changed);\n\t}\n\n\tasync backfillEmbeddings(llm: any): Promise<number> {\n\t\tconst missing = this.memories.filter(m => !m.embedding?.length);\n\t\tif(!missing.length) return 0;\n\n\t\tawait Promise.all(missing.map(node => embedMemoryFields(node, llm)));\n\t\tthis.commit(missing);\n\n\t\treturn missing.length;\n\t}\n}\n","import {AiTool} from '../tools.ts';\nimport type {LLMMessage, LLMRequest} from '../llm.ts';\nimport {MemoryCache, memoryStore} from './memory-state.ts';\nimport {cosineDistance, embedMemoryFields, stripHeader, updateMemory} from '../utils.ts';\n\nconst FACT_SIMILARITY_THRESHOLD = 0.62;\nconst DUPLICATE_THRESHOLD = 0.68;\nconst PROTECTED_MEMORIES = ['People/User'];\nconst COLLECTION_WORDS = ['project', 'projects', 'people', 'person', 'managed', 'guides', 'guide', 'research', 'class', 'classes'];\n\nexport type Memory = {\n\tname: string;\n\tdescription: string;\n\tcontent: string;\n\tembedding: number[];\n\ttitleEmbedding?: number[];\n\tbodyEmbeddings?: number[][];\n\tlinks: string[];\n\tbacklinks: string[];\n}\n\nexport type MemoryRef = {\n\tname: string;\n\tdescription: string;\n\tdistance?: number;\n}\n\nexport type MemoryOptions = {\n\tmemory: Memory[] | MemoryCache;\n\tinject?: boolean;\n\ttool?: boolean;\n\tupdate?: boolean;\n\tmaxTokens?: number;\n}\n\nexport type MemoryStore = Memory[] | MemoryCache;\n\n/** Create an empty memory shell. */\nfunction emptyNode(name: string, description = ''): Memory {\n\treturn {name, description, content: `# ${name.split('/').pop()}\\n`, embedding: [], links: [], backlinks: []};\n}\n\nfunction renderNode(node: Memory): string {\n\treturn `### ${node.name}\nDescription: ${node.description}\nLinks: ${[...node.links, ...node.backlinks].join(', ') || 'none'}\n\n\\`\\`\\`markdown\n${node.content}\n\\`\\`\\``;\n}\n\nfunction factSimilarity(a: Memory, b: Memory): number {\n\treturn !a.bodyEmbeddings?.length || !b.bodyEmbeddings?.length ? 0 : Math.max(...a.bodyEmbeddings.flatMap(av => b.bodyEmbeddings!.map(bv => 1 - cosineDistance(av, bv))));\n}\n\nfunction words(text: string): string[] {\n\treturn [...new Set(text.toLowerCase().replace(/[[\\]()/_-]/g, ' ').replace(/[^a-z0-9\\s]/g, '').split(/\\s+/).filter(w => w && !COLLECTION_WORDS.includes(w)))];\n}\n\nfunction jaccard(a: string[], b: string[]): number {\n\tconst bs = new Set(b), hit = a.filter(x => bs.has(x)).length, total = new Set([...a, ...b]).size;\n\treturn total ? hit / total : 0;\n}\n\nfunction duplicateScore(a: Memory, b: Memory): number {\n\tconst name = Math.max(\n\t\tjaccard(words(a.name), words(b.name)),\n\t\tjaccard(words(a.name.split('/').pop() || a.name), words(b.name.split('/').pop() || b.name)),\n\t);\n\tconst desc = jaccard(words(a.description), words(b.description));\n\tconst body = factSimilarity(a, b);\n\tconst emb = a.embedding?.length && b.embedding?.length && a.embedding.length === b.embedding.length ? 1 - cosineDistance(a.embedding, b.embedding) : 0;\n\treturn Math.max(body, name * 0.9 + desc * 0.06 + emb * 0.04, emb * 0.55 + name * 0.35 + desc * 0.1);\n}\n\nfunction homeScore(node: Memory): number {\n\treturn (PROTECTED_MEMORIES.includes(node.name) ? 1e9 : 0)\n\t\t+ (node.name.includes('/') ? 4 : 0)\n\t\t+ (node.description && node.description !== 'Persistent memory document' ? 1 : 0)\n\t\t+ Math.min(stripHeader(node.content).length / 1000, 5);\n}\n\nfunction pickMerge(a: Memory, b: Memory, touched: Set<string>): [drop: Memory, home: Memory] {\n\tconst as = homeScore(a), bs = homeScore(b);\n\tif(touched.has(a.name) && !touched.has(b.name)) return as > bs + 2 ? [b, a] : [a, b];\n\tif(touched.has(b.name) && !touched.has(a.name)) return bs > as + 2 ? [a, b] : [b, a];\n\treturn as <= bs ? [a, b] : [b, a];\n}\n\n/** Build memory tools and memory index text. */\nexport function memoryTools(llm: any, memories: MemoryStore): {tools: AiTool[]; list: string} {\n\tconst store = memoryStore(memories);\n\tconst names = new Map<string, string>();\n\n\tfor(const node of store.list)\n\t\tif(!names.has(node.name)) names.set(node.name, `${node.name} - ${node.description}`);\n\n\tfor(const name of store.ghosts())\n\t\tif(!names.has(name)) names.set(name, `${name} - ghost node`);\n\n\treturn {\n\t\tlist: [...names.values()].join('\\n'),\n\t\ttools: [\n\t\t\t{\n\t\t\t\tname: 'memory_search',\n\t\t\t\tdescription: 'Semantically search memories for most relevant',\n\t\t\t\targs: {\n\t\t\t\t\tquery: {type: 'string', description: 'Search query', required: true},\n\t\t\t\t\tlimit: {type: 'number', description: 'Maximum results, default 5', default: 5},\n\t\t\t\t},\n\t\t\t\tfn: async ({query, limit = 5}) => {\n\t\t\t\t\tif(!query?.trim()) return 'Search query is required.';\n\t\t\t\t\tconst [chunk] = await llm.embedding(query, {maxTokens: 8000, overlapTokens: 0});\n\t\t\t\t\tif(!chunk?.embedding) return 'Failed to create embedding from query';\n\t\t\t\t\tconst results = store.search(chunk.embedding, limit).map(ref => store.find(ref.name)).filter((node): node is Memory => !!node);\n\t\t\t\t\treturn results.length ? results.map(renderNode).join('\\n\\n---\\n\\n') : 'No relevant memories found.';\n\t\t\t\t},\n\t\t\t},\n\t\t\t{\n\t\t\t\tname: 'memory_read',\n\t\t\t\tdescription: 'Read an entire memory document by name',\n\t\t\t\targs: {name: {type: 'string', description: 'Exact document name', required: true}},\n\t\t\t\tfn: async ({name}) => {\n\t\t\t\t\tconst node = store.find(name);\n\t\t\t\t\treturn node ? renderNode(node) : store.ghosts().includes(name) ? `\"${name}\" is a ghost node with no document of its own.` : `Not found: \"${name}\".`;\n\t\t\t\t},\n\t\t\t},\n\t\t\t{\n\t\t\t\tname: 'memory_delete',\n\t\t\t\tdescription: 'Delete a duplicate or merged memory',\n\t\t\t\targs: {name: {type: 'string', description: 'Exact document name', required: true}},\n\t\t\t\tfn: async ({name}) => {\n\t\t\t\t\tstore.forget(name);\n\t\t\t\t\treturn `Removed: ${name}`;\n\t\t\t\t},\n\t\t\t},\n\t\t\t{\n\t\t\t\tname: 'memory_write',\n\t\t\t\tdescription: 'Create or replace a memory document.',\n\t\t\t\targs: {\n\t\t\t\t\tname: {type: 'string', description: 'Document name following the entity naming convention.', required: true},\n\t\t\t\t\tdescription: {type: 'string', description: 'One factual sentence describing the entire document subject', required: true},\n\t\t\t\t\tcontent: {type: 'string', description: 'Complete Markdown document body, including the # title', required: true},\n\t\t\t\t},\n\t\t\t\tfn: async (args: any) => {\n\t\t\t\t\tconst name = String(args.name || '').trim();\n\t\t\t\t\tif(!name) return 'A document name is required.';\n\t\t\t\t\tconst description = String(args.description || '').trim();\n\t\t\t\t\tif(!description) return 'A document description is required.';\n\t\t\t\t\tconst content = String(args.content || '').trim();\n\t\t\t\t\tif(!content) return 'Document content is required.';\n\n\t\t\t\t\tlet node = store.find(name);\n\t\t\t\t\tif(!node) {\n\t\t\t\t\t\tnode = emptyNode(name, description);\n\t\t\t\t\t\tif(store.cache) store.cache.add(node);\n\t\t\t\t\t\telse store.list.push(node);\n\t\t\t\t\t}\n\n\t\t\t\t\tnode.description = name === 'People/User' ? 'All information about the current user' : description.replace(/\\s+/g, ' ').trim();\n\t\t\t\t\tnode.content = updateMemory(node, content);\n\t\t\t\t\tawait embedMemoryFields(node, llm);\n\t\t\t\t\tstore.cache?.commit([node]);\n\t\t\t\t\treturn `Updated ${name}`;\n\t\t\t\t},\n\t\t\t},\n\t\t],\n\t};\n}\n\nexport class MemoryManager {\n\tprivate memorized = new WeakMap<LLMMessage[], LLMMessage>();\n\n\tconstructor(private llm: any) {}\n\n\tstatic normalize(memory?: Memory[] | MemoryCache | MemoryOptions): MemoryOptions | null {\n\t\tif(!memory) return null;\n\t\tif(Array.isArray(memory) || memory instanceof MemoryCache) return {memory, inject: true, tool: false, update: false};\n\t\tif(typeof memory === 'object' && 'memory' in memory) return {inject: true, tool: false, update: false, ...memory};\n\t\treturn null;\n\t}\n\n\tprivate memorySystem(list: string): string {\n\t\treturn `You maintain notes written in markdown used for memories from recent conversations using your tools.\nOnly preserve durable information worth remembering established by the USER.\nDo not store assistant guesses, speculation, suggestions, commentary, temporary state, or details that are not worth remembering.\n\n## Rules\n- ALWAYS READ a target memory before changing it, \\`memory_write\\` does a full replace, it DOES NOT append!\n- Memories should contain the final state, not deltas\n- New conversational context is authoritative when it contracts existing information; reconcile it\n- Only remove information when stale, contradicted or duplicated; always preserve existing information, formatting and keep related information together\n- Only merge memories when two or more nodes are clearly about the same thing; only split a memory when it is clearly about two distinct subjects\n- Use [[WikiLinks]] liberally to record aliases and relationships between entities, even ones without pages yet (ghost nodes)\n- Use headings, subheadings, lists, tables and other markdown formatting to make documents clean\n- Maintain a \\`## Todo List\\` of checkboxes AS THE FIRST SUBHEADING when an entity has tasks\n\t- Only create todo items for USER tasks, not AI work\n\t- Only store each in one place, no duplicates\n\t- Use  \\`People/User\\` for personal tasks or as a fallback\n\n## Naming\n- Every fact should be grouped with the owning entity\n- Always follow the naming convention \\`Collection/(Pro)Noun\\`\n- Facts about the user belong under People/User\n- Reuse existing memories when they are clearly the same entity including aliases and ghost references.\n- Only create deeper paths when there is a real parent/child entity relationship: \\`School/Class/Chapter\\`\n\nValid Examples:\n- People/User\n- People/John Smith\n- Projects/Momentum\n- Projects/Momentum/Marketing\n- Research/Object Recognition\n- Guides/HAM Radio SOP\n\n## Workflow\n\n1. Create groups of durable information and todos based on the owning entity & naming rules above\n2. For each group:\n  1. Read the existing memory(s)\n  2. Merge the information & todos based on the rules above\n  3. Write the entire patched document\n\nAvailable memories:\n\n${list || 'No memory documents exist yet.'}`;\n\t}\n\n\tprivate touchedNames(history: LLMMessage[]): string[] {\n\t\treturn [...new Set(history\n\t\t\t.filter((h: any) => h.role === 'tool' && h.name === 'memory_write' && !h.error)\n\t\t\t.map((h: any) => String(h.args?.name || h.content?.match(/^Updated (.+)$/)?.[1] || '').trim())\n\t\t\t.filter(Boolean))];\n\t}\n\n\tprivate async backfillEmbeddings(store: ReturnType<typeof memoryStore>): Promise<void> {\n\t\tconst missing = store.list.filter(m => !m.embedding?.length || !m.titleEmbedding?.length || !m.bodyEmbeddings?.length);\n\t\tawait Promise.all(missing.map(m => embedMemoryFields(m, this.llm)));\n\t\tstore.cache?.commit(missing);\n\t}\n\n\tprivate closestDuplicate(node: Memory, store: ReturnType<typeof memoryStore>): Memory | null {\n\t\treturn store.list\n\t\t\t.filter(m => m.name !== node.name && !m.name.startsWith('Journal/') && !node.name.startsWith('Journal/'))\n\t\t\t.map(m => ({node: m, score: duplicateScore(node, m)}))\n\t\t\t.filter(x => x.score >= DUPLICATE_THRESHOLD || factSimilarity(node, x.node) >= FACT_SIMILARITY_THRESHOLD)\n\t\t\t.sort((a, b) => b.score - a.score)[0]?.node || null;\n\t}\n\n\tprivate async rehomeDeleted(drop: Memory, home: Memory, memories: MemoryStore, options: LLMRequest): Promise<void> {\n\t\tconst store = memoryStore(memories);\n\t\tconst backup = structuredClone(drop);\n\t\tstore.forget(drop.name);\n\n\t\ttry {\n\t\t\tconst memory = memoryTools(this.llm, memories);\n\t\t\tawait this.llm.ask(`A duplicate memory document was removed automatically.\n\nDeleted document:\n${renderNode(backup)}\n\nClosest surviving home:\n${renderNode(home)}\n\nReinsert every durable unique fact, useful relationship, alias, and user todo from the deleted document into the best remaining memory document.\nUsually this should be \"${home.name}\", but use another existing memory if it is a better home.\nRead before writing. Write full replacement documents only.\nDo NOT recreate \"${backup.name}\" unless the deletion was wrong and it is clearly a distinct persistent entity.`, {\n\t\t\t\tmodel: options.memoryModel || options.model,\n\t\t\t\ttemperature: 0.2,\n\t\t\t\tmaxTokens: options.maxTokens,\n\t\t\t\ttools: memory.tools,\n\t\t\t\thistory: [],\n\t\t\t\tsystem: this.memorySystem(memory.list),\n\t\t\t});\n\t\t} catch(err) {\n\t\t\tif(!store.find(backup.name)) store.cache ? store.cache.add(backup) : store.list.push(backup);\n\t\t\tthrow err;\n\t\t} finally {\n\t\t\tstore.cache?.commit(store.list);\n\t\t}\n\t}\n\n\tprivate async reconcileSimilar(history: LLMMessage[], memories: MemoryStore, options: LLMRequest): Promise<void> {\n\t\tconst store = memoryStore(memories);\n\t\tconst touched = new Set(this.touchedNames(history));\n\t\tconst targets = store.list.filter(m => touched.has(m.name) || [...touched].some(t => duplicateScore(m, store.find(t) || m) >= DUPLICATE_THRESHOLD));\n\t\tconst deleted = new Set<string>();\n\t\tif(!targets.length) return;\n\t\tawait this.backfillEmbeddings(store);\n\n\t\tfor(const node of targets) {\n\t\t\tif(!store.find(node.name) || deleted.has(node.name) || PROTECTED_MEMORIES.includes(node.name)) continue;\n\t\t\tconst closest = this.closestDuplicate(node, store);\n\t\t\tif(!closest) continue;\n\t\t\tconst [drop, home] = pickMerge(node, closest, touched);\n\t\t\tif(deleted.has(drop.name) || PROTECTED_MEMORIES.includes(drop.name)) continue;\n\t\t\tdeleted.add(drop.name);\n\t\t\tawait this.rehomeDeleted(drop, home, memories, options);\n\t\t\tawait this.backfillEmbeddings(store);\n\t\t}\n\t}\n\n\tasync recollect(query: string, memory: MemoryStore, limit = 15): Promise<Memory[]> {\n\t\tconst store = memoryStore(memory);\n\t\tif(!store.list.length || !query?.trim()) return [];\n\t\tconst [chunk] = await this.llm.embedding(query, {maxTokens: 8000, overlapTokens: 0});\n\t\treturn !chunk?.embedding ? [] : store.search(chunk.embedding, limit).map(ref => store.find(ref.name)).filter((m: Memory | undefined): m is Memory => !!m);\n\t}\n\n\tget tools(): {read: (memory: MemoryStore) => AiTool[]} {\n\t\treturn {read: (memory: MemoryStore) => memoryTools(this.llm, memory).tools};\n\t}\n\n\tasync memorize(history: LLMMessage[], memories: Memory[] | MemoryCache, options: LLMRequest = {},): Promise<Memory[]> {\n\t\tconst store = memoryStore(memories);\n\t\tconst previous = this.memorized.get(history);\n\t\tlet start = 0;\n\n\t\tif(previous) {\n\t\t\tconst index = history.indexOf(previous);\n\t\t\tif(index >= 0) start = index + 1;\n\t\t}\n\n\t\tconst turns = history.slice(start).filter((h: any) => h.role === 'user' || h.role === 'assistant');\n\t\tconst conversation = turns.map((h: any) => `[${h.role}]: ${h.content}`).join('\\n\\n').trim();\n\t\tif(!conversation) return store.list;\n\n\t\tconst memory = memoryTools(this.llm, memories);\n\t\tconst memoryHistory: LLMMessage[] = [];\n\n\t\tawait this.llm.ask(conversation, {\n\t\t\tmodel: options.memoryModel || options.model,\n\t\t\ttemperature: 0.2,\n\t\t\tmaxTokens: options.maxTokens,\n\t\t\ttools: memory.tools,\n\t\t\thistory: memoryHistory,\n\t\t\tsystem: this.memorySystem(memory.list),\n\t\t});\n\n\t\tawait this.reconcileSimilar(memoryHistory, memories, options);\n\n\t\tconst lastTurn = turns.at(-1);\n\t\tif(lastTurn) this.memorized.set(history, lastTurn);\n\t\treturn store.list;\n\t}\n}\n","import {OpenAI as openAI} from 'openai';\nimport {findByProp, objectMap, JSONSanitize, JSONAttemptParse, clean, makeArray} from '@ztimson/utils';\nimport {AbortablePromise, Ai} from './ai.ts';\nimport {LLMMessage, LLMRequest} from './llm.ts';\nimport {LLMProvider} from './provider.ts';\nimport {TokenPool} from './token-pool.ts';\nimport {convertSchema} from './tools.ts';\n\nexport class OpenAi extends LLMProvider {\n\ttokenPool!: TokenPool;\n\tprivate clients = new Map<string, openAI>();\n\n\tconstructor(public readonly ai: Ai, public readonly host: string | null, public readonly token: string | string[], public model: string) {\n\t\tsuper();\n\t\tconst tokens = makeArray(token).filter(Boolean);\n\t\tthis.tokenPool = new TokenPool(...(tokens.length ? tokens : [host ? 'ignored' : '']));\n\t}\n\n\tprivate getClient(token: string): openAI {\n\t\tlet client = this.clients.get(token);\n\t\tif(!client) {\n\t\t\tclient = new openAI(clean({baseURL: this.host, apiKey: token || undefined}));\n\t\t\tthis.clients.set(token, client);\n\t\t}\n\t\treturn client;\n\t}\n\n\tprivate toWireContent(content: any): any {\n\t\tif(!Array.isArray(content)) return content;\n\t\treturn content.map(c => c.type === 'image'\n\t\t\t? {type: 'image_url', image_url: {url: `data:${c.mime};base64,${c.data}`}}\n\t\t\t: {type: 'text', text: c.text});\n\t}\n\n\t/** Convert standard history -> OpenAI wire format */\n\tprivate toWire(history: LLMMessage[], system?: string): any[] {\n\t\tconst wire: any[] = [];\n\t\tif(system) wire.push({role: 'system', content: system});\n\n\t\tfor(let i = 0; i < history.length; i++) {\n\t\t\tconst h = history[i];\n\n\t\t\tif(h.role !== 'tool') {\n\t\t\t\twire.push({role: h.role, content: this.toWireContent(h.content)});\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tconst calls: any[] = [];\n\t\t\tconst results: any[] = [];\n\n\t\t\twhile(i < history.length && history[i].role === 'tool') {\n\t\t\t\tconst tool: any = history[i];\n\n\t\t\t\tcalls.push({\n\t\t\t\t\tid: tool.id,\n\t\t\t\t\ttype: 'function',\n\t\t\t\t\tfunction: {\n\t\t\t\t\t\tname: tool.name,\n\t\t\t\t\t\targuments: JSON.stringify(tool.args || {})\n\t\t\t\t\t}\n\t\t\t\t});\n\n\t\t\t\tresults.push({\n\t\t\t\t\trole: 'tool',\n\t\t\t\t\ttool_call_id: tool.id,\n\t\t\t\t\tcontent: tool.error || tool.content || ''\n\t\t\t\t});\n\n\t\t\t\ti++;\n\t\t\t}\n\n\t\t\twire.push({\n\t\t\t\trole: 'assistant',\n\t\t\t\tcontent: null,\n\t\t\t\ttool_calls: calls\n\t\t\t});\n\n\t\t\twire.push(...results);\n\t\t\ti--;\n\t\t}\n\n\t\treturn wire;\n\t}\n\n\task(message: string, options: LLMRequest = {}): AbortablePromise<string | any> {\n\t\tconst controller = new AbortController();\n\t\treturn Object.assign(new Promise<any>(async (res, rej) => {\n\t\t\tif(!options.history) options.history = [];\n\t\t\tconst history = options.history;\n\t\t\tif(message) history.push({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\tstream: !!options.stream,\n\t\t\t\tmax_completion_tokens: options.maxTokens ?? this.ai.options.llm?.maxTokens,\n\t\t\t\ttemperature: options.temperature ?? this.ai.options.llm?.temperature,\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\n\t\t\t\t\t\t\t\t? objectMap(t.args, (key, value) => ({...value, required: undefined}))\n\t\t\t\t\t\t\t\t: {},\n\t\t\t\t\t\t\trequired: t.args\n\t\t\t\t\t\t\t\t? Object.entries(t.args).filter(t => t[1].required).map(t => t[0])\n\t\t\t\t\t\t\t\t: []\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\tif(options.schema) {\n\t\t\t\tconst schema = convertSchema(options.schema);\n\t\t\t\trequestParams.response_format = {\n\t\t\t\t\ttype: 'json_schema',\n\t\t\t\t\tjson_schema: {name: 'response', strict: true, schema}\n\t\t\t\t};\n\t\t\t}\n\t\t\tif(options.stream) requestParams.stream_options = {include_usage: true};\n\n\t\t\ttry {\n\t\t\t\tlet terminal = false;\n\t\t\t\tlet iteration = 0;\n\n\t\t\t\tdo {\n\t\t\t\t\titeration++;\n\t\t\t\t\trequestParams.messages = this.toWire(history.filter(h => h.role !== 'system'), options.system);\n\n\t\t\t\t\tconst callStart = Date.now();\n\t\t\t\t\tconst resp: any = await this.tokenPool.run(token =>\n\t\t\t\t\t\tthis.getClient(token).chat.completions.create(requestParams)\n\t\t\t\t\t).catch(err => {\n\t\t\t\t\t\terr.message += `\\n\\nMessages:\\n${JSON.stringify(requestParams.messages, null, 2)}`;\n\t\t\t\t\t\tthrow err;\n\t\t\t\t\t});\n\n\t\t\t\t\tlet usage: any;\n\t\t\t\t\tlet finishReason: string | undefined;\n\t\t\t\t\tlet msg: any = {content: '', tool_calls: []};\n\t\t\t\t\tlet streamedChars = 0;\n\n\t\t\t\t\tif(options.stream) {\n\t\t\t\t\t\tlet streamCompleted = false;\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tfor await (const chunk of resp) {\n\t\t\t\t\t\t\t\tif(controller.signal.aborted) break;\n\t\t\t\t\t\t\t\tif(chunk.usage) usage = chunk.usage;\n\n\t\t\t\t\t\t\t\tconst choice = chunk.choices?.[0];\n\t\t\t\t\t\t\t\tif(choice?.finish_reason) finishReason = choice.finish_reason;\n\n\t\t\t\t\t\t\t\tif(choice?.delta?.content) {\n\t\t\t\t\t\t\t\t\tmsg.content += choice.delta.content;\n\t\t\t\t\t\t\t\t\tstreamedChars += choice.delta.content.length;\n\t\t\t\t\t\t\t\t\toptions.stream({text: choice.delta.content});\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\tif(choice?.delta?.tool_calls) {\n\t\t\t\t\t\t\t\t\tfor(const deltaTC of choice.delta.tool_calls) {\n\t\t\t\t\t\t\t\t\t\tconst index = deltaTC.index ?? msg.tool_calls.length;\n\t\t\t\t\t\t\t\t\t\tlet existing = msg.tool_calls.find((tc: any) => tc.index === index);\n\n\t\t\t\t\t\t\t\t\t\tif(!existing) {\n\t\t\t\t\t\t\t\t\t\t\texisting = {index, id: '', function: {name: '', arguments: ''}};\n\t\t\t\t\t\t\t\t\t\t\tmsg.tool_calls.push(existing);\n\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\tif(deltaTC.id) existing.id = deltaTC.id;\n\t\t\t\t\t\t\t\t\t\tif(deltaTC.function?.name) existing.function.name = deltaTC.function.name;\n\t\t\t\t\t\t\t\t\t\tif(deltaTC.function?.arguments) existing.function.arguments += deltaTC.function.arguments;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tstreamCompleted = true;\n\t\t\t\t\t\t} catch(err) {\n\t\t\t\t\t\t\tif(!controller.signal.aborted) throw err;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif(streamCompleted && !finishReason) finishReason = msg.tool_calls.length ? 'tool_calls' : 'stop';\n\t\t\t\t\t} else {\n\t\t\t\t\t\tusage = resp.usage;\n\t\t\t\t\t\tfinishReason = resp.choices[0].finish_reason;\n\t\t\t\t\t\tmsg = resp.choices[0].message;\n\t\t\t\t\t}\n\n\t\t\t\t\tconst duration = Date.now() - callStart;\n\t\t\t\t\tconst tps = usage?.completion_tokens && duration > 0 ? usage.completion_tokens / (duration / 1000) : 0;\n\n\t\t\t\t\tif(finishReason === 'length' && !controller.signal.aborted) {\n\t\t\t\t\t\tif(msg.content?.trim()) history.push({role: 'assistant', content: msg.content.trim(), timestamp: Date.now(), duration, tps});\n\t\t\t\t\t\tthrow new Error(`[OpenAI] Response hit token limit before completing`);\n\t\t\t\t\t}\n\n\t\t\t\t\tif(!finishReason && !controller.signal.aborted) {\n\t\t\t\t\t\tthrow new Error('[OpenAI] Completion ended without a usable response');\n\t\t\t\t\t}\n\n\t\t\t\t\tconst toolCalls = msg.tool_calls || [];\n\n\t\t\t\t\tif(toolCalls.length && !controller.signal.aborted) {\n\t\t\t\t\t\tif(msg.content?.trim()) history.push({role: 'assistant', content: msg.content.trim(), timestamp: Date.now(), duration, tps});\n\n\t\t\t\t\t\tconst entries = toolCalls.map((tc: any) => {\n\t\t\t\t\t\t\tconst entry: any = {\n\t\t\t\t\t\t\t\trole: 'tool',\n\t\t\t\t\t\t\t\tid: tc.id,\n\t\t\t\t\t\t\t\tname: tc.function.name,\n\t\t\t\t\t\t\t\targs: JSONAttemptParse(tc.function.arguments, {}),\n\t\t\t\t\t\t\t\tcontent: undefined,\n\t\t\t\t\t\t\t\ttimestamp: Date.now()\n\t\t\t\t\t\t\t};\n\n\t\t\t\t\t\t\thistory.push(entry);\n\t\t\t\t\t\t\treturn {tc, entry};\n\t\t\t\t\t\t});\n\n\t\t\t\t\t\tawait Promise.all(entries.map(async ({tc, entry}: any) => {\n\t\t\t\t\t\t\tconst tool = tools.find(findByProp('name', tc.function.name));\n\t\t\t\t\t\t\tif(options.stream) options.stream({tool: tc.function.name});\n\t\t\t\t\t\t\tif(!tool) return entry.error = 'Tool not found';\n\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\tconst toolStream = options.stream && ((chunk: any) => {\n\t\t\t\t\t\t\t\t\tif(chunk.done) return;\n\t\t\t\t\t\t\t\t\toptions.stream!(chunk);\n\t\t\t\t\t\t\t\t});\n\n\t\t\t\t\t\t\t\tconst result = await tool.fn(entry.args, toolStream, this.ai, tc.id);\n\t\t\t\t\t\t\t\tentry.content = typeof result === 'object' ? JSONSanitize(result) : result;\n\t\t\t\t\t\t\t} catch(err: any) {\n\t\t\t\t\t\t\t\tentry.error = err?.message || err?.toString() || 'Unknown';\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}));\n\t\t\t\t\t} else {\n\t\t\t\t\t\tterminal = true;\n\t\t\t\t\t\tconst text = (msg.content || '').trim();\n\t\t\t\t\t\tif(text) history.push({role: 'assistant', content: text, timestamp: Date.now(), duration, tps});\n\t\t\t\t\t}\n\t\t\t\t} while(!terminal && !controller.signal.aborted);\n\n\t\t\t\tif(options.stream) options.stream({done: true});\n\t\t\t\tconst turnStart = history.map(h => h.role).lastIndexOf('user');\n\t\t\t\tconst finalContent = history.slice(turnStart + 1).reduce((str, h) => h.role === 'assistant' ? str + (h.content || '') : str, '').trim();\n\t\t\t\tres(options.schema ? JSONAttemptParse(finalContent, finalContent) : finalContent);\n\t\t\t} catch(err) {\n\t\t\t\trej(err);\n\t\t\t}\n\t\t}), {abort: () => controller.abort()});\n\t}\n}\n","import {clean, makeUnique, snakeCase} from '@ztimson/utils';\nimport {AbortablePromise, Ai} from './ai.ts';\nimport {Anthropic} from './antrhopic.ts';\nimport {MemoryCache} from './memory/memory-state.ts';\nimport {Memory, MemoryManager, MemoryOptions} from './memory/memory.ts';\nimport {OpenAi} from './open-ai.ts';\nimport {LLMProvider} from './provider.ts';\nimport {AiTool, AiToolArg} from './tools.ts';\nimport {fileURLToPath} from 'url';\nimport {spawn} from 'node:child_process';\nimport {mkdtempSync} from 'node:fs';\nimport fs from 'node:fs/promises';\nimport {tmpdir} from 'node:os';\nimport {dirname, join, basename, extname} from 'path';\nimport { PDFParse } from 'pdf-parse';\nimport {stripHeader} from './utils.ts';\n\nconst MAX_AGENT_DEPTH = 5;\nconst PDF_OCR_PAGE_THRESHOLD = 12; // above this many pages, OCR scanned pages instead of feeding images to the model\n\nexport type AnthropicConfig = {proto: 'anthropic', token: string | string[]};\nexport type OpenAiConfig = {proto: 'openai', host?: string, token: string | string[]};\n\nexport type AgentRef = {\n\tname: string;\n\tdescription?: string;\n\tdelegate?: boolean;\n\tfn: () => Agent | null | Promise<Agent | null>;\n}\n\nexport type Agent = {\n\tname: string;\n\tdescription?: string;\n\tmodel?: string | null;\n\ttemperature?: number;\n\tsystem: string;\n\tdelegate?: boolean;\n\tskills?: Skill[] | null;\n\ttools?: AiTool[] | null;\n\tmcp?: McpServer[] | null;\n\tagents?: AgentRef[] | null;\n}\n\nexport type LLMFile = {\n\t/** Path to file on disk */\n\tpath?: string;\n\t/** File content: raw text, base64-encoded binary, or a Buffer */\n\tcontent?: string | Buffer;\n\t/** Original filename, used to infer type from extension */\n\tname?: string;\n\t/** Mime type override, inferred from extension if omitted */\n\tmime?: string;\n\t/** @internal set once extraction has run, skips re-processing next turn */\n\textracted?: boolean;\n};\n\nexport type LLMMessage = {\n\t/** Message originator */\n\trole: 'assistant' | 'system' | 'user';\n\t/** Message content */\n\tcontent: string | any;\n\t/** Files attached to request */\n\tfiles?: LLMFile[];\n\t/** Timestamp */\n\ttimestamp?: number;\n\t/** Response duration in ms */\n\tduration?: number;\n\t/** Tokens per second */\n\ttps?: 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\t/** Response duration in ms */\n\tduration?: number;\n\t/** Tokens per second */\n\ttps?: number;\n}\n\nexport type LLMRequest = {\n\t/** Return a parsed JSON object that matches the schema */\n\tschema?: AiToolArg;\n\t/** System prompt */\n\tsystem?: string;\n\t/** Message history */\n\thistory?: LLMMessage[];\n\t/** Max tokens for request */\n\tmaxTokens?: 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?: {max: number; min: number};\n\t/** User's memory documents - RAG injected automatically each turn */\n\tmemory?: Memory[] | MemoryCache | MemoryOptions;\n\t/** Model to use for memory operations */\n\tmemoryModel?: string;\n\t/** Skill documents the AI can browse and read on demand */\n\tskills?: Skill[];\n\t/** MCP servers to connect and expose as tools */\n\tmcp?: McpServer[];\n\t/** Subagents exposed as delegatable/wrapped tools, resolved lazily via their `fn` */\n\tagents?: AgentRef[];\n\t/** Attach files to request */\n\tfiles?: LLMFile[];\n\t/** @internal recursion guard for nested agent delegation */\n\t_agentDepth?: number;\n}\n\nexport type McpServer = {\n\t/** MCP server name for humans */\n\tname: string;\n\t/** Host URL */\n\thost: string;\n\t/** Server access token */\n\ttoken?: string;\n}\n\nexport type Skill = {\n\t/** Name of skill for humans */\n\tname: string;\n\t/** Description LLM will use to decide to learn a skill */\n\tdescription: string;\n\t/** Skill instructions */\n\tcontent: string;\n}\n\nclass LLM {\n\tprivate static AUDIO_EXT = ['wav','mp3','m4a','flac','ogg','aac','wma'];\n\tprivate static IMAGE_EXT = ['png','jpg','jpeg','bmp','gif','tiff','webp'];\n\tprivate static TEXT_EXT = ['txt','md','csv','json','xml','html','js','ts','py','yaml','yml','log'];\n\tprivate static PDF_EXT = ['pdf'];\n\n\tprivate memoryManager!: MemoryManager;\n\n\tdefaultModel!: string;\n\tmodels: {[model: string]: LLMProvider} = {};\n\n\tconstructor(public readonly ai: Ai) {\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 == 'openai') this.models[model] = new OpenAi(this.ai, config.host || null, config.token, model);\n\t\t});\n\t\tthis.memoryManager = new MemoryManager(this);\n\t}\n\n\tprivate async loadBuffer(file: LLMFile, asText: boolean): Promise<Buffer> {\n\t\tif(file.path) return fs.readFile(file.path);\n\t\tif(Buffer.isBuffer(file.content)) return file.content;\n\t\tif(typeof file.content === 'string') return Buffer.from(file.content, asText ? 'utf-8' : 'base64');\n\t\tthrow new Error('No path or content provided');\n\t}\n\n\tprivate async writeTemp(name: string, buffer: Buffer): Promise<string> {\n\t\tconst path = join(mkdtempSync(join(tmpdir(), 'ai-file-')), name);\n\t\tawait fs.writeFile(path, buffer);\n\t\treturn path;\n\t}\n\n\t/**\n\t * Extract text from a PDF. Pages with no text layer (scanned/image-only) are handled as either:\n\t * - Rendered to images and returned alongside the text so the (vision-capable) model can read them directly\n\t * - OCR'd via Tesseract when the doc is too large to reasonably pass as images\n\t */\n\tprivate async resolvePdf(buffer: Buffer): Promise<{text: string, images: {mime: string, data: string}[]}> {\n\t\tconst parser = new PDFParse({data: buffer});\n\t\ttry {\n\t\t\tconst {text, pages} = await parser.getText();\n\t\t\tconst scanned = (pages || []).filter(p => !p.text?.trim());\n\t\t\tif(!scanned.length) return {text: text.trim() || '[Empty PDF]', images: []};\n\t\t\tconst total = pages.length;\n\t\t\tconst pageNums = scanned.map(p => p.num);\n\t\t\tconst {pages: shots} = await parser.getScreenshot({partial: pageNums});\n\t\t\tif(total <= PDF_OCR_PAGE_THRESHOLD) {\n\t\t\t\treturn {\n\t\t\t\t\ttext: text.trim(),\n\t\t\t\t\timages: shots.map(s => ({mime: 'image/png', data: Buffer.from(s.data).toString('base64')}))\n\t\t\t\t};\n\t\t\t}\n\t\t\tconst ocrText = await Promise.all(shots.map(async (s, i) => {\n\t\t\t\tconst path = await this.writeTemp(`page-${pageNums[i]}.png`, Buffer.from(s.data));\n\t\t\t\ttry {\n\t\t\t\t\treturn await this.ai.vision.ocr(path) || '';\n\t\t\t\t} finally {\n\t\t\t\t\tfs.rm(dirname(path), {recursive: true, force: true}).catch(() => {});\n\t\t\t\t}\n\t\t\t}));\n\t\t\treturn {text: [text.trim(), ...ocrText].filter(Boolean).join('\\n\\n'), images: []};\n\t\t} finally {\n\t\t\tawait parser.destroy();\n\t\t}\n\t}\n\n\tprivate async resolveFile(file: LLMFile): Promise<{text?: string, images?: {mime: string, data: string}[]}> {\n\t\tconst name = file.name || (file.path ? basename(file.path) : 'file');\n\n\t\t// Already resolved on a previous turn, reuse cached text\n\t\tif(file.extracted) return {text: `<file name=\"${name}\">\\n${file.content}\\n</file>`};\n\n\t\tconst ext = extname(name).slice(1).toLowerCase();\n\t\tconst mime = file.mime || '';\n\t\tconst isAudio = mime.startsWith('audio/') || LLM.AUDIO_EXT.includes(ext);\n\t\tconst isImage = mime.startsWith('image/') || LLM.IMAGE_EXT.includes(ext);\n\t\tconst isPdf = mime === 'application/pdf' || LLM.PDF_EXT.includes(ext);\n\t\tconst isText = mime.startsWith('text/') || LLM.TEXT_EXT.includes(ext);\n\n\t\tlet tmpDir: string | null = null;\n\t\ttry {\n\t\t\tif(isImage) {\n\t\t\t\tconst data = (await this.loadBuffer(file, false)).toString('base64');\n\t\t\t\treturn {images: [{mime: mime || `image/${ext === 'jpg' ? 'jpeg' : ext}`, data}]};\n\t\t\t}\n\n\t\t\tif(isPdf) {\n\t\t\t\tconst {text, images} = await this.resolvePdf(await this.loadBuffer(file, false));\n\t\t\t\t// Only cache/skip re-processing when we didn't need to hand off images (OCR'd or fully text-based)\n\t\t\t\tif(!images.length) {\n\t\t\t\t\tfile.content = text;\n\t\t\t\t\tfile.extracted = true;\n\t\t\t\t\tdelete file.path;\n\t\t\t\t}\n\t\t\t\treturn {text: `<file name=\"${name}\">\\n${text || '[Scanned PDF - see attached page images]'}\\n</file>`, images};\n\t\t\t}\n\n\t\t\tlet text: string;\n\t\t\tif(isAudio) {\n\t\t\t\tlet path = file.path;\n\t\t\t\tif(!path) {\n\t\t\t\t\tconst buffer = await this.loadBuffer(file, false);\n\t\t\t\t\tpath = await this.writeTemp(name, buffer);\n\t\t\t\t\ttmpDir = dirname(path);\n\t\t\t\t}\n\t\t\t\ttext = await this.ai.audio.asr(path) || '';\n\t\t\t} else if(isText) {\n\t\t\t\ttext = (await this.loadBuffer(file, true)).toString('utf-8');\n\t\t\t} else {\n\t\t\t\ttext = typeof file.content === 'string' ? file.content : `[Binary file, unable to extract: ${name}]`;\n\t\t\t}\n\t\t\tfile.content = text;\n\t\t\tfile.extracted = true;\n\t\t\tdelete file.path;\n\n\t\t\treturn {text: `<file name=\"${name}\">\\n${text}\\n</file>`};\n\t\t} catch(err: any) {\n\t\t\treturn {text: `<file name=\"${name}\">Failed to process: ${err.message}</file>`};\n\t\t} finally {\n\t\t\tif(tmpDir) fs.rm(tmpDir, {recursive: true, force: true}).catch(() => {});\n\t\t}\n\t}\n\n\tprivate async resolveFiles(files: LLMFile[]): Promise<{text: string, images: {mime: string, data: string}[]}> {\n\t\tconst resolved = await Promise.all(files.map(f => this.resolveFile(f)));\n\t\treturn {\n\t\t\ttext: resolved.filter(r => r.text).map(r => r.text).join('\\n\\n'),\n\t\t\timages: resolved.flatMap(r => r.images || [])\n\t\t};\n\t}\n\n\tprivate setupAgent(stubs: AgentRef[] = [], history: LLMMessage[], aborts: ((keep?: boolean) => void)[], depth = 0, delegateState: {resp: string | null}): AiTool[] {\n\t\treturn stubs.map(stub => {\n\t\t\tconst toolName = `${stub.delegate ? '' : 'sub'}agent_${snakeCase(stub.name)}`;\n\t\t\treturn {\n\t\t\t\tname: toolName,\n\t\t\t\tdescription: `${stub.delegate ? 'Delegate to ' : ''}Subagent: ${stub.description || stub.name}`,\n\t\t\t\targs: clean<any>({\n\t\t\t\t\tcontext: !stub.delegate ? {type: 'string', description: 'Summary of related messages, samples, files, etc...', required: true} : undefined,\n\t\t\t\t\tinstructions: {type: 'string', description: 'Detailed instructions for subagent to complete', required: true},\n\t\t\t\t}),\n\t\t\t\tfn: async (args: any, stream: any, ai: any, id?: string) => {\n\t\t\t\t\tif(depth >= MAX_AGENT_DEPTH) return 'Max agent delegation depth exceeded';\n\n\t\t\t\t\tconst a = await stub.fn();\n\t\t\t\t\tif(!a) return `Agent \"${stub.name}\" could not be resolved`;\n\n\t\t\t\t\tconst q = a.delegate ? '' : `${args.instructions}${args.context ? `\\n\\n<context>${args.context}</context>` : ''}`;\n\n\t\t\t\t\tconst request = this.ask(q, {\n\t\t\t\t\t\tsystem: `You are a specialized subagent being called from an orchestrator\n${a.delegate ? 'Your output streams directly to the user for the remainder of this turn. You are mid conversation' : 'You are wrapped in a tool call that will be analysis by an LLM'}\nDispense with greetings and focus on your instructions using available tools and returning only the final result unless specifically instructed to converse\n\n${a.system}`,\n\t\t\t\t\t\tmodel: a.model || undefined,\n\t\t\t\t\t\ttemperature: a.temperature,\n\t\t\t\t\t\tstream: a.delegate ? stream : undefined,\n\t\t\t\t\t\thistory: a.delegate ? history : [],\n\t\t\t\t\t\tmcp: a.mcp || undefined,\n\t\t\t\t\t\tskills: a.skills || undefined,\n\t\t\t\t\t\ttools: a.tools || undefined,\n\t\t\t\t\t\tagents: a.agents || [],\n\t\t\t\t\t\t_agentDepth: depth + 1,\n\t\t\t\t\t} as any);\n\t\t\t\t\taborts.push(request.abort);\n\t\t\t\t\tconst resp = await request;\n\n\t\t\t\t\tif(a.delegate) {\n\t\t\t\t\t\tdelegateState.resp = resp;\n\t\t\t\t\t\treturn '';\n\t\t\t\t\t}\n\t\t\t\t\treturn resp;\n\t\t\t\t}\n\t\t\t};\n\t\t});\n\t}\n\n\tprivate async setupMcp(servers: McpServer[] = []): Promise<{prompt: string, tools: AiTool[]}> {\n\t\tif(!servers?.length) return {prompt: '', tools: []};\n\t\tconst allTools: AiTool[] = [];\n\t\tawait Promise.all(servers.map(async server => {\n\t\t\tconst res = await fetch(`${server.host}/tools`, {headers: server.token ? {Authorization: `Bearer ${server.token}`} : {}});\n\t\t\tconst mcp: any = await res.json();\n\t\t\tif(!mcp?.tools) return;\n\t\t\tfor(const t of mcp.tools) {\n\t\t\t\tconst args: Record<string, any> = {};\n\t\t\t\tif(t.inputSchema?.properties) {\n\t\t\t\t\tfor(const [key, val] of Object.entries<any>(t.inputSchema.properties)) {\n\t\t\t\t\t\targs[key] = {type: val.type || 'string', description: val.description || '', required: t.inputSchema.required?.includes(key)};\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tallTools.push({\n\t\t\t\t\tname: `${server.name}_${t.name}`,\n\t\t\t\t\tdescription: t.description || '',\n\t\t\t\t\targs,\n\t\t\t\t\tfn: async (a: any) => {\n\t\t\t\t\t\tconst r = await fetch(`${server.host}/tools/call`, {\n\t\t\t\t\t\t\tmethod: 'POST',\n\t\t\t\t\t\t\theaders: {'Content-Type': 'application/json', ...(server.token ? {Authorization: `Bearer ${server.token}`} : {})},\n\t\t\t\t\t\t\tbody: JSON.stringify({name: t.name, arguments: a})\n\t\t\t\t\t\t});\n\t\t\t\t\t\tconst data: any = await r.json();\n\t\t\t\t\t\treturn data?.content?.[0]?.text ?? JSON.stringify(data);\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\t\t}));\n\n\t\tconst list = allTools.map(t => `- ${t.name}: ${t.description}`).join('\\n');\n\t\treturn {\n\t\t\tprompt: `## MCP\\nYou have access to the following MCP tools:\\n${list}`,\n\t\t\ttools: allTools\n\t\t};\n\t}\n\n\tprivate setupSkills(skills: Skill[] = []): {prompt: string, tools: AiTool[]} {\n\t\tif(!skills?.length) return {prompt: '', tools: []};\n\t\tconst list = skills.map(s => `- ${s.name}: ${s.description}`).join('\\n');\n\t\treturn {\n\t\t\tprompt: `## Skills\\nYou have access to the following skill documents, whenever there is overlap between a question and a skill file, use \\`skill_read\\` to get instructions and background knowledge:\\n${list}`,\n\t\t\ttools: [{\n\t\t\t\tname: 'skill_read',\n\t\t\t\tdescription: 'Read the full content of a skill/knowledge document',\n\t\t\t\targs: {\n\t\t\t\t\tname: {type: 'string', description: 'Exact skill name', required: true}\n\t\t\t\t},\n\t\t\t\tfn: (args: any) => {\n\t\t\t\t\tconst skill = skills.find(s => s.name === args.name);\n\t\t\t\t\tif(!skill) return `Skill not found. Available:\\n${list}`;\n\t\t\t\t\treturn `# ${skill.name}\\n${skill.content}`;\n\t\t\t\t}\n\t\t\t}]\n\t\t}\n\t}\n\n\tprivate wrapToolTiming(tools: AiTool[], timings: Map<string, {duration: number, tps: number}>): AiTool[] {\n\t\treturn tools.map(t => ({\n\t\t\t...t,\n\t\t\tfn: async (args: any, stream: any, ai: any, id?: string) => {\n\t\t\t\tconst start = Date.now();\n\t\t\t\tconst result = await t.fn(args, stream, ai, id);\n\t\t\t\tconst duration = Date.now() - start;\n\t\t\t\tconst tps = duration > 0 ? this.estimateTokens(result) / (duration / 1000) : 0;\n\t\t\t\tif(id) timings.set(id, {duration, tps});\n\t\t\t\treturn result;\n\t\t\t}\n\t\t}));\n\t}\n\n\task(message: string, options: LLMRequest = {}): AbortablePromise<string> {\n\t\toptions = <any>{\n\t\t\tsystem: '',\n\t\t\t...this.ai.options.llm,\n\t\t\tmodels: undefined,\n\t\t\thistory: [],\n\t\t\t...options,\n\t\t}\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 request: AbortablePromise<string> | null = null;\n\t\tlet aborted = false;\n\t\tlet keepOnAbort = true;\n\t\tconst nestedAborts: ((keep?: boolean) => void)[] = [];\n\t\tconst abort = (keep = true) => {\n\t\t\taborted = true;\n\t\t\tkeepOnAbort = keep;\n\t\t\trequest?.abort?.(keep);\n\t\t\tnestedAborts.forEach(a => a(keep));\n\t\t};\n\n\t\tlet promise: any;\n\t\tconst requestStart = Date.now();\n\n\t\tpromise = (async () => {\n\t\t\tlet tools: AiTool[] = options.tools || this.ai.options.llm?.tools || [];\n\t\t\tconst prompts: string[] = [];\n\t\t\tlet history = options.history || [];\n\t\t\tconst historyStart = history.length;\n\t\t\tconst files = options.files || [];\n\t\t\tif(message || files.length) history.push({role: 'user', content: message || '', timestamp: Date.now()});\n\n\t\t\t// Accumulate streamed text so it can be committed to history if aborted mid-generation\n\t\t\tlet partialText = '';\n\t\t\tconst onStream = options.stream;\n\t\t\tconst stream = (chunk: {text?: string, tool?: string, done?: true}) => {\n\t\t\t\tif(chunk.text) partialText += chunk.text;\n\t\t\t\treturn onStream?.(chunk);\n\t\t\t};\n\n\t\t\t/** Commit (keep) or discard this turn's progress on abort, then throw */\n\t\t\tconst abortNow = (): never => {\n\t\t\t\tif(keepOnAbort) { if(partialText) history.push({role: 'assistant', content: partialText, timestamp: Date.now()}); }\n\t\t\t\telse history.splice(historyStart, history.length - historyStart);\n\t\t\t\tthrow Object.assign(new Error('Aborted'), {name: 'AbortError'});\n\t\t\t};\n\n\t\t\t// MCP\n\t\t\tconst mcp = options.mcp || this.ai.options?.llm?.mcp;\n\t\t\tif(mcp?.length) {\n\t\t\t\tconst m = await this.setupMcp(mcp);\n\t\t\t\tprompts.unshift(m.prompt);\n\t\t\t\ttools.push(...m.tools);\n\t\t\t}\n\n\t\t\t// Skills\n\t\t\tconst skills = options.skills || this.ai.options?.llm?.skills;\n\t\t\tif(skills?.length) {\n\t\t\t\tconst s = this.setupSkills(skills);\n\t\t\t\tprompts.unshift(s.prompt);\n\t\t\t\ttools.push(...s.tools);\n\t\t\t}\n\n\t\t\t// Agents\n\t\t\tconst agents = options.agents || this.ai.options?.llm?.agents;\n\t\t\tconst delegateState: {resp: string | null} = {resp: null};\n\t\t\tif(agents?.length) tools.push(...this.setupAgent(agents, history, nestedAborts, options._agentDepth || 0, delegateState));\n\n\t\t\t// Memory\n\t\t\tconst mem = MemoryManager.normalize(options.memory);\n\t\t\tif(mem) {\n\t\t\t\tconst mems = mem.memory instanceof MemoryCache ? mem.memory.memories : mem.memory;\n\t\t\t\tif(mems.length) {\n\t\t\t\t\tif(mem.inject) {\n\t\t\t\t\t\tconst pool = 15;\n\t\t\t\t\t\tconst budget = mem.maxTokens ?? 2000;\n\t\t\t\t\t\tconst relevant = await this.memoryManager.recollect(message, mem.memory, pool);\n\n\t\t\t\t\t\tlet used = 0;\n\t\t\t\t\t\tconst preloaded: typeof relevant = [];\n\t\t\t\t\t\tconst listed: typeof relevant = [];\n\t\t\t\t\t\tfor(const r of relevant) {\n\t\t\t\t\t\t\tconst t = this.estimateTokens(r.content);\n\t\t\t\t\t\t\tif(used + t <= budget || preloaded.length === 0) {\n\t\t\t\t\t\t\t\tpreloaded.push(r);\n\t\t\t\t\t\t\t\tused += t;\n\t\t\t\t\t\t\t} else listed.push(r);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tprompts.unshift(`## Memory\nYou have a background memory process which has prefetched relevant information${mem.update ? ' and will create new memories from this conversation' : ''} for you\nAssume it is perfect and never mention this process to anyone ever\nAlways use your memories to craft a personalized response, they contain links / [[wiki links]] which you use navigate between them\n${mem.tool ? `You can access memory files via the \\`memory_search\\` and \\`memory_recall\\` tools\nWhen you need information about the user, \\`memory_recall\\` \\`People/User\\` before asking (fetch if not included bellow)\nWhen you need information not provided, attempt 1-3 \\`memory_search\\` calls with distinct queries before asking` : ''}\n\n${preloaded.length ? `### Prefetched Memories (Most relevant first):\n\n${preloaded.map(r => `Memory: ${r.name}\nDescription: ${r.description}\nLinked: ${makeUnique([...r.links, ...r.backlinks]).join(', ')}\n\\`\\`\\`\n${stripHeader(r.content)}\n\\`\\`\\``).join('\\n\\n')}` : ''}\n${mem.tool && listed.length ? '\\n' + listed.map(r => `Memory: ${r.name}\nDescription: ${r.description}\nLinked: ${makeUnique([...r.links, ...r.backlinks]).join(', ')}\n<!-- Truncated -->`).join('\\n\\n') : ''}`.trim())\n\t\t\t\t\t}\n\t\t\t\t\tif(mem.tool) tools.push(...this.memoryManager.tools.read(mem.memory));\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif(aborted) abortNow();\n\n\t\t\tconst lastMsg = history[history.length - 1];\n\t\t\tif(files.length && lastMsg?.role === 'user') lastMsg.files = files;\n\t\t\tconst restores: {msg: LLMMessage, content: any}[] = [];\n\t\t\tfor(const msg of history) {\n\t\t\t\tif(msg.role !== 'user' || !msg.files?.length) continue;\n\t\t\t\tconst {text, images} = await this.resolveFiles(msg.files);\n\t\t\t\tif(!text && !images.length) continue;\n\t\t\t\trestores.push({msg, content: msg.content});\n\t\t\t\tconst merged = text ? [msg.content, text].filter(Boolean).join('\\n\\n') : msg.content;\n\t\t\t\tmsg.content = images.length\n\t\t\t\t\t? [...images.map(i => ({type: 'image', mime: i.mime, data: i.data})), {type: 'text', text: merged}]\n\t\t\t\t\t: merged;\n\t\t\t}\n\n\t\t\tconst toolTimings = new Map<string, {duration: number, tps: number}>();\n\t\t\ttools = this.wrapToolTiming(tools, toolTimings);\n\n\t\t\tif(aborted) abortNow();\n\n\t\t\tprompts.unshift(options.system || this.ai.options.llm?.system || '');\n\t\t\trequest = this.models[m].ask('', {...options, tools, stream, system: prompts.filter(Boolean).join('\\n\\n')});\n\t\t\tlet resp: string;\n\t\t\ttry {\n\t\t\t\tresp = await request;\n\t\t\t} catch(err: any) {\n\t\t\t\tif(aborted) return abortNow();\n\t\t\t\tthrow err;\n\t\t\t}\n\n\t\t\t// Strip the file injection shim\n\t\t\trestores.forEach(({msg, content}) => msg.content = content);\n\n\t\t\t// Capture meta (duration / tps)\n\t\t\tfor(const h of history) {\n\t\t\t\tif(h.role === 'tool' && toolTimings.has(h.id)) Object.assign(h, toolTimings.get(h.id));\n\t\t\t}\n\n\t\t\tif(typeof resp === 'string' && !resp.trim() && delegateState.resp !== null) resp = delegateState.resp;\n\n\t\t\tif(mem?.tool) history.splice(0, history.length, ...history.filter(h => h.role !== 'tool' || h.name !== 'memory_recall'));\n\t\t\tif(options.compress && this.estimateTokens(history) >= options.compress.max) {\n\t\t\t\tif(mem?.update) await this.memoryManager.memorize(history, mem.memory, {model: options.memoryModel || this.defaultModel, ...options});\n\t\t\t\tconst compressed = await this.compressHistory(history, options.compress.max, options.compress.min, options);\n\t\t\t\tif(options.history) options.history.splice(0, options.history.length, ...compressed);\n\t\t\t}\n\n\t\t\tconst requestDuration = Date.now() - requestStart;\n\t\t\tconst totalTokens = history\n\t\t\t\t.filter((h: any) => h.role === 'assistant' && h.duration && h.tps)\n\t\t\t\t.reduce((sum: number, h: any) => sum + h.tps * (h.duration / 1000), 0);\n\t\t\tconst requestTps = requestDuration > 0 ? totalTokens / (requestDuration / 1000) : 0;\n\t\t\tObject.assign(promise, {duration: requestDuration, tps: requestTps});\n\n\t\t\treturn resp;\n\t\t})();\n\n\t\treturn Object.assign(promise, {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<LLMMessage[]> {\n\t\tif(this.estimateTokens(history) < max) return history;\n\t\tlet keep = 0, tokens = 0;\n\t\tfor(let m of history.toReversed()) {\n\t\t\ttokens += this.estimateTokens(m.content);\n\t\t\tif(tokens < min) keep++;\n\t\t\telse break;\n\t\t}\n\t\tif(history.length <= keep) return history;\n\t\tconst 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\n\t\tconst summary: any = await this.summarize(process.map(m => `[${m.role}]: ${m.content}`).join('\\n\\n'), 500, options);\n\t\tconst d = Date.now();\n\t\tconst h = [{role: <any>'tool', name: 'summary', id: `summary_` + d, args: {}, content: `Conversation Summary: ${summary?.summary}`, timestamp: d}, ...recent];\n\t\tif(system) h.splice(0, 0, system);\n\t\treturn h;\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.toString().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 {maxTokens?: number, overlapTokens?: number} opts Options for embedding such as chunk sizes\n\t * @returns {Promise<Awaited<{index: number, embedding: number[], text: string, tokens: number}>[]>} Chunked embeddings\n\t */\n\tembedding(target: object | string, opts: {maxTokens?: number, overlapTokens?: number} = {}): AbortablePromise<{index: number, embedding: number[], text: string, tokens: number}[]> {\n\t\tlet {maxTokens = 500, overlapTokens = 50} = opts;\n\t\tlet aborted = false;\n\t\tconst abort = () => { aborted = true; };\n\n\t\tconst embed = (text: string): Promise<number[]> => {\n\t\t\treturn new Promise((resolve, reject) => {\n\t\t\t\tif(aborted) return reject(new Error('Aborted'));\n\t\t\t\tconst args: string[] = [\n\t\t\t\t\tjoin(dirname(fileURLToPath(import.meta.url)), 'embedder.js'),\n\t\t\t\t\t<string>this.ai.options.path,\n\t\t\t\t\tthis.ai.options?.embedder || 'bge-small-en-v1.5'\n\t\t\t\t];\n\t\t\t\tconst proc = spawn('node', args, {stdio: ['pipe', 'pipe', 'ignore']});\n\t\t\t\tproc.stdin.write(text);\n\t\t\t\tproc.stdin.end();\n\t\t\t\tlet output = '';\n\t\t\t\tproc.stdout.on('data', (data: Buffer) => output += data.toString());\n\t\t\t\tproc.on('close', (code: number) => {\n\t\t\t\t\tif(aborted) return reject(new Error('Aborted'));\n\t\t\t\t\tif(code === 0) {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tconst result = JSON.parse(output);\n\t\t\t\t\t\t\tresolve(result.embedding);\n\t\t\t\t\t\t} catch(err) {\n\t\t\t\t\t\t\treject(err);\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\treject(new Error(`Embedder process exited with code ${code}`));\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t\tproc.on('error', reject);\n\t\t\t});\n\t\t};\n\n\t\tconst p = (async () => {\n\t\t\tconst chunks = this.chunk(target, maxTokens, overlapTokens), results: any[] = [];\n\t\t\tfor(let i = 0; i < chunks.length; i++) {\n\t\t\t\tif(aborted) break;\n\t\t\t\tconst text = chunks[i];\n\t\t\t\tconst embedding = await embed(text);\n\t\t\t\tresults.push({index: i, embedding, text, tokens: this.estimateTokens(text)});\n\t\t\t}\n\t\t\treturn results;\n\t\t})();\n\t\treturn <any>Object.assign(p, {abort});\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, ...searchTerms) {\n\t\tif (searchTerms.length < 2) throw new Error('Requires at least 2 strings to compare');\n\t\tconst levenshtein = (a, b) => {\n\t\t\tconst m = a.length, n = b.length;\n\t\t\tif (!m) return n;\n\t\t\tif (!n) return m;\n\t\t\tconst dp = Array.from({length: m + 1}, (_, i) => [i, ...Array(n).fill(0)]);\n\t\t\tfor (let j = 0; j <= n; j++) dp[0][j] = j;\n\t\t\tfor (let i = 1; i <= m; i++) {\n\t\t\t\tfor (let j = 1; j <= n; j++) {\n\t\t\t\t\tdp[i][j] = a[i - 1] === b[j - 1]\n\t\t\t\t\t\t? dp[i - 1][j - 1]\n\t\t\t\t\t\t: 1 + Math.min(dp[i - 1][j - 1], dp[i - 1][j], dp[i][j - 1]);\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn dp[m][n];\n\t\t};\n\t\tconst similarity = (a, b) => {\n\t\t\ta = a.toLowerCase(); b = b.toLowerCase();\n\t\t\treturn 1 - levenshtein(a, b) / Math.max(a.length, b.length, 1);\n\t\t};\n\t\tconst similarities = searchTerms.map(t => similarity(target, t));\n\t\treturn {\n\t\t\tavg: similarities.reduce((acc, s) => acc + s, 0) / similarities.length,\n\t\t\tmax: Math.max(...similarities),\n\t\t\tsimilarities\n\t\t};\n\t}\n\n\t/**\n\t * Digest full conversation history into memory documents.\n\t * Call on session end to persist the conversation.\n\t */\n\tasync memorize(history: LLMMessage[], memories: Memory[] | MemoryCache, options: LLMRequest = {}): Promise<Memory[]> {\n\t\treturn this.memoryManager.memorize(history, memories, {model: this.defaultModel, ...options});\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} length Max number of words\n\t * @param options LLM request options\n\t * @returns {Promise<string>} Summary\n\t */\n\tasync summarize(text: string, length: number = 500, options?: LLMRequest): Promise<string | null> {\n\t\tlet system = `Your job is to summarize the users message using tool calls. Call the \\`submit\\` tool at least once with the shortest summary possible that's <= ${length} words. The tool call will respond with the token count. Responses are ignored`;\n\t\tif(options?.system) system += '\\n\\n' + options.system;\n\t\treturn new Promise(async (resolve, reject) => {\n\t\t\tlet done = false;\n\t\t\tconst resp = await this.ask(text, {\n\t\t\t\ttemperature: 0.3,\n\t\t\t\t...options,\n\t\t\t\tsystem,\n\t\t\t\ttools: [{\n\t\t\t\t\tname: 'submit',\n\t\t\t\t\tdescription: 'Submit summary',\n\t\t\t\t\targs: {summary: {type: 'string', description: 'Text summarization', required: true}},\n\t\t\t\t\tfn: (args) => {\n\t\t\t\t\t\tif(!args.summary) return 'No summary provided';\n\t\t\t\t\t\tconst count = args.summary.split(' ').length;\n\t\t\t\t\t\tif(count > length) return `Too long: ${length} words`;\n\t\t\t\t\t\tdone = true;\n\t\t\t\t\t\tresolve(args.summary || null);\n\t\t\t\t\t\treturn `Saved: ${length} words`;\n\t\t\t\t\t}\n\t\t\t\t}, ...(options?.tools || [])],\n\t\t\t});\n\t\t\tif(!done) reject(`AI failed to create summary:\\n${resp}`);\n\t\t});\n\t}\n\n\taddModel(name: string, config: AnthropicConfig | OpenAiConfig, setDefault = false) {\n\t\tif(config.proto == 'anthropic') this.models[name] = new Anthropic(this.ai, config.token, name);\n\t\telse if(config.proto == 'openai') this.models[name] = new OpenAi(this.ai, config.host || null, config.token, name);\n\t\tif(setDefault || !this.defaultModel) this.defaultModel = name;\n\t}\n\n\tremoveModel(name: string) {\n\t\tdelete this.models[name];\n\t\tif(this.defaultModel === name) {\n\t\t\tthis.defaultModel = Object.keys(this.models)[0] ?? '';\n\t\t}\n\t}\n\n\tsetModels(models: {[model: string]: AnthropicConfig | OpenAiConfig}, replace = true) {\n\t\tif(replace) this.models = {};\n\t\tObject.entries(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 == 'openai') this.models[model] = new OpenAi(this.ai, config.host || null, config.token, model);\n\t\t});\n\t\tthis.defaultModel = Object.keys(this.models)[0] ?? '';\n\t}\n}\n\nexport default LLM;\n","import {execSync, spawn} from 'node:child_process';\nimport {mkdtempSync} from 'node:fs';\nimport fs from 'node:fs/promises';\nimport {tmpdir} from 'node:os';\nimport Path, {join} from 'node:path';\nimport {AbortablePromise, Ai} from './ai.ts';\n\nexport class Audio {\n\tprivate downloads: {[key: string]: Promise<string>} = {};\n\tprivate pyannote!: string;\n\tprivate whisperModel!: string;\n\n\tconstructor(private ai: Ai) {\n\t\tif(ai.options.whisper) {\n\t\t\tthis.whisperModel = ai.options.asr || 'ggml-base.en.bin';\n\t\t\tthis.downloadAsrModel();\n\t\t}\n\n\t\tthis.pyannote = `\nimport sys\nimport json\nimport os\nfrom pyannote.audio import Pipeline\n\nos.environ['TORCH_HOME'] = r\"${ai.options.path}\"\npipeline = Pipeline.from_pretrained(\"pyannote/speaker-diarization-3.1\", token=\"${ai.options.hfToken}\")\noutput = pipeline(sys.argv[1])\n\nsegments = []\nfor turn, speaker in output.speaker_diarization:\n    segments.append({\"start\": turn.start, \"end\": turn.end, \"speaker\": speaker})\n\nprint(json.dumps(segments))\n`;\n\t}\n\n\tprivate async addPunctuation(timestampData: any, llm?: boolean, cadence = 150): Promise<string> {\n\t\tconst countSyllables = (word: string): number => {\n\t\t\tword = word.toLowerCase().replace(/[^a-z]/g, '');\n\t\t\tif(word.length <= 3) return 1;\n\t\t\tconst matches = word.match(/[aeiouy]+/g);\n\t\t\tlet count = matches ? matches.length : 1;\n\t\t\tif(word.endsWith('e')) count--;\n\t\t\treturn Math.max(1, count);\n\t\t};\n\n\t\tlet result = '';\n\t\ttimestampData.transcription.filter((word, i) => {\n\t\t\tlet skip = false;\n\t\t\tconst prevWord = timestampData.transcription[i - 1];\n\t\t\tconst nextWord = timestampData.transcription[i + 1];\n\t\t\tif(!word.text && nextWord) {\n\t\t\t\tnextWord.offsets.from = word.offsets.from;\n\t\t\t\tnextWord.timestamps.from = word.offsets.from;\n\t\t\t} else if(word.text && word.text[0] != ' ' && prevWord) {\n\t\t\t\tprevWord.offsets.to = word.offsets.to;\n\t\t\t\tprevWord.timestamps.to = word.timestamps.to;\n\t\t\t\tprevWord.text += word.text;\n\t\t\t\tskip = true;\n\t\t\t}\n\t\t\treturn !!word.text && !skip;\n\t\t}).forEach((word: any) => {\n\t\t\tconst capital = /^[A-Z]/.test(word.text.trim());\n\t\t\tconst length = word.offsets.to - word.offsets.from;\n\t\t\tconst syllables = countSyllables(word.text.trim());\n\t\t\tconst expected = syllables * cadence;\n\t\t\tif(capital && length > expected * 2 && word.text[0] == ' ') result += '.';\n\t\t\tresult += word.text;\n\t\t});\n\t\tif(!llm) return result.trim();\n\t\treturn this.ai.language.ask(result, {\n\t\t\tsystem: 'Remove any misplaced punctuation from the following ASR transcript using the replace tool. Avoid modifying words unless there is an obvious typo',\n\t\t\ttemperature: 0.1,\n\t\t\ttools: [{\n\t\t\t\tname: 'replace',\n\t\t\t\tdescription: 'Use find and replace to fix errors',\n\t\t\t\targs: {\n\t\t\t\t\tfind: {type: 'string', description: 'Text to find', required: true},\n\t\t\t\t\treplace: {type: 'string', description: 'Text to replace', required: true}\n\t\t\t\t},\n\t\t\t\tfn: (args) => result = result.replace(args.find, args.replace)\n\t\t\t}]\n\t\t}).then(() => result);\n\t}\n\n\tprivate async diarizeTranscript(timestampData: any, speakers: any[], llm: boolean): Promise<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 punctuatedText = await this.addPunctuation(timestampData, llm);\n\t\tconst sentences = punctuatedText.match(/[^.!?]+[.!?]+/g) || [punctuatedText];\n\t\tconst words = timestampData.transcription.filter((w: any) => w.text.trim());\n\n\t\t// Assign speaker to each sentence\n\t\tconst sentencesWithSpeakers = sentences.map(sentence => {\n\t\t\tsentence = sentence.trim();\n\t\t\tif(!sentence) return null;\n\n\t\t\tconst sentenceWords = sentence.toLowerCase().replace(/[^\\w\\s]/g, '').split(/\\s+/);\n\t\t\tconst speakerWordCount = new Map<number, number>();\n\n\t\t\tsentenceWords.forEach(sw => {\n\t\t\t\tconst word = words.find((w: any) => sw === w.text.trim().toLowerCase().replace(/[^\\w]/g, ''));\n\t\t\t\tif(!word) return;\n\n\t\t\t\tconst wordTime = word.offsets.from / 1000;\n\t\t\t\tconst speaker = speakers.find((seg: any) => wordTime >= seg.start && wordTime <= seg.end);\n\t\t\t\tif(speaker) {\n\t\t\t\t\tconst spkNum = speakerMap.get(speaker.speaker);\n\t\t\t\t\tspeakerWordCount.set(spkNum, (speakerWordCount.get(spkNum) || 0) + 1);\n\t\t\t\t}\n\t\t\t});\n\n\t\t\tlet bestSpeaker = 1;\n\t\t\tlet maxWords = 0;\n\t\t\tspeakerWordCount.forEach((count, speaker) => {\n\t\t\t\tif(count > maxWords) {\n\t\t\t\t\tmaxWords = count;\n\t\t\t\t\tbestSpeaker = speaker;\n\t\t\t\t}\n\t\t\t});\n\n\t\t\treturn {speaker: bestSpeaker, text: sentence};\n\t\t}).filter(s => s !== null);\n\n\t\t// Merge adjacent sentences from same speaker\n\t\tconst merged: Array<{speaker: number, text: string}> = [];\n\t\tsentencesWithSpeakers.forEach(item => {\n\t\t\tconst last = merged[merged.length - 1];\n\t\t\tif(last && last.speaker === item.speaker) {\n\t\t\t\tlast.text += ' ' + item.text;\n\t\t\t} else {\n\t\t\t\tmerged.push({...item});\n\t\t\t}\n\t\t});\n\n\t\tlet transcript = merged.map(item => `[Speaker ${item.speaker}]: ${item.text}`).join('\\n').trim();\n\t\tif(!llm) return transcript;\n\t\tlet chunks = this.ai.language.chunk(transcript, 500, 0);\n\t\tif(chunks.length > 4) chunks = [...chunks.slice(0, 3), <string>chunks.at(-1)];\n\t\tawait this.ai.language.ask(chunks.join('\\n'), {\n\t\t\tsystem: 'Read the following transcript and attempt to identify every speaker. For every positively identified speaker, call the \\`identify\\` tool with the speaker\\'s ID number & the identified name exactly once.',\n\t\t\ttemperature: 0.1,\n\t\t\ttools: [\n\t\t\t\t{name: 'identify', description: 'Identify a speaker', args: {\n\t\t\t\t\tspeaker: {type: 'number', description: 'Speaker number', required: true},\n\t\t\t\t\tname: {type: 'string', description: 'Inferred name', required: true},\n\t\t\t\t}, fn: ({speaker, name}) => {\n\t\t\t\t\ttranscript = transcript.replaceAll(`[Speaker ${speaker}]`, `[${name}]`);\n\t\t\t\t}}\n\t\t\t]\n\t\t});\n\t\treturn transcript;\n\t}\n\n\tprivate runAsr(file: string, opts: {model?: string, diarization?: boolean} = {}): AbortablePromise<any> {\n\t\tlet proc: any;\n\t\tconst p = new Promise<any>((resolve, reject) => {\n\t\t\tthis.downloadAsrModel(opts.model).then(m => {\n\t\t\t\tif(opts.diarization) {\n\t\t\t\t\tlet output = join(Path.dirname(file), 'transcript');\n\t\t\t\t\tproc = spawn(<string>this.ai.options.whisper,\n\t\t\t\t\t\t['-m', m, '-f', file, '-np', '-ml', '1', '-oj', '-of', output],\n\t\t\t\t\t\t{stdio: ['ignore', 'ignore', 'pipe']}\n\t\t\t\t\t);\n\t\t\t\t\tproc.on('error', (err: Error) => reject(err));\n\t\t\t\t\tproc.on('close', async (code: number) => {\n\t\t\t\t\t\tif(code === 0) {\n\t\t\t\t\t\t\toutput = await fs.readFile(output + '.json', 'utf-8');\n\t\t\t\t\t\t\tfs.rm(output + '.json').catch(() => { });\n\t\t\t\t\t\t\ttry { resolve(JSON.parse(output)); }\n\t\t\t\t\t\t\tcatch(e) { reject(new Error('Failed to parse whisper JSON')); }\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\treject(new Error(`Exit code ${code}`));\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t} else {\n\t\t\t\t\tlet output = '';\n\t\t\t\t\tproc = spawn(<string>this.ai.options.whisper, ['-m', m, '-f', file, '-np', '-nt']);\n\t\t\t\t\tproc.on('error', (err: Error) => reject(err));\n\t\t\t\t\tproc.stdout.on('data', (data: Buffer) => output += data.toString());\n\t\t\t\t\tproc.on('close', async (code: number) => {\n\t\t\t\t\t\tif(code === 0) {\n\t\t\t\t\t\t\tresolve(output.trim() || null);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\treject(new Error(`Exit code ${code}`));\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t});\n\t\t});\n\t\treturn <any>Object.assign(p, {abort: () => proc?.kill('SIGTERM')});\n\t}\n\n\tprivate runDiarization(file: string): AbortablePromise<any> {\n\t\tlet aborted = false, abort = () => { aborted = true; };\n\t\tconst checkPython = (cmd: string) => {\n\t\t\treturn new Promise<boolean>((resolve) => {\n\t\t\t\tconst proc = spawn(cmd, ['-W', 'ignore', '-c', 'import pyannote.audio']);\n\t\t\t\tproc.on('close', (code: number) => resolve(code === 0));\n\t\t\t\tproc.on('error', () => resolve(false));\n\t\t\t});\n\t\t};\n\t\tconst p = Promise.all<any>([\n\t\t\tcheckPython('python'),\n\t\t\tcheckPython('python3'),\n\t\t]).then(<any>(async ([p, p3]: [boolean, boolean]) => {\n\t\t\tif(aborted) return;\n\t\t\tif(!p && !p3) throw new Error('Pyannote is not installed: pip install pyannote.audio');\n\t\t\tconst binary = p3 ? 'python3' : 'python';\n\t\t\treturn new Promise((resolve, reject) => {\n\t\t\t\tif(aborted) return;\n\t\t\t\tlet output = '';\n\t\t\t\tconst proc = spawn(binary, ['-W', 'ignore', '-c', this.pyannote, file]);\n\t\t\t\tproc.stdout.on('data', (data: Buffer) => output += data.toString());\n\t\t\t\tproc.stderr.on('data', (data: Buffer) => console.error(data.toString()));\n\t\t\t\tproc.on('close', (code: number) => {\n\t\t\t\t\tif(code === 0) {\n\t\t\t\t\t\ttry { resolve(JSON.parse(output)); }\n\t\t\t\t\t\tcatch (err) { reject(new Error('Failed to parse diarization output')); }\n\t\t\t\t\t} else {\n\t\t\t\t\t\treject(new Error(`Python process exited with code ${code}`));\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t\tproc.on('error', reject);\n\t\t\t\tabort = () => proc.kill('SIGTERM');\n\t\t\t});\n\t\t}));\n\t\treturn <any>Object.assign(p, {abort});\n\t}\n\n\tasr(path: string, options: { model?: string; diarization?: boolean | 'llm' } = {}): AbortablePromise<string | null> {\n\t\tif(!this.ai.options.whisper) throw new Error('Whisper not configured');\n\n\t\tconst tmp = join(mkdtempSync(join(tmpdir(), 'audio-')), 'converted.wav');\n\t\texecSync(`ffmpeg -i \"${path}\" -ar 16000 -ac 1 -f wav \"${tmp}\"`, { stdio: 'ignore' });\n\t\tconst clean = () => fs.rm(Path.dirname(tmp), {recursive: true, force: true}).catch(() => {});\n\n\t\tif(!options.diarization) return this.runAsr(tmp, {model: options.model});\n\t\tconst timestamps = this.runAsr(tmp, {model: options.model, diarization: true});\n\t\tconst diarization = this.runDiarization(tmp);\n\t\tlet aborted = false, abort = () => {\n\t\t\taborted = true;\n\t\t\ttimestamps.abort();\n\t\t\tdiarization.abort();\n\t\t\tclean();\n\t\t};\n\n\t\tconst response = Promise.allSettled([timestamps, diarization]).then(async ([ts, d]) => {\n\t\t\tif(ts.status == 'rejected') throw new Error('Whisper.cpp timestamps:\\n' + ts.reason);\n\t\t\tif(d.status == 'rejected') throw new Error('Pyannote:\\n' + d.reason);\n\t\t\tif(aborted || !options.diarization) return ts.value;\n\t\t\treturn this.diarizeTranscript(ts.value, d.value, options.diarization == 'llm');\n\t\t}).finally(() => clean());\n\t\treturn <any>Object.assign(response, {abort});\n\t}\n\n\tasync downloadAsrModel(model: string = this.whisperModel): Promise<string> {\n\t\tif(!this.ai.options.whisper) throw new Error('Whisper not configured');\n\t\tif(!model.endsWith('.bin')) model += '.bin';\n\t\tconst p = Path.join(<string>this.ai.options.path, model);\n\t\tif(await fs.stat(p).then(() => true).catch(() => false)) return p;\n\t\tif(!!this.downloads[model]) return this.downloads[model];\n\t\tthis.downloads[model] = fetch(`https://huggingface.co/ggerganov/whisper.cpp/resolve/main/${model}`)\n\t\t\t.then(resp => resp.arrayBuffer())\n\t\t\t.then(arr => Buffer.from(arr)).then(async buffer => {\n\t\t\t\tawait fs.writeFile(p, buffer);\n\t\t\t\tdelete this.downloads[model];\n\t\t\t\treturn p;\n\t\t\t});\n\t\treturn this.downloads[model];\n\t}\n}\n","import {createWorker} from 'tesseract.js';\nimport {AbortablePromise, Ai} from './ai.ts';\n\nexport class Vision {\n\n\tconstructor(private ai: Ai) {}\n\n\t/**\n\t * Convert image to text using Optical Character Recognition\n\t * @param {string} path Path to image\n\t * @returns {AbortablePromise<string | null>} Promise of extracted text with abort method\n\t */\n\tocr(path: string): AbortablePromise<string | null> {\n\t\tlet worker: any;\n\t\tlet reject: (err: any) => void;\n\n\t\tconst handler = (err: Error) => {\n\t\t\tif(err.stack?.includes('tesseract.js')) {\n\t\t\t\tprocess.off('uncaughtException', handler);\n\t\t\t\treject?.(err);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tthrow err;\n\t\t};\n\t\tprocess.on('uncaughtException', handler);\n\n\t\tconst p = (async () => {\n\t\t\tworker = await createWorker(this.ai.options.ocr || 'eng', 2, {cachePath: this.ai.options.path});\n\t\t\treturn await new Promise<string | null>((res, rej) => {\n\t\t\t\treject = rej;\n\t\t\t\tworker.recognize(path)\n\t\t\t\t\t.then(({data}: any) => res(data.text.trim() || null))\n\t\t\t\t\t.catch(rej);\n\t\t\t});\n\t\t})().finally(() => {\n\t\t\tprocess.off('uncaughtException', handler);\n\t\t\tworker?.terminate();\n\t\t});\n\n\t\treturn Object.assign(p, {abort: () => worker?.terminate()});\n\t}\n}\n","import * as os from 'node:os';\nimport LLM, {AnthropicConfig, OpenAiConfig, LLMRequest} from './llm';\nimport { Audio } from './audio.ts';\nimport {Vision} from './vision.ts';\n\nexport type AbortablePromise<T> = Promise<T> & {\n\tabort: (keep?: boolean) => any\n};\n\nexport type AiOptions = {\n\t/** Token to pull diarization models from hugging face */\n\thfToken?: string;\n\t/** Path to models */\n\tpath?: string;\n\t/** Whisper ASR model: ggml-tiny.en.bin, ggml-base.en.bin */\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 | OpenAiConfig};\n\t}\n\t/** OCR model: eng, eng_best, eng_fast */\n\tocr?: string;\n\t/** Whisper binary */\n\twhisper?: 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"],"mappings":"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"}