Simplify terminal streaming protocol

This commit is contained in:
Mohamed Boudra
2026-03-22 22:31:23 +07:00
parent 54282409bb
commit 50ea5a76fb
35 changed files with 1809 additions and 4121 deletions
+3 -46
View File
@@ -1,10 +1,8 @@
import { describe, expect, it } from "vitest";
import {
getTerminalResumeOffset,
getTerminalAttachRetryDelayMs,
isTerminalAttachRetryableError,
updateTerminalResumeOffset,
withPromiseTimeout,
} from "./terminal-attach";
@@ -24,53 +22,12 @@ describe("terminal-attach", () => {
expect(isTerminalAttachRetryableError({ message: "Network disconnected during attach" })).toBe(
true,
);
expect(isTerminalAttachRetryableError({ message: "stream ended before ack" })).toBe(true);
expect(isTerminalAttachRetryableError({ message: "stream ended before snapshot" })).toBe(
true,
);
expect(isTerminalAttachRetryableError({ message: "permission denied" })).toBe(false);
});
it("reads and updates resume offsets monotonically", () => {
const offsets = new Map<string, number>();
const terminalId = "term-1";
const resumeOffsetStore = {
get: ({ terminalId }: { terminalId: string }) => offsets.get(terminalId),
set: ({ terminalId, offset }: { terminalId: string; offset: number }) => {
offsets.set(terminalId, offset);
},
};
expect(
getTerminalResumeOffset({
terminalId,
resumeOffsetStore,
}),
).toBeUndefined();
updateTerminalResumeOffset({
terminalId,
offset: 8,
resumeOffsetStore,
});
expect(
getTerminalResumeOffset({
terminalId,
resumeOffsetStore,
}),
).toBe(8);
// Stale offsets must not move resume backwards.
updateTerminalResumeOffset({
terminalId,
offset: 3,
resumeOffsetStore,
});
expect(
getTerminalResumeOffset({
terminalId,
resumeOffsetStore,
}),
).toBe(8);
});
it("resolves before timeout when promise completes", async () => {
await expect(
withPromiseTimeout({
-43
View File
@@ -8,49 +8,6 @@ const TERMINAL_ATTACH_RETRYABLE_ERROR_PATTERNS = [
"stream ended",
] as const;
export type TerminalResumeOffsetStore = {
get: (input: { terminalId: string }) => number | undefined;
set: (input: { terminalId: string; offset: number }) => void;
};
export function getTerminalResumeOffset(input: {
terminalId: string;
resumeOffsetStore: TerminalResumeOffsetStore;
}): number | undefined {
const offset = input.resumeOffsetStore.get({ terminalId: input.terminalId });
if (typeof offset !== "number" || !Number.isFinite(offset)) {
return undefined;
}
const normalizedOffset = Math.max(0, Math.floor(offset));
return normalizedOffset;
}
export function updateTerminalResumeOffset(input: {
terminalId: string;
offset: number;
resumeOffsetStore: TerminalResumeOffsetStore;
}): void {
if (!Number.isFinite(input.offset)) {
return;
}
const normalizedOffset = Math.max(0, Math.floor(input.offset));
const previousOffset =
getTerminalResumeOffset({
terminalId: input.terminalId,
resumeOffsetStore: input.resumeOffsetStore,
}) ?? -1;
if (normalizedOffset <= previousOffset) {
return;
}
input.resumeOffsetStore.set({
terminalId: input.terminalId,
offset: normalizedOffset,
});
}
export function getTerminalAttachRetryDelayMs(input: { attempt: number }): number {
const clampedAttempt = Math.max(0, input.attempt);
const exponentialDelay = 250 * 2 ** clampedAttempt;