Skip to content

Commit bba76e6

Browse files
committed
Fix older thread page edge cases
1 parent d4efb50 commit bba76e6

1 file changed

Lines changed: 51 additions & 6 deletions

File tree

src/server/codexAppServerBridge.ts

Lines changed: 51 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,7 @@ const COMPOSIO_CONNECTORS_PAGE_LIMIT_MAX = 1000
220220
const PROVIDER_MODELS_FETCH_TIMEOUT_MS = 5_000
221221

222222
const THREAD_RESPONSE_TURN_LIMIT = 10
223+
const THREAD_TURN_PAGE_READ_CACHE_TTL_MS = 30_000
223224
const THREAD_METHODS_WITH_TURNS = new Set(['thread/read', 'thread/resume', 'thread/fork', 'thread/rollback'])
224225
const THREAD_SEARCH_FULL_TEXT_THREAD_LIMIT = 100
225226
const PROJECTLESS_THREAD_DIRECTORY_MAX_ATTEMPTS = 100
@@ -4292,6 +4293,8 @@ class AppServerProcess {
42924293
private readonly appServerArgs = buildAppServerArgs()
42934294
private readonly streamEventsByThreadId = new Map<string, StreamEventFrame[]>()
42944295
private readonly lastThreadReadSnapshotByThreadId = new Map<string, unknown>()
4296+
private readonly threadTurnPageReadCacheByThreadId = new Map<string, { result: unknown; expiresAt: number }>()
4297+
private readonly threadTurnPageReadPromiseByThreadId = new Map<string, Promise<unknown>>()
42954298
private readonly capturedItemsByThreadId = new Map<string, Map<string, CapturedItem>>()
42964299
private readonly liveStateCache = new Map<string, { data: unknown; turnCount: number; sessionSize: number }>()
42974300
private chatgptAuthRefreshPromise: Promise<ChatgptAuthTokensRefreshResponse> | null = null
@@ -4427,7 +4430,10 @@ class AppServerProcess {
44274430
this.recordStreamEvent(notification)
44284431
this.captureItemFromNotification(notification)
44294432
const nThreadId = this.extractThreadIdFromParams(notification.params)
4430-
if (nThreadId) this.invalidateLiveStateCache(nThreadId)
4433+
if (nThreadId) {
4434+
this.invalidateLiveStateCache(nThreadId)
4435+
this.threadTurnPageReadCacheByThreadId.delete(nThreadId)
4436+
}
44314437
for (const listener of this.notificationListeners) {
44324438
listener(notification)
44334439
}
@@ -4481,12 +4487,39 @@ class AppServerProcess {
44814487

44824488
storeThreadReadSnapshot(threadId: string, snapshot: unknown): void {
44834489
this.lastThreadReadSnapshotByThreadId.set(threadId, snapshot)
4490+
this.threadTurnPageReadCacheByThreadId.delete(threadId)
44844491
}
44854492

44864493
getLastThreadReadSnapshot(threadId: string): unknown | null {
44874494
return this.lastThreadReadSnapshotByThreadId.get(threadId) ?? null
44884495
}
44894496

4497+
async readThreadForTurnPage(threadId: string): Promise<unknown> {
4498+
const now = Date.now()
4499+
const cached = this.threadTurnPageReadCacheByThreadId.get(threadId)
4500+
if (cached && cached.expiresAt > now) return cached.result
4501+
if (cached) this.threadTurnPageReadCacheByThreadId.delete(threadId)
4502+
4503+
const pending = this.threadTurnPageReadPromiseByThreadId.get(threadId)
4504+
if (pending) return pending
4505+
4506+
const promise = this.rpc('thread/read', {
4507+
threadId,
4508+
includeTurns: true,
4509+
}).then((result) => {
4510+
this.threadTurnPageReadCacheByThreadId.set(threadId, {
4511+
result,
4512+
expiresAt: Date.now() + THREAD_TURN_PAGE_READ_CACHE_TTL_MS,
4513+
})
4514+
return result
4515+
}).finally(() => {
4516+
this.threadTurnPageReadPromiseByThreadId.delete(threadId)
4517+
})
4518+
4519+
this.threadTurnPageReadPromiseByThreadId.set(threadId, promise)
4520+
return promise
4521+
}
4522+
44904523
cacheLiveState(threadId: string, data: unknown, turnCount: number, sessionSize: number): void {
44914524
this.liveStateCache.set(threadId, { data, turnCount, sessionSize })
44924525
}
@@ -5786,10 +5819,7 @@ export function createCodexBridgeMiddleware(): CodexBridgeMiddleware {
57865819
return
57875820
}
57885821

5789-
const threadReadResult = await appServer.rpc('thread/read', {
5790-
threadId,
5791-
includeTurns: true,
5792-
})
5822+
const threadReadResult = await appServer.readThreadForTurnPage(threadId)
57935823
const record = asRecord(threadReadResult)
57945824
const thread = asRecord(record?.thread)
57955825
if (!record || !thread) {
@@ -5801,7 +5831,22 @@ export function createCodexBridgeMiddleware(): CodexBridgeMiddleware {
58015831
const beforeIndex = beforeTurnId
58025832
? turns.findIndex((turn) => asRecord(turn)?.id === beforeTurnId)
58035833
: turns.length
5804-
const endIndex = beforeIndex >= 0 ? beforeIndex : turns.length
5834+
if (beforeTurnId && beforeIndex < 0) {
5835+
setJson(res, 200, {
5836+
result: {
5837+
...record,
5838+
thread: {
5839+
...thread,
5840+
turns: [],
5841+
},
5842+
},
5843+
startTurnIndex: 0,
5844+
hasMoreOlder: false,
5845+
})
5846+
return
5847+
}
5848+
5849+
const endIndex = beforeIndex
58055850
const startIndex = Math.max(0, endIndex - limit)
58065851
const pageTurns = turns.slice(startIndex, endIndex)
58075852
const pagedResult = {

0 commit comments

Comments
 (0)