import type { ImageContent } from "@oh-my-pi/pi-ai";
import { Editor, type KeyId } from "@oh-my-pi/pi-tui";
import type { AppKeybinding } from "../../config/keybindings.js";
type ConfigurableEditorAction = Extract<AppKeybinding, "app.interrupt" | "app.clear" | "app.exit" | "app.suspend" | "app.display.reset" | "app.thinking.cycle" | "app.model.cycleForward" | "app.model.cycleBackward" | "app.model.select" | "app.model.selectTemporary" | "app.tools.expand" | "app.thinking.toggle" | "app.editor.external" | "app.history.search" | "app.message.dequeue" | "app.retry" | "app.clipboard.pasteImage" | "app.clipboard.pasteTextRaw" | "app.clipboard.copyPrompt">;
/** Max gap (ms) between two spaces for the later one to count as OS key auto-repeat rather than a
 *  deliberate press. OS auto-repeat is fast; a deliberate tap (even a fast one) is slower. */
export declare const SPACE_REPEAT_MAX_GAP_MS = 120;
/** Two consecutive inter-space gaps are "mechanical" (machine-driven auto-repeat) when both are
 *  within {@link SPACE_REPEAT_MAX_GAP_MS} and differ by no more than this — an absolute jitter floor
 *  or, for slower repeat rates, {@link SPACE_REPEAT_JITTER_RATIO} of the smaller gap. OS key-repeat
 *  is metronomic; a human smashing the bar is fast but irregular, so its deltas never stay this
 *  steady. */
export declare const SPACE_REPEAT_JITTER_MS = 18;
export declare const SPACE_REPEAT_JITTER_RATIO = 0.35;
/** Consecutive mechanical (fast + steady) deltas that confirm the space bar is held and start
 *  recording. Needs a sustained metronomic cadence, so jittery smashing and deliberate taps never
 *  reach it. */
export declare const SPACE_HOLD_MECHANICAL_RUN = 2;
/** Idle gap (ms) after the last repeated space that counts as the space bar being released, ending
 *  the push-to-talk recording. Must comfortably exceed the OS key-repeat interval. */
export declare const SPACE_HOLD_RELEASE_MS = 250;
/**
 * Extract image-or-other file paths from plain (un-bracketed) clipboard text.
 * Mirrors {@link extractBracketedPastePaths} for terminals/handlers that
 * already stripped the `\x1b[200~`…`\x1b[201~` markers (e.g. clipboard text
 * read directly via `pbpaste`/PowerShell).
 */
export declare function extractPastePathsFromText(text: string): string[] | undefined;
export declare function extractBracketedPastePaths(data: string): string[] | undefined;
export declare function extractBracketedImagePastePaths(data: string): string[] | undefined;
/**
 * Same shape as {@link extractBracketedImagePastePaths} but operates on a
 * payload that has already been stripped of the `\x1b[200~` / `\x1b[201~`
 * markers — used by the assembled-paste router in {@link CustomEditor.handleInput}
 * so split bracketed pastes get the same image-path detection as single-chunk ones.
 */
export declare function extractImagePastePathsFromText(text: string): string[] | undefined;
export declare function extractBracketedImagePastePath(data: string): string | undefined;
/**
 * Return a single image file path when `text` is exactly one explicit path
 * pointing at a supported image extension (`.png`, `.jpg`/`.jpeg`, `.gif`,
 * `.webp`). Used by the keybind-driven clipboard image paste path so a
 * clipboard whose only payload is an image file (e.g. Finder `Cmd+C` on
 * macOS) attaches the image instead of pasting the path as literal text.
 *
 * Two-stage detection:
 *
 * 1. Splitter pass (shared with the bracketed-paste handler) — handles
 *    quoted paths, shell-escaped spaces, and unambiguous single tokens.
 *    Returns the single image path when it parses cleanly; explicitly
 *    returns `undefined` when the splitter found multiple segments (so
 *    ambiguous multi-path clipboard text like `/tmp/a.png /tmp/b.png`
 *    still falls through to the text fallback instead of being mis-loaded
 *    as one giant path).
 * 2. Whole-text-as-path pass — only reached when the splitter failed
 *    (every segment must look like an explicit path; an unescaped space in
 *    a real path breaks that). Restricted to inputs anchored by
 *    {@link ABSOLUTE_PATH_PREFIX_REGEX} so prose containing a path-shaped
 *    fragment ("see /tmp/x.png") never hijacks the smart fallback. This
 *    is what recovers macOS screenshot filenames like
 *    `/Users/me/Desktop/Screenshot 2026-06-25 at 1.23.45 PM.png`.
 */
export declare function extractImagePathFromText(text: string): string | undefined;
/**
 * Custom editor that handles configurable app-level shortcuts for coding-agent.
 */
export declare class CustomEditor extends Editor {
    #private;
    imageLinks?: readonly (string | undefined)[];
    /** Draft images pasted into the composer, consumed on submit. Co-located with
     *  {@link imageLinks} so every piece of draft-image state lives on the editor. */
    pendingImages: ImageContent[];
    /** Per-image source links (file:// targets) parallel to {@link pendingImages};
     *  `undefined` entries are images without a backing reference yet. */
    pendingImageLinks: (string | undefined)[];
    /** Clear the composer draft: optionally commit `historyText` to history, then
     *  reset the editor text and all pending draft-image state. The shared tail of
     *  every "message submitted" path; pass no argument for a plain discard. */
    clearDraft(historyText?: string): void;
    /** Treat image/paste markers as indivisible: a stray backspace deletes the whole token
     *  instead of corrupting `[Paste #1, +30 lines]` into plain text. */
    atomicTokenPattern: RegExp;
    /** Magic-keyword shimmer cadence — drives one editor repaint every 70 ms while
     *  a keyword is on screen and the prompt is focused. ~14 frames/s is smooth
     *  without flooding the renderer. */
    static readonly SHIMMER_FRAME_MS = 70;
    /** Time for the gradient to sweep one full cycle across each keyword. */
    static readonly SHIMMER_PERIOD_MS = 1800;
    /** Gradient-highlight the "ultrathink" / "orchestrate" / "workflowz" keywords as the user types
     *  them, skipping any occurrence inside code spans, fenced blocks, or XML sections. Also make
     *  pasted image placeholders visually distinct and hyperlink them once their blob file exists.
     *  When the editor is focused, the buffer contains a magic keyword, and `magicKeywords.enabled`
     *  is on, the gradient shifts every frame to produce a Claude-Code-style shimmer; each render
     *  schedules the next frame, so losing focus, deleting the keyword, or flipping the setting
     *  stops the animation on its own. The static glow itself runs even when shimmering is gated
     *  off, matching existing behavior for the editor and sent bubbles. */
    decorateText: (text: string) => string;
    /** Optional test/host override for the magic-keyword shimmer gate. When
     *  defined, takes precedence over the global `magicKeywords.enabled` setting,
     *  letting tests assert the gating behaviour without mutating the
     *  process-wide Settings singleton (which races with parallel test files —
     *  see issue #2582). Production wires this through the host's Settings
     *  reader and updates it on the relevant setting change. */
    magicKeywordsEnabledOverride: boolean | undefined;
    /** Bind the host's render request callback. Idempotent — the host wires this
     *  once after construction (and again after `setEditorComponent` swaps the
     *  editor). Passing `undefined` clears any pending frame. */
    setShimmerRepaintHandler(handler: (() => void) | undefined): void;
    onEscape?: () => void;
    onClear?: () => void;
    onExit?: () => void;
    onDisplayReset?: () => void;
    onCycleThinkingLevel?: () => void;
    onCycleModelForward?: () => void;
    onCycleModelBackward?: () => void;
    onSelectModel?: () => void;
    onExpandTools?: () => void;
    onToggleThinking?: () => void;
    onExternalEditor?: () => void;
    onHistorySearch?: () => void;
    onSuspend?: () => void;
    onSelectModelTemporary?: () => void;
    /** Called when the configured copy-prompt shortcut is pressed. */
    onCopyPrompt?: () => void;
    /** Called when the configured image-paste shortcut is pressed. */
    onPasteImage?: () => Promise<boolean>;
    /** Called when a bracketed paste contains one or more image-file paths. */
    onPasteImagePath?: (path: string) => void | Promise<void>;
    /** Called when the configured raw text-paste shortcut is pressed. */
    onPasteTextRaw?: () => void;
    /** Called when the configured dequeue shortcut is pressed. */
    onDequeue?: () => void;
    /** Called when the configured retry shortcut is pressed. */
    onRetry?: () => void;
    /** Called when Caps Lock is pressed. */
    onCapsLock?: () => void;
    /** Called when left-arrow is pressed while the editor is empty (cursor necessarily at start). */
    onLeftAtStart?: () => void;
    /** Fired when a sustained space-bar hold is recognized — the push-to-talk STT start. The
     *  optimistically-typed spaces have already been deleted by the time this runs. */
    onSpaceHoldStart?: () => void;
    /** Fired when the held space bar is released (detected as an idle gap with no further repeated
     *  spaces) — the push-to-talk STT stop. */
    onSpaceHoldEnd?: () => void;
    /** Gate for the space-hold gesture. Returns false to keep the space bar inserting spaces
     *  normally; wired to `stt.enabled` so disabling STT restores plain space behavior. */
    sttHoldEnabled?: () => boolean;
    setActionKeys(action: ConfigurableEditorAction, keys: KeyId[]): void;
    /**
     * Register a custom key handler. Extensions use this for shortcuts.
     */
    setCustomKeyHandler(key: KeyId, handler: () => void): void;
    /**
     * Remove a custom key handler.
     */
    removeCustomKeyHandler(key: KeyId): void;
    /**
     * Clear all custom key handlers.
     */
    clearCustomKeyHandlers(): void;
    handleInput(data: string): void;
}
export {};
