Co-authored-by: Hdandria <henri.dandria@mistral.ai>
Co-authored-by: Liam Lyons <65613603+lyons-liam@users.noreply.github.com>
Co-authored-by: Mathias Gesbert <mathias.gesbert@mistral.ai>
Co-authored-by: Pierre Rossinès <pierre.rossines@mistral.ai>
Co-authored-by: Quentin <quentin.torroba@mistral.ai>
Co-authored-by: allansimon-mistral <allan.simon@ext.mistral.ai>
Co-authored-by: angelapopopo <angele.lenglemetz@mistral.ai>
Co-authored-by: Mistral Vibe <vibe@mistral.ai>
This commit is contained in:
Clément Drouin 2026-06-15 17:36:21 +02:00 committed by GitHub
parent cafb6d4147
commit c2cb612ac1
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
67 changed files with 2704 additions and 197 deletions

View file

@ -2,7 +2,7 @@ from __future__ import annotations
from pathlib import Path
from typing import cast
from unittest.mock import patch
from unittest.mock import AsyncMock, patch
from acp.schema import TextContentBlock, ToolCallProgress, ToolCallStart
import pytest
@ -11,8 +11,10 @@ from tests.conftest import build_test_vibe_config, make_test_models
from tests.stubs.fake_backend import FakeBackend
from tests.stubs.fake_client import FakeClient
from vibe.acp.acp_agent_loop import VibeAcpAgentLoop
from vibe.core.agent_loop import AgentLoop
from vibe.acp.exceptions import CompactionError
from vibe.core.agent_loop import AgentLoop, CompactionFailedError
from vibe.core.session.session_id import shorten_session_id
from vibe.core.types import LLMMessage, Role
@pytest.fixture
@ -87,3 +89,31 @@ class TestCompactEventHandling:
assert (
shorten_session_id(session.agent_loop.session_id) in compact_end_text.text
)
@pytest.mark.asyncio
async def test_slash_compact_maps_compaction_failure(
self, acp_agent_loop: VibeAcpAgentLoop
) -> None:
"""A /compact failure surfaces as a mapped CompactionError, not a raw
core exception same as the auto-compaction path.
"""
session_response = await acp_agent_loop.new_session(
cwd=str(Path.cwd()), mcp_servers=[]
)
session = acp_agent_loop.sessions[session_response.session_id]
# Need >1 message so /compact does not early-return.
session.agent_loop.messages.append(LLMMessage(role=Role.user, content="hello"))
with patch.object(
session.agent_loop,
"compact",
AsyncMock(side_effect=CompactionFailedError("tool_call")),
):
with pytest.raises(CompactionError) as exc_info:
await acp_agent_loop.prompt(
prompt=[TextContentBlock(type="text", text="/compact")],
session_id=session_response.session_id,
)
assert exc_info.value.code == -31006
assert exc_info.value.data == {"reason": "tool_call"}

View file

@ -1,5 +1,9 @@
from __future__ import annotations
from types import SimpleNamespace
from typing import Any, cast
from unittest.mock import AsyncMock
from acp import PROTOCOL_VERSION
from acp.schema import (
AgentCapabilities,
@ -13,6 +17,7 @@ from acp.schema import (
)
import pytest
from tests.conftest import build_test_vibe_config
from vibe.acp.acp_agent_loop import VibeAcpAgentLoop
from vibe.core.config import ProviderConfig
from vibe.core.types import Backend
@ -67,7 +72,7 @@ class TestACPInitialize:
),
)
assert response.agent_info == Implementation(
name="@mistralai/mistral-vibe", title="Mistral Vibe", version="2.15.0"
name="@mistralai/mistral-vibe", title="Mistral Vibe", version="2.16.0"
)
assert response.auth_methods is not None
@ -77,6 +82,72 @@ class TestACPInitialize:
assert auth_method.name == BROWSER_AUTH_NAME
assert auth_method.description == BROWSER_AUTH_DESCRIPTION
@pytest.mark.asyncio
async def test_load_config_uses_client_info_title_for_vibe_code_project_name(
self, monkeypatch: pytest.MonkeyPatch
) -> None:
config = build_test_vibe_config()
monkeypatch.setattr(
"vibe.acp.acp_agent_loop.VibeConfig.load", lambda *args, **kwargs: config
)
acp_agent_loop = build_acp_agent_loop()
await acp_agent_loop.initialize(
protocol_version=PROTOCOL_VERSION,
client_info=Implementation(name="zed", title="Zed", version="0.999.0"),
)
assert acp_agent_loop._load_config().vibe_code_project_name == "Zed"
@pytest.mark.asyncio
async def test_load_config_preserves_explicit_vibe_code_project_name(
self, monkeypatch: pytest.MonkeyPatch
) -> None:
config = build_test_vibe_config(vibe_code_project_name="Configured Project")
monkeypatch.setattr(
"vibe.acp.acp_agent_loop.VibeConfig.load", lambda *args, **kwargs: config
)
acp_agent_loop = build_acp_agent_loop()
await acp_agent_loop.initialize(
protocol_version=PROTOCOL_VERSION,
client_info=Implementation(name="zed", title="Zed", version="0.999.0"),
)
assert (
acp_agent_loop._load_config().vibe_code_project_name == "Configured Project"
)
@pytest.mark.asyncio
@pytest.mark.parametrize(
"reload_method_name", ["_reload_config", "_reload_session_config"]
)
async def test_reload_config_uses_client_info_title_for_vibe_code_project_name(
self, monkeypatch: pytest.MonkeyPatch, reload_method_name: str
) -> None:
config = build_test_vibe_config()
monkeypatch.setattr(
"vibe.acp.acp_agent_loop.VibeConfig.load", lambda *args, **kwargs: config
)
acp_agent_loop = build_acp_agent_loop()
agent_loop = SimpleNamespace(
config=SimpleNamespace(tool_paths=[]),
reload_with_initial_messages=AsyncMock(),
)
session = cast(Any, SimpleNamespace(agent_loop=agent_loop))
await acp_agent_loop.initialize(
protocol_version=PROTOCOL_VERSION,
client_info=Implementation(name="zed", title="Zed", version="0.999.0"),
)
await getattr(acp_agent_loop, reload_method_name)(session)
agent_loop.reload_with_initial_messages.assert_awaited_once()
reloaded_config = agent_loop.reload_with_initial_messages.await_args.kwargs[
"base_config"
]
assert reloaded_config.vibe_code_project_name == "Zed"
@pytest.mark.asyncio
async def test_initialize_with_terminal_auth(
self, unauthenticated_env: None
@ -101,7 +172,7 @@ class TestACPInitialize:
),
)
assert response.agent_info == Implementation(
name="@mistralai/mistral-vibe", title="Mistral Vibe", version="2.15.0"
name="@mistralai/mistral-vibe", title="Mistral Vibe", version="2.16.0"
)
assert response.auth_methods is not None