Files
orca/src/shared/native-chat-paste-bytes.ts
T
bfa0dc01ba fix(mobile): preserve long terminal and chat pastes (#31473)
* fix(mobile): preserve long terminal and chat pastes

Agents can keep only the last ~1 KiB read of unframed input (#13332).
Frame long single-line chat messages like multi-line ones, and frame Live
input appends over 1 KiB (an OS paste) with the terminal's paste rule,
including held text flushed before a terminal click.

Co-authored-by: Carlos Baraza Haro <carlos.baraza@ieee.org>

* fix(mobile): end the live input session after a framed paste

Agents such as Codex collapse a framed paste into one token, so later
per-character erases from the field mirror desynced the line. A long
append to a terminal in bracketed paste mode now commits the whole field
in one frame and clears the field, recording it like other session ends
so a late native echo cannot send the paste twice; without that mode the
paste stays unframed and editable. Chat sends measure the sanitized bytes
when deciding to frame.

---------

Co-authored-by: Carlos Baraza Haro <carlos.baraza@ieee.org>
Co-authored-by: Kelvin Amoaba <97001695+AmoabaKelvin@users.noreply.github.com>
2026-10-29 03:02:08 +00:00

41 lines
1.6 KiB
TypeScript

// Share exact PTY composer bytes across desktop/mobile.
import {
sanitizeBracketedPasteText,
UNFRAMED_AGENT_INPUT_MAX_BYTES,
wrapTerminalBracketedPasteText
} from './terminal-bracketed-paste-text'
import { getTerminalInputByteLength } from './terminal-input'
// PTY Enter is carriage return, not newline.
const SUBMIT = '\r'
/** Any CR/LF, including a trailing newline, needs bracketed-paste framing. */
export function isMultilineDraft(text: string): boolean {
return /[\r\n]/.test(text)
}
/** Write Enter separately from the framed body; see buildNativeChatPasteBytes. */
export const NATIVE_CHAT_SUBMIT = SUBMIT
/** Build sanitized body bytes, bracket-framed for multiline or long input, without submit.
* Agent TUIs treat CR in the same PTY write as pasted body, leaving text unsent. Write NATIVE_CHAT_SUBMIT separately after a short delay,
* matching orca-runtime writeTerminalAction Enter handling. */
export function buildNativeChatPasteBytes(text: string): string {
// Sanitize unframed text too so pasted scrollback cannot inject terminal escapes.
const sanitized = sanitizeBracketedPasteText(text)
if (
isMultilineDraft(text) ||
getTerminalInputByteLength(sanitized) > UNFRAMED_AGENT_INPUT_MAX_BYTES
) {
return wrapTerminalBracketedPasteText(text)
}
return sanitized
}
/** Image attachments must look like a real terminal image paste to Claude/Codex
* TUIs. A plain typed path (or @file mention) is treated as text/file-read. */
export function buildNativeChatImagePasteBytes(filePath: string): string {
return wrapTerminalBracketedPasteText(filePath)
}