fix(compaction): validate recovered agent config state
Retry compaction recovery when model or tool state is still incomplete, and treat reasoning or tool-only assistant progress as valid output so no-text tail recovery does not misfire.
This commit is contained in:
@@ -0,0 +1,52 @@
|
||||
const MEANINGFUL_ASSISTANT_PART_TYPES = new Set([
|
||||
"reasoning",
|
||||
"tool",
|
||||
"tool_use",
|
||||
])
|
||||
|
||||
export type TailMonitorState = {
|
||||
currentMessageID?: string
|
||||
currentHasOutput: boolean
|
||||
consecutiveNoTextMessages: number
|
||||
lastCompactedAt?: number
|
||||
lastRecoveryAt?: number
|
||||
}
|
||||
|
||||
export function finalizeTrackedAssistantMessage(
|
||||
state: TailMonitorState,
|
||||
): number {
|
||||
if (!state.currentMessageID) {
|
||||
return state.consecutiveNoTextMessages
|
||||
}
|
||||
|
||||
state.consecutiveNoTextMessages = state.currentHasOutput
|
||||
? 0
|
||||
: state.consecutiveNoTextMessages + 1
|
||||
state.currentMessageID = undefined
|
||||
state.currentHasOutput = false
|
||||
|
||||
return state.consecutiveNoTextMessages
|
||||
}
|
||||
|
||||
export function shouldTreatAssistantPartAsOutput(part: {
|
||||
type?: string
|
||||
text?: string
|
||||
}): boolean {
|
||||
if (part.type === "text") {
|
||||
return !!part.text?.trim()
|
||||
}
|
||||
|
||||
return typeof part.type === "string" && MEANINGFUL_ASSISTANT_PART_TYPES.has(part.type)
|
||||
}
|
||||
|
||||
export function trackAssistantOutput(
|
||||
state: TailMonitorState,
|
||||
messageID?: string,
|
||||
): void {
|
||||
if (messageID && !state.currentMessageID) {
|
||||
state.currentMessageID = messageID
|
||||
}
|
||||
|
||||
state.currentHasOutput = true
|
||||
state.consecutiveNoTextMessages = 0
|
||||
}
|
||||
Reference in New Issue
Block a user