Backup before continuing from Codex 5.2 session - User storage, compaction suggestions, streaming improvements

This commit is contained in:
Gemini AI
2025-12-24 21:27:05 +04:00
Unverified
parent f9748391a9
commit e8c38b0add
93 changed files with 10615 additions and 2037 deletions

View File

@@ -19,12 +19,13 @@ import { getLogger } from "../lib/logger"
import { showToastNotification, ToastVariant } from "../lib/notifications"
import { instances, addPermissionToQueue, removePermissionFromQueue, sendPermissionResponse } from "./instances"
import { getSoloState, incrementStep, popFromTaskQueue, setActiveTaskId } from "./solo-store"
import { sendMessage } from "./session-actions"
import { sendMessage, consumeTokenWarningSuppression, consumeCompactionSuppression, updateSessionModel } from "./session-actions"
import { showAlertDialog } from "./alerts"
import { sessions, setSessions, withSession } from "./session-state"
import { normalizeMessagePart } from "./message-v2/normalizers"
import { updateSessionInfo } from "./message-v2/session-info"
import { addTaskMessage, replaceTaskMessageId } from "./task-actions"
import { checkAndTriggerAutoCompact, getSessionCompactionState, setCompactionSuggestion } from "./session-compaction"
const log = getLogger("sse")
import { loadMessages } from "./session-api"
@@ -39,6 +40,7 @@ import {
} from "./message-v2/bridge"
import { messageStoreBus } from "./message-v2/bus"
import type { InstanceMessageStore } from "./message-v2/instance-store"
import { getDefaultModel } from "./session-models"
interface TuiToastEvent {
type: "tui.toast.show"
@@ -232,6 +234,16 @@ function handleMessageUpdate(instanceId: string, event: MessageUpdateEvent | Mes
upsertMessageInfoV2(instanceId, info, { status, bumpRevision: true })
updateSessionInfo(instanceId, sessionId)
checkAndTriggerAutoCompact(instanceId, sessionId)
.then((shouldCompact) => {
if (!shouldCompact) return
if (getSessionCompactionState(instanceId, sessionId)) return
setCompactionSuggestion(instanceId, sessionId, "Context usage is high. Compact to continue.")
})
.catch((err) => {
log.error("Failed to check and trigger auto-compact", err)
})
}
}
@@ -389,6 +401,21 @@ function handleSessionCompacted(instanceId: string, event: EventSessionCompacted
})
}
function isContextLengthError(error: any): boolean {
if (!error) return false
const errorMessage = error.data?.message || error.message || ""
return (
errorMessage.includes("maximum context length") ||
errorMessage.includes("context_length_exceeded") ||
errorMessage.includes("token count exceeds") ||
errorMessage.includes("token limit")
)
}
function isUnsupportedModelMessage(message: string): boolean {
return /model\s+.+\s+not supported/i.test(message)
}
function handleSessionError(instanceId: string, event: EventSessionError): void {
const error = event.properties?.error
log.error(`[SSE] Session error:`, error)
@@ -406,18 +433,73 @@ function handleSessionError(instanceId: string, event: EventSessionError): void
// Autonomous error recovery for SOLO
const solo = getSoloState(instanceId)
const sessionId = (event.properties as any)?.sessionID
if (solo.isAutonomous && sessionId && solo.currentStep < solo.maxSteps) {
log.info(`[SOLO] Session error in autonomous mode, prompting fix: ${message}`)
incrementStep(instanceId)
sendMessage(instanceId, sessionId, `I encountered an error: "${message}". Please analyze the cause and provide a fix.`, [], solo.activeTaskId || undefined).catch((err) => {
log.error("[SOLO] Failed to send error recovery message", err)
})
} else {
showAlertDialog(`Error: ${message}`, {
title: "Session error",
variant: "error",
})
return
}
// Check if this is a context length error
if (isContextLengthError(error)) {
if (sessionId && consumeCompactionSuppression(instanceId, sessionId)) {
showAlertDialog("Compaction failed because the model context limit was exceeded. Reduce context or switch to a larger context model, then try compact again.", {
title: "Compaction failed",
variant: "error",
})
return
}
if (sessionId && consumeTokenWarningSuppression(instanceId, sessionId)) {
showToastNotification({
title: "Context limit exceeded",
message: "Compaction is required before continuing.",
variant: "warning",
duration: 7000,
})
return
}
log.info("Context length error detected; suggesting compaction", { instanceId, sessionId })
if (sessionId) {
setCompactionSuggestion(instanceId, sessionId, "Context limit exceeded. Compact to continue.")
showToastNotification({
title: "Compaction required",
message: "Click Compact to continue this session.",
variant: "warning",
duration: 8000,
})
} else {
showAlertDialog(`Error: ${message}`, {
title: "Session error",
variant: "error",
})
}
return
}
if (sessionId && isUnsupportedModelMessage(message)) {
showToastNotification({
title: "Model not supported",
message: "Selected model is not supported by this provider. Reverting to a default model.",
variant: "warning",
duration: 8000,
})
const sessionRecord = sessions().get(instanceId)?.get(sessionId)
getDefaultModel(instanceId, sessionRecord?.agent)
.then((fallback) => updateSessionModel(instanceId, sessionId, fallback))
.catch((err) => log.error("Failed to restore default model after unsupported model error", err))
return
}
// Default error handling
showAlertDialog(`Error: ${message}`, {
title: "Session error",
variant: "error",
})
}
function handleMessageRemoved(instanceId: string, event: MessageRemovedEvent): void {