Reconcile permissions after message hydration
After loadMessages hydrates tool parts, reattach pending permissions to the correct tool-call part ids so ToolCall permission UI renders reliably.
This commit is contained in:
@@ -164,6 +164,34 @@ export function upsertPermissionV2(instanceId: string, permission: PermissionReq
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function reconcilePendingPermissionsV2(instanceId: string, sessionId?: string): void {
|
||||||
|
const store = messageStoreBus.getOrCreate(instanceId)
|
||||||
|
const pending = store.state.permissions.queue
|
||||||
|
if (!pending || pending.length === 0) return
|
||||||
|
|
||||||
|
for (const entry of pending) {
|
||||||
|
if (!entry || entry.partId) continue
|
||||||
|
const permission = entry.permission
|
||||||
|
if (!permission) continue
|
||||||
|
|
||||||
|
const permissionSessionId = (permission as any)?.sessionID ?? (permission as any)?.sessionId ?? undefined
|
||||||
|
if (sessionId && permissionSessionId && permissionSessionId !== sessionId) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
const messageId = entry.messageId ?? extractPermissionMessageId(permission)
|
||||||
|
const callId = extractPermissionCallId(permission)
|
||||||
|
const resolvedPartId = resolvePartIdFromCallId(store, messageId, callId)
|
||||||
|
if (!resolvedPartId) continue
|
||||||
|
|
||||||
|
store.upsertPermission({
|
||||||
|
...entry,
|
||||||
|
messageId,
|
||||||
|
partId: resolvedPartId,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export function removePermissionV2(instanceId: string, permissionId: string): void {
|
export function removePermissionV2(instanceId: string, permissionId: string): void {
|
||||||
if (!permissionId) return
|
if (!permissionId) return
|
||||||
const store = messageStoreBus.getOrCreate(instanceId)
|
const store = messageStoreBus.getOrCreate(instanceId)
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ import { DEFAULT_MODEL_OUTPUT_LIMIT, getDefaultModel, isModelValid } from "./ses
|
|||||||
import { normalizeMessagePart } from "./message-v2/normalizers"
|
import { normalizeMessagePart } from "./message-v2/normalizers"
|
||||||
import { updateSessionInfo } from "./message-v2/session-info"
|
import { updateSessionInfo } from "./message-v2/session-info"
|
||||||
import { deriveSessionStatusFromMessages } from "./session-status"
|
import { deriveSessionStatusFromMessages } from "./session-status"
|
||||||
import { seedSessionMessagesV2 } from "./message-v2/bridge"
|
import { seedSessionMessagesV2, reconcilePendingPermissionsV2 } from "./message-v2/bridge"
|
||||||
import { messageStoreBus } from "./message-v2/bus"
|
import { messageStoreBus } from "./message-v2/bus"
|
||||||
import { clearCacheForSession } from "../lib/global-cache"
|
import { clearCacheForSession } from "../lib/global-cache"
|
||||||
import { getLogger } from "../lib/logger"
|
import { getLogger } from "../lib/logger"
|
||||||
@@ -610,11 +610,15 @@ async function loadMessages(instanceId: string, sessionId: string, force = false
|
|||||||
}
|
}
|
||||||
seedSessionMessagesV2(instanceId, sessionForV2, messages, messagesInfo)
|
seedSessionMessagesV2(instanceId, sessionForV2, messages, messagesInfo)
|
||||||
|
|
||||||
|
// Permissions can be hydrated before messages/tool parts exist in the store.
|
||||||
|
// After message hydration, try to attach any pending permissions to tool-call part ids.
|
||||||
|
reconcilePendingPermissionsV2(instanceId, sessionId)
|
||||||
|
|
||||||
if (!alreadyLoaded) {
|
if (!alreadyLoaded) {
|
||||||
const nextStatus = deriveSessionStatusFromMessages(instanceId, sessionId)
|
const nextStatus = deriveSessionStatusFromMessages(instanceId, sessionId)
|
||||||
setSessionStatus(instanceId, sessionId, nextStatus)
|
setSessionStatus(instanceId, sessionId, nextStatus)
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
log.error("Failed to load messages:", error)
|
log.error("Failed to load messages:", error)
|
||||||
throw error
|
throw error
|
||||||
|
|||||||
Reference in New Issue
Block a user