import type { AssistantMessage, Model, ToolCall } from "../types.js"; /** * Escape reserved Harmony control tokens in arbitrary text so it can be * transported as data to a harmony-dialect model. Returns the input unchanged * when it carries no reserved spelling. * * Callers MUST gate on a harmony target and escape only the transport copy — * the persisted transcript keeps the byte-for-byte original. */ export declare function escapeHarmonyControlTokens(text: string): string; /** * Escape reserved Harmony control tokens inside a JSON document string (e.g. * `function_call.arguments`). Doubles the backslash so the document remains * valid JSON whose *decoded* strings carry the inert `<\|token\|>` spelling. * `<|` cannot occur outside a string literal in valid JSON, so the blanket * replace never corrupts structure; malformed documents are escaped * best-effort. */ export declare function escapeHarmonyControlTokensInJson(text: string): string; /** * Whether requests to `model` are served by a Harmony-dialect backend * (gpt-5.x / gpt-oss), which rejects reserved control-token spellings appearing * as data in the request. Resolves the wire model id (`requestModelId ?? id`) * so deployment/catalog aliases — e.g. an Azure alias whose `requestModelId` is * `gpt-5.4` — are detected even when the local id is opaque. */ export declare function isHarmonyDialectModel(model: Model): boolean; declare const SIGNAL_ORDER: readonly ["M", "C", "G", "S", "B", "R", "T"]; export type HarmonySignalClass = "H" | (typeof SIGNAL_ORDER)[number]; export type HarmonySurface = "assistant_text" | "assistant_thinking" | "tool_arg"; export interface HarmonySignal { classes: HarmonySignalClass[]; start: number; end: number; text: string; } export interface HarmonyDetection { surface: HarmonySurface; contentIndex?: number; toolName?: string; toolCallId?: string; signals: HarmonySignal[]; } export interface HarmonyAuditEvent { action: "truncate_resume" | "abort_retry" | "escalated"; surface: HarmonySurface; signal: string; retryN: number; model: string; provider: string; toolName?: string; removedLen: number; removedSha8: string; removedPreview: string; removedBlob?: string; } export interface HarmonyRecoveredToolCall { message: AssistantMessage; removed: string; } /** * Whether to run leak detection on responses from this model. We default-on * for every openai-codex model rather than enumerating ids, so a future * gpt-5.6 (or whatever) doesn't silently bypass the mitigation. Detection * itself is cheap; the cost of missing a leak on a new model is not. */ export declare function isHarmonyLeakMitigationTarget(model: Model): boolean; export declare function signalListLabel(signals: readonly HarmonySignal[]): string; /** * Detect harmony-protocol leakage in `text`. Returns undefined if clean. * * Trip rule: `H` alone, or `M` paired with at least one co-signal * (`C`/`G`/`S`/`B`/`R`/`T`). Bare `M` does not trip — this document, its * tests, and bug reports legitimately carry the marker. * * The `tool_arg` surface is held to a stricter rule. A tool argument is * arbitrary file/data content that can legitimately carry the marker, a * channel word, harmony control tokens, or a non-Latin script run (editing * these very fixtures does exactly that). The only robust leak signal there * is content trailing the structurally-valid parse, so a `tool_arg` detection * additionally requires the `T` co-signal. Absent a `parsedEnd` boundary `T` * is never set, so `tool_arg` scanning stays inert and a legitimate codex tool * call is never hard-aborted. `assistant_text`/`assistant_thinking` keep the * base rule. * * `parsedEnd`, when supplied, marks the byte at which a structurally valid * tool-argument parse ends; markers at or past it set the `T` co-signal. * `contentIndex`/`toolName`/`toolCallId` flow through to the returned * detection for downstream auditing. */ export declare function detectHarmonyLeak(text: string, surface: HarmonySurface, options?: { parsedEnd?: number; contentIndex?: number; toolName?: string; toolCallId?: string; }): HarmonyDetection | undefined; /** * Scan an assistant message's content blocks; return the first detection. * * `toolArgParseEnd`, when supplied, resolves the byte offset at which a tool * call's structurally-valid argument parse ends (the `T` co-signal in * {@link detectHarmonyLeak}). Callers that can parse a tool's argument DSL pass * it to enable `tool_arg` leak detection; omitting it keeps that surface inert * — the safe default the agent loop relies on, since it cannot bound a streamed * tool DSL and must never hard-abort a legitimate tool call. */ export declare function detectHarmonyLeakInAssistantMessage(message: AssistantMessage, toolArgParseEnd?: (toolCall: ToolCall) => number | undefined): HarmonyDetection | undefined; /** * Truncate a contaminated tool call at the start of the contaminated line and * append the tool's recovery sentinel. Returns a recovered AssistantMessage * (containing only the cleaned tool call), a synthetic continuation user * message asking the model to re-issue the rest, and the removed substring * for auditing. Returns undefined when the tool is not recovery-eligible or * the truncation would leave nothing meaningful to dispatch. * * `providerPayload` is dropped from the recovered message: for Codex the * encrypted reasoning blob is opaque/signed and we cannot validate that it is * uncontaminated. The model re-reasons on the next turn. */ export declare function recoverHarmonyToolCall(message: AssistantMessage, detection: HarmonyDetection): HarmonyRecoveredToolCall | undefined; /** * Return the contaminated substring from `message` for audit purposes when * recovery is not applicable (abort path). Walks from the first detected * signal to end-of-content within the relevant block. Returns "" if the * detection cannot be resolved against the message. */ export declare function extractHarmonyRemoved(message: AssistantMessage, detection: HarmonyDetection): string; export declare function createHarmonyAuditEvent(params: { action: HarmonyAuditEvent["action"]; detection: HarmonyDetection; model: Model; retryN: number; removed: string; }): HarmonyAuditEvent; export {};