import { ZodIssue, ZodTypeAny, infer } from 'zod'; /** * Telemetry data attached to every `guard()` result. * * @property durationMs - Wall-clock time (in milliseconds) the `guard()` call took. * @property status - Outcome classification: * - `"clean"` – The raw input was already valid JSON **and** matched the schema. * - `"repaired_natively"` – The Dirty Parser fixed syntactic issues before Zod validation succeeded. * - `"coerced_locally"` – Semantic clamp/coerce logic repaired out-of-bound values locally. * - `"failed"` – The input could not be parsed or did not match the schema. */ interface TelemetryData { durationMs: number; status: "clean" | "repaired_natively" | "coerced_locally" | "failed"; coercedPaths?: string[]; } interface RetryPromptContextBlock { startLine: number; endLine: number; text: string; } type RetryPromptMode = "compact" | "line-aware"; interface RetryPromptOptions { mode?: RetryPromptMode; contextRadius?: number; maxContextChars?: number; includeLineNumbers?: boolean; maxIssueBlocks?: number; redactPaths?: string[]; redactRegex?: RegExp[]; } interface RetryPromptStrategyInput { errors: ZodIssue[]; rawOutput?: string; contextBlocks?: RetryPromptContextBlock[]; } type RetryPromptStrategy = (input: RetryPromptStrategyInput) => string; type GuardProfile = "safe" | "standard" | "aggressive"; interface GuardHeuristicOptions { escapedQuotes: boolean; singleQuotes: boolean; stripComments: boolean; normalizePythonLiterals: boolean; unquotedKeys: boolean; trailingCommas: boolean; } interface GuardOptions { profile?: GuardProfile; heuristics?: Partial; retryPrompt?: RetryPromptOptions; retryPromptStrategy?: RetryPromptStrategy; semanticResolution?: GuardSemanticResolution; debug?: boolean; } interface GuardSemanticResolutionInput { path: (string | number)[]; issue: ZodIssue; currentValue: unknown; } type GuardSemanticResolver = (input: GuardSemanticResolutionInput) => unknown; interface GuardSemanticResolution { mode?: "retry" | "clamp"; pathDefaults?: Record; resolver?: GuardSemanticResolver; } interface GuardDebugArtifacts { extractedText?: string; repairedText?: string; appliedRepairs?: string[]; likelyErrorLine?: number; retryContextBlocks?: RetryPromptContextBlock[]; } /** * Returned when `guard()` succeeds — the LLM output has been parsed, * optionally repaired, and validated against the Zod schema. * * @typeParam T - The inferred type of the Zod schema. */ interface GuardSuccess { success: true; /** The validated & typed data. */ data: T; /** Telemetry about the guard run. */ telemetry: TelemetryData; /** `true` when the Dirty Parser had to repair the raw input before it could be parsed. */ isRepaired: boolean; /** Optional debug payload with repair artifacts. */ debug?: GuardDebugArtifacts; } /** * Returned when `guard()` fails — the LLM output could not be repaired * into valid JSON or did not pass Zod schema validation. */ interface GuardFailure { success: false; /** * A token-efficient prompt you can append to your LLM message array * to request a corrected response. * * The prompt assumes the LLM still has the original schema in its * conversation context — it never re-sends the full schema, only * describes what was wrong (parse error with raw snippet, or validation * errors with exact paths and expected types). */ retryPrompt: string; /** The Zod validation issues (empty when JSON parsing itself failed). */ errors: ZodIssue[]; /** Telemetry about the guard run. */ telemetry: TelemetryData; /** Optional debug payload with repair artifacts and context windows. */ debug?: GuardDebugArtifacts; } /** * Discriminated union returned by `guard()`. * * Use `result.success` to narrow the type: * * ```ts * const result = guard(raw, MySchema); * if (result.success) { * console.log(result.data); // typed as z.infer * } else { * console.log(result.retryPrompt); * } * ``` * * @typeParam T - The inferred type of the Zod schema. */ type GuardResult = GuardSuccess | GuardFailure; /** * A message in the LLM conversation format. */ interface MessageTextBlock { type: "text"; text: string; } interface MessageImageUrlBlock { type: "image_url"; image_url: { url: string; detail?: "auto" | "low" | "high"; }; } type MessageContentBlock = MessageTextBlock | MessageImageUrlBlock; type MessageContent = string | MessageContentBlock[]; interface ReforgeToolCall { id: string; name: string; arguments: string; } interface ReforgeToolResponse { toolCallId: string; name: string; content: MessageContent; isError?: boolean; } interface Message { role: "system" | "user" | "assistant" | "tool"; content: MessageContent; toolCalls?: ReforgeToolCall[]; toolResponse?: ReforgeToolResponse; } /** * Backwards-compatible alias for generic native provider options. */ type ProviderCallOptions = Record; /** * The minimal interface every provider adapter must implement. * * Each built-in adapter factory (`openaiCompatible()`, `anthropic()`, `google()`) * returns an object satisfying this interface. Users can also implement it * directly for any provider not covered by the built-ins. */ interface ReforgeProvider = ProviderCallOptions> { readonly id?: string; call(messages: Message[], options?: TNativeOptions): Promise; } interface ReforgeTool { description?: string; schema: TSchema; execute: (args: infer) => Promise | unknown; } interface ForgeFailurePayload { errors: ZodIssue[]; retryPrompt: string; } interface ForgeRetryPolicy = ProviderCallOptions> { maxRetries?: number; shouldRetry?: (failure: ForgeFailurePayload, attempt: number) => boolean; mutateProviderOptions?: (attempt: number, baseOptions: TNativeOptions | undefined) => TNativeOptions; } type ForgeEvent = { kind: "attempt_start"; attempt: number; totalAttempts: number; } | { kind: "provider_response"; attempt: number; rawLength: number; truncatedForRetry: boolean; } | { kind: "guard_success"; attempt: number; status: "clean" | "repaired_natively" | "coerced_locally"; durationMs: number; } | { kind: "guard_failure"; attempt: number; durationMs: number; errorCount: number; } | { kind: "retry_scheduled"; attempt: number; nextAttempt: number; reason: "guard_failure"; } | { kind: "finished"; success: boolean; attempts: number; totalDurationMs: number; }; /** * Options for the `forge()` orchestrator. */ interface ForgeOptions = ProviderCallOptions> { /** Maximum number of retry attempts after the initial call. Default: 3. */ maxRetries?: number; /** Optional retry policy hooks for advanced retry control. */ retryPolicy?: ForgeRetryPolicy; /** Options passed through to the provider on every call. */ providerOptions?: TNativeOptions; /** Forwarded to `guard()` on every attempt. */ guardOptions?: GuardOptions; /** Local tools exposed to the orchestrator. */ tools?: Record; /** Hard timeout applied to local tool execution. */ toolTimeoutMs?: number; /** Hard circuit breaker for model-tool loops. Default: 5. */ maxAgentIterations?: number; /** Optional stream callback for user-facing assistant text chunks. */ onChunk?: (text: string) => void; /** Callback invoked after a failed attempt that will be retried. */ onRetry?: (attempt: number, failure: { errors: ZodIssue[]; retryPrompt: string; }) => void; /** Structured event stream for observability. */ onEvent?: (event: ForgeEvent) => void; } interface ForgeFallbackProvider { provider: ReforgeProvider; maxAttempts?: number; providerOptions?: ProviderCallOptions; } interface ForgeFallbackOptions { guardOptions?: GuardOptions; onRetry?: ForgeOptions["onRetry"]; onEvent?: ForgeOptions["onEvent"]; onProviderFallback?: (fromProviderIndex: number, toProviderIndex: number) => void; } interface ForgeAttemptDetail { attempt: number; durationMs: number; status: "clean" | "repaired_natively" | "coerced_locally" | "failed"; } interface ForgeProviderHop { providerId: string; attempt: number; succeeded: boolean; durationMs: number; } /** * Telemetry data from a `forge()` run. Extends the core `TelemetryData` * with multi-attempt tracking. */ interface ForgeTelemetry extends TelemetryData { /** Total number of provider calls made (1 = success on first try). */ attempts: number; /** Wall-clock time across all attempts (including provider latency). */ totalDurationMs: number; /** Time spent inside provider calls. */ networkDurationMs: number; /** Time spent executing local tools. */ toolExecutionDurationMs: number; /** Ordered provider hops made by forge(). */ providerHops: ForgeProviderHop[]; /** Per-attempt guard telemetry snapshots. */ attemptDetails: ForgeAttemptDetail[]; } /** * Returned when `forge()` succeeds — the LLM output has been validated * (possibly after retries). */ interface ForgeSuccess { success: true; data: T; telemetry: ForgeTelemetry; isRepaired: boolean; } /** * Returned when `forge()` fails — all retry attempts exhausted. */ interface ForgeFailure { success: false; errors: ZodIssue[]; retryPrompt: string; telemetry: ForgeTelemetry; } /** * Discriminated union returned by `forge()`. */ type ForgeResult = ForgeSuccess | ForgeFailure; export type { ReforgeToolResponse as A, RetryPromptContextBlock as B, RetryPromptMode as C, RetryPromptOptions as D, RetryPromptStrategy as E, ForgeOptions as F, GuardOptions as G, RetryPromptStrategyInput as H, Message as M, ProviderCallOptions as P, ReforgeProvider as R, TelemetryData as T, GuardResult as a, ForgeResult as b, ForgeFallbackProvider as c, ForgeFallbackOptions as d, ForgeAttemptDetail as e, ForgeEvent as f, ForgeFailure as g, ForgeFailurePayload as h, ForgeProviderHop as i, ForgeRetryPolicy as j, ForgeSuccess as k, ForgeTelemetry as l, GuardDebugArtifacts as m, GuardFailure as n, GuardHeuristicOptions as o, GuardProfile as p, GuardSemanticResolution as q, GuardSemanticResolutionInput as r, GuardSemanticResolver as s, GuardSuccess as t, MessageContent as u, MessageContentBlock as v, MessageImageUrlBlock as w, MessageTextBlock as x, ReforgeTool as y, ReforgeToolCall as z };