blank session cleanup improvements
- make the blank session cleanup system optionally fetch full message histories for each session to better judge if it's blank - make a command that does the deep clean, keep the clean that happens on new session creation shallow
This commit is contained in:
committed by
Alexis Purslane
parent
f633d75005
commit
50676416ed
10
.dir-locals.el
Normal file
10
.dir-locals.el
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
((typescript-ts-mode
|
||||||
|
. ((eglot-workspace-configuration
|
||||||
|
. (:typescript.format (:indentSize 2
|
||||||
|
:tabSize 2
|
||||||
|
:convertTabsToSpaces t
|
||||||
|
:semicolons "remove")
|
||||||
|
:javascript.format (:indentSize 2
|
||||||
|
:tabSize 2
|
||||||
|
:convertTabsToSpaces t
|
||||||
|
:semicolons "remove"))))))
|
||||||
@@ -16,6 +16,7 @@ import { showAlertDialog } from "../../stores/alerts"
|
|||||||
import type { Instance } from "../../types/instance"
|
import type { Instance } from "../../types/instance"
|
||||||
import type { MessageRecord } from "../../stores/message-v2/types"
|
import type { MessageRecord } from "../../stores/message-v2/types"
|
||||||
import { messageStoreBus } from "../../stores/message-v2/bus"
|
import { messageStoreBus } from "../../stores/message-v2/bus"
|
||||||
|
import { cleanupBlankSessions } from "../../stores/session-state"
|
||||||
|
|
||||||
export interface UseCommandsOptions {
|
export interface UseCommandsOptions {
|
||||||
preferences: Accessor<Preferences>
|
preferences: Accessor<Preferences>
|
||||||
@@ -142,6 +143,19 @@ export function useCommands(options: UseCommandsOptions) {
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
|
commandRegistry.register({
|
||||||
|
id: "cleanup-blank-sessions",
|
||||||
|
label: "Cleanup Blank Sessions",
|
||||||
|
description: "Remove empty sessions from the current instance",
|
||||||
|
category: "Session",
|
||||||
|
keywords: ["cleanup", "blank", "empty", "sessions", "remove", "delete"],
|
||||||
|
action: async () => {
|
||||||
|
const instance = activeInstance()
|
||||||
|
if (!instance) return
|
||||||
|
await cleanupBlankSessions(instance.id, undefined, true)
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
commandRegistry.register({
|
commandRegistry.register({
|
||||||
id: "switch-to-info",
|
id: "switch-to-info",
|
||||||
label: "Instance Info",
|
label: "Instance Info",
|
||||||
|
|||||||
@@ -407,27 +407,6 @@ async function deleteSession(instanceId: string, sessionId: string): Promise<voi
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function cleanupBlankSessions(instanceId: string, excludeSessionId?: string): Promise<void> {
|
|
||||||
const instanceSessions = sessions().get(instanceId)
|
|
||||||
if (!instanceSessions) return
|
|
||||||
|
|
||||||
const deletionPromises: Promise<void>[] = []
|
|
||||||
|
|
||||||
for (const [sessionId, session] of instanceSessions) {
|
|
||||||
if (sessionId === excludeSessionId) continue
|
|
||||||
if (!isBlankSession(session, instanceId)) continue
|
|
||||||
|
|
||||||
deletionPromises.push(deleteSession(instanceId, sessionId).catch((error) => {
|
|
||||||
console.error(`Failed to delete blank session ${sessionId}:`, error)
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
|
|
||||||
if (deletionPromises.length > 0) {
|
|
||||||
console.log(`Cleaning up ${deletionPromises.length} blank sessions`)
|
|
||||||
await Promise.all(deletionPromises)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async function fetchAgents(instanceId: string): Promise<void> {
|
async function fetchAgents(instanceId: string): Promise<void> {
|
||||||
const instance = instances().get(instanceId)
|
const instance = instances().get(instanceId)
|
||||||
if (!instance || !instance.client) {
|
if (!instance || !instance.client) {
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
import { createSignal } from "solid-js"
|
import { createSignal } from "solid-js"
|
||||||
|
|
||||||
import type { Session, Agent, Provider } from "../types/session"
|
import type { Session, Agent, Provider } from "../types/session"
|
||||||
|
import { loadMessages, deleteSession } from "./session-api"
|
||||||
|
import { showToastNotification } from "../lib/notifications"
|
||||||
|
|
||||||
export interface SessionInfo {
|
export interface SessionInfo {
|
||||||
cost: number
|
cost: number
|
||||||
@@ -221,7 +223,7 @@ function getSessionInfo(instanceId: string, sessionId: string): SessionInfo | un
|
|||||||
return sessionInfoByInstance().get(instanceId)?.get(sessionId)
|
return sessionInfoByInstance().get(instanceId)?.get(sessionId)
|
||||||
}
|
}
|
||||||
|
|
||||||
function isBlankSession(session: Session, instanceId: string): boolean {
|
async function isBlankSession(session: Session, instanceId: string, fetchIfNeeded = false): Promise<boolean> {
|
||||||
if (session.parentId === null) {
|
if (session.parentId === null) {
|
||||||
// Parent session is only blank if actually blank AND has no children
|
// Parent session is only blank if actually blank AND has no children
|
||||||
|
|
||||||
@@ -234,7 +236,10 @@ function isBlankSession(session: Session, instanceId: string): boolean {
|
|||||||
// Subagent
|
// Subagent
|
||||||
|
|
||||||
const loadedSet = messagesLoaded().get(instanceId) || new Set()
|
const loadedSet = messagesLoaded().get(instanceId) || new Set()
|
||||||
if (!loadedSet.has(session.id)) return false
|
if (!loadedSet.has(session.id)) {
|
||||||
|
if (!fetchIfNeeded) return false
|
||||||
|
await loadMessages(instanceId, session.id)
|
||||||
|
}
|
||||||
|
|
||||||
if (session.messages.length === 0) return true
|
if (session.messages.length === 0) return true
|
||||||
|
|
||||||
@@ -250,10 +255,14 @@ function isBlankSession(session: Session, instanceId: string): boolean {
|
|||||||
|
|
||||||
// Subagent is blank if last message was NOT a tool call
|
// Subagent is blank if last message was NOT a tool call
|
||||||
return !lastMessageWasToolCall
|
return !lastMessageWasToolCall
|
||||||
} else if (session.revert?.messageID) {
|
} else if (!session.title?.includes("subagent") && session.parentId !== null) {
|
||||||
// Fork
|
// Fork
|
||||||
|
|
||||||
const loadedSet = messagesLoaded().get(instanceId) || new Set()
|
const loadedSet = messagesLoaded().get(instanceId) || new Set()
|
||||||
if (!loadedSet.has(session.id)) return false
|
if (!loadedSet.has(session.id)) {
|
||||||
|
if (!fetchIfNeeded) return false
|
||||||
|
await loadMessages(instanceId, session.id)
|
||||||
|
}
|
||||||
|
|
||||||
if (session.messages.length === 0) return true
|
if (session.messages.length === 0) return true
|
||||||
|
|
||||||
@@ -264,6 +273,36 @@ function isBlankSession(session: Session, instanceId: string): boolean {
|
|||||||
return false // default to not saying it's blank, just to be safe
|
return false // default to not saying it's blank, just to be safe
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function cleanupBlankSessions(instanceId: string, excludeSessionId?: string, fetchIfNeeded = false): Promise<void> {
|
||||||
|
const instanceSessions = sessions().get(instanceId)
|
||||||
|
if (!instanceSessions) return
|
||||||
|
|
||||||
|
const cleanupPromises = Array.from(instanceSessions)
|
||||||
|
.filter(([sessionId]) => sessionId !== excludeSessionId)
|
||||||
|
.map(async ([sessionId, session]) => {
|
||||||
|
const isBlank = await isBlankSession(session, instanceId, fetchIfNeeded)
|
||||||
|
if (!isBlank) return false
|
||||||
|
|
||||||
|
await deleteSession(instanceId, sessionId).catch((error: Error) => {
|
||||||
|
console.error(`Failed to delete blank session ${sessionId}:`, error)
|
||||||
|
})
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
|
||||||
|
if (cleanupPromises.length > 0) {
|
||||||
|
console.log(`Cleaning up ${cleanupPromises.length} blank sessions`)
|
||||||
|
const deletionResults = await Promise.all(cleanupPromises)
|
||||||
|
const deletedCount = deletionResults.filter(Boolean).length
|
||||||
|
|
||||||
|
if (deletedCount > 0) {
|
||||||
|
showToastNotification({
|
||||||
|
message: `Cleaned up ${deletedCount} blank session${deletedCount === 1 ? '' : 's'}`,
|
||||||
|
variant: "info"
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export {
|
export {
|
||||||
sessions,
|
sessions,
|
||||||
setSessions,
|
setSessions,
|
||||||
@@ -303,4 +342,5 @@ export {
|
|||||||
isSessionMessagesLoading,
|
isSessionMessagesLoading,
|
||||||
getSessionInfo,
|
getSessionInfo,
|
||||||
isBlankSession,
|
isBlankSession,
|
||||||
|
cleanupBlankSessions,
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user