2.1.0 (#317)
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:
parent
9809cfc831
commit
51fecc67d9
176 changed files with 8652 additions and 4451 deletions
154
tests/acp/test_agent_thought.py
Normal file
154
tests/acp/test_agent_thought.py
Normal file
|
|
@ -0,0 +1,154 @@
|
|||
from __future__ import annotations
|
||||
|
||||
from pathlib import Path
|
||||
from unittest.mock import patch
|
||||
|
||||
from acp.schema import AgentThoughtChunk, TextContentBlock
|
||||
import pytest
|
||||
|
||||
from tests.acp.conftest import _create_acp_agent
|
||||
from tests.conftest import build_test_vibe_config
|
||||
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.core.types import LLMChunk, LLMMessage, LLMUsage, Role
|
||||
|
||||
|
||||
def _create_backend_with_reasoning(
|
||||
reasoning_content: str, content: str = "Hi"
|
||||
) -> FakeBackend:
|
||||
return FakeBackend(
|
||||
LLMChunk(
|
||||
message=LLMMessage(
|
||||
role=Role.assistant,
|
||||
content=content,
|
||||
reasoning_content=reasoning_content,
|
||||
),
|
||||
usage=LLMUsage(prompt_tokens=1, completion_tokens=1),
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def backend_with_reasoning() -> FakeBackend:
|
||||
return _create_backend_with_reasoning("Let me think about this...")
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def acp_agent_loop_with_reasoning(
|
||||
backend_with_reasoning: FakeBackend,
|
||||
) -> VibeAcpAgentLoop:
|
||||
config = build_test_vibe_config(active_model="devstral-latest")
|
||||
|
||||
class PatchedAgentLoop(AgentLoop):
|
||||
def __init__(self, *args, **kwargs) -> None:
|
||||
super().__init__(*args, **{**kwargs, "backend": backend_with_reasoning})
|
||||
self._base_config = config
|
||||
self.agent_manager.invalidate_config()
|
||||
|
||||
patch("vibe.acp.acp_agent_loop.AgentLoop", side_effect=PatchedAgentLoop).start()
|
||||
return _create_acp_agent()
|
||||
|
||||
|
||||
class TestACPAgentThought:
|
||||
@pytest.mark.asyncio
|
||||
async def test_prompt_with_reasoning_emits_agent_thought_chunk(
|
||||
self, acp_agent_loop_with_reasoning: VibeAcpAgentLoop
|
||||
) -> None:
|
||||
session_response = await acp_agent_loop_with_reasoning.new_session(
|
||||
cwd=str(Path.cwd()), mcp_servers=[]
|
||||
)
|
||||
session_id = session_response.session_id
|
||||
|
||||
await acp_agent_loop_with_reasoning.prompt(
|
||||
session_id=session_id,
|
||||
prompt=[TextContentBlock(type="text", text="Just say hi")],
|
||||
)
|
||||
|
||||
fake_client: FakeClient = acp_agent_loop_with_reasoning.client # type: ignore
|
||||
thought_updates = [
|
||||
update
|
||||
for update in fake_client._session_updates
|
||||
if isinstance(update.update, AgentThoughtChunk)
|
||||
]
|
||||
|
||||
assert len(thought_updates) == 1
|
||||
thought_chunk = thought_updates[0].update
|
||||
assert thought_chunk.session_update == "agent_thought_chunk"
|
||||
assert thought_chunk.content is not None
|
||||
assert isinstance(thought_chunk.content, TextContentBlock)
|
||||
assert thought_chunk.content.text == "Let me think about this..."
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_prompt_without_reasoning_does_not_emit_agent_thought_chunk(
|
||||
self, acp_agent_loop: VibeAcpAgentLoop
|
||||
) -> None:
|
||||
session_response = await acp_agent_loop.new_session(
|
||||
cwd=str(Path.cwd()), mcp_servers=[]
|
||||
)
|
||||
session_id = session_response.session_id
|
||||
|
||||
await acp_agent_loop.prompt(
|
||||
session_id=session_id,
|
||||
prompt=[TextContentBlock(type="text", text="Just say hi")],
|
||||
)
|
||||
|
||||
fake_client: FakeClient = acp_agent_loop.client # type: ignore
|
||||
thought_updates = [
|
||||
update
|
||||
for update in fake_client._session_updates
|
||||
if isinstance(update.update, AgentThoughtChunk)
|
||||
]
|
||||
|
||||
assert len(thought_updates) == 0
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_agent_thought_chunk_contains_text_content_block(
|
||||
self, acp_agent_loop_with_reasoning: VibeAcpAgentLoop
|
||||
) -> None:
|
||||
session_response = await acp_agent_loop_with_reasoning.new_session(
|
||||
cwd=str(Path.cwd()), mcp_servers=[]
|
||||
)
|
||||
session_id = session_response.session_id
|
||||
|
||||
await acp_agent_loop_with_reasoning.prompt(
|
||||
session_id=session_id, prompt=[TextContentBlock(type="text", text="Hello")]
|
||||
)
|
||||
|
||||
fake_client: FakeClient = acp_agent_loop_with_reasoning.client # type: ignore
|
||||
thought_updates = [
|
||||
update
|
||||
for update in fake_client._session_updates
|
||||
if isinstance(update.update, AgentThoughtChunk)
|
||||
]
|
||||
|
||||
assert len(thought_updates) == 1
|
||||
thought_chunk = thought_updates[0].update
|
||||
assert thought_chunk.content.type == "text"
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_agent_thought_chunk_contains_message_id(
|
||||
self, acp_agent_loop_with_reasoning: VibeAcpAgentLoop
|
||||
) -> None:
|
||||
session_response = await acp_agent_loop_with_reasoning.new_session(
|
||||
cwd=str(Path.cwd()), mcp_servers=[]
|
||||
)
|
||||
session_id = session_response.session_id
|
||||
|
||||
await acp_agent_loop_with_reasoning.prompt(
|
||||
session_id=session_id, prompt=[TextContentBlock(type="text", text="Hello")]
|
||||
)
|
||||
|
||||
fake_client: FakeClient = acp_agent_loop_with_reasoning.client # type: ignore
|
||||
thought_updates = [
|
||||
update
|
||||
for update in fake_client._session_updates
|
||||
if isinstance(update.update, AgentThoughtChunk)
|
||||
]
|
||||
|
||||
assert len(thought_updates) == 1
|
||||
thought_chunk = thought_updates[0].update
|
||||
assert thought_chunk.field_meta is not None
|
||||
assert "messageId" in thought_chunk.field_meta
|
||||
assert thought_chunk.field_meta["messageId"] is not None
|
||||
|
|
@ -2,6 +2,7 @@ from __future__ import annotations
|
|||
|
||||
import asyncio
|
||||
|
||||
from acp import CreateTerminalResponse
|
||||
from acp.schema import EnvVariable, TerminalOutputResponse, WaitForTerminalExitResponse
|
||||
import pytest
|
||||
|
||||
|
|
@ -58,7 +59,7 @@ class MockClient:
|
|||
env: list | None = None,
|
||||
output_byte_limit: int | None = None,
|
||||
**kwargs,
|
||||
) -> MockTerminalHandle:
|
||||
) -> CreateTerminalResponse:
|
||||
self._create_terminal_called = True
|
||||
self._last_create_params = {
|
||||
"command": command,
|
||||
|
|
@ -70,7 +71,7 @@ class MockClient:
|
|||
}
|
||||
if self._create_terminal_error:
|
||||
raise self._create_terminal_error
|
||||
return self._terminal_handle
|
||||
return CreateTerminalResponse(terminal_id=self._terminal_handle.id)
|
||||
|
||||
async def terminal_output(
|
||||
self, session_id: str, terminal_id: str, **kwargs
|
||||
|
|
|
|||
|
|
@ -7,11 +7,11 @@ from unittest.mock import patch
|
|||
from acp.schema import TextContentBlock, ToolCallProgress, ToolCallStart
|
||||
import pytest
|
||||
|
||||
from tests.conftest import build_test_vibe_config
|
||||
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.core.config import SessionLoggingConfig, VibeConfig
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
|
|
@ -19,10 +19,7 @@ def acp_agent_loop(backend: FakeBackend) -> VibeAcpAgentLoop:
|
|||
class PatchedAgent(AgentLoop):
|
||||
def __init__(self, *args, **kwargs) -> None:
|
||||
# Force our config with auto_compact_threshold=1
|
||||
kwargs["config"] = VibeConfig(
|
||||
session_logging=SessionLoggingConfig(enabled=False),
|
||||
auto_compact_threshold=1,
|
||||
)
|
||||
kwargs["config"] = build_test_vibe_config(auto_compact_threshold=1)
|
||||
super().__init__(*args, **kwargs, backend=backend)
|
||||
|
||||
patch("vibe.acp.acp_agent_loop.AgentLoop", side_effect=PatchedAgent).start()
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ class TestACPInitialize:
|
|||
),
|
||||
)
|
||||
assert response.agent_info == Implementation(
|
||||
name="@mistralai/mistral-vibe", title="Mistral Vibe", version="2.0.2"
|
||||
name="@mistralai/mistral-vibe", title="Mistral Vibe", version="2.1.0"
|
||||
)
|
||||
|
||||
assert response.auth_methods == []
|
||||
|
|
@ -48,7 +48,7 @@ class TestACPInitialize:
|
|||
),
|
||||
)
|
||||
assert response.agent_info == Implementation(
|
||||
name="@mistralai/mistral-vibe", title="Mistral Vibe", version="2.0.2"
|
||||
name="@mistralai/mistral-vibe", title="Mistral Vibe", version="2.1.0"
|
||||
)
|
||||
|
||||
assert response.auth_methods is not None
|
||||
|
|
|
|||
|
|
@ -6,15 +6,16 @@ from unittest.mock import patch
|
|||
import pytest
|
||||
|
||||
from tests.acp.conftest import _create_acp_agent
|
||||
from tests.conftest import build_test_vibe_config
|
||||
from vibe.acp.acp_agent_loop import VibeAcpAgentLoop
|
||||
from vibe.core.agent_loop import AgentLoop
|
||||
from vibe.core.agents.models import BuiltinAgentName
|
||||
from vibe.core.config import ModelConfig, VibeConfig
|
||||
from vibe.core.config import ModelConfig
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def acp_agent_loop(backend) -> VibeAcpAgentLoop:
|
||||
config = VibeConfig(
|
||||
config = build_test_vibe_config(
|
||||
active_model="devstral-latest",
|
||||
models=[
|
||||
ModelConfig(
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ from unittest.mock import patch
|
|||
import pytest
|
||||
|
||||
from tests.acp.conftest import _create_acp_agent
|
||||
from tests.conftest import build_test_vibe_config
|
||||
from vibe.acp.acp_agent_loop import VibeAcpAgentLoop
|
||||
from vibe.core.agent_loop import AgentLoop
|
||||
from vibe.core.config import ModelConfig, VibeConfig
|
||||
|
|
@ -14,7 +15,7 @@ from vibe.core.types import LLMMessage, Role
|
|||
|
||||
@pytest.fixture
|
||||
def acp_agent_loop(backend) -> VibeAcpAgentLoop:
|
||||
config = VibeConfig(
|
||||
config = build_test_vibe_config(
|
||||
active_model="devstral-latest",
|
||||
models=[
|
||||
ModelConfig(
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue