Merge pull request #3134 from auyua9/fix/session-info-sqlite-sdk-auyua9
fix(session-manager): use sdk data in getSessionInfo
This commit is contained in:
@@ -10,6 +10,7 @@ const TEST_PART_STORAGE = join(TEST_DIR, "part")
|
|||||||
const TEST_SESSION_STORAGE = join(TEST_DIR, "session")
|
const TEST_SESSION_STORAGE = join(TEST_DIR, "session")
|
||||||
const TEST_TODO_DIR = join(TEST_DIR, "todos")
|
const TEST_TODO_DIR = join(TEST_DIR, "todos")
|
||||||
const TEST_TRANSCRIPT_DIR = join(TEST_DIR, "transcripts")
|
const TEST_TRANSCRIPT_DIR = join(TEST_DIR, "transcripts")
|
||||||
|
let sqliteBackend = false
|
||||||
|
|
||||||
mock.module("./constants", () => ({
|
mock.module("./constants", () => ({
|
||||||
OPENCODE_STORAGE: TEST_DIR,
|
OPENCODE_STORAGE: TEST_DIR,
|
||||||
@@ -27,7 +28,7 @@ mock.module("./constants", () => ({
|
|||||||
}))
|
}))
|
||||||
|
|
||||||
mock.module("../../shared/opencode-storage-detection", () => ({
|
mock.module("../../shared/opencode-storage-detection", () => ({
|
||||||
isSqliteBackend: () => false,
|
isSqliteBackend: () => sqliteBackend,
|
||||||
resetSqliteBackendCache: () => {},
|
resetSqliteBackendCache: () => {},
|
||||||
}))
|
}))
|
||||||
|
|
||||||
@@ -69,6 +70,7 @@ const storage = await import("./storage")
|
|||||||
|
|
||||||
describe("session-manager storage", () => {
|
describe("session-manager storage", () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
|
sqliteBackend = false
|
||||||
if (existsSync(TEST_DIR)) {
|
if (existsSync(TEST_DIR)) {
|
||||||
rmSync(TEST_DIR, { recursive: true, force: true })
|
rmSync(TEST_DIR, { recursive: true, force: true })
|
||||||
}
|
}
|
||||||
@@ -81,6 +83,8 @@ describe("session-manager storage", () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
|
sqliteBackend = false
|
||||||
|
storage.resetStorageClient()
|
||||||
if (existsSync(TEST_DIR)) {
|
if (existsSync(TEST_DIR)) {
|
||||||
rmSync(TEST_DIR, { recursive: true, force: true })
|
rmSync(TEST_DIR, { recursive: true, force: true })
|
||||||
}
|
}
|
||||||
@@ -235,6 +239,47 @@ describe("session-manager storage", () => {
|
|||||||
expect(info?.agents_used).toContain("build")
|
expect(info?.agents_used).toContain("build")
|
||||||
expect(info?.agents_used).toContain("oracle")
|
expect(info?.agents_used).toContain("oracle")
|
||||||
})
|
})
|
||||||
|
|
||||||
|
test("getSessionInfo uses SDK session messages on sqlite backend", async () => {
|
||||||
|
sqliteBackend = true
|
||||||
|
const now = Date.now()
|
||||||
|
|
||||||
|
storage.setStorageClient({
|
||||||
|
session: {
|
||||||
|
messages: async () => ({
|
||||||
|
data: [
|
||||||
|
{
|
||||||
|
info: {
|
||||||
|
id: "msg_sqlite_1",
|
||||||
|
role: "user",
|
||||||
|
agent: "atlas",
|
||||||
|
time: { created: now - 5000, updated: now - 5000 },
|
||||||
|
},
|
||||||
|
parts: [],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
info: {
|
||||||
|
id: "msg_sqlite_2",
|
||||||
|
role: "assistant",
|
||||||
|
agent: "prometheus",
|
||||||
|
time: { created: now, updated: now },
|
||||||
|
},
|
||||||
|
parts: [],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
todo: async () => ({ data: [] }),
|
||||||
|
},
|
||||||
|
} as never)
|
||||||
|
|
||||||
|
const info = await getSessionInfo("ses_sqlite")
|
||||||
|
|
||||||
|
expect(info).not.toBeNull()
|
||||||
|
expect(info?.id).toBe("ses_sqlite")
|
||||||
|
expect(info?.message_count).toBe(2)
|
||||||
|
expect(info?.agents_used).toContain("atlas")
|
||||||
|
expect(info?.agents_used).toContain("prometheus")
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe("session-manager storage - getMainSessions", () => {
|
describe("session-manager storage - getMainSessions", () => {
|
||||||
|
|||||||
@@ -119,5 +119,43 @@ export async function readSessionTranscript(sessionID: string): Promise<number>
|
|||||||
}
|
}
|
||||||
|
|
||||||
export async function getSessionInfo(sessionID: string): Promise<SessionInfo | null> {
|
export async function getSessionInfo(sessionID: string): Promise<SessionInfo | null> {
|
||||||
|
if (isSqliteBackend() && sdkClient) {
|
||||||
|
try {
|
||||||
|
const sdkMessages = await getSdkSessionMessages(sdkClient, sessionID)
|
||||||
|
if (sdkMessages.length > 0) {
|
||||||
|
const agentsUsed = new Set<string>()
|
||||||
|
let firstMessage: Date | undefined
|
||||||
|
let lastMessage: Date | undefined
|
||||||
|
|
||||||
|
for (const msg of sdkMessages) {
|
||||||
|
if (msg.agent) agentsUsed.add(msg.agent)
|
||||||
|
if (msg.time?.created) {
|
||||||
|
const date = new Date(msg.time.created)
|
||||||
|
if (!firstMessage || date < firstMessage) firstMessage = date
|
||||||
|
if (!lastMessage || date > lastMessage) lastMessage = date
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const todos = await readSessionTodos(sessionID)
|
||||||
|
const transcriptEntries = await readSessionTranscript(sessionID)
|
||||||
|
|
||||||
|
return {
|
||||||
|
id: sessionID,
|
||||||
|
message_count: sdkMessages.length,
|
||||||
|
first_message: firstMessage,
|
||||||
|
last_message: lastMessage,
|
||||||
|
agents_used: Array.from(agentsUsed),
|
||||||
|
has_todos: todos.length > 0,
|
||||||
|
has_transcript: transcriptEntries > 0,
|
||||||
|
todos,
|
||||||
|
transcript_entries: transcriptEntries,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
if (!shouldFallbackFromSdkError(error)) throw error
|
||||||
|
log("[session-manager] falling back to file session info after SDK unavailable error", { error: String(error), sessionID })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return getFileSessionInfo(sessionID)
|
return getFileSessionInfo(sessionID)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user