/** * Bracketed paste (DEC private mode 2004) for programmatic prompt injection. * * `submitInput()` writes a prompt into a coding agent's pty and then a `\r` to * send it. Both halves are ambiguous to a TUI unless the paste is bracketed: * * - A prompt with newlines in it (the canvas chat prepends a multi-line step * context to every question) is a stream of `\n`s to the app. Ink — Claude * Code's input layer — maps a bare `\n` to Return exactly like `\r`, so a * raw write submits at the FIRST newline and the rest of the prompt lands * as further half-prompts. * - The trailing `\r` is only a "submit" keypress if the app has already * stopped treating the write as pasted content. Its paste heuristic is a * timing/size guess, so the same click can submit or sit in the composer * depending on how busy the agent was — the reported inconsistency. * * With mode 2004 on, the app is told where pasted content starts and ends, so * newlines inside stay literal and the following `\r` is unambiguously a * keypress. The mode is only usable when the app turned it on, so * {@link trackBracketedPaste} reads that fact off the pty's own output rather * than assuming it: an app that never enables 2004 keeps the previous raw * behaviour instead of being fed escape sequences it would render as text. * * One exception, gated to Windows by its consumer (`SessionManager.submitInput`): * ConPTY re-renders output instead of passing DEC private-mode sequences * through, so the announcement never reaches us even from an app that DID * enable the mode. There, and only there, an adapter may declare * `assumesBracketedPaste` — hence {@link BracketedPasteState.observed}, which * separates "the app turned it off" from "we never saw the announcement". * * Pure — no I/O, no pty — so the parsing is unit-testable on strings. */ /** Start of pasted content (`ESC [ 200 ~`). */ export declare const PASTE_START = "\u001B[200~"; /** End of pasted content (`ESC [ 201 ~`). */ export declare const PASTE_END = "\u001B[201~"; /** Incremental scan state — see {@link trackBracketedPaste}. */ export interface BracketedPasteState { /** Whether the app currently has mode 2004 on. */ enabled: boolean; /** * Whether ANY 2004 set/reset has ever been seen on this pty. Distinguishes * "the app turned bracketed paste off" (observed, enabled=false — respect * it) from "we never saw the announcement" — which on Windows is the normal * case even for apps that DO enable it, because ConPTY re-renders output * instead of passing DEC private-mode sequences through. Consumers may fall * back to an adapter-declared assumption only in the never-observed state. */ observed: boolean; /** Trailing bytes of the last chunk that may be an unfinished sequence. */ carry: string; } export declare const initialBracketedPasteState: BracketedPasteState; /** * Fold one chunk of pty output into the running bracketed-paste mode state. * The LAST 2004 set/reset in the chunk wins, matching how the terminal itself * would apply them in order. */ export declare function trackBracketedPaste(state: BracketedPasteState, chunk: string): BracketedPasteState; /** * Wrap `text` as bracketed pasted content. * * Any `ESC [ 201 ~` inside the text would end the paste early and hand the * remainder to the app as keystrokes, so it is dropped — to a FIXPOINT, since * removing one terminator can let the bytes on either side re-form another * (`"\x1b[20" + ESC[201~ + "1~"` collapses to a fresh `ESC[201~`). `\r` is then * normalized to `\n`, because a carriage return inside a paste is what the app * reads as Return, which is precisely the premature submit this exists to prevent. */ export declare function wrapPaste(text: string): string; //# sourceMappingURL=bracketed-paste.d.ts.map