mirror of
https://github.com/Kilo-Org/kilocode.git
synced 2026-08-28 19:11:03 +08:00
fix(vscode): bound sync filter state
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"kilo-code": patch
|
||||
---
|
||||
|
||||
Prevent duplicate-event tracking from suppressing delayed sync events after reconnects or high event bursts.
|
||||
@@ -96,7 +96,6 @@ export class KiloConnectionService {
|
||||
private remoteService: import("../RemoteStatusService").RemoteStatusService | null = null
|
||||
|
||||
private readonly eventListeners: Set<SSEEventListener> = new Set()
|
||||
private readonly duplicateEvent = createDuplicateEventFilter()
|
||||
private readonly stateListeners: Set<StateListener> = new Set()
|
||||
private readonly notificationDismissListeners: Set<NotificationDismissListener> = new Set()
|
||||
private readonly languageChangeListeners: Set<LanguageChangeListener> = new Set()
|
||||
@@ -821,6 +820,7 @@ export class KiloConnectionService {
|
||||
},
|
||||
})
|
||||
const sse = new SdkSSEAdapter(client)
|
||||
const duplicateEvent = createDuplicateEventFilter()
|
||||
this.client = client
|
||||
this.sseClient = sse
|
||||
|
||||
@@ -839,7 +839,7 @@ export class KiloConnectionService {
|
||||
sse.onEvent((event, directory) => {
|
||||
if (this.sseClient !== sse) return
|
||||
// EventV2Bridge also emits these durable compatibility envelopes after their normal live events.
|
||||
if (this.duplicateEvent(event)) return
|
||||
if (duplicateEvent(event)) return
|
||||
this.handlePermissionEvent(event, directory)
|
||||
this.handleQuestionEvent(event, directory)
|
||||
for (const listener of this.eventListeners) {
|
||||
|
||||
@@ -24,8 +24,7 @@ export function createDuplicateEventFilter() {
|
||||
}
|
||||
|
||||
if (duplicateLiveEvents.has(event.type)) {
|
||||
seen.add(event.id)
|
||||
if (seen.size > DUPLICATE_EVENT_LIMIT) seen.delete(seen.values().next().value!)
|
||||
if (seen.size < DUPLICATE_EVENT_LIMIT) seen.add(event.id)
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -173,7 +173,7 @@ describe("resolveEventSessionId", () => {
|
||||
})
|
||||
})
|
||||
|
||||
describe("isDuplicateSyncEvent", () => {
|
||||
describe("createDuplicateEventFilter", () => {
|
||||
it("drops a compatibility envelope only after its live event", () => {
|
||||
const filter = createDuplicateEventFilter()
|
||||
const live = {
|
||||
@@ -233,4 +233,137 @@ describe("isDuplicateSyncEvent", () => {
|
||||
),
|
||||
).toBe(false)
|
||||
})
|
||||
|
||||
it("does not evict pending live events when the cap is reached", () => {
|
||||
const filter = createDuplicateEventFilter()
|
||||
for (let index = 0; index < 1024; index++) {
|
||||
expect(
|
||||
filter({
|
||||
id: `live-${index}`,
|
||||
type: "message.part.updated",
|
||||
properties: { sessionID: "s6", part, delta: "x" },
|
||||
}),
|
||||
).toBe(false)
|
||||
}
|
||||
|
||||
expect(
|
||||
filter(
|
||||
sync({
|
||||
type: "sync",
|
||||
name: "message.part.updated.1",
|
||||
id: "live-0",
|
||||
seq: 8,
|
||||
aggregateID: "s6",
|
||||
data: { sessionID: "s6", part, time: 0 },
|
||||
}),
|
||||
),
|
||||
).toBe(true)
|
||||
expect(
|
||||
filter({
|
||||
id: "live-1024",
|
||||
type: "message.part.updated",
|
||||
properties: { sessionID: "s6", part, delta: "x" },
|
||||
}),
|
||||
).toBe(false)
|
||||
expect(
|
||||
filter(
|
||||
sync({
|
||||
type: "sync",
|
||||
name: "message.part.updated.1",
|
||||
id: "live-1024",
|
||||
seq: 9,
|
||||
aggregateID: "s6",
|
||||
data: { sessionID: "s6", part, time: 0 },
|
||||
}),
|
||||
),
|
||||
).toBe(true)
|
||||
})
|
||||
|
||||
it("passes overflow events through without evicting pending IDs", () => {
|
||||
const filter = createDuplicateEventFilter()
|
||||
for (let index = 0; index < 1024; index++) {
|
||||
expect(
|
||||
filter({
|
||||
id: `pending-${index}`,
|
||||
type: "message.part.updated",
|
||||
properties: { sessionID: "s6", part, delta: "x" },
|
||||
}),
|
||||
).toBe(false)
|
||||
}
|
||||
|
||||
expect(
|
||||
filter({
|
||||
id: "overflow",
|
||||
type: "message.part.updated",
|
||||
properties: { sessionID: "s6", part, delta: "x" },
|
||||
}),
|
||||
).toBe(false)
|
||||
expect(
|
||||
filter(
|
||||
sync({
|
||||
type: "sync",
|
||||
name: "message.part.updated.1",
|
||||
id: "overflow",
|
||||
seq: 8,
|
||||
aggregateID: "s6",
|
||||
data: { sessionID: "s6", part, time: 0 },
|
||||
}),
|
||||
),
|
||||
).toBe(false)
|
||||
expect(
|
||||
filter(
|
||||
sync({
|
||||
type: "sync",
|
||||
name: "message.part.updated.1",
|
||||
id: "pending-0",
|
||||
seq: 9,
|
||||
aggregateID: "s6",
|
||||
data: { sessionID: "s6", part, time: 0 },
|
||||
}),
|
||||
),
|
||||
).toBe(true)
|
||||
expect(
|
||||
filter({
|
||||
id: "after-free",
|
||||
type: "message.part.updated",
|
||||
properties: { sessionID: "s6", part, delta: "x" },
|
||||
}),
|
||||
).toBe(false)
|
||||
expect(
|
||||
filter(
|
||||
sync({
|
||||
type: "sync",
|
||||
name: "message.part.updated.1",
|
||||
id: "after-free",
|
||||
seq: 10,
|
||||
aggregateID: "s6",
|
||||
data: { sessionID: "s6", part, time: 0 },
|
||||
}),
|
||||
),
|
||||
).toBe(true)
|
||||
})
|
||||
|
||||
it("does not carry duplicate IDs between connections", () => {
|
||||
const first = createDuplicateEventFilter()
|
||||
const second = createDuplicateEventFilter()
|
||||
const live = {
|
||||
id: "connection-event",
|
||||
type: "message.part.updated",
|
||||
properties: { sessionID: "s6", part, delta: "x" },
|
||||
} satisfies Payload
|
||||
|
||||
expect(first(live)).toBe(false)
|
||||
expect(
|
||||
second(
|
||||
sync({
|
||||
type: "sync",
|
||||
name: "message.part.updated.1",
|
||||
id: "connection-event",
|
||||
seq: 11,
|
||||
aggregateID: "s6",
|
||||
data: { sessionID: "s6", part, time: 0 },
|
||||
}),
|
||||
),
|
||||
).toBe(false)
|
||||
})
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user