import type { MergeConflict } from "../git/merge";
import type { ConflictHunk } from "../git/merge3";
import { acceptGenerated, assembleResolution, baseCandidates, blockContext, dedupe, redactSecrets } from "./candidates";
import type { Candidate, SecretVault } from "./candidates";
import { buildClefRequest, decideFile, MAX_HUNKS_PER_FILE } from "./decide";
import type { ClefRequest, ClefResponse, FileDecision, HunkInput, Thresholds } from "./decide";
export type ChatMessage = { role: "system" | "user"; content: string };
export type TokenUsage = { inputTokens: number; outputTokens: number };
export type GenerationInput = { messages: ChatMessage[]; hunk: ConflictHunk };
/** The two model calls the pipeline makes; production uses AI Gateway, tests and e2e use the mock. */
export interface MergeFixProvider {
generate(input: GenerationInput): Promise<{ text: string; usage: TokenUsage }>;
decide(request: ClefRequest): Promise<ClefResponse>;
}
export type FixLimits = {
maxFiles: number;
maxHunkBytes: number;
maxModelCalls: number;
aiCandidates: number;
callTimeoutMs: number;
/** Wall-clock budget for all model calls, kept below the Workflow plan step's timeout. */
totalTimeoutMs: number;
};
export const DEFAULT_LIMITS: FixLimits = {
maxFiles: 8,
maxHunkBytes: 4096,
maxModelCalls: 40,
aiCandidates: 2,
callTimeoutMs: 30_000,
totalTimeoutMs: 7 * 60 * 1000,
};
export type HunkResult = { candidates: Candidate[]; selected: string | null; probabilities: Record<string, number> };
export type FileResult =
| { path: string; status: "planned"; hunks: HunkResult[]; decision: FileDecision; resolution: string | null }
| { path: string; status: "skipped"; reason: string };