diff --git a/tools/talent-scout/src/api/controlpanel-controller.ts b/tools/talent-scout/src/api/controlpanel-controller.ts index 6c16fbab0..664b5ca38 100644 --- a/tools/talent-scout/src/api/controlpanel-controller.ts +++ b/tools/talent-scout/src/api/controlpanel-controller.ts @@ -20,6 +20,22 @@ import { registerRateRoutes } from './rate-controller'; import type { ControlPanelDeps } from './controlpanel-deps'; +// ============================================================================ +// Helpers +// ============================================================================ + +/** Quick health probe for externally-managed services. */ +async function probeHealth(port: number): Promise { + try { + const res = await fetch(`http://127.0.0.1:${port}/health`, { + signal: AbortSignal.timeout(2000), + }); + return res.ok; + } catch { + return false; + } +} + // ============================================================================ // Router Factory // ============================================================================ @@ -82,9 +98,25 @@ export function createControlPanelRouter(deps: ControlPanelDeps): Router { : 'inactive' as const; // Derive captcha solver status - const captchaStatus = captchaSolverManager - ? captchaSolverManager.getStatus() - : 'not_configured' as const; + // When EXTERNAL_WORKERS is set, the managers don't spawn processes themselves, + // so getStatus() returns 'inactive'. Probe the health endpoint directly instead. + let captchaStatus: 'active' | 'inactive' | 'not_configured' | 'error' | 'starting' | 'connected' | 'disconnected' | 'paused'; + let llmStatus: 'active' | 'inactive' | 'not_configured' | 'error' | 'starting' | 'connected' | 'disconnected' | 'paused'; + + if (process.env.EXTERNAL_WORKERS) { + const captchaPort = Number(process.env.CAPTCHA_PORT) || 3099; + const llmPort = Number(process.env.LLM_PORT) || 8100; + + captchaStatus = await probeHealth(captchaPort) ? 'active' : 'inactive'; + llmStatus = await probeHealth(llmPort) ? 'active' : 'inactive'; + } else { + captchaStatus = captchaSolverManager + ? captchaSolverManager.getStatus() + : 'not_configured'; + llmStatus = llmServiceManager + ? llmServiceManager.getStatus() + : 'not_configured'; + } // Derive tor status const torSnapshot = torMonitor?.getSnapshot(); @@ -116,9 +148,7 @@ export function createControlPanelRouter(deps: ControlPanelDeps): Router { processingWorker: { status: procWorkerStatus, requires: ['redis'] }, captchaSolver: { status: captchaStatus, requires: [] }, llmService: { - status: llmServiceManager - ? llmServiceManager.getStatus() - : 'not_configured' as const, + status: llmStatus, requires: [], poolMode: llmServiceManager?.isPoolMode() ?? false, pool: llmServiceManager ? llmServiceManager.getPoolStatus() : null,