import { Harness } from '../harness/index.js';
import { SkillEntry, ComposedSkills } from '../skills/index.js';
import '@tangle-network/agent-interface';
import '@tangle-network/sandbox';

/**
 * Harness-native skill directory resolution — the one place agent-app binds
 * to the platform's authoritative per-harness skill-dir map.
 *
 * `../skills` renders skill CONTENT (parse, tier-filter, `inline`/`mounted`
 * delivery) but deliberately stops short of naming WHICH cwd path a `mounted`
 * skill lands at on a given harness — that mapping is owned by the platform
 * materializer (`@tangle-network/agent-profile-materialize`'s
 * `skillDirForHarness`), not by app-shell. This subpath exists so no product
 * — and no other agent-app module — ever writes a skill path literal
 * (`~/.claude/skills/...`, `.opencode/skills`, ...) of its own; it bridges
 * agent-app's `Harness` taxonomy onto the platform's `HarnessId` and asks the
 * platform for the answer.
 *
 * Requires the OPTIONAL peer `@tangle-network/agent-profile-materialize`.
 * Products that don't install it simply don't import this subpath — every
 * other agent-app skills surface (`../skills`, `ProfileChannels.skillRefs`)
 * works without it, falling back to `inline` delivery.
 */

/** Resolve the cwd-relative skill dir `resources.skills` refs materialize
 *  into on `harness` — via the platform's `skillDirForHarness`. `null` when
 *  `harness` isn't bridged (see {@link HARNESS_BRIDGE}) or when the platform
 *  itself has no cwd skill primitive for it (e.g. `hermes`, user-dir-only). */
declare function resolveSkillDir(harness: Harness): string | null;
/** Filter `harnesses` down to those with no mounted skill dir (deduped,
 *  first-seen order preserved) — the set that must fall back to `inline`
 *  delivery, or that a caller should warn about before offering "mounted"
 *  install UX. */
declare function unsupportedSkillHarnesses(harnesses: Iterable<Harness>): Harness[];
/** Inputs to {@link composeSkillsForHarness}. */
interface ComposeSkillsForHarnessInput {
    skills: SkillEntry[];
    harness: Harness;
    tier?: string;
    heading?: string;
    /**
     * What to do when `harness` has no native skill-mount directory (see
     * {@link resolveSkillDir}). Default `'throw'`: refuse rather than silently
     * inlining every skill BODY into the system prompt. Pass `'inline'` only as
     * a deliberate, auditable opt-in — the caller has decided every skill must
     * reach this harness even though it will be concatenated into the prompt.
     */
    onNoSkillDir?: 'throw' | 'inline';
}
/**
 * Compose {@link ComposedSkills} for `harness`.
 *
 * `mounted` delivery is the standard path: whenever the platform names a cwd
 * skill dir for `harness`, skills ride the typed `resources.skills` channel
 * and the platform materializer writes each one to that directory as a real
 * file — the agent reads it on demand with its own file tools.
 *
 * `inline` delivery — every skill BODY rendered straight into the system
 * prompt — is a NARROW fallback for harnesses with no native skill dir, never
 * a co-equal mode. An `AgentProfile` is a RECIPE that materializes into a
 * sandbox, not a prompt template: skill bodies belong in a file mount, and
 * `prompt.systemPrompt` should carry only what the agent must obey without a
 * tool call (identity, tool-call contract, safety rules, output format) plus
 * a short index of what's mounted. Concatenating skill bodies into the prompt
 * degrades the model toward empty answers once it grows large enough — one
 * product reproduced a 151,882-byte prompt exactly this way, from an
 * unnoticed inline fallback.
 *
 * Because of that, `onNoSkillDir` defaults to `'throw'`: a harness with no
 * skill dir refuses instead of silently inlining. The thrown error names the
 * harness, the skill count, the byte size that would have been inlined, and
 * the harnesses that DO support native mounting. Pass `onNoSkillDir:
 * 'inline'` only as a deliberate, auditable opt-in when every skill genuinely
 * must reach this harness regardless of prompt cost.
 *
 * The one function a product calls instead of hand-checking `resolveSkillDir`
 * and branching between {@link composeSkills}'s two modes itself.
 */
declare function composeSkillsForHarness(input: ComposeSkillsForHarnessInput): ComposedSkills;

export { type ComposeSkillsForHarnessInput, ComposedSkills, SkillEntry, composeSkillsForHarness, resolveSkillDir, unsupportedSkillHarnesses };
