fix(websearch): filter disabled legacy CLI probes and skip unused version fetching

Closes #1716
This commit is contained in:
Tam Nhu Tran committed 2026-08-25 15:35:54 -04:00
1 parent 65dc902299
commit f4911694e3
6 files changed
+267 -101

No files matched your search

+35 -23
View File
@@ -22,35 +22,47 @@ let agyCliCache: AgyCliStatus | null = null;
* *
* @returns Antigravity CLI status with path and version * @returns Antigravity CLI status with path and version
*/ */
export function getAgyCliStatus(): AgyCliStatus { export function getAgyCliStatus(options?: { fetchVersion?: boolean }): AgyCliStatus {
// Return cached result if available const fetchVersion = options?.fetchVersion !== false;
if (agyCliCache) {
if (
agyCliCache &&
(!fetchVersion || agyCliCache.version !== undefined || !agyCliCache.installed)
) {
if (!fetchVersion) {
return { ...agyCliCache, version: undefined };
}
return agyCliCache; return agyCliCache;
} }
const result: AgyCliStatus = { const result: AgyCliStatus = agyCliCache
installed: false, ? { ...agyCliCache }
path: undefined, : {
version: undefined, installed: false,
}; path: undefined,
version: undefined,
};
try { try {
const isWindows = process.platform === 'win32'; if (!agyCliCache) {
const whichCmd = isWindows ? 'where agy' : 'which agy'; const isWindows = process.platform === 'win32';
const whichCmd = isWindows ? 'where agy' : 'which agy';
const pathResult = execSync(whichCmd, { const pathResult = execSync(whichCmd, {
encoding: 'utf8', encoding: 'utf8',
timeout: 5000, timeout: 5000,
stdio: ['pipe', 'pipe', 'pipe'], stdio: ['pipe', 'pipe', 'pipe'],
}); });
const agyPath = pathResult.trim().split('\n')[0]; // First result on Windows const agyPath = pathResult.trim().split('\n')[0];
if (agyPath) { if (agyPath) {
result.installed = true; result.installed = true;
result.path = agyPath; result.path = agyPath;
}
}
// Try to get version if (result.installed && fetchVersion && result.version === undefined) {
try { try {
const versionResult = execSync('agy --version', { const versionResult = execSync('agy --version', {
encoding: 'utf8', encoding: 'utf8',
@@ -59,17 +71,17 @@ export function getAgyCliStatus(): AgyCliStatus {
}); });
result.version = versionResult.trim(); result.version = versionResult.trim();
} catch { } catch {
// Version check failed, but CLI is installed
result.version = 'unknown'; result.version = 'unknown';
} }
} else if (!fetchVersion) {
result.version = undefined;
} }
} catch { } catch {
// Command not found - Antigravity CLI not installed // Command not found - Antigravity CLI not installed
} }
// Cache result
agyCliCache = result; agyCliCache = result;
return result; return fetchVersion ? result : { ...result, version: undefined };
} }
/** /**
+35 -23
View File
@@ -23,35 +23,47 @@ let geminiCliCache: GeminiCliStatus | null = null;
* *
* @returns Gemini CLI status with path and version * @returns Gemini CLI status with path and version
*/ */
export function getGeminiCliStatus(): GeminiCliStatus { export function getGeminiCliStatus(options?: { fetchVersion?: boolean }): GeminiCliStatus {
// Return cached result if available const fetchVersion = options?.fetchVersion !== false;
if (geminiCliCache) {
if (
geminiCliCache &&
(!fetchVersion || geminiCliCache.version !== undefined || !geminiCliCache.installed)
) {
if (!fetchVersion) {
return { ...geminiCliCache, version: undefined };
}
return geminiCliCache; return geminiCliCache;
} }
const result: GeminiCliStatus = { const result: GeminiCliStatus = geminiCliCache
installed: false, ? { ...geminiCliCache }
path: undefined, : {
version: undefined, installed: false,
}; path: undefined,
version: undefined,
};
try { try {
const isWindows = process.platform === 'win32'; if (!geminiCliCache) {
const whichCmd = isWindows ? 'where gemini' : 'which gemini'; const isWindows = process.platform === 'win32';
const whichCmd = isWindows ? 'where gemini' : 'which gemini';
const pathResult = execSync(whichCmd, { const pathResult = execSync(whichCmd, {
encoding: 'utf8', encoding: 'utf8',
timeout: 5000, timeout: 5000,
stdio: ['pipe', 'pipe', 'pipe'], stdio: ['pipe', 'pipe', 'pipe'],
}); });
const geminiPath = pathResult.trim().split('\n')[0]; // First result on Windows const geminiPath = pathResult.trim().split('\n')[0];
if (geminiPath) { if (geminiPath) {
result.installed = true; result.installed = true;
result.path = geminiPath; result.path = geminiPath;
}
}
// Try to get version if (result.installed && fetchVersion && result.version === undefined) {
try { try {
const versionResult = execSync('gemini --version', { const versionResult = execSync('gemini --version', {
encoding: 'utf8', encoding: 'utf8',
@@ -60,17 +72,17 @@ export function getGeminiCliStatus(): GeminiCliStatus {
}); });
result.version = versionResult.trim(); result.version = versionResult.trim();
} catch { } catch {
// Version check failed, but CLI is installed
result.version = 'unknown'; result.version = 'unknown';
} }
} else if (!fetchVersion) {
result.version = undefined;
} }
} catch { } catch {
// Command not found - Gemini CLI not installed // Command not found - Gemini CLI not installed
} }
// Cache result
geminiCliCache = result; geminiCliCache = result;
return result; return fetchVersion ? result : { ...result, version: undefined };
} }
/** /**
+35 -23
View File
@@ -20,35 +20,47 @@ let grokCliCache: GrokCliStatus | null = null;
* *
* @returns Grok CLI status with path and version * @returns Grok CLI status with path and version
*/ */
export function getGrokCliStatus(): GrokCliStatus { export function getGrokCliStatus(options?: { fetchVersion?: boolean }): GrokCliStatus {
// Return cached result if available const fetchVersion = options?.fetchVersion !== false;
if (grokCliCache) {
if (
grokCliCache &&
(!fetchVersion || grokCliCache.version !== undefined || !grokCliCache.installed)
) {
if (!fetchVersion) {
return { ...grokCliCache, version: undefined };
}
return grokCliCache; return grokCliCache;
} }
const result: GrokCliStatus = { const result: GrokCliStatus = grokCliCache
installed: false, ? { ...grokCliCache }
path: undefined, : {
version: undefined, installed: false,
}; path: undefined,
version: undefined,
};
try { try {
const isWindows = process.platform === 'win32'; if (!grokCliCache) {
const whichCmd = isWindows ? 'where grok' : 'which grok'; const isWindows = process.platform === 'win32';
const whichCmd = isWindows ? 'where grok' : 'which grok';
const pathResult = execSync(whichCmd, { const pathResult = execSync(whichCmd, {
encoding: 'utf8', encoding: 'utf8',
timeout: 5000, timeout: 5000,
stdio: ['pipe', 'pipe', 'pipe'], stdio: ['pipe', 'pipe', 'pipe'],
}); });
const grokPath = pathResult.trim().split('\n')[0]; // First result on Windows const grokPath = pathResult.trim().split('\n')[0];
if (grokPath) { if (grokPath) {
result.installed = true; result.installed = true;
result.path = grokPath; result.path = grokPath;
}
}
// Try to get version if (result.installed && fetchVersion && result.version === undefined) {
try { try {
const versionResult = execSync('grok --version', { const versionResult = execSync('grok --version', {
encoding: 'utf8', encoding: 'utf8',
@@ -57,17 +69,17 @@ export function getGrokCliStatus(): GrokCliStatus {
}); });
result.version = versionResult.trim(); result.version = versionResult.trim();
} catch { } catch {
// Version check failed, but CLI is installed
result.version = 'unknown'; result.version = 'unknown';
} }
} else if (!fetchVersion) {
result.version = undefined;
} }
} catch { } catch {
// Command not found - Grok CLI not installed // Command not found - Grok CLI not installed
} }
// Cache result
grokCliCache = result; grokCliCache = result;
return result; return fetchVersion ? result : { ...result, version: undefined };
} }
/** /**
+35 -23
View File
@@ -20,35 +20,47 @@ let opencodeCliCache: OpenCodeCliStatus | null = null;
* *
* @returns OpenCode CLI status with path and version * @returns OpenCode CLI status with path and version
*/ */
export function getOpenCodeCliStatus(): OpenCodeCliStatus { export function getOpenCodeCliStatus(options?: { fetchVersion?: boolean }): OpenCodeCliStatus {
// Return cached result if available const fetchVersion = options?.fetchVersion !== false;
if (opencodeCliCache) {
if (
opencodeCliCache &&
(!fetchVersion || opencodeCliCache.version !== undefined || !opencodeCliCache.installed)
) {
if (!fetchVersion) {
return { ...opencodeCliCache, version: undefined };
}
return opencodeCliCache; return opencodeCliCache;
} }
const result: OpenCodeCliStatus = { const result: OpenCodeCliStatus = opencodeCliCache
installed: false, ? { ...opencodeCliCache }
path: undefined, : {
version: undefined, installed: false,
}; path: undefined,
version: undefined,
};
try { try {
const isWindows = process.platform === 'win32'; if (!opencodeCliCache) {
const whichCmd = isWindows ? 'where opencode' : 'which opencode'; const isWindows = process.platform === 'win32';
const whichCmd = isWindows ? 'where opencode' : 'which opencode';
const pathResult = execSync(whichCmd, { const pathResult = execSync(whichCmd, {
encoding: 'utf8', encoding: 'utf8',
timeout: 5000, timeout: 5000,
stdio: ['pipe', 'pipe', 'pipe'], stdio: ['pipe', 'pipe', 'pipe'],
}); });
const opencodePath = pathResult.trim().split('\n')[0]; // First result on Windows const opencodePath = pathResult.trim().split('\n')[0];
if (opencodePath) { if (opencodePath) {
result.installed = true; result.installed = true;
result.path = opencodePath; result.path = opencodePath;
}
}
// Try to get version if (result.installed && fetchVersion && result.version === undefined) {
try { try {
const versionResult = execSync('opencode --version', { const versionResult = execSync('opencode --version', {
encoding: 'utf8', encoding: 'utf8',
@@ -57,17 +69,17 @@ export function getOpenCodeCliStatus(): OpenCodeCliStatus {
}); });
result.version = versionResult.trim(); result.version = versionResult.trim();
} catch { } catch {
// Version check failed, but CLI is installed
result.version = 'unknown'; result.version = 'unknown';
} }
} else if (!fetchVersion) {
result.version = undefined;
} }
} catch { } catch {
// Command not found - OpenCode CLI not installed // Command not found - OpenCode CLI not installed
} }
// Cache result
opencodeCliCache = result; opencodeCliCache = result;
return result; return fetchVersion ? result : { ...result, version: undefined };
} }
/** /**
+20 -9
View File
@@ -113,13 +113,23 @@ function applyCooldownStatus(
}; };
} }
function getLegacyProviderStatuses(wsConfig: WebSearchConfigSnapshot): WebSearchCliInfo[] { function getLegacyProviderStatuses(
const agyStatus = getAgyCliStatus(); wsConfig: WebSearchConfigSnapshot,
const geminiStatus = getGeminiCliStatus(); options?: { includeVersions?: boolean }
const grokStatus = getGrokCliStatus(); ): WebSearchCliInfo[] {
const opencodeStatus = getOpenCodeCliStatus(); const fetchVersion = options?.includeVersions !== false;
const geminiAuthed = geminiStatus.installed && isGeminiAuthenticated(); const agyEnabled = wsConfig.providers?.agy?.enabled ?? false;
const geminiEnabled = wsConfig.providers?.gemini?.enabled ?? false;
const grokEnabled = wsConfig.providers?.grok?.enabled ?? false;
const opencodeEnabled = wsConfig.providers?.opencode?.enabled ?? false;
const agyStatus = agyEnabled ? getAgyCliStatus({ fetchVersion }) : { installed: false };
const geminiStatus = geminiEnabled ? getGeminiCliStatus({ fetchVersion }) : { installed: false };
const grokStatus = grokEnabled ? getGrokCliStatus({ fetchVersion }) : { installed: false };
const opencodeStatus = opencodeEnabled
? getOpenCodeCliStatus({ fetchVersion })
: { installed: false };
const geminiAuthed = geminiEnabled && geminiStatus.installed && isGeminiAuthenticated();
return [ return [
{ {
id: 'agy', id: 'agy',
@@ -198,7 +208,8 @@ function getLegacyProviderStatuses(wsConfig: WebSearchConfigSnapshot): WebSearch
* Get all WebSearch providers with their current status. * Get all WebSearch providers with their current status.
*/ */
export function getWebSearchCliProviders( export function getWebSearchCliProviders(
wsConfig: WebSearchConfigSnapshot = getWebSearchConfig() wsConfig: WebSearchConfigSnapshot = getWebSearchConfig(),
options?: { includeVersions?: boolean }
): WebSearchCliInfo[] { ): WebSearchCliInfo[] {
const apiKeyStates = getWebSearchApiKeyStates(); const apiKeyStates = getWebSearchApiKeyStates();
const cooldowns = readProviderCooldowns(); const cooldowns = readProviderCooldowns();
@@ -284,7 +295,7 @@ export function getWebSearchCliProviders(
}, },
]; ];
return [...providers, ...getLegacyProviderStatuses(wsConfig)].map((provider) => return [...providers, ...getLegacyProviderStatuses(wsConfig, options)].map((provider) =>
applyCooldownStatus(provider, cooldowns) applyCooldownStatus(provider, cooldowns)
); );
} }
@@ -359,7 +370,7 @@ export function buildWebSearchReadiness(
export function getWebSearchReadiness( export function getWebSearchReadiness(
wsConfig: WebSearchConfigSnapshot = getWebSearchConfig() wsConfig: WebSearchConfigSnapshot = getWebSearchConfig()
): WebSearchStatus { ): WebSearchStatus {
const providers = getWebSearchCliProviders(wsConfig); const providers = getWebSearchCliProviders(wsConfig, { includeVersions: false });
return buildWebSearchReadiness(wsConfig.enabled, providers); return buildWebSearchReadiness(wsConfig.enabled, providers);
} }
+107
View File
@@ -301,6 +301,113 @@ describe('websearch readiness', () => {
} }
}); });
it('does not invoke legacy CLI status probes when those providers are disabled', () => {
const getConfigSpy = spyOn(unifiedConfigLoader, 'getWebSearchConfig').mockReturnValue({
enabled: true,
providers: {
exa: { enabled: false, max_results: 5 },
tavily: { enabled: false, max_results: 5 },
brave: { enabled: false, max_results: 5 },
searxng: { enabled: false, url: '', max_results: 5 },
duckduckgo: { enabled: true, max_results: 5 },
agy: { enabled: false },
gemini: { enabled: false },
grok: { enabled: false },
opencode: { enabled: false },
},
} as any);
const apiKeySpy = spyOn(providerSecrets, 'getWebSearchApiKeyStates').mockReturnValue({
exa: { envVar: 'EXA_API_KEY', configured: false, available: false, source: 'none' },
tavily: { envVar: 'TAVILY_API_KEY', configured: false, available: false, source: 'none' },
brave: { envVar: 'BRAVE_API_KEY', configured: false, available: false, source: 'none' },
});
const agyStatusSpy = spyOn(agyCli, 'getAgyCliStatus').mockReturnValue({
installed: false,
} as any);
const geminiStatusSpy = spyOn(geminiCli, 'getGeminiCliStatus').mockReturnValue({
installed: false,
} as any);
const geminiAuthSpy = spyOn(geminiCli, 'isGeminiAuthenticated').mockReturnValue(false);
const grokStatusSpy = spyOn(grokCli, 'getGrokCliStatus').mockReturnValue({
installed: false,
} as any);
const opencodeStatusSpy = spyOn(opencodeCli, 'getOpenCodeCliStatus').mockReturnValue({
installed: false,
} as any);
try {
getWebSearchCliProviders();
expect(agyStatusSpy).not.toHaveBeenCalled();
expect(geminiStatusSpy).not.toHaveBeenCalled();
expect(geminiAuthSpy).not.toHaveBeenCalled();
expect(grokStatusSpy).not.toHaveBeenCalled();
expect(opencodeStatusSpy).not.toHaveBeenCalled();
} finally {
getConfigSpy.mockRestore();
apiKeySpy.mockRestore();
agyStatusSpy.mockRestore();
geminiStatusSpy.mockRestore();
geminiAuthSpy.mockRestore();
grokStatusSpy.mockRestore();
opencodeStatusSpy.mockRestore();
}
});
it('does not spawn --version when includeVersions is false', () => {
const wsConfig = {
enabled: true,
providers: {
exa: { enabled: false, max_results: 5 },
tavily: { enabled: false, max_results: 5 },
brave: { enabled: false, max_results: 5 },
searxng: { enabled: false, url: '', max_results: 5 },
duckduckgo: { enabled: false, max_results: 5 },
agy: { enabled: true, model: 'gemini-2.5-flash', timeout: 90 },
gemini: { enabled: true },
grok: { enabled: true },
opencode: { enabled: true },
},
};
const apiKeySpy = spyOn(providerSecrets, 'getWebSearchApiKeyStates').mockReturnValue({
exa: { envVar: 'EXA_API_KEY', configured: false, available: false, source: 'none' },
tavily: { envVar: 'TAVILY_API_KEY', configured: false, available: false, source: 'none' },
brave: { envVar: 'BRAVE_API_KEY', configured: false, available: false, source: 'none' },
});
const agyStatusSpy = spyOn(agyCli, 'getAgyCliStatus').mockReturnValue({
installed: true,
version: undefined,
});
const geminiStatusSpy = spyOn(geminiCli, 'getGeminiCliStatus').mockReturnValue({
installed: false,
version: undefined,
});
const geminiAuthSpy = spyOn(geminiCli, 'isGeminiAuthenticated').mockReturnValue(false);
const grokStatusSpy = spyOn(grokCli, 'getGrokCliStatus').mockReturnValue({
installed: false,
version: undefined,
});
const opencodeStatusSpy = spyOn(opencodeCli, 'getOpenCodeCliStatus').mockReturnValue({
installed: false,
version: undefined,
});
try {
getWebSearchCliProviders(wsConfig as Parameters<typeof getWebSearchCliProviders>[0], {
includeVersions: false,
});
expect(agyStatusSpy).toHaveBeenCalledWith({ fetchVersion: false });
expect(geminiStatusSpy).toHaveBeenCalledWith({ fetchVersion: false });
expect(grokStatusSpy).toHaveBeenCalledWith({ fetchVersion: false });
expect(opencodeStatusSpy).toHaveBeenCalledWith({ fetchVersion: false });
} finally {
apiKeySpy.mockRestore();
agyStatusSpy.mockRestore();
geminiStatusSpy.mockRestore();
geminiAuthSpy.mockRestore();
grokStatusSpy.mockRestore();
opencodeStatusSpy.mockRestore();
}
});
it('treats cooled-down providers as temporarily unavailable in readiness status', () => { it('treats cooled-down providers as temporarily unavailable in readiness status', () => {
const tempHome = mkdtempSync(join(tmpdir(), 'websearch-status-cooldown-')); const tempHome = mkdtempSync(join(tmpdir(), 'websearch-status-cooldown-'));
const statePath = join(tempHome, '.ccs', 'cache', 'websearch-provider-state.json'); const statePath = join(tempHome, '.ccs', 'cache', 'websearch-provider-state.json');