/**
 * prototype-gen-launch.ts — thin host-side launcher for the prototype-gen
 * driver (producer plan §6, P3 mechanism — Option B).
 *
 * HOST_DRIVER_CONTRACT (inherited from `host-driver-launch.ts`): this module
 * ONLY overrides the launch path — every agent-logic decision delegates to
 * `runDriver()` in driver-runner.ts. It defaults `systemPromptAppend` to the
 * prototype-gen persona, widens `extraAllowedTools` with the prototype tools,
 * and installs a lineage-pinned `allocateMessageId` so revisions of one
 * prototype collapse under a single `message_id` (locked Q2 — render side keys
 * supersession on `message_id`). Adding agent-logic branches here is a
 * code-smell; extend `DriverRunnerOptions` instead.
 *
 * Mirrors `launchHostDriver`: the caller owns SDK construction (`sdkQuery`),
 * keeping this launcher sync and the SDK import out of the load graph.
 *
 * Scope (Option B, smallest blast radius): this is a launcher FUNCTION, not a
 * dispatch-config schema change. The first-class `olam dispatch --mode
 * prototype-gen` ergonomics (Option C) + host token pre-ingest/publish are
 * gated follow-ups (producer plan §6/§7 P3-P4) — this file wires the prompt,
 * tools, and lineage allocator that those phases build on.
 *
 * Producer plan: docs/plans/prototype-gen-producer/plan.md §1, §4, §6, §7.
 * Prompt spec:   docs/plans/prototype-gen-prompt-spec/plan.md §3, §9.
 */
import { makeLineageMessageIdAllocator } from '@olam/core/src/prototype/lineage-message-id-allocator.js';
import { buildPrototypeGenSystemPrompt } from '../prompts/prototype-gen-agent.js';
import { PROTOTYPE_GEN_TOOLS } from '../prompts/prototype-gen-agent.js';
import { runDriver, } from './driver-runner.js';
/**
 * The tool patterns the prototype-gen driver adds to the `allowedTools`
 * allowlist. The agent emits prototypes + style guides via these two tools;
 * the SDK surfaces them as `tool_use` blocks that the adapter persists as
 * `prototype` / `style_guide` chunks (zero adapter changes — producer plan §0).
 *
 * Derived from `PROTOTYPE_GEN_TOOLS` so the allowlist can never drift from the
 * tool definitions.
 */
export const PROTOTYPE_GEN_EXTRA_ALLOWED_TOOLS = PROTOTYPE_GEN_TOOLS.map((t) => t.name);
/**
 * Normalize a prototype title into a lineage key. Lowercase + collapse internal
 * whitespace + trim, so cosmetic title variation ("Primary CTA button" vs
 * "primary  cta  button") does not fork a lineage. Per Q-A (operator-gated):
 * the title keys the lineage WITHIN a single bounded dispatch — collisions are
 * the operator's own naming, low-stakes — NOT a global identity.
 */
export function normalizeLineageKey(title) {
    return title.trim().toLowerCase().replace(/\s+/g, ' ');
}
/**
 * Build a dispatch-scoped lineage allocator. Pure: the only state is the
 * in-memory title→root map, which lives for the dispatch's lifetime.
 */
export function makePrototypeLineageAllocator(options = {}) {
    const dispatchPrefix = options.dispatchPrefix ?? `proto-${Math.random().toString(36).slice(2) || '0'}`;
    const nonceSource = options.nonceSource ?? (() => Math.random().toString(36).slice(2) || '0');
    const clock = options.clock ?? (() => Date.now());
    // lineageKey → lineageRoot. Same title reuses the recorded root; a new title
    // mints a fresh one via the core per-lineage allocator.
    const lineages = new Map();
    let untitledCounter = 0;
    function mintRoot(seed) {
        // Anchor a core allocator at a dispatch-unique seed and take its lineageRoot
        // for the per-revision messageId structure. We use the allocator's
        // `lineageRoot` (stable) as the chunk message_id per the core contract.
        const anchor = `${dispatchPrefix}-${seed}-${clock()}-${nonceSource()}`;
        return makeLineageMessageIdAllocator(anchor, { clock, nonceSource }).allocate()
            .lineageRoot;
    }
    return {
        resolveForTitle(title) {
            const key = normalizeLineageKey(title);
            const existing = lineages.get(key);
            if (existing !== undefined)
                return existing;
            const root = mintRoot(key || `untitled-${untitledCounter++}`);
            lineages.set(key, root);
            return root;
        },
        allocate() {
            return mintRoot(`turn-${untitledCounter++}`);
        },
    };
}
/**
 * Launch a prototype-gen driver in the host process. Delegates everything
 * substantive to `runDriver`; this function only:
 *   1. defaults `systemPromptAppend` to the guide-pinned prototype-gen persona,
 *   2. widens `extraAllowedTools` with the prototype + style_guide tools,
 *   3. installs a lineage-pinned `allocateMessageId` (Q2 mechanism).
 *
 * The host token pre-ingest + `style_guide` chunk publish (producer plan
 * §3.2-A) is a gated P3 responsibility layered ABOVE this launcher — it runs
 * before the call so the prompt-pinned guide id resolves on the agent's first
 * `prototype` emission.
 */
export function launchPrototypeGenDriver(opts) {
    const systemPromptAppend = opts.systemPromptAppend ??
        buildPrototypeGenSystemPrompt(opts.styleGuideId, opts.styleGuideVersion);
    const allocateMessageId = opts.allocateMessageId ?? makePrototypeLineageAllocator().allocate;
    return runDriver({
        worldId: opts.worldId,
        sessionId: opts.sessionId,
        hostCpUrl: opts.hostCpUrl,
        bearer: opts.bearer,
        sdkQuery: opts.sdkQuery,
        systemPromptAppend,
        extraAllowedTools: opts.extraAllowedTools ?? PROTOTYPE_GEN_EXTRA_ALLOWED_TOOLS,
        allocateMessageId,
        abortSignal: opts.abortSignal,
    });
}
//# sourceMappingURL=prototype-gen-launch.js.map