Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 17 additions & 1 deletion src/ucode/agents/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,10 @@
from __future__ import annotations

import json
import os
import shutil
import subprocess
import sys

from ucode.agent_updates import available_npm_package_update
from ucode.config_io import ToolSpec
Expand Down Expand Up @@ -687,6 +689,19 @@ def provider_permission_error(tool: str, state: dict, err: str) -> str:
return err


# Both ``ug`` and ``ucode`` are console-script entry points for this CLI (see
# pyproject ``[project.scripts]``), so echo back whichever name the user actually
# launched when we tell them how to run a tool. Falls back to the primary ``ug``
# when argv[0] isn't a recognized name (``python -m ucode.cli``, a wrapper, tests).
_COMMAND_NAMES = frozenset({"ug", "ucode"})


def invoked_command_name() -> str:
"""Return the entry-point name the user launched (``ug`` or ``ucode``)."""
name = os.path.basename(sys.argv[0]) if sys.argv else ""
return name if name in _COMMAND_NAMES else "ug"


def validate_all_tools(state: dict) -> None:
from rich.panel import Panel # local to avoid bumping module-level deps

Expand Down Expand Up @@ -730,11 +745,12 @@ def validate_all_tools(state: dict) -> None:
success_tools = [(t, s) for t, s in results if s]
if success_tools and not low_verbosity:
console.print()
command = invoked_command_name()
lines = []
for tool, _ in success_tools:
spec = TOOL_SPECS[tool]
lines.append(
f"[green]✓[/green] [bold]{spec['display']}[/bold] — "
f"run with [cyan]ucode {tool}[/cyan]"
f"run with [cyan]{command} {tool}[/cyan]"
)
console.print(Panel("\n".join(lines), title="Ready", style="green", expand=False))
41 changes: 41 additions & 0 deletions tests/test_agents_init.py
Original file line number Diff line number Diff line change
Expand Up @@ -775,6 +775,30 @@ def test_empty_selection_preserves_existing(self, monkeypatch):
assert result["available_tools"] == ["codex"]


class TestInvokedCommandName:
@pytest.mark.parametrize(
"argv0, expected",
[
("/opt/homebrew/bin/ug", "ug"),
("/opt/homebrew/bin/ucode", "ucode"),
# Unrecognized launchers (python -m, wrappers, tests) fall back to `ug`.
("/usr/bin/python", "ug"),
("", "ug"),
],
)
def test_returns_recognized_name_or_falls_back(self, monkeypatch, argv0, expected):
import sys

monkeypatch.setattr(sys, "argv", [argv0])
assert agents_mod.invoked_command_name() == expected

def test_empty_argv_falls_back(self, monkeypatch):
import sys

monkeypatch.setattr(sys, "argv", [])
assert agents_mod.invoked_command_name() == "ug"


class TestValidateAllToolsVerbosity:
def _run(self, monkeypatch, capsys):
from contextlib import nullcontext
Expand All @@ -786,13 +810,30 @@ def _run(self, monkeypatch, capsys):
return capsys.readouterr().out

def test_normal_verbosity_renders_panels(self, monkeypatch, capsys):
import sys

import ucode.ui as ui_mod

monkeypatch.setattr(ui_mod, "_verbosity", "normal")
monkeypatch.setattr(sys, "argv", ["/opt/homebrew/bin/ug", "configure"])
out = self._run(monkeypatch, capsys)
assert "Testing each tool with a quick message" in out
assert "Ready" in out
assert "Codex is working" in out
# Launched as `ug`, the Ready panel echoes `ug`.
assert "ug codex" in out
assert "ucode codex" not in out

def test_ready_panel_echoes_ucode_entrypoint(self, monkeypatch, capsys):
import sys

import ucode.ui as ui_mod

monkeypatch.setattr(ui_mod, "_verbosity", "normal")
monkeypatch.setattr(sys, "argv", ["/opt/homebrew/bin/ucode", "configure"])
out = self._run(monkeypatch, capsys)
# Launched via the `ucode` alias, the Ready panel echoes `ucode`.
assert "ucode codex" in out

def test_low_verbosity_omits_panels(self, monkeypatch, capsys):
import ucode.ui as ui_mod
Expand Down
Loading