Add make doctor + secure dashboard bind under Tailscale + install UX fixes - #213
Draft
david-hummingbot wants to merge 8 commits into
Draft
Add make doctor + secure dashboard bind under Tailscale + install UX fixes#213david-hummingbot wants to merge 8 commits into
david-hummingbot wants to merge 8 commits into
Conversation
Open
7 tasks
david-hummingbot
added a commit
that referenced
this pull request
Aug 21, 2026
Resolves PR #213's conflict with main (339 files changed there since this branch diverged -- telemetry, DEX trading UI, and a large batch of new tests, among others). main.py and utils/config.py merged cleanly on their own; the only real conflict was uv.lock, which was regenerated fresh against the merged pyproject.toml with `uv lock` rather than hand-resolved (pyproject.toml itself merged without conflict -- both sides already agreed on hummingbot-api-client==1.5.7). Verified post-merge: full pytest suite (2268 passed, same one pre-existing unrelated failure -- a stale local `assistants/` dir check -- as before this branch touched anything), and this branch's own additions (condor/doctor.py, condor/setup_llm.py's bridge auto-install, USE_TAILSCALE wiring in main.py/utils/config.py) all still import and run correctly.
…fixes - condor/doctor.py: verifies dependencies, .env/config.yml, AI model readiness, dashboard port exposure, and Hummingbot API connectivity — wired into `make install` and available standalone via `make doctor`. - main.py/utils/tailscale.py: bind the web dashboard to 127.0.0.1 (with a `tailscale serve` proxy) instead of 0.0.0.0 when USE_TAILSCALE is set, matching the pattern hummingbot-api's Gateway already uses. - setup-environment.sh: Step 2 no longer pays the uv sync cost before the user can skip picking a model, and shows a cost estimate when they don't; Step 6's stale "Next steps" copy now describes what `make install` actually still does. - uv.lock: resync to the hummingbot-api-client==1.5.7 pin already declared in pyproject.toml (lockfile had drifted out of sync). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…ntil model choice
- Makefile: doctor target now sources ~/.nvm/nvm.sh before running
condor.doctor, matching the pattern install/build-frontend already use.
Without it, shutil.which("node"/"npm"/"tsc") and the AI-model readiness
probe (which shells out to `npm root -g`) cannot see nvm-installed
Node, so `make doctor` -- including the non-fatal check at the end of
`make install` -- reported node/npm/typescript as missing and the AI
model as not installed right after a clean install that actually
succeeded.
- setup-environment.sh: move the global
`npm install -g @agentclientprotocol/claude-agent-acp` install out of
Step 0 (Dependencies), which ran it unconditionally before the user had
picked a model, into a new step right after Step 2 (AI Model). It now
only runs if the resolved default agent actually uses the
claude-agent-acp bridge -- checked via the same
condor.setup_llm.current_default/base_of + condor.acp.client.ACP_COMMANDS
mapping the bot itself uses at runtime, so it can never disagree with
what will actually run. Users who pick Codex/Gemini/Copilot/etc. (or an
Ollama/custom model) no longer get an unused global npm package
installed on their machine.
Verified in a clean container: `make install` -> `make doctor` now shows
node/npm/tsc detected and the AI model correctly read as installed; full
pytest suite (1410 passed, 6 skipped) still green.
…sconnect Two related install-flow fixes: - condor/setup_llm.py: selecting a model whose CLI bridge isn't installed (e.g. Gemini CLI, GitHub Copilot CLI) used to just say "isn't ready" and reprompt, leaving the user to go run `npm install -g ...` themselves and come back. It now runs that install command right there (reusing readiness.install_command against ACP_COMMANDS, so it can never disagree with what the menu row displays), streams real npm output, re-probes, and proceeds with the pick on success -- or reprompts with a clear failure reason otherwise. main() applies the same check to the final effective default even when the picker is skipped, so a fresh install's recommended claude-agent-acp default still gets installed -- but never for `--status`/ non-tty, which promises to change nothing. - setup-environment.sh: this made the separate "Install Claude ACP (only if the chosen model needs it)" block (from the nvm/ACP-defer patch) redundant and worse, the actual source of the reported disconnect -- a user would answer "pick a model now?", watch the Python env sync, pick a model, get a completion report from setup_llm.py, and then get bounced into a second, unlabeled install pass for a check the picker itself now already covers more generally (any bridge, not just Claude's). Removed it: the Python env sync (before the menu appears) and the picked model's install (inline, the moment it's chosen) now happen as one continuous flow in a single process, with nothing tacked on afterward. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…e of it uv's own venv-creation/install output (Using CPython..., Creating virtual environment, the wheels progress bar, Installed N packages...) was showing up sandwiched between "Pick an AI model now? [Y/n]" and the actual "Which AI model should Condor use" menu -- both python invocations of the same step, so it read as the prompt getting interrupted mid-conversation rather than as one continuous flow. Moved the sync (`uv run python -c "pass"`, same lockfile-driven sync `uv run python -m condor.setup_llm` would trigger anyway) to the top of Step 2, before the Y/n question, and made it unconditional -- both branches below need the venv warm regardless (picking a model runs the wizard directly, skipping still needs `--status` for the no-tty fallback). Verified: the picker invocation immediately after the warm-up produces zero sync output, going straight to the menu. Trade-off: this reintroduces the sync cost on a straight "skip" (previously made instant by gating the sync behind the Y/n itself) -- accepted in favor of removing the disconnect, since in the common path (`make install`) the sync happens moments later regardless via `uv sync --dev`; the instant-skip win only mattered for a standalone `make setup` rerun. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…oise - condor/doctor.py: check_hummingbot_api() called cm.get_client(name) and discarded the result. get_client() is written for the long-running bot process, which keeps the client (and its aiohttp session) cached for reuse -- but doctor is a one-shot script that exits right after the check, so nothing ever closed that session. aiohttp then printed an "Unclosed client session" / "Unclosed connector" warning on interpreter shutdown, which read like a real error even though the check itself passed. Added _probe_and_close() to close the client the moment the check is done. - condor/doctor.py: the report was plain monochrome text. Added color (green/yellow/red badges + bold section headers) matching the palette setup-environment.sh already uses elsewhere in the install flow, gated on sys.stdout.isatty() and NO_COLOR so piped/CI output stays plain. - Makefile: set MAKEFLAGS += --no-print-directory so the recursive $(MAKE) doctor call inside install doesn't print an "Entering/Leaving directory" line around it. Verified: full pytest suite (1417 passed, 6 skipped) green; make doctor piped shows no escape codes and no more aiohttp warnings; under a real tty the report renders in color. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Bordered header/footer matching setup-environment.sh's own banner width (46 chars) and bold style, so the two read as one design when make install runs them back to back. Each section gets a header + a light divider instead of just a trailing colon, check details are dimmed so the glyph+name lead the eye, and the closing line is now a real tally (✓ passed / ! warnings / ✗ failed counts, always all three) with the footer border itself colored red/yellow/green by the worst outcome. Also adds tests/test_doctor.py -- this file had zero coverage before. Covers the new _tally() (counts + exit code) and the two existing pure classifiers (_is_public_bind, _connection_hint) it was easy to pick up alongside the rendering work. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
main moved the LLM-provider readiness/options/openrouter modules from handlers.agents.* into condor.llm.* (ARCH-190) while this branch was in flight, with compat shims keeping the old import paths working. The rebase onto main already picked up the new paths in condor/setup_llm.py's own imports (clean 3-way merge); this finishes the job in the few spots that still pointed at the old names by prose or by import, since new code is meant to use the new homes: - condor/doctor.py: import the readiness module from condor.llm directly instead of through the handlers.agents shim. - condor/setup_llm.py: two docstring references (_default_agent(), install_command()) still named the pre-move module paths. - tests/test_setup_llm.py: import AGENT_OPTIONS/readiness/openrouter_models from condor.llm.* instead of handlers.agents.*. - main.py: _web_server_config()'s docstring only mentioned local mode as a reason WEB_HOST binds loopback; added Tailscale, the other reason this branch introduced. No behavior change -- the shims meant all of this already worked; this is purely pointing at the modules' real, current homes. Full pytest suite still 2478 passed (same one pre-existing unrelated failure as before this branch touched anything).
david-hummingbot
force-pushed
the
feature/doctor-command-install-ux
branch
from
August 21, 2026 17:17
c67f22c to
847263b
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
make doctor(condor/doctor.py): checks dependencies (uv/tmux/node/npm/tsc),.env/config.ymlsanity, AI model readiness, whether the web dashboard port is exposed on all interfaces vs. loopback, and connectivity+auth to every Hummingbot API server inconfig.yml. Non-zero exit on real failures; wired intomake installas a non-fatal final step.0.0.0.0under Tailscale: whenUSE_TAILSCALE=true, the dashboard binds127.0.0.1and confirms atailscale serveproxy (utils/tailscale.py), mirroring the pattern hummingbot-api's own Gateway/dev-mode already use. Fails loud (logs an error) instead of silently falling back to a public bind iftailscale servecan't be confirmed.setup-environment.shnow asks before it pays theuv synccost, so skipping the AI model picker is instant, and shows a real cost estimate ("~250MB first run, 1-3 min") when the user opts in. Step 6's stale "Next steps" copy is fixed to describe whatmake installactually still does (frontend deps + Chrome setup) and points atmake doctor.uv.lockresynced to thehummingbot-api-client==1.5.7pin already declared inpyproject.toml(lockfile had drifted out of sync) — incidental, not part of the feature work.Test plan
uv run python -m condor.doctor/make doctor— runs correctly standalone, correct exit code on real failures (e.g. hummingbot-api not running)make -n install— confirms sequencing (setup→uv sync --dev→ frontend install → chrome setup → doctor)bash -n setup-environment.sh— syntax check passesblack --check/isort --checkclean on all touched filesuv run pytest— 1415 passed, 1 pre-existing unrelated failure (staleassistants/dir check, untouched by this PR)tailscale serveagainst a live tailnet (not available in the dev environment this was built in) — recommend verifying before merge/deploy🤖 Generated with Claude Code