From fbd832d64f19bd7f0877071fe248319d84427672 Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Mon, 2 Mar 2026 00:32:16 +0000 Subject: [PATCH] refactor(config): share byte-size parsing for memory flush --- src/auto-reply/reply/memory-flush.ts | 24 ++------------------ src/config/byte-size.ts | 29 +++++++++++++++++++++++++ src/config/zod-schema.agent-defaults.ts | 13 ++++------- 3 files changed, 35 insertions(+), 31 deletions(-) create mode 100644 src/config/byte-size.ts diff --git a/src/auto-reply/reply/memory-flush.ts b/src/auto-reply/reply/memory-flush.ts index 4fe74e7d4..4c8116fa0 100644 --- a/src/auto-reply/reply/memory-flush.ts +++ b/src/auto-reply/reply/memory-flush.ts @@ -2,7 +2,7 @@ import { lookupContextTokens } from "../../agents/context.js"; import { resolveCronStyleNow } from "../../agents/current-time.js"; import { DEFAULT_CONTEXT_TOKENS } from "../../agents/defaults.js"; import { DEFAULT_PI_COMPACTION_RESERVE_TOKENS_FLOOR } from "../../agents/pi-settings.js"; -import { parseByteSize } from "../../cli/parse-bytes.js"; +import { parseNonNegativeByteSize } from "../../config/byte-size.js"; import type { OpenClawConfig } from "../../config/config.js"; import { resolveFreshSessionTotalTokens, type SessionEntry } from "../../config/sessions.js"; import { SILENT_REPLY_TOKEN } from "../tokens.js"; @@ -78,26 +78,6 @@ const normalizeNonNegativeInt = (value: unknown): number | null => { return int >= 0 ? int : null; }; -const normalizeOptionalByteSize = (value: unknown): number | null => { - if (typeof value === "number" && Number.isFinite(value)) { - const int = Math.floor(value); - return int >= 0 ? int : null; - } - if (typeof value === "string") { - const trimmed = value.trim(); - if (!trimmed) { - return null; - } - try { - const bytes = parseByteSize(trimmed, { defaultUnit: "b" }); - return bytes >= 0 ? bytes : null; - } catch { - return null; - } - } - return null; -}; - export function resolveMemoryFlushSettings(cfg?: OpenClawConfig): MemoryFlushSettings | null { const defaults = cfg?.agents?.defaults?.compaction?.memoryFlush; const enabled = defaults?.enabled ?? true; @@ -107,7 +87,7 @@ export function resolveMemoryFlushSettings(cfg?: OpenClawConfig): MemoryFlushSet const softThresholdTokens = normalizeNonNegativeInt(defaults?.softThresholdTokens) ?? DEFAULT_MEMORY_FLUSH_SOFT_TOKENS; const forceFlushTranscriptBytes = - normalizeOptionalByteSize(defaults?.forceFlushTranscriptBytes) ?? + parseNonNegativeByteSize(defaults?.forceFlushTranscriptBytes) ?? DEFAULT_MEMORY_FLUSH_FORCE_TRANSCRIPT_BYTES; const prompt = defaults?.prompt?.trim() || DEFAULT_MEMORY_FLUSH_PROMPT; const systemPrompt = defaults?.systemPrompt?.trim() || DEFAULT_MEMORY_FLUSH_SYSTEM_PROMPT; diff --git a/src/config/byte-size.ts b/src/config/byte-size.ts new file mode 100644 index 000000000..4b76f4958 --- /dev/null +++ b/src/config/byte-size.ts @@ -0,0 +1,29 @@ +import { parseByteSize } from "../cli/parse-bytes.js"; + +/** + * Parse an optional byte-size value from config. + * Accepts non-negative numbers or strings like "2mb". + */ +export function parseNonNegativeByteSize(value: unknown): number | null { + if (typeof value === "number" && Number.isFinite(value)) { + const int = Math.floor(value); + return int >= 0 ? int : null; + } + if (typeof value === "string") { + const trimmed = value.trim(); + if (!trimmed) { + return null; + } + try { + const bytes = parseByteSize(trimmed, { defaultUnit: "b" }); + return bytes >= 0 ? bytes : null; + } catch { + return null; + } + } + return null; +} + +export function isValidNonNegativeByteSizeString(value: string): boolean { + return parseNonNegativeByteSize(value) !== null; +} diff --git a/src/config/zod-schema.agent-defaults.ts b/src/config/zod-schema.agent-defaults.ts index 1c04085f3..0f60ab980 100644 --- a/src/config/zod-schema.agent-defaults.ts +++ b/src/config/zod-schema.agent-defaults.ts @@ -1,5 +1,5 @@ import { z } from "zod"; -import { parseByteSize } from "../cli/parse-bytes.js"; +import { isValidNonNegativeByteSizeString } from "./byte-size.js"; import { HeartbeatSchema, AgentSandboxSchema, @@ -96,14 +96,9 @@ export const AgentDefaultsSchema = z forceFlushTranscriptBytes: z .union([ z.number().int().nonnegative(), - z.string().refine((value) => { - try { - parseByteSize(value.trim(), { defaultUnit: "b" }); - return true; - } catch { - return false; - } - }, "Expected byte size string like 2mb"), + z + .string() + .refine(isValidNonNegativeByteSizeString, "Expected byte size string like 2mb"), ]) .optional(), prompt: z.string().optional(),