v1.1.2
Co-Authored-By: Clément Drouin <clement.drouin@mistral.ai>
This commit is contained in:
parent
af43abea60
commit
a340a721ea
13 changed files with 234 additions and 80 deletions
2
.vscode/launch.json
vendored
2
.vscode/launch.json
vendored
|
|
@ -1,5 +1,5 @@
|
||||||
{
|
{
|
||||||
"version": "1.1.1",
|
"version": "1.1.2",
|
||||||
"configurations": [
|
"configurations": [
|
||||||
{
|
{
|
||||||
"name": "ACP Server",
|
"name": "ACP Server",
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,13 @@ All notable changes to this project will be documented in this file.
|
||||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||||
|
|
||||||
|
## [1.1.2] - 2025-12-11
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- add `terminal-auth` auth method to ACP agent only if the client supports it
|
||||||
|
- fix `user-agent` header when using Mistral backend, using SDK hook
|
||||||
|
|
||||||
## [1.1.1] - 2025-12-10
|
## [1.1.1] - 2025-12-10
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
id = "mistral-vibe"
|
id = "mistral-vibe"
|
||||||
name = "Mistral Vibe"
|
name = "Mistral Vibe"
|
||||||
description = "Mistral's open-source coding assistant"
|
description = "Mistral's open-source coding assistant"
|
||||||
version = "1.1.1"
|
version = "1.1.2"
|
||||||
schema_version = 1
|
schema_version = 1
|
||||||
authors = ["Mistral AI"]
|
authors = ["Mistral AI"]
|
||||||
repository = "https://github.com/mistralai/mistral-vibe"
|
repository = "https://github.com/mistralai/mistral-vibe"
|
||||||
|
|
@ -11,25 +11,25 @@ name = "Mistral Vibe"
|
||||||
icon = "./icons/mistral_vibe.svg"
|
icon = "./icons/mistral_vibe.svg"
|
||||||
|
|
||||||
[agent_servers.mistral-vibe.targets.darwin-aarch64]
|
[agent_servers.mistral-vibe.targets.darwin-aarch64]
|
||||||
archive = "https://github.com/mistralai/mistral-vibe/releases/download/v1.1.1/vibe-acp-darwin-aarch64-1.1.1.zip"
|
archive = "https://github.com/mistralai/mistral-vibe/releases/download/v1.1.2/vibe-acp-darwin-aarch64-1.1.2.zip"
|
||||||
cmd = "./vibe-acp"
|
cmd = "./vibe-acp"
|
||||||
|
|
||||||
[agent_servers.mistral-vibe.targets.darwin-x86_64]
|
[agent_servers.mistral-vibe.targets.darwin-x86_64]
|
||||||
archive = "https://github.com/mistralai/mistral-vibe/releases/download/v1.1.1/vibe-acp-darwin-x86_64-1.1.1.zip"
|
archive = "https://github.com/mistralai/mistral-vibe/releases/download/v1.1.2/vibe-acp-darwin-x86_64-1.1.2.zip"
|
||||||
cmd = "./vibe-acp"
|
cmd = "./vibe-acp"
|
||||||
|
|
||||||
# [agent_servers.mistral-vibe.targets.linux-aarch64]
|
# [agent_servers.mistral-vibe.targets.linux-aarch64]
|
||||||
# archive = "https://github.com/mistralai/mistral-vibe/releases/download/v1.1.1/vibe-acp-linux-aarch64-1.1.1.zip"
|
# archive = "https://github.com/mistralai/mistral-vibe/releases/download/v1.1.2/vibe-acp-linux-aarch64-1.1.2.zip"
|
||||||
# cmd = "./vibe-acp"
|
# cmd = "./vibe-acp"
|
||||||
|
|
||||||
[agent_servers.mistral-vibe.targets.linux-x86_64]
|
[agent_servers.mistral-vibe.targets.linux-x86_64]
|
||||||
archive = "https://github.com/mistralai/mistral-vibe/releases/download/v1.1.1/vibe-acp-linux-x86_64-1.1.1.zip"
|
archive = "https://github.com/mistralai/mistral-vibe/releases/download/v1.1.2/vibe-acp-linux-x86_64-1.1.2.zip"
|
||||||
cmd = "./vibe-acp"
|
cmd = "./vibe-acp"
|
||||||
|
|
||||||
# [agent_servers.mistral-vibe.targets.windows-aarch64]
|
# [agent_servers.mistral-vibe.targets.windows-aarch64]
|
||||||
# archive = "https://github.com/mistralai/mistral-vibe/releases/download/v1.1.1/vibe-acp-windows-aarch64-1.1.1.zip"
|
# archive = "https://github.com/mistralai/mistral-vibe/releases/download/v1.1.2/vibe-acp-windows-aarch64-1.1.2.zip"
|
||||||
# cmd = "./vibe-acp.exe"
|
# cmd = "./vibe-acp.exe"
|
||||||
|
|
||||||
[agent_servers.mistral-vibe.targets.windows-x86_64]
|
[agent_servers.mistral-vibe.targets.windows-x86_64]
|
||||||
archive = "https://github.com/mistralai/mistral-vibe/releases/download/v1.1.1/vibe-acp-windows-x86_64-1.1.1.zip"
|
archive = "https://github.com/mistralai/mistral-vibe/releases/download/v1.1.2/vibe-acp-windows-x86_64-1.1.2.zip"
|
||||||
cmd = "./vibe-acp.exe"
|
cmd = "./vibe-acp.exe"
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
[project]
|
[project]
|
||||||
name = "mistral-vibe"
|
name = "mistral-vibe"
|
||||||
version = "1.1.1"
|
version = "1.1.2"
|
||||||
description = "Minimal CLI coding agent by Mistral"
|
description = "Minimal CLI coding agent by Mistral"
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
requires-python = ">=3.12"
|
requires-python = ">=3.12"
|
||||||
|
|
|
||||||
|
|
@ -134,9 +134,9 @@ Examples:
|
||||||
"vibe/core/__init__.py",
|
"vibe/core/__init__.py",
|
||||||
[(f'__version__ = "{current_version}"', f'__version__ = "{new_version}"')],
|
[(f'__version__ = "{current_version}"', f'__version__ = "{new_version}"')],
|
||||||
)
|
)
|
||||||
# Update tests/acp/test_acp.py
|
# Update tests/acp/test_initialize.py
|
||||||
update_hard_values_files(
|
update_hard_values_files(
|
||||||
"tests/acp/test_acp.py",
|
"tests/acp/test_initialize.py",
|
||||||
[(f'version="{current_version}"', f'version="{new_version}"')],
|
[(f'version="{current_version}"', f'version="{new_version}"')],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -17,14 +17,10 @@ from acp import (
|
||||||
WriteTextFileRequest,
|
WriteTextFileRequest,
|
||||||
)
|
)
|
||||||
from acp.schema import (
|
from acp.schema import (
|
||||||
AgentCapabilities,
|
|
||||||
AllowedOutcome,
|
AllowedOutcome,
|
||||||
DeniedOutcome,
|
DeniedOutcome,
|
||||||
Implementation,
|
|
||||||
InitializeResponse,
|
InitializeResponse,
|
||||||
McpCapabilities,
|
|
||||||
NewSessionResponse,
|
NewSessionResponse,
|
||||||
PromptCapabilities,
|
|
||||||
PromptResponse,
|
PromptResponse,
|
||||||
SessionNotification,
|
SessionNotification,
|
||||||
TextContentBlock,
|
TextContentBlock,
|
||||||
|
|
@ -324,48 +320,6 @@ async def initialize_session(acp_agent_process: asyncio.subprocess.Process) -> s
|
||||||
return session_response_obj.result.sessionId
|
return session_response_obj.result.sessionId
|
||||||
|
|
||||||
|
|
||||||
class TestInitialization:
|
|
||||||
@pytest.mark.asyncio
|
|
||||||
async def test_initialize_request_response(self) -> None:
|
|
||||||
mock_env = get_mocking_env()
|
|
||||||
async for process in get_acp_agent_process(mock_env=mock_env):
|
|
||||||
await send_json_rpc(
|
|
||||||
process,
|
|
||||||
InitializeJsonRpcRequest(
|
|
||||||
id=1, params=InitializeRequest(protocolVersion=1)
|
|
||||||
),
|
|
||||||
)
|
|
||||||
|
|
||||||
text_response = await read_response(process, timeout=10.0)
|
|
||||||
assert text_response is not None, "No response to initialize"
|
|
||||||
response_json = json.loads(text_response)
|
|
||||||
response = InitializeJsonRpcResponse.model_validate(response_json)
|
|
||||||
assert response.error is None, f"JSON-RPC error: {response.error}"
|
|
||||||
assert response.result is not None, "No result in response"
|
|
||||||
assert response.result.protocolVersion == 1
|
|
||||||
assert response.result.agentCapabilities == AgentCapabilities(
|
|
||||||
loadSession=False,
|
|
||||||
promptCapabilities=PromptCapabilities(
|
|
||||||
audio=False, embeddedContext=True, image=False
|
|
||||||
),
|
|
||||||
mcpCapabilities=McpCapabilities(http=False, sse=False),
|
|
||||||
)
|
|
||||||
assert response.result.agentInfo == Implementation(
|
|
||||||
name="@mistralai/mistral-vibe", title="Mistral Vibe", version="1.1.1"
|
|
||||||
)
|
|
||||||
vibe_setup_method = next(
|
|
||||||
(
|
|
||||||
method
|
|
||||||
for method in response.result.authMethods or []
|
|
||||||
if method.id == "vibe-setup"
|
|
||||||
),
|
|
||||||
None,
|
|
||||||
)
|
|
||||||
assert vibe_setup_method is not None, "vibe-setup auth not found"
|
|
||||||
assert vibe_setup_method.field_meta is not None
|
|
||||||
assert "terminal-auth" in vibe_setup_method.field_meta.keys()
|
|
||||||
|
|
||||||
|
|
||||||
class TestSessionManagement:
|
class TestSessionManagement:
|
||||||
@pytest.mark.asyncio
|
@pytest.mark.asyncio
|
||||||
async def test_multiple_sessions_unique_ids(self) -> None:
|
async def test_multiple_sessions_unique_ids(self) -> None:
|
||||||
|
|
|
||||||
80
tests/acp/test_initialize.py
Normal file
80
tests/acp/test_initialize.py
Normal file
|
|
@ -0,0 +1,80 @@
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from acp import PROTOCOL_VERSION, AgentSideConnection, InitializeRequest
|
||||||
|
from acp.schema import (
|
||||||
|
AgentCapabilities,
|
||||||
|
ClientCapabilities,
|
||||||
|
Implementation,
|
||||||
|
PromptCapabilities,
|
||||||
|
)
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
from tests.stubs.fake_connection import FakeAgentSideConnection
|
||||||
|
from vibe.acp.acp_agent import VibeAcpAgent
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def acp_agent() -> VibeAcpAgent:
|
||||||
|
vibe_acp_agent: VibeAcpAgent | None = None
|
||||||
|
|
||||||
|
def _create_agent(connection: AgentSideConnection) -> VibeAcpAgent:
|
||||||
|
nonlocal vibe_acp_agent
|
||||||
|
vibe_acp_agent = VibeAcpAgent(connection)
|
||||||
|
return vibe_acp_agent
|
||||||
|
|
||||||
|
FakeAgentSideConnection(_create_agent)
|
||||||
|
return vibe_acp_agent # pyright: ignore[reportReturnType]
|
||||||
|
|
||||||
|
|
||||||
|
class TestACPInitialize:
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
async def test_initialize(self, acp_agent: VibeAcpAgent) -> None:
|
||||||
|
"""Test regular initialize without terminal-auth capabilities."""
|
||||||
|
request = InitializeRequest(protocolVersion=PROTOCOL_VERSION)
|
||||||
|
response = await acp_agent.initialize(request)
|
||||||
|
|
||||||
|
assert response.protocolVersion == PROTOCOL_VERSION
|
||||||
|
assert response.agentCapabilities == AgentCapabilities(
|
||||||
|
loadSession=False,
|
||||||
|
promptCapabilities=PromptCapabilities(
|
||||||
|
audio=False, embeddedContext=True, image=False
|
||||||
|
),
|
||||||
|
)
|
||||||
|
assert response.agentInfo == Implementation(
|
||||||
|
name="@mistralai/mistral-vibe", title="Mistral Vibe", version="1.1.2"
|
||||||
|
)
|
||||||
|
|
||||||
|
assert response.authMethods == []
|
||||||
|
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
async def test_initialize_with_terminal_auth(self, acp_agent: VibeAcpAgent) -> None:
|
||||||
|
"""Test initialize with terminal-auth capabilities to check it was included."""
|
||||||
|
client_capabilities = ClientCapabilities(field_meta={"terminal-auth": True})
|
||||||
|
request = InitializeRequest(
|
||||||
|
protocolVersion=PROTOCOL_VERSION, clientCapabilities=client_capabilities
|
||||||
|
)
|
||||||
|
response = await acp_agent.initialize(request)
|
||||||
|
|
||||||
|
assert response.protocolVersion == PROTOCOL_VERSION
|
||||||
|
assert response.agentCapabilities == AgentCapabilities(
|
||||||
|
loadSession=False,
|
||||||
|
promptCapabilities=PromptCapabilities(
|
||||||
|
audio=False, embeddedContext=True, image=False
|
||||||
|
),
|
||||||
|
)
|
||||||
|
assert response.agentInfo == Implementation(
|
||||||
|
name="@mistralai/mistral-vibe", title="Mistral Vibe", version="1.1.2"
|
||||||
|
)
|
||||||
|
|
||||||
|
assert response.authMethods is not None
|
||||||
|
assert len(response.authMethods) == 1
|
||||||
|
auth_method = response.authMethods[0]
|
||||||
|
assert auth_method.id == "vibe-setup"
|
||||||
|
assert auth_method.name == "Register your API Key"
|
||||||
|
assert auth_method.description == "Register your API Key inside Mistral Vibe"
|
||||||
|
assert auth_method.field_meta is not None
|
||||||
|
assert "terminal-auth" in auth_method.field_meta
|
||||||
|
terminal_auth_meta = auth_method.field_meta["terminal-auth"]
|
||||||
|
assert "command" in terminal_auth_meta
|
||||||
|
assert "args" in terminal_auth_meta
|
||||||
|
assert terminal_auth_meta["label"] == "Mistral Vibe Setup"
|
||||||
|
|
@ -29,12 +29,14 @@ from tests.backend.data.mistral import (
|
||||||
STREAMED_TOOL_CONVERSATION_PARAMS as MISTRAL_STREAMED_TOOL_CONVERSATION_PARAMS,
|
STREAMED_TOOL_CONVERSATION_PARAMS as MISTRAL_STREAMED_TOOL_CONVERSATION_PARAMS,
|
||||||
TOOL_CONVERSATION_PARAMS as MISTRAL_TOOL_CONVERSATION_PARAMS,
|
TOOL_CONVERSATION_PARAMS as MISTRAL_TOOL_CONVERSATION_PARAMS,
|
||||||
)
|
)
|
||||||
from vibe.core.config import ModelConfig, ProviderConfig
|
from vibe.core.config import Backend, ModelConfig, ProviderConfig
|
||||||
|
from vibe.core.llm.backend.factory import BACKEND_FACTORY
|
||||||
from vibe.core.llm.backend.generic import GenericBackend
|
from vibe.core.llm.backend.generic import GenericBackend
|
||||||
from vibe.core.llm.backend.mistral import MistralBackend
|
from vibe.core.llm.backend.mistral import MistralBackend
|
||||||
from vibe.core.llm.exceptions import BackendError
|
from vibe.core.llm.exceptions import BackendError
|
||||||
from vibe.core.llm.types import BackendLike
|
from vibe.core.llm.types import BackendLike
|
||||||
from vibe.core.types import LLMChunk, LLMMessage, Role, ToolCall
|
from vibe.core.types import LLMChunk, LLMMessage, Role, ToolCall
|
||||||
|
from vibe.core.utils import get_user_agent
|
||||||
|
|
||||||
|
|
||||||
class TestBackend:
|
class TestBackend:
|
||||||
|
|
@ -246,3 +248,99 @@ class TestBackend:
|
||||||
assert e.value.status == response.status_code
|
assert e.value.status == response.status_code
|
||||||
assert e.value.reason == response.reason_phrase
|
assert e.value.reason == response.reason_phrase
|
||||||
assert e.value.parsed_error is None
|
assert e.value.parsed_error is None
|
||||||
|
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
@pytest.mark.parametrize("backend_type", [Backend.MISTRAL, Backend.GENERIC])
|
||||||
|
async def test_backend_user_agent(self, backend_type: Backend):
|
||||||
|
user_agent = get_user_agent(backend_type)
|
||||||
|
base_url = "https://api.example.com"
|
||||||
|
json_response = {
|
||||||
|
"id": "fake_id_1234",
|
||||||
|
"created": 1234567890,
|
||||||
|
"model": "devstral-latest",
|
||||||
|
"usage": {
|
||||||
|
"prompt_tokens": 100,
|
||||||
|
"total_tokens": 300,
|
||||||
|
"completion_tokens": 200,
|
||||||
|
},
|
||||||
|
"object": "chat.completion",
|
||||||
|
"choices": [
|
||||||
|
{
|
||||||
|
"index": 0,
|
||||||
|
"finish_reason": "stop",
|
||||||
|
"message": {
|
||||||
|
"role": "assistant",
|
||||||
|
"tool_calls": None,
|
||||||
|
"content": "Hey",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
],
|
||||||
|
}
|
||||||
|
with respx.mock(base_url=base_url) as mock_api:
|
||||||
|
mock_api.post("/v1/chat/completions").mock(
|
||||||
|
return_value=httpx.Response(status_code=200, json=json_response)
|
||||||
|
)
|
||||||
|
|
||||||
|
provider = ProviderConfig(
|
||||||
|
name="provider_name",
|
||||||
|
api_base=f"{base_url}/v1",
|
||||||
|
api_key_env_var="API_KEY",
|
||||||
|
)
|
||||||
|
backend = BACKEND_FACTORY[backend_type](provider=provider)
|
||||||
|
model = ModelConfig(
|
||||||
|
name="model_name", provider="provider_name", alias="model_alias"
|
||||||
|
)
|
||||||
|
messages = [LLMMessage(role=Role.user, content="Just say hi")]
|
||||||
|
|
||||||
|
await backend.complete(
|
||||||
|
model=model,
|
||||||
|
messages=messages,
|
||||||
|
temperature=0.2,
|
||||||
|
tools=None,
|
||||||
|
max_tokens=None,
|
||||||
|
tool_choice=None,
|
||||||
|
extra_headers={"user-agent": user_agent},
|
||||||
|
)
|
||||||
|
|
||||||
|
assert mock_api.calls.last.request.headers["user-agent"] == user_agent
|
||||||
|
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
@pytest.mark.parametrize("backend_type", [Backend.MISTRAL, Backend.GENERIC])
|
||||||
|
async def test_backend_user_agent_when_streaming(self, backend_type: Backend):
|
||||||
|
user_agent = get_user_agent(backend_type)
|
||||||
|
|
||||||
|
base_url = "https://api.example.com"
|
||||||
|
with respx.mock(base_url=base_url) as mock_api:
|
||||||
|
chunks = [
|
||||||
|
rb'data: {"id":"fake_id_1234","object":"chat.completion.chunk","created":1234567890,"model":"devstral-latest","choices":[{"index":0,"delta":{"role":"assistant","content":"Hey"},"finish_reason":"stop"}]}'
|
||||||
|
]
|
||||||
|
mock_response = httpx.Response(
|
||||||
|
status_code=200,
|
||||||
|
stream=httpx.ByteStream(stream=b"\n\n".join(chunks)),
|
||||||
|
headers={"Content-Type": "text/event-stream"},
|
||||||
|
)
|
||||||
|
mock_api.post("/v1/chat/completions").mock(return_value=mock_response)
|
||||||
|
|
||||||
|
provider = ProviderConfig(
|
||||||
|
name="provider_name",
|
||||||
|
api_base=f"{base_url}/v1",
|
||||||
|
api_key_env_var="API_KEY",
|
||||||
|
)
|
||||||
|
backend = BACKEND_FACTORY[backend_type](provider=provider)
|
||||||
|
model = ModelConfig(
|
||||||
|
name="model_name", provider="provider_name", alias="model_alias"
|
||||||
|
)
|
||||||
|
messages = [LLMMessage(role=Role.user, content="Just say hi")]
|
||||||
|
|
||||||
|
async for _ in backend.complete_streaming(
|
||||||
|
model=model,
|
||||||
|
messages=messages,
|
||||||
|
temperature=0.2,
|
||||||
|
tools=None,
|
||||||
|
max_tokens=None,
|
||||||
|
tool_choice=None,
|
||||||
|
extra_headers={"user-agent": user_agent},
|
||||||
|
):
|
||||||
|
pass
|
||||||
|
|
||||||
|
assert mock_api.calls.last.request.headers["user-agent"] == user_agent
|
||||||
|
|
|
||||||
2
uv.lock
generated
2
uv.lock
generated
|
|
@ -661,7 +661,7 @@ wheels = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "mistral-vibe"
|
name = "mistral-vibe"
|
||||||
version = "1.1.1"
|
version = "1.1.2"
|
||||||
source = { editable = "." }
|
source = { editable = "." }
|
||||||
dependencies = [
|
dependencies = [
|
||||||
{ name = "agent-client-protocol" },
|
{ name = "agent-client-protocol" },
|
||||||
|
|
|
||||||
|
|
@ -100,7 +100,14 @@ class VibeAcpAgent(AcpAgent):
|
||||||
script_name = sys.argv[0]
|
script_name = sys.argv[0]
|
||||||
args = [script_name, "--setup"]
|
args = [script_name, "--setup"]
|
||||||
|
|
||||||
auth_methods = [
|
supports_terminal_auth = (
|
||||||
|
self.client_capabilities
|
||||||
|
and self.client_capabilities.field_meta
|
||||||
|
and self.client_capabilities.field_meta.get("terminal-auth") is True
|
||||||
|
)
|
||||||
|
|
||||||
|
auth_methods = (
|
||||||
|
[
|
||||||
AuthMethod(
|
AuthMethod(
|
||||||
id="vibe-setup",
|
id="vibe-setup",
|
||||||
name="Register your API Key",
|
name="Register your API Key",
|
||||||
|
|
@ -114,6 +121,9 @@ class VibeAcpAgent(AcpAgent):
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
|
if supports_terminal_auth
|
||||||
|
else []
|
||||||
|
)
|
||||||
|
|
||||||
response = InitializeResponse(
|
response = InitializeResponse(
|
||||||
agentCapabilities=AgentCapabilities(
|
agentCapabilities=AgentCapabilities(
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
__all__ = ["__version__", "run_programmatic"]
|
__all__ = ["__version__", "run_programmatic"]
|
||||||
__version__ = "1.1.1"
|
__version__ = "1.1.2"
|
||||||
|
|
||||||
from vibe.core.programmatic import run_programmatic
|
from vibe.core.programmatic import run_programmatic
|
||||||
|
|
|
||||||
|
|
@ -625,7 +625,7 @@ class Agent:
|
||||||
tools=available_tools,
|
tools=available_tools,
|
||||||
tool_choice=tool_choice,
|
tool_choice=tool_choice,
|
||||||
extra_headers={
|
extra_headers={
|
||||||
"User-Agent": get_user_agent(),
|
"user-agent": get_user_agent(provider.backend),
|
||||||
"x-affinity": self.session_id,
|
"x-affinity": self.session_id,
|
||||||
},
|
},
|
||||||
max_tokens=max_tokens,
|
max_tokens=max_tokens,
|
||||||
|
|
@ -682,7 +682,7 @@ class Agent:
|
||||||
tools=available_tools,
|
tools=available_tools,
|
||||||
tool_choice=tool_choice,
|
tool_choice=tool_choice,
|
||||||
extra_headers={
|
extra_headers={
|
||||||
"User-Agent": get_user_agent(),
|
"user-agent": get_user_agent(provider.backend),
|
||||||
"x-affinity": self.session_id,
|
"x-affinity": self.session_id,
|
||||||
},
|
},
|
||||||
max_tokens=max_tokens,
|
max_tokens=max_tokens,
|
||||||
|
|
@ -903,6 +903,7 @@ class Agent:
|
||||||
self.messages = [system_message, summary_message]
|
self.messages = [system_message, summary_message]
|
||||||
|
|
||||||
active_model = self.config.get_active_model()
|
active_model = self.config.get_active_model()
|
||||||
|
provider = self.config.get_provider_for_model(active_model)
|
||||||
|
|
||||||
async with self.backend as backend:
|
async with self.backend as backend:
|
||||||
actual_context_tokens = await backend.count_tokens(
|
actual_context_tokens = await backend.count_tokens(
|
||||||
|
|
@ -911,7 +912,7 @@ class Agent:
|
||||||
tools=self.format_handler.get_available_tools(
|
tools=self.format_handler.get_available_tools(
|
||||||
self.tool_manager, self.config
|
self.tool_manager, self.config
|
||||||
),
|
),
|
||||||
extra_headers={"User-Agent": get_user_agent()},
|
extra_headers={"user-agent": get_user_agent(provider.backend)},
|
||||||
)
|
)
|
||||||
|
|
||||||
self.stats.context_tokens = actual_context_tokens
|
self.stats.context_tokens = actual_context_tokens
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ from typing import Any
|
||||||
import httpx
|
import httpx
|
||||||
|
|
||||||
from vibe.core import __version__
|
from vibe.core import __version__
|
||||||
from vibe.core.config import CONFIG_DIR, CONFIG_FILE, GLOBAL_CONFIG_FILE
|
from vibe.core.config import CONFIG_DIR, CONFIG_FILE, GLOBAL_CONFIG_FILE, Backend
|
||||||
from vibe.core.types import BaseEvent, ToolResultEvent
|
from vibe.core.types import BaseEvent, ToolResultEvent
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -160,8 +160,12 @@ if CONFIG_FILE != GLOBAL_CONFIG_FILE and GLOBAL_CONFIG_FILE.is_file():
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def get_user_agent() -> str:
|
def get_user_agent(backend: Backend) -> str:
|
||||||
return f"Mistral-Vibe/{__version__}"
|
user_agent = f"Mistral-Vibe/{__version__}"
|
||||||
|
if backend == Backend.MISTRAL:
|
||||||
|
mistral_sdk_prefix = "mistral-client-python/"
|
||||||
|
user_agent = f"{mistral_sdk_prefix}{user_agent}"
|
||||||
|
return user_agent
|
||||||
|
|
||||||
|
|
||||||
def _is_retryable_http_error(e: Exception) -> bool:
|
def _is_retryable_http_error(e: Exception) -> bool:
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue