import { AgentProfileFileMount, AgentProfileMcpServer, AgentProfile } from '@tangle-network/sandbox';
import { profile } from '@tangle-network/agent-eval';
export { profile } from '@tangle-network/agent-eval';
import { SkillEntry } from '../skills/index.js';
export { ComposeShellResourcesInput, CorpusEntry, CorpusLoadResult, GlobModules, LoadCorpusOptions, composeShellResources, corpusSkills, loadMarkdownCorpus, registrySkills, skillMountPath } from '../skills/index.js';

/**
 * Profile composer + evolvable-section seam for agent products.
 *
 * The standard "load a deployable AgentProfile, including skills, plus the
 * skills the end user added to their own instance" entry point. A product holds
 * a canonical base `AgentProfile` (role/environment/tool-conventions rendered
 * into `prompt.systemPrompt`, baseline skills, baseline MCP). At deploy/turn
 * time it layers four file-mount channels onto `resources.files` —
 *
 *   1. skills      — the always-mounted product skill corpus
 *   2. knowledge   — a second always-mounted corpus (domain knowledge pack)
 *   3. registry    — the tier-gated installable registry (free -> boot-mounted)
 *   4. userSkills  — per-user / per-workspace skills the END USER adds to their
 *                    own instance, mounted at `~/.claude/skills/<id>/SKILL.md`
 *                    exactly like the registry's free tier
 *
 * plus an optional MCP overlay (delegation + per-turn app-tool side channel), a
 * per-turn `systemPrompt` override, and a `name` override. The merge is the SDK
 * `mergeAgentProfiles`: `mcp` is last-wins per key (base -> overlay), `resources`
 * arrays are concatenated (base ++ overlay), `prompt` is shallow-merged so an
 * overlay carrying only `systemPrompt` overrides it while keeping base
 * instructions. The compose algebra is DATA — the product injects the base
 * profile, the channel mounts (built with the `skills` subpath primitives), the
 * delegation/app-tool MCP map, and the override strings; nothing here reaches
 * for env, a glob, or a specific product's profile.
 *
 * The evolvable-section seam is the loader closure. A product's single
 * self-improvable domain section (the one `applyDomainPatch` targets) loads its
 * body from a deployed markdown override, falling back to an in-tree baseline.
 * The `import.meta.glob('<lit>', ...)` literal must stay at the CONSUMER call
 * site (Vite static-analyzes it), so `makeEvolvableSection` takes the loader as
 * a closure and a REQUIRED `baseline` — it never constructs a glob and never
 * defaults the baseline, so a product can't render an empty learned-guidance
 * section. `stripComments` is the shared "is this addendum really empty?" test.
 */

/** The file-mount channels layered onto `resources.files`. The first three
 *  mirror {@link ComposeShellResourcesInput}; `userSkills` is the per-user /
 *  per-workspace channel — skills the END USER added to their own instance,
 *  mounted at the harness skill-discovery path like the registry's free tier. */
interface ProfileChannels {
    /** Always-mounted skill corpus (pass `corpusSkills(...)`). */
    skills?: AgentProfileFileMount[];
    /** Always-mounted knowledge corpus (pass `corpusSkills(...)` for the pack). */
    knowledge?: AgentProfileFileMount[];
    /** Single-file evolvable / learned-guidance corpora, if mounted as files. */
    evolvable?: AgentProfileFileMount[];
    /** Tier-gated installable registry (pass the registry array; free tier is
     *  mounted, paid is install-on-demand). Gated through {@link registrySkills}. */
    registry?: SkillEntry[];
    /** Per-user / per-workspace skills the end user adds to their own instance.
     *  Mounted at `~/.claude/skills/<id>/SKILL.md`, the same harness path the
     *  registry uses, so a user skill and a registry skill with the same id
     *  collide deterministically (the user skill, appended last, wins). */
    userSkills?: UserSkill[];
    /** Final skip filter applied to the composed mount list by mount `path`. */
    filesPredicate?: (mount: AgentProfileFileMount) => boolean;
}
/** A per-user / per-workspace skill: an id and an inline `SKILL.md` body. The
 *  user-facing analogue of a registry {@link SkillEntry} with no tier gate —
 *  every user skill is mounted (the user opted in by adding it). */
interface UserSkill {
    id: string;
    /** Inline `SKILL.md` body mounted at {@link skillMountPath}. */
    skillMd: string;
}
/** Overlay overrides applied on top of the channel mounts. */
interface ProfileOverlay {
    /** Extra MCP servers merged into the profile `mcp` map (last-wins per key over
     *  the base servers). The product builds this from its delegation MCP entry
     *  and any per-turn app-tool side-channel servers. An absent/`undefined` entry
     *  is dropped — pass only the servers that resolved (fail-closed at the seam,
     *  not here). */
    mcp?: Record<string, AgentProfileMcpServer>;
    /** Per-turn system-prompt override. When set, replaces the base
     *  `prompt.systemPrompt` while keeping base `prompt.instructions`. When unset,
     *  the base prompt passes through unchanged. */
    systemPrompt?: string;
    /** Extra instruction lines merged onto the active prompt (e.g. a per-turn
     *  domain/integration directive). Appended to base `prompt.instructions` by
     *  the SDK merge. */
    instructions?: string[];
    /** Profile `name` override. When unset, the base name is kept. */
    name?: string;
}
/** Project per-user skills onto SDK file mounts at the harness skill-discovery
 *  path. No tier gate — a user skill is mounted because the user added it.
 *  Sorted by path for determinism (matches {@link registrySkills}). */
declare function userSkillMounts(userSkills: UserSkill[]): AgentProfileFileMount[];
/**
 * Compose a deployable `AgentProfile` from a canonical base plus the four
 * file-mount channels and the overlay overrides.
 *
 * Files: base `resources.files` come first; the four channels follow in
 * `skills -> knowledge -> evolvable -> registry -> userSkills` order (so a
 * userSkill that mounts at the same path as a registry skill is the last write
 * and wins). MCP: base servers first, the overlay `mcp` last (last-wins per
 * key). Prompt: the overlay `systemPrompt`, when set, replaces the base one;
 * base instructions are preserved. Name: the overlay `name`, when set, wins.
 *
 * The merge delegates to the SDK `mergeAgentProfiles` (overlay-wins on records,
 * arrays concatenated) — the deterministic algebra is the overlay we hand it,
 * not a hand-rolled spread. `mergeAgentProfiles(base, overlay)` returns
 * `undefined` only when BOTH are `undefined`; `base` is always defined here, so
 * the result is non-`undefined` by construction and we assert that to the caller.
 */
declare function composeAgentProfile(base: AgentProfile, channels?: ProfileChannels, overlay?: ProfileOverlay): AgentProfile;
/** True body of an addendum file with HTML comments stripped — an all-comment
 *  placeholder counts as empty, so the loader falls back to the baseline. */
declare function stripComments(raw: string): string;
/** Inputs to {@link makeEvolvableSection}. */
interface EvolvableSectionInput {
    /** Section id the self-improvement loop targets with `applyDomainPatch`. */
    id: string;
    /** Section title rendered as `### <title>`. */
    title: string;
    /**
     * Load the deployed section body. The CONSUMER supplies this closure and runs
     * its own `import.meta.glob('<lit>', { eager: true, query: '?raw', import:
     * 'default' })` inside it — the literal must stay at the call site so Vite can
     * static-analyze it; a glob constructed here would not resolve the product's
     * files. Return the raw markdown (comments and all); `makeEvolvableSection`
     * applies {@link stripComments} to decide whether it is really populated.
     */
    load: () => string;
    /**
     * The in-tree fallback body, used when `load()` returns an
     * all-comments/empty placeholder. REQUIRED — no internal default — so a
     * product can never accidentally render an empty evolvable section.
     */
    baseline: string;
}
/**
 * Build the one evolvable (`evolvable: true`) domain section whose body comes
 * from the product's loader, falling back to the required baseline when the
 * loaded body is empty after stripping comments. Returns the agent-eval
 * `AgentProfileSection` shape — drop it straight into `prodProfile`'s shipped
 * sections. The loader is the only seam; the empty-vs-populated rule and the
 * baseline fallback are the lifted algebra.
 */
declare function makeEvolvableSection(input: EvolvableSectionInput): profile.AgentProfileSection;

export { type EvolvableSectionInput, type ProfileChannels, type ProfileOverlay, SkillEntry, type UserSkill, composeAgentProfile, makeEvolvableSection, stripComments, userSkillMounts };
