feat(session-manager): implement session management tools

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
This commit is contained in:
YeonGyu-Kim
2026-04-10 15:53:08 +09:00
parent 1a090af2eb
commit 7244d048fb
+54 -15
View File
@@ -27,9 +27,48 @@ function withTimeout<T>(promise: Promise<T>, ms: number, operation: string): Pro
])
}
export function createSessionManagerTools(ctx: PluginInput): Record<string, ToolDefinition> {
type SessionManagerToolDeps = {
getAllSessions: typeof getAllSessions
getMainSessions: typeof getMainSessions
getSessionInfo: typeof getSessionInfo
readSessionMessages: typeof readSessionMessages
readSessionTodos: typeof readSessionTodos
sessionExists: typeof sessionExists
setStorageClient: typeof setStorageClient
filterSessionsByDate: typeof filterSessionsByDate
formatSessionInfo: typeof formatSessionInfo
formatSessionList: typeof formatSessionList
formatSessionMessages: typeof formatSessionMessages
formatSearchResults: typeof formatSearchResults
searchInSession: typeof searchInSession
}
const defaultSessionManagerToolDeps: SessionManagerToolDeps = {
getAllSessions,
getMainSessions,
getSessionInfo,
readSessionMessages,
readSessionTodos,
sessionExists,
setStorageClient,
filterSessionsByDate,
formatSessionInfo,
formatSessionList,
formatSessionMessages,
formatSearchResults,
searchInSession,
}
export function createSessionManagerTools(
ctx: PluginInput,
deps: Partial<SessionManagerToolDeps> = {},
): Record<string, ToolDefinition> {
const resolvedDeps: SessionManagerToolDeps = {
...defaultSessionManagerToolDeps,
...deps,
}
// Initialize storage client for SDK-based operations (beta mode)
setStorageClient(ctx.client)
resolvedDeps.setStorageClient(ctx.client)
const session_list: ToolDefinition = tool({
description: SESSION_LIST_DESCRIPTION,
@@ -42,18 +81,18 @@ export function createSessionManagerTools(ctx: PluginInput): Record<string, Tool
execute: async (args: SessionListArgs, _context) => {
try {
const directory = args.project_path ?? ctx.directory
let sessions = await getMainSessions({ directory })
let sessions = await resolvedDeps.getMainSessions({ directory })
let sessionIDs = sessions.map((s) => s.id)
if (args.from_date || args.to_date) {
sessionIDs = await filterSessionsByDate(sessionIDs, args.from_date, args.to_date)
sessionIDs = await resolvedDeps.filterSessionsByDate(sessionIDs, args.from_date, args.to_date)
}
if (args.limit && args.limit > 0) {
sessionIDs = sessionIDs.slice(0, args.limit)
}
return await formatSessionList(sessionIDs)
return await resolvedDeps.formatSessionList(sessionIDs)
} catch (e) {
return `Error: ${e instanceof Error ? e.message : String(e)}`
}
@@ -70,11 +109,11 @@ export function createSessionManagerTools(ctx: PluginInput): Record<string, Tool
},
execute: async (args: SessionReadArgs, _context) => {
try {
if (!(await sessionExists(args.session_id))) {
if (!(await resolvedDeps.sessionExists(args.session_id))) {
return `Session not found: ${args.session_id}`
}
let messages = await readSessionMessages(args.session_id)
let messages = await resolvedDeps.readSessionMessages(args.session_id)
if (messages.length === 0) {
return `Session not found: ${args.session_id}`
@@ -84,9 +123,9 @@ export function createSessionManagerTools(ctx: PluginInput): Record<string, Tool
messages = messages.slice(0, args.limit)
}
const todos = args.include_todos ? await readSessionTodos(args.session_id) : undefined
const todos = args.include_todos ? await resolvedDeps.readSessionTodos(args.session_id) : undefined
return formatSessionMessages(messages, args.include_todos, todos)
return resolvedDeps.formatSessionMessages(messages, args.include_todos, todos)
} catch (e) {
return `Error: ${e instanceof Error ? e.message : String(e)}`
}
@@ -107,10 +146,10 @@ export function createSessionManagerTools(ctx: PluginInput): Record<string, Tool
const searchOperation = async (): Promise<SearchResult[]> => {
if (args.session_id) {
return searchInSession(args.session_id, args.query, args.case_sensitive, resultLimit)
return resolvedDeps.searchInSession(args.session_id, args.query, args.case_sensitive, resultLimit)
}
const allSessions = await getAllSessions()
const allSessions = await resolvedDeps.getAllSessions()
const sessionsToScan = allSessions.slice(0, MAX_SESSIONS_TO_SCAN)
const allResults: SearchResult[] = []
@@ -118,7 +157,7 @@ export function createSessionManagerTools(ctx: PluginInput): Record<string, Tool
if (allResults.length >= resultLimit) break
const remaining = resultLimit - allResults.length
const sessionResults = await searchInSession(sid, args.query, args.case_sensitive, remaining)
const sessionResults = await resolvedDeps.searchInSession(sid, args.query, args.case_sensitive, remaining)
allResults.push(...sessionResults)
}
@@ -127,7 +166,7 @@ export function createSessionManagerTools(ctx: PluginInput): Record<string, Tool
const results = await withTimeout(searchOperation(), SEARCH_TIMEOUT_MS, "Search")
return formatSearchResults(results)
return resolvedDeps.formatSearchResults(results)
} catch (e) {
return `Error: ${e instanceof Error ? e.message : String(e)}`
}
@@ -141,13 +180,13 @@ export function createSessionManagerTools(ctx: PluginInput): Record<string, Tool
},
execute: async (args: SessionInfoArgs, _context) => {
try {
const info = await getSessionInfo(args.session_id)
const info = await resolvedDeps.getSessionInfo(args.session_id)
if (!info) {
return `Session not found: ${args.session_id}`
}
return formatSessionInfo(info)
return resolvedDeps.formatSessionInfo(info)
} catch (e) {
return `Error: ${e instanceof Error ? e.message : String(e)}`
}