fix(app): more startup efficiency (#19454)

This commit is contained in:
Adam
2026-03-27 20:26:57 -05:00
committed by GitHub
parent 82fc493520
commit f736116967
19 changed files with 251 additions and 205 deletions

View File

@@ -105,6 +105,8 @@ export const { use: useGlobalSDK, provider: GlobalSDKProvider } = createSimpleCo
const aborted = (error: unknown) => abortError.safeParse(error).success
let attempt: AbortController | undefined
let run: Promise<void> | undefined
let started = false
const HEARTBEAT_TIMEOUT_MS = 15_000
let lastEventAt = Date.now()
let heartbeat: ReturnType<typeof setTimeout> | undefined
@@ -121,78 +123,93 @@ export const { use: useGlobalSDK, provider: GlobalSDKProvider } = createSimpleCo
heartbeat = undefined
}
void (async () => {
while (!abort.signal.aborted) {
attempt = new AbortController()
lastEventAt = Date.now()
const onAbort = () => {
attempt?.abort()
}
abort.signal.addEventListener("abort", onAbort)
try {
const events = await eventSdk.global.event({
signal: attempt.signal,
onSseError: (error) => {
if (aborted(error)) return
if (streamErrorLogged) return
const start = () => {
if (started) return run
started = true
run = (async () => {
while (!abort.signal.aborted && started) {
attempt = new AbortController()
lastEventAt = Date.now()
const onAbort = () => {
attempt?.abort()
}
abort.signal.addEventListener("abort", onAbort)
try {
const events = await eventSdk.global.event({
signal: attempt.signal,
onSseError: (error) => {
if (aborted(error)) return
if (streamErrorLogged) return
streamErrorLogged = true
console.error("[global-sdk] event stream error", {
url: currentServer.http.url,
fetch: eventFetch ? "platform" : "webview",
error,
})
},
})
let yielded = Date.now()
resetHeartbeat()
for await (const event of events.stream) {
resetHeartbeat()
streamErrorLogged = false
const directory = event.directory ?? "global"
const payload = event.payload
const k = key(directory, payload)
if (k) {
const i = coalesced.get(k)
if (i !== undefined) {
queue[i] = { directory, payload }
if (payload.type === "message.part.updated") {
const part = payload.properties.part
staleDeltas.add(deltaKey(directory, part.messageID, part.id))
}
continue
}
coalesced.set(k, queue.length)
}
queue.push({ directory, payload })
schedule()
if (Date.now() - yielded < STREAM_YIELD_MS) continue
yielded = Date.now()
await wait(0)
}
} catch (error) {
if (!aborted(error) && !streamErrorLogged) {
streamErrorLogged = true
console.error("[global-sdk] event stream error", {
console.error("[global-sdk] event stream failed", {
url: currentServer.http.url,
fetch: eventFetch ? "platform" : "webview",
error,
})
},
})
let yielded = Date.now()
resetHeartbeat()
for await (const event of events.stream) {
resetHeartbeat()
streamErrorLogged = false
const directory = event.directory ?? "global"
const payload = event.payload
const k = key(directory, payload)
if (k) {
const i = coalesced.get(k)
if (i !== undefined) {
queue[i] = { directory, payload }
if (payload.type === "message.part.updated") {
const part = payload.properties.part
staleDeltas.add(deltaKey(directory, part.messageID, part.id))
}
continue
}
coalesced.set(k, queue.length)
}
queue.push({ directory, payload })
schedule()
} finally {
abort.signal.removeEventListener("abort", onAbort)
attempt = undefined
clearHeartbeat()
}
if (Date.now() - yielded < STREAM_YIELD_MS) continue
yielded = Date.now()
await wait(0)
}
} catch (error) {
if (!aborted(error) && !streamErrorLogged) {
streamErrorLogged = true
console.error("[global-sdk] event stream failed", {
url: currentServer.http.url,
fetch: eventFetch ? "platform" : "webview",
error,
})
}
} finally {
abort.signal.removeEventListener("abort", onAbort)
attempt = undefined
clearHeartbeat()
if (abort.signal.aborted || !started) return
await wait(RECONNECT_DELAY_MS)
}
})().finally(() => {
run = undefined
flush()
})
return run
}
if (abort.signal.aborted) return
await wait(RECONNECT_DELAY_MS)
}
})().finally(flush)
const stop = () => {
started = false
attempt?.abort()
clearHeartbeat()
}
const onVisibility = () => {
if (typeof document === "undefined") return
if (document.visibilityState !== "visible") return
if (!started) return
if (Date.now() - lastEventAt < HEARTBEAT_TIMEOUT_MS) return
attempt?.abort()
}
@@ -204,6 +221,7 @@ export const { use: useGlobalSDK, provider: GlobalSDKProvider } = createSimpleCo
if (typeof document !== "undefined") {
document.removeEventListener("visibilitychange", onVisibility)
}
stop()
abort.abort()
flush()
})
@@ -217,7 +235,11 @@ export const { use: useGlobalSDK, provider: GlobalSDKProvider } = createSimpleCo
return {
url: currentServer.http.url,
client: sdk,
event: emitter,
event: {
on: emitter.on.bind(emitter),
listen: emitter.listen.bind(emitter),
start,
},
createClient(opts: Omit<Parameters<typeof createSdkForServer>[0], "server" | "fetch">) {
const s = server.current
if (!s) throw new Error(language.t("error.globalSDK.serverNotAvailable"))

View File

@@ -72,10 +72,16 @@ function createGlobalSync() {
let projectWritten = false
let bootedAt = 0
let bootingRoot = false
let eventFrame: number | undefined
let eventTimer: ReturnType<typeof setTimeout> | undefined
onCleanup(() => {
active = false
})
onCleanup(() => {
if (eventFrame !== undefined) cancelAnimationFrame(eventFrame)
if (eventTimer !== undefined) clearTimeout(eventTimer)
})
const cacheProjects = () => {
setProjectCache(
@@ -348,6 +354,20 @@ function createGlobalSync() {
}
onMount(() => {
if (typeof requestAnimationFrame === "function") {
eventFrame = requestAnimationFrame(() => {
eventFrame = undefined
eventTimer = setTimeout(() => {
eventTimer = undefined
globalSDK.event.start()
}, 0)
})
} else {
eventTimer = setTimeout(() => {
eventTimer = undefined
globalSDK.event.start()
}, 0)
}
void bootstrap()
})

View File

@@ -43,8 +43,10 @@ function waitForPaint() {
const timer = setTimeout(finish, 50)
if (typeof requestAnimationFrame !== "function") return
requestAnimationFrame(() => {
clearTimeout(timer)
finish()
setTimeout(() => {
clearTimeout(timer)
finish()
}, 0)
})
})
}
@@ -87,12 +89,6 @@ export async function bootstrapGlobal(input: {
setGlobalStore: SetStoreFunction<GlobalStore>
}) {
const fast = [
() =>
retry(() =>
input.globalSDK.path.get().then((x) => {
input.setGlobalStore("path", x.data!)
}),
),
() =>
retry(() =>
input.globalSDK.global.config.get().then((x) => {
@@ -108,6 +104,12 @@ export async function bootstrapGlobal(input: {
]
const slow = [
() =>
retry(() =>
input.globalSDK.path.get().then((x) => {
input.setGlobalStore("path", x.data!)
}),
),
() =>
retry(() =>
input.globalSDK.project.list().then((x) => {
@@ -221,12 +223,16 @@ export async function bootstrapDirectory(input: {
if (loading) input.setStore("status", "partial")
const fast = [
() => retry(() => input.sdk.app.agents().then((x) => input.setStore("agent", normalizeAgentList(x.data)))),
() => retry(() => input.sdk.config.get().then((x) => input.setStore("config", x.data!))),
() => retry(() => input.sdk.session.status().then((x) => input.setStore("session_status", x.data!))),
]
const slow = [
() =>
seededProject
? Promise.resolve()
: retry(() => input.sdk.project.current()).then((x) => input.setStore("project", x.data!.id)),
() => retry(() => input.sdk.app.agents().then((x) => input.setStore("agent", normalizeAgentList(x.data)))),
() => retry(() => input.sdk.config.get().then((x) => input.setStore("config", x.data!))),
() =>
seededPath
? Promise.resolve()
@@ -237,7 +243,6 @@ export async function bootstrapDirectory(input: {
if (next) input.setStore("project", next)
}),
),
() => retry(() => input.sdk.session.status().then((x) => input.setStore("session_status", x.data!))),
() =>
retry(() =>
input.sdk.vcs.get().then((x) => {
@@ -299,9 +304,6 @@ export async function bootstrapDirectory(input: {
)
}),
),
]
const slow = [
() => Promise.resolve(input.loadSessions(input.directory)),
() =>
retry(() =>

View File

@@ -544,12 +544,26 @@ export const { use: useLayout, provider: LayoutProvider } = createSimpleContext(
}
})
let sessionFrame: number | undefined
let sessionTimer: number | undefined
onMount(() => {
Promise.all(
server.projects.list().map((project) => {
return globalSync.project.loadSessions(project.worktree)
}),
)
sessionFrame = requestAnimationFrame(() => {
sessionFrame = undefined
sessionTimer = window.setTimeout(() => {
sessionTimer = undefined
void Promise.all(
server.projects.list().map((project) => {
return globalSync.project.loadSessions(project.worktree)
}),
)
}, 0)
})
})
onCleanup(() => {
if (sessionFrame !== undefined) cancelAnimationFrame(sessionFrame)
if (sessionTimer !== undefined) window.clearTimeout(sessionTimer)
})
return {

View File

@@ -94,7 +94,11 @@ export namespace ServerConnection {
export const { use: useServer, provider: ServerProvider } = createSimpleContext({
name: "Server",
init: (props: { defaultServer: ServerConnection.Key; servers?: Array<ServerConnection.Any> }) => {
init: (props: {
defaultServer: ServerConnection.Key
disableHealthCheck?: boolean
servers?: Array<ServerConnection.Any>
}) => {
const checkServerHealth = useCheckServerHealth()
const [store, setStore, _, ready] = persisted(
@@ -202,6 +206,10 @@ export const { use: useServer, provider: ServerProvider } = createSimpleContext(
const current_ = current()
if (!current_) return
if (props.disableHealthCheck) {
setState("healthy", true)
return
}
setState("healthy", undefined)
onCleanup(startHealthPolling(current_))
})

View File

@@ -32,8 +32,8 @@ export interface Settings {
}
appearance: {
fontSize: number
font: string
uiFont: string
mono: string
sans: string
}
keybinds: Record<string, string>
permissions: {
@@ -43,20 +43,18 @@ export interface Settings {
sounds: SoundSettings
}
export const monoDefault = "IBM Plex Mono"
export const sansDefault = "Inter"
export const monoDefault = "System Mono"
export const sansDefault = "System Sans"
const monoFallback =
'ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace'
const sansFallback = 'ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif'
const monoBase = `"${monoDefault}", "IBM Plex Mono Fallback", ${monoFallback}`
const sansBase = `"${sansDefault}", "Inter Fallback", ${sansFallback}`
const monoKey = "ibm-plex-mono"
const monoBase = monoFallback
const sansBase = sansFallback
function input(font: string | undefined, key?: string) {
if (!font || font === key || !font.trim()) return ""
return font
function input(font: string | undefined) {
return font ?? ""
}
function family(font: string) {
@@ -64,14 +62,14 @@ function family(font: string) {
return `"${font.replaceAll("\\", "\\\\").replaceAll('"', '\\"')}"`
}
function stack(font: string | undefined, base: string, key?: string) {
const value = input(font, key).trim()
function stack(font: string | undefined, base: string) {
const value = font?.trim() ?? ""
if (!value) return base
return `${family(value)}, ${base}`
}
export function monoInput(font: string | undefined) {
return input(font, monoKey)
return input(font)
}
export function sansInput(font: string | undefined) {
@@ -79,7 +77,7 @@ export function sansInput(font: string | undefined) {
}
export function monoFontFamily(font: string | undefined) {
return stack(font, monoBase, monoKey)
return stack(font, monoBase)
}
export function sansFontFamily(font: string | undefined) {
@@ -100,8 +98,8 @@ const defaultSettings: Settings = {
},
appearance: {
fontSize: 14,
font: "",
uiFont: "",
mono: "",
sans: "",
},
keybinds: {},
permissions: {
@@ -134,8 +132,8 @@ export const { use: useSettings, provider: SettingsProvider } = createSimpleCont
createEffect(() => {
if (typeof document === "undefined") return
const root = document.documentElement
root.style.setProperty("--font-family-mono", monoFontFamily(store.appearance?.font))
root.style.setProperty("--font-family-sans", sansFontFamily(store.appearance?.uiFont))
root.style.setProperty("--font-family-mono", monoFontFamily(store.appearance?.mono))
root.style.setProperty("--font-family-sans", sansFontFamily(store.appearance?.sans))
})
return {
@@ -189,13 +187,13 @@ export const { use: useSettings, provider: SettingsProvider } = createSimpleCont
setFontSize(value: number) {
setStore("appearance", "fontSize", value)
},
font: withFallback(() => store.appearance?.font, defaultSettings.appearance.font),
font: withFallback(() => store.appearance?.mono, defaultSettings.appearance.mono),
setFont(value: string) {
setStore("appearance", "font", value.trim() ? value : "")
setStore("appearance", "mono", value.trim() ? value : "")
},
uiFont: withFallback(() => store.appearance?.uiFont, defaultSettings.appearance.uiFont),
uiFont: withFallback(() => store.appearance?.sans, defaultSettings.appearance.sans),
setUIFont(value: string) {
setStore("appearance", "uiFont", value.trim() ? value : "")
setStore("appearance", "sans", value.trim() ? value : "")
},
},
keybinds: {