import { readFile } from "node:fs/promises";
import { resolve } from "node:path";
import { homedir } from "node:os";
const HAIKU_MODEL = "claude-haiku-4-5-20251001";
const API_URL = "https://api.anthropic.com/v1/messages";
const API_VERSION = "2023-06-01";
const REQUEST_TIMEOUT_MS = 15_000;
// ---------------------------------------------------------------------------
// API key resolution — reads ~/.maxy/.anthropic-api-key
// Same pattern as admin MCP (api-key-verify).
// ---------------------------------------------------------------------------
export async function resolveApiKey() {
    const keyPath = resolve(homedir(), ".maxy", ".anthropic-api-key");
    let raw;
    try {
        raw = await readFile(keyPath, "utf-8");
    }
    catch {
        throw new Error(`No Anthropic API key file at ${keyPath}. Run the get-api-key skill to set one up.`);
    }
    const key = raw.trim();
    if (!key) {
        throw new Error(`Anthropic API key file at ${keyPath} is empty. Store a valid key with api-key-store.`);
    }
    return key;
}
/**
 * Send a conversation transcript to Haiku and extract structured lead data.
 * Returns null if no email is found in the conversation.
 * Throws on API or parse errors (caller handles via try/catch).
 */
export async function extractFromConversation(messages, apiKey) {
    const transcript = messages.join("\n");
    const res = await fetch(API_URL, {
        method: "POST",
        headers: {
            "Content-Type": "application/json",
            "x-api-key": apiKey,
            "anthropic-version": API_VERSION,
        },
        body: JSON.stringify({
            model: HAIKU_MODEL,
            max_tokens: 1024,
            system: "You extract contact details and customer discovery intelligence from a visitor's chat messages. " +
                "Return ONLY a JSON object with these fields:\n" +
                '- "email": the visitor\'s email address, or null if none given\n' +
                '- "givenName": the visitor\'s first/given name, or null if unclear\n' +
                '- "familyName": the visitor\'s last/family name, or null if unclear\n' +
                '- "businessType": what kind of business they run or work in (e.g. "estate agency", "accounting firm"), or null\n' +
                '- "role": their role or position (e.g. "owner", "marketing manager"), or null\n' +
                '- "needs": what they need or are looking for, in their own words where possible, or null\n' +
                '- "challenges": pain points or challenges they mentioned, or null\n' +
                '- "interests": specific features, capabilities, or topics they asked about or expressed interest in, or null\n' +
                '- "engagementQuality": one of "high" (asked detailed questions, shared specifics about their situation), "medium" (some back-and-forth, showed genuine interest), or "low" (brief, noncommittal), or null\n' +
                '- "otherSignals": any other noteworthy signal — e.g. timeline urgency, competitor mentions, referral source, or null\n' +
                "Only include fields where the visitor actually revealed information. " +
                "Return valid JSON only. No markdown, no explanation.",
            messages: [
                {
                    role: "user",
                    content: `Extract the visitor's contact details and discovery intelligence from these chat messages:\n\n${transcript}`,
                },
            ],
        }),
        signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS),
    });
    if (!res.ok) {
        const body = await res.text().catch(() => "");
        throw new Error(`Anthropic API returned ${res.status}: ${body.slice(0, 200)}`);
    }
    const apiResponse = (await res.json());
    const text = apiResponse.content
        ?.filter((b) => b.type === "text")
        .map((b) => b.text ?? "")
        .join("");
    if (!text) {
        throw new Error("Haiku returned empty content");
    }
    // Strip markdown code fences if Haiku wraps the JSON despite instructions
    const cleaned = text
        .replace(/^```json?\s*/i, "")
        .replace(/\s*```\s*$/i, "")
        .trim();
    const parsed = JSON.parse(cleaned);
    if (!parsed.email || typeof parsed.email !== "string")
        return null;
    const email = parsed.email.trim().toLowerCase();
    if (!email.includes("@"))
        return null;
    // Validate the email actually appears in the source messages.
    // Guards against hallucination — if Haiku invents an email not in the
    // conversation, we skip rather than create a spurious Person node.
    const joined = messages.join(" ").toLowerCase();
    if (!joined.includes(email))
        return null;
    const givenName = typeof parsed.givenName === "string"
        ? parsed.givenName.trim() || null
        : null;
    const familyName = typeof parsed.familyName === "string"
        ? parsed.familyName.trim() || null
        : null;
    const str = (v) => typeof v === "string" && v.trim() ? v.trim() : null;
    const notes = {
        businessType: str(parsed.businessType),
        role: str(parsed.role),
        needs: str(parsed.needs),
        challenges: str(parsed.challenges),
        interests: str(parsed.interests),
        engagementQuality: str(parsed.engagementQuality),
        otherSignals: str(parsed.otherSignals),
    };
    const hasAnyNote = Object.values(notes).some((v) => v !== null);
    return { email, givenName, familyName, discoveryNotes: hasAnyNote ? notes : null };
}
//# sourceMappingURL=anthropic.js.map