惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
V
Visual Studio Blog
IT之家
IT之家
博客园 - 聂微东
The Cloudflare Blog
月光博客
月光博客
阮一峰的网络日志
阮一峰的网络日志
S
SegmentFault 最新的问题
Apple Machine Learning Research
Apple Machine Learning Research
酷 壳 – CoolShell
酷 壳 – CoolShell
爱范儿
爱范儿
H
Help Net Security
博客园 - 叶小钗
V
V2EX
WordPress大学
WordPress大学
J
Java Code Geeks
Hugging Face - Blog
Hugging Face - Blog
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
博客园_首页
C
Check Point Blog
B
Blog
D
DataBreaches.Net
美团技术团队
罗磊的独立博客

Recent Commits to openclaw:main

test: merge chat side-result checks · openclaw/openclaw@ddd2c2a test: merge cron history checks · openclaw/openclaw@f7eb746 test: merge responsive navigation shell checks · openclaw/openclaw@c2e4b47 docs(changelog): add codex oauth fixes · openclaw/openclaw@628e6cd test: merge navigation routing cases · openclaw/openclaw@5d8cecb Tests: mock channel registry bundled fallback · openclaw/openclaw@2b08233 Secrets: avoid broad web search discovery for single plugin config · openclaw/openclaw@a464f59 test: merge config view browser checks · openclaw/openclaw@20cf511 fix(status): align oauth health with runtime · openclaw/openclaw@eed7116 feat: add macOS screen snapshots for monitor preview (#67954) thanks … · openclaw/openclaw@f377db1 fix: report shared auth scopes in hello-ok (#67810) thanks @BunsDev · openclaw/openclaw@0b6c39b Auto-reply: avoid eager bundled route fallback · openclaw/openclaw@3ea1bf4 Tests: narrow session binding contract setup · openclaw/openclaw@54e4e16 fix(macOS): enable undo/redo in webchat composer text input (#34962) · openclaw/openclaw@00951dc Tests: speed up channel setup promotion · openclaw/openclaw@82b529a Docs: refresh agent instructions · openclaw/openclaw@5775fe2 fix(auth): serialize OAuth refresh across agents to fix #26322 (#67876) · openclaw/openclaw@8e79080 test: allow ollama public surface boundary test · openclaw/openclaw@7d4f1a6 Docs: add test performance guardrails · openclaw/openclaw@89706d3 Tests: restore context-engine usage proof · openclaw/openclaw@e4c4f95 Tests: slim context engine runtime coverage · openclaw/openclaw@74c198f ci: retry failed custom checkouts · openclaw/openclaw@0ee5baf test: trim duplicate provider auth onboarding cases · openclaw/openclaw@1ffc02e matrix: fix sessions_spawn --thread subagent session spawning (#67643) · openclaw/openclaw@1ce2596 test: reduce auth choice fixture churn · openclaw/openclaw@857b9cd test: mock health status config boundaries · openclaw/openclaw@9d5ab4a test: mock onboard config io boundary · openclaw/openclaw@299694d test: mock legacy state plugin boundaries · openclaw/openclaw@2713089 test: mock channel install boundaries · openclaw/openclaw@b945248 test: mock doctor preview channel boundaries · openclaw/openclaw@b1a3ad4
fix(update): guard startup timestamps · openclaw/openclaw...
steipete · 2026-05-30 · via Recent Commits to openclaw:main

@@ -5,6 +5,7 @@ import { formatCliCommand } from "../cli/command-format.js";

55

import { resolveStateDir } from "../config/paths.js";

66

import type { OpenClawConfig } from "../config/types.openclaw.js";

77

import { runCommandWithTimeout } from "../process/exec.js";

8+

import { asDateTimestampMs, timestampMsToIsoString } from "../shared/number-coercion.js";

89

import { normalizeLowercaseStringOrEmpty } from "../shared/string-coerce.js";

910

import { VERSION } from "../version.js";

1011

import { isTruthyEnvValue } from "./env.js";

@@ -188,6 +189,18 @@ function resolveStableJitterMs(params: {

188189

return bucket % (Math.floor(params.jitterWindowMs) + 1);

189190

}

190191192+

function resolveUpdateCheckNowMs(valueMs: unknown): number {

193+

return asDateTimestampMs(valueMs) ?? asDateTimestampMs(Date.now()) ?? 0;

194+

}

195+196+

function resolveUpdateCheckTimestamp(valueMs: unknown): string {

197+

return (

198+

timestampMsToIsoString(valueMs) ??

199+

timestampMsToIsoString(resolveUpdateCheckNowMs(Date.now())) ??

200+

new Date().toISOString()

201+

);

202+

}

203+191204

function resolveStableAutoApplyAtMs(params: {

192205

state: UpdateCheckState;

193206

nextState: UpdateCheckState;

@@ -208,16 +221,17 @@ function resolveStableAutoApplyAtMs(params: {

208221

if (!matchesExisting) {

209222

params.nextState.autoFirstSeenVersion = params.version;

210223

params.nextState.autoFirstSeenTag = params.tag;

211-

params.nextState.autoFirstSeenAt = new Date(params.nowMs).toISOString();

224+

params.nextState.autoFirstSeenAt = resolveUpdateCheckTimestamp(params.nowMs);

212225

} else {

213226

params.nextState.autoFirstSeenVersion = params.state.autoFirstSeenVersion;

214227

params.nextState.autoFirstSeenTag = params.state.autoFirstSeenTag;

215228

params.nextState.autoFirstSeenAt = params.state.autoFirstSeenAt;

216229

}

217230218-

const firstSeenMs = params.nextState.autoFirstSeenAt

231+

const parsedFirstSeenMs = params.nextState.autoFirstSeenAt

219232

? Date.parse(params.nextState.autoFirstSeenAt)

220233

: params.nowMs;

234+

const firstSeenMs = Number.isFinite(parsedFirstSeenMs) ? parsedFirstSeenMs : params.nowMs;

221235

const baseDelayMs = Math.max(0, params.stableDelayHours) * ONE_HOUR_MS;

222236

const jitterWindowMs = Math.max(0, params.stableJitterHours) * ONE_HOUR_MS;

223237

const jitterMs = resolveStableJitterMs({

@@ -327,7 +341,9 @@ export async function runGatewayUpdateCheck(params: {

327341328342

const statePath = path.join(resolveStateDir(), UPDATE_CHECK_FILENAME);

329343

const state = await readState(statePath);

330-

const now = Date.now();

344+

const rawNow = Date.now();

345+

const now = resolveUpdateCheckNowMs(rawNow);

346+

const rawNowIsValid = asDateTimestampMs(rawNow) !== undefined;

331347

const lastCheckedAt = state.lastCheckedAt ? Date.parse(state.lastCheckedAt) : null;

332348

if (shouldRunUpdateHints) {

333349

const persistedAvailable = resolvePersistedUpdateAvailable(state);

@@ -344,7 +360,7 @@ export async function runGatewayUpdateCheck(params: {

344360

const checkIntervalMs = shouldRunAutoUpdate

345361

? resolveCheckIntervalMs(params.cfg)

346362

: UPDATE_CHECK_INTERVAL_MS;

347-

if (lastCheckedAt && Number.isFinite(lastCheckedAt)) {

363+

if (rawNowIsValid && lastCheckedAt && Number.isFinite(lastCheckedAt)) {

348364

if (now - lastCheckedAt < checkIntervalMs) {

349365

return;

350366

}

@@ -364,7 +380,7 @@ export async function runGatewayUpdateCheck(params: {

364380365381

const nextState: UpdateCheckState = {

366382

...state,

367-

lastCheckedAt: new Date(now).toISOString(),

383+

lastCheckedAt: resolveUpdateCheckTimestamp(now),

368384

};

369385370386

if (status.installKind !== "package") {

@@ -451,7 +467,7 @@ export async function runGatewayUpdateCheck(params: {

451467

params.log.info("auto-update deferred (stable rollout window active)", {

452468

version: resolved.version,

453469

tag,

454-

applyAfter: applyAfterMs ? new Date(applyAfterMs).toISOString() : undefined,

470+

applyAfter: applyAfterMs ? resolveUpdateCheckTimestamp(applyAfterMs) : undefined,

455471

});

456472

} else if (recentAttemptForSameVersion) {

457473

params.log.info("auto-update deferred (recent attempt exists)", {

@@ -460,15 +476,15 @@ export async function runGatewayUpdateCheck(params: {

460476

});

461477

} else {

462478

nextState.autoLastAttemptVersion = resolved.version;

463-

nextState.autoLastAttemptAt = new Date(now).toISOString();

479+

nextState.autoLastAttemptAt = resolveUpdateCheckTimestamp(now);

464480

const outcome = await runAuto({

465481

channel,

466482

timeoutMs: AUTO_UPDATE_COMMAND_TIMEOUT_MS,

467483

root: root ?? undefined,

468484

});

469485

if (outcome.ok) {

470486

nextState.autoLastSuccessVersion = resolved.version;

471-

nextState.autoLastSuccessAt = new Date(now).toISOString();

487+

nextState.autoLastSuccessAt = resolveUpdateCheckTimestamp(now);

472488

params.log.info("auto-update applied", {

473489

channel,

474490

version: resolved.version,