fix: resolve 3 community-reported bugs (#2915, #2917, #2918)

- background_output: snapshot read cursor before consuming, restore on
  /undo message removal so re-reads return data (fixes #2915)
- MCP loader: preserve oauth field in transformMcpServer, add scope/
  projectPath filtering so local-scoped MCPs only load in matching
  directories (fixes #2917)
- runtime-fallback: add 'reached your usage limit' to retryable error
  patterns so quota exhaustion triggers model fallback (fixes #2918)

Verified: bun test (4606 pass / 0 fail), tsc --noEmit clean
This commit is contained in:
YeonGyu-Kim
2026-03-29 04:53:36 +09:00
parent 9fc56ab544
commit b2497f1327
16 changed files with 575 additions and 6 deletions
+24 -1
View File
@@ -13,13 +13,21 @@ export type CursorMessage = {
info?: MessageInfo
}
interface CursorState {
export interface CursorState {
lastKey?: string
lastCount: number
}
const sessionCursors = new Map<string, CursorState>()
function cloneCursorState(state: CursorState | undefined): CursorState | undefined {
if (!state) return undefined
return {
lastKey: state.lastKey,
lastCount: state.lastCount,
}
}
function buildMessageKey(message: CursorMessage, index: number): string {
const id = message.info?.id
if (id) return `id:${id}`
@@ -83,3 +91,18 @@ export function resetMessageCursor(sessionID?: string): void {
}
sessionCursors.clear()
}
export function getMessageCursor(sessionID: string | undefined): CursorState | undefined {
if (!sessionID) return undefined
return cloneCursorState(sessionCursors.get(sessionID))
}
export function restoreMessageCursor(sessionID: string | undefined, cursor: CursorState | undefined): void {
if (!sessionID) return
if (!cursor) {
sessionCursors.delete(sessionID)
return
}
sessionCursors.set(sessionID, cloneCursorState(cursor)!)
}