From bb27f3531932eaee5201a396a734a5a7d73da6d1 Mon Sep 17 00:00:00 2001 From: Junebugg1214 <82672745+Junebugg1214@users.noreply.github.com> Date: Thu, 12 Mar 2026 22:45:22 -0400 Subject: [PATCH] fix: use conversation key for cortex snapshot cache --- src/gateway/server/health-state.test.ts | 39 +++++++++++++++++++++++++ src/gateway/server/health-state.ts | 26 +++++++++++++---- 2 files changed, 60 insertions(+), 5 deletions(-) diff --git a/src/gateway/server/health-state.test.ts b/src/gateway/server/health-state.test.ts index a62d6df0b9f..6596091f824 100644 --- a/src/gateway/server/health-state.test.ts +++ b/src/gateway/server/health-state.test.ts @@ -4,11 +4,14 @@ const loadConfigMock = vi.hoisted(() => vi.fn()); const createConfigIOMock = vi.hoisted(() => vi.fn()); const resolveDefaultAgentIdMock = vi.hoisted(() => vi.fn()); const resolveMainSessionKeyMock = vi.hoisted(() => vi.fn()); +const resolveStorePathMock = vi.hoisted(() => vi.fn()); +const loadSessionStoreMock = vi.hoisted(() => vi.fn()); const normalizeMainKeyMock = vi.hoisted(() => vi.fn()); const listSystemPresenceMock = vi.hoisted(() => vi.fn()); const resolveGatewayAuthMock = vi.hoisted(() => vi.fn()); const getUpdateAvailableMock = vi.hoisted(() => vi.fn()); const resolveAgentCortexConfigMock = vi.hoisted(() => vi.fn()); +const resolveCortexChannelTargetMock = vi.hoisted(() => vi.fn()); const getCachedLatestCortexCaptureHistoryEntryMock = vi.hoisted(() => vi.fn()); vi.mock("../../config/config.js", () => ({ @@ -22,7 +25,9 @@ vi.mock("../../agents/agent-scope.js", () => ({ })); vi.mock("../../config/sessions.js", () => ({ + loadSessionStore: loadSessionStoreMock, resolveMainSessionKey: resolveMainSessionKeyMock, + resolveStorePath: resolveStorePathMock, })); vi.mock("../../routing/session-key.js", async (importOriginal) => { @@ -48,6 +53,7 @@ vi.mock("../../infra/update-startup.js", () => ({ vi.mock("../../agents/cortex.js", () => ({ resolveAgentCortexConfig: resolveAgentCortexConfigMock, + resolveCortexChannelTarget: resolveCortexChannelTargetMock, })); vi.mock("../../agents/cortex-history.js", () => ({ @@ -68,6 +74,19 @@ describe("buildGatewaySnapshot", () => { createConfigIOMock.mockReturnValue({ configPath: "/tmp/openclaw/openclaw.json" }); resolveDefaultAgentIdMock.mockReturnValue("main"); resolveMainSessionKeyMock.mockReturnValue("agent:main:main"); + resolveStorePathMock.mockReturnValue("/tmp/openclaw-state/sessions/main/sessions.json"); + loadSessionStoreMock.mockReturnValue({ + "agent:main:main": { + sessionId: "session-1", + updatedAt: 1234, + lastChannel: "telegram", + lastTo: "telegram:user-123", + deliveryContext: { + channel: "telegram", + to: "telegram:user-123", + }, + }, + }); normalizeMainKeyMock.mockReturnValue("main"); listSystemPresenceMock.mockReturnValue([]); resolveGatewayAuthMock.mockReturnValue({ mode: "token" }); @@ -78,8 +97,11 @@ describe("buildGatewaySnapshot", () => { maxChars: 1500, graphPath: ".cortex/context.json", }); + resolveCortexChannelTargetMock.mockReturnValue("telegram:user-123"); getCachedLatestCortexCaptureHistoryEntryMock.mockReturnValue({ agentId: "main", + sessionId: "session-1", + channelId: "telegram:user-123", captured: true, score: 0.7, reason: "high-signal memory candidate", @@ -89,6 +111,23 @@ describe("buildGatewaySnapshot", () => { const snapshot = buildGatewaySnapshot(); + expect(resolveStorePathMock).toHaveBeenCalledWith(undefined, { agentId: "main" }); + expect(loadSessionStoreMock).toHaveBeenCalledWith( + "/tmp/openclaw-state/sessions/main/sessions.json", + ); + expect(resolveCortexChannelTargetMock).toHaveBeenCalledWith({ + channel: "telegram", + originatingChannel: "telegram", + originatingTo: "telegram:user-123", + nativeChannelId: "telegram:user-123", + to: "telegram:user-123", + }); + expect(getCachedLatestCortexCaptureHistoryEntryMock).toHaveBeenCalledWith({ + agentId: "main", + sessionId: "session-1", + channelId: "telegram:user-123", + }); + expect(snapshot.cortex).toEqual({ enabled: true, mode: "technical", diff --git a/src/gateway/server/health-state.ts b/src/gateway/server/health-state.ts index 848df148c04..b3a2f58efbb 100644 --- a/src/gateway/server/health-state.ts +++ b/src/gateway/server/health-state.ts @@ -1,9 +1,13 @@ import { resolveDefaultAgentId } from "../../agents/agent-scope.js"; import { getCachedLatestCortexCaptureHistoryEntry } from "../../agents/cortex-history.js"; -import { resolveAgentCortexConfig } from "../../agents/cortex.js"; +import { resolveAgentCortexConfig, resolveCortexChannelTarget } from "../../agents/cortex.js"; import { getHealthSnapshot, type HealthSummary } from "../../commands/health.js"; import { STATE_DIR, createConfigIO, loadConfig } from "../../config/config.js"; -import { resolveMainSessionKey } from "../../config/sessions.js"; +import { + loadSessionStore, + resolveMainSessionKey, + resolveStorePath, +} from "../../config/sessions.js"; import { listSystemPresence } from "../../infra/system-presence.js"; import { getUpdateAvailable } from "../../infra/update-startup.js"; import { normalizeMainKey } from "../../routing/session-key.js"; @@ -21,11 +25,23 @@ export function buildGatewaySnapshot(): Snapshot { const configPath = createConfigIO().configPath; const defaultAgentId = resolveDefaultAgentId(cfg); const cortex = resolveAgentCortexConfig(cfg, defaultAgentId); - const latestCortexCapture = cortex - ? getCachedLatestCortexCaptureHistoryEntry({ agentId: defaultAgentId }) - : null; const mainKey = normalizeMainKey(cfg.session?.mainKey); const mainSessionKey = resolveMainSessionKey(cfg); + const sessionStorePath = resolveStorePath(cfg.session?.store, { agentId: defaultAgentId }); + const mainSessionEntry = loadSessionStore(sessionStorePath)[mainSessionKey]; + const latestCortexCapture = cortex + ? getCachedLatestCortexCaptureHistoryEntry({ + agentId: defaultAgentId, + sessionId: mainSessionEntry?.sessionId, + channelId: resolveCortexChannelTarget({ + channel: mainSessionEntry?.lastChannel, + originatingChannel: mainSessionEntry?.deliveryContext?.channel, + originatingTo: mainSessionEntry?.deliveryContext?.to, + nativeChannelId: mainSessionEntry?.deliveryContext?.to, + to: mainSessionEntry?.lastTo, + }), + }) + : null; const scope = cfg.session?.scope ?? "per-sender"; const presence = listSystemPresence(); const uptimeMs = Math.round(process.uptime() * 1000);