fix(app): more terminal stability fixes

This commit is contained in:
Adam
2026-02-05 11:28:22 -06:00
parent 8c0300c021
commit 2875405514
5 changed files with 43 additions and 17 deletions

View File

@@ -44,7 +44,7 @@
"@thisbeyond/solid-dnd": "0.7.5",
"diff": "catalog:",
"fuzzysort": "catalog:",
"ghostty-web": "0.3.0",
"ghostty-web": "0.4.0",
"luxon": "catalog:",
"marked": "catalog:",
"marked-shiki": "catalog:",
@@ -496,9 +496,6 @@
"web-tree-sitter",
"tree-sitter-bash",
],
"patchedDependencies": {
"ghostty-web@0.3.0": "patches/ghostty-web@0.3.0.patch",
},
"overrides": {
"@types/bun": "catalog:",
"@types/node": "catalog:",
@@ -2605,7 +2602,7 @@
"get-tsconfig": ["get-tsconfig@4.13.0", "", { "dependencies": { "resolve-pkg-maps": "^1.0.0" } }, "sha512-1VKTZJCwBrvbd+Wn3AOgQP/2Av+TfTCOlE4AcRJE72W1ksZXbAx8PPBR9RzgTeSPzlPMHrbANMH3LbltH73wxQ=="],
"ghostty-web": ["ghostty-web@0.3.0", "", {}, "sha512-SAdSHWYF20GMZUB0n8kh1N6Z4ljMnuUqT8iTB2n5FAPswEV10MejEpLlhW/769GL5+BQa1NYwEg9y/XCckV5+A=="],
"ghostty-web": ["ghostty-web@0.4.0", "", {}, "sha512-0puDBik2qapbD/QQBW9o5ZHfXnZBqZWx/ctBiVtKZ6ZLds4NYb+wZuw1cRLXZk9zYovIQ908z3rvFhexAvc5Hg=="],
"gifwrap": ["gifwrap@0.10.1", "", { "dependencies": { "image-q": "^4.0.0", "omggif": "^1.0.10" } }, "sha512-2760b1vpJHNmLzZ/ubTtNnEx5WApN/PYWJvXvgS+tL1egTTthayFYIQQNi136FLEDcN/IyEY2EcGpIITD6eYUw=="],

View File

@@ -100,7 +100,5 @@
"@types/bun": "catalog:",
"@types/node": "catalog:"
},
"patchedDependencies": {
"ghostty-web@0.3.0": "patches/ghostty-web@0.3.0.patch"
}
"patchedDependencies": {}
}

View File

@@ -54,7 +54,7 @@
"@thisbeyond/solid-dnd": "0.7.5",
"diff": "catalog:",
"fuzzysort": "catalog:",
"ghostty-web": "0.3.0",
"ghostty-web": "0.4.0",
"luxon": "catalog:",
"marked": "catalog:",
"marked-shiki": "catalog:",

View File

@@ -70,6 +70,7 @@ export const Terminal = (props: TerminalProps) => {
let handleTextareaBlur: () => void
let disposed = false
const cleanups: VoidFunction[] = []
let tail = local.pty.tail ?? ""
const cleanup = () => {
if (!cleanups.length) return
@@ -256,6 +257,7 @@ export const Terminal = (props: TerminalProps) => {
serializeAddon = serializer
t.open(container)
container.addEventListener("pointerdown", handlePointerDown)
cleanups.push(() => container.removeEventListener("pointerdown", handlePointerDown))
@@ -276,15 +278,11 @@ export const Terminal = (props: TerminalProps) => {
focusTerminal()
fit.fit()
if (local.pty.buffer) {
if (local.pty.rows && local.pty.cols) {
t.resize(local.pty.cols, local.pty.rows)
}
t.write(local.pty.buffer, () => {
if (local.pty.scrollY) {
t.scrollToLine(local.pty.scrollY)
}
fitAddon.fit()
if (local.pty.scrollY) t.scrollToLine(local.pty.scrollY)
})
}
@@ -322,6 +320,19 @@ export const Terminal = (props: TerminalProps) => {
// console.log("Scroll position:", ydisp)
// })
const limit = 16_384
const seed = tail
let sync = !!seed
const overlap = (data: string) => {
if (!seed) return 0
const max = Math.min(seed.length, data.length)
for (let i = max; i > 0; i--) {
if (seed.slice(-i) === data.slice(0, i)) return i
}
return 0
}
const handleOpen = () => {
local.onConnect?.()
sdk.client.pty
@@ -338,7 +349,25 @@ export const Terminal = (props: TerminalProps) => {
cleanups.push(() => socket.removeEventListener("open", handleOpen))
const handleMessage = (event: MessageEvent) => {
t.write(event.data)
const data = typeof event.data === "string" ? event.data : ""
if (!data) return
const next = (() => {
if (!sync) return data
const n = overlap(data)
if (!n) {
sync = false
return data
}
const trimmed = data.slice(n)
if (trimmed) sync = false
return trimmed
})()
if (!next) return
t.write(next)
tail = next.length >= limit ? next.slice(-limit) : (tail + next).slice(-limit)
}
socket.addEventListener("message", handleMessage)
cleanups.push(() => socket.removeEventListener("message", handleMessage))
@@ -392,6 +421,7 @@ export const Terminal = (props: TerminalProps) => {
props.onCleanup({
...local.pty,
buffer,
tail,
rows: t.rows,
cols: t.cols,
scrollY: t.getViewportY(),

View File

@@ -13,6 +13,7 @@ export type LocalPTY = {
cols?: number
buffer?: string
scrollY?: number
tail?: string
}
const WORKSPACE_KEY = "__workspace__"