From 4638b064547a5190e68737bc5d5347100dca094e Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Mon, 13 Jul 2026 04:40:52 +0100 Subject: [PATCH] refactor(runtime): remove deprecated timing aliases --- .../reply/agent-runner-execution.test.ts | 2 - ...run.cron-model-override-forwarding.test.ts | 5 -- src/cron/service/agent-watchdog.ts | 2 +- src/cron/types.ts | 2 - src/gateway/channel-health-monitor.test.ts | 16 +++-- src/gateway/channel-health-monitor.ts | 21 ++---- .../server-runtime-startup-services.ts | 2 +- src/logging/console.ts | 4 +- src/logging/timestamps.test.ts | 66 +++---------------- src/logging/timestamps.ts | 8 --- 10 files changed, 26 insertions(+), 102 deletions(-) diff --git a/src/auto-reply/reply/agent-runner-execution.test.ts b/src/auto-reply/reply/agent-runner-execution.test.ts index 94652303e2e8..2c9b128f4c7d 100644 --- a/src/auto-reply/reply/agent-runner-execution.test.ts +++ b/src/auto-reply/reply/agent-runner-execution.test.ts @@ -402,7 +402,6 @@ type EmbeddedAgentParams = { tool?: string; toolCallId?: string; itemId?: string; - firstModelCallStarted?: boolean; }) => void; onBlockReply?: (payload: { text?: string; mediaUrls?: string[] }) => Promise | void; onPartialReply?: (payload: { text?: string; mediaUrls?: string[] }) => Promise | void; @@ -1718,7 +1717,6 @@ describe("runAgentTurnWithFallback", () => { phase: "model_call_started", provider: "openai", model: "gpt-5.4", - firstModelCallStarted: true, }); return { payloads: [{ text: "final" }], meta: {} }; }); diff --git a/src/cron/isolated-agent/run.cron-model-override-forwarding.test.ts b/src/cron/isolated-agent/run.cron-model-override-forwarding.test.ts index c114f0620d50..c4ba5f9a20fd 100644 --- a/src/cron/isolated-agent/run.cron-model-override-forwarding.test.ts +++ b/src/cron/isolated-agent/run.cron-model-override-forwarding.test.ts @@ -194,7 +194,6 @@ describe("runCronIsolatedAgentTurn — cron model override forwarding (#58065)", phase: "model_call_started", provider: "google", model: "gemini-2.0-flash", - firstModelCallStarted: true, }); return { payloads: [{ text: "summary done" }], @@ -216,7 +215,6 @@ describe("runCronIsolatedAgentTurn — cron model override forwarding (#58065)", phase: "model_call_started", provider: "google", model: "gemini-2.0-flash", - firstModelCallStarted: true, }), ).toBe(true); }); @@ -258,7 +256,6 @@ describe("runCronIsolatedAgentTurn — cron model override forwarding (#58065)", phase: "model_call_started", provider: "google", model: "gemini-2.0-flash", - firstModelCallStarted: true, }); return { payloads: [{ text: "summary done" }], @@ -278,7 +275,6 @@ describe("runCronIsolatedAgentTurn — cron model override forwarding (#58065)", expect( hasPhaseWithFields(phases, { phase: "model_call_started", - firstModelCallStarted: true, }), ).toBe(false); @@ -302,7 +298,6 @@ describe("runCronIsolatedAgentTurn — cron model override forwarding (#58065)", expect( hasPhaseWithFields(phases, { phase: "model_call_started", - firstModelCallStarted: true, }), ).toBe(true); }); diff --git a/src/cron/service/agent-watchdog.ts b/src/cron/service/agent-watchdog.ts index f0237e04850d..6c69c58d4148 100644 --- a/src/cron/service/agent-watchdog.ts +++ b/src/cron/service/agent-watchdog.ts @@ -129,7 +129,7 @@ export function createCronAgentWatchdog(params: { startPreExecutionTimeout(); return; } - if (stage === "execution" || info.firstModelCallStarted) { + if (stage === "execution") { state = "executing"; clearPreExecutionTimeout(); } diff --git a/src/cron/types.ts b/src/cron/types.ts index 0345d1160759..62229b68a10c 100644 --- a/src/cron/types.ts +++ b/src/cron/types.ts @@ -212,8 +212,6 @@ export type CronAgentExecutionStarted = { tool?: string; toolCallId?: string; itemId?: string; - /** @deprecated Use phase-specific execution milestones for watchdog progress. */ - firstModelCallStarted?: boolean; }; /** Watchdog update that requires the new execution phase. */ diff --git a/src/gateway/channel-health-monitor.test.ts b/src/gateway/channel-health-monitor.test.ts index 7d7c36d2ce53..5b80b4f20207 100644 --- a/src/gateway/channel-health-monitor.test.ts +++ b/src/gateway/channel-health-monitor.test.ts @@ -62,8 +62,8 @@ function startDefaultMonitor( return startChannelHealthMonitor({ channelManager: manager, checkIntervalMs: DEFAULT_CHECK_INTERVAL_MS, - startupGraceMs: 0, ...overrides, + timing: { monitorStartupGraceMs: 0, ...overrides.timing }, }); } @@ -72,7 +72,7 @@ async function startAndRunCheck( overrides: Partial[0], "channelManager">> = {}, ) { const monitor = startDefaultMonitor(manager, overrides); - const startupGraceMs = overrides.timing?.monitorStartupGraceMs ?? overrides.startupGraceMs ?? 0; + const startupGraceMs = overrides.timing?.monitorStartupGraceMs ?? 0; const checkIntervalMs = overrides.checkIntervalMs ?? DEFAULT_CHECK_INTERVAL_MS; await vi.advanceTimersByTimeAsync(startupGraceMs + checkIntervalMs + 1); return monitor; @@ -201,7 +201,7 @@ describe("channel-health-monitor", () => { it("does not run before the grace period", async () => { const manager = createMockChannelManager(); - const monitor = startDefaultMonitor(manager, { startupGraceMs: 60_000 }); + const monitor = startDefaultMonitor(manager, { timing: { monitorStartupGraceMs: 60_000 } }); await vi.advanceTimersByTimeAsync(5_001); expect(manager.getRuntimeSnapshot).not.toHaveBeenCalled(); monitor.stop(); @@ -209,7 +209,9 @@ describe("channel-health-monitor", () => { it("runs health check after grace period", async () => { const manager = createMockChannelManager(); - const monitor = await startAndRunCheck(manager, { startupGraceMs: 1_000 }); + const monitor = await startAndRunCheck(manager, { + timing: { monitorStartupGraceMs: 1_000 }, + }); expect(manager.getRuntimeSnapshot).toHaveBeenCalled(); monitor.stop(); }); @@ -456,7 +458,9 @@ describe("channel-health-monitor", () => { }, }, }); - const monitor = await startAndRunCheck(manager, { channelStartupGraceMs: 60_000 }); + const monitor = await startAndRunCheck(manager, { + timing: { channelConnectGraceMs: 60_000 }, + }); expect(manager.stopChannel).not.toHaveBeenCalled(); expect(manager.startChannel).not.toHaveBeenCalled(); monitor.stop(); @@ -845,7 +849,7 @@ describe("channel-health-monitor", () => { }), ); const monitor = await startAndRunCheck(manager, { - staleEventThresholdMs: customThreshold, + timing: { staleEventThresholdMs: customThreshold }, }); expect(manager.stopChannel).toHaveBeenCalledWith("slack", "default", { manual: false }); expect(manager.startChannel).toHaveBeenCalledWith("slack", "default"); diff --git a/src/gateway/channel-health-monitor.ts b/src/gateway/channel-health-monitor.ts index 207da3725002..984ecc3e06e2 100644 --- a/src/gateway/channel-health-monitor.ts +++ b/src/gateway/channel-health-monitor.ts @@ -36,12 +36,6 @@ type ChannelHealthTimingPolicy = { type ChannelHealthMonitorDeps = { channelManager: ChannelManager; checkIntervalMs?: number; - /** @deprecated use timing.monitorStartupGraceMs */ - startupGraceMs?: number; - /** @deprecated use timing.channelConnectGraceMs */ - channelStartupGraceMs?: number; - /** @deprecated use timing.staleEventThresholdMs */ - staleEventThresholdMs?: number; timing?: Partial; cooldownCycles?: number; maxRestartsPerHour?: number; @@ -60,22 +54,15 @@ type RestartRecord = { }; function resolveTimingPolicy( - deps: Pick< - ChannelHealthMonitorDeps, - "startupGraceMs" | "channelStartupGraceMs" | "staleEventThresholdMs" | "timing" - >, + deps: Pick, ): ChannelHealthTimingPolicy { return { monitorStartupGraceMs: - deps.timing?.monitorStartupGraceMs ?? deps.startupGraceMs ?? DEFAULT_MONITOR_STARTUP_GRACE_MS, + deps.timing?.monitorStartupGraceMs ?? DEFAULT_MONITOR_STARTUP_GRACE_MS, channelConnectGraceMs: - deps.timing?.channelConnectGraceMs ?? - deps.channelStartupGraceMs ?? - DEFAULT_CHANNEL_CONNECT_GRACE_MS, + deps.timing?.channelConnectGraceMs ?? DEFAULT_CHANNEL_CONNECT_GRACE_MS, staleEventThresholdMs: - deps.timing?.staleEventThresholdMs ?? - deps.staleEventThresholdMs ?? - DEFAULT_CHANNEL_STALE_EVENT_THRESHOLD_MS, + deps.timing?.staleEventThresholdMs ?? DEFAULT_CHANNEL_STALE_EVENT_THRESHOLD_MS, }; } diff --git a/src/gateway/server-runtime-startup-services.ts b/src/gateway/server-runtime-startup-services.ts index aa4f9ea4b7fc..b1a1668a957e 100644 --- a/src/gateway/server-runtime-startup-services.ts +++ b/src/gateway/server-runtime-startup-services.ts @@ -30,7 +30,7 @@ export function startGatewayChannelHealthMonitor(params: { channelManager: params.channelManager, checkIntervalMs: (healthCheckMinutes ?? 5) * 60_000, ...(staleEventThresholdMinutes != null && { - staleEventThresholdMs: staleEventThresholdMinutes * 60_000, + timing: { staleEventThresholdMs: staleEventThresholdMinutes * 60_000 }, }), ...(maxRestartsPerHour != null && { maxRestartsPerHour }), }); diff --git a/src/logging/console.ts b/src/logging/console.ts index c6a4dee42524..44455ac5c81b 100644 --- a/src/logging/console.ts +++ b/src/logging/console.ts @@ -9,7 +9,7 @@ import { type LogLevel, normalizeLogLevel } from "./levels.js"; import { getLogger } from "./logger.js"; import { redactSensitiveText } from "./redact.js"; import { loggingState } from "./state.js"; -import { formatLocalIsoWithOffset, formatTimestamp } from "./timestamps.js"; +import { formatTimestamp } from "./timestamps.js"; import type { ConsoleStyle, LoggerSettings } from "./types.js"; export type { ConsoleStyle } from "./types.js"; @@ -182,7 +182,7 @@ export function formatConsoleTimestamp(style: ConsoleStyle): string { if (style === "pretty") { return formatTimestamp(now, { style: "short" }).replace(/[+-]\d{2}:\d{2}$/, ""); } - return formatLocalIsoWithOffset(now); + return formatTimestamp(now, { style: "long" }); } function hasTimestampPrefix(value: string): boolean { diff --git a/src/logging/timestamps.test.ts b/src/logging/timestamps.test.ts index b4d3b4136a98..72472e6902c3 100644 --- a/src/logging/timestamps.test.ts +++ b/src/logging/timestamps.test.ts @@ -1,55 +1,6 @@ // Timestamp tests cover timezone validation and timestamp formatting. -import * as fs from "node:fs"; -import * as path from "node:path"; import { describe, expect, it } from "vitest"; -import { formatLocalIsoWithOffset, formatTimestamp, isValidTimeZone } from "./timestamps.js"; - -describe("formatLocalIsoWithOffset", () => { - const testDate = new Date("2025-01-01T04:00:00.000Z"); - - it("produces +00:00 offset for UTC", () => { - const result = formatLocalIsoWithOffset(testDate, "UTC"); - expect(result).toBe("2025-01-01T04:00:00.000+00:00"); - }); - - it("produces +08:00 offset for Asia/Shanghai", () => { - const result = formatLocalIsoWithOffset(testDate, "Asia/Shanghai"); - expect(result).toBe("2025-01-01T12:00:00.000+08:00"); - }); - - it("produces correct offset for America/New_York", () => { - const result = formatLocalIsoWithOffset(testDate, "America/New_York"); - // January is EST = UTC-5 - expect(result).toBe("2024-12-31T23:00:00.000-05:00"); - }); - - it("produces correct offset for America/New_York in summer (EDT)", () => { - const summerDate = new Date("2025-07-01T12:00:00.000Z"); - const result = formatLocalIsoWithOffset(summerDate, "America/New_York"); - // July is EDT = UTC-4 - expect(result).toBe("2025-07-01T08:00:00.000-04:00"); - }); - - it("outputs a valid ISO 8601 string with offset", () => { - const result = formatLocalIsoWithOffset(testDate, "Asia/Shanghai"); - // ISO 8601 with offset: YYYY-MM-DDTHH:MM:SS.mmm±HH:MM - const iso8601WithOffset = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}[+-]\d{2}:\d{2}$/; - expect(result).toMatch(iso8601WithOffset); - }); - - it("falls back gracefully for an invalid timezone", () => { - const result = formatLocalIsoWithOffset(testDate, "not-a-tz"); - const iso8601WithOffset = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}[+-]\d{2}:\d{2}$/; - expect(result).toMatch(iso8601WithOffset); - }); - - it("does NOT use getHours, getMinutes, getTimezoneOffset in the implementation", () => { - const source = fs.readFileSync(path.resolve(__dirname, "timestamps.ts"), "utf-8"); - expect(source).not.toMatch(/\.getHours\s*\(/); - expect(source).not.toMatch(/\.getMinutes\s*\(/); - expect(source).not.toMatch(/\.getTimezoneOffset\s*\(/); - }); -}); +import { formatTimestamp, isValidTimeZone } from "./timestamps.js"; describe("formatTimestamp", () => { const testDate = new Date("2024-01-15T14:30:45.123Z"); @@ -64,14 +15,13 @@ describe("formatTimestamp", () => { ); }); - it.each(["UTC", "America/New_York", "Europe/Paris"])( - "matches formatLocalIsoWithOffset for long style in %s", - (timeZone) => { - expect(formatTimestamp(testDate, { style: "long", timeZone })).toBe( - formatLocalIsoWithOffset(testDate, timeZone), - ); - }, - ); + it.each([ + ["UTC", "2024-01-15T14:30:45.123+00:00"], + ["America/New_York", "2024-01-15T09:30:45.123-05:00"], + ["Europe/Paris", "2024-01-15T15:30:45.123+01:00"], + ])("formats long style in %s", (timeZone, expected) => { + expect(formatTimestamp(testDate, { style: "long", timeZone })).toBe(expected); + }); it("falls back to a valid offset when the timezone is invalid", () => { expect(formatTimestamp(testDate, { style: "short", timeZone: "not-a-tz" })).toMatch( diff --git a/src/logging/timestamps.ts b/src/logging/timestamps.ts index 70b418f856e7..7fd78d0fb59d 100644 --- a/src/logging/timestamps.ts +++ b/src/logging/timestamps.ts @@ -85,11 +85,3 @@ export function formatTimestamp(date: Date, options?: FormatTimestampOptions): s } throw new Error("Unsupported timestamp style"); } - -/** - * @deprecated Use formatTimestamp from "./timestamps.js" instead. - * This function will be removed in a future version. - */ -export function formatLocalIsoWithOffset(now: Date, timeZone?: string): string { - return formatTimestamp(now, { style: "long", timeZone }); -}