diff --git a/src/agents/command/session-store.ts b/src/agents/command/session-store.ts index 5726a9470bb..7c15059643a 100644 --- a/src/agents/command/session-store.ts +++ b/src/agents/command/session-store.ts @@ -11,6 +11,7 @@ import { patchSessionEntry } from "../../config/sessions/session-accessor.js"; import { resolveMaintenanceConfigFromInput } from "../../config/sessions/store-maintenance.js"; import type { OpenClawConfig } from "../../config/types.openclaw.js"; import { createLazyImportLoader } from "../../shared/lazy-promise.js"; +import { resolveNonNegativeNumber } from "../../shared/number-coercion.js"; import { clearCliSession, setCliSessionBinding, setCliSessionId } from "../cli-session.js"; import { DEFAULT_CONTEXT_TOKENS } from "../defaults.js"; import { isCliProvider } from "../model-selection.js"; @@ -29,10 +30,6 @@ async function getContextModule() { return await contextModuleLoader.load(); } -function resolveNonNegativeNumber(value: number | undefined): number | undefined { - return typeof value === "number" && Number.isFinite(value) && value >= 0 ? value : undefined; -} - function resolvePositiveInteger(value: number | undefined): number | undefined { if (typeof value !== "number" || !Number.isFinite(value) || value <= 0) { return undefined; diff --git a/src/auto-reply/reply/session-usage.ts b/src/auto-reply/reply/session-usage.ts index d681a05e7db..3d61607d64a 100644 --- a/src/auto-reply/reply/session-usage.ts +++ b/src/auto-reply/reply/session-usage.ts @@ -18,6 +18,7 @@ import { import { updateSessionEntry } from "../../config/sessions/session-accessor.js"; import type { OpenClawConfig } from "../../config/types.openclaw.js"; import { logVerbose } from "../../globals.js"; +import { resolveNonNegativeNumber } from "../../shared/number-coercion.js"; import { estimateUsageCost, resolveModelCostConfig } from "../../utils/usage-format.js"; function applyCliSessionIdToSessionPatch( @@ -67,10 +68,6 @@ function applyCliSessionIdToSessionPatch( return patch; } -function resolveNonNegativeNumber(value: number | undefined): number | undefined { - return typeof value === "number" && Number.isFinite(value) && value >= 0 ? value : undefined; -} - function resolveNonNegativeTokenCount(value: number | undefined): number | undefined { const resolved = resolveNonNegativeNumber(value); return resolved === undefined ? undefined : Math.floor(resolved); diff --git a/src/cron/isolated-agent/run.ts b/src/cron/isolated-agent/run.ts index 542becc12b6..1dae5344639 100644 --- a/src/cron/isolated-agent/run.ts +++ b/src/cron/isolated-agent/run.ts @@ -39,6 +39,7 @@ import { createDiagnosticMessageLifecycle } from "../../logging/message-lifecycl import { isCommandLaneTaskTimeoutError } from "../../process/command-queue.js"; import { CommandLane } from "../../process/lanes.js"; import { createLazyImportLoader } from "../../shared/lazy-promise.js"; +import { resolveNonNegativeNumber } from "../../shared/number-coercion.js"; import { resolveCronSkillsSnapshot } from "../../skills/runtime/cron-snapshot.js"; import type { SkillSnapshot } from "../../skills/types.js"; import { @@ -175,10 +176,6 @@ function hasConfiguredAuthProfiles(cfg: OpenClawConfig): boolean { ); } -function resolveNonNegativeNumber(value: number | undefined): number | undefined { - return typeof value === "number" && Number.isFinite(value) && value >= 0 ? value : undefined; -} - function isCronNestedLaneTaskTimeoutError(err: unknown): boolean { return isCommandLaneTaskTimeoutError(err, CommandLane.CronNested); } diff --git a/src/gateway/session-utils.ts b/src/gateway/session-utils.ts index a3f6c28dad1..7f091a51e5b 100644 --- a/src/gateway/session-utils.ts +++ b/src/gateway/session-utils.ts @@ -91,6 +91,7 @@ import { isWorkspaceRelativeAvatarPath, resolveAvatarMime, } from "../shared/avatar-policy.js"; +import { resolveNonNegativeNumber } from "../shared/number-coercion.js"; import { normalizeSessionDeliveryFields } from "../utils/delivery-context.shared.js"; import type { ModelCostConfig } from "../utils/usage-format.js"; import { estimateUsageCost, resolveModelCostConfig } from "../utils/usage-format.js"; @@ -274,10 +275,6 @@ function resolvePositiveNumber(value: number | null | undefined): number | undef return typeof value === "number" && Number.isFinite(value) && value > 0 ? value : undefined; } -function resolveNonNegativeNumber(value: number | null | undefined): number | undefined { - return typeof value === "number" && Number.isFinite(value) && value >= 0 ? value : undefined; -} - type SessionCompactionCheckpointEntry = NonNullable[number]; function isProjectableCompactionCheckpoint( diff --git a/src/shared/number-coercion.ts b/src/shared/number-coercion.ts index 4c93865de6c..6d0465e500f 100644 --- a/src/shared/number-coercion.ts +++ b/src/shared/number-coercion.ts @@ -1,2 +1,6 @@ /** Shared numeric coercion facade for legacy imports inside core. */ export * from "@openclaw/normalization-core/number-coercion"; + +export function resolveNonNegativeNumber(value: number | null | undefined): number | undefined { + return typeof value === "number" && Number.isFinite(value) && value >= 0 ? value : undefined; +}