import { type EngineHealthEntry } from '../search/core/engine-health.js'; import type { EngineEntry } from '../search/core/engine-base.js'; import { type LocalModelTier } from '../integrations/cloud/llm/local-tier.js'; /** * Mask an API key for display in doctor output. * Shows at most 8 characters (or 25% of the key length) then asterisks. * Never returns the full key value. */ export declare function maskApiKey(value: string): string; /** * Format provider/key-location/masked-value lines for doctor output. * Returns one or more display lines. Key value is ALWAYS masked. */ export declare function formatProviderDoctorLines(provider: string, location: 'keychain' | 'file' | 'env', keyValue: string): string[]; /** * Format the engine-health summary for doctor output. Pure so the lines can * be asserted from tests without spinning up the whole CLI. Returns one * string per line (no trailing newlines). Adds per-engine * status visibility for the cold-start health check. * * ok → " bing general ok" * needs-key → " github-code code needs-key (set WIGOLO_GITHUB_TOKEN ...)" * disabled → " brave general disabled (set BRAVE_API_KEY ...)" * * Sorted by vertical then engine name so the same registry produces the * same output every run. */ export declare function formatEngineHealthLines(entries: EngineHealthEntry[]): string[]; /** * Live per-engine probe behind `doctor --probe-engines`. Dedupes * the registered entries by engine name, skips parked (disabled) adapters, * and runs one bounded query per engine SEQUENTIALLY — politeness beats * speed for a diagnostic that hits 15+ third-party services. No-op when * the flag is off so the default doctor stays network-free. */ export declare function runEngineProbeSection(probeEngines: boolean, entries: EngineEntry[], print?: (line: string) => void): Promise; /** * Build the `tls_tier` doctor line. Pure so it stays unit-testable. * * WIGOLO_TLS_TIER=off → `off (default)` * WIGOLO_TLS_TIER=auto → `auto (chrome_142, wreq-js ✓)` when wreq-js loaded * `auto (wreq-js missing — fallback only)` when not * WIGOLO_TLS_TIER=on → `on (chrome_142, wreq-js ✓)` etc. */ export declare function formatTlsTierLine(mode: 'off' | 'auto' | 'on', browser: string, wreqAvailable: boolean): string; /** * Build the Ollama (local LLM server) diagnostic lines for doctor. Pure so the * branching can be asserted without a live server. * * - ollama is the active provider → show resolved base URL + model (always, * even when the server is mid-run unreachable — runtime falls back * gracefully, doctor should still report what's configured). * - no LLM configured AND a local server is reachable → emit an enable-hint. * - otherwise → no lines (don't nag a user who already configured an LLM, and * stay silent when no local server is present). * * The hint NEVER auto-enables anything; it only tells the user the lever exists. */ /** * Strip control / ANSI bytes from an untrusted string before printing it to the * terminal. A compromised localhost server could return an ANSI-laden model * name; rendering it verbatim is a terminal-injection vector. Security LOW. */ export declare function sanitizeForTerminal(value: string): string; /** * Resolve the active-ollama model for display, bounded by a short timeout so a * stalled (connection-accepted-then-silent) server can never hang doctor. When * the pick times out / fails, returns undefined and doctor degrades gracefully * (the active section still prints the base URL). `pick` is injected for tests. */ export declare function resolveOllamaModelBounded(baseUrl: string, pick?: (url: string, fetchImpl: typeof fetch, signal: AbortSignal) => Promise, timeoutMs?: number): Promise; export declare function buildOllamaDoctorLines(state: { llmConfigured: boolean; ollamaActive: boolean; reachable: boolean; baseUrl: string; model?: string; }): string[]; /** * Build the opt-in local-model tier (`WIGOLO_LOCAL_LLM`) diagnostic lines. Pure * so the branching is asserted without a live server. Component names (local * model server / model name) are allowed in doctor output. * * - off → state the flag is off (default) so the lever stays * discoverable; no endpoint is implied. * - auto + reachable → resolved endpoint + model + "reachable". * - auto + unreachable → "enabled, no local model detected" so an * enabled-but-absent server is visible, not hidden. */ export declare function buildLocalTierDoctorLines(state: { localLlm: string; tier: LocalModelTier | null; }): string[]; /** * Exit code contract: * - 0 when all required components OK, or only optional packages (content extractor/ML reranker) missing. * - 1 when any required component is degraded: Python missing, browser missing, * search engine bootstrap failed/no_runtime, or search engine process supposed to be up but isn't. */ export interface DoctorOptions { /** Run a live search probe against every registered engine. */ probeEngines?: boolean; /** Attempt an automatic repair for every failed check with a known fix. */ fix?: boolean; /** Emit a machine-readable JSON report on stdout (logs still go to stderr). */ json?: boolean; } /** One diagnosable component in the doctor report. `fixable` marks checks that * `--fix` knows how to repair. */ export interface DoctorCheck { name: string; status: 'ok' | 'failed' | 'skipped'; fixable: boolean; detail?: string; } /** Before/after record for one repair `--fix` attempted. */ export interface DoctorFix { name: string; action: string; before: 'ok' | 'failed' | 'skipped'; after: 'ok' | 'failed' | 'skipped'; ok: boolean; error?: string; } /** The machine-readable doctor report emitted under `--json`. */ export interface DoctorReport { status: 'ok' | 'degraded'; exitCode: number; /** Running package version — for cross-channel support triage. */ version: string; /** How wigolo was installed: `binary` (packaged executable) or `npm-or-source`. */ install_channel: 'binary' | 'npm-or-source'; checks: DoctorCheck[]; fixes: DoctorFix[]; } /** * Collect the checks `--fix` knows how to repair. Each returns `ok`/`failed` * with a fixable flag. Pure snapshots — no side effects — so they can be run * before AND after a repair to build the before/after record. * * Exported as the shared cold-check surface: `init` reuses it after a full * warmup to append a doctor summary (component presence, browser installed, * data-dir writable, breakers) WITHOUT a live network verify. Every check here * is presence/snapshot-only — none downloads a model or spawns a browser — so * it is safe to run on a `--no-warmup` init too (writes zero bytes). */ export declare function runDoctorColdChecks(dataDir: string): Promise; export declare function runDoctor(dataDir: string, opts?: DoctorOptions): Promise; export declare function isPostExitNativeNoise(line: string): boolean; /** * Doctor isolation wrapper. * * `runDoctor` loads the embedding model (onnxruntime-node) to verify it * works. Onnxruntime owns a global thread pool that races libc++ during * static-destructor teardown on macOS, surfacing as * `mutex lock failed: Invalid argument` and a SIGABRT (exit 134) AFTER the * diagnostic output has already been written. The crash is unrecoverable * from JS — `session.release()`, `process.reallyExit`, and the SIGABRT * handler all run too early; the abort fires during C++ global dtors when * the JS VM is gone. * * Fix: run doctor in a child process. The child inherits stdio so the user * sees identical output, runs the diagnostic, writes its intended exit code * to a sentinel file, then exits. The parent never loads onnxruntime so its * own exit is clean. If the child crashes with SIGABRT (134) after the * sentinel was written, we know the diagnostic completed and we use the * sentinel code. Any other crash propagates as a real failure. */ export declare function runDoctorIsolated(dataDir: string, opts?: DoctorOptions): Promise; export declare function runDoctorAsChild(dataDir: string, opts?: DoctorOptions): Promise; //# sourceMappingURL=doctor.d.ts.map