From 0a808de6a25afd59222a695fcbc1fa6d03c3571b Mon Sep 17 00:00:00 2001 From: Sisyphus Date: Sat, 18 Apr 2026 17:23:50 +0900 Subject: [PATCH] fix(auto-update-checker): trigger deferred startup on session.created with parentID guard --- src/hooks/auto-update-checker/hook.test.ts | 22 +++++++++---------- src/hooks/auto-update-checker/hook.ts | 21 +++++++++++++++--- .../hook/deferred-idle-check.ts | 4 ---- .../hook/deferred-startup-check.ts | 4 ++++ src/hooks/zauc-mocks-hook/hook.test.ts | 4 ++-- 5 files changed, 35 insertions(+), 20 deletions(-) delete mode 100644 src/hooks/auto-update-checker/hook/deferred-idle-check.ts create mode 100644 src/hooks/auto-update-checker/hook/deferred-startup-check.ts diff --git a/src/hooks/auto-update-checker/hook.test.ts b/src/hooks/auto-update-checker/hook.test.ts index 4dba87298..a6cacd54d 100644 --- a/src/hooks/auto-update-checker/hook.test.ts +++ b/src/hooks/auto-update-checker/hook.test.ts @@ -6,7 +6,7 @@ type HookOptions = Parameters[1] type HookDeps = NonNullable[2]> let latestVersionCallCount = 0 -let scheduleDeferredIdleCheckCallCount = 0 +let scheduleDeferredStartupCheckCallCount = 0 const flushMicrotasks = async (count: number): Promise => { for (let index = 0; index < count; index += 1) { @@ -19,8 +19,8 @@ const latestVersionMock = async () => { return "3.0.1" } -const scheduleDeferredIdleCheckMock = (runCheck: () => void) => { - scheduleDeferredIdleCheckCallCount += 1 +const scheduleDeferredStartupCheckMock = (runCheck: () => void) => { + scheduleDeferredStartupCheckCallCount += 1 scheduledCheck = runCheck } @@ -30,8 +30,8 @@ mock.module("./checker/latest-version", () => ({ getLatestVersion: latestVersionMock, })) -mock.module("./hook/deferred-idle-check", () => ({ - scheduleDeferredIdleCheck: scheduleDeferredIdleCheckMock, +mock.module("./hook/deferred-startup-check", () => ({ + scheduleDeferredStartupCheck: scheduleDeferredStartupCheckMock, })) const createPluginInput = (): PluginInput => ({ @@ -105,7 +105,7 @@ const createHook = async ( const resetDeferredState = (): void => { latestVersionCallCount = 0 - scheduleDeferredIdleCheckCallCount = 0 + scheduleDeferredStartupCheckCallCount = 0 scheduledCheck = null } @@ -135,7 +135,7 @@ describe("auto-update-checker hook", () => { triggerSessionCreated(hook) // then - expect(scheduleDeferredIdleCheckCallCount).toBe(1) + expect(scheduleDeferredStartupCheckCallCount).toBe(1) expect(mocks.showVersionToast).not.toHaveBeenCalled() expect(mocks.runBackgroundUpdateCheck).not.toHaveBeenCalled() expect(latestVersionCallCount).toBe(0) @@ -158,7 +158,7 @@ describe("auto-update-checker hook", () => { triggerSessionCreated(hook, { info: { parentID: "parent-123" } }) // then - expect(scheduleDeferredIdleCheckCallCount).toBe(0) + expect(scheduleDeferredStartupCheckCallCount).toBe(0) expect(mocks.showVersionToast).not.toHaveBeenCalled() expect(mocks.runBackgroundUpdateCheck).not.toHaveBeenCalled() }) @@ -172,7 +172,7 @@ describe("auto-update-checker hook", () => { triggerSessionIdle(hook) // then - expect(scheduleDeferredIdleCheckCallCount).toBe(0) + expect(scheduleDeferredStartupCheckCallCount).toBe(0) expect(mocks.showVersionToast).not.toHaveBeenCalled() expect(mocks.runBackgroundUpdateCheck).not.toHaveBeenCalled() }) @@ -205,14 +205,14 @@ describe("auto-update-checker hook", () => { triggerSessionCreated(hook) // then - expect(scheduleDeferredIdleCheckCallCount).toBe(1) + expect(scheduleDeferredStartupCheckCallCount).toBe(1) // when await runScheduledCheck() triggerSessionCreated(hook) // then - expect(scheduleDeferredIdleCheckCallCount).toBe(1) + expect(scheduleDeferredStartupCheckCallCount).toBe(1) expect(mocks.showConfigErrorsIfAny).toHaveBeenCalledTimes(1) expect(mocks.updateAndShowConnectedProvidersCacheStatus).toHaveBeenCalledTimes(1) expect(mocks.showModelCacheWarningIfNeeded).toHaveBeenCalledTimes(1) diff --git a/src/hooks/auto-update-checker/hook.ts b/src/hooks/auto-update-checker/hook.ts index 73f5eed4b..2306c03a0 100644 --- a/src/hooks/auto-update-checker/hook.ts +++ b/src/hooks/auto-update-checker/hook.ts @@ -3,7 +3,7 @@ import { log } from "../../shared/logger" import type { AutoUpdateCheckerOptions } from "./types" import { getCachedVersion, getLocalDevVersion } from "./checker" import { runBackgroundUpdateCheck } from "./hook/background-update-check" -import { scheduleDeferredIdleCheck } from "./hook/deferred-idle-check" +import { scheduleDeferredStartupCheck } from "./hook/deferred-startup-check" import { showConfigErrorsIfAny } from "./hook/config-errors-toast" import { updateAndShowConnectedProvidersCacheStatus } from "./hook/connected-providers-status" import { refreshModelCapabilitiesOnStartup } from "./hook/model-capabilities-status" @@ -36,6 +36,20 @@ const defaultDeps: AutoUpdateCheckerDeps = { log, } +const isRecord = (value: unknown): value is Record => { + return typeof value === "object" && value !== null +} + +const getParentID = (properties: unknown): string | undefined => { + if (!isRecord(properties)) return undefined + + const { info } = properties + if (!isRecord(info)) return undefined + + const { parentID } = info + return typeof parentID === "string" && parentID.length > 0 ? parentID : undefined +} + export function createAutoUpdateCheckerHook( ctx: PluginInput, options: AutoUpdateCheckerOptions = {}, @@ -65,13 +79,14 @@ export function createAutoUpdateCheckerHook( return { event: ({ event }: { event: { type: string; properties?: unknown } }) => { - if (event.type !== "session.idle") return + if (event.type !== "session.created") return if (isCliRunMode) return if (hasChecked || hasScheduled) return + if (getParentID(event.properties)) return hasScheduled = true - scheduleDeferredIdleCheck(() => { + scheduleDeferredStartupCheck(() => { hasChecked = true void (async () => { const cachedVersion = deps.getCachedVersion() diff --git a/src/hooks/auto-update-checker/hook/deferred-idle-check.ts b/src/hooks/auto-update-checker/hook/deferred-idle-check.ts deleted file mode 100644 index a929cf4ee..000000000 --- a/src/hooks/auto-update-checker/hook/deferred-idle-check.ts +++ /dev/null @@ -1,4 +0,0 @@ -export function scheduleDeferredIdleCheck(runCheck: () => void): void { - const timeout = setTimeout(runCheck, 5000) - timeout.unref?.() -} diff --git a/src/hooks/auto-update-checker/hook/deferred-startup-check.ts b/src/hooks/auto-update-checker/hook/deferred-startup-check.ts new file mode 100644 index 000000000..2e1066424 --- /dev/null +++ b/src/hooks/auto-update-checker/hook/deferred-startup-check.ts @@ -0,0 +1,4 @@ +export function scheduleDeferredStartupCheck(runCheck: () => void): void { + const timeout = setTimeout(runCheck, 5000) + timeout.unref?.() +} diff --git a/src/hooks/zauc-mocks-hook/hook.test.ts b/src/hooks/zauc-mocks-hook/hook.test.ts index ce1e3e3d3..de0e4d3d2 100644 --- a/src/hooks/zauc-mocks-hook/hook.test.ts +++ b/src/hooks/zauc-mocks-hook/hook.test.ts @@ -1,8 +1,8 @@ import { afterEach, beforeEach, describe, expect, it, mock } from "bun:test" let scheduledDeferredCheck: (() => void) | null = null -mock.module("../auto-update-checker/hook/deferred-idle-check", () => ({ - scheduleDeferredIdleCheck: (runCheck: () => void) => { +mock.module("../auto-update-checker/hook/deferred-startup-check", () => ({ + scheduleDeferredStartupCheck: (runCheck: () => void) => { scheduledDeferredCheck = runCheck }, }))