Skip to content

feat: deepdive doctor — aggregated health report#4

Merged
askalf merged 1 commit into
masterfrom
feat/doctor
Apr 23, 2026
Merged

feat: deepdive doctor — aggregated health report#4
askalf merged 1 commit into
masterfrom
feat/doctor

Conversation

@askalf

@askalf askalf commented Apr 23, 2026

Copy link
Copy Markdown
Owner

Summary

Adds deepdive doctor — one command, one paste-able health report across every subsystem. Mirrors dario's doctor philosophy: the user's supposed to paste the output when filing an issue, and we surface everything that could be wrong in one place.

Output

13 checks by default, five categories, OK/WARN/FAIL/INFO badges:

deepdive doctor — v0.3.0

# environment
  OK  Node        v22.21.1
  --- Platform    win32 x64
  --- deepdive    v0.3.0

# cache
  --- dir         ~/.deepdive/cache
  OK  writable    yes
  --- entries     42 files · 18.3 MB

# llm
  --- base URL    http://localhost:3456
  --- model       claude-sonnet-4-6
  OK  reachable   200 in 142ms
  OK  probe       max_tokens=1 · in=3 out=1

# search
  --- adapter     duckduckgo
  OK  probe       4 results in 380ms

# browser
  OK  playwright  module loaded
  OK  chromium    launch + close in 244ms

Summary: 13 checks · 8 ok · 0 warn · 0 fail

--json for structured output. Exit code 1 on any fail (warnings alone don't fail).

New exports (library API)

  • runDoctor, renderDoctorText, renderDoctorJson, exitCodeFor
  • Pure helpers: scrubPath, formatBytes, formatDuration, classifyFetchError, nodeMeetsMinimum
  • Types: CheckResult, CheckStatus, DoctorReport, DoctorOptions

DoctorOptions has skipLLM/skipSearch/skipBrowser/skipCache switches and fetchImpl/now injection points for tests.

Probe cost

  • LLM: one max_tokens=1 request per run (few tokens, essentially free on subscription billing)
  • Search: one request to the configured adapter with query "hello world"
  • Browser: Chromium launch + immediate close (~250ms)
  • Cache: readdir + stat only

Nothing persists across the run.

Test plan

  • npm run build — clean under strict: true
  • npm test — 134 pass (up from 116), 0 fail
  • 18 new assertions: pure helpers (scrubPath, formatBytes, formatDuration, classifyFetchError, nodeMeetsMinimum), rendering round-trips, and mock-HTTP-server integration tests for the healthy / 500 / non-Anthropic-shape LLM paths + cache-dir inspection with mixed file types
  • Manual run against local dario: 13 checks, all green, 4.1s

One command, one paste-able report. Mirrors dario's doctor philosophy:
every subsystem deepdive depends on (Node, the LLM endpoint, the search
adapter, Playwright + Chromium, the cache dir) gets probed; anything
unhealthy is visible without chasing error messages across three
separate commands. Exit code 1 on any fail, 0 otherwise.

13 checks by default, grouped into five categories:

  # environment — Node version, platform, deepdive version
  # cache       — dir, writable, file count, total bytes, oldest entry
  # llm         — base URL, model, reachability (max_tokens=1 probe),
                  response-shape validation
  # search      — configured adapter, live probe against "hello world"
  # browser     — playwright module, chromium launch + close

Text output is the default (sectioned with # headers, color when TTY).
`--json` emits the same structured report for piping.

Sub-subsystems can be skipped via DoctorOptions for tests (`skipLLM`,
`skipSearch`, `skipBrowser`, `skipCache`). `fetchImpl` and `now` are
injectable hooks.

New exports on the public API: runDoctor, renderDoctorText,
renderDoctorJson, exitCodeFor, plus pure helpers scrubPath (home-dir +
backslash scrubber used throughout so error messages don't leak paths),
formatBytes, formatDuration, classifyFetchError (ECONNREFUSED /
ENOTFOUND / timeout / TLS / fallback), nodeMeetsMinimum.

Tests: 18 assertions (134 total, up from 116). Pure-helper coverage,
rendering round-trips, and mock-HTTP-server integration tests
covering the healthy LLM, 500, and non-Anthropic-shape paths plus
cache-dir inspection with mixed file types.

The CLI now dispatches on `deepdive doctor` as a subcommand; `--json`
selects structured output, `--help` still documents everything. USAGE
banner updated to show both paths.
@askalf askalf enabled auto-merge (squash) April 23, 2026 01:01
Comment thread src/doctor.ts
detail: model,
});

const url = `${baseUrl.replace(/\/+$/, "")}/v1/messages`;
@askalf askalf merged commit 01506bf into master Apr 23, 2026
3 of 4 checks passed
@askalf askalf deleted the feat/doctor branch April 23, 2026 01:02
askalf added a commit that referenced this pull request Apr 23, 2026
)

CodeQL flagged `baseUrl.replace(/\/+$/, "")` in doctor.ts as polynomial-
ReDoS after PR #4 landed doctor.ts. Same class as the original 7 fixed
in #3; the regex is actually benign (no nested repetition) but using
the shared trimTrailingSlashes helper from url-util.ts keeps the
pattern consistent and CodeQL's query clean.

Co-authored-by: askalf <263217947+askalf@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants