mirror of
https://github.com/Kilo-Org/kilocode.git
synced 2026-09-19 10:02:04 +08:00
Merge pull request #12950 from Kilo-Org/fix/tui-disposal-abort-log
fix(tui): suppress expected disposal aborts
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"@kilocode/cli": patch
|
||||
---
|
||||
|
||||
Avoid printing an error when closing the TUI cancels in-flight startup refreshes.
|
||||
@@ -64,6 +64,23 @@ export function eventLocation(metadata: { directory: string; workspace?: string
|
||||
}
|
||||
// kilocode_change end
|
||||
|
||||
// kilocode_change start - suppress only refreshes canceled by normal TUI disposal
|
||||
export function shouldReportDefaultLocationFailure(reason: unknown, disposed: boolean) {
|
||||
if (!disposed) return true
|
||||
return !(typeof reason === "object" && reason !== null && "name" in reason && reason.name === "AbortError")
|
||||
}
|
||||
|
||||
export async function reportDefaultLocationFailure(
|
||||
promise: Promise<void>,
|
||||
disposed: () => boolean,
|
||||
report: (reason: unknown) => void = (reason) => console.error("Failed to refresh default location data", reason),
|
||||
) {
|
||||
return promise.catch((reason) => {
|
||||
if (shouldReportDefaultLocationFailure(reason, disposed())) report(reason)
|
||||
})
|
||||
}
|
||||
// kilocode_change end
|
||||
|
||||
export const { use: useData, provider: DataProvider } = createSimpleContext({
|
||||
name: "Data",
|
||||
init: () => {
|
||||
@@ -575,21 +592,26 @@ export const { use: useData, provider: DataProvider } = createSimpleContext({
|
||||
},
|
||||
}
|
||||
|
||||
onMount(() => {
|
||||
void Promise.allSettled([
|
||||
result.location.refresh(),
|
||||
result.location.agent.refresh(),
|
||||
result.location.integration.refresh(),
|
||||
result.location.model.refresh(),
|
||||
result.location.provider.refresh(),
|
||||
result.location.reference.refresh(),
|
||||
result.location.command.refresh(),
|
||||
result.location.skill.refresh(),
|
||||
]).then((settled) => {
|
||||
for (const failure of settled.filter((item) => item.status === "rejected"))
|
||||
console.error("Failed to refresh default location data", failure.reason)
|
||||
})
|
||||
// kilocode_change start - classify each rejection when it occurs so later disposal cannot hide earlier failures
|
||||
let disposed = false
|
||||
onCleanup(() => {
|
||||
disposed = true
|
||||
})
|
||||
// kilocode_change end
|
||||
// kilocode_change start
|
||||
onMount(() => {
|
||||
void Promise.all([
|
||||
reportDefaultLocationFailure(result.location.refresh(), () => disposed),
|
||||
reportDefaultLocationFailure(result.location.agent.refresh(), () => disposed),
|
||||
reportDefaultLocationFailure(result.location.integration.refresh(), () => disposed),
|
||||
reportDefaultLocationFailure(result.location.model.refresh(), () => disposed),
|
||||
reportDefaultLocationFailure(result.location.provider.refresh(), () => disposed),
|
||||
reportDefaultLocationFailure(result.location.reference.refresh(), () => disposed),
|
||||
reportDefaultLocationFailure(result.location.command.refresh(), () => disposed),
|
||||
reportDefaultLocationFailure(result.location.skill.refresh(), () => disposed),
|
||||
])
|
||||
})
|
||||
// kilocode_change end
|
||||
|
||||
return result
|
||||
},
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { describe, expect, test } from "bun:test"
|
||||
import { eventLocation } from "../../src/context/data"
|
||||
import { eventLocation, reportDefaultLocationFailure, shouldReportDefaultLocationFailure } from "../../src/context/data"
|
||||
|
||||
describe("eventLocation", () => {
|
||||
test("uses the default location for global events", () => {
|
||||
@@ -13,3 +13,47 @@ describe("eventLocation", () => {
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe("shouldReportDefaultLocationFailure", () => {
|
||||
test("suppresses lifecycle aborts after disposal", () => {
|
||||
expect(shouldReportDefaultLocationFailure(new DOMException("aborted", "AbortError"), true)).toBe(false)
|
||||
})
|
||||
|
||||
test("suppresses cross-realm-shaped lifecycle aborts after disposal", () => {
|
||||
expect(shouldReportDefaultLocationFailure({ name: "AbortError" }, true)).toBe(false)
|
||||
})
|
||||
|
||||
test("reports aborts while mounted", () => {
|
||||
expect(shouldReportDefaultLocationFailure(new DOMException("aborted", "AbortError"), false)).toBe(true)
|
||||
})
|
||||
|
||||
test("reports non-abort failures after disposal", () => {
|
||||
expect(shouldReportDefaultLocationFailure(new Error("network failed"), true)).toBe(true)
|
||||
})
|
||||
})
|
||||
|
||||
describe("reportDefaultLocationFailure", () => {
|
||||
test("reports a mounted abort immediately even if disposal happens before other refreshes settle", async () => {
|
||||
let disposed = false
|
||||
const reports: unknown[] = []
|
||||
const abort = Promise.reject(new DOMException("aborted", "AbortError"))
|
||||
const pending = Promise.withResolvers<void>()
|
||||
|
||||
const first = reportDefaultLocationFailure(
|
||||
abort,
|
||||
() => disposed,
|
||||
(reason) => reports.push(reason),
|
||||
)
|
||||
await first
|
||||
disposed = true
|
||||
pending.reject(new DOMException("aborted", "AbortError"))
|
||||
await reportDefaultLocationFailure(
|
||||
pending.promise,
|
||||
() => disposed,
|
||||
(reason) => reports.push(reason),
|
||||
)
|
||||
|
||||
expect(reports).toHaveLength(1)
|
||||
expect(reports[0]).toBeInstanceOf(DOMException)
|
||||
})
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user