import OpenAI from 'openai';
import { TotemConfigError, TotemError } from '../errors.js';
const MAX_BATCH_SIZE = 2048;
const DEFAULT_DIMENSIONS = 1536;
const MAX_RETRIES = 3;
const INITIAL_BACKOFF_MS = 1000;
export class OpenAIEmbedder {
    dimensions;
    client;
    model;
    constructor(model = 'text-embedding-3-small', dimensions) {
        this.model = model;
        this.dimensions = dimensions ?? DEFAULT_DIMENSIONS;
        const apiKey = process.env['OPENAI_API_KEY'];
        if (!apiKey) {
            throw new TotemConfigError('No OpenAI API key found.', "Set OPENAI_API_KEY in your .env or configure provider: 'ollama' in totem.config.ts.", 'CONFIG_MISSING');
        }
        this.client = new OpenAI({ apiKey });
    }
    async embed(texts) {
        if (texts.length === 0)
            return [];
        const results = [];
        for (let i = 0; i < texts.length; i += MAX_BATCH_SIZE) {
            const batch = texts.slice(i, i + MAX_BATCH_SIZE);
            const response = await this.embedWithRetry(batch);
            const sorted = response.data.sort((a, b) => a.index - b.index);
            for (const item of sorted) {
                results.push(item.embedding);
            }
        }
        return results;
    }
    async embedWithRetry(batch) {
        let lastErr;
        for (let attempt = 0; attempt <= MAX_RETRIES; attempt++) {
            try {
                return await this.client.embeddings.create({
                    model: this.model,
                    input: batch,
                });
            }
            catch (err) {
                lastErr = err;
                const isRetryable = err instanceof OpenAI.APIError && (err.status === 429 || err.status === 503);
                if (!isRetryable || attempt === MAX_RETRIES)
                    break;
                const delay = INITIAL_BACKOFF_MS * 2 ** attempt + Math.random() * 1000;
                await new Promise((resolve) => setTimeout(resolve, delay));
            }
        }
        const detail = lastErr instanceof Error ? lastErr.message : String(lastErr);
        throw new TotemError('EMBEDDING_UNAVAILABLE', `OpenAI embedding failed after ${MAX_RETRIES + 1} attempts: ${detail}`, 'Check your OPENAI_API_KEY and network connection, then retry with `totem sync`.');
    }
}
//# sourceMappingURL=openai-embedder.js.map