fix(gateway): invalidate bootstrap cache on session rollover (openclaw#38535)

Verified:
- pnpm install --frozen-lockfile
- pnpm build
- pnpm check
- pnpm test:macmini

Co-authored-by: yfge <1186273+yfge@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
This commit is contained in:
拐爷&&老拐瘦
2026-03-07 13:46:02 +08:00
committed by GitHub
parent e802840b62
commit 2e31aead39
7 changed files with 63 additions and 1 deletions

View File

@@ -2,6 +2,7 @@ import fs from "node:fs/promises";
import os from "node:os";
import path from "node:path";
import { afterAll, afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
import * as bootstrapCache from "../../agents/bootstrap-cache.js";
import { buildModelAliasIndex } from "../../agents/model-selection.js";
import type { OpenClawConfig } from "../../config/config.js";
import type { SessionEntry } from "../../config/sessions.js";
@@ -850,11 +851,18 @@ describe("initSessionState RawBody", () => {
});
describe("initSessionState reset policy", () => {
let clearBootstrapSnapshotOnSessionRolloverSpy: ReturnType<typeof vi.spyOn>;
beforeEach(() => {
vi.useFakeTimers();
clearBootstrapSnapshotOnSessionRolloverSpy = vi.spyOn(
bootstrapCache,
"clearBootstrapSnapshotOnSessionRollover",
);
});
afterEach(() => {
clearBootstrapSnapshotOnSessionRolloverSpy.mockRestore();
vi.useRealTimers();
});
@@ -881,6 +889,10 @@ describe("initSessionState reset policy", () => {
expect(result.isNewSession).toBe(true);
expect(result.sessionId).not.toBe(existingSessionId);
expect(clearBootstrapSnapshotOnSessionRolloverSpy).toHaveBeenCalledWith({
sessionKey,
previousSessionId: existingSessionId,
});
});
it("treats sessions as stale before the daily reset when updated before yesterday's boundary", async () => {
@@ -1057,6 +1069,10 @@ describe("initSessionState reset policy", () => {
expect(result.isNewSession).toBe(false);
expect(result.sessionId).toBe(existingSessionId);
expect(clearBootstrapSnapshotOnSessionRolloverSpy).toHaveBeenCalledWith({
sessionKey,
previousSessionId: undefined,
});
});
});

View File

@@ -5,6 +5,7 @@ import {
parseTelegramChatIdFromTarget,
} from "../../acp/conversation-id.js";
import { resolveSessionAgentId } from "../../agents/agent-scope.js";
import { clearBootstrapSnapshotOnSessionRollover } from "../../agents/bootstrap-cache.js";
import { normalizeChatType } from "../../channels/chat-type.js";
import type { OpenClawConfig } from "../../config/config.js";
import {
@@ -358,6 +359,10 @@ export async function initSessionState(params: {
// and for scheduled/daily resets where the session has become stale (!freshEntry).
// Without this, daily-reset transcripts are left as orphaned files on disk (#35481).
const previousSessionEntry = (resetTriggered || !freshEntry) && entry ? { ...entry } : undefined;
clearBootstrapSnapshotOnSessionRollover({
sessionKey,
previousSessionId: previousSessionEntry?.sessionId,
});
if (!isNewSession && freshEntry) {
sessionId = entry.sessionId;