import { KnowledgeResearchLoopContext, AddSourceTextInput, SourceAdapter, RunKnowledgeResearchLoopOptions, KnowledgeResearchLoopResult } from '@tangle-network/agent-knowledge';
import { KnowledgeSourceSpec, AgentKnowledgeConfig } from '../config/index.js';
import '../knowledge/index.js';
import '@tangle-network/agent-eval';
import '../model-dF2h4xT9.js';

/**
 * `@tangle-network/agent-app/knowledge-loop` — wire the declarative
 * `AgentKnowledgeConfig` to a running, source-grounded, eval-gated knowledge
 * acquisition loop.
 *
 * This module does NOT implement a loop. `@tangle-network/agent-knowledge`
 * already ships `runKnowledgeResearchLoop` — the source-grounded,
 * propose-don't-apply primitive (sources become immutable records first; only
 * accepted `---FILE: knowledge/...---` write blocks are applied; lint +
 * validation + optional readiness gate every iteration). It is pluggable on two
 * seams: a `SourceAdapter[]` (how raw bytes/text become curated source records —
 * text by default, audio/video/image adapters added by the consumer) and a
 * `step` decider (the per-iteration policy: an agentic judge, a sandbox run, or
 * a deterministic gate — the loop deliberately bakes none).
 *
 * `createKnowledgeLoop(config.knowledge, deps)` is the thin mapper between the
 * two:
 *
 *  - `config.knowledge.sources` → adapter selection. The text adapter is the
 *    default; `deps.adapters` is the multimodal seam (prepend an audio/video/
 *    image `SourceAdapter` and the loop ingests that media). agent-app bakes no
 *    media handler — it's a parameter.
 *  - `config.knowledge.loop` → `runKnowledgeResearchLoop` options. `goal` maps
 *    to the loop goal, `minConfidence` to the gate threshold, `freshness` is
 *    threaded to the decider so a per-source-freshness policy can read it.
 *  - `deps.decide` → the pluggable gate. DEFAULT is a reviewer policy
 *    (agent-knowledge's propose-don't-apply posture): a candidate carrying
 *    confidence below `minConfidence` is gated OUT (its proposal text is
 *    dropped — sources are still recorded, because grounding is never the thing
 *    we gate); at/above threshold it is accepted and the loop applies the write
 *    blocks. Swap in an agentic judge or a sandbox run by passing your own
 *    `decide`.
 *  - `deps.driver` → the agent-runtime turn driver (this repo's `../runtime`
 *    `runAppToolLoop` seam, or any compatible driver) the decider invokes for
 *    the loop's agent turns. Optional; a deterministic / sandbox decider needs
 *    no model turns and omits it.
 *
 * Layering: agent-knowledge and agent-runtime are PEER dependencies, never
 * bundled. This module imports only TYPES + the loop entry from agent-knowledge
 * and stays substrate-free behind the `decide` / `driver` / `adapters` seams.
 */

/**
 * A research candidate the decider evaluates before the loop applies it. This is
 * the propose-don't-apply unit: notes + the sources discovered this iteration +
 * the proposed write blocks, each carrying a confidence the gate scores against
 * the configured `minConfidence`.
 */
interface KnowledgeCandidate {
    /** Human-readable research transcript for this iteration. */
    notes?: string;
    /**
     * Textual source artifacts to register as immutable sources BEFORE any
     * proposal is applied. Recording these is grounding, not the gated step — a
     * rejected candidate still keeps its sources (so the next iteration is better
     * grounded). The decider may not strip these.
     */
    sourceTexts?: AddSourceTextInput[];
    /** Local files to register as immutable sources (same grounding posture). */
    sourcePaths?: string[];
    /**
     * Safe-write-protocol text (`---FILE: knowledge/...---` blocks). This IS the
     * gated step: the default decider drops it when `confidence < minConfidence`.
     */
    proposalText?: string;
    /**
     * Aggregate confidence in this candidate's proposal, in [0, 1]. The default
     * reviewer gate compares this to `minConfidence`. A candidate with no
     * `proposalText` needs no confidence (nothing is gated).
     */
    confidence?: number;
    /** The researcher's signal that the goal is met; ends the loop. */
    done?: boolean;
    metadata?: Record<string, unknown>;
}
/** The verdict a gate returns for one candidate. */
interface KnowledgeGateVerdict {
    /** Whether the candidate's proposal is accepted (applied) or gated out. */
    accepted: boolean;
    /** Why — surfaced in the decision metadata for audit. */
    reason: string;
    /** The confidence the gate scored (echoed for telemetry). */
    confidence: number;
    /** The threshold it was scored against. */
    minConfidence: number;
}
/**
 * The pluggable acquisition policy. Given the loop context (current index, lint,
 * validation, freshness target, the driver), produce a candidate AND a gate
 * verdict on it. This is the seam an agentic judge or a sandbox run plugs into;
 * the default {@link createReviewerDecider} is a confidence gate.
 */
interface KnowledgeDecider {
    (input: KnowledgeDeciderInput): Promise<KnowledgeDecision> | KnowledgeDecision;
}
interface KnowledgeDeciderInput {
    /** The agent-knowledge loop context for this iteration. */
    context: KnowledgeResearchLoopContext;
    /** The acquisition goal (from `config.loop.goal` or a deps fallback). */
    goal: string;
    /** The confidence threshold a proposal must clear to be applied. */
    minConfidence: number;
    /** The freshness target (`config.loop.freshness`), if set. */
    freshness?: string;
    /** The configured sources, for a decider that fetches/selects among them. */
    sources: KnowledgeSourceSpec[];
    /** The agent-runtime turn driver, if one was supplied to the loop. */
    driver?: KnowledgeLoopDriver;
}
interface KnowledgeDecision {
    /** The candidate the policy produced (may be empty to end the loop). */
    candidate: KnowledgeCandidate;
    /** The gate's verdict on the candidate's proposal. */
    verdict: KnowledgeGateVerdict;
}
/**
 * The agent-runtime turn driver seam. This is exactly `../runtime`'s
 * `runAppToolLoop` shape (a bounded, awaitable tool-driving turn loop over a
 * model). Typed structurally so a decider can drive the loop's agent turns
 * without this module importing the runtime engine. A deterministic / sandbox
 * decider may omit it.
 */
interface KnowledgeLoopDriver {
    (opts: {
        systemPrompt: string;
        userMessage: string;
    }): Promise<{
        finalText: string;
    }>;
}
interface CreateKnowledgeLoopDeps {
    /**
     * The knowledge-base root the loop reads/writes (an agent-knowledge layout).
     * Required — agent-knowledge owns disk; agent-app owns only the wiring.
     */
    root: string;
    /**
     * The per-iteration policy. Defaults to {@link createReviewerDecider} keyed on
     * the config's `minConfidence`. Pass your own to use an agentic judge or a
     * sandbox run.
     */
    decide?: KnowledgeDecider;
    /**
     * Extra source adapters (audio/video/image/PDF/...). The text adapter is
     * always present as the fallback; these are tried first so a multimodal
     * source is claimed by its adapter. This is the multimodal seam.
     */
    adapters?: SourceAdapter[];
    /** The agent-runtime turn driver for the loop's agent turns. */
    driver?: KnowledgeLoopDriver;
    /**
     * Fallback goal when `config.loop.goal` is unset. agent-knowledge requires a
     * goal; this keeps the loop runnable for a config with only requirement specs.
     */
    defaultGoal?: string;
    /** Default confidence threshold when `config.loop.minConfidence` is unset. */
    defaultMinConfidence?: number;
    /** Max research iterations (forwarded to agent-knowledge). Default 3. */
    maxIterations?: number;
    /** Actor stamped on the loop's knowledge events. */
    actor?: string;
    /** Abort the loop. */
    signal?: AbortSignal;
    /** Per-step hook (forwarded to agent-knowledge's `onStep`). */
    onStep?: RunKnowledgeResearchLoopOptions['onStep'];
}
/** The handle `createKnowledgeLoop` returns. */
interface KnowledgeLoop {
    /** Run the acquisition loop to completion and return the agent-knowledge result. */
    run(): Promise<KnowledgeResearchLoopResult>;
    /** The resolved goal the loop pursues. */
    readonly goal: string;
    /** The resolved confidence gate threshold. */
    readonly minConfidence: number;
    /** The adapters the loop uses (consumer extras first, text last). */
    readonly adapters: SourceAdapter[];
}
/**
 * The default gate — agent-knowledge's propose-don't-apply reviewer posture as a
 * confidence threshold. A candidate's `proposalText` is applied only when its
 * `confidence` is at/above `minConfidence`; otherwise the proposal is gated out
 * (sources are still recorded). A candidate with no `proposalText` is trivially
 * accepted (nothing to gate). This is the floor policy; swap in an agentic judge
 * or a sandbox-run decider via `deps.decide` for richer review.
 */
declare function reviewCandidate(candidate: KnowledgeCandidate, minConfidence: number): KnowledgeGateVerdict;
/**
 * Wrap a candidate-producing policy in the default reviewer gate. The policy
 * decides WHAT to propose (notes, sources, proposalText, confidence); the gate
 * decides whether the proposal is APPLIED. Use this when you have a proposer but
 * want the standard confidence gate; pass a full {@link KnowledgeDecider} to
 * `deps.decide` to own the gate too.
 */
declare function createReviewerDecider(propose: (input: KnowledgeDeciderInput) => Promise<KnowledgeCandidate> | KnowledgeCandidate): KnowledgeDecider;
/**
 * Build a runnable knowledge-acquisition loop from the product's
 * `AgentKnowledgeConfig` and a small set of seams. Maps config → agent-knowledge
 * `runKnowledgeResearchLoop` options; never reimplements the loop.
 */
declare function createKnowledgeLoop(knowledge: AgentKnowledgeConfig, deps: CreateKnowledgeLoopDeps): KnowledgeLoop;

export { type CreateKnowledgeLoopDeps, type KnowledgeCandidate, type KnowledgeDecider, type KnowledgeDeciderInput, type KnowledgeDecision, type KnowledgeGateVerdict, type KnowledgeLoop, type KnowledgeLoopDriver, createKnowledgeLoop, createReviewerDecider, reviewCandidate };
