mirror of
https://github.com/stablyai/orca.git
synced 2026-10-08 08:02:32 +00:00
* docs: design SSH relay PTY backpressure * fix(ssh): bound relay frame decoding * fix(relay): bound PTY output publication * fix(ssh): bound PTY model admission * fix(ssh): settle closed model admissions * feat(ssh): negotiate bounded PTY consumer sessions * fix(ssh): fence exit on renderer settlement * feat(ssh): track PTY source credit end to end * fix(ssh): recover bounded PTY output across reconnect * feat(ssh): complete relay PTY output backpressure * fix(ssh): close final PTY source credit races * docs(ssh): record final backpressure validation * feat(ssh): complete relay PTY source-credit lifecycle * test(ssh): complete provider notification fixture * fix(ssh): preserve terminal source credit across rotation * fix(ssh): fail closed on recovery cancellation * fix(ssh): prioritize mux control writes after drain * fix(ssh): retire canceled relay restore deliveries * fix(ssh): order exit cancellation cleanup * fix(ssh): gate provisional source activation * test(ssh): register mux drain-priority coverage * fix(ssh): type stale owner recovery mismatches * fix(ssh): close projection replacement races * fix(relay): contain streaming edge failures * fix(ssh): secure relay endpoint credentials * docs(ssh): reconcile final backpressure lifecycle * fix(ssh): bound main IPC output lifecycle * fix(ssh): close recovery ownership gaps * docs(ssh): record exact artifact validation * fix(ssh): reject reclaimed snapshot replacements * fix(ssh): fence model admission across reconnect * fix(ssh): contain migration failure per PTY * docs(ssh): record final exact-head validation * test(ssh): align deploy fixtures with credential publication * feat(ssh): add per-target bounded output setting * fix(ssh): close source recovery review gaps * fix(ssh): latch source credit environment override * feat(ssh): make PTY source credit the default * docs(ssh): record always-on relay validation * docs(ssh): bind validation to current main * test(ssh): grant source credit in IPC fixture * test(ssh): grant source credit in fake relay --------- Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
100 lines
2.7 KiB
TypeScript
100 lines
2.7 KiB
TypeScript
import {
|
|
assertTerminalOutputSourceRange,
|
|
sameTerminalOutputSourceIdentity,
|
|
type TerminalOutputSourceRange
|
|
} from '../../../shared/terminal-output-source-range'
|
|
|
|
export type TerminalSourceRangeFrame = Readonly<{
|
|
encodedStartByte: number
|
|
encodedEndByte: number
|
|
displayLength: number
|
|
outputSeq?: number
|
|
sourceRanges: readonly TerminalOutputSourceRange[]
|
|
}>
|
|
|
|
export function freezeTerminalOutputSourceRanges(
|
|
ranges: readonly TerminalOutputSourceRange[]
|
|
): readonly TerminalOutputSourceRange[] {
|
|
return Object.freeze(
|
|
ranges.map((range) =>
|
|
Object.freeze({
|
|
...range,
|
|
transform: Object.freeze({ ...range.transform })
|
|
})
|
|
)
|
|
)
|
|
}
|
|
|
|
export function validateTerminalSourceRangeFrame(
|
|
displayLength: number,
|
|
ranges: readonly TerminalOutputSourceRange[]
|
|
): boolean {
|
|
if (!Number.isSafeInteger(displayLength) || displayLength < 0) {
|
|
return false
|
|
}
|
|
if (ranges.length === 0) {
|
|
return true
|
|
}
|
|
try {
|
|
for (const range of ranges) {
|
|
assertTerminalOutputSourceRange(range)
|
|
}
|
|
} catch {
|
|
return false
|
|
}
|
|
const first = ranges[0]!
|
|
let previous = first
|
|
for (const range of ranges.slice(1)) {
|
|
if (
|
|
!sameTerminalOutputSourceIdentity(first, range) ||
|
|
range.sourceStartSu !== previous.sourceEndSu ||
|
|
range.displayStart !== previous.displayEnd
|
|
) {
|
|
return false
|
|
}
|
|
previous = range
|
|
}
|
|
return previous.displayEnd - first.displayStart === displayLength
|
|
}
|
|
|
|
export function replaceTerminalSourceRangeFrames(
|
|
frames: readonly TerminalSourceRangeFrame[],
|
|
snapshotSeq: number
|
|
): Readonly<{
|
|
frames: TerminalSourceRangeFrame[]
|
|
mappingMode: 'mapped' | null
|
|
boundRange: TerminalOutputSourceRange | null
|
|
mappedSourceEndSu: number | null
|
|
mappedDisplayEnd: number | null
|
|
}> {
|
|
const replaced = frames.map((frame) =>
|
|
typeof frame.outputSeq === 'number' && frame.outputSeq <= snapshotSeq
|
|
? Object.freeze({ ...frame, sourceRanges: Object.freeze([]) })
|
|
: frame
|
|
)
|
|
const remainingRanges = replaced.flatMap((frame) => frame.sourceRanges)
|
|
const last = remainingRanges.at(-1)
|
|
return Object.freeze({
|
|
frames: replaced,
|
|
mappingMode: remainingRanges.length > 0 ? 'mapped' : null,
|
|
boundRange: last ?? null,
|
|
mappedSourceEndSu: last?.sourceEndSu ?? null,
|
|
mappedDisplayEnd: last?.displayEnd ?? null
|
|
})
|
|
}
|
|
|
|
export function canPlanTerminalSourceRangeReplacement(
|
|
frames: readonly TerminalSourceRangeFrame[],
|
|
snapshotSeq: number
|
|
): boolean {
|
|
return (
|
|
Number.isSafeInteger(snapshotSeq) &&
|
|
snapshotSeq >= 0 &&
|
|
frames.every(
|
|
(frame) =>
|
|
frame.sourceRanges.length === 0 ||
|
|
(typeof frame.outputSeq === 'number' && frame.outputSeq <= snapshotSeq)
|
|
)
|
|
)
|
|
}
|