Skip to content

Spec: full provider/model-picker support, progress UX, and config persistence #34

Closed

Description

@Mrbaeksang

Problem

DeepCloak's provider layer has two broken mappings and no model discovery:

  1. gemini is broken end-to-end. config.py maps our gemini → LDR "gemini", but LDR 1.6.11's VALID_PROVIDERS only contains "google" (normalize_provider just lowercases), so get_llm() raises ValueError: Invalid provider. We also write llm.gemini.api_key while LDR's GoogleProvider reads llm.google.api_key.
  2. openrouter credentials never arrive. We map openrouter → "openai_endpoint" but write the key to llm.openrouter.api_key; LDR's openai_endpoint path reads llm.openai_endpoint.api_key (unset → placeholder key) → 401 against OpenRouter. LDR 1.6.11 ships a native openrouter provider (api_key_setting = "llm.openrouter.api_key", base URL already OpenRouter) — the workaround is pointless.
  3. No model picker. --model is a free string; there is no way to list models; defaults are hardcoded in three parallel tables (_PROVIDER_ENV, _DEFAULT_MODEL, _LDR_PROVIDER) that must be edited together.
  4. Progress is Evidence-events-only. LDR's research functions accept a progress_callback: Callable[[str, int, dict], None]; we never pass one, so the CLI shows nothing about research phases.
  5. Silent degradation hides the product's core value. Three bare except Exception: pass blocks in research_core.py mean a failed settings-snapshot or shim install quietly drops search.snippets_only=False / Stealth Fetch — the run "succeeds" without ever Bypassing a wall.
  6. MCP surface ignores model choice (tools take depth only) and _RUNS grows unbounded.
  7. Settings are re-typed every run. Only DEEPCLOAK_MODEL exists; no config file.

Decisions

  • Fix mappings first using LDR's native providers: gemini → llm.provider=google, llm.google.api_key; openrouter → llm.provider=openrouter, keep llm.openrouter.api_key.
  • New deep module providers.py: one registry (env var, keyless flag, default model, LDR provider + api-key setting per provider). It also owns model listing via each provider's public HTTP API (OpenRouter/OpenAI/LM Studio/llama.cpp/vLLM /v1/models-style, Gemini v1beta/models?key=, Ollama /api/tags). This deliberately does not touch any new LDR internals — ADR-0001's seam stays _fetch_html only.
  • CLI: deepcloak models [--provider X] [--base-url U] prints sorted model ids (one per line, pipe-friendly).
  • Progress: wire progress_callback through research_core._run_ldr into progress.py phase lines on stderr; feature-detect the parameter instead of assuming every depth supports it.
  • MCP: deep_research/quick_summary gain optional provider/model; new list_models tool; cap stored runs (keep last).
  • Fail loudly-ish: replace quiet except Exception: pass with a one-line stderr warning (verbose) so degraded Stealth Fetch is visible; behavior otherwise unchanged.
  • --json output mode: one JSON object (query, report, evidence, resolved settings minus secrets) to stdout for scripting/piping.
  • Config file: read ~/.config/deepcloak/config.toml (override: DEEPCLOAK_CONFIG). Precedence: CLI flag > env > file > default.

Constraints

  • ADR-0001 holds: no new internal-LDR symbols; LDR pin stays ==.
  • Pure modules stay pure: providers.py/config.py do I/O only at the edges (listing functions, file loader), keeping them trivially testable.
  • Domain vocabulary per CONTEXT.md (Bot Wall, Stealth Fetch, Escalation, Bypass, Evidence Record).

Non-goals (backlog, tracked separately)

Interactive TUI picker, rich spinners, run history, cost display, retriever parallelization.

Activity

  1. Mrbaeksang commented on Aug 22, 2026

    @Mrbaeksang
    OwnerAuthor

    Implemented in full — tickets #35–#43 closed. Suite: 100 passed, 1 skipped (MCP runtime optional), ruff clean. Backlog polish items moved to #44 (needs-triage). Not committed yet — awaiting maintainer review.

  2. added 2 commits that reference this issue on Aug 22, 2026
  3. Mrbaeksang commented on Aug 22, 2026

    @Mrbaeksang
    OwnerAuthor

    Shipped in #45 (merged to main as 5cbb4e2). Tickets #35–#43 all closed; remaining polish candidates live in #44.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions