UNPKG

@matthew.ngo/ai-toolkit

Version:

A comprehensive AI toolkit with multi-provider support

2 lines 36.6 kB
'use strict';var chunk6OKKVZHN_cjs=require('./chunk-6OKKVZHN.cjs'),lruCache=require('lru-cache'),M=require('crypto'),zod=require('zod'),D=require('@hapi/boom'),B=require('verror'),v=require('bottleneck'),K=require('p-retry'),exponentialBackoff=require('exponential-backoff'),gptTokenizer=require('gpt-tokenizer'),tiktoken=require('tiktoken');function _interopDefault(e){return e&&e.__esModule?e:{default:e}}var M__default=/*#__PURE__*/_interopDefault(M);var D__default=/*#__PURE__*/_interopDefault(D);var B__default=/*#__PURE__*/_interopDefault(B);var v__default=/*#__PURE__*/_interopDefault(v);var K__default=/*#__PURE__*/_interopDefault(K);var d=class{events=[];maxEvents=1e5;stats={tokensUsed:0,requestsCount:0,costEstimate:0,lastReset:new Date,byProvider:{},byModel:{},byCapability:{},errors:[]};trackEvent(e){let t={...e,timestamp:new Date};this.events.push(t),this.updateStats(t),this.events.length>this.maxEvents&&(this.events=this.events.slice(-this.maxEvents/2));}updateStats(e){if(!this.stats.byProvider){console.warn("No provider stats initialized.");return}e.type==="success"&&(this.stats.requestsCount++,e.tokens&&(this.stats.tokensUsed+=e.tokens.total),e.cost&&(this.stats.costEstimate+=e.cost)),this.stats.byProvider[e.provider]||(this.stats.byProvider[e.provider]={requests:0,tokens:0,cost:0,averageLatency:0,errorRate:0});let t=this.stats.byProvider[e.provider];if(!t){console.warn(`Unknown provider ${e.provider}.`);return}if((e.type==="success"||e.type==="error")&&t.requests++,e.type==="success"&&(e.tokens&&(t.tokens+=e.tokens.total),e.cost&&(t.cost+=e.cost),e.latency)){let r=t.averageLatency*(t.requests-1);t.averageLatency=(r+e.latency)/t.requests;}if(e.type==="error"&&(t.errorRate=this.calculateErrorRate(e.provider)),!this.stats.byModel){console.warn("No model stats initialized.");return}if(e.model){this.stats.byModel[e.model]||(this.stats.byModel[e.model]={requests:0,tokens:0,inputTokens:0,outputTokens:0,cost:0});let r=this.stats.byModel[e.model];if(!r){console.warn(`Unknown model ${e.model}.`);return}e.type==="success"&&(r.requests++,e.tokens&&(r.tokens+=e.tokens.total,r.inputTokens+=e.tokens.prompt,r.outputTokens+=e.tokens.completion),e.cost&&(r.cost+=e.cost));}if(!this.stats.byCapability){console.warn("No capability stats initialized.");return}this.stats.byCapability[e.operation]||(this.stats.byCapability[e.operation]=0),e.type==="success"&&this.stats.byCapability[e.operation]++,e.type==="error"&&e.error&&this.updateErrorStats(e);}calculateErrorRate(e){let t=this.events.filter(s=>s.provider===e),r=t.filter(s=>s.type==="error").length,i=t.filter(s=>s.type==="success"||s.type==="error").length;return i>0?r/i:0}updateErrorStats(e){if(!e.error)return;let t=this.stats.errors?.find(r=>r.error===e.error&&r.provider===e.provider);t?t.count++:this.stats.errors?.push({timestamp:e.timestamp,provider:e.provider,error:e.error,count:1}),this.stats.errors&&this.stats.errors.length>100&&(this.stats.errors=this.stats.errors.sort((r,i)=>i.timestamp.getTime()-r.timestamp.getTime()).slice(0,50));}getStats(){return {...this.stats,byProvider:{...this.stats.byProvider},byModel:{...this.stats.byModel},byCapability:{...this.stats.byCapability},errors:[...this.stats.errors||[]]}}getTrends(e="day",t=30){let r={hour:36e5,day:864e5,week:6048e5,month:2592e6}[e],i=Date.now(),s=[];for(let n=0;n<t;n++){let o=i-n*r,a=o-r,u=this.events.filter(g=>{let p=g.timestamp.getTime();return p>=a&&p<o}),m=u.filter(g=>g.type==="success");s.unshift({timestamp:new Date(o).toISOString(),requests:m.length,tokens:m.reduce((g,p)=>g+(p.tokens?.total||0),0),cost:m.reduce((g,p)=>g+(p.cost||0),0),errors:u.filter(g=>g.type==="error").length});}return s}getTopOperations(e=10){if(!this.stats.byCapability)return [];let t=Object.values(this.stats.byCapability).reduce((r,i)=>r+i,0);return Object.entries(this.stats.byCapability).map(([r,i])=>({operation:r,count:i,percentage:t>0?i/t*100:0})).sort((r,i)=>i.count-r.count).slice(0,e)}getCostBreakdown(){if(!this.stats.byProvider||!this.stats.byModel)return {};let e={};return this.events.filter(t=>t.type==="success"&&t.cost).forEach(t=>{e[t.operation]=(e[t.operation]||0)+(t.cost||0);}),{total:this.stats.costEstimate,byProvider:Object.entries(this.stats.byProvider).reduce((t,[r,i])=>(t[r]=i.cost,t),{}),byModel:Object.entries(this.stats.byModel).reduce((t,[r,i])=>(t[r]=i.cost,t),{}),byOperation:e}}getProviderComparison(){if(!this.stats.byProvider)return [];let e=Object.entries(this.stats.byProvider).map(([s,n])=>({provider:s,stats:n})),t=[...e].sort((s,n)=>s.stats.averageLatency-n.stats.averageLatency),r=[...e].sort((s,n)=>s.stats.errorRate-n.stats.errorRate),i=[...e].sort((s,n)=>s.stats.cost/s.stats.tokens-n.stats.cost/n.stats.tokens);return e.map(({provider:s,stats:n})=>{let o=t.findIndex(m=>m.provider===s)+1,a=r.findIndex(m=>m.provider===s)+1,u=i.findIndex(m=>m.provider===s)+1;return {provider:s,stats:n,rank:{speed:o,reliability:a,cost:u,overall:Math.round((o+a+u)/3)}}})}getRecommendations(){let e=[],t=this.getStats(),r=this.getProviderComparison();t.costEstimate>100&&e.push("Consider using cheaper models for simple tasks to reduce costs"),r.forEach(({provider:a,stats:u})=>{u.errorRate>.05&&e.push(`${a} has high error rate (${(u.errorRate*100).toFixed(1)}%). Consider using fallback providers.`),u.averageLatency>5e3&&e.push(`${a} has high latency. Enable caching for frequently used prompts.`);});let i=this.events.filter(a=>a.type==="cache_hit").length,s=t.requestsCount;return (s>0?i/s:0)<.2&&s>100&&e.push("Low cache hit rate. Consider increasing cache TTL or size."),this.events.filter(a=>a.type==="rate_limit").length>10&&e.push("Frequent rate limiting detected. Implement request queuing or upgrade API limits."),e}reset(){this.stats={tokensUsed:0,requestsCount:0,costEstimate:0,lastReset:new Date,byProvider:{},byModel:{},byCapability:{},errors:[]},this.events=[];}exportData(){return {stats:this.getStats(),trends:this.getTrends(),topOperations:this.getTopOperations(),costBreakdown:this.getCostBreakdown(),providerComparison:this.getProviderComparison(),recommendations:this.getRecommendations()}}};var h=class{metrics=new Map;history=[];maxHistorySize=1e4;windowSize=3e5;startOperation(e,t,r,i){this.metrics.set(e,{operationId:e,operation:t,provider:r,startTime:performance.now(),success:false,metadata:i});}endOperation(e,t=true,r){let i=this.metrics.get(e);if(!i)return null;i.endTime=performance.now(),i.duration=i.endTime-i.startTime,i.success=t,i.error=r;let s={operationId:i.operationId,operation:i.operation,provider:i.provider,duration:i.duration,success:i.success,error:i.error,timestamp:new Date().toISOString()};return this.history.push(s),this.metrics.delete(e),this.history.length>this.maxHistorySize&&(this.history=this.history.slice(-this.maxHistorySize/2)),s}getStats(e){let t=Date.now()-(e?.timeWindow||this.windowSize),r=this.history.filter(o=>new Date(o.timestamp).getTime()>t);if(e?.provider&&(r=r.filter(o=>o.provider===e.provider)),e?.operation&&(r=r.filter(o=>o.operation===e.operation)),r.length===0)return {averageLatency:0,minLatency:0,maxLatency:0,successRate:0,errorRate:0,throughput:0,percentiles:{p50:0,p90:0,p95:0,p99:0}};let i=r.map(o=>o.duration).sort((o,a)=>o-a),s=r.filter(o=>o.success).length,n=r.length;return {averageLatency:i.reduce((o,a)=>o+a,0)/i.length,minLatency:i[0]??0,maxLatency:i[i.length-1]??0,successRate:s/n,errorRate:(n-s)/n,throughput:n/((e?.timeWindow||this.windowSize)/1e3),percentiles:{p50:this.getPercentile(i,50),p90:this.getPercentile(i,90),p95:this.getPercentile(i,95),p99:this.getPercentile(i,99)}}}getStatsByProvider(){let e=new Set(this.history.map(r=>r.provider)),t={};for(let r of e)t[r]=this.getStats({provider:r});return t}getStatsByOperation(){let e=new Set(this.history.map(r=>r.operation)),t={};for(let r of e)t[r]=this.getStats({operation:r});return t}getTrends(e="hour",t=24){let r={minute:6e4,hour:36e5,day:864e5}[e],i=Date.now(),s=[];for(let n=0;n<t;n++){let o=i-n*r,a=o-r,u=this.getStats({timeWindow:i-a});s.unshift({timestamp:new Date(o).toISOString(),stats:u});}return s}getErrorAnalysis(){let e=this.history.filter(n=>!n.success&&n.error),t=new Map,r={};for(let n of e)n.error&&(t.set(n.error,(t.get(n.error)||0)+1),r[n.provider]=(r[n.provider]||0)+1);let i=Array.from(t.entries()).map(([n,o])=>({error:n,count:o})).sort((n,o)=>o.count-n.count).slice(0,10),s={timeout:0,rateLimit:0,authentication:0,network:0,other:0};for(let[n,o]of t)n.includes("timeout")?s.timeout=(s.timeout??0)+o:n.includes("rate limit")?s.rateLimit=(s.rateLimit??0)+o:n.includes("auth")||n.includes("401")?s.authentication=(s.authentication??0)+o:n.includes("network")?s.network=(s.network??0)+o:s.other=(s.other??0)+o;return {totalErrors:e.length,errorsByType:s,errorsByProvider:r,commonErrors:i}}getSlowOperations(e){let t=this.getStats().percentiles.p95,r=e||t||5e3;return this.history.filter(i=>i.duration>r).sort((i,s)=>s.duration-i.duration).slice(0,100)}getPercentile(e,t){let r=Math.ceil(t/100*e.length)-1;return e[Math.max(0,r)]??0}clearHistory(){this.history=[],this.metrics.clear();}exportData(){return {history:this.history,stats:this.getStats(),statsByProvider:this.getStatsByProvider(),statsByOperation:this.getStatsByOperation(),errorAnalysis:this.getErrorAnalysis()}}getActiveOperations(){return Array.from(this.metrics.values())}getHealthStatus(){let e=this.getStats(),t=[];return e.successRate<.95&&t.push(`Low success rate: ${(e.successRate*100).toFixed(1)}%`),e.percentiles.p95>5e3&&t.push(`High P95 latency: ${e.percentiles.p95.toFixed(0)}ms`),e.throughput<.1&&t.push(`Low throughput: ${e.throughput.toFixed(2)} req/s`),{status:t.length===0?"healthy":t.length===1?"degraded":"unhealthy",issues:t}}};var f=class{cache;enabled;namespace;stats={hits:0,misses:0,evictions:0};constructor(e){this.enabled=e.enabled??true,this.namespace=e.namespace||"ai-toolkit";let t=(e.maxSize||100)*1024*1024;this.cache=new lruCache.LRUCache({max:1e3,maxSize:t,sizeCalculation:r=>JSON.stringify(r).length,ttl:e.ttl||6e5,updateAgeOnGet:true,updateAgeOnHas:false,dispose:()=>{this.stats.evictions++;}}),this.setupCleanup();}generateKey(e,t,r){let i={namespace:this.namespace,method:e,params:t.map(n=>typeof n=="object"?JSON.stringify(n,Object.keys(n).sort()):String(n)),options:r?JSON.stringify(r,Object.keys(r).sort()):null},s=M__default.default.createHash("sha256").update(JSON.stringify(i)).digest("hex");return `${this.namespace}:${e}:${s}`}async get(e){if(!this.enabled)return null;let t=this.cache.get(e);return t?(this.stats.hits++,t.hits++,t.value):(this.stats.misses++,null)}async set(e,t,r){if(!this.enabled)return;let i={key:e,value:t,timestamp:Date.now(),hits:0,metadata:r};this.cache.set(e,i);}async delete(e){return this.cache.delete(e)}async clear(){this.cache.clear(),this.stats={hits:0,misses:0,evictions:0};}has(e){return this.cache.has(e)}getStats(){let e=this.stats.hits+this.stats.misses>0?this.stats.hits/(this.stats.hits+this.stats.misses):0;return {...this.stats,hitRate:Math.round(e*100)/100,size:this.cache.size,calculatedSize:this.cache.calculatedSize,maxSize:this.cache.maxSize,itemCount:this.cache.size,enabled:this.enabled}}keys(){return Array.from(this.cache.keys())}entries(){let e=[];for(let[t,r]of this.cache.entries())e.push({key:t,metadata:r.metadata,age:Date.now()-r.timestamp});return e}prune(){let e=this.cache.size;return this.cache.purgeStale(),e-this.cache.size}setEnabled(e){this.enabled=e,e||this.clear();}updateTTL(e){let t=Array.from(this.cache.entries());this.cache=new lruCache.LRUCache({max:this.cache.max,maxSize:this.cache.maxSize,ttl:e,updateAgeOnGet:true,updateAgeOnHas:false,sizeCalculation:r=>JSON.stringify(r).length,dispose:()=>{this.stats.evictions++;}});for(let[r,i]of t)this.cache.set(r,i);}getMemoryUsage(){return {used:this.cache.calculatedSize,max:this.cache.maxSize,percentage:Math.round(this.cache.calculatedSize/this.cache.maxSize*100)}}setupCleanup(){setInterval(()=>{this.prune();},5*60*1e3);}async wrap(e,t,r){let i=await this.get(e);if(i!==null)return i;let s=await t();return await this.set(e,s,r?.metadata),s}createTextGenerationKey(e,t,r,i){return this.generateKey("generateText",[e],{...t,provider:r,model:i})}createEmbeddingKey(e,t,r){return this.generateKey("generateEmbedding",[e],{provider:t,model:r})}export(){let e={};for(let[t,r]of this.cache.entries())e[t]={value:r.value,timestamp:r.timestamp,hits:r.hits,metadata:r.metadata};return e}import(e){this.clear();for(let[t,r]of Object.entries(e))r&&typeof r=="object"&&"value"in r&&this.cache.set(t,r);}};var I=zod.z.object({requestsPerMinute:zod.z.number().optional(),tokensPerMinute:zod.z.number().optional(),requestsPerHour:zod.z.number().optional(),tokensPerHour:zod.z.number().optional(),concurrent:zod.z.number().default(5),strategy:zod.z.enum(["fixed-window","sliding-window","token-bucket"]).default("sliding-window")}),L=zod.z.object({enabled:zod.z.boolean().default(true),ttl:zod.z.number().default(6e5),maxSize:zod.z.number().default(100),strategy:zod.z.enum(["lru","fifo","lfu"]).default("lru")}),z=zod.z.object({maxAttempts:zod.z.number().default(3),baseDelay:zod.z.number().default(1e3),maxDelay:zod.z.number().default(3e4),backoff:zod.z.enum(["exponential","linear","fixed"]).default("exponential")}),P=zod.z.object({provider:zod.z.custom(),apiKey:zod.z.string().optional(),apiKeys:zod.z.record(zod.z.string()).optional(),model:zod.z.string().optional(),models:zod.z.record(zod.z.string()).optional(),baseUrl:zod.z.string().optional(),headers:zod.z.record(zod.z.string()).optional(),maxRetries:zod.z.number().optional(),timeout:zod.z.number().optional(),cache:L.optional(),rateLimit:I.optional(),retry:z.optional(),fallbackProviders:zod.z.array(zod.z.custom()).optional()});var y=class{config;encryptedKeys=new Map;constructor(e){this.config=P.parse(e),this.config.apiKey&&this.encryptedKeys.set(this.config.provider,this.encryptApiKey(this.config.apiKey)),this.config.apiKeys&&Object.entries(this.config.apiKeys).forEach(([t,r])=>{this.encryptedKeys.set(t,this.encryptApiKey(r));});}getConfig(){return {...this.config}}getProviderConfig(e){let t=e||this.config.provider;return {provider:t,apiKey:this.getApiKey(t),model:this.getModel(t),baseUrl:this.config.baseUrl,headers:this.config.headers}}getApiKey(e){let t=e||this.config.provider,r=this.encryptedKeys.get(t);if(r)return this.decryptApiKey(r)}getModel(e){let t=e||this.config.provider;return this.config.models&&this.config.models[t]?this.config.models[t]:this.config.model}getCacheConfig(){return this.config.cache||{enabled:true,ttl:6e5,maxSize:100,strategy:"lru"}}getRateLimitConfig(){return this.config.rateLimit||{requestsPerMinute:60,strategy:"sliding-window",concurrent:5}}getRetryConfig(){return this.config.retry||{maxAttempts:3,baseDelay:1e3,maxDelay:3e4,backoff:"exponential"}}getFallbackProviders(){return this.config.fallbackProviders||[]}updateConfig(e){let t={...this.config,...e};this.config=P.parse(t),e.apiKey&&this.encryptedKeys.set(this.config.provider,this.encryptApiKey(e.apiKey)),e.apiKeys&&Object.entries(e.apiKeys).forEach(([r,i])=>{this.encryptedKeys.set(r,this.encryptApiKey(i));});}encryptApiKey(e){return Buffer.from(e).toString("base64")}decryptApiKey(e){return Buffer.from(e,"base64").toString("utf-8")}validateProvider(e){let t=[];return !this.getApiKey(e)&&e!=="local"&&e!=="mock"&&t.push(`API key required for provider: ${e}`),this.getModel(e)||t.push(`Model not specified for provider: ${e}`),{valid:t.length===0,errors:t}}exportConfig(){let{apiKey:e,apiKeys:t,...r}=this.config;return {...r,hasApiKey:!!e||!!t,configuredProviders:Array.from(this.encryptedKeys.keys())}}};var b=class{errorHistory=[];maxHistorySize=1e3;handleError(e,t){let r=this.enhanceError(e,t);return this.addToHistory(r,t),r}enhanceError(e,t){let r=new B__default.default({name:this.getErrorName(e),cause:e,info:{...t,originalError:{message:e.message,code:e.code,status:e.status}}},this.getErrorMessage(e,t));return r.code=e.code||this.inferErrorCode(e),r.status=e.status||this.inferStatusCode(e),r.category=this.categorizeError(e),r.userMessage=this.getUserFriendlyMessage(r),r.isRetryable=this.isRetryable(r),r.context=t,r.recommendations=this.getRecommendations(r),r.timestamp=new Date().toISOString(),r}getErrorName(e){let t=this.categorizeError(e);return {authentication:"AuthenticationError","rate-limit":"RateLimitError","invalid-request":"ValidationError","server-error":"ServerError",network:"NetworkError",timeout:"TimeoutError",billing:"BillingError","not-found":"NotFoundError",permission:"PermissionError"}[t]||"AIProviderError"}getErrorMessage(e,t){return `${t.operation} failed on ${t.provider}${t.model?` (model: ${t.model})`:""}: ${e.message}`}categorizeError(e){let t=e.message?.toLowerCase()||"",r=e.code||e.status;return r===401||t.includes("unauthorized")||t.includes("api key")?"authentication":r===429||t.includes("rate limit")||t.includes("quota exceeded")?"rate-limit":r===402||t.includes("billing")||t.includes("payment")?"billing":r===400||t.includes("invalid")||t.includes("validation")?"invalid-request":r===403||t.includes("forbidden")||t.includes("permission")?"permission":r===404||t.includes("not found")?"not-found":r>=500||t.includes("internal server")?"server-error":t.includes("network")||t.includes("econnrefused")||t.includes("enotfound")?"network":t.includes("timeout")||r==="ETIMEDOUT"?"timeout":"unknown"}inferErrorCode(e){if(e.code)return e.code;let t=this.categorizeError(e);return {authentication:"AUTH_ERROR","rate-limit":"RATE_LIMIT_ERROR","invalid-request":"VALIDATION_ERROR","server-error":"SERVER_ERROR",network:"NETWORK_ERROR",timeout:"TIMEOUT_ERROR",billing:"BILLING_ERROR","not-found":"NOT_FOUND",permission:"PERMISSION_DENIED"}[t]||"UNKNOWN_ERROR"}inferStatusCode(e){if(e.status)return e.status;let t=this.categorizeError(e);return {authentication:401,"rate-limit":429,"invalid-request":400,"server-error":500,network:503,timeout:504,billing:402,"not-found":404,permission:403}[t]||500}getUserFriendlyMessage(e){return {authentication:"Authentication failed. Please check your API key and ensure it has the necessary permissions.","rate-limit":"Rate limit exceeded. Please wait a moment before trying again.",billing:"There is an issue with your billing or quota. Please check your account status.","invalid-request":"The request contains invalid parameters. Please check your input and try again.","server-error":"The AI service is temporarily unavailable. Please try again later.",network:"Network connection issue. Please check your internet connection and try again.",timeout:"The request timed out. Please try again with a shorter prompt or wait a moment.","not-found":"The requested resource was not found. Please verify the endpoint or model name.",permission:"You do not have permission to perform this action.",unknown:"An unexpected error occurred. Please try again or contact support if the issue persists."}[e.category||"unknown"]}isRetryable(e){return ["rate-limit","server-error","network","timeout"].includes(e.category||"")}getRecommendations(e){let t=[];switch(e.category){case "authentication":t.push("Verify your API key is correct"),t.push("Check if the API key has been revoked or expired"),t.push("Ensure the API key has the necessary permissions");break;case "rate-limit":t.push("Implement request queuing or throttling"),t.push("Consider upgrading your API plan for higher limits"),t.push("Spread requests over time to avoid bursts");break;case "billing":t.push("Check your account balance and payment method"),t.push("Review your usage and adjust limits if needed"),t.push("Contact support if billing issues persist");break;case "invalid-request":t.push("Review the API documentation for correct parameters"),t.push("Validate input data before sending requests"),t.push("Check for any recent API changes or deprecations");break;case "network":t.push("Check your internet connection"),t.push("Verify firewall or proxy settings"),t.push("Try using a different network");break;case "timeout":t.push("Reduce the size of your request"),t.push("Increase timeout settings if possible"),t.push("Break large requests into smaller chunks");break}return e.context?.attempt&&e.context.attempt>2&&(t.push("Consider using a fallback provider"),t.push("Implement circuit breaker pattern")),t}addToHistory(e,t){this.errorHistory.push({timestamp:new Date,error:e,context:t,resolved:false}),this.errorHistory.length>this.maxHistorySize&&(this.errorHistory=this.errorHistory.slice(-this.maxHistorySize/2));}createHttpError(e){let t=D__default.default.boomify(e,{statusCode:e.status||500,message:e.userMessage});return t.output.payload.code=e.code,t.output.payload.category=e.category,t.output.payload.isRetryable=e.isRetryable,t.output.payload.recommendations=e.recommendations,t}getErrorStats(e){let t=e?Date.now()-e:0,r=this.errorHistory.filter(n=>n.timestamp.getTime()>t),i={total:r.length,byCategory:{},byProvider:{},resolutionRate:0,recentErrors:[]};r.forEach(n=>{let o=n.error.category||"unknown";i.byCategory[o]=(i.byCategory[o]||0)+1;let a=n.context.provider;i.byProvider[a]=(i.byProvider[a]||0)+1,i.recentErrors.length<10&&i.recentErrors.push({timestamp:n.timestamp.toISOString(),category:o,provider:a,message:n.error.message});});let s=r.filter(n=>n.resolved).length;return i.resolutionRate=r.length>0?s/r.length:0,i}markResolved(e){let t=this.errorHistory.find(r=>r.timestamp.toISOString()===e);t&&(t.resolved=true);}clearHistory(){this.errorHistory=[];}exportHistory(){return this.errorHistory.map(e=>({timestamp:e.timestamp.toISOString(),error:{message:e.error.message,code:e.error.code,category:e.error.category,userMessage:e.error.userMessage,isRetryable:e.error.isRetryable,recommendations:e.error.recommendations},context:e.context,resolved:e.resolved}))}};var k=class{limiters=new Map;tokenBuckets=new Map;createLimiter(e){let t=this.limiters.get(e.id);if(t)return t;let r;switch(e.strategy){case "token-bucket":r=this.createTokenBucketConfig(e);break;case "fixed-window":r=this.createFixedWindowConfig(e);break;case "sliding-window":default:r=this.createSlidingWindowConfig(e);break}let i=new v__default.default(r);return i.on("error",s=>{console.error(`Rate limiter error for ${e.id}:`,s);}),i.on("failed",async s=>{console.warn(`Job failed in rate limiter ${e.id}:`,s);}),this.limiters.set(e.id,i),(e.tokensPerMinute||e.tokensPerHour)&&this.createTokenBucket(e),i}getLimiter(e){return this.limiters.get(e)}async schedule(e,t,r){let i=this.limiters.get(e);if(!i)throw new Error(`No rate limiter found with ID: ${e}`);let s={};return r!==void 0&&(s.priority=r),i.schedule(s,t)}async consumeTokens(e,t){let r=this.tokenBuckets.get(e);return r?r.consume(t):true}async getStats(e){let t=this.limiters.get(e);if(!t)return null;let r=await t.counts(),i=await t.currentReservoir();return {running:r.RUNNING,queued:r.QUEUED,done:r.DONE||0,failed:r.FAILED||0,reservoir:i}}async getAllStats(){let e={};for(let[t]of this.limiters){let r=await this.getStats(t);r&&(e[t]=r);}return e}async updateLimiter(e,t){let r=this.limiters.get(e);if(!r)throw new Error(`No rate limiter found with ID: ${e}`);let s={...await this.getLimiterConfig(e),...t,id:e};await r.stop(),this.limiters.delete(e),this.createLimiter(s);}async clearQueue(e){let t=this.limiters.get(e);t&&await t.stop({dropWaitingJobs:true});}async stopLimiter(e){let t=this.limiters.get(e);t&&(await t.stop(),this.limiters.delete(e));let r=this.tokenBuckets.get(e);r&&(r.stop(),this.tokenBuckets.delete(e));}async stopAll(){let e=[];for(let[t]of this.limiters)e.push(this.stopLimiter(t));await Promise.all(e);}createSlidingWindowConfig(e){let t=e.requestsPerMinute||60,r=Math.ceil(6e4/t);return {maxConcurrent:e.concurrent||5,minTime:r,highWater:Math.max(100,t*2),strategy:v__default.default.strategy.LEAK,rejectOnDrop:false}}createFixedWindowConfig(e){let t=e.requestsPerMinute||60;return {maxConcurrent:e.concurrent||5,reservoir:t,reservoirRefreshInterval:6e4,reservoirRefreshAmount:t,highWater:Math.max(100,t*2),strategy:v__default.default.strategy.LEAK}}createTokenBucketConfig(e){let t=e.requestsPerMinute||60,r=Math.ceil(t/60);return {maxConcurrent:e.concurrent||5,reservoir:t,reservoirRefreshInterval:1e3,reservoirRefreshAmount:r,highWater:Math.max(100,t*2),strategy:v__default.default.strategy.LEAK}}createTokenBucket(e){let t=new x(e);this.tokenBuckets.set(e.id,t);}async getLimiterConfig(e){return {requestsPerMinute:60,strategy:"sliding-window",concurrent:5}}},x=class{tokens;maxTokens;refillRate;lastRefill;interval;constructor(e){this.maxTokens=e.tokensPerMinute||1e5,this.tokens=this.maxTokens,this.refillRate=this.maxTokens/6e4,this.lastRefill=Date.now(),this.startRefillTimer();}consume(e){return this.refill(),this.tokens>=e?(this.tokens-=e,true):false}getAvailable(){return this.refill(),Math.floor(this.tokens)}refill(){let e=Date.now(),r=(e-this.lastRefill)*this.refillRate;this.tokens=Math.min(this.maxTokens,this.tokens+r),this.lastRefill=e;}startRefillTimer(){this.interval=setInterval(()=>{this.refill();},1e3);}stop(){this.interval&&clearInterval(this.interval);}};var R=class{config;constructor(e){this.config=e;}async execute(e,t,r){let i={...this.config,...r};return K__default.default(async s=>{try{return await e()}catch(n){let o=this.wrapError(n,t,s);throw this.shouldRetry(n,i)?(i.onRetry&&i.onRetry(o,s),o):new K.AbortError(o)}},{retries:i.maxAttempts-1,factor:i.backoff==="exponential"?2:1,minTimeout:i.baseDelay,maxTimeout:i.maxDelay,randomize:true,onFailedAttempt:s=>{console.warn(`Retry attempt ${s.attemptNumber} failed for ${t.operation}:`,s.message);}})}async executeWithBackoff(e,t,r){let i={...this.config,...r};try{return await exponentialBackoff.backOff(e,{numOfAttempts:i.maxAttempts,startingDelay:i.baseDelay,maxDelay:i.maxDelay,jitter:"full",timeMultiple:2,retry:(s,n)=>{let o=this.shouldRetry(s,i);return o&&i.onRetry&&i.onRetry(s,n),o}})}catch(s){throw this.wrapError(s,t,i.maxAttempts)}}wrapError(e,t,r){return new B__default.default({name:"AIProviderError",cause:e,info:{...t,attempt:r,timestamp:new Date().toISOString(),errorCode:e.code||e.status,errorType:this.categorizeError(e)}},`Failed to execute ${t.operation} on ${t.provider} (attempt ${r})`)}shouldRetry(e,t){if(t.shouldRetry)return t.shouldRetry(e);switch(this.categorizeError(e)){case "authentication":case "invalid_request":case "not_found":case "permission_denied":return false;case "rate_limit":return true;case "server_error":case "network":case "timeout":return true;default:return true}}categorizeError(e){let t=e.message?.toLowerCase()||"",r=e.code||e.status;return r===401||t.includes("unauthorized")||t.includes("api key")||t.includes("authentication")?"authentication":r===429||t.includes("rate limit")?"rate_limit":r===400||t.includes("invalid")||t.includes("validation")?"invalid_request":r===404||t.includes("not found")?"not_found":r===403||t.includes("forbidden")?"permission_denied":r>=500||t.includes("internal server")?"server_error":t.includes("network")||t.includes("econnrefused")||t.includes("enotfound")||t.includes("econnreset")?"network":t.includes("timeout")||t.includes("etimedout")||r==="ETIMEDOUT"?"timeout":"unknown"}wrap(e,t,r){return async(...i)=>this.execute(()=>e(...i),t,r)}updateConfig(e){this.config={...this.config,...e};}getConfig(){return {...this.config}}calculateDelay(e,t){let r={...this.config,...t},i;switch(r.backoff){case "exponential":i=Math.min(r.baseDelay*Math.pow(2,e-1),r.maxDelay);break;case "linear":i=Math.min(r.baseDelay*e,r.maxDelay);break;case "fixed":default:i=r.baseDelay;break}let s=i*.2*Math.random();return Math.floor(i+s)}getRetryStats(e){let t=this.categorizeError(e),r=this.shouldRetry(e,this.config),i=this.config.baseDelay;return t==="rate_limit"&&(i=this.config.baseDelay*2),{shouldRetry:r,errorType:t,suggestedDelay:i,maxAttempts:this.config.maxAttempts}}};var T=class{tokenLimits={"gpt-4":8192,"gpt-4-32k":32768,"gpt-4-turbo":128e3,"gpt-4-turbo-preview":128e3,"gpt-3.5-turbo":4096,"gpt-3.5-turbo-16k":16384,"claude-3-opus":2e5,"claude-3-sonnet":2e5,"claude-3-haiku":2e5,"claude-2.1":2e5,"claude-2":1e5,"gemini-pro":30720,"gemini-pro-vision":30720,"palm-2":8192,default:4096};modelPricing={"gpt-4":{input:.03,output:.06},"gpt-4-turbo":{input:.01,output:.03},"gpt-3.5-turbo":{input:5e-4,output:.0015},"claude-3-opus":{input:.015,output:.075},"claude-3-sonnet":{input:.003,output:.015},"claude-3-haiku":{input:25e-5,output:.00125},"gemini-pro":{input:5e-4,output:.0015},default:{input:0,output:0}};async countTokens(e,t){try{return t.includes("gpt")||t.includes("davinci")||t.includes("turbo")?this.countTokensWithTiktoken(e,t):gptTokenizer.encode(e).length}catch{return this.estimateTokens(e)}}countTokensWithTiktoken(e,t){try{let r=tiktoken.encoding_for_model(t),s=r.encode(e).length;return r.free(),s}catch{let r=tiktoken.get_encoding("cl100k_base"),s=r.encode(e).length;return r.free(),s}}estimateTokens(e){return Math.ceil(e.length/4)}async getTokenInfo(e,t,r){let i=await this.countTokens(e,t),s=r??this.tokenLimits[t]??this.tokenLimits.default??4096;return {count:i,truncated:i>s,originalLength:e.length}}async validateTokenLimits(e,t,r,i=1e3){let s=await this.countTokens(e,t),n=this.tokenLimits[t]??this.tokenLimits.default??4096,o=r??n,u=s+i<=o,m=Math.max(0,o-s);return {valid:u,availableTokens:m}}async truncateToTokenLimit(e,t,r,i=false){if(await this.countTokens(e,t)<=r)return e;let n=0,o=e.length,a="";for(;n<=o;){let u=Math.floor((n+o)/2),m=i?e.slice(e.length-u):e.slice(0,u);await this.countTokens(m,t)<=r?(a=m,n=u+1):o=u-1;}return i?"..."+a:a+"..."}async splitIntoChunks(e,t,r,i=0){let s=[],n=this.splitIntoSentences(e),o="",a=0;for(let u of n){let m=await this.countTokens(u,t);a+m>r&&o?(s.push(o.trim()),i>0?(o=await this.getOverlapText(o,t,i)+" "+u,a=await this.countTokens(o,t)):(o=u,a=m)):(o+=(o?" ":"")+u,a+=m);}return o&&s.push(o.trim()),s}splitIntoSentences(e){return e.match(/[^.!?]+[.!?]+/g)||[e]}async getOverlapText(e,t,r){let i=this.splitIntoSentences(e).reverse(),s="",n=0;for(let o of i){let a=await this.countTokens(o,t);if(n+a<=r)s=o+" "+s,n+=a;else break}return s.trim()}estimateCost(e,t,r="input"){let i=this.modelPricing[t]??this.modelPricing.default;return e/1e3*i[r]}getModelTokenLimit(e){return this.tokenLimits[e]??this.tokenLimits.default??4096}getAllModelLimits(){return {...this.tokenLimits}}async estimateConversationTokens(e,t){let r=0;for(let i of e)r+=await this.countTokens(`${i.role}: ${i.content}`,t),r+=4;return r}};var O=class{config;providers=new Map;cache;rateLimiter;retryManager;tokenManager;errorHandler;performanceMonitor;analytics;debug;constructor(e){this.debug=e.debug||false,this.config=new y(e),this.cache=new f({...this.config.getCacheConfig(),namespace:"ai-engine"}),this.rateLimiter=new k,this.retryManager=new R(this.config.getRetryConfig()),this.tokenManager=new T,this.errorHandler=new b,this.performanceMonitor=new h,this.analytics=new d,this.initializeProviders(),this.setupRateLimiters(),this.log("AI Engine initialized",{config:this.config.exportConfig()});}initializeProviders(){let e=this.config.getConfig().provider,t=this.config.getFallbackProviders(),r=[e,...t];for(let i of r)try{let s=this.createProvider(i);s&&(this.providers.set(i,s),this.log(`Provider initialized: ${i}`));}catch(s){this.log(`Failed to initialize provider: ${i}`,s);}}createProvider(e){let t=this.config.getProviderConfig(e);if(!t.apiKey&&e!=="mock"&&e!=="local")return this.log(`No API key for provider: ${e}`),null;let r={name:e,apiKey:t.apiKey,model:t.model,baseUrl:t.baseUrl,headers:t.headers,timeout:this.config.getConfig().timeout,maxRetries:this.config.getConfig().maxRetries};switch(e){case "openai":return new chunk6OKKVZHN_cjs.e(r);case "anthropic":return new chunk6OKKVZHN_cjs.b(r);case "google":return new chunk6OKKVZHN_cjs.c(r);case "mock":return new chunk6OKKVZHN_cjs.d(r);default:return null}}setupRateLimiters(){let e=this.config.getRateLimitConfig();for(let[t]of this.providers)this.rateLimiter.createLimiter({id:t,...e});}async getProvider(){let e=this.config.getConfig().provider,t=this.providers.get(e);if(t)return {provider:t,type:e};let r=this.config.getFallbackProviders();for(let i of r){let s=this.providers.get(i);if(s)return this.log(`Using fallback provider: ${i}`),{provider:s,type:i}}throw new Error("No available providers")}async executeOperation(e,t,r){let i=`${e}-${Date.now()}-${Math.random().toString(36).substr(2,9)}`;if(!r?.skipCache&&r?.cacheKey){let o=await this.cache.get(r.cacheKey);if(o!==null)return this.analytics.trackEvent({type:"cache_hit",provider:"cache",operation:e}),o}let{provider:s,type:n}=await this.getProvider();this.performanceMonitor.startOperation(i,e,n);try{if(r?.estimatedTokens&&!await this.rateLimiter.consumeTokens(n,r.estimatedTokens))throw new Error("Token limit exceeded");let o=await this.rateLimiter.schedule(n,()=>this.retryManager.execute(()=>t(s),{provider:n,operation:e})),a=this.performanceMonitor.endOperation(i,!0);return this.analytics.trackEvent({type:"success",provider:n,operation:e,model:this.config.getModel(n),latency:a?.duration}),!r?.skipCache&&r?.cacheKey&&await this.cache.set(r.cacheKey,o),o}catch(o){let a=this.errorHandler.handleError(o,{provider:n,operation:e});throw this.performanceMonitor.endOperation(i,false,a.message),this.analytics.trackEvent({type:"error",provider:n,operation:e,error:a.message}),a}}async generateText(e,t){let r=this.cache.createTextGenerationKey(e,t,this.config.getConfig().provider,this.config.getModel()),i=await this.tokenManager.countTokens(e,this.config.getModel()||"gpt-3.5-turbo"),s=await this.executeOperation("generateText",u=>u.generateText(e,t),{cacheKey:r,estimatedTokens:i,skipCache:t?.stream}),n=await this.tokenManager.countTokens(s,this.config.getModel()||"gpt-3.5-turbo"),o={promptTokens:i,completionTokens:n,totalTokens:i+n},a=this.tokenManager.estimateCost(o.promptTokens,this.config.getModel()||"gpt-3.5-turbo","input")+this.tokenManager.estimateCost(o.completionTokens,this.config.getModel()||"gpt-3.5-turbo","output");return this.analytics.trackEvent({type:"success",provider:this.config.getConfig().provider,operation:"generateText",model:this.config.getModel(),tokens:{prompt:o.promptTokens,completion:o.completionTokens,total:o.totalTokens},cost:a}),s}async*generateStream(e,t){let{provider:r,type:i}=await this.getProvider();if(!r.generateStream)throw new Error(`Provider ${i} does not support streaming`);let s=`generateStream-${Date.now()}`;this.performanceMonitor.startOperation(s,"generateStream",i);try{yield*r.generateStream(e,t),this.performanceMonitor.endOperation(s,!0),this.analytics.trackEvent({type:"success",provider:i,operation:"generateStream",model:this.config.getModel(i)});}catch(n){throw this.performanceMonitor.endOperation(s,false,n.message),this.analytics.trackEvent({type:"error",provider:i,operation:"generateStream",error:n.message}),n}}async generateEmbedding(e){let t=this.cache.createEmbeddingKey(e,this.config.getConfig().provider,this.config.getModel());return this.executeOperation("generateEmbedding",r=>r.generateEmbedding(e),{cacheKey:t})}async classifyText(e,t){let r=this.cache.generateKey("classifyText",[e,t]);return this.executeOperation("classifyText",i=>i.classifyText(e,t),{cacheKey:r})}async summarize(e,t){let r=this.cache.generateKey("summarize",[e,t]);return this.executeOperation("summarize",i=>i.summarize(e,t),{cacheKey:r})}async generateImage(e,t){return this.executeOperation("generateImage",r=>r.generateImage(e,t))}async transcribeAudio(e,t){return this.executeOperation("transcribeAudio",r=>r.transcribeAudio(e,t))}async generateSpeech(e,t){return this.executeOperation("generateSpeech",r=>r.generateSpeech(e,t))}async generateCode(e,t){return this.executeOperation("generateCode",r=>r.generateCode(e,t))}async updateConfig(e){this.config.updateConfig(e),this.initializeProviders(),this.setupRateLimiters(),this.log("Configuration updated",{config:this.config.exportConfig()});}getStats(){return {usage:this.analytics.getStats(),performance:this.performanceMonitor.getStats(),cache:this.cache.getStats(),rateLimiter:this.rateLimiter.getAllStats(),errors:this.errorHandler.getErrorStats(),health:this.performanceMonitor.getHealthStatus()}}async reset(){await this.cache.clear(),this.analytics.reset(),this.performanceMonitor.clearHistory(),this.errorHandler.clearHistory(),this.log("AI Engine reset");}log(e,t){this.debug&&console.log(`[AI Engine] ${e}`,t||"");}exportConfig(){return this.config.exportConfig()}getAvailableProviders(){return Array.from(this.providers.keys())}};exports.a=d;exports.b=h;exports.c=f;exports.d=I;exports.e=L;exports.f=z;exports.g=P;exports.h=y;exports.i=b;exports.j=k;exports.k=R;exports.l=T;exports.m=O;//# sourceMappingURL=chunk-ZACX7RDK.cjs.map //# sourceMappingURL=chunk-ZACX7RDK.cjs.map