/**
 * Port: LLM access for non-grader features.
 *
 * Adapters wrap a vendor REST API and centralize retry, rate-limit handling,
 * cost calculation, and observability. Features call this port instead of
 * importing the grader's internals or a vendor SDK directly.
 *
 * The grader path (`packages/eval/src/pipeline/grader-api.ts`) is intentionally
 * NOT migrated here — D0051 defers grader migration as a follow-up.
 *
 * @see docs/decisions/D0051-llm-client-port.md
 */
import { err, ok, } from "../types/branded-ids.js";
/**
 * Parse a raw string into a `ParsedModelId`. Returns `Result` — never throws.
 *
 * Recognized prefixes:
 * - `openai:<modelName>` or `openai:<sub>:<modelName>` (e.g. `"openai:chat:gpt-5"`)
 * - `anthropic:<modelName>` or `anthropic:messages:<modelName>`
 */
export function parseModelId(raw) {
    const parts = raw.split(":");
    if (parts.length < 2 || parts[0] === "" || parts.some((p) => p === "")) {
        return err({
            code: "INVALID_MODEL_ID",
            raw,
            message: `Invalid ModelId "${raw}": expected "<provider>:<modelName>" with non-empty segments`,
        });
    }
    const provider = parts[0];
    if (provider === "openai") {
        const modelName = parts.length >= 3 ? parts.slice(2).join(":") : parts.slice(1).join(":");
        return ok({ id: raw, provider, modelName });
    }
    if (provider === "anthropic") {
        const modelName = parts.length >= 3 && parts[1] === "messages"
            ? parts.slice(2).join(":")
            : parts.slice(1).join(":");
        return ok({ id: raw, provider, modelName });
    }
    return err({
        code: "INVALID_MODEL_ID",
        raw,
        message: `Invalid ModelId "${raw}": unknown provider "${provider}". Supported: openai, anthropic.`,
    });
}
/**
 * Throwing constructor — convenient for known-good inputs (config files,
 * tests). Throws if the id is malformed; use `parseModelId` for untrusted
 * input.
 */
export function modelId(raw) {
    const result = parseModelId(raw);
    if (!result.ok)
        throw new Error(result.error.message);
    return result.value.id;
}
/**
 * Extract `provider` + `modelName` from an already-branded `ModelId`. Assumes
 * the id was produced by `parseModelId` / `modelId` and is therefore valid;
 * if it isn't, the caller's bug surfaces as a thrown `Error`.
 */
export function splitModelId(id) {
    const result = parseModelId(id);
    if (!result.ok)
        throw new Error(result.error.message);
    return result.value;
}
