diff --git a/src/renderer/src/components/sidebar/LinearAgentSkillSetupPrompt.test.tsx b/src/renderer/src/components/sidebar/LinearAgentSkillSetupPrompt.test.tsx index cef69177f0f..9ed0ccf3263 100644 --- a/src/renderer/src/components/sidebar/LinearAgentSkillSetupPrompt.test.tsx +++ b/src/renderer/src/components/sidebar/LinearAgentSkillSetupPrompt.test.tsx @@ -682,6 +682,45 @@ describe('LinearAgentSkillSetupPrompt', () => { expect(document.body.textContent).not.toContain('Linear ticket access is ready') }) + it('accepts same-context prerequisite CLI status callbacks after a newer Re-check', async () => { + let reportHostCliStatus: ((status: CliInstallStatus) => void) | null = null + let resolveEnsureCli: () => void = () => {} + mocks.ensureCli.mockImplementationOnce( + async (options?: { onStatusChange?: (status: CliInstallStatus) => void }) => { + reportHostCliStatus = options?.onStatusChange ?? null + await new Promise((resolve) => { + resolveEnsureCli = resolve + }) + return null + } + ) + await renderPrompt({ linked: true, remote: false, surface: 'modal' }) + + await act(async () => { + findBodyButton('Mock install')?.dispatchEvent(new MouseEvent('click', { bubbles: true })) + }) + + mocks.getCliStatus.mockResolvedValue( + cliStatus({ state: 'not_installed', pathConfigured: false }) + ) + await act(async () => { + findBodyButton('Re-check')?.dispatchEvent(new MouseEvent('click', { bubbles: true })) + }) + await settleRender() + + await act(async () => { + reportHostCliStatus?.(cliStatus({})) + resolveEnsureCli() + }) + await settleRender() + + expect(document.body.textContent).toContain( + 'Enable agents to read and edit the attached Linear ticket.' + ) + expect(document.body.textContent).toContain('Linear agent skill is missing.') + expect(document.body.textContent).not.toContain('Orca CLI is missing.') + }) + it('ignores older same-context CLI refreshes that finish after a newer Re-check', async () => { const rendered = await renderPrompt({ linked: true, remote: false }) const recheckButton = Array.from(rendered.querySelectorAll('button')).find( diff --git a/src/renderer/src/components/sidebar/LinearAgentSkillSetupPrompt.tsx b/src/renderer/src/components/sidebar/LinearAgentSkillSetupPrompt.tsx index 8884ad87c8c..a330acb4587 100644 --- a/src/renderer/src/components/sidebar/LinearAgentSkillSetupPrompt.tsx +++ b/src/renderer/src/components/sidebar/LinearAgentSkillSetupPrompt.tsx @@ -134,6 +134,12 @@ export function LinearAgentSkillSetupPrompt({ [] ) + const writeCliStatusForIdentity = useCallback((requestIdentity: string, write: () => void) => { + if (currentSetupCheckIdentityRef.current === requestIdentity) { + write() + } + }, []) + const refreshCliStatus = useCallback(async (): Promise => { const requestIdentity = setupCheckIdentity const requestGeneration = ++cliRefreshGenerationRef.current @@ -280,9 +286,8 @@ export function LinearAgentSkillSetupPrompt({ } onBeforeOpenTerminal={async () => { const requestIdentity = setupCheckIdentity - const requestGeneration = ++cliRefreshGenerationRef.current const writeIfCurrent = (write: () => void): void => { - writeCliStatusIfCurrent(requestIdentity, requestGeneration, write) + writeCliStatusForIdentity(requestIdentity, write) } const nextStatus = agentRuntime.runtime === 'wsl'