/**
 * sdk-client.ts — thin wrapper over `@anthropic-ai/claude-agent-sdk`'s
 * `query()` for `olam ask`.
 *
 * Auth model (per repo CLAUDE.md, Decision D15): the Claude Agent SDK consumes
 * the operator's LOCAL Claude Code subscription via stdio/IPC. It is NOT an
 * `api.anthropic.com` HTTPS caller, so it is EXEMPT from `audit:auth-callers`
 * and the `withCredential` helper-or-die rule. Nothing in this file references
 * `api.anthropic.com`; the operator pays $0 incremental on top of their
 * existing Claude Code login.
 *
 * The SDK is imported via dynamic `import()` so a missing / unbuilt SDK (or a
 * Claude Code that isn't logged in) degrades to a clear, actionable error
 * rather than a hard module-load crash (Rule 12 — fail loud, not cryptic).
 *
 * The model is pinned to `claude-sonnet-4-6` — the locked decision for this
 * feature. `olam ask` is a fast Q&A surface, not a deep-reasoning loop.
 */
/** Pinned model for `olam ask`. Locked decision — do not change without sign-off. */
export const ASK_MODEL = 'claude-sonnet-4-6';
/** Error thrown when the Agent SDK / local Claude Code is unavailable. */
export class AskSdkUnavailableError extends Error {
    cause;
    constructor(message, cause) {
        super(message);
        this.cause = cause;
        this.name = 'AskSdkUnavailableError';
    }
}
/** Read-only tool allowlist used when running inside a checkout. */
const READ_ONLY_TOOLS = ['Read', 'Grep', 'Glob'];
/**
 * Resolve the SDK's `query` function, mapping any import failure to a
 * domain error with an actionable message. Exported for the degradation test.
 */
export async function resolveQueryFn(injected) {
    if (injected)
        return injected;
    try {
        // Dynamic import: a missing/unbuilt SDK must not crash module load.
        const mod = (await import('@anthropic-ai/claude-agent-sdk'));
        if (typeof mod.query !== 'function') {
            throw new Error('SDK loaded but `query` export is missing');
        }
        return mod.query;
    }
    catch (err) {
        throw new AskSdkUnavailableError([
            'olam ask needs the Claude Agent SDK backed by a logged-in Claude Code.',
            '',
            'Fix:',
            '  1. Install Claude Code:  https://docs.claude.com/claude-code',
            '  2. Log in:               run `claude` once and complete login',
            '  3. Retry:                olam ask "<your question>"',
            '',
            'olam ask uses your local Claude subscription (Sonnet) — no extra API cost.',
        ].join('\n'), err);
    }
}
/**
 * Build the `query()` options object. Pinned model + the system-prompt append
 * on the Claude Code preset. Read-only tools enabled only inside a checkout;
 * otherwise an empty allowlist (no filesystem access). Exported so the
 * options shape is snapshot-testable (Rule 9 — a regression that unpinned the
 * model or dropped the system prompt would slip past behaviour tests).
 */
export function buildAskQueryOptions(opts) {
    return {
        model: ASK_MODEL,
        systemPrompt: {
            type: 'preset',
            preset: 'claude_code',
            append: opts.systemPromptAppend,
        },
        // Inside a checkout → read-only tools so the model can pull live files.
        // Outside → empty allowlist = zero tools (pack-only answers).
        allowedTools: opts.repoRoot ? READ_ONLY_TOOLS : [],
        ...(opts.repoRoot ? { cwd: opts.repoRoot } : {}),
        thinking: { type: 'disabled' },
    };
}
/**
 * Extract the assistant's visible text from an SDK message. Returns '' for
 * non-text messages (system / result / tool-use). Exported for the unit test
 * that asserts text aggregation across content blocks.
 */
export function extractAssistantText(msg) {
    if (msg.type !== 'assistant' || !msg.message?.content)
        return '';
    return msg.message.content
        .filter((b) => b.type === 'text' && typeof b.text === 'string')
        .map((b) => b.text)
        .join('');
}
/**
 * Run one prompt through the SDK and return the aggregated assistant text.
 * Streams via the optional `onText` callback so the REPL/one-shot can print
 * incrementally. Throws {@link AskSdkUnavailableError} when the SDK can't be
 * resolved, or the underlying error if the SDK itself fails mid-stream.
 */
export async function askOnce(prompt, opts, onText) {
    const query = await resolveQueryFn(opts.queryFn);
    const options = buildAskQueryOptions(opts);
    let answer = '';
    const stream = query({ prompt, options });
    for await (const msg of stream) {
        if (msg.type === 'result' && msg.is_error) {
            throw new Error(`Claude Agent SDK returned an error result${msg.subtype ? ` (${msg.subtype})` : ''}.`);
        }
        const text = extractAssistantText(msg);
        if (text) {
            answer += text;
            onText?.(text);
        }
    }
    return answer;
}
//# sourceMappingURL=sdk-client.js.map