import type { ConflictHunk } from "../git/merge3";
import { redactSecrets } from "./candidates";
import type { Candidate, SecretVault } from "./candidates";
export type Thresholds = { confidence: number; margin: number };
export const DEFAULT_THRESHOLDS: Thresholds = { confidence: 0.8, margin: 0.3 };
export const RISK_LEVELS = ["cosmetic", "logic", "security-sensitive"] as const;
export type RiskLevel = (typeof RISK_LEVELS)[number];
/** Any real chance of a security-sensitive change routes the file to a human. */
const SECURITY_PROBABILITY_LIMIT = 0.25;
const NEEDS_HUMAN_LIMIT = 0.5;
/** Clef accepts at most 64 questions; two are the per-file risk and needs-human questions. */
export const MAX_HUNKS_PER_FILE = 16;
type ChoiceQuestion = { type: "choice"; instructions: string; criteria: Record<string, string> };
type ScoreQuestion = { type: "score"; instructions: string; criteria: string[] };
type NoulQuestion = { type: "noul"; instructions: string; criteria?: { true: string; false: string } };
export type ClefRequest = {
model: "clef" | "clef-flash";
state: unknown;
questions: Record<string, ChoiceQuestion | ScoreQuestion | NoulQuestion>;
};
type ChoiceAnswer = { type: "choice"; choice: string; probabilities: Record<string, number>; confidence: number };
type ScoreAnswer = { type: "score"; score: number; probabilities: Record<string, number>; confidence: number };
type NoulAnswer = { type: "noul"; noul: number };
export type ClefResponse = {
answers: Record<string, ChoiceAnswer | ScoreAnswer | NoulAnswer | undefined>;
usage?: { input_tokens: number; output_tokens: number };
};
export type HunkInput = { hunk: ConflictHunk; candidates: Candidate[] };
function isRecord(value: unknown): value is Record<string, unknown> {
return typeof value === "object" && value !== null && !Array.isArray(value);
}
/** Clef output is parsed defensively: anything that is not a probability counts as zero. */