Files
orca/src/shared/osc-title-extraction.ts
T
NeilandOrca 879aad7dd6 oom(foundation): bound shared readers/limits + add BoundedMap primitive (#10299)
* oom(01): A1-shared-readers — reintroduce #10179 subset

Files: 18 applied, 0 deleted (from 6eb70d8370)

Co-authored-by: Orca <help@stably.ai>

* oom(02): A2-shared-image-media — reintroduce #10179 subset

Files: 7 applied, 0 deleted (from 6eb70d8370)

Co-authored-by: Orca <help@stably.ai>

* oom(03): A3-shared-fs-listing — reintroduce #10179 subset

Files: 21 applied, 0 deleted (from 6eb70d8370)

Co-authored-by: Orca <help@stably.ai>

* oom(04): A4-shared-remote-relay — reintroduce #10179 subset

Files: 8 applied, 0 deleted (from 6eb70d8370)

Co-authored-by: Orca <help@stably.ai>

* oom(05): A5-shared-misc — reintroduce #10179 subset

Files: 28 applied, 0 deleted (from 6eb70d8370)

Co-authored-by: Orca <help@stably.ai>

* oom(06): B-shared-wiring — reintroduce #10179 subset

Files: 81 applied, 0 deleted (from 6eb70d8370)

Co-authored-by: Orca <help@stably.ai>

---------

Co-authored-by: Orca <help@stably.ai>
2026-07-24 21:36:57 -07:00

135 lines
3.9 KiB
TypeScript

const ESC_CODE_UNIT = 0x1b
const BEL_CODE_UNIT = 0x07
const RIGHT_BRACKET_CODE_UNIT = 0x5d
const BACKSLASH_CODE_UNIT = 0x5c
const SEMICOLON_CODE_UNIT = 0x3b
const OSC_TITLE_COMMANDS = new Set([0x30, 0x31, 0x32])
export const MAX_OSC_TITLE_CHARS = 1024
export const MAX_OSC_TITLES_PER_CHUNK = 4096
type OscTitleParseResult =
| { kind: 'title'; title: string; nextIndex: number }
| { kind: 'invalid'; nextIndex: number }
| { kind: 'incomplete' }
function isOscIntroducerAt(data: string, index: number): boolean {
return (
data.charCodeAt(index) === ESC_CODE_UNIT &&
data.charCodeAt(index + 1) === RIGHT_BRACKET_CODE_UNIT
)
}
function parseOscTitleAt(data: string, index: number): OscTitleParseResult {
if (!isOscIntroducerAt(data, index)) {
return { kind: 'invalid', nextIndex: index + 1 }
}
if (
!OSC_TITLE_COMMANDS.has(data.charCodeAt(index + 2)) ||
data.charCodeAt(index + 3) !== SEMICOLON_CODE_UNIT
) {
return { kind: 'invalid', nextIndex: index + 2 }
}
const titleStart = index + 4
for (let cursor = titleStart; cursor < data.length; cursor += 1) {
const code = data.charCodeAt(cursor)
if (code === BEL_CODE_UNIT) {
return {
kind: 'title',
title: readBoundedOscTitle(data, titleStart, cursor),
nextIndex: cursor + 1
}
}
if (code !== ESC_CODE_UNIT) {
continue
}
if (data.charCodeAt(cursor + 1) === BACKSLASH_CODE_UNIT) {
return {
kind: 'title',
title: readBoundedOscTitle(data, titleStart, cursor),
nextIndex: cursor + 2
}
}
return { kind: 'invalid', nextIndex: cursor }
}
return { kind: 'incomplete' }
}
function readBoundedOscTitle(data: string, titleStart: number, titleEnd: number): string {
// Why: PTY output can contain pasted or remote-controlled OSC titles; keep
// downstream title detection bounded while preserving trailing status words.
const length = titleEnd - titleStart
if (length <= MAX_OSC_TITLE_CHARS) {
return data.slice(titleStart, titleEnd)
}
const prefixLength = Math.ceil(MAX_OSC_TITLE_CHARS / 2)
const suffixLength = MAX_OSC_TITLE_CHARS - prefixLength
return (
data.slice(titleStart, titleStart + prefixLength) +
data.slice(titleEnd - suffixLength, titleEnd)
)
}
export function extractLastOscTitle(data: string): string | null {
if (!data.includes('\x1b]')) {
return null
}
let last: string | null = null
let searchStart = 0
// Why: raw PTY chunks can include large pasted content. Parse OSC titles
// directly instead of running a global regex over the whole chunk.
while (searchStart < data.length) {
const start = data.indexOf('\x1b]', searchStart)
if (start === -1) {
break
}
const parsed = parseOscTitleAt(data, start)
if (parsed.kind === 'incomplete') {
break
}
if (parsed.kind === 'title') {
last = parsed.title
searchStart = parsed.nextIndex
continue
}
searchStart = parsed.nextIndex
}
return last
}
export function extractAllOscTitles(data: string): string[] {
if (!data.includes('\x1b]')) {
return []
}
const titles: string[] = []
let oldestTitleIndex = 0
let searchStart = 0
while (searchStart < data.length) {
const start = data.indexOf('\x1b]', searchStart)
if (start === -1) {
break
}
const parsed = parseOscTitleAt(data, start)
if (parsed.kind === 'incomplete') {
break
}
if (parsed.kind === 'title') {
if (titles.length < MAX_OSC_TITLES_PER_CHUNK) {
titles.push(parsed.title)
} else {
titles[oldestTitleIndex] = parsed.title
oldestTitleIndex = (oldestTitleIndex + 1) % MAX_OSC_TITLES_PER_CHUNK
}
searchStart = parsed.nextIndex
continue
}
searchStart = parsed.nextIndex
}
return oldestTitleIndex === 0
? titles
: [...titles.slice(oldestTitleIndex), ...titles.slice(0, oldestTitleIndex)]
}