fix(session-manager): convert blocking sync I/O to async for improved concurrency
Convert session-manager storage layer from synchronous blocking I/O (readdirSync, readFileSync) to non-blocking async I/O (readdir, readFile from fs/promises). This fixes hanging issues in session_search and other tools caused by blocking filesystem operations. Changes: - storage.ts: getAllSessions, readSessionMessages, getSessionInfo now async - utils.ts: Updated utility functions to be async-compatible - tools.ts: Added await calls for async storage functions - storage.test.ts, utils.test.ts: Updated tests with async/await patterns This resolves the session_search tool hang issue and improves overall responsiveness. 🤖 Generated with assistance of OhMyOpenCode (https://github.com/code-yeongyu/oh-my-opencode)
This commit is contained in:
@@ -1,12 +1,14 @@
|
||||
import type { SessionInfo, SessionMessage, SearchResult } from "./types"
|
||||
import { getSessionInfo, readSessionMessages } from "./storage"
|
||||
|
||||
export function formatSessionList(sessionIDs: string[]): string {
|
||||
export async function formatSessionList(sessionIDs: string[]): Promise<string> {
|
||||
if (sessionIDs.length === 0) {
|
||||
return "No sessions found."
|
||||
}
|
||||
|
||||
const infos = sessionIDs.map((id) => getSessionInfo(id)).filter((info): info is SessionInfo => info !== null)
|
||||
const infos = (await Promise.all(sessionIDs.map((id) => getSessionInfo(id)))).filter(
|
||||
(info): info is SessionInfo => info !== null
|
||||
)
|
||||
|
||||
if (infos.length === 0) {
|
||||
return "No valid sessions found."
|
||||
@@ -39,7 +41,11 @@ export function formatSessionList(sessionIDs: string[]): string {
|
||||
return [formatRow(headers), separator, ...rows.map(formatRow)].join("\n")
|
||||
}
|
||||
|
||||
export function formatSessionMessages(messages: SessionMessage[], includeTodos?: boolean, todos?: Array<{id: string; content: string; status: string}>): string {
|
||||
export function formatSessionMessages(
|
||||
messages: SessionMessage[],
|
||||
includeTodos?: boolean,
|
||||
todos?: Array<{ id: string; content: string; status: string }>
|
||||
): string {
|
||||
if (messages.length === 0) {
|
||||
return "No messages found in this session."
|
||||
}
|
||||
@@ -116,32 +122,46 @@ export function formatSearchResults(results: SearchResult[]): string {
|
||||
return lines.join("\n")
|
||||
}
|
||||
|
||||
export function filterSessionsByDate(sessionIDs: string[], fromDate?: string, toDate?: string): string[] {
|
||||
export async function filterSessionsByDate(
|
||||
sessionIDs: string[],
|
||||
fromDate?: string,
|
||||
toDate?: string
|
||||
): Promise<string[]> {
|
||||
if (!fromDate && !toDate) return sessionIDs
|
||||
|
||||
const from = fromDate ? new Date(fromDate) : null
|
||||
const to = toDate ? new Date(toDate) : null
|
||||
|
||||
return sessionIDs.filter((id) => {
|
||||
const info = getSessionInfo(id)
|
||||
if (!info || !info.last_message) return false
|
||||
const results: string[] = []
|
||||
for (const id of sessionIDs) {
|
||||
const info = await getSessionInfo(id)
|
||||
if (!info || !info.last_message) continue
|
||||
|
||||
if (from && info.last_message < from) return false
|
||||
if (to && info.last_message > to) return false
|
||||
if (from && info.last_message < from) continue
|
||||
if (to && info.last_message > to) continue
|
||||
|
||||
return true
|
||||
})
|
||||
results.push(id)
|
||||
}
|
||||
|
||||
return results
|
||||
}
|
||||
|
||||
export function searchInSession(sessionID: string, query: string, caseSensitive = false): SearchResult[] {
|
||||
const messages = readSessionMessages(sessionID)
|
||||
export async function searchInSession(
|
||||
sessionID: string,
|
||||
query: string,
|
||||
caseSensitive = false,
|
||||
maxResults?: number
|
||||
): Promise<SearchResult[]> {
|
||||
const messages = await readSessionMessages(sessionID)
|
||||
const results: SearchResult[] = []
|
||||
|
||||
const searchQuery = caseSensitive ? query : query.toLowerCase()
|
||||
|
||||
for (const msg of messages) {
|
||||
if (maxResults && results.length >= maxResults) break
|
||||
|
||||
let matchCount = 0
|
||||
let excerpts: string[] = []
|
||||
const excerpts: string[] = []
|
||||
|
||||
for (const part of msg.parts) {
|
||||
if (part.type === "text" && part.text) {
|
||||
|
||||
Reference in New Issue
Block a user