Merge pull request #2212 from code-yeongyu/fix/h5-collector-ordering

fix(context-injector): use monotonic registration order instead of timestamp for deterministic sorting
This commit is contained in:
YeonGyu-Kim
2026-02-28 13:40:20 +09:00
committed by GitHub
3 changed files with 45 additions and 4 deletions

View File

@@ -205,6 +205,45 @@ describe("ContextCollector", () => {
const ids = pending.entries.map((e) => e.id)
expect(ids).toEqual(["first", "second", "third"])
})
it("keeps registration order even when Date.now values are not monotonic", () => {
// given
const sessionID = "ses_order_non_monotonic_time"
const originalDateNow = Date.now
const mockedTimestamps = [300, 100, 200]
let timestampIndex = 0
Date.now = () => mockedTimestamps[timestampIndex++] ?? 0
try {
collector.register(sessionID, {
id: "first",
source: "custom",
content: "First",
priority: "normal",
})
collector.register(sessionID, {
id: "second",
source: "custom",
content: "Second",
priority: "normal",
})
collector.register(sessionID, {
id: "third",
source: "custom",
content: "Third",
priority: "normal",
})
} finally {
Date.now = originalDateNow
}
// when
const pending = collector.getPending(sessionID)
// then
const ids = pending.entries.map((entry) => entry.id)
expect(ids).toEqual(["first", "second", "third"])
})
})
describe("consume", () => {

View File

@@ -14,6 +14,8 @@ const PRIORITY_ORDER: Record<ContextPriority, number> = {
const CONTEXT_SEPARATOR = "\n\n---\n\n"
let registrationCounter = 0
export class ContextCollector {
private sessions: Map<string, Map<string, ContextEntry>> = new Map()
@@ -30,7 +32,7 @@ export class ContextCollector {
source: options.source,
content: options.content,
priority: options.priority ?? "normal",
timestamp: Date.now(),
registrationOrder: ++registrationCounter,
metadata: options.metadata,
}
@@ -77,7 +79,7 @@ export class ContextCollector {
return entries.sort((a, b) => {
const priorityDiff = PRIORITY_ORDER[a.priority] - PRIORITY_ORDER[b.priority]
if (priorityDiff !== 0) return priorityDiff
return a.timestamp - b.timestamp
return a.registrationOrder - b.registrationOrder
})
}
}

View File

@@ -27,8 +27,8 @@ export interface ContextEntry {
content: string
/** Priority for ordering (default: normal) */
priority: ContextPriority
/** Timestamp when registered */
timestamp: number
/** Monotonic order when registered */
registrationOrder: number
/** Optional metadata for debugging/logging */
metadata?: Record<string, unknown>
}