Skip to content
Merged
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
5 changes: 2 additions & 3 deletions src/ucode/agents/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@
}


def install_ai_tools_for_agents(tools: list[str], state: dict) -> None:
def install_databricks_ai_tools_for_agents(tools: list[str], state: dict) -> None:
"""Install Databricks AI Tools for the coding agents that support them
(gemini/pi have no ``aitools`` support and are dropped)."""
if state.get("databricks_ai_tools_enabled", True) is False:
Expand Down Expand Up @@ -429,7 +429,6 @@ def configure_single_tool(tool: str, state: dict) -> dict:
available_tools = list(set((state.get("available_tools") or []) + [tool]))
state["available_tools"] = available_tools
save_state(state)
install_ai_tools_for_agents([tool], state)
return state


Expand Down Expand Up @@ -462,7 +461,7 @@ def configure_selected_tools(state: dict, tools: list[str]) -> dict:
existing = state.get("available_tools") or []
state["available_tools"] = sorted(set(existing) | set(tools))
save_state(state)
install_ai_tools_for_agents(tools, state)
install_databricks_ai_tools_for_agents(tools, state)
return state


Expand Down
2 changes: 2 additions & 0 deletions src/ucode/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
configure_tool,
ensure_bootstrap_dependencies,
ensure_provider_state,
install_databricks_ai_tools_for_agents,
install_tool_binary,
normalize_tool,
provider_permission_error,
Expand Down Expand Up @@ -769,6 +770,7 @@ def configure_workspace_command(
)
state = states[0]
state = configure_single_tool(tool, state)
install_databricks_ai_tools_for_agents([tool], state)
spec = TOOL_SPECS[tool]
console.print(
Panel(
Expand Down
28 changes: 13 additions & 15 deletions tests/test_agents_init.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
configure_selected_tools,
default_model_for_tool,
ensure_tool_binary_available,
install_ai_tools_for_agents,
install_databricks_ai_tools_for_agents,
install_tool_binary,
normalize_tool,
provider_permission_error,
Expand Down Expand Up @@ -74,26 +74,30 @@ def _capture(self, monkeypatch):
def test_maps_supported_tools_and_drops_others(self, monkeypatch):
captured = self._capture(monkeypatch)
# gemini and pi aren't supported by `databricks aitools`, so they drop.
install_ai_tools_for_agents(["claude", "codex", "gemini", "pi"], {"profile": "prof"})
install_databricks_ai_tools_for_agents(
["claude", "codex", "gemini", "pi"], {"profile": "prof"}
)
assert captured == {"agents": ["claude-code", "codex"], "profile": "prof"}

def test_installed_by_default(self, monkeypatch):
# Opt-out: absent flag means install.
captured = self._capture(monkeypatch)
install_ai_tools_for_agents(["claude"], {"profile": "p"})
install_databricks_ai_tools_for_agents(["claude"], {"profile": "p"})
assert captured == {"agents": ["claude-code"], "profile": "p"}

def test_skipped_when_disabled(self, monkeypatch):
# `configure --disable-databricks-ai-tools` persists this False.
captured = self._capture(monkeypatch)
install_ai_tools_for_agents(
install_databricks_ai_tools_for_agents(
["claude"], {"profile": "p", "databricks_ai_tools_enabled": False}
)
assert captured == {} # install_ai_tools never called


class TestConfigureWiresAiToolsInstall:
"""Both configure chokepoints must trigger AI Tools install."""
"""AI Tools install is a `ucode configure`-only step. `configure_selected_tools`
(a configure-only chokepoint) triggers it; `configure_single_tool` does NOT,
because the launch path auto-configures through it and must never install."""

def _stub_configure(self, monkeypatch):
captured = {}
Expand All @@ -106,24 +110,18 @@ def _stub_configure(self, monkeypatch):
)
return captured

def test_configure_single_tool_triggers_install(self, monkeypatch):
def test_configure_single_tool_does_not_install(self, monkeypatch):
# Launch auto-configures through configure_single_tool, so it must not
# install skills — that would put skill installation on the launch path.
captured = self._stub_configure(monkeypatch)
agents_mod.configure_single_tool("codex", {"codex_models": ["m"], "profile": "myprof"})
assert captured == {"agents": ["codex"], "profile": "myprof"}
assert captured == {}

def test_configure_selected_tools_triggers_install(self, monkeypatch):
captured = self._stub_configure(monkeypatch)
agents_mod.configure_selected_tools({"profile": "myprof"}, ["codex"])
assert captured == {"agents": ["codex"], "profile": "myprof"}

def test_configure_single_tool_respects_disable(self, monkeypatch):
captured = self._stub_configure(monkeypatch)
agents_mod.configure_single_tool(
"codex",
{"codex_models": ["m"], "profile": "myprof", "databricks_ai_tools_enabled": False},
)
assert captured == {}


class TestNormalizeTool:
@pytest.mark.parametrize(
Expand Down
9 changes: 9 additions & 0 deletions tests/test_cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -2181,6 +2181,12 @@ def test_skip_validate_skips_single_tool_validation(self, monkeypatch):
state = {**MINIMAL_STATE, "workspace": "https://first.com"}
monkeypatch.setattr(cli_mod, "configure_shared_state", lambda *a, **k: state)
monkeypatch.setattr(cli_mod, "configure_single_tool", lambda t, s: s)
installed: list = []
monkeypatch.setattr(
cli_mod,
"install_databricks_ai_tools_for_agents",
lambda tools, s: installed.append(tools),
)
validated: list = []
monkeypatch.setattr(cli_mod, "validate_tool", lambda t: validated.append(t) or (True, ""))

Expand All @@ -2192,6 +2198,9 @@ def test_skip_validate_skips_single_tool_validation(self, monkeypatch):

assert result == 0
assert validated == []
# `ucode configure` (single-agent) still installs AI Tools — it's the
# configure path, unlike launch which auto-configures without installing.
assert installed == [["claude"]]


class TestConfigureSharedStateMcpCleanup:
Expand Down
Loading