improve PR

This commit is contained in:
Alexis Purslane
2025-11-29 21:38:23 -05:00
parent 96b88dbcdc
commit aa0c31fa1e
3 changed files with 629 additions and 1960 deletions

View File

@@ -1,10 +0,0 @@
((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"))))))

2495
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -4,6 +4,7 @@ import type { Session, Agent, Provider } from "../types/session"
import { deleteSession, loadMessages } from "./session-api" import { deleteSession, loadMessages } from "./session-api"
import { showToastNotification } from "../lib/notifications" import { showToastNotification } from "../lib/notifications"
import { messageStoreBus } from "./message-v2/bus" import { messageStoreBus } from "./message-v2/bus"
import { instances } from "./instances"
export interface SessionInfo { export interface SessionInfo {
cost: number cost: number
@@ -225,55 +226,64 @@ function getSessionInfo(instanceId: string, sessionId: string): SessionInfo | un
} }
async function isBlankSession(session: Session, instanceId: string, fetchIfNeeded = false): Promise<boolean> { async function isBlankSession(session: Session, instanceId: string, fetchIfNeeded = false): Promise<boolean> {
const loadedSet = messagesLoaded().get(instanceId) const created = session.time?.created || 0
const notLoaded = !loadedSet?.has(session.id) const updated = session.time?.updated || 0
const hasChildren = getChildSessions(instanceId, session.id).length > 0
const isFreshSession = created === updated && !hasChildren
if (notLoaded && !fetchIfNeeded) { // Common short-circuit: fresh sessions without children
return false if (!fetchIfNeeded) {
return isFreshSession
} }
if (notLoaded && fetchIfNeeded) { // For a more thorough deep clean, we need to look at actual messages
await loadMessages(instanceId, session.id)
const instance = instances().get(instanceId)
if (!instance?.client) {
return isFreshSession
}
let messages: any[] = []
try {
const response = await instance.client.session.messages({ path: { id: session.id } })
messages = response.data || []
} catch (error) {
console.error(`Failed to fetch messages for session ${session.id}:`, error)
return isFreshSession
} }
const store = messageStoreBus.getOrCreate(instanceId) // Specific logic by session type
const messageIds = store.getSessionMessageIds(session.id)
const usage = store.getSessionUsage(session.id)
if (session.parentId === null) { if (session.parentId === null) {
// Parent session: check tokens and children // Parent: blank if no messages and no children (fresh !== blank sometimes!)
const hasChildren = getChildSessions(instanceId, session.id).length > 0 const hasChildren = getChildSessions(instanceId, session.id).length > 0
const hasZeroTokens = usage ? usage.actualUsageTokens === 0 : true return messages.length === 0 && !hasChildren
} else if (session.title?.includes("subagent)")) {
// Subagent: "blank" (really: finished doing its job) if actually blank...
// ... OR no streaming, no pending perms, no tool parts
if (messages.length === 0) return true
return hasZeroTokens && !hasChildren const hasStreaming = messages.some((msg) => {
} else if (session.title?.includes("subagent")) { const info = msg.info.status || msg.status
// Subagent session return info === "streaming" || info === "sending"
if (messageIds.length === 0) return true
// Check for streaming or tool parts in last message
const lastMessageId = messageIds[messageIds.length - 1]
const lastMessage = store.getMessage(lastMessageId)
if (!lastMessage) return false
const hasToolPart = Object.values(lastMessage.parts).some((part) => part.data.type === "tool")
const hasStreaming = messageIds.some((id) => {
const msg = store.getMessage(id)
return msg?.status === "streaming"
}) })
const isWaitingForPermission = session.pendingPermission === true
return !hasStreaming && !isWaitingForPermission && !hasToolPart const lastMessage = messages[messages.length - 1]
const lastParts = lastMessage?.parts || []
const hasToolPart = lastParts.some((part: any) =>
part.type === "tool" || part.data?.type === "tool"
)
return !hasStreaming && !session.pendingPermission && !hasToolPart
} else { } else {
// Fork session // Fork: blank if somehow has no messages or at revert point
if (messageIds.length === 0) return true if (messages.length === 0) return true
const lastMessageId = messageIds[messageIds.length - 1] const lastMessage = messages[messages.length - 1]
const revert = store.getSessionRevert(session.id) const lastInfo = lastMessage?.info || lastMessage
return lastInfo?.id === session.revert?.messageID
return lastMessageId === revert?.messageID
} }
} }
async function cleanupBlankSessions(instanceId: string, excludeSessionId?: string, fetchIfNeeded = false): Promise<void> { async function cleanupBlankSessions(instanceId: string, excludeSessionId?: string, fetchIfNeeded = false): Promise<void> {
const instanceSessions = sessions().get(instanceId) const instanceSessions = sessions().get(instanceId)
if (!instanceSessions) return if (!instanceSessions) return