UNPKG

ai-cant-even

Version:

A satirical AI-powered utility that's confidently wrong about basic math operations

314 lines (274 loc) 9.2 kB
import { AiCantEvenConfig, Confidence, Logic, PromptParams, Provider } from './types'; import { AiSdkClient } from './ai-sdk-client'; /** * Default configuration for the AI */ const DEFAULT_CONFIG: AiCantEvenConfig = { confidence: Confidence.OVERWHELMED, logic: Logic.SIMPLE, }; /** * Main class for the AI that can't even determine if numbers are even */ export class AiCantEven { // Default configuration values private confidence: Confidence; private logic: Logic; private provider?: Provider; private model?: string; private apiKey?: string; private apiEndpoint?: string; private aiSdkClient?: AiSdkClient; // Temporary values for method chaining private tempConfidence?: Confidence; private tempLogic?: Logic; private tempModel?: string; /** * Create a new AI that can't even * @param config - Configuration options */ constructor(config: AiCantEvenConfig = {}) { this.confidence = config.confidence || DEFAULT_CONFIG.confidence!; this.logic = config.logic || DEFAULT_CONFIG.logic!; // Set model, API key and endpoint from config this.model = config.model; this.apiKey = config.apiKey; this.apiEndpoint = config.apiEndpoint; // Set provider from config or default this.provider = config.provider || DEFAULT_CONFIG.provider; // Initialize client if provider is available this.initializeClients(); } /** * Initialize client based on provider and API key */ private initializeClients(): void { // Only initialize if we have a provider and API key if (this.provider && this.apiKey) { this.aiSdkClient = new AiSdkClient(this.provider, this.apiKey, this.apiEndpoint, this.model); } } /** * Set the confidence level for the AI * @param confidence - The confidence level * @returns The AI instance for method chaining */ withConfidence(confidence: Confidence): AiCantEven { // Set temporary confidence for the next operation this.tempConfidence = confidence; return this; } /** * Set the model for the next operation */ public withModel(model: string): AiCantEven { this.tempModel = model; return this; } /** * Set the logic type for the AI * @param logic - The logic type * @returns The AI instance for method chaining */ withLogic(logic: Logic): AiCantEven { // Set temporary logic for the next operation this.tempLogic = logic; return this; } /** * Set the API key for the LLM * @param apiKey - The API key * @param apiEndpoint - Optional custom API endpoint * @returns The AI instance for method chaining */ withApiKey(apiKey: string, apiEndpoint?: string): AiCantEven { this.apiKey = apiKey; if (apiEndpoint) { this.apiEndpoint = apiEndpoint; } // Re-initialize client with new API key this.initializeClients(); return this; } /** * Get the current confidence level (temporary or default) */ private getCurrentConfidence(): Confidence { return this.tempConfidence !== undefined ? this.tempConfidence : this.confidence; } /** * Get the current logic type (temporary or default) */ private getCurrentLogic(): Logic { return this.tempLogic !== undefined ? this.tempLogic : this.logic; } /** * Get the current model (temporary or permanent) */ private getCurrentModel(): string | undefined { return this.tempModel || this.model; } /** * Reset temporary settings after an operation */ private resetTemporarySettings(): void { this.tempConfidence = undefined; this.tempLogic = undefined; this.tempModel = undefined; } /** * Generate a response using the LLM or fallback to hardcoded responses */ private async generateResponse( operation: string, value: number, comparisonValue?: number, ): Promise<string> { try { // Get current model for this operation const currentModel = this.getCurrentModel(); // If no client is available, use hardcoded responses if (!this.aiSdkClient) { return this.generateFallbackResponse(operation, value); } const params: PromptParams = { confidence: this.getCurrentConfidence(), logic: this.getCurrentLogic(), operation, value, comparisonValue, }; // Use AI SDK client to generate response const response = await this.aiSdkClient.generateResponse(params); return response.text; } finally { // Always reset temporary settings after generating a response this.resetTemporarySettings(); } } /** * Generate a fallback response when no LLM client is available */ private generateFallbackResponse(operation: string, value: number): string { const operationResponses = [ `I can't even process ${value} right now. Numbers are just, like, so abstract?`, `Error 418: I'm a teapot, not a calculator. But I'm pretty sure the answer is purple.`, `My neural networks are taking a coffee break. Try asking a human, they're terrible at math too.`, ]; return operationResponses[Math.floor(Math.random() * operationResponses.length)]; } /** * Determine if a number is even (but not really) * @param value - The number to check * @returns A hilariously wrong explanation */ async isEven(value: number): Promise<string> { return this.generateResponse('isEven', value); } /** * Determine if a number is odd (but not really) * @param value - The number to check * @returns A hilariously wrong explanation */ async isOdd(value: number): Promise<string> { return this.generateResponse('isOdd', value); } /** * Determine if a number is greater than another (but not really) * @param value - The first number * @param comparisonValue - The second number * @returns A hilariously wrong explanation */ async isGreaterThan(value: number, comparisonValue: number): Promise<string> { return this.generateResponse('isGreaterThan', value, comparisonValue); } /** * Determine if a number is less than another (but not really) * @param value - The first number * @param comparisonValue - The second number * @returns A hilariously wrong explanation */ async isLessThan(value: number, comparisonValue: number): Promise<string> { return this.generateResponse('isLessThan', value, comparisonValue); } /** * Determine if two numbers are equal (but not really) * @param value - The first number * @param comparisonValue - The second number * @returns A hilariously wrong explanation */ async areEqual(value: number, comparisonValue: number): Promise<string> { return this.generateResponse('areEqual', value, comparisonValue); } /** * Determine if a number is prime (but not really) * @param value - The number to check * @returns A hilariously wrong explanation */ async isPrime(value: number): Promise<string> { return this.generateResponse('isPrime', value); } /** * Determine if a number is positive (but not really) * @param value - The number to check * @returns A hilariously wrong explanation */ async isPositive(value: number): Promise<string> { return this.generateResponse('isPositive', value); } /** * Determine if a number is divisible by another (but not really) * @param value - The first number * @param comparisonValue - The second number * @returns A hilariously wrong explanation */ async isDivisibleBy(value: number, comparisonValue: number): Promise<string> { return this.generateResponse('isDivisibleBy', value, comparisonValue); } /** * Determine if a value is a number (but not really) * @param value - The value to check * @returns A hilariously wrong explanation */ // eslint-disable-next-line @typescript-eslint/no-explicit-any async isNumber(value: any): Promise<string> { return this.generateResponse('isNumber', Number(value)); } /** * Determine if a number is an integer (but not really) * @param value - The number to check * @returns A hilariously wrong explanation */ async isInteger(value: number): Promise<string> { return this.generateResponse('isInteger', value); } } /** * Create a new AI that can't even * @param config - Configuration options * @returns A new AI instance */ export function aiCantEven(config: AiCantEvenConfig = {}): AiCantEven { // If the provider and API key are provided, initialize the client if (config.provider && config.apiKey) { return new AiCantEven(config); } // If API key is in the environment, use it based on provider if (process.env.ANTHROPIC_API_KEY) { return new AiCantEven({ ...config, provider: Provider.ANTHROPIC, apiKey: process.env.ANTHROPIC_API_KEY, }); } else if (process.env.OPENAI_API_KEY) { return new AiCantEven({ ...config, provider: Provider.OPENAI, apiKey: process.env.OPENAI_API_KEY, }); } // Else return default config return new AiCantEven(config); } // Export types and enums export { Confidence, Logic, Provider, AiCantEvenConfig } from './types';