Co-authored-by: Quentin Torroba <quentin.torroba@mistral.ai>
Co-authored-by: Michel Thomazo <michel.thomazo@mistral.ai>
Co-authored-by: Clément Drouin <clement.drouin@mistral.ai>
Co-authored-by: Vincent Guilloux <vincent.guilloux@mistral.ai>
Co-authored-by: Clément Siriex <clement.sirieix@mistral.ai>
Co-authored-by: Kim-Adeline Miguel <kimadeline.miguel@mistral.ai>
Co-authored-by: Nicolas Karolak <nicolas@karolak.fr>
This commit is contained in:
Mathias Gesbert 2026-02-11 18:17:30 +01:00 committed by GitHub
parent 9809cfc831
commit 51fecc67d9
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
176 changed files with 8652 additions and 4451 deletions

View file

@ -4,17 +4,15 @@ from pathlib import Path
import pytest
from vibe.core.config import SessionLoggingConfig, VibeConfig
from tests.conftest import build_test_vibe_config
from vibe.core.tools.base import BaseToolConfig, ToolPermission
from vibe.core.tools.manager import ToolManager
@pytest.fixture
def config():
return VibeConfig(
session_logging=SessionLoggingConfig(enabled=False),
system_prompt_id="tests",
include_project_context=False,
return build_test_vibe_config(
system_prompt_id="tests", include_project_context=False
)
@ -35,8 +33,7 @@ def test_returns_default_config_when_no_overrides(tool_manager):
def test_merges_user_overrides_with_defaults():
vibe_config = VibeConfig(
session_logging=SessionLoggingConfig(enabled=False),
vibe_config = build_test_vibe_config(
system_prompt_id="tests",
include_project_context=False,
tools={"bash": BaseToolConfig(permission=ToolPermission.ALWAYS)},
@ -53,8 +50,7 @@ def test_merges_user_overrides_with_defaults():
def test_preserves_tool_specific_fields_from_overrides():
vibe_config = VibeConfig(
session_logging=SessionLoggingConfig(enabled=False),
vibe_config = build_test_vibe_config(
system_prompt_id="tests",
include_project_context=False,
tools={"bash": BaseToolConfig(permission=ToolPermission.ASK)},
@ -77,8 +73,7 @@ def test_falls_back_to_base_config_for_unknown_tool(tool_manager):
class TestToolManagerFiltering:
def test_enabled_tools_filters_to_only_enabled(self):
vibe_config = VibeConfig(
session_logging=SessionLoggingConfig(enabled=False),
vibe_config = build_test_vibe_config(
system_prompt_id="tests",
include_project_context=False,
enabled_tools=["bash", "grep"],
@ -93,8 +88,7 @@ class TestToolManagerFiltering:
assert "write_file" not in tools
def test_disabled_tools_excludes_disabled(self):
vibe_config = VibeConfig(
session_logging=SessionLoggingConfig(enabled=False),
vibe_config = build_test_vibe_config(
system_prompt_id="tests",
include_project_context=False,
disabled_tools=["bash", "write_file"],
@ -109,8 +103,7 @@ class TestToolManagerFiltering:
assert "read_file" in tools
def test_enabled_tools_takes_precedence_over_disabled(self):
vibe_config = VibeConfig(
session_logging=SessionLoggingConfig(enabled=False),
vibe_config = build_test_vibe_config(
system_prompt_id="tests",
include_project_context=False,
enabled_tools=["bash"],
@ -123,8 +116,7 @@ class TestToolManagerFiltering:
assert "bash" in tools
def test_glob_pattern_matching(self):
vibe_config = VibeConfig(
session_logging=SessionLoggingConfig(enabled=False),
vibe_config = build_test_vibe_config(
system_prompt_id="tests",
include_project_context=False,
disabled_tools=["*_file"], # Matches read_file, write_file
@ -138,8 +130,7 @@ class TestToolManagerFiltering:
assert "grep" in tools
def test_regex_pattern_matching(self):
vibe_config = VibeConfig(
session_logging=SessionLoggingConfig(enabled=False),
vibe_config = build_test_vibe_config(
system_prompt_id="tests",
include_project_context=False,
enabled_tools=["re:^(bash|grep)$"],
@ -152,8 +143,7 @@ class TestToolManagerFiltering:
assert "grep" in tools
def test_case_insensitive_matching(self):
vibe_config = VibeConfig(
session_logging=SessionLoggingConfig(enabled=False),
vibe_config = build_test_vibe_config(
system_prompt_id="tests",
include_project_context=False,
enabled_tools=["BASH", "GREP"],
@ -165,11 +155,8 @@ class TestToolManagerFiltering:
assert "grep" in tools
def test_empty_enabled_tools_returns_all(self):
vibe_config = VibeConfig(
session_logging=SessionLoggingConfig(enabled=False),
system_prompt_id="tests",
include_project_context=False,
enabled_tools=[],
vibe_config = build_test_vibe_config(
system_prompt_id="tests", include_project_context=False, enabled_tools=[]
)
manager = ToolManager(lambda: vibe_config)
@ -228,8 +215,7 @@ class FileTool(BaseTool[FileToolArgs, FileToolResult, BaseToolConfig, BaseToolSt
for k in to_remove:
del sys.modules[k]
vibe_config = VibeConfig(
session_logging=SessionLoggingConfig(enabled=False),
vibe_config = build_test_vibe_config(
system_prompt_id="tests",
include_project_context=False,
tool_paths=[tool_dir, file_tool],
@ -252,10 +238,8 @@ class TestToolManagerModuleReuse:
def test_multiple_managers_share_tool_classes(self):
"""Tool classes should be identical across multiple ToolManager instances."""
vibe_config = VibeConfig(
session_logging=SessionLoggingConfig(enabled=False),
system_prompt_id="tests",
include_project_context=False,
vibe_config = build_test_vibe_config(
system_prompt_id="tests", include_project_context=False
)
manager1 = ToolManager(lambda: vibe_config)
@ -272,10 +256,8 @@ class TestToolManagerModuleReuse:
def test_tool_state_classes_are_identical(self):
"""Tool state classes should be identical across managers."""
vibe_config = VibeConfig(
session_logging=SessionLoggingConfig(enabled=False),
system_prompt_id="tests",
include_project_context=False,
vibe_config = build_test_vibe_config(
system_prompt_id="tests", include_project_context=False
)
manager1 = ToolManager(lambda: vibe_config)
@ -291,10 +273,8 @@ class TestToolManagerModuleReuse:
def test_tool_args_results_classes_are_identical(self):
"""Tool args and result classes should be identical across managers."""
vibe_config = VibeConfig(
session_logging=SessionLoggingConfig(enabled=False),
system_prompt_id="tests",
include_project_context=False,
vibe_config = build_test_vibe_config(
system_prompt_id="tests", include_project_context=False
)
manager1 = ToolManager(lambda: vibe_config)
@ -315,10 +295,8 @@ class TestToolManagerModuleReuse:
This ensures subagents have isolated state (e.g., separate todo lists)
while still sharing class definitions for Pydantic validation.
"""
vibe_config = VibeConfig(
session_logging=SessionLoggingConfig(enabled=False),
system_prompt_id="tests",
include_project_context=False,
vibe_config = build_test_vibe_config(
system_prompt_id="tests", include_project_context=False
)
manager1 = ToolManager(lambda: vibe_config)
@ -343,10 +321,8 @@ class TestToolManagerModuleReuse:
def test_class_shared_but_instances_isolated(self):
"""Classes must be shared (for validation) but instances isolated (for state)."""
vibe_config = VibeConfig(
session_logging=SessionLoggingConfig(enabled=False),
system_prompt_id="tests",
include_project_context=False,
vibe_config = build_test_vibe_config(
system_prompt_id="tests", include_project_context=False
)
manager1 = ToolManager(lambda: vibe_config)

View file

@ -4,10 +4,10 @@ from unittest.mock import MagicMock, patch
import pytest
from tests.conftest import build_test_vibe_config
from tests.mock.utils import collect_result
from vibe.core.agents.manager import AgentManager
from vibe.core.agents.models import BUILTIN_AGENTS, AgentType
from vibe.core.config import VibeConfig
from vibe.core.tools.base import BaseToolState, InvokeContext, ToolError
from vibe.core.tools.builtins.task import Task, TaskArgs, TaskResult, TaskToolConfig
from vibe.core.types import AssistantEvent, LLMMessage, Role
@ -32,7 +32,9 @@ class TestTaskArgs:
class TestTaskToolValidation:
@pytest.fixture
def ctx(self) -> InvokeContext:
config = VibeConfig(include_project_context=False, include_prompt_detail=False)
config = build_test_vibe_config(
include_project_context=False, include_prompt_detail=False
)
manager = AgentManager(lambda: config)
return InvokeContext(tool_call_id="test-call-id", agent_manager=manager)
@ -77,7 +79,9 @@ class TestTaskToolValidation:
class TestTaskToolExecution:
@pytest.fixture
def ctx(self) -> InvokeContext:
config = VibeConfig(include_project_context=False, include_prompt_detail=False)
config = build_test_vibe_config(
include_project_context=False, include_prompt_detail=False
)
manager = AgentManager(lambda: config)
return InvokeContext(tool_call_id="test-call-id", agent_manager=manager)

View file

@ -1,6 +1,5 @@
from __future__ import annotations
from pathlib import Path
import time
import pytest
@ -9,20 +8,6 @@ from textual.widgets import Static
from vibe.cli.textual_ui.app import VibeApp
from vibe.cli.textual_ui.widgets.chat_input.container import ChatInputContainer
from vibe.cli.textual_ui.widgets.messages import BashOutputMessage, ErrorMessage
from vibe.core.agent_loop import AgentLoop
from vibe.core.config import SessionLoggingConfig, VibeConfig
@pytest.fixture
def vibe_config(tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> VibeConfig:
monkeypatch.chdir(tmp_path)
return VibeConfig(session_logging=SessionLoggingConfig(enabled=False))
@pytest.fixture
def vibe_app(vibe_config: VibeConfig) -> VibeApp:
agent_loop = AgentLoop(vibe_config)
return VibeApp(agent_loop=agent_loop)
async def _wait_for_bash_output_message(
@ -76,9 +61,8 @@ async def test_ui_shows_success_in_case_of_zero_code(vibe_app: VibeApp) -> None:
await pilot.press("enter")
message = await _wait_for_bash_output_message(vibe_app, pilot)
icon = message.query_one(".bash-exit-success", Static)
assert str(icon.render()) == ""
assert not list(message.query(".bash-exit-failure"))
assert message.has_class("bash-success")
assert not message.has_class("bash-error")
@pytest.mark.asyncio
@ -89,11 +73,8 @@ async def test_ui_shows_failure_in_case_of_non_zero_code(vibe_app: VibeApp) -> N
await pilot.press("enter")
message = await _wait_for_bash_output_message(vibe_app, pilot)
icon = message.query_one(".bash-exit-failure", Static)
assert str(icon.render()) == ""
code = message.query_one(".bash-exit-code", Static)
assert "7" in str(code.render())
assert not list(message.query(".bash-exit-success"))
assert message.has_class("bash-error")
assert not message.has_class("bash-success")
@pytest.mark.asyncio
@ -122,7 +103,7 @@ async def test_ui_handles_utf8_output(vibe_app: VibeApp) -> None:
await pilot.press("enter")
message = await _wait_for_bash_output_message(vibe_app, pilot)
output_widget = message.query_one(".bash-output", Static)
assert str(output_widget.render()) == "hello\n"
assert str(output_widget.render()) == "hello"
assert_no_command_error(vibe_app)