Files
codewhale/crates/tui
Hunter Bown 2b54b7e79d feat(tools): probe Python interpreter at catalog-build time; doctor surfaces missing deps
Closes the "code_execution: program not found" failure reported by a
Windows contributor and adds the surrounding plumbing so future
external-binary dependencies can be added without each one repeating
the same probe-and-skip logic.

New module `crates/tui/src/dependencies.rs`:

  * `PYTHON_CANDIDATES = ["python3", "python", "py -3"]` — try the
    Unix-style name first, then the bare name (common on Windows and
    modern macOS), then the Windows launcher as a last resort.
  * `probe_executable(spec)` — splits the spec on whitespace, spawns
    `<program> [args...] --version`, returns true on success. stdout
    and stderr are routed to /dev/null so the probe doesn't print to
    the TUI's first frame.
  * `resolve_python_interpreter()` — OnceLock-cached resolver that
    returns the first candidate that probed successfully, or None.
  * `resolve_pdftotext()` — same shape, for doctor's PDF-path
    diagnostic.
  * `split_interpreter_spec("py -3") → ("py", ["-3"])` — needed so
    `tokio::process::Command::new(program).args(args).arg(script)`
    runs the Windows launcher correctly.

Wiring in `core/engine/tool_catalog.rs::ensure_advanced_tooling`:

  * The hardcoded `catalog.push(Tool { name: "code_execution", … })`
    is now gated on `resolve_python_interpreter().is_some()`. On a
    machine without Python the tool is not advertised — the model
    never sees a tool it can't actually run, which removes the
    "Failed to execute tool: program not found" class of failure
    entirely. On a machine WITH Python the behavior is unchanged
    from the user's perspective.

Wiring in `execute_code_execution_tool`:

  * Resolves the interpreter at call time (still cached) and splits
    on whitespace so `py -3` runs as `py -3 /tmp/.../code.py`.
  * Writes the user code to a tempfile under tempdir() and runs the
    file rather than passing it through `python3 -c "..."`. Fixes
    argv length limits on Windows, multiline code with quote
    nesting, and traceback line numbers (real filename instead of
    `<string>`). Folds in the contributor's Part 2 proposal.
  * Returns a clear actionable error if the interpreter somehow
    disappears between startup and the call (uninstall mid-session,
    PATH manipulation, etc.).

Doctor (`crates/tui/src/main.rs::run_doctor`) gains two new sections:

  * "Tool Dependencies": ✓/✗ for Python and pdftotext with a
    platform-specific install hint when missing. The Python miss
    explicitly tells users that `code_execution` is not advertised.
  * "Terminal Quirks": shows which env-driven auto-overrides are
    currently active (VS Code / Ghostty low-motion, Termius/SSH
    low-motion per #1433, Ptyxis sync-output-off per v0.8.31).
    Answers the "why is my flicker / motion behaving this way"
    question without needing the user to read the source.

The contributor's Part 1 proposal (share the sandbox/approval
substrate with task_shell_start) is deferred to v0.8.32 — that
touches `sandbox/` which CLAUDE.md flags as "stop and ask before
changing" and needs an explicit design pass on approval semantics.

Six new unit tests in `dependencies.rs` covering probe behavior,
spec splitting, and cache stability. Existing tool_catalog tests
still pass.
2026-05-11 22:54:52 -05:00
..
2026-05-11 19:21:45 -05:00