import { AbortablePromise, Ai } from './ai.ts'; import { LLMProvider } from './provider.ts'; import { AiTool, AiToolArg } from './tools.ts'; import { Memory, MemoryCache, MemoryOptions } from './memory.ts'; export type AnthropicConfig = { proto: 'anthropic'; token: string | string[]; }; export type OpenAiConfig = { proto: 'openai'; host?: string; token: string | string[]; }; export type AgentRef = { name: string; description?: string; delegate?: boolean; fn: () => Agent | null | Promise; }; export type Agent = { name: string; description?: string; model?: string | null; temperature?: number; system: string; delegate?: boolean; skills?: Skill[] | null; tools?: AiTool[] | null; mcp?: McpServer[] | null; agents?: AgentRef[] | null; }; export type LLMFile = { /** Path to file on disk */ path?: string; /** File content: raw text, base64-encoded binary, or a Buffer */ content?: string | Buffer; /** Original filename, used to infer type from extension */ name?: string; /** Mime type override, inferred from extension if omitted */ mime?: string; /** @internal set once extraction has run, skips re-processing next turn */ extracted?: boolean; }; export type LLMMessage = { /** Message originator */ role: 'assistant' | 'system' | 'user'; /** Message content */ content: string | any; /** Files attached to request */ files?: LLMFile[]; /** Timestamp */ timestamp?: number; /** Response duration in ms */ duration?: number; /** Tokens per second */ tps?: number; } | { /** Tool call */ role: 'tool'; /** Unique ID for call */ id: string; /** Tool that was run */ name: string; /** Tool arguments */ args: any; /** Tool result */ content: undefined | string; /** Tool error */ error?: undefined | string; /** Timestamp */ timestamp?: number; /** Response duration in ms */ duration?: number; /** Tokens per second */ tps?: number; }; export type LLMRequest = { /** Return a parsed JSON object that matches the schema */ schema?: AiToolArg; /** System prompt */ system?: string; /** Message history */ history?: LLMMessage[]; /** Max tokens for request */ maxTokens?: number; /** 0 = Rigid Logic, 1 = Balanced, 2 = Hyper Creative **/ temperature?: number; /** Available tools */ tools?: AiTool[]; /** LLM model */ model?: string; /** Stream response */ stream?: (chunk: { text?: string; tool?: string; done?: true; }) => any; /** Compress old messages in the chat to free up context */ compress?: { max: number; min: number; }; /** User's memory documents - RAG injected automatically each turn */ memory?: Memory[] | MemoryCache | MemoryOptions; /** Model to use for memory operations */ memoryModel?: string; /** Skill documents the AI can browse and read on demand */ skills?: Skill[]; /** MCP servers to connect and expose as tools */ mcp?: McpServer[]; /** Subagents exposed as delegatable/wrapped tools, resolved lazily via their `fn` */ agents?: AgentRef[]; /** Attach files to request */ files?: LLMFile[]; /** @internal recursion guard for nested agent delegation */ _agentDepth?: number; }; export type McpServer = { /** MCP server name for humans */ name: string; /** Host URL */ host: string; /** Server access token */ token?: string; }; export type Skill = { /** Name of skill for humans */ name: string; /** Description LLM will use to decide to learn a skill */ description: string; /** Skill instructions */ content: string; }; declare class LLM { readonly ai: Ai; private static AUDIO_EXT; private static IMAGE_EXT; private static TEXT_EXT; private static PDF_EXT; private memoryManager; defaultModel: string; models: { [model: string]: LLMProvider; }; constructor(ai: Ai); private loadBuffer; private writeTemp; /** * Extract text from a PDF. Pages with no text layer (scanned/image-only) are handled as either: * - Rendered to images and returned alongside the text so the (vision-capable) model can read them directly * - OCR'd via Tesseract when the doc is too large to reasonably pass as images */ private resolvePdf; private resolveFile; private resolveFiles; private setupAgent; private setupMcp; private setupSkills; private wrapToolTiming; ask(message: string, options?: LLMRequest): AbortablePromise; /** * Compress chat history to reduce context size * @param {LLMMessage[]} history Chatlog that will be compressed * @param max Trigger compression once context is larger than max * @param min Leave messages less than the token minimum, summarize the rest * @param {LLMRequest} options LLM options * @returns {Promise} New chat history will summary at index 0 */ compressHistory(history: LLMMessage[], max: number, min: number, options?: LLMRequest): Promise; /** * Compare the difference between embeddings (calculates the angle between two vectors) * @param {number[]} v1 First embedding / vector comparison * @param {number[]} v2 Second embedding / vector for comparison * @returns {number} Similarity values 0-1: 0 = unique, 1 = identical */ cosineSimilarity(v1: number[], v2: number[]): number; /** * Chunk text into parts for AI digestion * @param {object | string} target Item that will be chunked (objects get converted) * @param {number} maxTokens Chunking size. More = better context, less = more specific (Search by paragraphs or lines) * @param {number} overlapTokens Includes previous X tokens to provide continuity to AI (In addition to max tokens) * @returns {string[]} Chunked strings */ chunk(target: object | string, maxTokens?: number, overlapTokens?: number): string[]; /** * Create a vector representation of a string * @param {object | string} target Item that will be embedded (objects get converted) * @param {maxTokens?: number, overlapTokens?: number} opts Options for embedding such as chunk sizes * @returns {Promise[]>} Chunked embeddings */ embedding(target: object | string, opts?: { maxTokens?: number; overlapTokens?: number; }): AbortablePromise<{ index: number; embedding: number[]; text: string; tokens: number; }[]>; /** * Estimate variable as tokens * @param history Object to size * @returns {number} Rough token count */ estimateTokens(history: any): number; /** * Compare the difference between two strings using tensor math * @param target Text that will be checked * @param {string} searchTerms Multiple search terms to check against target * @returns {{avg: number, max: number, similarities: number[]}} Similarity values 0-1: 0 = unique, 1 = identical */ fuzzyMatch(target: any, ...searchTerms: any[]): { avg: number; max: number; similarities: number[]; }; /** * Digest full conversation history into memory documents. * Call on session end to persist the conversation. */ memorize(history: LLMMessage[], memories: Memory[] | MemoryCache, options?: LLMRequest): Promise; /** * Create a summary of some text * @param {string} text Text to summarize * @param {number} length Max number of words * @param options LLM request options * @returns {Promise} Summary */ summarize(text: string, length?: number, options?: LLMRequest): Promise; addModel(name: string, config: AnthropicConfig | OpenAiConfig, setDefault?: boolean): void; removeModel(name: string): void; setModels(models: { [model: string]: AnthropicConfig | OpenAiConfig; }, replace?: boolean): void; } export default LLM;