feat: enable continuous hooks configuration reload

Move the periodic hooks configuration reload from the HooksSettings component to the main App component. This ensures that hooks are reloaded every 5 seconds whenever the feature is enabled, regardless of which settings tab is currently active.
This commit is contained in:
Toray Altas 2026-01-17 10:43:22 -05:00
parent ad1cbc206c
commit f8bd3ba870
3 changed files with 75 additions and 1 deletions

View file

@ -66,8 +66,19 @@ const App = () => {
cloudOrganizations,
renderContext,
mdmCompliant,
experiments,
} = useExtensionState()
// Hooks auto-reload
useEffect(() => {
if (experiments?.hooks) {
const intervalId = setInterval(() => {
vscode.postMessage({ type: "hooksReloadConfig" })
}, 5000)
return () => clearInterval(intervalId)
}
}, [experiments?.hooks])
// Create a persistent state manager
const marketplaceStateManager = useMemo(() => new MarketplaceViewStateManager(), [])

View file

@ -4,6 +4,7 @@ import React from "react"
import { render, screen, act, cleanup } from "@/utils/test-utils"
import AppWithProviders from "../App"
import { vscode } from "@src/utils/vscode"
vi.mock("@src/utils/vscode", () => ({
vscode: {
@ -172,6 +173,68 @@ describe("App", () => {
})
})
it("auto-reloads hooks config every 5 seconds when hooks experiment is enabled", () => {
vi.useFakeTimers()
mockUseExtensionState.mockReturnValue({
didHydrateState: true,
showWelcome: false,
shouldShowAnnouncement: false,
experiments: { hooks: true },
language: "en",
telemetrySetting: "enabled",
})
const { unmount } = render(<AppWithProviders />)
// Initial render shouldn't trigger reload (it's triggered by effect interval)
expect(vscode.postMessage).not.toHaveBeenCalledWith({ type: "hooksReloadConfig" })
// Advance time by 5s
act(() => {
vi.advanceTimersByTime(5000)
})
expect(vscode.postMessage).toHaveBeenCalledWith({ type: "hooksReloadConfig" })
// Advance time another 5s
act(() => {
vi.advanceTimersByTime(5000)
})
expect(vscode.postMessage).toHaveBeenCalledTimes(3) // 1 initial (webviewDidLaunch) + 2 repeats
// Unmount and verify no more calls
unmount()
act(() => {
vi.advanceTimersByTime(5000)
})
expect(vscode.postMessage).toHaveBeenCalledTimes(3)
vi.useRealTimers()
})
it("does not auto-reload hooks config when hooks experiment is disabled", () => {
vi.useFakeTimers()
mockUseExtensionState.mockReturnValue({
didHydrateState: true,
showWelcome: false,
shouldShowAnnouncement: false,
experiments: { hooks: false },
language: "en",
telemetrySetting: "enabled",
})
render(<AppWithProviders />)
// Advance time by 5s
act(() => {
vi.advanceTimersByTime(5000)
})
expect(vscode.postMessage).not.toHaveBeenCalledWith({ type: "hooksReloadConfig" })
vi.useRealTimers()
})
afterEach(() => {
cleanup()
window.removeEventListener("message", () => {})

View file

@ -903,7 +903,7 @@
},
"HOOKS": {
"name": "Enable Hooks",
"description": "Use custom shell commands to automate actions before or after tool execution."
"description": "Use custom shell commands to automate actions before or after tool execution. (Restart required after saving settings)"
}
},
"promptCaching": {