Add `extra` to the installed dcode tool environment. Runs `uv tool install --reinstall -U 'deepagents-code[ ]== ' --prerelease allow`, preserving any extras that are already installed. Editable installs are refused — the caller should rerun their `uv tool install --ed
(
extra: str,
*,
progress: UpgradeProgressCallback | None = None,
log_path: Path | None = None,
)
| 2540 | |
| 2541 | |
| 2542 | async def perform_install_extra( |
| 2543 | extra: str, |
| 2544 | *, |
| 2545 | progress: UpgradeProgressCallback | None = None, |
| 2546 | log_path: Path | None = None, |
| 2547 | ) -> tuple[bool, str]: |
| 2548 | """Add `extra` to the installed dcode tool environment. |
| 2549 | |
| 2550 | Runs `uv tool install --reinstall -U 'deepagents-code[<extras>]==<current>' |
| 2551 | --prerelease allow`, preserving any extras that are already installed. |
| 2552 | Editable installs are refused — the caller should rerun their |
| 2553 | `uv tool install --editable` command with `--with 'deepagents-code[<extra>]'` |
| 2554 | added so the extra is resolved against the editable source. |
| 2555 | |
| 2556 | Args: |
| 2557 | extra: The extra name to install. Must satisfy `is_valid_extra_name`; |
| 2558 | invalid names are rejected without invoking uv (defense in depth |
| 2559 | against shell injection via the `--force`/`--yes` bypass paths). |
| 2560 | progress: Optional callback invoked for each output line. |
| 2561 | log_path: Optional path to persist command output. |
| 2562 | |
| 2563 | Returns: |
| 2564 | `(success, output)` — *output* is the combined stdout/stderr, or an |
| 2565 | explanatory error message when the install method is unsupported |
| 2566 | or `extra` is malformed. |
| 2567 | """ |
| 2568 | if not is_valid_extra_name(extra): |
| 2569 | return False, ( |
| 2570 | f"Invalid extra name {extra!r}: must match {_EXTRA_NAME_RE.pattern}" |
| 2571 | ) |
| 2572 | method = detect_install_method() |
| 2573 | if method == "unknown": |
| 2574 | return False, ( |
| 2575 | "Editable install detected — cannot add extras automatically.\n" |
| 2576 | + editable_extra_hint(extra) |
| 2577 | ) |
| 2578 | if method == "brew": |
| 2579 | # Homebrew formula doesn't expose extras; uv tool install is the |
| 2580 | # right escape hatch but would conflict with the brew-managed binary. |
| 2581 | return False, ( |
| 2582 | "Homebrew install detected — extras are not supported via brew. " |
| 2583 | f"Reinstall with `{install_extra_command(extra)}` to switch to a " |
| 2584 | "uv-managed tool install with extras." |
| 2585 | ) |
| 2586 | if method == "other": |
| 2587 | return False, ( |
| 2588 | "Unsupported install method detected — cannot add extras without " |
| 2589 | "knowing which environment provides `dcode`. Reinstall with " |
| 2590 | f"`{install_extra_command(extra)}` to switch to a uv-managed tool " |
| 2591 | "install with extras." |
| 2592 | ) |
| 2593 | |
| 2594 | if not shutil.which("uv"): |
| 2595 | return False, ( |
| 2596 | "`uv` not found on PATH. Reinstall dcode following the docs, or " |
| 2597 | "install uv (https://docs.astral.sh/uv/) so extras can be added." |
| 2598 | ) |
| 2599 |
searching dependent graphs…