
























@@ -5,6 +5,13 @@ import {
55getNodeSqliteKysely,
66} from "../../infra/kysely-sync.js";
77import { normalizeAgentId } from "../../routing/session-key.js";
8+import {
9+MAX_DATE_TIMESTAMP_MS,
10+asDateTimestampMs,
11+isFutureDateTimestampMs,
12+resolveDateTimestampMs,
13+resolveExpiresAtMsFromDurationMs,
14+} from "../../shared/number-coercion.js";
815import type { DB as OpenClawAgentKyselyDatabase } from "../../state/openclaw-agent-db.generated.js";
916import {
1017openOpenClawAgentDatabase,
@@ -89,7 +96,7 @@ function parseValue(raw: string | null): unknown {
89969097function isExpired(row: AgentCacheRow, now: number): boolean {
9198const expiresAt = asNumber(row.expires_at);
92-return expiresAt !== null && expiresAt <= now;
99+return expiresAt !== null && !isFutureDateTimestampMs(expiresAt, { nowMs: now });
93100}
9410195102function rowToCacheValue(
@@ -112,17 +119,31 @@ function resolveExpiresAt(options: AgentRuntimeCacheWriteOptions, now: number):
112119if (!Number.isFinite(options.ttlMs) || options.ttlMs <= 0) {
113120throw new Error("SQLite agent cache ttlMs must be a positive finite number.");
114121}
115-return now + options.ttlMs;
122+const expiresAt = resolveExpiresAtMsFromDurationMs(options.ttlMs, { nowMs: now });
123+if (expiresAt === undefined) {
124+throw new Error("SQLite agent cache ttlMs must resolve to a valid Date timestamp.");
125+}
126+return expiresAt;
116127}
117-return options.expiresAt ?? null;
128+if (options.expiresAt !== undefined) {
129+if (options.expiresAt === null) {
130+return null;
131+}
132+const expiresAt = asDateTimestampMs(options.expiresAt);
133+if (expiresAt === undefined) {
134+throw new Error("SQLite agent cache expiresAt must be a valid Date timestamp.");
135+}
136+return expiresAt;
137+}
138+return null;
118139}
119140120141export function writeSqliteAgentCacheEntry(
121142options: WriteSqliteAgentCacheEntryOptions,
122143): AgentRuntimeCacheValue {
123144const scope = normalizeScope(options);
124145const key = normalizeKey(options.key);
125-const updatedAt = options.now?.() ?? Date.now();
146+const updatedAt = resolveDateTimestampMs(options.now?.());
126147const expiresAt = resolveExpiresAt(options, updatedAt);
127148const valueJson = options.value === undefined ? null : JSON.stringify(options.value);
128149const blob =
@@ -182,7 +203,7 @@ export function readSqliteAgentCacheEntry(
182203.where("scope", "=", scope.scope)
183204.where("key", "=", key),
184205) ?? null;
185-if (!row || isExpired(row, options.now?.() ?? Date.now())) {
206+if (!row || isExpired(row, resolveDateTimestampMs(options.now?.()))) {
186207return null;
187208}
188209return rowToCacheValue(row, scope);
@@ -192,7 +213,7 @@ export function listSqliteAgentCacheEntries(
192213options: SqliteAgentCacheStoreOptions,
193214): AgentRuntimeCacheValue[] {
194215const scope = normalizeScope(options);
195-const now = options.now?.() ?? Date.now();
216+const now = resolveDateTimestampMs(options.now?.());
196217const database = openOpenClawAgentDatabase(toDatabaseOptions(options));
197218const db = getNodeSqliteKysely<AgentCacheDatabase>(database.db);
198219return executeSqliteQuerySync(
@@ -238,7 +259,10 @@ export function clearExpiredSqliteAgentCacheEntries(
238259options: SqliteAgentCacheStoreOptions & { currentTime?: number },
239260): number {
240261const scope = normalizeScope(options);
241-const currentTime = options.currentTime ?? options.now?.() ?? Date.now();
262+const currentTime = asDateTimestampMs(options.currentTime ?? options.now?.() ?? Date.now());
263+if (currentTime === undefined) {
264+return 0;
265+}
242266return runOpenClawAgentWriteTransaction((database) => {
243267const db = getNodeSqliteKysely<AgentCacheDatabase>(database.db);
244268const result = executeSqliteQuerySync(
@@ -247,7 +271,13 @@ export function clearExpiredSqliteAgentCacheEntries(
247271.deleteFrom("cache_entries")
248272.where("scope", "=", scope.scope)
249273.where("expires_at", "is not", null)
250-.where("expires_at", "<=", currentTime),
274+.where((eb) =>
275+eb.or([
276+eb("expires_at", "<=", currentTime),
277+eb("expires_at", ">", MAX_DATE_TIMESTAMP_MS),
278+eb("expires_at", "<", -MAX_DATE_TIMESTAMP_MS),
279+]),
280+),
251281);
252282return Number(result.numAffectedRows ?? 0);
253283}, toDatabaseOptions(options));
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。