mirror of
https://github.com/openclaw/openclaw.git
synced 2026-07-21 10:16:44 +00:00
fix: preserve plugin maintenance config compatibility
This commit is contained in:
@@ -47,6 +47,12 @@ export type ResolvedSessionMaintenanceConfig = {
|
||||
highWaterBytes: number | null;
|
||||
};
|
||||
|
||||
export type ResolvedSessionMaintenanceConfigInput = Omit<
|
||||
ResolvedSessionMaintenanceConfig,
|
||||
"modelRunPruneAfterMs"
|
||||
> &
|
||||
Partial<Pick<ResolvedSessionMaintenanceConfig, "modelRunPruneAfterMs">>;
|
||||
|
||||
function resolvePruneAfterMs(maintenance?: SessionMaintenanceConfig): number {
|
||||
const raw = maintenance?.pruneAfter ?? maintenance?.pruneDays;
|
||||
const normalized = normalizeStringifiedOptionalString(raw);
|
||||
@@ -147,6 +153,15 @@ export function resolveMaintenanceConfigFromInput(
|
||||
};
|
||||
}
|
||||
|
||||
export function normalizeResolvedMaintenanceConfigInput(
|
||||
maintenance: ResolvedSessionMaintenanceConfigInput,
|
||||
): ResolvedSessionMaintenanceConfig {
|
||||
return {
|
||||
...maintenance,
|
||||
modelRunPruneAfterMs: maintenance.modelRunPruneAfterMs ?? DEFAULT_MODEL_RUN_PRUNE_AFTER_MS,
|
||||
};
|
||||
}
|
||||
|
||||
export function resolveSessionEntryMaintenanceHighWater(maxEntries: number): number {
|
||||
if (!Number.isSafeInteger(maxEntries) || maxEntries <= 0) {
|
||||
return 1;
|
||||
|
||||
@@ -69,6 +69,7 @@ import {
|
||||
pruneStaleModelRunEntries,
|
||||
pruneStaleEntries,
|
||||
type ResolvedSessionMaintenanceConfig,
|
||||
type ResolvedSessionMaintenanceConfigInput,
|
||||
type SessionMaintenanceWarning,
|
||||
} from "./store-maintenance.js";
|
||||
import { runExclusiveSessionStoreWrite } from "./store-writer.js";
|
||||
@@ -173,7 +174,11 @@ export {
|
||||
resolveMaintenanceConfig,
|
||||
};
|
||||
export type { SessionMaintenanceApplyReport } from "./store-maintenance-operations.js";
|
||||
export type { ResolvedSessionMaintenanceConfig, SessionMaintenanceWarning };
|
||||
export type {
|
||||
ResolvedSessionMaintenanceConfig,
|
||||
ResolvedSessionMaintenanceConfigInput,
|
||||
SessionMaintenanceWarning,
|
||||
};
|
||||
|
||||
type SaveSessionStoreOptions = {
|
||||
/** Skip pruning, capping, and rotation (e.g. during one-time migrations). */
|
||||
|
||||
@@ -165,6 +165,51 @@ describe("session-store-runtime compatibility surface", () => {
|
||||
expect(getSessionEntry({ sessionKey: staleSessionKey, storePath })).toBeUndefined();
|
||||
});
|
||||
|
||||
it("accepts pre-model-run maintenance configs through entry patches", async () => {
|
||||
const staleModelRunKey = "agent:main:explicit:model-run-123e4567-e89b-12d3-a456-426614174000";
|
||||
const activeSessionKey = "agent:main:active";
|
||||
const now = Date.now();
|
||||
await saveSessionStore(
|
||||
storePath,
|
||||
{
|
||||
[staleModelRunKey]: {
|
||||
sessionId: "session-probe",
|
||||
updatedAt: now - 2 * DAY_MS,
|
||||
},
|
||||
[activeSessionKey]: {
|
||||
sessionId: "session-active",
|
||||
updatedAt: now,
|
||||
},
|
||||
},
|
||||
{ skipMaintenance: true },
|
||||
);
|
||||
|
||||
const legacyMaintenanceConfig = {
|
||||
mode: "enforce" as const,
|
||||
pruneAfterMs: 7 * DAY_MS,
|
||||
maxEntries: 500,
|
||||
resetArchiveRetentionMs: 7 * DAY_MS,
|
||||
maxDiskBytes: null,
|
||||
highWaterBytes: null,
|
||||
};
|
||||
|
||||
await expect(
|
||||
patchSessionEntry({
|
||||
sessionKey: activeSessionKey,
|
||||
storePath,
|
||||
maintenanceConfig: legacyMaintenanceConfig,
|
||||
update: () => ({ model: "gpt-5.5" }),
|
||||
}),
|
||||
).resolves.toMatchObject({
|
||||
model: "gpt-5.5",
|
||||
sessionId: "session-active",
|
||||
});
|
||||
|
||||
expect(getSessionEntry({ sessionKey: staleModelRunKey, storePath })).toMatchObject({
|
||||
sessionId: "session-probe",
|
||||
});
|
||||
});
|
||||
|
||||
it("keeps deprecated whole-store mutations grouped as one compatibility operation", async () => {
|
||||
const firstSessionKey = "agent:main:first";
|
||||
const secondSessionKey = "agent:main:second";
|
||||
|
||||
@@ -12,7 +12,8 @@ import {
|
||||
updateSessionEntry,
|
||||
} from "../config/sessions/session-accessor.js";
|
||||
import { loadSessionStore as loadSessionStoreImpl } from "../config/sessions/store-load.js";
|
||||
import type { ResolvedSessionMaintenanceConfig } from "../config/sessions/store.js";
|
||||
import { normalizeResolvedMaintenanceConfigInput } from "../config/sessions/store-maintenance.js";
|
||||
import type { ResolvedSessionMaintenanceConfigInput } from "../config/sessions/store.js";
|
||||
import type { SessionEntry } from "../config/sessions/types.js";
|
||||
|
||||
type SessionStoreReadParams = {
|
||||
@@ -42,7 +43,7 @@ type SessionStoreEntryPatch = (
|
||||
|
||||
type PatchSessionEntryParams = SessionStoreReadParams & {
|
||||
fallbackEntry?: SessionEntry;
|
||||
maintenanceConfig?: ResolvedSessionMaintenanceConfig;
|
||||
maintenanceConfig?: ResolvedSessionMaintenanceConfigInput;
|
||||
preserveActivity?: boolean;
|
||||
replaceEntry?: boolean;
|
||||
update: SessionStoreEntryPatch;
|
||||
@@ -128,7 +129,10 @@ export async function patchSessionEntry(
|
||||
): Promise<SessionEntry | null> {
|
||||
return await patchAccessorSessionEntry(toSessionAccessScope(params), params.update, {
|
||||
fallbackEntry: params.fallbackEntry,
|
||||
maintenanceConfig: params.maintenanceConfig,
|
||||
maintenanceConfig:
|
||||
params.maintenanceConfig !== undefined
|
||||
? normalizeResolvedMaintenanceConfigInput(params.maintenanceConfig)
|
||||
: undefined,
|
||||
preserveActivity: params.preserveActivity,
|
||||
replaceEntry: params.replaceEntry,
|
||||
});
|
||||
|
||||
@@ -19,11 +19,12 @@ import {
|
||||
type SessionAccessScope,
|
||||
updateSessionEntry,
|
||||
} from "../../config/sessions/session-accessor.js";
|
||||
import { normalizeResolvedMaintenanceConfigInput } from "../../config/sessions/store-maintenance.js";
|
||||
import {
|
||||
loadSessionStore,
|
||||
saveSessionStore,
|
||||
updateSessionStore,
|
||||
type ResolvedSessionMaintenanceConfig,
|
||||
type ResolvedSessionMaintenanceConfigInput,
|
||||
} from "../../config/sessions/store.js";
|
||||
import type { SessionEntry } from "../../config/sessions/types.js";
|
||||
import { createLazyRuntimeMethod, createLazyRuntimeModule } from "../../shared/lazy-runtime.js";
|
||||
@@ -59,7 +60,7 @@ type RuntimeSessionStoreEntryUpdateParams = {
|
||||
|
||||
type RuntimeSessionStoreEntryPatchParams = RuntimeSessionStoreReadParams & {
|
||||
fallbackEntry?: SessionEntry;
|
||||
maintenanceConfig?: ResolvedSessionMaintenanceConfig;
|
||||
maintenanceConfig?: ResolvedSessionMaintenanceConfigInput;
|
||||
preserveActivity?: boolean;
|
||||
replaceEntry?: boolean;
|
||||
update: (
|
||||
@@ -123,7 +124,10 @@ async function patchSessionEntry(
|
||||
): Promise<SessionEntry | null> {
|
||||
return await patchAccessorSessionEntry(toSessionAccessScope(params), params.update, {
|
||||
fallbackEntry: params.fallbackEntry,
|
||||
maintenanceConfig: params.maintenanceConfig,
|
||||
maintenanceConfig:
|
||||
params.maintenanceConfig !== undefined
|
||||
? normalizeResolvedMaintenanceConfigInput(params.maintenanceConfig)
|
||||
: undefined,
|
||||
preserveActivity: params.preserveActivity,
|
||||
replaceEntry: params.replaceEntry,
|
||||
});
|
||||
|
||||
@@ -75,7 +75,7 @@ type RuntimeSessionStoreEntrySummary = {
|
||||
};
|
||||
type RuntimeSessionStoreEntryPatchParams = RuntimeSessionStoreReadParams & {
|
||||
fallbackEntry?: RuntimeSessionEntry;
|
||||
maintenanceConfig?: import("../../config/sessions/store.js").ResolvedSessionMaintenanceConfig;
|
||||
maintenanceConfig?: import("../../config/sessions/store.js").ResolvedSessionMaintenanceConfigInput;
|
||||
preserveActivity?: boolean;
|
||||
replaceEntry?: boolean;
|
||||
update: (
|
||||
|
||||
Reference in New Issue
Block a user