update blank session cleanup code for now session store logic
This commit is contained in:
82
dev-docs/solidjs-llms.txt
Normal file
82
dev-docs/solidjs-llms.txt
Normal file
@@ -0,0 +1,82 @@
|
|||||||
|
# SolidJS Documentation
|
||||||
|
|
||||||
|
> Solid is a modern JavaScript framework for building user interfaces with fine-grained reactivity. It compiles JSX to real DOM elements and updates only what changes, delivering exceptional performance without a virtual DOM. Solid provides reactive primitives like signals, effects, and stores for predictable state management.
|
||||||
|
|
||||||
|
SolidJS is a declarative JavaScript framework that prioritizes performance and developer experience. Unlike frameworks that re-run components on every update, Solid components run once during initialization and set up a reactive system that precisely updates the DOM when dependencies change.
|
||||||
|
|
||||||
|
Key principles:
|
||||||
|
- Fine-grained reactivity: Updates only the specific DOM nodes that depend on changed data
|
||||||
|
- Compile-time optimization: JSX transforms into efficient DOM operations
|
||||||
|
- Unidirectional data flow: Props are read-only, promoting predictable state management
|
||||||
|
- Component lifecycle: Components run once, with reactive primitives handling updates
|
||||||
|
|
||||||
|
**Use your web fetch tool on any of the following links to understand the relevant concept**.
|
||||||
|
|
||||||
|
## Quick Start
|
||||||
|
|
||||||
|
- [Overview](https://docs.solidjs.com/): Framework introduction and key advantages
|
||||||
|
- [Quick Start](https://docs.solidjs.com/quick-start): Installation and project setup with create-solid
|
||||||
|
- [Interactive Tutorial](https://www.solidjs.com/tutorial/introduction_basics): Learn Solid basics through guided examples
|
||||||
|
- [Playground](https://playground.solidjs.com/): Experiment with Solid directly in your browser
|
||||||
|
|
||||||
|
## Core Concepts
|
||||||
|
|
||||||
|
- [Intro to Reactivity](https://docs.solidjs.com/concepts/intro-to-reactivity): Signals, subscribers, and reactive principles
|
||||||
|
- [Understanding JSX](https://docs.solidjs.com/concepts/understanding-jsx): How Solid uses JSX and key differences from HTML
|
||||||
|
- [Components Basics](https://docs.solidjs.com/concepts/components/basics): Component trees, lifecycles, and composition patterns
|
||||||
|
- [Signals](https://docs.solidjs.com/concepts/signals): Core reactive primitive for state management with getters/setters
|
||||||
|
- [Effects](https://docs.solidjs.com/concepts/effects): Side effects, dependency tracking, and lifecycle functions
|
||||||
|
- [Stores](https://docs.solidjs.com/concepts/stores): Complex state management with proxy-based reactivity
|
||||||
|
- [Context](https://docs.solidjs.com/concepts/context): Cross-component state sharing without prop drilling
|
||||||
|
|
||||||
|
## Component APIs
|
||||||
|
|
||||||
|
- [Props](https://docs.solidjs.com/concepts/components/props): Passing data and handlers to child components
|
||||||
|
- [Event Handlers](https://docs.solidjs.com/concepts/components/event-handlers): Managing user interactions
|
||||||
|
- [Class and Style](https://docs.solidjs.com/concepts/components/class-style): Dynamic styling approaches
|
||||||
|
- [Refs](https://docs.solidjs.com/concepts/refs): Accessing DOM elements directly
|
||||||
|
|
||||||
|
## Control Flow
|
||||||
|
|
||||||
|
- [Conditional Rendering](https://docs.solidjs.com/concepts/control-flow/conditional-rendering): Show, Switch, and Match components
|
||||||
|
- [List Rendering](https://docs.solidjs.com/concepts/control-flow/list-rendering): For, Index, and keyed iteration
|
||||||
|
- [Dynamic](https://docs.solidjs.com/concepts/control-flow/dynamic): Dynamic component switching
|
||||||
|
- [Portal](https://docs.solidjs.com/concepts/control-flow/portal): Rendering outside component hierarchy
|
||||||
|
- [Error Boundary](https://docs.solidjs.com/concepts/control-flow/error-boundary): Graceful error handling
|
||||||
|
|
||||||
|
## Derived Values
|
||||||
|
|
||||||
|
- [Derived Signals](https://docs.solidjs.com/concepts/derived-values/derived-signals): Computed values from signals
|
||||||
|
- [Memos](https://docs.solidjs.com/concepts/derived-values/memos): Cached computed values for performance
|
||||||
|
|
||||||
|
## State Management
|
||||||
|
|
||||||
|
- [Basic State Management](https://docs.solidjs.com/guides/state-management): One-way data flow and lifting state
|
||||||
|
- [Complex State Management](https://docs.solidjs.com/guides/complex-state-management): Stores for scalable applications
|
||||||
|
- [Fetching Data](https://docs.solidjs.com/guides/fetching-data): Async data with createResource
|
||||||
|
|
||||||
|
## Routing
|
||||||
|
|
||||||
|
- [Routing & Navigation](https://docs.solidjs.com/guides/routing-and-navigation): @solidjs/router setup and usage
|
||||||
|
- [Dynamic Routes](https://docs.solidjs.com/guides/routing-and-navigation#dynamic-routes): Route parameters and validation
|
||||||
|
- [Nested Routes](https://docs.solidjs.com/guides/routing-and-navigation#nested-routes): Hierarchical route structures
|
||||||
|
- [Preload Functions](https://docs.solidjs.com/guides/routing-and-navigation#preload-functions): Parallel data fetching
|
||||||
|
|
||||||
|
## Advanced Topics
|
||||||
|
|
||||||
|
- [Fine-Grained Reactivity](https://docs.solidjs.com/advanced-concepts/fine-grained-reactivity): Deep dive into reactive system
|
||||||
|
- [TypeScript](https://docs.solidjs.com/configuration/typescript): Type safety and configuration
|
||||||
|
|
||||||
|
## Ecosystem
|
||||||
|
|
||||||
|
- [Solid Router](https://docs.solidjs.com/solid-router/): File-system routing and data APIs
|
||||||
|
- [SolidStart](https://docs.solidjs.com/solid-start/): Full-stack meta-framework
|
||||||
|
- [Solid Meta](https://docs.solidjs.com/solid-meta/): Document head management
|
||||||
|
- [Templates](https://github.com/solidjs/templates): Starter templates for different setups
|
||||||
|
|
||||||
|
## Optional
|
||||||
|
|
||||||
|
- [Ecosystem Libraries](https://www.solidjs.com/ecosystem): Community packages and tools
|
||||||
|
- [API Reference](https://docs.solidjs.com/reference/): Complete API documentation
|
||||||
|
- [Testing](https://docs.solidjs.com/guides/testing): Testing strategies and utilities
|
||||||
|
- [Deployment](https://docs.solidjs.com/guides/deploying-your-app): Build and deployment options
|
||||||
2495
package-lock.json
generated
2495
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -152,7 +152,7 @@ export function useCommands(options: UseCommandsOptions) {
|
|||||||
action: async () => {
|
action: async () => {
|
||||||
const instance = activeInstance()
|
const instance = activeInstance()
|
||||||
if (!instance) return
|
if (!instance) return
|
||||||
await cleanupBlankSessions(instance.id, undefined, true)
|
cleanupBlankSessions(instance.id, undefined, true)
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ import {
|
|||||||
sessions,
|
sessions,
|
||||||
loading,
|
loading,
|
||||||
setLoading,
|
setLoading,
|
||||||
|
cleanupBlankSessions,
|
||||||
} from "./session-state"
|
} from "./session-state"
|
||||||
import { DEFAULT_MODEL_OUTPUT_LIMIT, getDefaultModel, isModelValid } from "./session-models"
|
import { DEFAULT_MODEL_OUTPUT_LIMIT, getDefaultModel, isModelValid } from "./session-models"
|
||||||
import { normalizeMessagePart } from "./message-v2/normalizers"
|
import { normalizeMessagePart } from "./message-v2/normalizers"
|
||||||
@@ -230,8 +231,6 @@ async function createSession(instanceId: string, agent?: string): Promise<Sessio
|
|||||||
return next
|
return next
|
||||||
})
|
})
|
||||||
|
|
||||||
getSessionIndex(instanceId, session.id)
|
|
||||||
|
|
||||||
await cleanupBlankSessions(instanceId, session.id)
|
await cleanupBlankSessions(instanceId, session.id)
|
||||||
|
|
||||||
return session
|
return session
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
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 { deleteSession, loadMessages } from "./session-api"
|
||||||
import { showToastNotification } from "../lib/notifications"
|
import { showToastNotification } from "../lib/notifications"
|
||||||
|
import { messageStoreBus } from "./message-v2/bus"
|
||||||
|
|
||||||
export interface SessionInfo {
|
export interface SessionInfo {
|
||||||
cost: number
|
cost: number
|
||||||
@@ -224,53 +225,53 @@ 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> {
|
||||||
if (session.parentId === null) {
|
const loadedSet = messagesLoaded().get(instanceId)
|
||||||
// Parent session is only blank if actually blank AND has no children
|
const notLoaded = !loadedSet?.has(session.id)
|
||||||
|
|
||||||
const sessionInfo = getSessionInfo(instanceId, session.id)
|
if (notLoaded && !fetchIfNeeded) {
|
||||||
const hasChildren = getChildSessions(instanceId, session.id).length > 0
|
return false
|
||||||
|
|
||||||
// Only consider blank if we have loaded info, it shows 0 tokens, and no children
|
|
||||||
return sessionInfo !== undefined && sessionInfo.tokens === 0 && !hasChildren
|
|
||||||
} else if (session.title?.includes("subagent")) {
|
|
||||||
// Subagent
|
|
||||||
|
|
||||||
const loadedSet = messagesLoaded().get(instanceId) || new Set()
|
|
||||||
if (!loadedSet.has(session.id)) {
|
|
||||||
if (!fetchIfNeeded) return false
|
|
||||||
await loadMessages(instanceId, session.id)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (session.messages.length === 0) return true
|
|
||||||
|
|
||||||
const hasStreamingMessage = session.messages.some((msg) => msg.status === "streaming")
|
|
||||||
const isWaitingForPermission = session.pendingPermission === true
|
|
||||||
|
|
||||||
// If streaming or waiting for permission, not blank
|
|
||||||
if (hasStreamingMessage || isWaitingForPermission) return false
|
|
||||||
|
|
||||||
// Check if last message was a tool call
|
|
||||||
const lastMessage = session.messages[session.messages.length - 1]
|
|
||||||
const lastMessageWasToolCall = lastMessage.parts.some((part) => part.type === "tool")
|
|
||||||
|
|
||||||
// Subagent is blank if last message was NOT a tool call
|
|
||||||
return !lastMessageWasToolCall
|
|
||||||
} else if (!session.title?.includes("subagent") && session.parentId !== null) {
|
|
||||||
// Fork
|
|
||||||
|
|
||||||
const loadedSet = messagesLoaded().get(instanceId) || new Set()
|
|
||||||
if (!loadedSet.has(session.id)) {
|
|
||||||
if (!fetchIfNeeded) return false
|
|
||||||
await loadMessages(instanceId, session.id)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (session.messages.length === 0) return true
|
|
||||||
|
|
||||||
const lastMessage = session.messages[session.messages.length - 1]
|
|
||||||
return lastMessage.id === session.revert.messageID
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return false // default to not saying it's blank, just to be safe
|
if (notLoaded && fetchIfNeeded) {
|
||||||
|
await loadMessages(instanceId, session.id)
|
||||||
|
}
|
||||||
|
|
||||||
|
const store = messageStoreBus.getOrCreate(instanceId)
|
||||||
|
const messageIds = store.getSessionMessageIds(session.id)
|
||||||
|
const usage = store.getSessionUsage(session.id)
|
||||||
|
|
||||||
|
if (session.parentId === null) {
|
||||||
|
// Parent session: check tokens and children
|
||||||
|
const hasChildren = getChildSessions(instanceId, session.id).length > 0
|
||||||
|
const hasZeroTokens = usage ? usage.actualUsageTokens === 0 : true
|
||||||
|
|
||||||
|
return hasZeroTokens && !hasChildren
|
||||||
|
} else if (session.title?.includes("subagent")) {
|
||||||
|
// Subagent session
|
||||||
|
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
|
||||||
|
} else {
|
||||||
|
// Fork session
|
||||||
|
if (messageIds.length === 0) return true
|
||||||
|
|
||||||
|
const lastMessageId = messageIds[messageIds.length - 1]
|
||||||
|
const revert = store.getSessionRevert(session.id)
|
||||||
|
|
||||||
|
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> {
|
||||||
@@ -296,7 +297,7 @@ async function cleanupBlankSessions(instanceId: string, excludeSessionId?: strin
|
|||||||
|
|
||||||
if (deletedCount > 0) {
|
if (deletedCount > 0) {
|
||||||
showToastNotification({
|
showToastNotification({
|
||||||
message: `Cleaned up ${deletedCount} blank session${deletedCount === 1 ? '' : 's'}`,
|
message: `Cleaned up ${deletedCount} blank session${deletedCount === 1 ? "" : "s"}`,
|
||||||
variant: "info"
|
variant: "info"
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user