Co-authored-by: Guillaume LE GOFF <guillaume.lgf@gmail.com>
Co-authored-by: Michel Thomazo <51709227+michelTho@users.noreply.github.com>
Co-authored-by: Pierre Rossinès <pierre.rossines@mistral.ai>
Co-authored-by: Val <102326092+vdeva@users.noreply.github.com>
Co-authored-by: Vincent G <10739306+VinceOPS@users.noreply.github.com>
Co-authored-by: Mistral Vibe <vibe@mistral.ai>
This commit is contained in:
Clément Drouin 2026-05-20 11:39:59 +02:00 committed by GitHub
parent 228f3c65a9
commit f71bfd3b8c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
57 changed files with 2950 additions and 402 deletions

View file

@ -123,7 +123,10 @@ from vibe.core.agent_loop import AgentLoop, TeleportError
from vibe.core.agents import AgentProfile
from vibe.core.audio_player.audio_player import AudioPlayer
from vibe.core.audio_recorder import AudioRecorder
from vibe.core.autocompletion.path_prompt import build_path_prompt_payload
from vibe.core.autocompletion.path_prompt import (
build_path_prompt_payload,
build_title_segments,
)
from vibe.core.autocompletion.path_prompt_adapter import render_path_prompt
from vibe.core.config import VibeConfig
from vibe.core.data_retention import DATA_RETENTION_MESSAGE
@ -140,6 +143,7 @@ from vibe.core.session.resume_sessions import (
)
from vibe.core.session.saved_sessions import update_saved_session_title_at_path
from vibe.core.session.session_loader import SessionLoader
from vibe.core.session.title_format import format_session_title
from vibe.core.skills.manager import SkillManager
from vibe.core.teleport.telemetry import send_teleport_early_failure_telemetry
from vibe.core.teleport.types import (
@ -957,7 +961,7 @@ class VibeApp(App): # noqa: PLR0904
self.agent_loop.telemetry_client.send_slash_command_used(skill.name, "skill")
prompt = SkillManager.build_skill_prompt(user_input, skill)
await self._handle_user_message(prompt)
await self._handle_user_message(prompt, title_source=user_input)
return True
@staticmethod
@ -1146,7 +1150,9 @@ class VibeApp(App): # noqa: PLR0904
return "\n\n".join(sections)
async def _handle_user_message(self, message: str) -> None:
async def _handle_user_message(
self, message: str, *, title_source: str | None = None
) -> None:
if self._remote_manager.is_active:
await self._handle_remote_user_message(message)
return
@ -1165,7 +1171,7 @@ class VibeApp(App): # noqa: PLR0904
await self._remote_manager.stop_stream()
await self._remove_loading_widget()
self._agent_task = asyncio.create_task(
self._handle_agent_loop_turn(message)
self._handle_agent_loop_turn(message, title_source=title_source)
)
async def _handle_remote_user_message(self, message: str) -> None:
@ -1366,7 +1372,9 @@ class VibeApp(App): # noqa: PLR0904
event, loading_widget=self._loading_widget
)
async def _handle_agent_loop_turn(self, prompt: str) -> None:
async def _handle_agent_loop_turn(
self, prompt: str, *, title_source: str | None = None
) -> None:
self._agent_running = True
await self._remove_loading_widget()
@ -1393,10 +1401,22 @@ class VibeApp(App): # noqa: PLR0904
message_id=message_id,
)
rendered_prompt = render_path_prompt(prompt, base_dir=Path.cwd())
auto_title: str | None = None
if self.agent_loop.session_logger.needs_initial_auto_title():
auto_title = (
format_session_title(
build_title_segments(
title_source or prompt, base_dir=Path.cwd()
)
)
or None
)
self._narrator_manager.cancel()
self._narrator_manager.on_turn_start(rendered_prompt)
async with aclosing(
self.agent_loop.act(rendered_prompt, client_message_id=message_id)
self.agent_loop.act(
rendered_prompt, client_message_id=message_id, auto_title=auto_title
)
) as events:
await self._handle_agent_loop_events(events)
except asyncio.CancelledError:

View file

@ -33,6 +33,7 @@ from vibe.core.types import (
PlanReviewEndedEvent,
PlanReviewRequestedEvent,
ReasoningEvent,
SessionTitleUpdatedEvent,
ToolCallEvent,
ToolResultEvent,
ToolStreamEvent,
@ -116,6 +117,8 @@ class EventHandler:
case AgentProfileChangedEvent():
if self.on_profile_changed:
self.on_profile_changed()
case SessionTitleUpdatedEvent():
pass
case UserMessageEvent():
await self.finalize_streaming()
if self.is_remote:

View file

@ -71,6 +71,7 @@ _LIST_VIEW_HELP_AUTH = (
_DETAIL_VIEW_HELP = (
"↑↓ Navigate D Disable E Enable Backspace Back R Refresh Esc Close"
)
_DETAIL_VIEW_HELP_NO_TOOLS = "↑↓ Navigate Backspace Back R Refresh Esc Close"
class MCPApp(Container):
@ -211,7 +212,16 @@ class MCPApp(Container):
return
self._status_message = "Refreshing..."
help = _DETAIL_VIEW_HELP if self._viewing_server else _LIST_VIEW_HELP_TOOLS
if self._viewing_server:
tools_source = (
self._index.connector_tools
if self._viewing_kind == MCPSourceKind.CONNECTOR
else self._index.server_tools
)
all_tools = tools_source.get(self._viewing_server, [])
help = _DETAIL_VIEW_HELP if all_tools else _DETAIL_VIEW_HELP_NO_TOOLS
else:
help = _LIST_VIEW_HELP_TOOLS
self._set_help_text(help)
self._refreshing = True
@ -516,9 +526,11 @@ class MCPApp(Container):
self.query_one("#mcp-title", NoMarkupStatic).update(
f"{title_prefix}: {server_name}"
)
self._set_help_text(_DETAIL_VIEW_HELP)
tools_source = index.connector_tools if is_connector else index.server_tools
all_tools = sorted(tools_source.get(server_name, []), key=lambda t: t[0])
self._set_help_text(
_DETAIL_VIEW_HELP if all_tools else _DETAIL_VIEW_HELP_NO_TOOLS
)
if not all_tools:
if (
is_connector