Co-authored-by: Antoine <33425718+anth2o@users.noreply.github.com>
Co-authored-by: Bastien <bastien.baret@gmail.com>
Co-authored-by: Clément Sirieix <clement.sirieix@mistral.ai>
Co-authored-by: Kim-Adeline Miguel <51720070+kimadeline@users.noreply.github.com>
Co-authored-by: Mathias Gesbert <mathias.gesbert@mistral.ai>
Co-authored-by: Maxime Dolores <maxime.dolores@ext.mistral.ai>
Co-authored-by: Michel Thomazo <51709227+michelTho@users.noreply.github.com>
Co-authored-by: Nelson PROIA <144663685+Nelson-PROIA@users.noreply.github.com>
Co-authored-by: Pierre Rossinès <pierre.rossines@mistral.ai>
Co-authored-by: Quentin <quentin.torroba@mistral.ai>
Co-authored-by: Robin Gullo <robin.gullo@mistral.ai>
Co-authored-by: Mistral Vibe <vibe@mistral.ai>
This commit is contained in:
Clément Drouin 2026-04-28 17:44:07 +02:00 committed by GitHub
parent a83c81ecf5
commit 632ea8c032
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
253 changed files with 13965 additions and 2525 deletions

244
AGENTS.md
View file

@ -1,181 +1,101 @@
# python312.rule
# Rule for enforcing modern Python 3.12+ best practices.
# Applies to all Python files (*.py) in the project.
#
# Guidelines covered:
# - Use match-case syntax instead of if/elif/else for pattern matching.
# - Use the walrus operator (:=) when it simplifies assignments and tests.
# - Favor a "never nester" approach by avoiding deep nesting with early returns or guard clauses.
# - Employ modern type hints using built-in generics (list, dict) and the union pipe (|) operator,
# rather than deprecated types from the typing module (e.g., Optional, Union, Dict, List).
# - Ensure code adheres to strong static typing practices compatible with static analyzers like pyright.
# - Favor pathlib.Path methods for file system operations over older os.path functions.
# - Write code in a declarative and minimalist style that clearly expresses its intent.
# - Additional best practices including f-string formatting, comprehensions, context managers, and overall PEP 8 compliance.
# AGENTS.md
description: "Modern Python 3.12+ best practices and style guidelines for coding."
files: "**/*.py"
Conventions for AI agents and humans contributing to **Mistral Vibe** — a Python 3.12+ CLI coding assistant managed with `uv`.
guidelines:
- title: "Match-Case Syntax"
description: >
Prefer using the match-case construct over traditional if/elif/else chains when pattern matching
is applicable. This leads to clearer, more concise, and more maintainable code.
Layout: `vibe/core` is the engine (agent loop, tools, LLM backends, config); `vibe/cli` is the Textual TUI; `vibe/acp` bridges to the Agent Client Protocol; `vibe/setup` runs first-run wizards. Tests live in `tests/` with autouse fixtures in `conftest.py` and test doubles in `tests/stubs/`.
- title: "Walrus Operator"
description: >
Utilize the walrus operator (:=) to streamline code where assignment and conditional testing can be combined.
Use it judiciously when it improves readability and reduces redundancy.
## Commands
- title: "Never Nester"
description: >
Aim to keep code flat by avoiding deep nesting. Use early returns, guard clauses, and refactoring to
minimize nested structures, making your code more readable and maintainable.
Always go through `uv` — never invoke bare `python` or `pip`.
- title: "Modern Type Hints"
description: >
Adopt modern type hinting by using built-in generics like list and dict, along with the pipe (|) operator
for union types (e.g., int | None). Avoid older, deprecated constructs such as Optional, Union, Dict, and List
from the typing module.
- `uv run vibe` / `uv run vibe-acp` — the two entry points.
- `uv run pytest` — full suite (parallel via `pytest-xdist`).
- `uv run pyright` — strict type check.
- `uv run ruff check --fix .` and `uv run ruff format .` — run both after every code change and report the files modified.
- `uv run pre-commit run --all-files` — full lint pass. Install once with `uv tool install pre-commit && uv run pre-commit install`.
- Useful uv basics: `uv sync --all-extras`, `uv add <pkg>`, `uv remove <pkg>`.
- title: "Strong Static Typing"
description: >
Write code with explicit and robust type annotations that are fully compatible with static type checkers
like pyright. This ensures higher code reliability and easier maintenance.
## Project layout & module conventions
- title: "Pydantic-First Parsing"
description: >
Prefer Pydantic v2's native validation over ad-hoc parsing. Use `model_validate`,
`field_validator`, `from_attributes`, and field aliases to coerce external SDK/DTO objects.
Avoid manual `getattr`/`hasattr` flows and custom constructors like `from_sdk` unless they are
thin wrappers over `model_validate`. Keep normalization logic inside model validators so call sites
remain declarative and typed.
- `__init__.py` exposes the public API via an explicit `__all__`.
- Private modules are prefixed with `_` (e.g. `_settings.py`, `_config.py`).
- Pydantic models live in `models.py`; configuration in `_settings.py` / `_config.py`.
- Abstract interfaces use the `_port.py` suffix (hexagonal-style ports).
- Tests mirror the source layout; test doubles in `tests/stubs/` are named `Fake*`.
- title: "Pathlib for File Operations"
description: >
Favor the use of pathlib.Path methods for file system operations. This approach offers a more
readable, object-oriented way to handle file paths and enhances cross-platform compatibility,
reducing reliance on legacy os.path functions.
## Python style
- title: "Declarative and Minimalist Code"
description: >
Write code that is declarative—clearly expressing its intentions rather than focusing on implementation details.
Strive to keep your code minimalist by removing unnecessary complexity and boilerplate. This approach improves
readability, maintainability, and aligns with modern Python practices.
- Prefer `match` / `case` over long `if` / `elif` chains.
- Use the walrus operator `:=` only when it shortens code and improves clarity.
- Be a never-nester: early returns and guard clauses over nested blocks.
- Modern type hints only: built-in generics (`list`, `dict`) and `|` unions. Never import `Optional`, `Union`, `Dict`, `List` from `typing`.
- Use `pathlib.Path` (and `anyio.Path` in async paths) instead of `os.path`.
- Use f-strings, comprehensions, and context managers; follow PEP 8.
- Enums: `StrEnum` / `IntEnum` with `auto()` and UPPERCASE members. For type-mixing, the mix-in type comes before `Enum` in the bases. Add methods or `@property` rather than parallel lookup tables.
- Write declarative, minimalist code: express intent, drop boilerplate.
- Never call a private method from outside of it's class
- title: "Additional Best Practices"
description: >
Embrace other modern Python idioms such as:
- Using f-strings for string formatting.
- Favoring comprehensions for building lists and dictionaries.
- Employing context managers (with statements) for resource management.
- Following PEP 8 guidelines to maintain overall code style consistency.
## Typing & imports
- title: "Exception Documentation"
description: >
Document exceptions accurately and minimally in docstrings:
- Only document exceptions that are explicitly raised in the function implementation
- Remove Raises entries for exceptions that are not directly raised
- Include all possible exceptions from explicit raise statements
- For public APIs, document exceptions from called functions if they are allowed to propagate
- Avoid documenting built-in exceptions that are obvious (like TypeError from type hints)
This ensures documentation stays accurate and maintainable, avoiding the common pitfall
of listing every possible exception that could theoretically occur.
- Pyright is strict and gates CI; fix types at the source.
- No relative imports — `ban-relative-imports = "all"`. Always `from vibe.core.x import …`.
- No inline `# type: ignore` or `# noqa`. Fix with refined signatures (TypeVar, Protocol), `isinstance` guards, `typing.cast` when control flow guarantees the type, or a small typed wrapper at the boundary.
- title: "Modern Enum Usage"
description: >
Leverage Python's enum module effectively following modern practices:
- Use StrEnum for string-based enums that need string comparison
- Use IntEnum/IntFlag for performance-critical integer-based enums
- Use auto() for automatic value assignment to maintain clean code
- Always use UPPERCASE for enum members to avoid name clashes
- Add methods to enums when behavior needs to be associated with values
- Use @property for computed attributes rather than storing values
- For type mixing, ensure mix-in types appear before Enum in base class sequence
- Consider Flag/IntFlag for bit field operations
- Use _generate_next_value_ for custom value generation
- Implement __bool__ when enum boolean evaluation should depend on value
This promotes type-safe constants, self-documenting code, and maintainable value sets.
## Pydantic
- title: "No Inline Ignores"
description: >
Do not use inline suppressions like `# type: ignore[...]` or `# noqa[...]` in production code.
Instead, fix types and lint warnings at the source by:
- Refining signatures with generics (TypeVar), Protocols, or precise return types
- Guarding with `isinstance` checks before attribute access
- Using `typing.cast` when control flow guarantees the type
- Extracting small helpers to create clearer, typed boundaries
If a suppression is truly unavoidable at an external boundary, prefer a narrow, well-typed wrapper
over in-line ignores, and document the rationale in code comments.
- Parse external data via `model_validate`, `field_validator`, or `model_validator(mode="before")` — never ad-hoc `getattr` / `hasattr` walks or custom `from_sdk` constructors.
- Set `ConfigDict(extra=…)` explicitly. Use `validation_alias` (or field aliases) for kebab-case TOML keys.
- Discriminated unions (e.g. MCP `transport`): use sibling final classes plus a shared base/mixin, and compose with `Annotated[Union[...], Field(discriminator=...)]`. Never narrow the discriminator field in a subclass — it violates LSP and pyright will reject it.
- Document `Raises:` only for exceptions the function actually raises (or that propagate from public API calls). Don't list speculative built-ins.
- title: "Pydantic Discriminated Unions"
description: >
When modeling variants with a discriminated union (e.g., on a `transport` field), do not narrow a
field type in a subclass (e.g., overriding `transport: Literal['http']` with `Literal['streamable-http']`).
This violates Liskov substitution and triggers type checker errors due to invariance of class attributes.
Prefer sibling classes plus a shared mixin for common fields and helpers, and compose the union with
`Annotated[Union[...], Field(discriminator='transport')]`.
Example pattern:
- Create a base with shared non-discriminator fields (e.g., `_MCPBase`).
- Create a mixin with protocol-specific fields/methods (e.g., `_MCPHttpFields`), without a `transport`.
- Define sibling final classes per variant (e.g., `MCPHttp`, `MCPStreamableHttp`, `MCPStdio`) that set
`transport: Literal[...]` once in each final class.
- Use `match` on the discriminator to narrow types at call sites.
## Async
- title: "Use uv for All Commands"
description: >
We use uv to manage our python environment. You should never try to run bare python commands.
Always run commands using `uv` instead of invoking `python` or `pip` directly.
For example, use `uv add package` and `uv run script.py` rather than `pip install package` or `python script.py`.
This practice helps avoid environment drift and leverages modern Python packaging best practices.
Useful uv commands are:
- uv add/remove <package> to manage dependencies
- uv sync to install dependencies declared in pyproject.toml and uv.lock
- uv run script.py to run a script within the uv environment
- uv run pytest (or any other python tool) to run the tool within the uv environment
- `asyncio` is the orchestration runtime in the agent loop and tool execution. Use `asyncio.create_task` + queues for concurrent work, not blanket `gather`.
- Use `anyio.Path` for file I/O on async paths.
- Streaming surfaces return `AsyncGenerator[Event, None]`, not coroutines.
- HTTP via `httpx.AsyncClient`; mock with `respx` in tests.
- title: "Safe File Reading"
description: >
When reading files from disk, prefer the helpers in `vibe.core.utils.io` over raw
`Path.read_text()`, `Path.read_bytes().decode()`, or `open()` calls:
- `read_safe(path)` — synchronous read with automatic encoding detection.
- `read_safe_async(path)` — async equivalent (anyio-based).
- `decode_safe(raw)` — decode an already-read `bytes` object.
These functions try UTF-8 first, then BOM detection, the locale encoding, and
`charset_normalizer` (lazily, only when cheaper candidates fail). They return a
`ReadSafeResult(text, encoding)` so callers always get valid `str` output without
having to handle encoding errors manually.
Use `raise_on_error=True` only when the caller must distinguish corrupt files from
valid ones; the default (`False`) replaces undecodable bytes with U+FFFD.
## Tools
- title: "Imports in Cursor (no Pylance)"
description: >
Cursor's built-in Pyright does not offer the "Add import" quick fix (Ctrl+.). To add a missing import:
- Use the workspace snippets: type the prefix (e.g. acpschema, acphelpers, vibetypes, vibeconfig) and accept the suggestion to insert the import line, then change the symbol name.
- Or ask Cursor: select the undefined symbol, then Cmd+K and request "Add the missing import for <symbol>".
- Or copy the import from an existing file in the repo (e.g. acp.schema, acp.helpers, vibe.core.*).
- Subclass `BaseTool` from `vibe/core/tools/base.py` with a Pydantic args model and a `BaseToolConfig` generic parameter.
- Implement `async def run(args, ctx: InvokeContext)` and yield events progressively.
- Raise `ToolError` for user-facing failures; raise `ToolPermissionError` for authorization failures.
- Declare permission with `ToolPermission` (`ALWAYS` / `ASK` / `NEVER`); honor it consistently.
- title: "Keep Builtin Vibe Skill Up-to-Date"
description: >
The file `vibe/core/skills/builtins/vibe.py` is the builtin self-awareness skill.
It documents the CLI's features for the model: config.toml fields, CLI parameters, slash
commands, agents, skills, tools, VIBE_HOME structure, and environment variables.
When you change any of the following, update `vibe/core/skills/builtins/vibe.py`
to reflect the new behavior:
- CLI arguments or flags (vibe/cli/entrypoint.py)
- config.toml fields or defaults (vibe/core/config/_settings.py)
- Slash commands (vibe/cli/commands.py)
- Built-in agents (vibe/core/agents/)
- VIBE_HOME directory layout or paths (vibe/core/paths/)
- Skill, tool, or agent discovery logic
- Environment variables
If in doubt, read the skill file and check whether your change makes any section stale.
## Logging & errors
- title: "No Docstrings in Tests"
description: >
Do not add docstrings to test functions, test methods, or test classes.
Test names should be descriptive enough to convey intent (e.g.,
`test_create_user_returns_403_when_unauthorized`). Docstrings in tests add
noise, duplicate the function name, and can suppress pytest's default output
(pytest displays the docstring instead of the node id when one is present).
Use inline comments sparingly for non-obvious setup or assertions instead.
- Use `from vibe.core.logger import logger` — stdlib `logging` with `StructuredLogFormatter`, not `structlog`.
- Configure via env: `LOG_LEVEL` (default `WARNING`), `DEBUG_MODE`, `LOG_MAX_BYTES`. Logs land in `~/.vibe/logs/vibe.log`.
- Pass variables as keyword args, not interpolated into the message: prefer `logger.error("Failed to fetch", url=url)` over `logger.error(f"Failed to fetch {url}")`.
- Define module-local exception hierarchies. Always chain with `raise NewError(...) from e`. Rich exceptions expose a `_fmt()` helper for human-readable output.
## File I/O
- Prefer `vibe.core.utils.io.read_safe` / `read_safe_async` / `decode_safe` over raw `Path.read_text()`, `Path.read_bytes().decode()`, or `open()`.
- They return `ReadSafeResult(text, encoding)` and try UTF-8, then BOM detection, then locale, then `charset_normalizer` lazily.
- Pass `raise_on_error=True` only when callers must distinguish corrupt files from valid ones; the default replaces undecodable bytes with U+FFFD.
## Tests
- Stack: `pytest` + `pytest-asyncio` + `pytest-textual-snapshot` + `respx`.
- Mark async tests with `@pytest.mark.asyncio`. Mock outbound HTTP with `respx`.
- Rely on the autouse fixtures in `tests/conftest.py` (`config_dir`, `tmp_working_directory`) for filesystem and home-dir isolation.
- No docstrings on test functions, methods, or classes — descriptive names like `test_create_user_returns_403_when_unauthorized` carry the intent. Pytest displays docstrings instead of node IDs when present, which hurts.
- Tests are exempt from the `ANN` and `PLR` ruff rules (see `per-file-ignores`).
## Git
- Never use `git commit --amend`, `git push --force`, or `git push --force-with-lease`.
- Always create new commits and push with a plain `git push`.
- If a push is rejected due to upstream changes, rebase onto the updated remote branch — never merge and never force-push.
## Editor tip
In Cursor / Pyright, the "Add import" quick fix is missing — use the workspace snippets `acpschema`, `acphelpers`, `vibetypes`, `vibeconfig` to insert the import line, then rename the symbol.
## Autoimprovement
- Suggest to add new rules to AGENTS.md based on user input or PR comments, when a change request could be generalized as a rule.
- Suggest updates to the README.md file according to feature changes or additions
- Keep the builtin Vibe Skill (`vibe/core/skills/builtins/vibe.py`) up-to-date. It documents the CLI's features, such as args, flags, config options and persistence, commands, built-in agents, file discovery logic.

View file

@ -5,6 +5,51 @@ 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/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [2.9.0] - 2026-04-28
### Added
- Scratchpad directory for temporary working files shared with subagents
- `/copy` slash command
- Experimental hooks system with post-agent-turn lifecycle
- OpenAI Responses API adapter
- ACP session fork and session close support
- Thinking level picker in ACP CLI
- `--trust` session-only flag and fail-fast behavior in `-p` mode
- Opus 4.7 model support
- `ConfigLayer` for layered configuration resolution
- `~/.vibe/prompts` overrides for builtin prompts
- Enable/disable MCP servers and individual tools from `/mcp` menu
- Custom compaction instructions via `/compact`
- `vibe.ready` telemetry event
- Usage updates sent after every LLM turn for ACP
- Headless section in system prompt to prevent bad model behavior
### Changed
- Renamed `auto_approve` config to `bypass_tool_permissions`
- Increased feedback bar frequency with cooldown and TOML cache
- Feedback bar only shown when active model is Mistral
- Centralized telemetry metadata construction and wired through entrypoints
- Preserved stable session identity across compact/fork/rewind
- Filtered remote sessions by current user and deduped continue-as-new
- `--continue` now only looks for sessions of the current working directory
- Batched widget mounts and narrowed CSS selectors for UI performance
### Fixed
- Autocomplete popup height calculation for wrapped lines
- Autocomplete popup dismissed on tab completion and escape
- Double Ctrl+C/Ctrl+D required to quit instead of killing session immediately
- Context window overrun now shows a friendly error message
- `MallocStackLogging` error messages suppressed in CLI input
- `index.lock` leftover on interrupted deferred init
- Safe `find` commands allowed by default
- Session ID preserved when resuming sessions through ACP
- Usage updates sent after tool results instead of tool streams in ACP
- KV cache warming via x-affinity in count tokens
## [2.8.1] - 2026-04-21
### Fixed
@ -457,7 +502,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Bumped agent-client-protocol to 0.7.1
- Refactored UI to require AgentLoop at VibeApp construction
- Updated README with new MCP server config
- Improved readability of the AskUserQuerstion tool output
- Improved readability of the AskUserQuestion tool output
### Fixed

View file

@ -1,7 +1,7 @@
id = "mistral-vibe"
name = "Mistral Vibe"
description = "Mistral's open-source coding assistant"
version = "2.8.1"
version = "2.9.0"
schema_version = 1
authors = ["Mistral AI"]
repository = "https://github.com/mistralai/mistral-vibe"
@ -11,25 +11,25 @@ name = "Mistral Vibe"
icon = "./icons/mistral_vibe.svg"
[agent_servers.mistral-vibe.targets.darwin-aarch64]
archive = "https://github.com/mistralai/mistral-vibe/releases/download/v2.8.1/vibe-acp-darwin-aarch64-2.8.1.zip"
archive = "https://github.com/mistralai/mistral-vibe/releases/download/v2.9.0/vibe-acp-darwin-aarch64-2.9.0.zip"
cmd = "./vibe-acp"
[agent_servers.mistral-vibe.targets.darwin-x86_64]
archive = "https://github.com/mistralai/mistral-vibe/releases/download/v2.8.1/vibe-acp-darwin-x86_64-2.8.1.zip"
archive = "https://github.com/mistralai/mistral-vibe/releases/download/v2.9.0/vibe-acp-darwin-x86_64-2.9.0.zip"
cmd = "./vibe-acp"
[agent_servers.mistral-vibe.targets.linux-aarch64]
archive = "https://github.com/mistralai/mistral-vibe/releases/download/v2.8.1/vibe-acp-linux-aarch64-2.8.1.zip"
archive = "https://github.com/mistralai/mistral-vibe/releases/download/v2.9.0/vibe-acp-linux-aarch64-2.9.0.zip"
cmd = "./vibe-acp"
[agent_servers.mistral-vibe.targets.linux-x86_64]
archive = "https://github.com/mistralai/mistral-vibe/releases/download/v2.8.1/vibe-acp-linux-x86_64-2.8.1.zip"
archive = "https://github.com/mistralai/mistral-vibe/releases/download/v2.9.0/vibe-acp-linux-x86_64-2.9.0.zip"
cmd = "./vibe-acp"
[agent_servers.mistral-vibe.targets.windows-aarch64]
archive = "https://github.com/mistralai/mistral-vibe/releases/download/v2.8.1/vibe-acp-windows-aarch64-2.8.1.zip"
archive = "https://github.com/mistralai/mistral-vibe/releases/download/v2.9.0/vibe-acp-windows-aarch64-2.9.0.zip"
cmd = "./vibe-acp.exe"
[agent_servers.mistral-vibe.targets.windows-x86_64]
archive = "https://github.com/mistralai/mistral-vibe/releases/download/v2.8.1/vibe-acp-windows-x86_64-2.8.1.zip"
archive = "https://github.com/mistralai/mistral-vibe/releases/download/v2.9.0/vibe-acp-windows-x86_64-2.9.0.zip"
cmd = "./vibe-acp.exe"

View file

@ -1,6 +1,6 @@
[project]
name = "mistral-vibe"
version = "2.8.1"
version = "2.9.0"
description = "Minimal CLI coding agent by Mistral"
readme = "README.md"
requires-python = ">=3.12"

View file

@ -67,6 +67,7 @@ def create_test_session():
messages: list[dict] | None = None,
title: str | None = None,
end_time: str | None = None,
parent_session_id: str | None = None,
) -> Path:
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
session_folder = session_dir / f"session_{timestamp}_{session_id[:8]}"
@ -84,9 +85,14 @@ def create_test_session():
"session_id": session_id,
"start_time": "2024-01-01T12:00:00Z",
"end_time": end_time or "2024-01-01T12:05:00Z",
"git_commit": None,
"git_branch": None,
"username": "test-user",
"environment": {"working_directory": cwd},
"title": title,
}
if parent_session_id is not None:
metadata["parent_session_id"] = parent_session_id
metadata_file = session_folder / "meta.json"
with metadata_file.open("w", encoding="utf-8") as f:

View file

@ -513,12 +513,11 @@ class TestSessionUpdates:
),
),
)
text_responses = await read_multiple_responses(process, max_count=10)
text_responses = await read_multiple_responses(
process, max_count=15, timeout_per_response=2.0
)
assert len(text_responses) > 0
responses = [
UpdateJsonRpcNotification.model_validate(json.loads(r))
for r in text_responses
]
responses = parse_conversation(text_responses)
tool_call = next(
(

171
tests/acp/test_acp_hooks.py Normal file
View file

@ -0,0 +1,171 @@
from __future__ import annotations
from pathlib import Path
from unittest.mock import MagicMock, patch
import pytest
import tomli_w
from tests.conftest import get_base_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.hooks.models import HookConfigResult, HookType
from vibe.core.types import LLMChunk, LLMMessage, LLMUsage, Role, SessionMetadata
@pytest.fixture
def backend() -> FakeBackend:
return FakeBackend(
LLMChunk(
message=LLMMessage(role=Role.assistant, content="Hi"),
usage=LLMUsage(prompt_tokens=1, completion_tokens=1),
)
)
def _write_config(config_dir: Path, *, enable_hooks: bool) -> None:
config = get_base_config()
config["enable_experimental_hooks"] = enable_hooks
with (config_dir / "config.toml").open("wb") as f:
tomli_w.dump(config, f)
def _create_acp_agent() -> VibeAcpAgentLoop:
agent = VibeAcpAgentLoop()
client = FakeClient()
agent.on_connect(client)
client.on_connect(agent)
return agent
def _spy_agent_loop(backend: FakeBackend) -> tuple[MagicMock, type[AgentLoop]]:
spy = MagicMock()
class Patched(AgentLoop):
def __init__(self, *args, **kwargs) -> None:
spy(*args, **kwargs)
super().__init__(*args, **kwargs, backend=backend)
return spy, Patched
def _hook_config_from_spy(spy: MagicMock) -> HookConfigResult | None:
hook_config_result = spy.call_args.kwargs["hook_config_result"]
if hook_config_result is None:
return None
assert isinstance(hook_config_result, HookConfigResult)
return hook_config_result
async def _new_session(backend: FakeBackend) -> MagicMock:
spy, patched_loop = _spy_agent_loop(backend)
acp = _create_acp_agent()
with patch("vibe.acp.acp_agent_loop.AgentLoop", side_effect=patched_loop):
await acp.new_session(cwd=str(Path.cwd()), mcp_servers=[])
spy.assert_called_once()
return spy
async def _load_session(
backend: FakeBackend,
tmp_path: Path,
*,
session_id: str = "session-id",
loaded_messages: list[LLMMessage] | None = None,
) -> MagicMock:
spy, patched_loop = _spy_agent_loop(backend)
acp = _create_acp_agent()
session_dir = tmp_path / "sessions" / session_id
session_dir.mkdir(parents=True)
disk_metadata = SessionMetadata(
session_id=session_id,
start_time="2024-01-01T12:00:00Z",
end_time="2024-01-01T12:05:00Z",
git_commit=None,
git_branch=None,
environment={"working_directory": str(Path.cwd())},
username="test-user",
)
(session_dir / "meta.json").write_text(disk_metadata.model_dump_json())
loader_result = (loaded_messages or [], {"session_id": session_id})
with (
patch("vibe.acp.acp_agent_loop.AgentLoop", side_effect=patched_loop),
patch(
"vibe.acp.acp_agent_loop.SessionLoader.find_session_by_id",
return_value=session_dir,
),
patch(
"vibe.acp.acp_agent_loop.SessionLoader.load_session",
return_value=loader_result,
),
):
await acp.load_session(
cwd=str(Path.cwd()), session_id=session_id, mcp_servers=[]
)
spy.assert_called_once()
return spy
@pytest.mark.asyncio
class TestAcpHooksLoading:
async def test_new_session_hooks_enabled_loads_valid_hook(
self, backend: FakeBackend, config_dir: Path
) -> None:
_write_config(config_dir, enable_hooks=True)
(config_dir / "hooks.toml").write_text(
'[[hooks]]\nname = "lint"\ntype = "post_agent_turn"\ncommand = "eslint ."\n'
)
spy = await _new_session(backend)
result = _hook_config_from_spy(spy)
assert result is not None
assert len(result.hooks) == 1
assert result.hooks[0].name == "lint"
assert result.hooks[0].type == HookType.POST_AGENT_TURN
assert result.hooks[0].command == "eslint ."
assert result.hooks[0].timeout == 30.0
assert result.issues == []
async def test_new_session_hooks_enabled_invalid_toml(
self, backend: FakeBackend, config_dir: Path
) -> None:
_write_config(config_dir, enable_hooks=True)
(config_dir / "hooks.toml").write_text("{{broken toml")
spy = await _new_session(backend)
result = _hook_config_from_spy(spy)
assert result is not None
assert result.hooks == []
assert len(result.issues) == 1
assert "Failed to parse" in result.issues[0].message
async def test_load_session_hooks_enabled_loads_valid_hook(
self, backend: FakeBackend, config_dir: Path, tmp_path: Path
) -> None:
_write_config(config_dir, enable_hooks=True)
(config_dir / "hooks.toml").write_text(
'[[hooks]]\nname = "lint"\ntype = "post_agent_turn"\ncommand = "eslint ."\n'
)
spy = await _load_session(
backend,
tmp_path,
loaded_messages=[
LLMMessage(role=Role.system, content="system"),
LLMMessage(role=Role.user, content="hello"),
],
)
result = _hook_config_from_spy(spy)
assert result is not None
assert len(result.hooks) == 1
assert result.hooks[0].name == "lint"
assert result.hooks[0].type == HookType.POST_AGENT_TURN
assert result.hooks[0].command == "eslint ."
assert result.hooks[0].timeout == 30.0
assert result.issues == []

View file

@ -0,0 +1,101 @@
from __future__ import annotations
import asyncio
from typing import Any, cast
from unittest.mock import AsyncMock
from acp import RequestError
from acp.schema import TextContentBlock
import pytest
from vibe.acp.acp_agent_loop import VibeAcpAgentLoop
class TestCloseSession:
@pytest.mark.asyncio
async def test_close_session_removes_session_and_closes_resources(
self, acp_agent_loop: VibeAcpAgentLoop
) -> None:
session_response = await acp_agent_loop.new_session(cwd=".", mcp_servers=[])
session = acp_agent_loop.sessions[session_response.session_id]
backend_close = AsyncMock()
telemetry_close = AsyncMock()
cast(Any, session.agent_loop.backend).close = backend_close
session.agent_loop.telemetry_client.aclose = telemetry_close
response = await acp_agent_loop.close_session(session_response.session_id)
assert response is not None
assert session_response.session_id not in acp_agent_loop.sessions
backend_close.assert_awaited_once()
telemetry_close.assert_awaited_once()
@pytest.mark.asyncio
async def test_close_session_cancels_active_prompt(
self, acp_agent_loop: VibeAcpAgentLoop
) -> None:
session_response = await acp_agent_loop.new_session(cwd=".", mcp_servers=[])
session = acp_agent_loop.sessions[session_response.session_id]
async def wait_forever() -> None:
await asyncio.Event().wait()
task = session.set_prompt_task(wait_forever())
session.agent_loop.telemetry_client.aclose = AsyncMock()
await acp_agent_loop.close_session(session_response.session_id)
assert task.cancelled()
@pytest.mark.asyncio
async def test_close_session_cancels_background_tasks(
self, acp_agent_loop: VibeAcpAgentLoop
) -> None:
session_response = await acp_agent_loop.new_session(cwd=".", mcp_servers=[])
session = acp_agent_loop.sessions[session_response.session_id]
background_event = asyncio.Event()
async def background_work() -> None:
await background_event.wait()
bg_task = session.spawn(background_work())
assert bg_task is not None
session.agent_loop.telemetry_client.aclose = AsyncMock()
await acp_agent_loop.close_session(session_response.session_id)
assert bg_task.cancelled()
@pytest.mark.asyncio
async def test_close_session_rejects_new_background_tasks(
self, acp_agent_loop: VibeAcpAgentLoop
) -> None:
session_response = await acp_agent_loop.new_session(cwd=".", mcp_servers=[])
session = acp_agent_loop.sessions[session_response.session_id]
session.agent_loop.telemetry_client.aclose = AsyncMock()
await acp_agent_loop.close_session(session_response.session_id)
async def noop() -> None:
pass
assert session.spawn(noop()) is None
@pytest.mark.asyncio
async def test_closed_session_rejects_new_prompts(
self, acp_agent_loop: VibeAcpAgentLoop
) -> None:
session_response = await acp_agent_loop.new_session(cwd=".", mcp_servers=[])
session = acp_agent_loop.sessions[session_response.session_id]
session.agent_loop.telemetry_client.aclose = AsyncMock()
await acp_agent_loop.close_session(session_response.session_id)
with pytest.raises(RequestError, match="Session not found"):
await acp_agent_loop.prompt(
prompt=[TextContentBlock(type="text", text="Hello")],
session_id=session_response.session_id,
)

View file

@ -259,6 +259,72 @@ class TestAvailableCommandsWithSkills:
assert "hidden-skill" not in cmd_names
class TestSlashCommandTelemetry:
@pytest.mark.asyncio
async def test_builtin_command_fires_telemetry(
self, acp_agent_loop: VibeAcpAgentLoop, telemetry_events: list[dict]
) -> None:
session_id = await _new_session_and_clear(acp_agent_loop)
telemetry_events.clear()
await _prompt(acp_agent_loop, session_id, "/help")
slash_events = [
e for e in telemetry_events if e["event_name"] == "vibe.slash_command_used"
]
assert len(slash_events) == 1
assert slash_events[0]["properties"]["command"] == "help"
assert slash_events[0]["properties"]["command_type"] == "builtin"
@pytest.mark.asyncio
async def test_skill_command_fires_telemetry(
self,
acp_agent_loop_with_skills: VibeAcpAgentLoop,
skills_dir: Path,
telemetry_events: list[dict],
) -> None:
create_skill(skills_dir, "my-skill", "Does something")
session_id = await _new_session_and_clear(acp_agent_loop_with_skills)
telemetry_events.clear()
await _prompt(acp_agent_loop_with_skills, session_id, "/my-skill")
slash_events = [
e for e in telemetry_events if e["event_name"] == "vibe.slash_command_used"
]
assert len(slash_events) == 1
assert slash_events[0]["properties"]["command"] == "my-skill"
assert slash_events[0]["properties"]["command_type"] == "skill"
@pytest.mark.asyncio
async def test_unknown_slash_command_does_not_fire_telemetry(
self, acp_agent_loop: VibeAcpAgentLoop, telemetry_events: list[dict]
) -> None:
session_id = await _new_session_and_clear(acp_agent_loop)
telemetry_events.clear()
await _prompt(acp_agent_loop, session_id, "/nonexistent")
slash_events = [
e for e in telemetry_events if e["event_name"] == "vibe.slash_command_used"
]
assert slash_events == []
@pytest.mark.asyncio
async def test_regular_message_does_not_fire_telemetry(
self, acp_agent_loop: VibeAcpAgentLoop, telemetry_events: list[dict]
) -> None:
session_id = await _new_session_and_clear(acp_agent_loop)
telemetry_events.clear()
await _prompt(acp_agent_loop, session_id, "Hello world")
slash_events = [
e for e in telemetry_events if e["event_name"] == "vibe.slash_command_used"
]
assert slash_events == []
class TestCommandCaseInsensitivity:
@pytest.mark.asyncio
async def test_uppercase_command(self, acp_agent_loop: VibeAcpAgentLoop) -> None:

View file

@ -0,0 +1,192 @@
from __future__ import annotations
import asyncio
from pathlib import Path
from acp.schema import TextContentBlock
import pytest
from vibe.acp.acp_agent_loop import VibeAcpAgentLoop
from vibe.acp.exceptions import InvalidRequestError
from vibe.core.agents.models import BuiltinAgentName
from vibe.core.session.session_id import extract_suffix
from vibe.core.types import FunctionCall, LLMMessage, Role, ToolCall
class TestACPForkSession:
@pytest.mark.asyncio
async def test_fork_session_clones_history_and_mode(
self, acp_agent_loop: VibeAcpAgentLoop
) -> None:
session_response = await acp_agent_loop.new_session(
cwd=str(Path.cwd()), mcp_servers=[]
)
source_session = acp_agent_loop.sessions[session_response.session_id]
await acp_agent_loop.set_session_mode(
session_id=source_session.id, mode_id=BuiltinAgentName.PLAN
)
await acp_agent_loop.prompt(
prompt=[TextContentBlock(type="text", text="Say hi")],
session_id=source_session.id,
)
response = await acp_agent_loop.fork_session(
cwd=str(Path.cwd()), session_id=source_session.id, mcp_servers=[]
)
assert response.session_id != source_session.id
assert response.modes is not None
assert response.modes.current_mode_id == BuiltinAgentName.PLAN
assert response.models is not None
assert (
response.models.current_model_id
== source_session.agent_loop.config.active_model
)
assert response.config_options is not None
assert len(response.config_options) == 3
forked_session = acp_agent_loop.sessions[response.session_id]
assert forked_session.agent_loop.agent_profile.name == BuiltinAgentName.PLAN
source_messages = [
message.model_dump(mode="json", exclude_none=True)
for message in source_session.agent_loop.messages
if message.role != Role.system
]
forked_messages = [
message.model_dump(mode="json", exclude_none=True)
for message in forked_session.agent_loop.messages
if message.role != Role.system
]
assert forked_messages == source_messages
@pytest.mark.asyncio
async def test_fork_session_from_user_message_keeps_full_turn(
self, acp_agent_loop: VibeAcpAgentLoop
) -> None:
session_response = await acp_agent_loop.new_session(
cwd=str(Path.cwd()), mcp_servers=[]
)
source_session = acp_agent_loop.sessions[session_response.session_id]
source_session.agent_loop.messages.extend([
LLMMessage(role=Role.user, content="First", message_id="user-1"),
LLMMessage(
role=Role.assistant, content="First answer", message_id="assistant-1"
),
LLMMessage(
role=Role.assistant,
content="",
message_id="assistant-2",
tool_calls=[
ToolCall(
id="call-1",
index=0,
function=FunctionCall(
name="read_file", arguments='{"path":"a.txt"}'
),
)
],
),
LLMMessage(role=Role.tool, content="contents", tool_call_id="call-1"),
LLMMessage(role=Role.user, content="Second", message_id="user-2"),
LLMMessage(
role=Role.assistant, content="Second answer", message_id="assistant-3"
),
])
response = await acp_agent_loop.fork_session(
cwd=str(Path.cwd()),
session_id=source_session.id,
mcp_servers=[],
messageId="user-1",
)
forked_session = acp_agent_loop.sessions[response.session_id]
assert [
(message.role, message.content, message.message_id, message.tool_call_id)
for message in forked_session.agent_loop.messages
if message.role != Role.system
] == [
(Role.user, "First", "user-1", None),
(Role.assistant, "First answer", "assistant-1", None),
(Role.assistant, "", "assistant-2", None),
(Role.tool, "contents", None, "call-1"),
]
@pytest.mark.asyncio
async def test_fork_session_rejects_non_user_message_id(
self, acp_agent_loop: VibeAcpAgentLoop
) -> None:
session_response = await acp_agent_loop.new_session(
cwd=str(Path.cwd()), mcp_servers=[]
)
source_session = acp_agent_loop.sessions[session_response.session_id]
source_session.agent_loop.messages.extend([
LLMMessage(role=Role.user, content="First", message_id="user-1"),
LLMMessage(
role=Role.assistant, content="First answer", message_id="assistant-1"
),
])
with pytest.raises(
InvalidRequestError,
match="Fork from message_id is only supported for user messages",
):
await acp_agent_loop.fork_session(
cwd=str(Path.cwd()),
session_id=source_session.id,
mcp_servers=[],
messageId="assistant-1",
)
@pytest.mark.asyncio
async def test_fork_session_sets_parent_session_id(
self, acp_agent_loop: VibeAcpAgentLoop
) -> None:
session_response = await acp_agent_loop.new_session(
cwd=str(Path.cwd()), mcp_servers=[]
)
source_session = acp_agent_loop.sessions[session_response.session_id]
response = await acp_agent_loop.fork_session(
cwd=str(Path.cwd()), session_id=source_session.id, mcp_servers=[]
)
forked_session = acp_agent_loop.sessions[response.session_id]
assert forked_session.agent_loop.parent_session_id == source_session.id
@pytest.mark.asyncio
async def test_fork_session_rejects_running_session(
self, acp_agent_loop: VibeAcpAgentLoop
) -> None:
session_response = await acp_agent_loop.new_session(
cwd=str(Path.cwd()), mcp_servers=[]
)
source_session = acp_agent_loop.sessions[session_response.session_id]
source_session.set_prompt_task(asyncio.sleep(10))
with pytest.raises(
InvalidRequestError,
match="Cannot fork a session while the agent loop is running",
):
await acp_agent_loop.fork_session(
cwd=str(Path.cwd()), session_id=source_session.id, mcp_servers=[]
)
await source_session.cancel_prompt()
@pytest.mark.asyncio
async def test_fork_session_preserves_session_id_suffix(
self, acp_agent_loop: VibeAcpAgentLoop
) -> None:
session_response = await acp_agent_loop.new_session(
cwd=str(Path.cwd()), mcp_servers=[]
)
source_session = acp_agent_loop.sessions[session_response.session_id]
response = await acp_agent_loop.fork_session(
cwd=str(Path.cwd()), session_id=source_session.id, mcp_servers=[]
)
assert extract_suffix(response.session_id) == extract_suffix(source_session.id)

View file

@ -7,6 +7,8 @@ from acp.schema import (
Implementation,
PromptCapabilities,
SessionCapabilities,
SessionCloseCapabilities,
SessionForkCapabilities,
SessionListCapabilities,
)
import pytest
@ -25,10 +27,14 @@ class TestACPInitialize:
prompt_capabilities=PromptCapabilities(
audio=False, embedded_context=True, image=False
),
session_capabilities=SessionCapabilities(list=SessionListCapabilities()),
session_capabilities=SessionCapabilities(
close=SessionCloseCapabilities(),
list=SessionListCapabilities(),
fork=SessionForkCapabilities(),
),
)
assert response.agent_info == Implementation(
name="@mistralai/mistral-vibe", title="Mistral Vibe", version="2.8.1"
name="@mistralai/mistral-vibe", title="Mistral Vibe", version="2.9.0"
)
assert response.auth_methods == []
@ -49,10 +55,14 @@ class TestACPInitialize:
prompt_capabilities=PromptCapabilities(
audio=False, embedded_context=True, image=False
),
session_capabilities=SessionCapabilities(list=SessionListCapabilities()),
session_capabilities=SessionCapabilities(
close=SessionCloseCapabilities(),
list=SessionListCapabilities(),
fork=SessionForkCapabilities(),
),
)
assert response.agent_info == Implementation(
name="@mistralai/mistral-vibe", title="Mistral Vibe", version="2.8.1"
name="@mistralai/mistral-vibe", title="Mistral Vibe", version="2.9.0"
)
assert response.auth_methods is not None

View file

@ -99,7 +99,7 @@ class TestLoadSession:
}
assert response.config_options is not None
assert len(response.config_options) == 2
assert len(response.config_options) == 3
assert response.config_options[0].id == "mode"
assert response.config_options[0].category == "mode"
assert response.config_options[0].current_value == BuiltinAgentName.DEFAULT
@ -118,6 +118,9 @@ class TestLoadSession:
assert len(response.config_options[1].options) == 2
model_option_values = {opt.value for opt in response.config_options[1].options}
assert model_option_values == {"devstral-latest", "devstral-small"}
assert response.config_options[2].id == "thinking"
assert response.config_options[2].category == "thinking"
assert response.config_options[2].current_value == "off"
@pytest.mark.asyncio
async def test_load_session_registers_session_with_original_id(
@ -136,6 +139,7 @@ class TestLoadSession:
assert session_id in acp_agent.sessions
assert acp_agent.sessions[session_id].id == session_id
assert acp_agent.sessions[session_id].agent_loop.session_id == session_id
@pytest.mark.asyncio
async def test_load_session_injects_messages_into_agent_loop(
@ -375,6 +379,36 @@ class TestLoadSession:
assert agent_updates[0].update.content.text == "First response"
assert agent_updates[1].update.content.text == "Second response"
@pytest.mark.asyncio
async def test_load_session_restores_agent_loop_session_identity(
self,
acp_agent_with_session_config: tuple[VibeAcpAgentLoop, FakeClient],
temp_session_dir: Path,
create_test_session,
) -> None:
acp_agent, _client = acp_agent_with_session_config
session_id = "restore-id-12345678"
parent_session_id = "parent-id-87654321"
cwd = str(Path.cwd())
session_dir = create_test_session(
temp_session_dir, session_id, cwd, parent_session_id=parent_session_id
)
await acp_agent.load_session(cwd=cwd, mcp_servers=[], session_id=session_id)
agent_loop = acp_agent.sessions[session_id].agent_loop
assert agent_loop.session_id == session_id
assert agent_loop.parent_session_id == parent_session_id
assert agent_loop.session_logger.session_id == session_id
assert agent_loop.session_logger.session_dir == session_dir
assert agent_loop.session_logger.session_metadata is not None
assert (
agent_loop.session_logger.session_metadata.parent_session_id
== parent_session_id
)
@pytest.mark.asyncio
async def test_replay_user_message_has_message_id(
self,

View file

@ -99,7 +99,7 @@ class TestACPNewSession:
# Check config_options
assert session_response.config_options is not None
assert len(session_response.config_options) == 2
assert len(session_response.config_options) == 3
# Mode config option
mode_config = session_response.config_options[0]
@ -125,6 +125,13 @@ class TestACPNewSession:
model_option_values = {opt.value for opt in model_config.options}
assert model_option_values == {"devstral-latest", "devstral-small"}
# Thinking config option
thinking_config = session_response.config_options[2]
assert thinking_config.id == "thinking"
assert thinking_config.category == "thinking"
assert thinking_config.current_value == "off"
assert len(thinking_config.options) == 5
@pytest.mark.skip(reason="TODO: Fix this test")
@pytest.mark.asyncio
async def test_new_session_preserves_model_after_set_model(

155
tests/acp/test_session.py Normal file
View file

@ -0,0 +1,155 @@
from __future__ import annotations
import asyncio
from unittest.mock import MagicMock
import pytest
from vibe.acp.session import AcpSessionLoop
def _make_session() -> AcpSessionLoop:
return AcpSessionLoop(
id="test-session", agent_loop=MagicMock(), command_registry=MagicMock()
)
class TestSpawn:
@pytest.mark.asyncio
async def test_spawn_creates_task(self) -> None:
session = _make_session()
ran = asyncio.Event()
async def work() -> None:
ran.set()
task = session.spawn(work())
assert task is not None
await task
assert ran.is_set()
@pytest.mark.asyncio
async def test_spawn_returns_none_after_close(self) -> None:
session = _make_session()
await session.close()
async def noop() -> None:
pass
assert session.spawn(noop()) is None
@pytest.mark.asyncio
async def test_spawn_tracks_multiple_tasks(self) -> None:
session = _make_session()
gate = asyncio.Event()
async def wait_for_gate() -> None:
await gate.wait()
t1 = session.spawn(wait_for_gate())
t2 = session.spawn(wait_for_gate())
assert t1 is not None
assert t2 is not None
assert not t1.done()
assert not t2.done()
gate.set()
await asyncio.gather(t1, t2)
class TestPromptTask:
@pytest.mark.asyncio
async def test_set_prompt_task_tracks_task(self) -> None:
session = _make_session()
async def work() -> None:
pass
task = session.set_prompt_task(work())
assert session.prompt_task is task
await task
assert session.prompt_task is None
@pytest.mark.asyncio
async def test_cancel_prompt_cancels_active_task(self) -> None:
session = _make_session()
async def hang() -> None:
await asyncio.Event().wait()
task = session.set_prompt_task(hang())
await session.cancel_prompt()
assert task.cancelled()
assert session.prompt_task is None
@pytest.mark.asyncio
async def test_cancel_prompt_is_noop_without_task(self) -> None:
session = _make_session()
await session.cancel_prompt()
@pytest.mark.asyncio
async def test_cancel_prompt_does_not_cancel_background_tasks(self) -> None:
session = _make_session()
gate = asyncio.Event()
async def bg() -> None:
await gate.wait()
bg_task = session.spawn(bg())
assert bg_task is not None
async def hang() -> None:
await asyncio.Event().wait()
session.set_prompt_task(hang())
await session.cancel_prompt()
assert not bg_task.cancelled()
gate.set()
await bg_task
class TestClose:
@pytest.mark.asyncio
async def test_close_cancels_all_tasks(self) -> None:
session = _make_session()
async def hang() -> None:
await asyncio.Event().wait()
bg = session.spawn(hang())
prompt = session.set_prompt_task(hang())
assert bg is not None
await session.close()
assert bg.cancelled()
assert prompt.cancelled()
assert session.prompt_task is None
@pytest.mark.asyncio
async def test_close_is_idempotent(self) -> None:
session = _make_session()
await session.close()
await session.close()
@pytest.mark.asyncio
async def test_close_waits_for_task_cleanup(self) -> None:
session = _make_session()
cleanup_ran = asyncio.Event()
async def task_with_cleanup() -> None:
try:
await asyncio.Event().wait()
except asyncio.CancelledError:
cleanup_ran.set()
raise
session.spawn(task_with_cleanup())
await asyncio.sleep(0) # let the task start
await session.close()
assert cleanup_ran.is_set()

View file

@ -75,11 +75,11 @@ class TestACPSetConfigOptionMode:
assert response is not None
assert response.config_options is not None
assert len(response.config_options) == 2
assert len(response.config_options) == 3
assert (
acp_session.agent_loop.agent_profile.name == BuiltinAgentName.AUTO_APPROVE
)
assert acp_session.agent_loop.auto_approve is True
assert acp_session.agent_loop.bypass_tool_permissions is True
# Verify config_options reflect the new state
mode_config = response.config_options[0]
@ -126,10 +126,10 @@ class TestACPSetConfigOptionMode:
assert response is not None
assert response.config_options is not None
assert len(response.config_options) == 2
assert len(response.config_options) == 3
assert acp_session.agent_loop.agent_profile.name == BuiltinAgentName.CHAT
assert (
acp_session.agent_loop.auto_approve is True
acp_session.agent_loop.bypass_tool_permissions is True
) # Chat mode auto-approves read-only tools
mode_config = response.config_options[0]
@ -200,7 +200,7 @@ class TestACPSetConfigOptionModel:
assert response is not None
assert response.config_options is not None
assert len(response.config_options) == 2
assert len(response.config_options) == 3
assert acp_session.agent_loop.config.active_model == "devstral-small"
# Verify config_options reflect the new state
@ -315,3 +315,87 @@ class TestACPSetConfigOptionInvalidConfigId:
)
assert response is None
class TestACPSetConfigOptionThinking:
@pytest.mark.asyncio
async def test_set_config_option_thinking_success(
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
acp_session = next(
(s for s in acp_agent_loop.sessions.values() if s.id == session_id), None
)
assert acp_session is not None
assert acp_session.agent_loop.config.get_active_model().thinking == "off"
response = await acp_agent_loop.set_config_option(
session_id=session_id, config_id="thinking", value="high"
)
assert response is not None
assert response.config_options is not None
assert len(response.config_options) == 3
assert acp_session.agent_loop.config.get_active_model().thinking == "high"
thinking_config = response.config_options[2]
assert thinking_config.id == "thinking"
assert thinking_config.current_value == "high"
@pytest.mark.asyncio
async def test_set_config_option_thinking_all_levels(
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
acp_session = next(
(s for s in acp_agent_loop.sessions.values() if s.id == session_id), None
)
assert acp_session is not None
for level in ["low", "medium", "high", "max", "off"]:
response = await acp_agent_loop.set_config_option(
session_id=session_id, config_id="thinking", value=level
)
assert response is not None
assert acp_session.agent_loop.config.get_active_model().thinking == level
@pytest.mark.asyncio
async def test_set_config_option_thinking_invalid_returns_none(
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
acp_session = next(
(s for s in acp_agent_loop.sessions.values() if s.id == session_id), None
)
assert acp_session is not None
response = await acp_agent_loop.set_config_option(
session_id=session_id, config_id="thinking", value="ultra"
)
assert response is None
assert acp_session.agent_loop.config.get_active_model().thinking == "off"
@pytest.mark.asyncio
async def test_set_config_option_thinking_empty_string_returns_none(
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
response = await acp_agent_loop.set_config_option(
session_id=session_id, config_id="thinking", value=""
)
assert response is None

View file

@ -28,7 +28,7 @@ class TestACPSetMode:
assert response is not None
assert acp_session.agent_loop.agent_profile.name == BuiltinAgentName.DEFAULT
assert acp_session.agent_loop.auto_approve is False
assert acp_session.agent_loop.bypass_tool_permissions is False
@pytest.mark.asyncio
async def test_set_mode_to_auto_approve(
@ -44,7 +44,7 @@ class TestACPSetMode:
assert acp_session is not None
assert acp_session.agent_loop.agent_profile.name == BuiltinAgentName.DEFAULT
assert acp_session.agent_loop.auto_approve is False
assert acp_session.agent_loop.bypass_tool_permissions is False
response = await acp_agent_loop.set_session_mode(
session_id=session_id, mode_id=BuiltinAgentName.AUTO_APPROVE
@ -54,7 +54,7 @@ class TestACPSetMode:
assert (
acp_session.agent_loop.agent_profile.name == BuiltinAgentName.AUTO_APPROVE
)
assert acp_session.agent_loop.auto_approve is True
assert acp_session.agent_loop.bypass_tool_permissions is True
@pytest.mark.asyncio
async def test_set_mode_to_plan(self, acp_agent_loop: VibeAcpAgentLoop) -> None:
@ -76,7 +76,7 @@ class TestACPSetMode:
assert response is not None
assert acp_session.agent_loop.agent_profile.name == BuiltinAgentName.PLAN
assert (
acp_session.agent_loop.auto_approve is False
acp_session.agent_loop.bypass_tool_permissions is False
) # Plan mode uses per-tool allowlists, not global auto-approve
@pytest.mark.asyncio
@ -103,7 +103,7 @@ class TestACPSetMode:
acp_session.agent_loop.agent_profile.name == BuiltinAgentName.ACCEPT_EDITS
)
assert (
acp_session.agent_loop.auto_approve is False
acp_session.agent_loop.bypass_tool_permissions is False
) # Accept Edits mode doesn't auto-approve all
@pytest.mark.asyncio
@ -126,7 +126,7 @@ class TestACPSetMode:
assert response is not None
assert acp_session.agent_loop.agent_profile.name == BuiltinAgentName.CHAT
assert (
acp_session.agent_loop.auto_approve is True
acp_session.agent_loop.bypass_tool_permissions is True
) # Chat mode auto-approves read-only tools
@pytest.mark.asyncio
@ -143,7 +143,7 @@ class TestACPSetMode:
assert acp_session is not None
initial_agent = acp_session.agent_loop.agent_profile.name
initial_auto_approve = acp_session.agent_loop.auto_approve
initial_bypass = acp_session.agent_loop.bypass_tool_permissions
response = await acp_agent_loop.set_session_mode(
session_id=session_id, mode_id="invalid-mode"
@ -151,7 +151,7 @@ class TestACPSetMode:
assert response is None
assert acp_session.agent_loop.agent_profile.name == initial_agent
assert acp_session.agent_loop.auto_approve == initial_auto_approve
assert acp_session.agent_loop.bypass_tool_permissions == initial_bypass
@pytest.mark.asyncio
async def test_set_mode_to_same_mode(
@ -174,7 +174,7 @@ class TestACPSetMode:
assert response is not None
assert acp_session.agent_loop.agent_profile.name == BuiltinAgentName.DEFAULT
assert acp_session.agent_loop.auto_approve is False
assert acp_session.agent_loop.bypass_tool_permissions is False
@pytest.mark.asyncio
async def test_set_mode_with_empty_string(
@ -190,7 +190,7 @@ class TestACPSetMode:
assert acp_session is not None
initial_agent = acp_session.agent_loop.agent_profile.name
initial_auto_approve = acp_session.agent_loop.auto_approve
initial_bypass = acp_session.agent_loop.bypass_tool_permissions
response = await acp_agent_loop.set_session_mode(
session_id=session_id, mode_id=""
@ -198,4 +198,4 @@ class TestACPSetMode:
assert response is None
assert acp_session.agent_loop.agent_profile.name == initial_agent
assert acp_session.agent_loop.auto_approve == initial_auto_approve
assert acp_session.agent_loop.bypass_tool_permissions == initial_bypass

View file

@ -0,0 +1,53 @@
from __future__ import annotations
from pathlib import Path
from unittest.mock import patch
import pytest
from tests.acp.conftest import _create_acp_agent
from vibe.acp.acp_agent_loop import VibeAcpAgentLoop
from vibe.acp.exceptions import InvalidRequestError
from vibe.core.agent_loop import AgentLoop
@pytest.fixture
def acp_agent_loop(backend) -> VibeAcpAgentLoop:
class PatchedAgentLoop(AgentLoop):
def __init__(self, *args, **kwargs) -> None:
super().__init__(*args, **{**kwargs, "backend": backend})
patch("vibe.acp.acp_agent_loop.AgentLoop", side_effect=PatchedAgentLoop).start()
return _create_acp_agent()
class TestTelemetryNotification:
@pytest.mark.asyncio
async def test_ignores_unknown_event_gracefully(
self,
acp_agent_loop: VibeAcpAgentLoop,
telemetry_events: list[dict[str, object]],
) -> None:
session = await acp_agent_loop.new_session(cwd=str(Path.cwd()), mcp_servers=[])
telemetry_events.clear()
await acp_agent_loop.ext_notification(
"telemetry/send",
{
"event": "vibe.unsupported_event",
"session_id": session.session_id,
"properties": {"context_type": "file"},
},
)
assert telemetry_events == []
@pytest.mark.asyncio
async def test_raises_on_invalid_params(
self, acp_agent_loop: VibeAcpAgentLoop
) -> None:
with pytest.raises(InvalidRequestError):
await acp_agent_loop.ext_notification(
"telemetry/send",
{"event": "vibe.some_event"}, # missing session_id
)

View file

@ -212,6 +212,9 @@ class TestLoadSessionUsageUpdate:
"session_id": session_id,
"start_time": "2024-01-01T12:00:00Z",
"end_time": "2024-01-01T12:05:00Z",
"git_commit": None,
"git_branch": None,
"username": "test-user",
"environment": {"working_directory": cwd},
}
with (session_folder / "meta.json").open("w") as f:

View file

@ -115,9 +115,9 @@ def test_on_text_change_limits_the_number_of_results_and_preserves_insertion_ord
suggestions, selected_index = view.suggestion_events[-1]
assert len(suggestions) == 7
assert [suggestion.alias for suggestion in suggestions] == [
"/help",
"/config",
"/compact",
"/help",
"/summarize",
"/logpath",
"/exit",

View file

@ -8,7 +8,10 @@ from textual.style import Style
from textual.widgets import Markdown
from vibe.cli.textual_ui.app import VibeApp
from vibe.cli.textual_ui.widgets.chat_input.completion_popup import CompletionPopup
from vibe.cli.textual_ui.widgets.chat_input.completion_popup import (
CompletionPopup,
_CompletionItem,
)
from vibe.cli.textual_ui.widgets.chat_input.container import ChatInputContainer
@ -20,7 +23,7 @@ async def test_popup_appears_with_matching_suggestions(vibe_app: VibeApp) -> Non
await pilot.press(*"/com")
popup_content = str(popup.render())
popup_content = popup.content_text
assert popup.styles.display == "block"
assert "/compact" in popup_content
assert "Compact conversation history by summarizing" in popup_content
@ -39,7 +42,7 @@ async def test_popup_hides_when_input_cleared(vibe_app: VibeApp) -> None:
@pytest.mark.asyncio
async def test_pressing_tab_writes_selected_command_and_keeps_popup_visible(
async def test_pressing_tab_writes_selected_command_and_hides_popup(
vibe_app: VibeApp,
) -> None:
async with vibe_app.run_test() as pilot:
@ -49,22 +52,22 @@ async def test_pressing_tab_writes_selected_command_and_keeps_popup_visible(
await pilot.press(*"/co")
await pilot.press("tab")
assert chat_input.value == "/compact"
assert popup.styles.display == "block"
assert chat_input.value == "/config"
assert popup.styles.display == "none"
def ensure_selected_command(popup: CompletionPopup, expected_alias: str) -> None:
renderable = popup.render()
assert isinstance(renderable, Content)
content = str(renderable)
selected_aliases: list[str] = []
for span in renderable.spans:
style = span.style
if isinstance(style, Style) and style.reverse:
alias_text = content[span.start : span.end].strip()
alias = alias_text.split()[0] if alias_text else ""
selected_aliases.append(alias)
for item in popup.query(_CompletionItem):
renderable = item.render()
assert isinstance(renderable, Content)
content = str(renderable)
for span in renderable.spans:
style = span.style
if isinstance(style, Style) and style.reverse:
alias_text = content[span.start : span.end].strip()
alias = alias_text.split()[0] if alias_text else ""
selected_aliases.append(alias)
assert len(selected_aliases) == 1
assert selected_aliases[0] == expected_alias
@ -77,11 +80,11 @@ async def test_arrow_navigation_updates_selected_suggestion(vibe_app: VibeApp) -
await pilot.press(*"/c")
ensure_selected_command(popup, "/clear")
ensure_selected_command(popup, "/config")
await pilot.press("down")
ensure_selected_command(popup, "/compact")
await pilot.press("up")
ensure_selected_command(popup, "/clear")
await pilot.press("up")
ensure_selected_command(popup, "/config")
@pytest.mark.asyncio
@ -91,11 +94,11 @@ async def test_arrow_navigation_cycles_through_suggestions(vibe_app: VibeApp) ->
await pilot.press(*"/co")
ensure_selected_command(popup, "/compact")
await pilot.press("down")
ensure_selected_command(popup, "/config")
await pilot.press("up")
await pilot.press("down")
ensure_selected_command(popup, "/compact")
await pilot.press("up")
ensure_selected_command(popup, "/config")
@pytest.mark.asyncio
@ -155,7 +158,7 @@ async def test_path_completion_popup_lists_files_and_directories(
await pilot.press(*"@s")
popup_content = str(popup.render())
popup_content = popup.content_text
assert "src/" in popup_content
assert popup.styles.display == "block"
@ -176,7 +179,7 @@ async def test_path_completion_popup_shows_up_to_ten_results(
await pilot.press(*"@src/core/extra/")
popup_content = str(popup.render())
popup_content = popup.content_text
assert "src/core/extra/extra_file_1.py" in popup_content
assert "src/core/extra/extra_file_10.py" in popup_content
assert "src/core/extra/extra_file_11.py" in popup_content
@ -190,6 +193,24 @@ async def test_path_completion_popup_shows_up_to_ten_results(
assert popup.styles.display == "block"
@pytest.mark.asyncio
async def test_pressing_tab_on_directory_keeps_popup_visible_with_contents(
vibe_app: VibeApp, file_tree: Path
) -> None:
async with vibe_app.run_test() as pilot:
chat_input = vibe_app.query_one(ChatInputContainer)
popup = vibe_app.query_one(CompletionPopup)
await pilot.press(*"@sr")
await pilot.press("tab")
await pilot.pause(0.2)
assert chat_input.value == "@src/"
popup_content = popup.content_text
assert popup.styles.display == "block"
assert "src/main.py" in popup_content
@pytest.mark.asyncio
async def test_pressing_tab_writes_selected_path_name_and_hides_popup(
vibe_app: VibeApp, file_tree: Path
@ -229,7 +250,7 @@ async def test_fuzzy_matches_subsequence_characters(
await pilot.press(*"@src/utils/handling")
popup_content = str(popup.render())
popup_content = popup.content_text
assert "src/utils/error_handling.py" in popup_content
assert popup.styles.display == "block"
@ -243,7 +264,7 @@ async def test_fuzzy_matches_word_boundaries(
await pilot.press(*"@src/utils/eh")
popup_content = str(popup.render())
popup_content = popup.content_text
assert "src/utils/error_handling.py" in popup_content
assert popup.styles.display == "block"
@ -257,7 +278,7 @@ async def test_finds_files_recursively_by_filename(
await pilot.press(*"@entryp")
popup_content = str(popup.render())
popup_content = popup.content_text
assert "vibe/acp/entrypoint.py" in popup_content
assert popup.styles.display == "block"
@ -271,7 +292,7 @@ async def test_finds_files_recursively_with_partial_path(
await pilot.press(*"@acp/entry")
popup_content = str(popup.render())
popup_content = popup.content_text
assert "vibe/acp/entrypoint.py" in popup_content
assert popup.styles.display == "block"

View file

@ -0,0 +1,520 @@
from __future__ import annotations
import json
from typing import Any
from tests.backend.data import Chunk, JsonResponse, ResultData, Url
OPENAI_RESPONSES_TEST_BASE_URL = "https://api.openai.com"
def _sse_event(data: dict[str, Any] | str) -> Chunk:
if data == "[DONE]":
return b"data: [DONE]"
return f"data: {json.dumps(data, separators=(',', ':'))}".encode()
def _usage(prompt_tokens: int = 0, completion_tokens: int = 0) -> dict[str, int]:
return {"prompt_tokens": prompt_tokens, "completion_tokens": completion_tokens}
def _result(
message: str = "",
*,
prompt_tokens: int = 0,
completion_tokens: int = 0,
reasoning_content: str | None = None,
tool_calls: list[dict[str, Any]] | None = None,
) -> ResultData:
result: ResultData = {
"message": message,
"usage": _usage(prompt_tokens, completion_tokens),
}
if reasoning_content is not None:
result["reasoning_content"] = reasoning_content
if tool_calls is not None:
result["tool_calls"] = tool_calls
return result
def _tool_call_result(
name: str | None, arguments: str, index: int | None
) -> dict[str, Any]:
return {"name": name, "arguments": arguments, "index": index}
def _output_text(text: str) -> dict[str, Any]:
return {"type": "output_text", "text": text, "annotations": [], "logprobs": []}
def _message_output_item(
message_id: str, text: str, *, phase: str | None = None, status: str = "completed"
) -> dict[str, Any]:
item: dict[str, Any] = {
"id": message_id,
"type": "message",
"status": status,
"content": [_output_text(text)],
"role": "assistant",
}
if phase is not None:
item["phase"] = phase
return item
def _stream_message_item(
message_id: str, *, phase: str | None = None, status: str = "in_progress"
) -> dict[str, Any]:
item: dict[str, Any] = {
"id": message_id,
"type": "message",
"status": status,
"content": [],
"role": "assistant",
}
if phase is not None:
item["phase"] = phase
return item
def _function_call_item(
item_id: str, call_id: str, name: str, arguments: str, *, status: str = "completed"
) -> dict[str, Any]:
return {
"id": item_id,
"type": "function_call",
"call_id": call_id,
"name": name,
"arguments": arguments,
"status": status,
}
SIMPLE_CONVERSATION_PARAMS: list[tuple[Url, JsonResponse, ResultData]] = [
(
OPENAI_RESPONSES_TEST_BASE_URL,
{
"id": "resp_fake_id_1234",
"object": "response",
"created_at": 1234567890,
"model": "gpt-4o-2024-08-06",
"output": [
_message_output_item(
"msg_fake_id_5678", "Hello! How can I help you today?"
)
],
"usage": {"input_tokens": 100, "output_tokens": 200, "total_tokens": 300},
},
_result(
"Hello! How can I help you today?", prompt_tokens=100, completion_tokens=200
),
)
]
TOOL_CONVERSATION_PARAMS: list[tuple[Url, JsonResponse, ResultData]] = [
(
OPENAI_RESPONSES_TEST_BASE_URL,
{
"id": "resp_fake_id_9012",
"object": "response",
"created_at": 1234567890,
"model": "gpt-4o-2024-08-06",
"output": [
_message_output_item("msg_fake_id_3456", ""),
_function_call_item(
"fc_fake_id_7890",
"call_fake_id_1111",
"some_tool",
'{"some_argument": "some_argument_value"}',
),
],
"usage": {"input_tokens": 100, "output_tokens": 200, "total_tokens": 300},
},
_result(
prompt_tokens=100,
completion_tokens=200,
tool_calls=[
_tool_call_result(
"some_tool", '{"some_argument": "some_argument_value"}', 1
)
],
),
)
]
STREAMED_SIMPLE_CONVERSATION_PARAMS: list[tuple[Url, list[Chunk], list[ResultData]]] = [
(
OPENAI_RESPONSES_TEST_BASE_URL,
[
_sse_event({
"type": "response.created",
"response": {
"id": "resp_fake_id_1234",
"object": "response",
"created_at": 1234567890,
"model": "gpt-4o-2024-08-06",
"output": [],
"usage": None,
},
}),
_sse_event({
"type": "response.in_progress",
"response": {"id": "resp_fake_id_1234"},
}),
_sse_event({
"type": "response.output_item.added",
"output_index": 0,
"item": _stream_message_item("msg_fake_id_5678"),
}),
_sse_event({
"type": "response.content_part.added",
"output_index": 0,
"content_index": 0,
"part": _output_text(""),
}),
_sse_event({
"type": "response.output_text.delta",
"output_index": 0,
"content_index": 0,
"delta": "Hello",
}),
_sse_event({
"type": "response.output_text.delta",
"output_index": 0,
"content_index": 0,
"delta": "!",
}),
_sse_event({
"type": "response.output_text.done",
"output_index": 0,
"content_index": 0,
"text": "Hello!",
}),
_sse_event({
"type": "response.content_part.done",
"output_index": 0,
"content_index": 0,
"part": _output_text("Hello!"),
}),
_sse_event({
"type": "response.output_item.done",
"output_index": 0,
"item": _message_output_item("msg_fake_id_5678", "Hello!"),
}),
_sse_event({
"type": "response.completed",
"response": {
"id": "resp_fake_id_1234",
"object": "response",
"created_at": 1234567890,
"model": "gpt-4o-2024-08-06",
"output": [_message_output_item("msg_fake_id_5678", "Hello!")],
"usage": {
"input_tokens": 100,
"output_tokens": 200,
"total_tokens": 300,
},
},
}),
_sse_event("[DONE]"),
],
[
_result(),
_result(),
_result(),
_result(),
_result("Hello"),
_result("!"),
_result(),
_result(),
_result(),
_result(prompt_tokens=100, completion_tokens=200),
],
)
]
COMMENTARY_CONVERSATION_PARAMS: list[tuple[Url, JsonResponse, ResultData]] = [
(
OPENAI_RESPONSES_TEST_BASE_URL,
{
"id": "resp_thinking_1234",
"object": "response",
"created_at": 1234567890,
"model": "gpt-5.4-2025-04-14",
"output": [
_message_output_item(
"msg_commentary_5678",
"The user said hello, I should respond warmly.",
phase="commentary",
),
_message_output_item(
"msg_final_9012",
"Hello! How can I help you today?",
phase="final_answer",
),
],
"usage": {"input_tokens": 150, "output_tokens": 250, "total_tokens": 400},
},
_result(
"Hello! How can I help you today?",
prompt_tokens=150,
completion_tokens=250,
reasoning_content="The user said hello, I should respond warmly.",
),
)
]
STREAMED_COMMENTARY_CONVERSATION_PARAMS: list[
tuple[Url, list[Chunk], list[ResultData]]
] = [
(
OPENAI_RESPONSES_TEST_BASE_URL,
[
_sse_event({
"type": "response.created",
"response": {
"id": "resp_thinking_1234",
"object": "response",
"created_at": 1234567890,
"model": "gpt-5.4-2025-04-14",
"output": [],
"usage": None,
},
}),
_sse_event({
"type": "response.in_progress",
"response": {"id": "resp_thinking_1234"},
}),
_sse_event({
"type": "response.output_item.added",
"output_index": 0,
"item": _stream_message_item("msg_commentary_5678", phase="commentary"),
}),
_sse_event({
"type": "response.content_part.added",
"output_index": 0,
"content_index": 0,
"part": _output_text(""),
}),
_sse_event({
"type": "response.output_text.delta",
"output_index": 0,
"content_index": 0,
"delta": "Thinking",
}),
_sse_event({
"type": "response.output_text.delta",
"output_index": 0,
"content_index": 0,
"delta": " about it...",
}),
_sse_event({
"type": "response.output_text.done",
"output_index": 0,
"content_index": 0,
"text": "Thinking about it...",
}),
_sse_event({
"type": "response.content_part.done",
"output_index": 0,
"content_index": 0,
"part": _output_text("Thinking about it..."),
}),
_sse_event({
"type": "response.output_item.done",
"output_index": 0,
"item": _message_output_item(
"msg_commentary_5678", "Thinking about it...", phase="commentary"
),
}),
_sse_event({
"type": "response.output_item.added",
"output_index": 1,
"item": _stream_message_item("msg_final_9012", phase="final_answer"),
}),
_sse_event({
"type": "response.content_part.added",
"output_index": 1,
"content_index": 0,
"part": _output_text(""),
}),
_sse_event({
"type": "response.output_text.delta",
"output_index": 1,
"content_index": 0,
"delta": "Hello",
}),
_sse_event({
"type": "response.output_text.delta",
"output_index": 1,
"content_index": 0,
"delta": "!",
}),
_sse_event({
"type": "response.output_text.done",
"output_index": 1,
"content_index": 0,
"text": "Hello!",
}),
_sse_event({
"type": "response.content_part.done",
"output_index": 1,
"content_index": 0,
"part": _output_text("Hello!"),
}),
_sse_event({
"type": "response.output_item.done",
"output_index": 1,
"item": _message_output_item(
"msg_final_9012", "Hello!", phase="final_answer"
),
}),
_sse_event({
"type": "response.completed",
"response": {
"id": "resp_thinking_1234",
"object": "response",
"created_at": 1234567890,
"model": "gpt-5.4-2025-04-14",
"output": [
_message_output_item(
"msg_commentary_5678",
"Thinking about it...",
phase="commentary",
),
_message_output_item(
"msg_final_9012", "Hello!", phase="final_answer"
),
],
"usage": {
"input_tokens": 150,
"output_tokens": 250,
"total_tokens": 400,
},
},
}),
_sse_event("[DONE]"),
],
[
_result(),
_result(),
_result(),
_result(),
_result(reasoning_content="Thinking"),
_result(reasoning_content=" about it..."),
_result(),
_result(),
_result(),
_result(),
_result(),
_result("Hello"),
_result("!"),
_result(),
_result(),
_result(),
_result(prompt_tokens=150, completion_tokens=250),
],
)
]
STREAMED_TOOL_CONVERSATION_PARAMS: list[tuple[Url, list[Chunk], list[ResultData]]] = [
(
OPENAI_RESPONSES_TEST_BASE_URL,
[
_sse_event({
"type": "response.created",
"response": {
"id": "resp_fake_id_9012",
"object": "response",
"created_at": 1234567890,
"model": "gpt-4o-2024-08-06",
"output": [],
"usage": None,
},
}),
_sse_event({
"type": "response.in_progress",
"response": {"id": "resp_fake_id_9012"},
}),
_sse_event({
"type": "response.output_item.added",
"output_index": 0,
"item": _function_call_item(
"fc_fake_id_7890",
"call_fake_id_1111",
"some_tool",
"",
status="in_progress",
),
}),
_sse_event({
"type": "response.function_call_arguments.delta",
"output_index": 0,
"call_id": "call_fake_id_1111",
"delta": '{"some_argument": ',
}),
_sse_event({
"type": "response.function_call_arguments.delta",
"output_index": 0,
"call_id": "call_fake_id_1111",
"delta": '"some_argument_value"}',
}),
_sse_event({
"type": "response.function_call_arguments.done",
"output_index": 0,
"call_id": "call_fake_id_1111",
"name": "some_tool",
"arguments": '{"some_argument": "some_argument_value"}',
}),
_sse_event({
"type": "response.output_item.done",
"output_index": 0,
"item": _function_call_item(
"fc_fake_id_7890",
"call_fake_id_1111",
"some_tool",
'{"some_argument": "some_argument_value"}',
),
}),
_sse_event({
"type": "response.completed",
"response": {
"id": "resp_fake_id_9012",
"object": "response",
"created_at": 1234567890,
"model": "gpt-4o-2024-08-06",
"output": [
_function_call_item(
"fc_fake_id_7890",
"call_fake_id_1111",
"some_tool",
'{"some_argument": "some_argument_value"}',
)
],
"usage": {
"input_tokens": 100,
"output_tokens": 200,
"total_tokens": 300,
},
},
}),
_sse_event("[DONE]"),
],
[
_result(),
_result(),
_result(tool_calls=[_tool_call_result("some_tool", "", 0)]),
_result(),
_result(),
_result(
tool_calls=[
_tool_call_result(
"some_tool", '{"some_argument": "some_argument_value"}', 0
)
]
),
_result(),
_result(prompt_tokens=100, completion_tokens=200),
],
)
]

View file

@ -465,11 +465,14 @@ class TestAdapterPrepareRequest:
assert payload["temperature"] == 1
assert payload["max_tokens"] == expected_budget + 8192
@pytest.mark.parametrize(
"model_name", ["claude-opus-4-6-20260101", "claude-opus-4-7-20260418"]
)
@pytest.mark.parametrize("level", ["low", "medium", "high"])
def test_thinking_levels_adaptive_model(self, adapter, provider, level):
def test_thinking_levels_adaptive_model(self, adapter, provider, model_name, level):
messages = [LLMMessage(role=Role.user, content="Hello")]
req = adapter.prepare_request(
model_name="claude-opus-4-6-20260101",
model_name=model_name,
messages=messages,
temperature=0.5,
tools=None,
@ -480,11 +483,33 @@ class TestAdapterPrepareRequest:
thinking=level,
)
payload = json.loads(req.body)
assert payload["thinking"] == {"type": "adaptive"}
assert payload["thinking"] == {"type": "adaptive", "display": "summarized"}
assert payload["output_config"] == {"effort": level}
assert payload["temperature"] == 1
if "opus-4-7" in model_name:
assert "temperature" not in payload
else:
assert payload["temperature"] == 1
assert payload["max_tokens"] == 32_768
@pytest.mark.parametrize("thinking_level", ["off", "low", "medium", "high"])
def test_temperature_omitted_for_deprecated_model(
self, adapter, provider, thinking_level
):
messages = [LLMMessage(role=Role.user, content="Hello")]
req = adapter.prepare_request(
model_name="claude-opus-4-7-20260418",
messages=messages,
temperature=0.5,
tools=None,
max_tokens=None,
tool_choice=None,
enable_streaming=False,
provider=provider,
thinking=thinking_level,
)
payload = json.loads(req.body)
assert "temperature" not in payload
def test_history_forced_thinking_budget_model(self, adapter, provider):
messages = [
LLMMessage(role=Role.user, content="Hello"),
@ -533,7 +558,7 @@ class TestAdapterPrepareRequest:
provider=provider,
)
payload = json.loads(req.body)
assert payload["thinking"] == {"type": "adaptive"}
assert payload["thinking"] == {"type": "adaptive", "display": "summarized"}
assert payload["output_config"] == {"effort": "medium"}
assert payload["max_tokens"] == 32_768

File diff suppressed because it is too large Load diff

View file

@ -1,21 +1,29 @@
"""Tests for the Banner widget initial state with connectors/MCP."""
from __future__ import annotations
from unittest.mock import Mock, patch
from unittest.mock import Mock
from vibe.cli.textual_ui.widgets.banner.banner import (
Banner,
BannerState,
_connector_count,
_pluralize,
)
from vibe.cli.textual_ui.widgets.banner.banner import Banner, BannerState, _pluralize
from vibe.core.config import VibeConfig
from vibe.core.config._settings import ModelConfig, ThinkingLevel
from vibe.core.skills.manager import SkillManager
from vibe.core.tools.connectors.connector_registry import ConnectorRegistry
from vibe.core.tools.mcp.registry import MCPRegistry
def _make_mock_config(
active_model: str = "test-model", thinking: ThinkingLevel = "off"
) -> Mock:
config = Mock(spec=VibeConfig)
config.active_model = active_model
config.models = [active_model]
config.mcp_servers = []
config.connectors = []
config.disable_welcome_banner_animation = False
config.get_active_model.return_value = ModelConfig(
name=active_model, provider="mistral", alias=active_model, thinking=thinking
)
return config
class TestBannerInitialState:
"""Test that Banner properly displays initial state including connectors/MCP."""
@ -28,54 +36,27 @@ class TestBannerInitialState:
assert _pluralize(1, "MCP server") == "1 MCP server"
assert _pluralize(2, "connector") == "2 connectors"
def test_connector_count_with_registry(self) -> None:
"""Test _connector_count with a populated registry."""
registry = Mock(spec=ConnectorRegistry)
registry.connector_count = 3
assert _connector_count(registry) == 3
def test_connector_count_without_registry(self) -> None:
"""Test _connector_count with None registry."""
assert _connector_count(None) == 0
def test_banner_initial_state_includes_connectors(self) -> None:
"""Test that Banner._initial_state includes connector count."""
config = Mock(spec=VibeConfig)
config.active_model = "test-model"
config.models = ["test-model"]
config.mcp_servers = []
config.disable_welcome_banner_animation = False
skill_manager = Mock(spec=SkillManager)
skill_manager.custom_skills_count = 0
mcp_registry = Mock(spec=MCPRegistry)
mcp_registry.count_loaded.return_value = 0
connector_registry = Mock(spec=ConnectorRegistry)
connector_registry.connector_count = 5
banner = Banner(
config=config,
config=_make_mock_config(),
skill_manager=skill_manager,
mcp_registry=mcp_registry,
connector_registry=connector_registry,
connectors_count=5,
)
assert banner._initial_state.active_model == "test-model"
assert banner._initial_state.active_model == "test-model[off]"
assert banner._initial_state.models_count == 1
assert banner._initial_state.mcp_servers_count == 0
assert banner._initial_state.connectors_count == 5
assert banner._initial_state.skills_count == 0
def test_banner_initial_state_with_none_connector_registry(self) -> None:
"""Test that Banner._initial_state handles None connector registry."""
config = Mock(spec=VibeConfig)
config.active_model = "test-model"
config.models = ["test-model"]
config.mcp_servers = []
config.disable_welcome_banner_animation = False
def test_banner_initial_state_with_no_connectors(self) -> None:
skill_manager = Mock(spec=SkillManager)
skill_manager.custom_skills_count = 0
@ -83,23 +64,14 @@ class TestBannerInitialState:
mcp_registry.count_loaded.return_value = 0
banner = Banner(
config=config,
config=_make_mock_config(),
skill_manager=skill_manager,
mcp_registry=mcp_registry,
connector_registry=None,
)
assert banner._initial_state.connectors_count == 0
def test_format_meta_counts_includes_connectors(self) -> None:
"""Test that _format_meta_counts includes connector count when > 0."""
# Test _format_meta_counts by directly calling it on a Banner instance
config = Mock(spec=VibeConfig)
config.active_model = "test-model"
config.models = [] # Must be a list for len() to work
config.mcp_servers = []
config.disable_welcome_banner_animation = False
def test_banner_shows_thinking_level(self) -> None:
skill_manager = Mock(spec=SkillManager)
skill_manager.custom_skills_count = 0
@ -107,10 +79,24 @@ class TestBannerInitialState:
mcp_registry.count_loaded.return_value = 0
banner = Banner(
config=config,
config=_make_mock_config(thinking="max"),
skill_manager=skill_manager,
mcp_registry=mcp_registry,
)
assert banner._initial_state.active_model == "test-model[max]"
def test_format_meta_counts_includes_connectors(self) -> None:
skill_manager = Mock(spec=SkillManager)
skill_manager.custom_skills_count = 0
mcp_registry = Mock(spec=MCPRegistry)
mcp_registry.count_loaded.return_value = 0
banner = Banner(
config=_make_mock_config(),
skill_manager=skill_manager,
mcp_registry=mcp_registry,
connector_registry=None,
)
# Now test _format_meta_counts by setting state
@ -134,34 +120,19 @@ class TestBannerInitialState:
assert "5 skills" in result
class TestBannerWithEnabledConnectors:
"""Integration tests for Banner with EXPERIMENTAL_ENABLE_CONNECTORS=1."""
@patch("vibe.core.tools.connectors.connectors_enabled")
def test_connectors_enabled_flag(self, mock_enabled: Mock) -> None:
"""Test that connector count is read when enabled."""
mock_enabled.return_value = True
config = Mock(spec=VibeConfig)
config.active_model = "test-model"
config.models = ["test-model"]
config.mcp_servers = []
config.disable_welcome_banner_animation = False
class TestBannerConnectorsCount:
def test_connectors_count_passed_through(self) -> None:
skill_manager = Mock(spec=SkillManager)
skill_manager.custom_skills_count = 0
mcp_registry = Mock(spec=MCPRegistry)
mcp_registry.count_loaded.return_value = 0
connector_registry = Mock(spec=ConnectorRegistry)
connector_registry.connector_count = 5
banner = Banner(
config=config,
config=_make_mock_config(),
skill_manager=skill_manager,
mcp_registry=mcp_registry,
connector_registry=connector_registry,
connectors_count=5,
)
assert banner._initial_state.connectors_count == 5

View file

@ -8,6 +8,7 @@ import pytest
from tests.cli.plan_offer.adapters.fake_whoami_gateway import FakeWhoAmIGateway
from vibe.cli.plan_offer.decide_plan_offer import (
PlanInfo,
WhoAmIPlanType,
decide_plan_offer,
resolve_api_key_for_plan,
@ -171,3 +172,52 @@ def test_resolve_api_key_for_plan_with_missing_env_var() -> None:
if previous_api_key is not None:
environ["MISTRAL_API_KEY"] = previous_api_key
@pytest.mark.parametrize(
("response", "expected"),
[
(
WhoAmIResponse(
plan_type=WhoAmIPlanType.CHAT,
plan_name="INDIVIDUAL",
prompt_switching_to_pro_plan=False,
),
True,
),
(
WhoAmIResponse(
plan_type=WhoAmIPlanType.CHAT,
plan_name="INDIVIDUAL",
prompt_switching_to_pro_plan=True,
),
False,
),
(
WhoAmIResponse(
plan_type=WhoAmIPlanType.API,
plan_name="FREE",
prompt_switching_to_pro_plan=False,
),
False,
),
(
WhoAmIResponse(
plan_type=WhoAmIPlanType.MISTRAL_CODE,
plan_name="E",
prompt_switching_to_pro_plan=False,
),
False,
),
],
ids=[
"chat-plan-is-eligible",
"chat-plan-requiring-key-switch-is-ineligible",
"api-plan-is-ineligible",
"mistral-code-enterprise-is-ineligible",
],
)
def test_teleport_eligibility_depends_on_chat_plan_and_current_key(
response: WhoAmIResponse, expected: bool
) -> None:
assert PlanInfo.from_response(response).is_teleport_eligible() is expected

73
tests/cli/test_cache.py Normal file
View file

@ -0,0 +1,73 @@
from __future__ import annotations
from pathlib import Path
import tomllib
from vibe.cli.cache import read_cache, write_cache
class TestReadCache:
def test_reads_valid_toml(self, tmp_path: Path) -> None:
cache_path = tmp_path / "cache.toml"
cache_path.write_text('[update_cache]\nlatest_version = "1.0.0"\n')
result = read_cache(cache_path)
assert result["update_cache"]["latest_version"] == "1.0.0"
def test_returns_empty_dict_when_missing(self, tmp_path: Path) -> None:
assert read_cache(tmp_path / "missing.toml") == {}
def test_returns_empty_dict_when_corrupted(self, tmp_path: Path) -> None:
cache_path = tmp_path / "cache.toml"
cache_path.write_text("{bad toml")
assert read_cache(cache_path) == {}
class TestWriteCache:
def test_writes_new_file(self, tmp_path: Path) -> None:
cache_path = tmp_path / "cache.toml"
write_cache(cache_path, "feedback", {"last_shown_at": 100.0})
with cache_path.open("rb") as f:
data = tomllib.load(f)
assert data["feedback"]["last_shown_at"] == 100.0
def test_merges_with_existing(self, tmp_path: Path) -> None:
cache_path = tmp_path / "cache.toml"
cache_path.write_text('[update_cache]\nlatest_version = "1.0.0"\n')
write_cache(cache_path, "feedback", {"last_shown_at": 200.0})
with cache_path.open("rb") as f:
data = tomllib.load(f)
assert data["update_cache"]["latest_version"] == "1.0.0"
assert data["feedback"]["last_shown_at"] == 200.0
def test_merges_within_section_and_leaves_other_sections_alone(
self, tmp_path: Path
) -> None:
cache_path = tmp_path / "cache.toml"
cache_path.write_text(
"[update_cache]\n"
'latest_version = "1.0.0"\n'
"stored_at_timestamp = 1\n"
'seen_whats_new_version = "1.0.0"\n\n'
"[feedback]\n"
"last_shown_at = 100.0\n"
)
write_cache(
cache_path,
"update_cache",
{"latest_version": "2.0.0", "stored_at_timestamp": 2},
)
with cache_path.open("rb") as f:
data = tomllib.load(f)
assert data["update_cache"]["latest_version"] == "2.0.0"
assert data["update_cache"]["stored_at_timestamp"] == 2
assert data["update_cache"]["seen_whats_new_version"] == "1.0.0"
assert data["feedback"]["last_shown_at"] == 100.0

View file

@ -1,6 +1,7 @@
from __future__ import annotations
import base64
import subprocess
from types import SimpleNamespace
from typing import cast
from unittest.mock import MagicMock, mock_open, patch
@ -16,6 +17,7 @@ from vibe.cli.clipboard import (
_copy_xclip,
_read_clipboard,
copy_selection_to_clipboard,
copy_text_to_clipboard,
)
@ -174,6 +176,44 @@ def test_copy_selection_to_clipboard_multiple_widgets(mock_app: MagicMock) -> No
)
@patch("vibe.cli.clipboard._copy_to_clipboard")
def test_copy_text_to_clipboard_success(
mock_copy_to_clipboard: MagicMock, mock_app: MagicMock
) -> None:
result = copy_text_to_clipboard(
mock_app, "assistant text", success_message="Agent message copied"
)
assert result == "assistant text"
mock_copy_to_clipboard.assert_called_once_with("assistant text")
mock_app.notify.assert_called_once_with(
"Agent message copied", severity="information", timeout=2, markup=False
)
@patch("vibe.cli.clipboard._copy_to_clipboard")
def test_copy_text_to_clipboard_shows_failure_when_clipboard_unavailable(
mock_copy_to_clipboard: MagicMock, mock_app: MagicMock
) -> None:
mock_copy_to_clipboard.side_effect = RuntimeError("All clipboard strategies failed")
result = copy_text_to_clipboard(mock_app, "assistant text")
assert result is None
mock_copy_to_clipboard.assert_called_once_with("assistant text")
mock_app.notify.assert_called_once_with(
"Failed to copy - clipboard not available", severity="warning", timeout=3
)
def test_copy_text_to_clipboard_returns_none_for_empty_text(
mock_app: MagicMock,
) -> None:
result = copy_text_to_clipboard(mock_app, "")
assert result is None
mock_app.notify.assert_not_called()
def test_copy_to_clipboard_stops_after_verified_copy() -> None:
"""Stops iterating once _read_clipboard confirms the text landed."""
mock_first = MagicMock()
@ -244,21 +284,28 @@ def test_read_clipboard_skips_failing_reader() -> None:
@patch("subprocess.run")
def test_copy_pbcopy(mock_run: MagicMock) -> None:
_copy_pbcopy("hello")
mock_run.assert_called_once_with(["pbcopy"], input=b"hello", check=True)
mock_run.assert_called_once_with(
["pbcopy"], input=b"hello", check=True, stderr=subprocess.DEVNULL
)
@patch("subprocess.run")
def test_copy_xclip(mock_run: MagicMock) -> None:
_copy_xclip("hello")
mock_run.assert_called_once_with(
["xclip", "-selection", "clipboard"], input=b"hello", check=True
["xclip", "-selection", "clipboard"],
input=b"hello",
check=True,
stderr=subprocess.DEVNULL,
)
@patch("subprocess.run")
def test_copy_wl_copy(mock_run: MagicMock) -> None:
_copy_wl_copy("hello")
mock_run.assert_called_once_with(["wl-copy"], input=b"hello", check=True)
mock_run.assert_called_once_with(
["wl-copy"], input=b"hello", check=True, stderr=subprocess.DEVNULL
)
def test_copy_methods_includes_available_commands() -> None:

View file

@ -1,6 +1,20 @@
from __future__ import annotations
from vibe.cli.commands import Command, CommandRegistry
from vibe.cli.commands import Command, CommandAvailabilityContext, CommandRegistry
from vibe.cli.plan_offer.decide_plan_offer import PlanInfo
from vibe.cli.plan_offer.ports.whoami_gateway import WhoAmIPlanType
def _eligible_teleport_context() -> CommandAvailabilityContext:
return CommandAvailabilityContext(
vibe_code_enabled=True,
is_active_model_mistral=True,
plan_info=PlanInfo(
plan_type=WhoAmIPlanType.CHAT,
plan_name="INDIVIDUAL",
prompt_switching_to_pro_plan=False,
),
)
class TestCommandRegistry:
@ -59,6 +73,26 @@ class TestCommandRegistry:
assert registry.parse_command("/exit") is None
assert registry.get_command_name("/help") == "help"
def test_teleport_command_hidden_without_eligible_context(self) -> None:
registry = CommandRegistry()
assert registry.get_command_name("/teleport") is None
assert registry.parse_command("/teleport") is None
def test_teleport_command_registration_uses_resolved_context(self) -> None:
registry = CommandRegistry(availability_context=_eligible_teleport_context())
assert registry.get_command_name("/teleport") == "teleport"
assert registry.has_command("teleport")
def test_teleport_help_text_uses_resolved_context(self) -> None:
registry = CommandRegistry()
assert "/teleport" not in registry.get_help_text()
eligible_registry = CommandRegistry(
availability_context=_eligible_teleport_context()
)
assert eligible_registry.get("teleport") is not None
assert "/teleport" in eligible_registry.get_help_text()
def test_resume_command_registration(self) -> None:
registry = CommandRegistry()
assert registry.get_command_name("/resume") == "resume"

View file

@ -0,0 +1,53 @@
from __future__ import annotations
from unittest.mock import patch
import pytest
from tests.conftest import build_test_vibe_app
from vibe.cli.textual_ui.widgets.messages import AssistantMessage
@pytest.mark.asyncio
async def test_copy_command_copies_last_assistant_message() -> None:
app = build_test_vibe_app()
second_reply = "\n```python\nprint('second reply')\n```\n"
stripped_second_reply = second_reply.strip()
async with app.run_test() as pilot:
await app._mount_and_scroll(AssistantMessage("first reply"))
await app._mount_and_scroll(AssistantMessage(second_reply))
with (
patch(
"vibe.cli.textual_ui.app.copy_text_to_clipboard",
return_value=stripped_second_reply,
) as mock_copy,
patch.object(
app.agent_loop.telemetry_client, "send_user_copied_text"
) as mock_telemetry,
):
handled = await app._handle_command("/copy")
await pilot.pause()
assert handled is True
assert stripped_second_reply != second_reply
mock_copy.assert_called_once_with(
app,
stripped_second_reply,
success_message="Last agent message copied to clipboard",
)
mock_telemetry.assert_called_once_with(stripped_second_reply)
@pytest.mark.asyncio
async def test_copy_command_warns_when_no_assistant_message() -> None:
app = build_test_vibe_app()
async with app.run_test() as pilot:
with patch.object(app, "notify") as mock_notify:
handled = await app._handle_command("/copy")
await pilot.pause()
assert handled is True
mock_notify.assert_called_once_with(
"No agent message available to copy", severity="warning", timeout=3
)

View file

@ -4,13 +4,13 @@ from unittest.mock import patch
import pytest
from tests.snapshots.base_snapshot_test_app import BaseSnapshotTestApp
from tests.conftest import build_test_vibe_app, build_test_vibe_config
@pytest.mark.asyncio
async def test_ctrl_y_triggers_copy_selection() -> None:
"""Test that ctrl+y keybinding triggers copy_selection_to_clipboard."""
app = BaseSnapshotTestApp()
app = build_test_vibe_app()
with patch("vibe.cli.textual_ui.app.copy_selection_to_clipboard") as mock_copy:
async with app.run_test() as pilot:
@ -21,7 +21,7 @@ async def test_ctrl_y_triggers_copy_selection() -> None:
@pytest.mark.asyncio
async def test_ctrl_shift_c_triggers_copy_selection() -> None:
"""Test that ctrl+shift+c keybinding triggers copy_selection_to_clipboard."""
app = BaseSnapshotTestApp()
app = build_test_vibe_app()
with patch("vibe.cli.textual_ui.app.copy_selection_to_clipboard") as mock_copy:
async with app.run_test() as pilot:
@ -32,11 +32,7 @@ async def test_ctrl_shift_c_triggers_copy_selection() -> None:
@pytest.mark.asyncio
async def test_mouse_up_respects_autocopy_config_enabled() -> None:
"""Test that mouse up copies when autocopy_to_clipboard is True."""
from tests.snapshots.base_snapshot_test_app import default_config
config = default_config()
config.autocopy_to_clipboard = True
app = BaseSnapshotTestApp(config=config)
app = build_test_vibe_app(config=build_test_vibe_config(autocopy_to_clipboard=True))
with patch("vibe.cli.textual_ui.app.copy_selection_to_clipboard") as mock_copy:
async with app.run_test() as pilot:
@ -47,11 +43,9 @@ async def test_mouse_up_respects_autocopy_config_enabled() -> None:
@pytest.mark.asyncio
async def test_mouse_up_respects_autocopy_config_disabled() -> None:
"""Test that mouse up does not copy when autocopy_to_clipboard is False."""
from tests.snapshots.base_snapshot_test_app import default_config
config = default_config()
config.autocopy_to_clipboard = False
app = BaseSnapshotTestApp(config=config)
app = build_test_vibe_app(
config=build_test_vibe_config(autocopy_to_clipboard=False)
)
with patch("vibe.cli.textual_ui.app.copy_selection_to_clipboard") as mock_copy:
async with app.run_test() as pilot:

View file

@ -6,27 +6,21 @@ from vibe.cli.textual_ui.widgets.feedback_bar import FeedbackBar
class TestFeedbackBarState:
def test_maybe_show_shows_when_random_below_threshold(self):
def test_show_activates(self):
bar = FeedbackBar()
bar.display = False
bar._set_active = MagicMock()
with patch(
"vibe.cli.textual_ui.widgets.feedback_bar.random.random", return_value=0
):
bar.maybe_show()
bar.show()
bar._set_active.assert_called_once_with(True)
def test_maybe_show_does_not_show_when_random_above_threshold(self):
def test_show_skips_when_already_displayed(self):
bar = FeedbackBar()
bar.display = False
bar.display = True
bar._set_active = MagicMock()
with patch(
"vibe.cli.textual_ui.widgets.feedback_bar.random.random", return_value=1.0
):
bar.maybe_show()
bar.show()
bar._set_active.assert_not_called()

View file

@ -0,0 +1,149 @@
from __future__ import annotations
from pathlib import Path
import time
import tomllib
from unittest.mock import MagicMock, patch
from vibe.cli.textual_ui.widgets.feedback_bar_manager import (
_CACHE_SECTION,
_LAST_SHOWN_KEY,
FEEDBACK_COOLDOWN_SECONDS,
MIN_USER_MESSAGES_FOR_FEEDBACK,
FeedbackBarManager,
)
from vibe.core.types import LLMMessage, Role
def _patch_cache_file(tmp_path: Path):
from vibe.core.paths._vibe_home import GlobalPath
return patch(
"vibe.cli.textual_ui.widgets.feedback_bar_manager.CACHE_FILE",
GlobalPath(lambda: tmp_path / "cache.toml"),
)
def _patch_probability(value: float):
return patch(
"vibe.cli.textual_ui.widgets.feedback_bar_manager.FEEDBACK_PROBABILITY", value
)
def _make_agent_loop(
user_message_count: int = MIN_USER_MESSAGES_FOR_FEEDBACK,
telemetry_active: bool = True,
) -> MagicMock:
loop = MagicMock()
loop.telemetry_client.is_active.return_value = telemetry_active
messages = [
LLMMessage(role=Role.user, content=f"msg {i}")
for i in range(user_message_count)
]
loop.messages = messages
return loop
class TestShouldShow:
def test_shows_when_conditions_met(self, tmp_path: Path) -> None:
manager = FeedbackBarManager()
with (
_patch_cache_file(tmp_path),
_patch_probability(0.2),
patch(
"vibe.cli.textual_ui.widgets.feedback_bar_manager.random.random",
return_value=0.0,
),
):
assert manager.should_show(_make_agent_loop()) is True
def test_does_not_show_when_random_misses(self, tmp_path: Path) -> None:
manager = FeedbackBarManager()
with (
_patch_cache_file(tmp_path),
_patch_probability(0.2),
patch(
"vibe.cli.textual_ui.widgets.feedback_bar_manager.random.random",
return_value=1.0,
),
):
assert manager.should_show(_make_agent_loop()) is False
def test_does_not_show_within_cooldown(self, tmp_path: Path) -> None:
(tmp_path / "cache.toml").write_text(
f"[{_CACHE_SECTION}]\n{_LAST_SHOWN_KEY} = {int(time.time()) - 60}\n"
)
manager = FeedbackBarManager()
with (
_patch_cache_file(tmp_path),
_patch_probability(0.2),
patch(
"vibe.cli.textual_ui.widgets.feedback_bar_manager.random.random",
return_value=0.0,
),
):
assert manager.should_show(_make_agent_loop()) is False
def test_shows_after_cooldown_expires(self, tmp_path: Path) -> None:
(tmp_path / "cache.toml").write_text(
f"[{_CACHE_SECTION}]\n{_LAST_SHOWN_KEY} = {int(time.time()) - FEEDBACK_COOLDOWN_SECONDS - 1}\n"
)
manager = FeedbackBarManager()
with (
_patch_cache_file(tmp_path),
_patch_probability(0.2),
patch(
"vibe.cli.textual_ui.widgets.feedback_bar_manager.random.random",
return_value=0.0,
),
):
assert manager.should_show(_make_agent_loop()) is True
def test_does_not_show_when_telemetry_inactive(self, tmp_path: Path) -> None:
manager = FeedbackBarManager()
with _patch_cache_file(tmp_path), _patch_probability(0.2):
assert (
manager.should_show(_make_agent_loop(telemetry_active=False)) is False
)
def test_does_not_show_when_too_few_user_messages(self, tmp_path: Path) -> None:
manager = FeedbackBarManager()
with (
_patch_cache_file(tmp_path),
_patch_probability(0.2),
patch(
"vibe.cli.textual_ui.widgets.feedback_bar_manager.random.random",
return_value=0.0,
),
):
assert manager.should_show(_make_agent_loop(user_message_count=1)) is False
def test_skips_injected_messages_in_count(self, tmp_path: Path) -> None:
loop = _make_agent_loop(user_message_count=0)
loop.messages = [
LLMMessage(role=Role.user, content="real"),
LLMMessage(role=Role.user, content="injected", injected=True),
LLMMessage(role=Role.assistant, content="reply"),
]
manager = FeedbackBarManager()
with (
_patch_cache_file(tmp_path),
_patch_probability(0.2),
patch(
"vibe.cli.textual_ui.widgets.feedback_bar_manager.random.random",
return_value=0.0,
),
):
# Only 1 non-injected user message, below MIN_USER_MESSAGES_FOR_FEEDBACK
assert manager.should_show(loop) is False
class TestRecordFeedbackAsked:
def test_writes_timestamp_to_cache(self, tmp_path: Path) -> None:
manager = FeedbackBarManager()
before = int(time.time())
with _patch_cache_file(tmp_path):
manager.record_feedback_asked()
with (tmp_path / "cache.toml").open("rb") as f:
data = tomllib.load(f)
assert data[_CACHE_SECTION][_LAST_SHOWN_KEY] >= before

View file

@ -150,9 +150,7 @@ class TestMCPAppInit:
app = MCPApp(mcp_servers=servers, tool_manager=mgr)
app._viewing_server = "srv"
render_calls: list[str | None] = []
app._refresh_view = lambda server_name, *, kind=None: render_calls.append(
server_name
)
app._refresh_view = lambda server_name, **_kw: render_calls.append(server_name)
app.action_back()
assert render_calls == [None]
@ -161,9 +159,7 @@ class TestMCPAppInit:
app = MCPApp(mcp_servers=[], tool_manager=mgr)
app._viewing_server = None
render_calls: list[str | None] = []
app._refresh_view = lambda server_name, *, kind=None: render_calls.append(
server_name
)
app._refresh_view = lambda server_name, **_kw: render_calls.append(server_name)
app.action_back()
assert render_calls == []
@ -176,17 +172,13 @@ class TestMCPAppInit:
mcp_servers=servers, tool_manager=mgr, refresh_callback=refresh_callback
)
app._viewing_server = "srv"
render_calls: list[tuple[str | None, str | None]] = []
app._refresh_view = lambda server_name, *, kind=None: render_calls.append((
server_name,
kind,
))
app._set_help_text = MagicMock()
app.run_worker = MagicMock()
await app.action_refresh()
assert app._status_message == "Refreshing..."
assert render_calls == [("srv", None)]
assert app._refreshing is True
app.run_worker.assert_called_once()
def test_on_worker_state_changed_updates_after_refresh(self) -> None:

View file

@ -0,0 +1,194 @@
from __future__ import annotations
import argparse
from pathlib import Path
import pytest
from vibe.cli import cli as cli_mod, entrypoint as entrypoint_mod
from vibe.core.config import MissingAPIKeyError
from vibe.core.trusted_folders import trusted_folders_manager
def _make_args(**overrides: object) -> argparse.Namespace:
base: dict[str, object] = {
"initial_prompt": None,
"prompt": "hello",
"max_turns": None,
"max_price": None,
"enabled_tools": None,
"output": "text",
"agent": "default",
"setup": False,
"workdir": None,
"trust": False,
"teleport": False,
"continue_session": False,
"resume": None,
}
base.update(overrides)
return argparse.Namespace(**base)
def test_programmatic_mode_does_not_run_onboarding_on_missing_api_key(
monkeypatch: pytest.MonkeyPatch, capsys: pytest.CaptureFixture[str]
) -> None:
def boom() -> None:
raise MissingAPIKeyError("MISTRAL_API_KEY", "mistral")
monkeypatch.setattr(cli_mod.VibeConfig, "load", staticmethod(boom))
sentinel: dict[str, bool] = {"called": False}
def fail_onboarding(*_args: object, **_kwargs: object) -> None:
sentinel["called"] = True
monkeypatch.setattr(cli_mod, "run_onboarding", fail_onboarding)
with pytest.raises(SystemExit) as exc_info:
cli_mod.load_config_or_exit(interactive=False)
assert exc_info.value.code == 1
assert sentinel["called"] is False
err = capsys.readouterr().err
assert "MISTRAL_API_KEY" in err
assert "vibe --setup" in err
def test_interactive_mode_still_runs_onboarding_on_missing_api_key(
monkeypatch: pytest.MonkeyPatch,
) -> None:
# Replace VibeConfig.load with a stub that fails the first time.
state = {"raised": False}
def fake_load() -> object:
if not state["raised"]:
state["raised"] = True
raise MissingAPIKeyError("MISTRAL_API_KEY", "mistral")
return "config-sentinel"
monkeypatch.setattr(cli_mod.VibeConfig, "load", staticmethod(fake_load))
onboarding_called: list[bool] = []
monkeypatch.setattr(
cli_mod, "run_onboarding", lambda *a, **k: onboarding_called.append(True)
)
result = cli_mod.load_config_or_exit(interactive=True)
assert onboarding_called == [True]
assert result == "config-sentinel"
def test_warn_if_workdir_untrusted_writes_stderr_when_project_config_present(
tmp_path: Path, monkeypatch: pytest.MonkeyPatch, capsys: pytest.CaptureFixture[str]
) -> None:
project = tmp_path / "proj"
project.mkdir()
(project / "AGENTS.md").write_text("hello", encoding="utf-8")
monkeypatch.chdir(project)
cli_mod.warn_if_workdir_trust_is_unset()
err = " ".join(capsys.readouterr().err.split())
assert "not trusted" in err
assert "AGENTS.md" in err
assert "--trust" in err
def test_warn_if_workdir_untrusted_silent_when_already_trusted(
tmp_path: Path, monkeypatch: pytest.MonkeyPatch, capsys: pytest.CaptureFixture[str]
) -> None:
project = tmp_path / "proj"
project.mkdir()
(project / "AGENTS.md").write_text("hello", encoding="utf-8")
monkeypatch.chdir(project)
trusted_folders_manager.add_trusted(project)
cli_mod.warn_if_workdir_trust_is_unset()
assert capsys.readouterr().err == ""
def test_warn_if_workdir_untrusted_silent_when_no_project_config(
tmp_path: Path, monkeypatch: pytest.MonkeyPatch, capsys: pytest.CaptureFixture[str]
) -> None:
project = tmp_path / "proj"
project.mkdir()
monkeypatch.chdir(project)
cli_mod.warn_if_workdir_trust_is_unset()
assert capsys.readouterr().err == ""
def test_trust_flag_trusts_cwd_for_session_only(
tmp_path: Path, monkeypatch: pytest.MonkeyPatch
) -> None:
project = tmp_path / "proj"
project.mkdir()
monkeypatch.chdir(project)
args = _make_args(trust=True, prompt=None)
monkeypatch.setattr(entrypoint_mod, "parse_arguments", lambda: args)
monkeypatch.setattr(
entrypoint_mod, "check_and_resolve_trusted_folder", lambda _cwd: None
)
monkeypatch.setattr(
entrypoint_mod, "init_harness_files_manager", lambda *a, **k: None
)
# Stop main() before it runs the actual CLI.
monkeypatch.setattr(
"vibe.cli.cli.run_cli", lambda _args: (_ for _ in ()).throw(SystemExit(0))
)
with pytest.raises(SystemExit) as exc_info:
entrypoint_mod.main()
assert exc_info.value.code == 0
assert trusted_folders_manager.is_trusted(project) is True
# --trust must NOT persist to trusted_folders.toml.
assert trusted_folders_manager._trusted == []
assert str(project.resolve()) in trusted_folders_manager._session_trusted
def test_trust_flag_works_in_programmatic_mode(
tmp_path: Path, monkeypatch: pytest.MonkeyPatch
) -> None:
project = tmp_path / "proj"
project.mkdir()
monkeypatch.chdir(project)
args = _make_args(trust=True, prompt="run")
monkeypatch.setattr(entrypoint_mod, "parse_arguments", lambda: args)
monkeypatch.setattr(
entrypoint_mod,
"check_and_resolve_trusted_folder",
lambda _cwd: pytest.fail("must not prompt in -p mode"),
)
monkeypatch.setattr(
entrypoint_mod, "init_harness_files_manager", lambda *a, **k: None
)
monkeypatch.setattr(
"vibe.cli.cli.run_cli", lambda _args: (_ for _ in ()).throw(SystemExit(0))
)
with pytest.raises(SystemExit):
entrypoint_mod.main()
assert trusted_folders_manager.is_trusted(project) is True
assert trusted_folders_manager._trusted == []
def test_session_trust_does_not_write_to_disk(
tmp_path: Path, monkeypatch: pytest.MonkeyPatch
) -> None:
trust_file = tmp_path / "trusted_folders.toml"
monkeypatch.setattr(trusted_folders_manager, "_file_path", trust_file)
project = tmp_path / "proj"
project.mkdir()
trusted_folders_manager.trust_for_session(project)
assert trusted_folders_manager.is_trusted(project) is True
assert not trust_file.exists()

View file

@ -0,0 +1,73 @@
from __future__ import annotations
import os
import sys
from unittest.mock import patch
import pytest
from vibe.cli.stderr_guard import stderr_guard
_FORCE_ACTIVE = patch("vibe.cli.stderr_guard._is_stderr_a_tty", return_value=True)
@pytest.mark.skipif(sys.platform == "win32", reason="fd redirect is Unix-only")
class TestStderrGuard:
def test_fd2_redirected_to_devnull_inside_guard(self) -> None:
with _FORCE_ACTIVE:
with stderr_guard():
devnull_stat = os.stat(os.devnull)
fd2_stat = os.fstat(2)
assert fd2_stat.st_rdev == devnull_stat.st_rdev
def test_fd2_restored_after_guard(self) -> None:
stat_before = os.fstat(2)
with _FORCE_ACTIVE:
with stderr_guard():
stat_inside = os.fstat(2)
assert stat_inside.st_ino != stat_before.st_ino
stat_after = os.fstat(2)
assert stat_after.st_ino == stat_before.st_ino
def test_sys_stderr_restored_after_exit(self) -> None:
original_stderr = sys.stderr
original_dunder = sys.__stderr__
with _FORCE_ACTIVE:
with stderr_guard():
assert sys.__stderr__ is not original_dunder
assert sys.stderr is original_stderr
assert sys.__stderr__ is original_dunder
def test_restores_stderr_when_render_flush_raises_value_error(self) -> None:
original_stderr = sys.stderr
original_dunder = sys.__stderr__
stat_before = os.fstat(2)
with _FORCE_ACTIVE:
with stderr_guard():
assert sys.__stderr__ is not None
sys.__stderr__.close()
stat_after = os.fstat(2)
assert stat_after.st_ino == stat_before.st_ino
assert sys.stderr is original_stderr
assert sys.__stderr__ is original_dunder
def test_render_file_is_writable_inside_guard(self) -> None:
with _FORCE_ACTIVE:
with stderr_guard():
assert sys.__stderr__ is not None
assert sys.__stderr__.writable()
def test_noop_when_stderr_is_not_a_tty(self) -> None:
original_stderr = sys.stderr
with patch("vibe.cli.stderr_guard._is_stderr_a_tty", return_value=False):
with stderr_guard():
assert sys.stderr is original_stderr
def test_native_write_to_fd2_goes_to_devnull(self) -> None:
with _FORCE_ACTIVE:
with stderr_guard():
# Should not raise; bytes vanish into /dev/null.
written = os.write(2, b"stray MallocStackLogging message\n")
assert written > 0

View file

@ -1,6 +1,6 @@
from __future__ import annotations
from unittest.mock import patch
from unittest.mock import AsyncMock, patch
import pytest
@ -8,7 +8,8 @@ from tests.conftest import build_test_vibe_app, build_test_vibe_config
from vibe.cli.textual_ui.app import BottomApp
from vibe.cli.textual_ui.widgets.config_app import ConfigApp
from vibe.cli.textual_ui.widgets.model_picker import ModelPickerApp
from vibe.core.config._settings import ModelConfig
from vibe.cli.textual_ui.widgets.thinking_picker import ThinkingPickerApp
from vibe.core.config._settings import THINKING_LEVELS, ModelConfig
def _make_config_with_models():
@ -60,7 +61,8 @@ async def test_config_toggle_autocopy() -> None:
await app._show_config()
await pilot.pause(0.2)
# Navigate down to Auto-copy (second item) and toggle
# Navigate down to Auto-copy (third item, after Model + Thinking) and toggle
await pilot.press("down")
await pilot.press("down")
await pilot.press("enter")
await pilot.pause(0.1)
@ -80,7 +82,8 @@ async def test_config_escape_saves_changes() -> None:
await app._show_config()
await pilot.pause(0.2)
# Toggle auto-copy
# Toggle auto-copy (skip Model + Thinking rows)
await pilot.press("down")
await pilot.press("down")
await pilot.press("enter")
await pilot.pause(0.1)
@ -268,13 +271,15 @@ async def test_config_pending_changes_saved_before_model_picker() -> None:
await app._show_config()
await pilot.pause(0.2)
# Toggle auto-copy (second row)
# Toggle auto-copy (third row, after Model + Thinking)
await pilot.press("down")
await pilot.press("down")
await pilot.press("enter")
await pilot.pause(0.1)
# Go back up to model row and open model picker
await pilot.press("up")
await pilot.press("up")
with patch("vibe.cli.textual_ui.app.VibeConfig.save_updates") as mock_save:
await pilot.press("enter")
await pilot.pause(0.3)
@ -282,3 +287,151 @@ async def test_config_pending_changes_saved_before_model_picker() -> None:
mock_save.assert_called_once()
changes = mock_save.call_args[0][0]
assert changes["autocopy_to_clipboard"] is True
# --- /thinking command ---
@pytest.mark.asyncio
async def test_thinking_opens_thinking_picker() -> None:
app = build_test_vibe_app(config=_make_config_with_models())
async with app.run_test() as pilot:
await pilot.pause(0.1)
await app._show_thinking()
await pilot.pause(0.2)
assert app._current_bottom_app == BottomApp.ThinkingPicker
assert len(app.query(ThinkingPickerApp)) == 1
@pytest.mark.asyncio
async def test_thinking_picker_shows_all_levels() -> None:
app = build_test_vibe_app(config=_make_config_with_models())
async with app.run_test() as pilot:
await pilot.pause(0.1)
await app._show_thinking()
await pilot.pause(0.2)
picker = app.query_one(ThinkingPickerApp)
assert picker._thinking_levels == THINKING_LEVELS
assert picker._current_thinking == "off"
@pytest.mark.asyncio
async def test_thinking_picker_escape_returns_to_input() -> None:
app = build_test_vibe_app(config=_make_config_with_models())
async with app.run_test() as pilot:
await pilot.pause(0.1)
await app._show_thinking()
await pilot.pause(0.2)
await pilot.press("escape")
await pilot.pause(0.2)
assert app._current_bottom_app == BottomApp.Input
assert len(app.query(ThinkingPickerApp)) == 0
@pytest.mark.asyncio
async def test_thinking_picker_select_level() -> None:
app = build_test_vibe_app(config=_make_config_with_models())
async with app.run_test() as pilot:
await pilot.pause(0.1)
await app._show_thinking()
await pilot.pause(0.2)
# Navigate down to "low" (second item) and select
await pilot.press("down")
with patch.object(app, "_reload_config", new=AsyncMock()):
await pilot.press("enter")
await pilot.pause(0.2)
assert app._current_bottom_app == BottomApp.Input
assert len(app.query(ThinkingPickerApp)) == 0
assert app.config.get_active_model().thinking == "low"
@pytest.mark.asyncio
async def test_thinking_picker_select_high() -> None:
app = build_test_vibe_app(config=_make_config_with_models())
async with app.run_test() as pilot:
await pilot.pause(0.1)
await app._show_thinking()
await pilot.pause(0.2)
# Navigate to "high" (4th item = 3 downs from "off")
await pilot.press("down")
await pilot.press("down")
await pilot.press("down")
with patch.object(app, "_reload_config", new=AsyncMock()):
await pilot.press("enter")
await pilot.pause(0.2)
assert app.config.get_active_model().thinking == "high"
# --- config -> thinking picker flow ---
@pytest.mark.asyncio
async def test_config_thinking_entry_opens_thinking_picker() -> None:
app = build_test_vibe_app(config=_make_config_with_models())
async with app.run_test() as pilot:
await pilot.pause(0.1)
await app._show_config()
await pilot.pause(0.2)
# Thinking row is the second item (after Model). Navigate down and press enter.
await pilot.press("down")
await pilot.press("enter")
await pilot.pause(0.3)
assert app._current_bottom_app == BottomApp.ThinkingPicker
assert len(app.query(ThinkingPickerApp)) == 1
assert len(app.query(ConfigApp)) == 0
@pytest.mark.asyncio
async def test_config_to_thinking_picker_escape_returns_to_input() -> None:
app = build_test_vibe_app(config=_make_config_with_models())
async with app.run_test() as pilot:
await pilot.pause(0.1)
await app._show_config()
await pilot.pause(0.2)
# Open thinking picker from config
await pilot.press("down")
await pilot.press("enter")
await pilot.pause(0.3)
# Escape thinking picker
await pilot.press("escape")
await pilot.pause(0.2)
assert app._current_bottom_app == BottomApp.Input
assert len(app.query(ThinkingPickerApp)) == 0
assert len(app.query(ConfigApp)) == 0
@pytest.mark.asyncio
async def test_config_to_thinking_picker_select_returns_to_input() -> None:
app = build_test_vibe_app(config=_make_config_with_models())
async with app.run_test() as pilot:
await pilot.pause(0.1)
await app._show_config()
await pilot.pause(0.2)
# Open thinking picker from config
await pilot.press("down")
await pilot.press("enter")
await pilot.pause(0.3)
# Select "medium" (3rd item = 2 downs from "off")
await pilot.press("down")
await pilot.press("down")
with patch.object(app, "_reload_config", new=AsyncMock()):
await pilot.press("enter")
await pilot.pause(0.2)
assert app._current_bottom_app == BottomApp.Input
assert app.config.get_active_model().thinking == "medium"

View file

@ -0,0 +1,188 @@
from __future__ import annotations
import time
from unittest.mock import AsyncMock, patch
import pytest
from tests.cli.plan_offer.adapters.fake_whoami_gateway import FakeWhoAmIGateway
from tests.conftest import build_test_vibe_app, build_test_vibe_config
from vibe.cli.plan_offer.ports.whoami_gateway import WhoAmIPlanType, WhoAmIResponse
from vibe.cli.textual_ui.widgets.chat_input import ChatInputContainer
from vibe.core.config import ModelConfig, ProviderConfig, VibeConfig
from vibe.core.types import Backend
def _chat_plan_gateway(*, prompt_switching_to_pro_plan: bool) -> FakeWhoAmIGateway:
return FakeWhoAmIGateway(
WhoAmIResponse(
plan_type=WhoAmIPlanType.CHAT,
plan_name="INDIVIDUAL",
prompt_switching_to_pro_plan=prompt_switching_to_pro_plan,
)
)
def _vibe_code_enabled_config() -> VibeConfig:
return build_test_vibe_config(vibe_code_enabled=True)
async def _wait_until(pause, predicate, timeout: float = 2.0) -> None:
start = time.monotonic()
while time.monotonic() - start < timeout:
if predicate():
return
await pause(0.02)
raise AssertionError("Condition was not met within the timeout")
@pytest.mark.asyncio
async def test_teleport_command_visible_for_paid_chat_users() -> None:
app = build_test_vibe_app(
config=_vibe_code_enabled_config(),
plan_offer_gateway=_chat_plan_gateway(prompt_switching_to_pro_plan=False),
)
async with app.run_test() as pilot:
await _wait_until(
pilot.pause,
lambda: app.commands.get_command_name("/teleport") == "teleport",
)
assert app.commands.get_command_name("/teleport") == "teleport"
assert "/teleport" in app.commands.get_help_text()
input_widget = app.query_one(ChatInputContainer).input_widget
assert input_widget is not None
assert "&" in input_widget.mode_characters
@pytest.mark.asyncio
async def test_teleport_command_hidden_when_current_key_is_not_eligible() -> None:
app = build_test_vibe_app(
config=_vibe_code_enabled_config(),
plan_offer_gateway=_chat_plan_gateway(prompt_switching_to_pro_plan=True),
)
async with app.run_test() as pilot:
await pilot.pause(0.2)
assert app.commands.get_command_name("/teleport") is None
assert "/teleport" not in app.commands.get_help_text()
input_widget = app.query_one(ChatInputContainer).input_widget
assert input_widget is not None
assert "&" not in input_widget.mode_characters
@pytest.mark.asyncio
async def test_hidden_teleport_command_falls_through_as_user_text() -> None:
app = build_test_vibe_app(
config=_vibe_code_enabled_config(),
plan_offer_gateway=_chat_plan_gateway(prompt_switching_to_pro_plan=True),
)
async with app.run_test() as pilot:
await pilot.pause(0.2)
app._handle_teleport_command = AsyncMock()
app._handle_user_message = AsyncMock()
await app.on_chat_input_container_submitted(
ChatInputContainer.Submitted("/teleport")
)
app._handle_teleport_command.assert_not_awaited()
app._handle_user_message.assert_awaited_once_with("/teleport")
@pytest.mark.asyncio
async def test_hidden_ampersand_teleport_shortcut_falls_through_as_user_text() -> None:
app = build_test_vibe_app(
config=_vibe_code_enabled_config(),
plan_offer_gateway=_chat_plan_gateway(prompt_switching_to_pro_plan=True),
)
async with app.run_test() as pilot:
await pilot.pause(0.2)
app._handle_teleport_command = AsyncMock()
app._handle_user_message = AsyncMock()
await app.on_chat_input_container_submitted(
ChatInputContainer.Submitted("&continue")
)
app._handle_teleport_command.assert_not_awaited()
app._handle_user_message.assert_awaited_once_with("&continue")
@pytest.mark.asyncio
async def test_teleport_command_hides_after_switching_to_non_mistral_model(
monkeypatch: pytest.MonkeyPatch,
) -> None:
monkeypatch.setenv("OPENAI_API_KEY", "mock-openai-key")
config = build_test_vibe_config(
vibe_code_enabled=True,
providers=[
ProviderConfig(
name="mistral",
api_base="https://api.mistral.ai/v1",
api_key_env_var="MISTRAL_API_KEY",
backend=Backend.MISTRAL,
),
ProviderConfig(
name="openai",
api_base="https://api.openai.com/v1",
api_key_env_var="OPENAI_API_KEY",
backend=Backend.GENERIC,
),
],
models=[
ModelConfig(
name="mistral-vibe-cli-latest", provider="mistral", alias="devstral"
),
ModelConfig(name="gpt-4.1", provider="openai", alias="gpt"),
],
active_model="devstral",
)
app = build_test_vibe_app(
config=config,
plan_offer_gateway=_chat_plan_gateway(prompt_switching_to_pro_plan=False),
)
non_mistral_config = build_test_vibe_config(
vibe_code_enabled=True,
providers=config.providers,
models=config.models,
active_model="gpt",
)
async def fake_reload_with_initial_messages(*, base_config) -> None:
app.agent_loop._base_config = base_config
app.agent_loop.agent_manager.invalidate_config()
async with app.run_test() as pilot:
await _wait_until(
pilot.pause,
lambda: app.commands.get_command_name("/teleport") == "teleport",
)
with (
patch(
"vibe.cli.textual_ui.app.VibeConfig.load",
return_value=non_mistral_config,
),
patch.object(
app.agent_loop,
"reload_with_initial_messages",
new=AsyncMock(side_effect=fake_reload_with_initial_messages),
),
):
await app._reload_config()
await _wait_until(
pilot.pause, lambda: app.commands.get_command_name("/teleport") is None
)
assert app.commands.get_command_name("/teleport") is None
input_widget = app.query_one(ChatInputContainer).input_widget
assert input_widget is not None
assert "&" not in input_widget.mode_characters

View file

@ -0,0 +1,12 @@
from __future__ import annotations
from vibe.cli.textual_ui.widgets.chat_input.completion_popup import CompletionPopup
def test_rendered_text_length_uses_terminal_cell_width() -> None:
# "你" and "🙂" both occupy 2 terminal cells in Rich (+2 for separator).
assert CompletionPopup.rendered_text_length("@你", "🙂") == 6
def test_rendered_text_length_keeps_description_separator() -> None:
assert CompletionPopup.rendered_text_length("@abc", "def") == 8

View file

@ -0,0 +1,81 @@
from __future__ import annotations
from unittest.mock import AsyncMock
import pytest
import vibe.cli.textual_ui.handlers.event_handler as event_handler_module
from vibe.cli.textual_ui.handlers.event_handler import EventHandler
from vibe.core.hooks.models import (
HookEndEvent,
HookMessageSeverity,
HookRunEndEvent,
HookRunStartEvent,
)
class FakeHookRunContainer:
def __init__(self) -> None:
self.display = False
self.remove = AsyncMock()
async def add_message(self, _widget: object) -> None:
self.display = True
@pytest.mark.asyncio
async def test_hook_run_end_removes_empty_container(
monkeypatch: pytest.MonkeyPatch,
) -> None:
created_containers: list[FakeHookRunContainer] = []
def make_container() -> FakeHookRunContainer:
container = FakeHookRunContainer()
created_containers.append(container)
return container
monkeypatch.setattr(event_handler_module, "HookRunContainer", make_container)
mount_callback = AsyncMock()
handler = EventHandler(
mount_callback=mount_callback, get_tools_collapsed=lambda: False
)
await handler.handle_event(HookRunStartEvent())
await handler.handle_event(HookRunEndEvent())
assert len(created_containers) == 1
created_containers[0].remove.assert_awaited_once()
assert handler._hook_run_container is None
@pytest.mark.asyncio
async def test_hook_run_end_keeps_container_with_messages(
monkeypatch: pytest.MonkeyPatch,
) -> None:
created_containers: list[FakeHookRunContainer] = []
def make_container() -> FakeHookRunContainer:
container = FakeHookRunContainer()
created_containers.append(container)
return container
monkeypatch.setattr(event_handler_module, "HookRunContainer", make_container)
mount_callback = AsyncMock()
handler = EventHandler(
mount_callback=mount_callback, get_tools_collapsed=lambda: False
)
await handler.handle_event(HookRunStartEvent())
await handler.handle_event(
HookEndEvent(
hook_name="post-turn", status=HookMessageSeverity.OK, content="Hook output"
)
)
await handler.handle_event(HookRunEndEvent())
assert len(created_containers) == 1
created_containers[0].remove.assert_not_awaited()
assert created_containers[0].display is True
assert handler._hook_run_container is None

View file

@ -0,0 +1,169 @@
from __future__ import annotations
import time
from unittest.mock import MagicMock, patch
import pytest
from tests.conftest import build_test_vibe_app
from vibe.cli.textual_ui.app import VibeApp
from vibe.cli.textual_ui.quit_manager import QUIT_CONFIRM_DELAY, QuitManager
@pytest.fixture
def app() -> VibeApp:
return build_test_vibe_app()
@pytest.fixture
def qm() -> QuitManager:
mock_app = MagicMock()
mock_app.query_one.side_effect = Exception("not mounted")
mock_app.set_timer.return_value = MagicMock()
return QuitManager(mock_app)
class TestQuitManager:
def test_not_confirmed_initially(self, qm: QuitManager) -> None:
assert qm.is_confirmed("Ctrl+C") is False
assert qm.is_confirmed("Ctrl+D") is False
def test_confirmed_within_delay(self, qm: QuitManager) -> None:
qm.request_confirmation("Ctrl+C")
assert qm.is_confirmed("Ctrl+C") is True
def test_wrong_key_not_confirmed(self, qm: QuitManager) -> None:
qm.request_confirmation("Ctrl+C")
assert qm.is_confirmed("Ctrl+D") is False
def test_expired_not_confirmed(self, qm: QuitManager) -> None:
qm.request_confirmation("Ctrl+C")
qm._confirm_time = time.monotonic() - QUIT_CONFIRM_DELAY - 0.1
assert qm.is_confirmed("Ctrl+C") is False
def test_request_resets_timer_on_key_switch(self, qm: QuitManager) -> None:
qm.request_confirmation("Ctrl+C")
qm._confirm_time = time.monotonic() - QUIT_CONFIRM_DELAY + 0.05
qm.request_confirmation("Ctrl+D")
assert qm.is_confirmed("Ctrl+D") is True
def test_confirm_key_property(self, qm: QuitManager) -> None:
assert qm.confirm_key is None
qm.request_confirmation("Ctrl+D")
assert qm.confirm_key == "Ctrl+D"
def test_request_schedules_cancel_timer(self, qm: QuitManager) -> None:
qm.request_confirmation("Ctrl+D")
mock_app = qm._app
assert isinstance(mock_app, MagicMock)
mock_app.set_timer.assert_called_once_with(
QUIT_CONFIRM_DELAY, qm.cancel_confirmation
)
def test_request_stops_previous_timer(self, qm: QuitManager) -> None:
qm.request_confirmation("Ctrl+C")
first_timer = qm._confirm_timer
assert isinstance(first_timer, MagicMock)
qm.request_confirmation("Ctrl+D")
first_timer.stop.assert_called_once()
def test_cancel_confirmation_resets_state(self, qm: QuitManager) -> None:
qm.request_confirmation("Ctrl+C")
qm.cancel_confirmation()
assert qm.is_confirmed("Ctrl+C") is False
assert qm.confirm_key is None
assert qm._confirm_timer is None
def test_cancel_confirmation_noop_when_idle(self, qm: QuitManager) -> None:
qm.cancel_confirmation()
assert qm.confirm_key is None
class TestActionInterruptOrQuit:
def test_clears_input_when_has_value(self, app: VibeApp) -> None:
mock_container = MagicMock()
mock_container.value = "some text"
with patch.object(app, "_get_chat_input", return_value=mock_container):
app.action_interrupt_or_quit()
assert mock_container.value == ""
def test_skips_empty_input(self, app: VibeApp) -> None:
mock_container = MagicMock()
mock_container.value = ""
with (
patch.object(app, "_get_chat_input", return_value=mock_container),
patch.object(app, "_try_interrupt", return_value=False),
patch.object(app._quit_manager, "request_confirmation") as mock_confirm,
):
app.action_interrupt_or_quit()
mock_confirm.assert_called_once_with("Ctrl+C")
def test_quits_on_confirmed(self, app: VibeApp) -> None:
app._quit_manager._confirm_time = time.monotonic()
app._quit_manager._confirm_key = "Ctrl+C"
with (
patch.object(app, "_get_chat_input", return_value=None),
patch.object(app, "_force_quit") as mock_quit,
):
app.action_interrupt_or_quit()
mock_quit.assert_called_once()
def test_interrupts_before_requesting_confirmation(self, app: VibeApp) -> None:
with (
patch.object(app, "_get_chat_input", return_value=None),
patch.object(app, "_try_interrupt", return_value=True) as mock_interrupt,
patch.object(app._quit_manager, "request_confirmation") as mock_confirm,
):
app.action_interrupt_or_quit()
mock_interrupt.assert_called_once()
mock_confirm.assert_not_called()
def test_requests_confirmation_when_nothing_to_interrupt(
self, app: VibeApp
) -> None:
with (
patch.object(app, "_get_chat_input", return_value=None),
patch.object(app, "_try_interrupt", return_value=False),
patch.object(app._quit_manager, "request_confirmation") as mock_confirm,
):
app.action_interrupt_or_quit()
mock_confirm.assert_called_once_with("Ctrl+C")
class TestActionDeleteRightOrQuit:
def test_deletes_right_when_input_has_value(self, app: VibeApp) -> None:
mock_input = MagicMock()
mock_container = MagicMock()
mock_container.value = "some text"
mock_container.input_widget = mock_input
with patch.object(app, "_get_chat_input", return_value=mock_container):
app.action_delete_right_or_quit()
mock_input.action_delete_right.assert_called_once()
def test_skips_empty_input(self, app: VibeApp) -> None:
mock_container = MagicMock()
mock_container.value = ""
with (
patch.object(app, "_get_chat_input", return_value=mock_container),
patch.object(app._quit_manager, "request_confirmation") as mock_confirm,
):
app.action_delete_right_or_quit()
mock_confirm.assert_called_once_with("Ctrl+D")
def test_quits_on_confirmed(self, app: VibeApp) -> None:
app._quit_manager._confirm_time = time.monotonic()
app._quit_manager._confirm_key = "Ctrl+D"
with (
patch.object(app, "_get_chat_input", return_value=None),
patch.object(app, "_force_quit") as mock_quit,
):
app.action_delete_right_or_quit()
mock_quit.assert_called_once()
def test_requests_confirmation_when_no_input(self, app: VibeApp) -> None:
with (
patch.object(app, "_get_chat_input", return_value=None),
patch.object(app._quit_manager, "request_confirmation") as mock_confirm,
):
app.action_delete_right_or_quit()
mock_confirm.assert_called_once_with("Ctrl+D")

View file

@ -1,5 +1,6 @@
from __future__ import annotations
from collections.abc import Generator
from pathlib import Path
import sys
from typing import Any
@ -98,6 +99,7 @@ def _reset_trusted_folders_manager(config_dir: Path) -> None:
trusted_folders_manager._file_path = config_dir / "trusted_folders.toml"
trusted_folders_manager._trusted = []
trusted_folders_manager._untrusted = []
trusted_folders_manager._session_trusted = []
@pytest.fixture(autouse=True)
@ -108,6 +110,31 @@ def _init_harness_files_manager():
reset_harness_files_manager()
@pytest.fixture(autouse=True)
def _scratchpad_dir(
monkeypatch: pytest.MonkeyPatch, tmp_path_factory: pytest.TempPathFactory
) -> Generator[Path]:
import vibe.core.scratchpad as scratchpad_mod
scratchpad_mod._active_scratchpads.clear()
scratchpad_root = tmp_path_factory.mktemp("scratchpad")
_counter = 0
def _fake_mkdtemp(prefix: str = "") -> str:
nonlocal _counter
_counter += 1
d = scratchpad_root / f"{prefix}{_counter}"
d.mkdir(parents=True, exist_ok=True)
return str(d)
monkeypatch.setattr("vibe.core.scratchpad.tempfile.mkdtemp", _fake_mkdtemp)
yield scratchpad_root
scratchpad_mod._active_scratchpads.clear()
@pytest.fixture(autouse=True)
def _mock_api_key(monkeypatch: pytest.MonkeyPatch) -> None:
monkeypatch.setenv("MISTRAL_API_KEY", "mock")
@ -132,7 +159,7 @@ def _mock_update_commands(monkeypatch: pytest.MonkeyPatch) -> None:
@pytest.fixture(autouse=True)
def _disable_feedback_bar(monkeypatch: pytest.MonkeyPatch) -> None:
monkeypatch.setattr(
"vibe.cli.textual_ui.widgets.feedback_bar.FEEDBACK_PROBABILITY", 0
"vibe.cli.textual_ui.widgets.feedback_bar_manager.FEEDBACK_PROBABILITY", 0
)

View file

@ -2,6 +2,7 @@ from __future__ import annotations
from unittest.mock import AsyncMock, MagicMock, patch
from pydantic import BaseModel, ValidationError
import pytest
from tests.conftest import build_test_vibe_config
@ -281,3 +282,20 @@ class TestBrokerSequenceTracking:
assert events == []
assert source._next_start_seq == 5
def test_consume_workflow_event_validation_error_is_logged_and_ignored() -> None:
class _InvalidPayload(BaseModel):
required: str
source = _make_source()
with pytest.raises(ValidationError) as exc_info:
_InvalidPayload.model_validate({})
source._translator.consume_workflow_event = MagicMock(side_effect=exc_info.value)
with patch("vibe.core.nuage.remote_events_source.logger.warning") as mock_warning:
events = source._consume_workflow_event(MagicMock())
assert events == []
mock_warning.assert_called_once()

View file

@ -1,13 +1,14 @@
from __future__ import annotations
import json
from unittest.mock import AsyncMock, patch
from unittest.mock import AsyncMock, MagicMock, patch
import pytest
from vibe.core.nuage.client import WorkflowsClient
from vibe.core.nuage.exceptions import ErrorCode, WorkflowsException
from vibe.core.nuage.streaming import StreamEvent, StreamEventsQueryParams
from vibe.core.nuage.workflow import WorkflowExecutionStatus
def _make_client() -> WorkflowsClient:
@ -198,6 +199,47 @@ class TestStreamEvents:
assert "Failed to stream events" in exc_info.value.message
class TestGetWorkflowRuns:
@pytest.mark.asyncio
async def test_sends_current_user_filter_by_default(self) -> None:
client = _make_client()
mock_response = MagicMock()
mock_response.raise_for_status.return_value = None
mock_response.json.return_value = {"executions": [], "next_page_token": None}
mock_http = AsyncMock()
mock_http.get.return_value = mock_response
client._client = mock_http
await client.get_workflow_runs(
workflow_identifier="workflow-1",
page_size=10,
status=[WorkflowExecutionStatus.RUNNING],
)
mock_http.get.assert_awaited_once()
call_params = mock_http.get.call_args.kwargs["params"]
assert call_params["user_id"] == "current"
assert call_params["workflow_identifier"] == "workflow-1"
assert call_params["page_size"] == 10
@pytest.mark.asyncio
async def test_allows_overriding_user_id(self) -> None:
client = _make_client()
mock_response = MagicMock()
mock_response.raise_for_status.return_value = None
mock_response.json.return_value = {"executions": [], "next_page_token": None}
mock_http = AsyncMock()
mock_http.get.return_value = mock_response
client._client = mock_http
await client.get_workflow_runs(user_id="user-123")
call_params = mock_http.get.call_args.kwargs["params"]
assert call_params["user_id"] == "user-123"
def _async_line_iter(lines: list[str]):
async def _iter():
for line in lines:

View file

@ -0,0 +1,79 @@
from __future__ import annotations
import re
import pytest
from vibe.core.session.session_id import extract_suffix, generate_session_id
UUID_RE = re.compile(r"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$")
class TestGenerateSessionId:
def test_uuid_shape(self) -> None:
sid = generate_session_id()
assert UUID_RE.match(sid), f"Not UUID-shaped: {sid}"
assert len(sid) == 36
def test_unique_ids(self) -> None:
ids = {generate_session_id() for _ in range(100)}
assert len(ids) == 100
def test_suffix_preserved(self) -> None:
suffix = "aabbccddeeff"
sid = generate_session_id(suffix=suffix)
assert UUID_RE.match(sid)
assert sid.endswith(suffix)
def test_suffix_stable_across_regeneration(self) -> None:
suffix = "112233445566"
ids = [generate_session_id(suffix=suffix) for _ in range(50)]
# All share the same last segment
assert all(s.rsplit("-", 1)[-1] == suffix for s in ids)
# But first 8 chars are different (probabilistically)
prefixes = {s[:8] for s in ids}
assert len(prefixes) > 1
def test_default_suffix_is_12_hex(self) -> None:
sid = generate_session_id()
suffix = sid.rsplit("-", 1)[-1]
assert len(suffix) == 12
assert re.fullmatch(r"[0-9a-f]+", suffix)
def test_first_8_chars_are_unique_with_same_suffix(self) -> None:
suffix = "abcdef123456"
a = generate_session_id(suffix=suffix)
b = generate_session_id(suffix=suffix)
assert a[:8] != b[:8]
class TestExtractSuffix:
def test_extract_from_generated_id(self) -> None:
sid = generate_session_id()
suffix = extract_suffix(sid)
assert sid.endswith(suffix)
assert len(suffix) == 12
def test_extract_from_real_uuid(self) -> None:
uuid_str = "550e8400-e29b-41d4-a716-446655440000"
assert extract_suffix(uuid_str) == "446655440000"
def test_extract_roundtrip(self) -> None:
original_suffix = "deadbeef1234"
sid = generate_session_id(suffix=original_suffix)
assert extract_suffix(sid) == original_suffix
def test_extract_from_no_hyphen(self) -> None:
assert extract_suffix("abcdef") == "abcdef"
@pytest.mark.parametrize(
"session_id",
[
"550e8400-e29b-41d4-a716-446655440000",
"abcdef01-2345-6789-abcd-ef0123456789",
"12345678-aaaa-bbbb-cccc-aabbccddeeff",
],
)
def test_extract_always_returns_last_segment(self, session_id: str) -> None:
expected = session_id.rsplit("-", 1)[-1]
assert extract_suffix(session_id) == expected

View file

@ -0,0 +1,493 @@
from __future__ import annotations
import asyncio
from typing import Any
from pydantic import BaseModel, ValidationError
import pytest
from vibe.core.config.layer import (
ConfigLayer,
LayerImplementationError,
RawConfig,
UntrustedLayerError,
)
class StubLayer(ConfigLayer[BaseModel]):
"""Minimal concrete layer for testing."""
def __init__(
self,
*,
name: str = "stub",
output_schema: type[BaseModel] | None = None,
trusted: bool = True,
data: dict[str, Any] | None = None,
) -> None:
kwargs: dict[str, Any] = {"name": name}
if output_schema is not None:
kwargs["output_schema"] = output_schema
super().__init__(**kwargs)
self._stub_trusted = trusted
self._data = data or {}
self.read_count = 0
async def _check_trust(self) -> bool:
return self._stub_trusted
async def _read_config(self) -> dict[str, Any]:
self.read_count += 1
return dict(self._data)
class ObservableStubLayer(StubLayer):
"""Stub that records _on_trust_changed calls."""
def __init__(self, **kwargs: Any) -> None:
super().__init__(**kwargs)
self.trust_changes: list[tuple[bool | None, bool | None]] = []
async def _on_trust_changed(self, old: bool | None, new: bool | None) -> None:
self.trust_changes.append((old, new))
class SampleSchema(BaseModel):
name: str
count: int = 0
def test_abstract_read_config_enforced() -> None:
class IncompleteLayer(ConfigLayer[BaseModel]):
pass
with pytest.raises(TypeError):
IncompleteLayer(name="incomplete") # type: ignore[abstract]
def test_repr() -> None:
layer = StubLayer(name="my-layer")
assert repr(layer) == "StubLayer(name='my-layer')"
@pytest.mark.asyncio
async def test_default_check_trust_returns_false() -> None:
class DefaultTrustLayer(ConfigLayer[BaseModel]):
async def _read_config(self) -> dict[str, Any]:
return {}
layer = DefaultTrustLayer(name="default")
result = await layer.resolve_trust()
assert result is False
@pytest.mark.asyncio
async def test_trust_initially_none() -> None:
layer = StubLayer()
assert layer.is_trusted is None
@pytest.mark.asyncio
async def test_resolve_trust_trusted() -> None:
layer = StubLayer(trusted=True)
result = await layer.resolve_trust()
assert result is True
assert layer.is_trusted is True
@pytest.mark.asyncio
async def test_resolve_trust_untrusted() -> None:
layer = StubLayer(trusted=False)
result = await layer.resolve_trust()
assert result is False
assert layer.is_trusted is False
@pytest.mark.asyncio
async def test_resolve_trust_fires_on_trust_changed() -> None:
layer = ObservableStubLayer(trusted=True)
await layer.resolve_trust()
assert layer.trust_changes == [(None, True)]
@pytest.mark.asyncio
async def test_resolve_trust_no_callback_when_unchanged() -> None:
layer = ObservableStubLayer(trusted=True)
await layer.resolve_trust()
layer.trust_changes.clear()
await layer.resolve_trust()
assert layer.trust_changes == []
@pytest.mark.asyncio
async def test_grant_trust() -> None:
layer = StubLayer(trusted=False)
await layer.grant_trust()
assert layer.is_trusted is True
@pytest.mark.asyncio
async def test_grant_trust_fires_callback() -> None:
layer = ObservableStubLayer(trusted=False)
await layer.grant_trust()
assert layer.trust_changes == [(None, True)]
@pytest.mark.asyncio
async def test_grant_trust_noop_when_already_trusted() -> None:
layer = ObservableStubLayer(trusted=True)
await layer.resolve_trust()
layer.trust_changes.clear()
await layer.grant_trust()
assert layer.trust_changes == []
@pytest.mark.asyncio
async def test_revoke_trust() -> None:
layer = StubLayer(trusted=True)
await layer.resolve_trust()
await layer.revoke_trust()
assert layer.is_trusted is False
@pytest.mark.asyncio
async def test_revoke_trust_fires_callback() -> None:
layer = ObservableStubLayer(trusted=True)
await layer.resolve_trust()
layer.trust_changes.clear()
await layer.revoke_trust()
assert layer.trust_changes == [(True, False)]
@pytest.mark.asyncio
async def test_revoke_trust_clears_data() -> None:
layer = StubLayer(data={"k": "v"})
await layer.load()
assert layer.read_count == 1
await layer.revoke_trust()
await layer.grant_trust()
await layer.load()
assert layer.read_count == 2
@pytest.mark.asyncio
async def test_on_trust_changed_failure_preserves_state() -> None:
class FailingLayer(StubLayer):
def __init__(self, **kwargs: Any) -> None:
super().__init__(**kwargs)
self.should_fail = True
async def _on_trust_changed(self, old: bool | None, new: bool | None) -> None:
if self.should_fail:
raise RuntimeError("persistence failure")
layer = FailingLayer(trusted=False)
assert layer.is_trusted is None
with pytest.raises(LayerImplementationError, match="_on_trust_changed") as exc_info:
await layer.grant_trust()
assert isinstance(exc_info.value.__cause__, RuntimeError)
assert layer.is_trusted is None
layer.should_fail = False
await layer.grant_trust()
assert layer.is_trusted is True
@pytest.mark.asyncio
async def test_check_trust_failure_wrapped() -> None:
class BrokenTrustLayer(StubLayer):
async def _check_trust(self) -> bool:
raise OSError("trust store unavailable")
layer = BrokenTrustLayer()
with pytest.raises(LayerImplementationError, match="_check_trust") as exc_info:
await layer.resolve_trust()
assert isinstance(exc_info.value.__cause__, IOError)
@pytest.mark.asyncio
async def test_load_returns_data() -> None:
layer = StubLayer(data={"key": "value"})
result = await layer.load()
assert isinstance(result, RawConfig)
assert result.model_extra == {"key": "value"}
@pytest.mark.asyncio
async def test_load_auto_resolves_trust() -> None:
layer = StubLayer(trusted=True, data={"a": 1})
assert layer.is_trusted is None
result = await layer.load()
assert layer.is_trusted is True
assert result.model_extra == {"a": 1}
@pytest.mark.asyncio
async def test_load_caches_result() -> None:
layer = StubLayer()
await layer.load()
await layer.load()
await layer.load()
assert layer.read_count == 1
@pytest.mark.asyncio
async def test_load_force_bypasses_cache() -> None:
layer = StubLayer()
await layer.load()
assert layer.read_count == 1
await layer.load(force=True)
assert layer.read_count == 2
@pytest.mark.asyncio
async def test_load_untrusted_raises() -> None:
layer = StubLayer(trusted=False)
with pytest.raises(UntrustedLayerError, match="stub"):
await layer.load()
@pytest.mark.asyncio
async def test_load_after_grant_trust() -> None:
layer = StubLayer(trusted=False)
await layer.grant_trust()
result = await layer.load()
assert isinstance(result, RawConfig)
@pytest.mark.asyncio
async def test_load_after_revoke_trust_raises() -> None:
layer = StubLayer(trusted=True)
await layer.load()
await layer.revoke_trust()
with pytest.raises(UntrustedLayerError):
await layer.load()
@pytest.mark.asyncio
async def test_invalidate_cache_causes_reload() -> None:
layer = StubLayer()
await layer.load()
assert layer.read_count == 1
await layer.invalidate_cache()
await layer.load()
assert layer.read_count == 2
@pytest.mark.asyncio
async def test_revoke_grant_cycle_refreshes_data() -> None:
layer = StubLayer(data={"v": 1})
result1 = await layer.load()
assert result1.model_extra == {"v": 1}
await layer.revoke_trust()
layer._data = {"v": 2}
await layer.grant_trust()
result2 = await layer.load()
assert result2.model_extra == {"v": 2}
@pytest.mark.asyncio
async def test_resolve_trust_clears_data_on_revocation() -> None:
layer = StubLayer(data={"v": 1})
result1 = await layer.load()
assert result1.model_extra == {"v": 1}
# External revocation via resolve_trust (not revoke_trust)
layer._stub_trusted = False
await layer.resolve_trust()
assert layer.is_trusted is False
# Re-trust and update backing data while revoked
layer._stub_trusted = True
layer._data = {"v": 2}
await layer.resolve_trust()
result2 = await layer.load()
assert result2.model_extra == {"v": 2}
@pytest.mark.asyncio
async def test_load_returns_deep_copy() -> None:
layer = StubLayer(data={"items": ["a", "b"]})
result1 = await layer.load()
assert result1.model_extra is not None
result1.model_extra["items"].append("mutated")
result2 = await layer.load()
assert result2.model_extra == {"items": ["a", "b"]}
assert layer.read_count == 1
@pytest.mark.asyncio
async def test_read_config_failure_wrapped() -> None:
class BrokenReadLayer(StubLayer):
async def _read_config(self) -> dict[str, Any]:
raise OSError("config file missing")
layer = BrokenReadLayer()
with pytest.raises(LayerImplementationError, match="_read_config") as exc_info:
await layer.load()
assert isinstance(exc_info.value.__cause__, IOError)
@pytest.mark.asyncio
async def test_default_schema_preserves_extras() -> None:
layer = StubLayer(data={"anything": "goes"})
result = await layer.load()
assert isinstance(result, RawConfig)
assert result.model_extra == {"anything": "goes"}
@pytest.mark.asyncio
async def test_custom_schema_validates() -> None:
layer = StubLayer(output_schema=SampleSchema, data={"name": "test", "count": 3})
result = await layer.load()
assert isinstance(result, SampleSchema)
assert result.name == "test"
assert result.count == 3
@pytest.mark.asyncio
async def test_invalid_data_raises_validation_error() -> None:
layer = StubLayer(output_schema=SampleSchema, data={"count": "bad"})
with pytest.raises(ValidationError):
await layer.load()
@pytest.mark.asyncio
async def test_concurrent_loads_serialize() -> None:
class SlowLayer(ConfigLayer[BaseModel]):
def __init__(self) -> None:
super().__init__(name="slow")
self.read_count = 0
async def _check_trust(self) -> bool:
return True
async def _read_config(self) -> dict[str, Any]:
self.read_count += 1
await asyncio.sleep(0.05)
return {"v": self.read_count}
layer = SlowLayer()
results = await asyncio.gather(layer.load(), layer.load(), layer.load())
assert layer.read_count == 1
assert all(r == results[0] for r in results)
@pytest.mark.asyncio
async def test_get_fingerprint_not_implemented() -> None:
layer = StubLayer()
with pytest.raises(NotImplementedError):
await layer.get_fingerprint()
@pytest.mark.asyncio
async def test_apply_not_implemented() -> None:
layer = StubLayer()
with pytest.raises(NotImplementedError):
await layer.apply({"op": "set"})
# Scenario: LocalUserConfigLayer
class UserConfigSchema(BaseModel):
active_model: str
theme: str = "dark"
class FakeLocalUserLayer(ConfigLayer[UserConfigSchema]):
"""Simulates ~/.vibe/config.toml — always trusted, typed output."""
def __init__(self, data: dict[str, Any]) -> None:
super().__init__(name="user-toml", output_schema=UserConfigSchema)
self._data = data
async def _check_trust(self) -> bool:
return True
async def _read_config(self) -> dict[str, Any]:
return dict(self._data)
@pytest.mark.asyncio
async def test_scenario_local_user_layer_always_trusted() -> None:
layer = FakeLocalUserLayer({"active_model": "devstral-2", "theme": "light"})
assert layer.is_trusted is None
result = await layer.load()
assert layer.is_trusted is True
assert isinstance(result, UserConfigSchema)
assert result.active_model == "devstral-2"
assert result.theme == "light"
validated = layer.validate_output({
"active_model": "mistral-large",
"theme": "dark",
})
assert isinstance(validated, UserConfigSchema)
assert validated.active_model == "mistral-large"
# Scenario: LocalProjectConfigLayer
class FakeLocalProjectLayer(ConfigLayer[BaseModel]):
def __init__(
self, *, project_path: str, data: dict[str, Any], trust_store: dict[str, bool]
) -> None:
super().__init__(name=f"project-toml:{project_path}")
self._project_path = project_path
self._data = data
self._trust_store = trust_store
async def _check_trust(self) -> bool:
return self._trust_store.get(self._project_path, False)
async def _on_trust_changed(self, old: bool | None, new: bool | None) -> None:
if new:
self._trust_store[self._project_path] = True
else:
self._trust_store.pop(self._project_path, None)
async def _read_config(self) -> dict[str, Any]:
return dict(self._data)
@pytest.mark.asyncio
async def test_scenario_local_project_layer_trust_lifecycle() -> None:
trust_store: dict[str, bool] = {}
project_data = {"disabled_tools": ["rm"], "max_tokens": 4096}
# 1. Fresh layer with empty trust store — load raises
layer = FakeLocalProjectLayer(
project_path="/tmp/my-project", data=project_data, trust_store=trust_store
)
with pytest.raises(UntrustedLayerError):
await layer.load()
# 2. Grant trust — persisted in store, load succeeds
await layer.grant_trust()
assert trust_store == {"/tmp/my-project": True}
result = await layer.load()
assert result.model_extra == project_data
# 3. New instance with same trust store — loads directly
layer2 = FakeLocalProjectLayer(
project_path="/tmp/my-project", data=project_data, trust_store=trust_store
)
assert layer2.is_trusted is None
result2 = await layer2.load()
assert layer2.is_trusted is True
assert result2.model_extra == project_data
# 4. Revoke trust — removed from store, load raises
await layer2.revoke_trust()
assert "/tmp/my-project" not in trust_store
with pytest.raises(UntrustedLayerError):
await layer2.load()

View file

@ -198,26 +198,50 @@ class TestSaveUpdates:
assert result == {"tools": {"bash": {"default_timeout": 600}}}
class TestMigrateRemovesFindFromBashAllowlist:
def test_removes_find_from_config_file(
self, tmp_path: Path, monkeypatch: pytest.MonkeyPatch
) -> None:
monkeypatch.setenv("VIBE_HOME", str(tmp_path))
config_file = tmp_path / "config.toml"
data = {"tools": {"bash": {"allowlist": ["echo", "find", "ls"]}}}
class TestSetThinking:
def test_persists_thinking_to_toml(self, config_dir: Path) -> None:
config_file = config_dir / "config.toml"
data = {
"active_model": "my-model",
"models": [
{"name": "my-model", "provider": "mistral", "alias": "my-model"}
],
}
with config_file.open("wb") as f:
tomli_w.dump(data, f)
reset_harness_files_manager()
init_harness_files_manager("user")
VibeConfig._migrate()
cfg = VibeConfig.load()
cfg.set_thinking("high")
reloaded = VibeConfig.load()
assert reloaded.get_active_model().thinking == "high"
with config_file.open("rb") as f:
result = tomllib.load(f)
assert result["models"][0]["thinking"] == "high"
def test_persists_thinking_for_correct_model(self, config_dir: Path) -> None:
config_file = config_dir / "config.toml"
data = {
"active_model": "model-b",
"models": [
{"name": "model-a", "provider": "mistral", "alias": "model-a"},
{"name": "model-b", "provider": "mistral", "alias": "model-b"},
],
}
with config_file.open("wb") as f:
tomli_w.dump(data, f)
cfg = VibeConfig.load()
cfg.set_thinking("max")
with config_file.open("rb") as f:
result = tomllib.load(f)
assert "find" not in result["tools"]["bash"]["allowlist"]
assert result["tools"]["bash"]["allowlist"] == ["echo", "ls"]
assert result["models"][0].get("thinking") is None
assert result["models"][1]["thinking"] == "max"
def test_noop_when_find_not_present(
class TestMigrateLeavesFindInBashAllowlist:
def test_keeps_find_in_config_file(
self, tmp_path: Path, monkeypatch: pytest.MonkeyPatch
) -> None:
monkeypatch.setenv("VIBE_HOME", str(tmp_path))
@ -232,7 +256,24 @@ class TestMigrateRemovesFindFromBashAllowlist:
with config_file.open("rb") as f:
result = tomllib.load(f)
assert result["tools"]["bash"]["allowlist"] == ["echo", "ls"]
assert result["tools"]["bash"]["allowlist"] == ["echo", "find", "ls"]
def test_noop_when_find_already_present(
self, tmp_path: Path, monkeypatch: pytest.MonkeyPatch
) -> None:
monkeypatch.setenv("VIBE_HOME", str(tmp_path))
config_file = tmp_path / "config.toml"
data = {"tools": {"bash": {"allowlist": ["echo", "find", "ls"]}}}
with config_file.open("wb") as f:
tomli_w.dump(data, f)
reset_harness_files_manager()
init_harness_files_manager("user")
VibeConfig._migrate()
with config_file.open("rb") as f:
result = tomllib.load(f)
assert result["tools"]["bash"]["allowlist"] == ["echo", "find", "ls"]
def test_noop_when_no_bash_tools_section(
self, tmp_path: Path, monkeypatch: pytest.MonkeyPatch
@ -313,7 +354,7 @@ class TestDefaultProviderConfig:
class TestMistralBrowserAuthConfig:
def test_provider_browser_auth_urls_are_dumped_when_set(self) -> None:
cfg = build_test_vibe_config()
provider = cfg.get_provider_for_model(cfg.get_active_model())
provider = cfg.get_active_provider()
dumped = cfg.model_dump(mode="json")
assert provider.browser_auth_base_url == DEFAULT_MISTRAL_BROWSER_AUTH_BASE_URL
@ -808,7 +849,7 @@ class TestGetMistralProvider:
def test_returns_active_provider_when_it_is_mistral(self) -> None:
cfg = build_test_vibe_config()
provider = cfg.get_mistral_provider()
active = cfg.get_provider_for_model(cfg.get_active_model())
active = cfg.get_active_provider()
assert provider is active
assert provider is not None
assert provider.backend == Backend.MISTRAL
@ -867,3 +908,46 @@ class TestGetMistralProvider:
)
provider = cfg.get_mistral_provider()
assert provider is mistral_provider
class TestIsActiveModelMistral:
def test_returns_true_when_active_provider_is_mistral(self) -> None:
cfg = build_test_vibe_config()
assert cfg.is_active_model_mistral() is True
def test_returns_false_when_active_provider_is_not_mistral(self) -> None:
cfg = build_test_vibe_config(
providers=[
ProviderConfig(
name="llamacpp",
api_base="http://127.0.0.1:8080/v1",
api_key_env_var="",
)
],
models=[
ModelConfig(
name="llama-local", provider="llamacpp", alias="llama-local"
)
],
active_model="llama-local",
)
assert cfg.is_active_model_mistral() is False
def test_returns_false_when_active_model_resolution_fails(self) -> None:
cfg = build_test_vibe_config(
providers=[
ProviderConfig(
name="mistral",
api_base="https://api.mistral.ai/v1",
api_key_env_var="MISTRAL_API_KEY",
backend=Backend.MISTRAL,
)
],
models=[
ModelConfig(
name="llama-local", provider="llamacpp", alias="llama-local"
)
],
active_model="llama-local",
)
assert cfg.is_active_model_mistral() is False

504
tests/core/test_hooks.py Normal file
View file

@ -0,0 +1,504 @@
from __future__ import annotations
from pathlib import Path
import sys
import pytest
import tomli_w
from tests.conftest import build_test_agent_loop
from tests.mock.utils import mock_llm_chunk
from tests.stubs.fake_backend import FakeBackend
from vibe.core.config import VibeConfig
from vibe.core.hooks.config import (
HookConfig,
HookConfigResult,
_load_hooks_file,
load_hooks_from_fs,
)
from vibe.core.hooks.executor import HookExecutor
from vibe.core.hooks.manager import HooksManager
from vibe.core.hooks.models import (
HookEndEvent,
HookInvocation,
HookMessageSeverity,
HookStartEvent,
HookType,
HookUserMessage,
)
from vibe.core.types import BaseEvent
@pytest.fixture
def sample_invocation() -> HookInvocation:
return HookInvocation(
session_id="test-session",
transcript_path="",
cwd=str(Path.cwd()),
hook_event_name="post_agent_turn",
)
@pytest.fixture
def config_hooks_disabled() -> VibeConfig:
return VibeConfig(enable_experimental_hooks=False)
@pytest.fixture
def config_hooks_enabled() -> VibeConfig:
return VibeConfig(enable_experimental_hooks=True)
def _write_hooks_toml(path: Path, hooks: list[dict]) -> None:
path.parent.mkdir(parents=True, exist_ok=True)
with path.open("wb") as f:
tomli_w.dump({"hooks": hooks}, f)
def _make_hook(
name: str = "test-hook", command: str = "echo ok", timeout: float = 30.0
) -> HookConfig:
return HookConfig(
name=name, type=HookType.POST_AGENT_TURN, command=command, timeout=timeout
)
class TestConfigLoading:
def test_load_from_global_file(
self, config_dir: Path, config_hooks_enabled: VibeConfig
) -> None:
_write_hooks_toml(
config_dir / "hooks.toml",
[
{
"name": "lint",
"type": HookType.POST_AGENT_TURN,
"command": "echo lint",
}
],
)
result = load_hooks_from_fs(config_hooks_enabled)
assert len(result.hooks) == 1
assert result.hooks[0].name == "lint"
assert result.issues == []
def test_load_from_both_global_and_project(
self,
config_dir: Path,
tmp_working_directory: Path,
config_hooks_enabled: VibeConfig,
) -> None:
_write_hooks_toml(
config_dir / "hooks.toml",
[
{
"name": "global-hook",
"type": "post_agent_turn",
"command": "echo global",
}
],
)
project_vibe = tmp_working_directory / ".vibe"
_write_hooks_toml(
project_vibe / "hooks.toml",
[
{
"name": "project-hook",
"type": "post_agent_turn",
"command": "echo project",
}
],
)
from vibe.core.trusted_folders import trusted_folders_manager
trusted_folders_manager.add_trusted(tmp_working_directory)
result = load_hooks_from_fs(config_hooks_enabled)
assert len(result.hooks) == 2
names = {h.name for h in result.hooks}
assert names == {"global-hook", "project-hook"}
def test_project_file_skipped_when_untrusted(
self, tmp_working_directory: Path, config_hooks_enabled: VibeConfig
) -> None:
project_vibe = tmp_working_directory / ".vibe"
_write_hooks_toml(
project_vibe / "hooks.toml",
[
{
"name": "sneaky-hook",
"type": "post_agent_turn",
"command": "echo sneaky",
}
],
)
result = load_hooks_from_fs(config_hooks_enabled)
assert not any(h.name == "sneaky-hook" for h in result.hooks)
def test_duplicate_hook_name_detection(
self,
config_dir: Path,
tmp_working_directory: Path,
config_hooks_enabled: VibeConfig,
) -> None:
_write_hooks_toml(
config_dir / "hooks.toml",
[{"name": "dup-hook", "type": "post_agent_turn", "command": "echo global"}],
)
project_vibe = tmp_working_directory / ".vibe"
_write_hooks_toml(
project_vibe / "hooks.toml",
[
{
"name": "dup-hook",
"type": "post_agent_turn",
"command": "echo project",
}
],
)
from vibe.core.trusted_folders import trusted_folders_manager
trusted_folders_manager.add_trusted(tmp_working_directory)
result = load_hooks_from_fs(config_hooks_enabled)
assert len(result.hooks) == 1
assert any("Duplicate" in i.message for i in result.issues)
def test_toml_parse_error_reported(
self, config_dir: Path, config_hooks_enabled: VibeConfig
) -> None:
hooks_file = config_dir / "hooks.toml"
hooks_file.write_text("this is not valid toml [[[", encoding="utf-8")
result = load_hooks_from_fs(config_hooks_enabled)
assert result.hooks == []
assert len(result.issues) == 1
assert (
"parse" in result.issues[0].message.lower()
or "Failed" in result.issues[0].message
)
def test_validation_error_reported(
self, config_dir: Path, config_hooks_enabled: VibeConfig
) -> None:
_write_hooks_toml(
config_dir / "hooks.toml",
[{"name": "bad", "type": "InvalidType", "command": "echo"}],
)
result = load_hooks_from_fs(config_hooks_enabled)
assert result.hooks == []
assert len(result.issues) == 1
def test_missing_command_reported(
self, config_dir: Path, config_hooks_enabled: VibeConfig
) -> None:
_write_hooks_toml(
config_dir / "hooks.toml", [{"name": "no-cmd", "type": "post_agent_turn"}]
)
result = load_hooks_from_fs(config_hooks_enabled)
assert result.hooks == []
assert len(result.issues) == 1
def test_empty_command_reported(
self, config_dir: Path, config_hooks_enabled: VibeConfig
) -> None:
_write_hooks_toml(
config_dir / "hooks.toml",
[{"name": "empty-cmd", "type": "post_agent_turn", "command": " "}],
)
result = load_hooks_from_fs(config_hooks_enabled)
assert result.hooks == []
assert len(result.issues) == 1
def test_default_timeout(
self, config_dir: Path, config_hooks_enabled: VibeConfig
) -> None:
_write_hooks_toml(
config_dir / "hooks.toml",
[{"name": "h", "type": "post_agent_turn", "command": "echo ok"}],
)
result = load_hooks_from_fs(config_hooks_enabled)
assert result.hooks[0].timeout == 30.0
def test_nonexistent_file_returns_empty(self, tmp_path: Path) -> None:
result = _load_hooks_file(tmp_path / "missing.toml")
assert result.hooks == []
assert result.issues == []
def test_hooks_disabled_returns_empty(
self, config_dir: Path, config_hooks_disabled: VibeConfig
) -> None:
_write_hooks_toml(
config_dir / "hooks.toml",
[
{
"name": "lint",
"type": HookType.POST_AGENT_TURN,
"command": "echo lint",
}
],
)
result = load_hooks_from_fs(config_hooks_disabled)
assert result.hooks == []
assert result.issues == []
class TestHookExecutor:
@pytest.mark.asyncio
async def test_exit_0_success(self, sample_invocation: HookInvocation) -> None:
hook = _make_hook(command="echo success")
result = await HookExecutor().run(hook, sample_invocation)
assert result.exit_code == 0
assert result.stdout == "success"
assert not result.timed_out
@pytest.mark.asyncio
async def test_exit_2_retry(self, sample_invocation: HookInvocation) -> None:
hook = _make_hook(command="echo 'fix this'; exit 2")
result = await HookExecutor().run(hook, sample_invocation)
assert result.exit_code == 2
assert "fix this" in result.stdout
assert not result.timed_out
@pytest.mark.asyncio
async def test_other_exit_code(self, sample_invocation: HookInvocation) -> None:
hook = _make_hook(command="echo 'oops'; exit 1")
result = await HookExecutor().run(hook, sample_invocation)
assert result.exit_code == 1
assert "oops" in result.stdout
@pytest.mark.asyncio
async def test_timeout(self, sample_invocation: HookInvocation) -> None:
hook = _make_hook(command="sleep 60", timeout=0.5)
result = await HookExecutor().run(hook, sample_invocation)
assert result.timed_out
assert result.exit_code is None
@pytest.mark.asyncio
async def test_stderr_captured_separately(
self, sample_invocation: HookInvocation
) -> None:
hook = _make_hook(command="echo out; echo err >&2")
result = await HookExecutor().run(hook, sample_invocation)
assert result.exit_code == 0
assert result.stdout == "out"
assert result.stderr == "err"
@pytest.mark.asyncio
async def test_stdin_json_received(self, sample_invocation: HookInvocation) -> None:
hook = _make_hook(
command=f"{sys.executable} -c \"import sys,json; d=json.load(sys.stdin); print(d['session_id'])\""
)
result = await HookExecutor().run(hook, sample_invocation)
assert result.exit_code == 0
assert result.stdout == "test-session"
class TestHooksManager:
@pytest.mark.asyncio
async def test_exit_0_emits_start_and_end(self) -> None:
handler = HooksManager([_make_hook(command="echo ok")])
from vibe.core.config import SessionLoggingConfig
from vibe.core.session.session_logger import SessionLogger
logger = SessionLogger(SessionLoggingConfig(enabled=False), "test-id")
events: list[BaseEvent | HookUserMessage] = []
async for ev in handler.run(HookType.POST_AGENT_TURN, "sess", logger):
events.append(ev)
event_types = [type(e).__name__ for e in events]
assert "HookStartEvent" in event_types
assert "HookEndEvent" in event_types
# Exit 0 with no retry = no HookUserMessage
assert not any(isinstance(e, HookUserMessage) for e in events)
@pytest.mark.asyncio
async def test_exit_2_emits_retry_message(self) -> None:
handler = HooksManager([_make_hook(command="echo 'fix it'; exit 2")])
from vibe.core.config import SessionLoggingConfig
from vibe.core.session.session_logger import SessionLogger
logger = SessionLogger(SessionLoggingConfig(enabled=False), "test-id")
events: list[BaseEvent | HookUserMessage] = []
async for ev in handler.run(HookType.POST_AGENT_TURN, "sess", logger):
events.append(ev)
retry_msgs = [e for e in events if isinstance(e, HookUserMessage)]
assert len(retry_msgs) == 1
assert "fix it" in retry_msgs[0].content
# Display message should be generic, not the stdout
end_msgs = [
e for e in events if isinstance(e, HookEndEvent) and e.content is not None
]
assert any("retrying" in m.content.lower() for m in end_msgs if m.content)
assert not any("fix it" in (m.content or "") for m in end_msgs)
@pytest.mark.asyncio
async def test_exit_2_without_output_emits_warning(self) -> None:
handler = HooksManager([_make_hook(command="exit 2")])
from vibe.core.config import SessionLoggingConfig
from vibe.core.session.session_logger import SessionLogger
logger = SessionLogger(SessionLoggingConfig(enabled=False), "test-id")
events: list[BaseEvent | HookUserMessage] = []
async for ev in handler.run(HookType.POST_AGENT_TURN, "sess", logger):
events.append(ev)
end_msgs = [e for e in events if isinstance(e, HookEndEvent)]
assert len(end_msgs) == 1
assert end_msgs[0].content == "Exited with code 2"
@pytest.mark.asyncio
async def test_max_retry_limit(self) -> None:
handler = HooksManager([_make_hook(command="echo retry; exit 2")])
from vibe.core.config import SessionLoggingConfig
from vibe.core.session.session_logger import SessionLogger
logger = SessionLogger(SessionLoggingConfig(enabled=False), "test-id")
# Run 3 times (should get retry each time)
for _ in range(3):
events = [
ev async for ev in handler.run(HookType.POST_AGENT_TURN, "sess", logger)
]
assert any(isinstance(e, HookUserMessage) for e in events)
# 4th time: max exceeded, no retry
events = [
ev async for ev in handler.run(HookType.POST_AGENT_TURN, "sess", logger)
]
assert not any(isinstance(e, HookUserMessage) for e in events)
# Should have error message about max retries
error_events = [
e
for e in events
if isinstance(e, HookEndEvent)
and e.content
and "exhausted" in e.content.lower()
]
assert len(error_events) == 1
@pytest.mark.asyncio
async def test_warning_on_nonzero_exit(self) -> None:
handler = HooksManager([_make_hook(command="echo warn; exit 1")])
from vibe.core.config import SessionLoggingConfig
from vibe.core.session.session_logger import SessionLogger
logger = SessionLogger(SessionLoggingConfig(enabled=False), "test-id")
events = [
ev async for ev in handler.run(HookType.POST_AGENT_TURN, "sess", logger)
]
warnings = [
e
for e in events
if isinstance(e, HookEndEvent) and e.status == HookMessageSeverity.WARNING
]
assert len(warnings) == 1
assert warnings[0].content and "warn" in warnings[0].content
@pytest.mark.asyncio
async def test_warning_falls_back_to_stderr(self) -> None:
hook = _make_hook(command="echo problem >&2; exit 1")
handler = HooksManager([hook])
from vibe.core.config import SessionLoggingConfig
from vibe.core.session.session_logger import SessionLogger
logger = SessionLogger(SessionLoggingConfig(enabled=False), "test-id")
events = [
ev async for ev in handler.run(HookType.POST_AGENT_TURN, "sess", logger)
]
warnings = [
e
for e in events
if isinstance(e, HookEndEvent) and e.status == HookMessageSeverity.WARNING
]
assert len(warnings) == 1
assert warnings[0].content and "problem" in warnings[0].content
@pytest.mark.asyncio
async def test_timeout_emits_warning(self) -> None:
handler = HooksManager([_make_hook(command="sleep 60", timeout=0.5)])
from vibe.core.config import SessionLoggingConfig
from vibe.core.session.session_logger import SessionLogger
logger = SessionLogger(SessionLoggingConfig(enabled=False), "test-id")
events = [
ev async for ev in handler.run(HookType.POST_AGENT_TURN, "sess", logger)
]
warnings = [
e
for e in events
if isinstance(e, HookEndEvent) and e.status == HookMessageSeverity.WARNING
]
assert len(warnings) == 1
assert warnings[0].content and "Timed out" in warnings[0].content
class TestAgentLoopIntegration:
@pytest.mark.asyncio
async def test_hooks_run_after_turn(self) -> None:
backend = FakeBackend(mock_llm_chunk(content="Hello!"))
hooks = [_make_hook(name="post-lint", command="echo ok")]
agent_loop = build_test_agent_loop(
backend=backend, hook_config_result=HookConfigResult(hooks=hooks, issues=[])
)
events = [ev async for ev in agent_loop.act("hi")]
event_types = [type(e).__name__ for e in events]
assert "HookStartEvent" in event_types
assert "HookEndEvent" in event_types
@pytest.mark.asyncio
async def test_hook_retry_reinjects_message(self) -> None:
# First call: LLM responds. Hook requests retry with "fix this".
# Second call (after retry injection): LLM responds again. Hook exits 0.
backend = FakeBackend([
[mock_llm_chunk(content="first response")],
[mock_llm_chunk(content="second response")],
])
# Create a script that exits 2 on first call, 0 on subsequent
counter_file = Path.cwd() / ".hook_counter"
script = (
f'{sys.executable} -c "'
f"from pathlib import Path; "
f"p = Path({str(counter_file)!r}); "
f"c = int(p.read_text()) if p.exists() else 0; "
f"p.write_text(str(c + 1)); "
f"import sys; "
f"print('fix this'); "
f"sys.exit(2 if c == 0 else 0)"
f'"'
)
hooks = [_make_hook(name="retry-hook", command=script)]
agent_loop = build_test_agent_loop(
backend=backend, hook_config_result=HookConfigResult(hooks=hooks, issues=[])
)
events = [ev async for ev in agent_loop.act("hi")]
# Should have two assistant events (two LLM turns)
from vibe.core.types import AssistantEvent
assistant_events = [e for e in events if isinstance(e, AssistantEvent)]
assert len(assistant_events) == 2
# Check that a retry user message was injected
user_messages = [
m for m in agent_loop.messages if m.role.value == "user" and m.injected
]
assert any("fix this" in (m.content or "") for m in user_messages)
@pytest.mark.asyncio
async def test_no_hooks_no_events(self) -> None:
backend = FakeBackend(mock_llm_chunk(content="Hello!"))
agent_loop = build_test_agent_loop(backend=backend)
events = [ev async for ev in agent_loop.act("hi")]
hook_events = [
e for e in events if isinstance(e, (HookStartEvent, HookEndEvent))
]
assert hook_events == []

View file

@ -1,6 +1,7 @@
from __future__ import annotations
from typing import Any
from unittest.mock import patch
from tests.conftest import build_test_vibe_config
from vibe.core.nuage.events import (
@ -244,6 +245,28 @@ def test_ask_user_question_tool_emits_assistant_question() -> None:
assert tool_call_event.tool_call_id == "call-question"
def test_ask_user_question_invalid_args_are_logged_and_ignored() -> None:
loop = _make_loop(enabled_tools=["ask_user_question"])
started = _started(
"tool-task-question",
"AgentToolCallState",
{
"name": "ask_user_question",
"tool_call_id": "call-question",
"kwargs": {"questions": [{}]},
},
)
with patch(
"vibe.core.nuage.remote_workflow_event_translator.logger.warning"
) as mock_warning:
events = loop._consume_workflow_event(started)
assert any(isinstance(event, ToolCallEvent) for event in events)
assert not any(isinstance(event, AssistantEvent) for event in events)
mock_warning.assert_called_once()
def test_ask_user_question_wait_for_input_completion_emits_tool_result() -> None:
loop = _make_loop(enabled_tools=["ask_user_question"])
ask_started = _started(
@ -765,5 +788,152 @@ def test_steer_input_events_are_suppressed() -> None:
)
assert loop._consume_workflow_event(steer_started) == []
assert loop._translator.pending_input_request is not None
assert loop._translator.pending_input_request.task_id == "steer-1"
assert loop._consume_workflow_event(steer_completed) == []
assert loop._translator.pending_input_request is None
def test_steer_input_allows_user_submission() -> None:
loop = _make_loop()
steer_started = _started(
"steer-1",
"wait_for_input",
{"input_schema": {"title": "ChatInput"}, "label": "Send a message to steer..."},
)
assert loop._consume_workflow_event(steer_started) == []
assert loop.is_waiting_for_input
loop._translator.pending_input_request = None
steer_completed = _completed(
"steer-1",
"wait_for_input",
{
"input_schema": {"title": "ChatInput"},
"label": "Send a message to steer...",
"input": {"message": [{"type": "text", "text": "do X instead"}]},
},
)
events = loop._consume_workflow_event(steer_completed)
assert any(isinstance(e, UserMessageEvent) for e in events)
user_event = next(e for e in events if isinstance(e, UserMessageEvent))
assert user_event.content == "do X instead"
def test_steer_does_not_overwrite_regular_pending_input() -> None:
loop = _make_loop()
regular_started = _started(
"regular-1",
"wait_for_input",
{"input_schema": {"title": "ChatInput"}, "label": "Enter your message"},
)
loop._consume_workflow_event(regular_started)
assert loop._translator.pending_input_request is not None
assert loop._translator.pending_input_request.task_id == "regular-1"
steer_started = _started(
"steer-1",
"wait_for_input",
{"input_schema": {"title": "ChatInput"}, "label": "Send a message to steer..."},
)
loop._consume_workflow_event(steer_started)
assert loop._translator.pending_input_request.task_id == "regular-1"
def test_invalid_steer_start_registers_task_for_terminal_handling() -> None:
loop = _make_loop()
steer_started = _started(
"steer-1", "wait_for_input", {"label": "Send a message to steer..."}
)
with patch("vibe.core.nuage.remote_events_source.logger.warning") as mock_warning:
assert loop._consume_workflow_event(steer_started) == []
mock_warning.assert_called_once()
assert "steer-1" in loop._translator._steer_task_ids
assert "steer-1" in loop._translator._invalid_steer_task_ids
assert loop._translator.pending_input_request is None
def test_invalid_steer_completion_does_not_clear_regular_prompt() -> None:
loop = _make_loop()
regular_started = _started(
"regular-1",
"wait_for_input",
{"input_schema": {"title": "ChatInput"}, "label": "Pick an option"},
)
loop._consume_workflow_event(regular_started)
steer_started = _started(
"steer-1", "wait_for_input", {"label": "Send a message to steer..."}
)
assert loop._consume_workflow_event(steer_started) == []
assert loop._translator.pending_input_request is not None
assert loop._translator.pending_input_request.task_id == "regular-1"
steer_completed = _completed(
"steer-1",
"wait_for_input",
{"label": "Send a message to steer...", "input": None},
)
events = loop._consume_workflow_event(steer_completed)
assert events == []
assert loop._translator.pending_input_request is not None
assert loop._translator.pending_input_request.task_id == "regular-1"
def test_invalid_steer_cancellation_does_not_clear_regular_prompt() -> None:
loop = _make_loop()
regular_started = _started(
"regular-1",
"wait_for_input",
{"input_schema": {"title": "ChatInput"}, "label": "Pick an option"},
)
loop._consume_workflow_event(regular_started)
steer_started = _started(
"steer-1", "wait_for_input", {"label": "Send a message to steer..."}
)
assert loop._consume_workflow_event(steer_started) == []
assert loop._translator.pending_input_request is not None
assert loop._translator.pending_input_request.task_id == "regular-1"
events = loop._consume_workflow_event(_canceled("steer-1", "wait_for_input"))
assert events == []
assert loop._translator.pending_input_request is not None
assert loop._translator.pending_input_request.task_id == "regular-1"
def test_steer_completion_is_preserved_while_regular_prompt_pending() -> None:
loop = _make_loop()
regular_started = _started(
"regular-1",
"wait_for_input",
{"input_schema": {"title": "ChatInput"}, "label": "Pick an option"},
)
loop._consume_workflow_event(regular_started)
steer_started = _started(
"steer-1",
"wait_for_input",
{"input_schema": {"title": "ChatInput"}, "label": "Send a message to steer..."},
)
loop._consume_workflow_event(steer_started)
steer_completed = _completed(
"steer-1",
"wait_for_input",
{
"input_schema": {"title": "ChatInput"},
"label": "Send a message to steer...",
"input": {"message": [{"type": "text", "text": "user steer msg"}]},
},
)
events = loop._consume_workflow_event(steer_completed)
user_event = next(e for e in events if isinstance(e, UserMessageEvent))
assert user_event.content == "user steer msg"
assert loop._translator.pending_input_request is not None
assert loop._translator.pending_input_request.task_id == "regular-1"

View file

@ -0,0 +1,81 @@
from __future__ import annotations
from vibe.core.scratchpad import get_scratchpad_dir, init_scratchpad, is_scratchpad_path
class TestInitScratchpad:
def test_creates_directory(self):
result = init_scratchpad("test-session")
assert result is not None
assert result.is_dir()
def test_idempotent_same_session(self):
first = init_scratchpad("session-1")
second = init_scratchpad("session-1")
assert first == second
def test_different_sessions_get_different_dirs(self):
first = init_scratchpad("session-1")
second = init_scratchpad("session-2")
assert first != second
def test_session_id_in_dir_name(self):
result = init_scratchpad("abcdef123456")
assert result is not None
assert "abcdef12" in result.name
def test_sets_module_state(self):
init_scratchpad("test-session")
assert get_scratchpad_dir("test-session") is not None
class TestGetScratchpadDir:
def test_none_for_unknown_session(self):
assert get_scratchpad_dir("nonexistent") is None
def test_returns_path_after_init(self):
path = init_scratchpad("test-session")
assert get_scratchpad_dir("test-session") == path
class TestIsScratchpadPath:
def test_false_when_not_initialized(self):
assert not is_scratchpad_path("/tmp/anything")
def test_true_for_file_inside(self):
sp = init_scratchpad("test-session")
assert sp is not None
assert is_scratchpad_path(str(sp / "file.txt"))
def test_true_for_nested_file(self):
sp = init_scratchpad("test-session")
assert sp is not None
assert is_scratchpad_path(str(sp / "subdir" / "file.txt"))
def test_true_for_dir_itself(self):
sp = init_scratchpad("test-session")
assert sp is not None
assert is_scratchpad_path(str(sp))
def test_true_across_sessions(self):
sp1 = init_scratchpad("session-1")
sp2 = init_scratchpad("session-2")
assert sp1 is not None and sp2 is not None
assert is_scratchpad_path(str(sp1 / "file.txt"))
assert is_scratchpad_path(str(sp2 / "file.txt"))
def test_false_for_outside_path(self):
init_scratchpad("test-session")
assert not is_scratchpad_path("/etc/passwd")
def test_false_for_traversal_attack(self):
sp = init_scratchpad("test-session")
assert sp is not None
traversal = str(sp / ".." / ".." / ".." / "etc" / "passwd")
assert not is_scratchpad_path(traversal)
def test_false_for_sibling_directory(self):
sp = init_scratchpad("test-session")
assert sp is not None
sibling = str(sp.parent / "other-dir" / "file.txt")
assert not is_scratchpad_path(sibling)

View file

@ -10,7 +10,12 @@ from tests.conftest import build_test_vibe_config
from tests.stubs.fake_tool import FakeTool, FakeToolArgs
from vibe.core.agent_loop import ToolDecision, ToolExecutionResponse
from vibe.core.llm.format import ResolvedToolCall
from vibe.core.telemetry.build_metadata import (
build_base_metadata,
build_request_metadata,
)
from vibe.core.telemetry.send import TelemetryClient
from vibe.core.telemetry.types import EntrypointMetadata, TelemetryRequestMetadata
from vibe.core.tools.base import BaseTool, ToolPermission
from vibe.core.types import Backend
from vibe.core.utils import get_user_agent
@ -55,9 +60,7 @@ class TestTelemetryClient:
self, monkeypatch: pytest.MonkeyPatch
) -> None:
config = build_test_vibe_config(enable_telemetry=True)
env_key = config.get_provider_for_model(
config.get_active_model()
).api_key_env_var
env_key = config.get_active_provider().api_key_env_var
monkeypatch.delenv(env_key, raising=False)
client = TelemetryClient(config_getter=lambda: config)
assert client._get_mistral_api_key() is None
@ -76,9 +79,7 @@ class TestTelemetryClient:
TelemetryClient, "send_telemetry_event", _original_send_telemetry_event
)
config = build_test_vibe_config(enable_telemetry=False)
env_key = config.get_provider_for_model(
config.get_active_model()
).api_key_env_var
env_key = config.get_active_provider().api_key_env_var
monkeypatch.setenv(env_key, "sk-test")
client = TelemetryClient(config_getter=lambda: config)
client._client = MagicMock()
@ -97,9 +98,7 @@ class TestTelemetryClient:
TelemetryClient, "send_telemetry_event", _original_send_telemetry_event
)
config = build_test_vibe_config(enable_telemetry=True)
env_key = config.get_provider_for_model(
config.get_active_model()
).api_key_env_var
env_key = config.get_active_provider().api_key_env_var
monkeypatch.setenv(env_key, "sk-test")
client = TelemetryClient(config_getter=lambda: config)
mock_post = AsyncMock(return_value=MagicMock(status_code=204))
@ -150,6 +149,25 @@ class TestTelemetryClient:
assert properties["model"] == "mistral-large"
assert properties["nb_files_created"] == 0
assert properties["nb_files_modified"] == 0
assert properties["message_id"] is None
def test_send_tool_call_finished_with_message_id(
self, telemetry_events: list[dict[str, Any]]
) -> None:
config = build_test_vibe_config(enable_telemetry=True)
client = TelemetryClient(config_getter=lambda: config)
tool_call = _make_resolved_tool_call("todo", {})
client.send_tool_call_finished(
tool_call=tool_call,
status="success",
decision=None,
agent_profile_name="default",
model="mistral-large",
message_id="msg-123",
)
assert telemetry_events[0]["properties"]["message_id"] == "msg-123"
def test_send_tool_call_finished_nb_files_created_write_file_new(
self, telemetry_events: list[dict[str, Any]]
@ -237,10 +255,21 @@ class TestTelemetryClient:
config = build_test_vibe_config(enable_telemetry=True)
client = TelemetryClient(config_getter=lambda: config)
client.send_auto_compact_triggered()
client.send_auto_compact_triggered(
nb_context_tokens_before=123,
nb_context_tokens_after=45,
auto_compact_threshold=100,
status="success",
)
assert len(telemetry_events) == 1
assert telemetry_events[0]["event_name"] == "vibe.auto_compact_triggered"
assert telemetry_events[0]["properties"] == {
"nb_context_tokens_before": 123,
"nb_context_tokens_after": 45,
"auto_compact_threshold": 100,
"status": "success",
}
def test_send_slash_command_used_payload(
self, telemetry_events: list[dict[str, Any]]
@ -289,8 +318,55 @@ class TestTelemetryClient:
assert properties["terminal_emulator"] == "vscode"
assert "version" in properties
def test_build_base_metadata_includes_entrypoint_and_session(self) -> None:
metadata = build_base_metadata(
entrypoint_metadata=EntrypointMetadata(
agent_entrypoint="cli",
agent_version="1.0.0",
client_name="vibe_cli",
client_version="1.0.0",
),
session_id="session-123",
parent_session_id="parent-session-456",
)
assert metadata == {
"agent_entrypoint": "cli",
"agent_version": "1.0.0",
"client_name": "vibe_cli",
"client_version": "1.0.0",
"session_id": "session-123",
"parent_session_id": "parent-session-456",
}
def test_build_request_metadata_includes_all_telemetry_metadata(self) -> None:
metadata = build_request_metadata(
entrypoint_metadata=EntrypointMetadata(
agent_entrypoint="cli",
agent_version="1.0.0",
client_name="vibe_cli",
client_version="1.0.0",
),
session_id="session-123",
parent_session_id="parent-session-456",
call_type="secondary_call",
message_id="message-456",
)
assert metadata == TelemetryRequestMetadata(
agent_entrypoint="cli",
agent_version="1.0.0",
client_name="vibe_cli",
client_version="1.0.0",
session_id="session-123",
parent_session_id="parent-session-456",
call_source="vibe_code",
call_type="secondary_call",
message_id="message-456",
)
@pytest.mark.asyncio
async def test_session_id_added_when_getter_provided(
async def test_parent_session_id_added_when_getter_provided(
self, monkeypatch: pytest.MonkeyPatch
) -> None:
monkeypatch.setattr(
@ -301,6 +377,46 @@ class TestTelemetryClient:
config.get_active_model()
).api_key_env_var
monkeypatch.setenv(env_key, "sk-test")
client = TelemetryClient(
config_getter=lambda: config,
session_id_getter=lambda: "session-123",
parent_session_id_getter=lambda: "parent-session-456",
)
mock_post = AsyncMock(return_value=MagicMock(status_code=204))
client._client = MagicMock()
client._client.post = mock_post
client._client.aclose = AsyncMock()
client.send_telemetry_event("vibe.test_event", {"key": "value"})
await client.aclose()
mock_post.assert_called_once_with(
"https://api.mistral.ai/v1/datalake/events",
json={
"event": "vibe.test_event",
"properties": {
"session_id": "session-123",
"parent_session_id": "parent-session-456",
"key": "value",
},
},
headers={
"Content-Type": "application/json",
"Authorization": "Bearer sk-test",
"User-Agent": get_user_agent(Backend.MISTRAL),
},
)
@pytest.mark.asyncio
async def test_session_id_added_when_getter_provided(
self, monkeypatch: pytest.MonkeyPatch
) -> None:
monkeypatch.setattr(
TelemetryClient, "send_telemetry_event", _original_send_telemetry_event
)
config = build_test_vibe_config(enable_telemetry=True)
env_key = config.get_active_provider().api_key_env_var
monkeypatch.setenv(env_key, "sk-test")
session_id = "test-session-uuid"
client = TelemetryClient(
config_getter=lambda: config, session_id_getter=lambda: session_id
@ -334,9 +450,7 @@ class TestTelemetryClient:
TelemetryClient, "send_telemetry_event", _original_send_telemetry_event
)
config = build_test_vibe_config(enable_telemetry=True)
env_key = config.get_provider_for_model(
config.get_active_model()
).api_key_env_var
env_key = config.get_active_provider().api_key_env_var
monkeypatch.setenv(env_key, "sk-test")
client = TelemetryClient(config_getter=lambda: config)
mock_post = AsyncMock(return_value=MagicMock(status_code=204))
@ -365,9 +479,7 @@ class TestTelemetryClient:
TelemetryClient, "send_telemetry_event", _original_send_telemetry_event
)
config = build_test_vibe_config(enable_telemetry=True)
env_key = config.get_provider_for_model(
config.get_active_model()
).api_key_env_var
env_key = config.get_active_provider().api_key_env_var
monkeypatch.setenv(env_key, "sk-test")
current_id = "first-session-id"
client = TelemetryClient(
@ -389,6 +501,40 @@ class TestTelemetryClient:
calls[1].kwargs["json"]["properties"]["session_id"] == "second-session-id"
)
def test_send_auto_compact_triggered_overrides_session_metadata(
self, telemetry_events: list[dict[str, Any]]
) -> None:
config = build_test_vibe_config(enable_telemetry=True)
client = TelemetryClient(
config_getter=lambda: config,
session_id_getter=lambda: "new-session-id",
parent_session_id_getter=lambda: "new-parent-session-id",
)
client.send_auto_compact_triggered(
nb_context_tokens_before=123,
nb_context_tokens_after=45,
auto_compact_threshold=100,
status="success",
session_id="original-session-id",
parent_session_id=None,
)
assert len(telemetry_events) == 1
properties = telemetry_events[0]["properties"]
assert properties["session_id"] == "original-session-id"
assert properties["parent_session_id"] is None
def test_send_ready_payload(self, telemetry_events: list[dict[str, Any]]) -> None:
config = build_test_vibe_config(enable_telemetry=True)
client = TelemetryClient(config_getter=lambda: config)
client.send_ready(init_duration_ms=1240)
assert len(telemetry_events) == 1
assert telemetry_events[0]["event_name"] == "vibe.ready"
assert telemetry_events[0]["properties"]["init_duration_ms"] == 1240
def test_send_request_sent_payload(
self, telemetry_events: list[dict[str, Any]]
) -> None:
@ -400,6 +546,7 @@ class TestTelemetryClient:
nb_context_chars=1234,
nb_context_messages=5,
nb_prompt_chars=42,
call_type="main_call",
)
assert len(telemetry_events) == 1
@ -409,6 +556,9 @@ class TestTelemetryClient:
assert properties["nb_context_chars"] == 1234
assert properties["nb_context_messages"] == 5
assert properties["nb_prompt_chars"] == 42
assert properties["call_source"] == "vibe_code"
assert properties["call_type"] == "main_call"
assert properties["message_id"] is None
def test_send_user_rating_feedback_payload(
self, telemetry_events: list[dict[str, Any]]
@ -522,9 +672,7 @@ class TestTelemetryClient:
self, monkeypatch: pytest.MonkeyPatch
) -> None:
config = build_test_vibe_config(enable_telemetry=True)
env_key = config.get_provider_for_model(
config.get_active_model()
).api_key_env_var
env_key = config.get_active_provider().api_key_env_var
monkeypatch.delenv(env_key, raising=False)
client = TelemetryClient(config_getter=lambda: config)

View file

@ -134,7 +134,9 @@ class TestNuageClientStartWorkflow:
mock_client.post = AsyncMock(return_value=mock_response)
params = WorkflowParams(prompt="test", integrations=WorkflowIntegrations())
with pytest.raises(ServiceTeleportError, match="Nuage workflow trigger failed"):
with pytest.raises(
ServiceTeleportError, match="Vibe Code workflow trigger failed"
):
await nuage.start_workflow(params)

View file

@ -45,9 +45,9 @@ class TestTeleportServiceCompressDiff:
mock_session_logger = MagicMock()
return TeleportService(
session_logger=mock_session_logger,
nuage_base_url="https://api.example.com",
nuage_workflow_id="workflow-id",
nuage_api_key="api-key",
vibe_code_base_url="https://api.example.com",
vibe_code_workflow_id="workflow-id",
vibe_code_api_key="api-key",
workdir=tmp_path,
)
@ -75,9 +75,9 @@ class TestTeleportServiceBuildGitHubParams:
mock_session_logger = MagicMock()
return TeleportService(
session_logger=mock_session_logger,
nuage_base_url="https://api.example.com",
nuage_workflow_id="workflow-id",
nuage_api_key="api-key",
vibe_code_base_url="https://api.example.com",
vibe_code_workflow_id="workflow-id",
vibe_code_api_key="api-key",
workdir=tmp_path,
)
@ -116,9 +116,9 @@ class TestTeleportServiceValidateConfig:
mock_session_logger = MagicMock()
service = TeleportService(
session_logger=mock_session_logger,
nuage_base_url="https://api.example.com",
nuage_workflow_id="workflow-id",
nuage_api_key="",
vibe_code_base_url="https://api.example.com",
vibe_code_workflow_id="workflow-id",
vibe_code_api_key="",
workdir=tmp_path,
)
with pytest.raises(ServiceTeleportError, match="MISTRAL_API_KEY not set"):
@ -128,9 +128,9 @@ class TestTeleportServiceValidateConfig:
mock_session_logger = MagicMock()
service = TeleportService(
session_logger=mock_session_logger,
nuage_base_url="https://api.example.com",
nuage_workflow_id="workflow-id",
nuage_api_key="valid-key",
vibe_code_base_url="https://api.example.com",
vibe_code_workflow_id="workflow-id",
vibe_code_api_key="valid-key",
workdir=tmp_path,
)
service._validate_config()
@ -138,12 +138,12 @@ class TestTeleportServiceValidateConfig:
def test_uses_custom_env_var_name_in_error(self, tmp_path: Path) -> None:
mock_session_logger = MagicMock()
mock_config = MagicMock()
mock_config.nuage_api_key_env_var = "CUSTOM_API_KEY"
mock_config.vibe_code_api_key_env_var = "CUSTOM_API_KEY"
service = TeleportService(
session_logger=mock_session_logger,
nuage_base_url="https://api.example.com",
nuage_workflow_id="workflow-id",
nuage_api_key="",
vibe_code_base_url="https://api.example.com",
vibe_code_workflow_id="workflow-id",
vibe_code_api_key="",
workdir=tmp_path,
vibe_config=mock_config,
)
@ -157,9 +157,9 @@ class TestTeleportServiceCheckSupported:
mock_session_logger = MagicMock()
return TeleportService(
session_logger=mock_session_logger,
nuage_base_url="https://api.example.com",
nuage_workflow_id="workflow-id",
nuage_api_key="api-key",
vibe_code_base_url="https://api.example.com",
vibe_code_workflow_id="workflow-id",
vibe_code_api_key="api-key",
workdir=tmp_path,
)
@ -199,9 +199,9 @@ class TestTeleportServiceIsSupported:
mock_session_logger = MagicMock()
return TeleportService(
session_logger=mock_session_logger,
nuage_base_url="https://api.example.com",
nuage_workflow_id="workflow-id",
nuage_api_key="api-key",
vibe_code_base_url="https://api.example.com",
vibe_code_workflow_id="workflow-id",
vibe_code_api_key="api-key",
workdir=tmp_path,
)
@ -222,9 +222,9 @@ class TestTeleportServiceExecute:
mock_session_logger = MagicMock()
service = TeleportService(
session_logger=mock_session_logger,
nuage_base_url="https://api.example.com",
nuage_workflow_id="workflow-id",
nuage_api_key="api-key",
vibe_code_base_url="https://api.example.com",
vibe_code_workflow_id="workflow-id",
vibe_code_api_key="api-key",
workdir=tmp_path,
)
service._git.fetch = AsyncMock()
@ -268,7 +268,7 @@ class TestTeleportServiceExecute:
mock_nuage.get_chat_assistant_url = AsyncMock(
return_value="https://chat.example.com/123"
)
service._nuage = mock_nuage
service._nuage_client_instance = mock_nuage
session = TeleportSession()
events = []
@ -282,6 +282,9 @@ class TestTeleportServiceExecute:
assert isinstance(events[3], TeleportFetchingUrlEvent)
assert isinstance(events[4], TeleportCompleteEvent)
assert events[4].url == "https://chat.example.com/123"
workflow_params = mock_nuage.start_workflow.call_args.args[0]
assert workflow_params.integrations.chat_assistant is not None
assert workflow_params.integrations.chat_assistant.project_name is None
@pytest.mark.asyncio
async def test_execute_requires_push_and_user_approves(
@ -303,7 +306,7 @@ class TestTeleportServiceExecute:
mock_nuage.get_chat_assistant_url = AsyncMock(
return_value="https://chat.example.com/123"
)
service._nuage = mock_nuage
service._nuage_client_instance = mock_nuage
session = TeleportSession()
events = []
@ -368,7 +371,7 @@ class TestTeleportServiceExecute:
mock_nuage.get_chat_assistant_url = AsyncMock(
return_value="https://chat.example.com/123"
)
service._nuage = mock_nuage
service._nuage_client_instance = mock_nuage
session = TeleportSession()
events = []
@ -400,7 +403,7 @@ class TestTeleportServiceExecute:
return_value=mock_github_connected
)
mock_nuage.get_chat_assistant_url = AsyncMock(return_value=None)
service._nuage = mock_nuage
service._nuage_client_instance = mock_nuage
session = TeleportSession()
gen = service.execute("test prompt", session)
@ -427,7 +430,7 @@ class TestTeleportServiceExecute:
mock_nuage.get_chat_assistant_url = AsyncMock(
return_value="https://chat.example.com/123"
)
service._nuage = mock_nuage
service._nuage_client_instance = mock_nuage
session = TeleportSession(
messages=[{"role": "user", "content": "help me refactor"}]
@ -446,15 +449,15 @@ class TestTeleportServiceContextManager:
mock_session_logger = MagicMock()
service = TeleportService(
session_logger=mock_session_logger,
nuage_base_url="https://api.example.com",
nuage_workflow_id="workflow-id",
nuage_api_key="api-key",
vibe_code_base_url="https://api.example.com",
vibe_code_workflow_id="workflow-id",
vibe_code_api_key="api-key",
workdir=tmp_path,
)
assert service._client is None
async with service:
assert service._client is not None
assert service._nuage is not None
assert service._nuage_client_instance is not None
assert service._client is None

View file

@ -49,15 +49,23 @@ def strip_ansi(text: str) -> str:
return re.sub(r"\x1b\[[0-9;?]*[ -/]*[@-~]|\x1b\][^\x07]*\x07", "", text)
def poll_until(predicate: Callable[[], bool], timeout: float, message: str) -> None:
start = time.monotonic()
while time.monotonic() - start < timeout:
if predicate():
return
time.sleep(0.05)
raise AssertionError(message)
def wait_for_request_count(
request_count_getter: Callable[[], int], expected_count: int, timeout: float
) -> None:
start = time.monotonic()
while time.monotonic() - start < timeout:
if request_count_getter() >= expected_count:
return
time.sleep(0.05)
raise AssertionError(f"Timed out waiting for {expected_count} backend request(s).")
poll_until(
lambda: request_count_getter() >= expected_count,
timeout,
f"Timed out waiting for {expected_count} backend request(s).",
)
def wait_for_main_screen(child: pexpect.spawn, timeout: float = 20.0) -> None:
@ -84,3 +92,24 @@ def wait_for_rendered_text(
raise AssertionError(
f"Timed out waiting for rendered text: {needle!r}\n\nRendered tail:\n{rendered_tail}"
)
def send_ctrl_c_until_quit_confirmation(
child: pexpect.spawn, captured: io.StringIO, timeout: float = 3
) -> None:
"""Send Ctrl+C and wait for quit confirmation prompt. Retries if first Ctrl+C interrupts."""
start = time.monotonic()
while time.monotonic() - start < timeout:
child.sendcontrol("c")
try:
child.expect(ansi_tolerant_pattern("Press Ctrl+C again to quit"), timeout=2)
# Confirmation prompt appeared, send second Ctrl+C
child.sendcontrol("c")
return
except pexpect.TIMEOUT:
# First Ctrl+C may have interrupted something, try again
continue
rendered_tail = strip_ansi(captured.getvalue())[-1200:]
raise AssertionError(
f"Timed out waiting for quit confirmation prompt.\n\nRendered tail:\n{rendered_tail}"
)

View file

@ -0,0 +1,87 @@
from __future__ import annotations
import json
import os
from pathlib import Path
import tomllib
import pexpect
import pytest
import tomli_w
from tests.e2e.common import (
SpawnedVibeProcessFixture,
poll_until,
send_ctrl_c_until_quit_confirmation,
wait_for_main_screen,
wait_for_rendered_text,
wait_for_request_count,
)
from tests.e2e.mock_server import StreamingMockServer
def _enable_hooks(vibe_home: Path, invocation_path: Path) -> None:
config_path = vibe_home / "config.toml"
config = tomllib.loads(config_path.read_text(encoding="utf-8"))
config["enable_experimental_hooks"] = True
config_path.write_bytes(tomli_w.dumps(config).encode())
script = vibe_home / "_record_hook.py"
script.write_text(
"import json, sys\n"
"from pathlib import Path\n"
f"Path({str(invocation_path)!r}).write_text("
"json.dumps(json.load(sys.stdin)), encoding='utf-8')\n",
encoding="utf-8",
)
with (vibe_home / "hooks.toml").open("wb") as f:
tomli_w.dump(
{
"hooks": [
{
"name": "record-invocation",
"type": "post_agent_turn",
"command": f"uv run python {script}",
}
]
},
f,
)
@pytest.mark.timeout(20)
def test_spawn_cli_runs_configured_hook_after_turn(
streaming_mock_server: StreamingMockServer,
setup_e2e_env: None,
e2e_workdir: Path,
spawned_vibe_process: SpawnedVibeProcessFixture,
) -> None:
vibe_home = Path(os.environ["VIBE_HOME"])
invocation_path = vibe_home / "hook-invocation.json"
_enable_hooks(vibe_home, invocation_path)
with spawned_vibe_process(e2e_workdir) as (child, captured):
wait_for_main_screen(child, timeout=15)
child.send("Run the configured hook")
child.send("\r")
wait_for_request_count(
lambda: len(streaming_mock_server.requests), expected_count=1, timeout=10
)
wait_for_rendered_text(
child, captured, needle="Hello from mock server", timeout=10
)
poll_until(
invocation_path.is_file,
timeout=10,
message=f"Timed out waiting for hook output file: {invocation_path}",
)
send_ctrl_c_until_quit_confirmation(child, captured, timeout=5)
child.expect(pexpect.EOF, timeout=10)
assert len(streaming_mock_server.requests) == 1
invocation = json.loads(invocation_path.read_text(encoding="utf-8"))
assert invocation["hook_event_name"] == "post_agent_turn"
assert isinstance(invocation["cwd"], str) and invocation["cwd"]
assert isinstance(invocation["session_id"], str) and invocation["session_id"]

View file

@ -12,6 +12,7 @@ import pytest
from tests.e2e.common import (
SpawnedVibeProcessFixture,
ansi_tolerant_pattern,
send_ctrl_c_until_quit_confirmation,
strip_ansi,
wait_for_main_screen,
wait_for_request_count,
@ -103,7 +104,7 @@ def test_resumed_session_prints_only_fresh_token_usage_on_exit(
request_count_getter=lambda: len(streaming_mock_server.requests),
)
child.sendcontrol("c")
send_ctrl_c_until_quit_confirmation(child, captured, timeout=5)
child.expect(pexpect.EOF, timeout=10)
first_output = strip_ansi(captured.getvalue())
@ -130,7 +131,7 @@ def test_resumed_session_prints_only_fresh_token_usage_on_exit(
request_count_getter=lambda: len(streaming_mock_server.requests),
)
resumed_child.sendcontrol("c")
send_ctrl_c_until_quit_confirmation(resumed_child, resumed_captured, timeout=5)
resumed_child.expect(pexpect.EOF, timeout=10)
second_output = strip_ansi(resumed_captured.getvalue())

View file

@ -8,6 +8,7 @@ import pytest
from tests.e2e.common import (
SpawnedVibeProcessFixture,
ansi_tolerant_pattern,
send_ctrl_c_until_quit_confirmation,
wait_for_main_screen,
wait_for_request_count,
)
@ -31,7 +32,7 @@ def test_spawn_cli_to_send_and_receive_message(
)
child.expect(ansi_tolerant_pattern("Hello from mock server"), timeout=10)
child.sendcontrol("c")
send_ctrl_c_until_quit_confirmation(child, captured, timeout=5)
child.expect(pexpect.EOF, timeout=10)
output = captured.getvalue()

View file

@ -7,6 +7,7 @@ import pytest
from tests.e2e.common import (
SpawnedVibeProcessFixture,
send_ctrl_c_until_quit_confirmation,
wait_for_main_screen,
wait_for_rendered_text,
wait_for_request_count,
@ -83,5 +84,5 @@ def test_spawn_cli_asks_bash_permission_and_shows_tool_output_after_approval(
child.send("\r")
wait_for_rendered_text(child, captured, needle=PREDICTABLE_OUTPUT, timeout=10)
child.sendcontrol("c")
send_ctrl_c_until_quit_confirmation(child, captured, timeout=5)
child.expect(pexpect.EOF, timeout=10)

View file

@ -9,6 +9,9 @@ from textual.widgets import Input
from vibe.core.config import ProviderConfig
from vibe.core.paths import GLOBAL_ENV_FILE
from vibe.core.telemetry.build_metadata import build_entrypoint_metadata
from vibe.core.telemetry.send import TelemetryClient
from vibe.core.types import Backend
from vibe.setup.onboarding import OnboardingApp
from vibe.setup.onboarding.screens.api_key import ApiKeyScreen, persist_api_key
@ -118,3 +121,39 @@ def test_persist_api_key_returns_env_var_error_for_empty_env_var_name() -> None:
result = persist_api_key(provider, "secret")
assert result == "env_var_error:<empty>"
def test_persist_api_key_sends_onboarding_telemetry_with_entrypoint_metadata(
monkeypatch: pytest.MonkeyPatch,
) -> None:
recorded_metadata: dict[str, str] = {}
def capture(self: TelemetryClient) -> None:
recorded_metadata.update(self.build_client_event_metadata())
monkeypatch.setattr(TelemetryClient, "send_onboarding_api_key_added", capture)
provider = ProviderConfig(
name="mistral",
api_base="https://api.mistral.ai/v1",
api_key_env_var="MISTRAL_API_KEY",
backend=Backend.MISTRAL,
)
result = persist_api_key(
provider,
"secret",
entrypoint_metadata=build_entrypoint_metadata(
agent_entrypoint="cli",
agent_version="1.0.0",
client_name="vibe_cli",
client_version="1.0.0",
),
)
assert result == "completed"
assert recorded_metadata["agent_entrypoint"] == "cli"
assert recorded_metadata["agent_version"] == "1.0.0"
assert recorded_metadata["client_name"] == "vibe_cli"
assert recorded_metadata["client_version"] == "1.0.0"
assert "session_id" not in recorded_metadata

View file

@ -39,31 +39,31 @@ class TestShortSessionId:
class TestListRemoteResumeSessions:
@pytest.mark.asyncio
async def test_returns_empty_when_nuage_disabled(self) -> None:
async def test_returns_empty_when_vibe_code_disabled(self) -> None:
config = MagicMock()
config.nuage_enabled = False
config.nuage_api_key = "key"
config.vibe_code_enabled = False
config.vibe_code_api_key = "key"
result = await list_remote_resume_sessions(config)
assert result == []
@pytest.mark.asyncio
async def test_returns_empty_when_no_api_key(self) -> None:
config = MagicMock()
config.nuage_enabled = True
config.nuage_api_key = None
config.vibe_code_enabled = True
config.vibe_code_api_key = None
result = await list_remote_resume_sessions(config)
assert result == []
@pytest.mark.asyncio
async def test_returns_empty_when_both_missing(self) -> None:
config = MagicMock()
config.nuage_enabled = False
config.nuage_api_key = None
config.vibe_code_enabled = False
config.vibe_code_api_key = None
result = await list_remote_resume_sessions(config)
assert result == []
@pytest.mark.asyncio
async def test_filters_only_active_statuses(self) -> None:
async def test_passes_active_statuses_to_api(self) -> None:
from datetime import datetime
from vibe.core.nuage.workflow import (
@ -79,13 +79,6 @@ class TestListRemoteResumeSessions:
start_time=datetime(2026, 1, 1),
end_time=None,
)
completed = WorkflowExecutionWithoutResultResponse(
workflow_name="vibe",
execution_id="exec-completed",
status=WorkflowExecutionStatus.COMPLETED,
start_time=datetime(2026, 1, 1),
end_time=datetime(2026, 1, 2),
)
retrying = WorkflowExecutionWithoutResultResponse(
workflow_name="vibe",
execution_id="exec-retrying",
@ -93,17 +86,90 @@ class TestListRemoteResumeSessions:
start_time=datetime(2026, 1, 1),
end_time=None,
)
continued = WorkflowExecutionWithoutResultResponse(
workflow_name="vibe",
execution_id="exec-continued",
status=WorkflowExecutionStatus.CONTINUED_AS_NEW,
start_time=datetime(2026, 1, 1),
end_time=None,
)
mock_response = WorkflowExecutionListResponse(
executions=[running, completed, retrying]
executions=[running, retrying, continued]
)
config = MagicMock()
config.nuage_enabled = True
config.nuage_api_key = "test-key"
config.nuage_base_url = "https://test.example.com"
config.vibe_code_enabled = True
config.vibe_code_api_key = "test-key"
config.vibe_code_base_url = "https://test.example.com"
config.api_timeout = 30
config.nuage_workflow_id = "workflow-1"
config.vibe_code_workflow_id = "workflow-1"
with patch("vibe.core.session.resume_sessions.WorkflowsClient") as MockClient:
mock_client = AsyncMock()
mock_client.get_workflow_runs.return_value = mock_response
MockClient.return_value.__aenter__ = AsyncMock(return_value=mock_client)
MockClient.return_value.__aexit__ = AsyncMock(return_value=False)
result = await list_remote_resume_sessions(config)
assert len(result) == 3
session_ids = {s.session_id for s in result}
assert "exec-running" in session_ids
assert "exec-retrying" in session_ids
assert "exec-continued" in session_ids
assert all(s.source == "remote" for s in result)
mock_client.get_workflow_runs.assert_called_once_with(
workflow_identifier="workflow-1",
page_size=50,
status=[
WorkflowExecutionStatus.RUNNING,
WorkflowExecutionStatus.RETRYING_AFTER_ERROR,
WorkflowExecutionStatus.CONTINUED_AS_NEW,
],
)
@pytest.mark.asyncio
async def test_deduplicates_execution_ids_keeps_latest(self) -> None:
from datetime import datetime
from vibe.core.nuage.workflow import (
WorkflowExecutionListResponse,
WorkflowExecutionStatus,
WorkflowExecutionWithoutResultResponse,
)
older = WorkflowExecutionWithoutResultResponse(
workflow_name="vibe",
execution_id="exec-1",
status=WorkflowExecutionStatus.RUNNING,
start_time=datetime(2026, 1, 1),
end_time=None,
)
newer = WorkflowExecutionWithoutResultResponse(
workflow_name="vibe",
execution_id="exec-1",
status=WorkflowExecutionStatus.RUNNING,
start_time=datetime(2026, 1, 5),
end_time=None,
)
other = WorkflowExecutionWithoutResultResponse(
workflow_name="vibe",
execution_id="exec-2",
status=WorkflowExecutionStatus.RUNNING,
start_time=datetime(2026, 1, 3),
end_time=None,
)
mock_response = WorkflowExecutionListResponse(executions=[older, newer, other])
config = MagicMock()
config.vibe_code_enabled = True
config.vibe_code_api_key = "test-key"
config.vibe_code_base_url = "https://test.example.com"
config.api_timeout = 30
config.vibe_code_workflow_id = "workflow-1"
with patch("vibe.core.session.resume_sessions.WorkflowsClient") as MockClient:
mock_client = AsyncMock()
@ -114,8 +180,54 @@ class TestListRemoteResumeSessions:
result = await list_remote_resume_sessions(config)
assert len(result) == 2
session_ids = {s.session_id for s in result}
assert "exec-running" in session_ids
assert "exec-retrying" in session_ids
assert "exec-completed" not in session_ids
assert all(s.source == "remote" for s in result)
by_id = {s.session_id: s for s in result}
assert by_id["exec-1"].end_time == datetime(2026, 1, 5).isoformat()
assert "exec-2" in by_id
@pytest.mark.asyncio
async def test_dedup_keeps_latest_start_time_when_previous_has_end_time(
self,
) -> None:
from datetime import datetime
from vibe.core.nuage.workflow import (
WorkflowExecutionListResponse,
WorkflowExecutionStatus,
WorkflowExecutionWithoutResultResponse,
)
previous = WorkflowExecutionWithoutResultResponse(
workflow_name="vibe",
execution_id="exec-1",
status=WorkflowExecutionStatus.RETRYING_AFTER_ERROR,
start_time=datetime(2026, 1, 1),
end_time=datetime(2026, 1, 10),
)
newer = WorkflowExecutionWithoutResultResponse(
workflow_name="vibe",
execution_id="exec-1",
status=WorkflowExecutionStatus.RUNNING,
start_time=datetime(2026, 1, 5),
end_time=None,
)
mock_response = WorkflowExecutionListResponse(executions=[previous, newer])
config = MagicMock()
config.vibe_code_enabled = True
config.vibe_code_api_key = "test-key"
config.vibe_code_base_url = "https://test.example.com"
config.api_timeout = 30
config.vibe_code_workflow_id = "workflow-1"
with patch("vibe.core.session.resume_sessions.WorkflowsClient") as MockClient:
mock_client = AsyncMock()
mock_client.get_workflow_runs.return_value = mock_response
MockClient.return_value.__aenter__ = AsyncMock(return_value=mock_client)
MockClient.return_value.__aexit__ = AsyncMock(return_value=False)
result = await list_remote_resume_sessions(config)
assert len(result) == 1
assert result[0].session_id == "exec-1"
assert result[0].status == WorkflowExecutionStatus.RUNNING

View file

@ -39,10 +39,11 @@ def create_test_session():
messages: list[LLMMessage] | None = None,
metadata: dict | None = None,
encoding: str = "utf-8",
working_directory: Path | None = Path("/test"),
) -> Path:
"""Create a test session directory with messages and metadata files."""
# Create session directory
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S_%f")
session_folder = session_dir / f"test_{timestamp}_{session_id[:8]}"
session_folder.mkdir(exist_ok=True)
@ -79,7 +80,7 @@ def create_test_session():
},
"system_prompt": {"content": "System prompt", "role": "system"},
"username": "testuser",
"environment": {"working_directory": "/test"},
"environment": {"working_directory": str(working_directory)},
"git_commit": None,
"git_branch": None,
}
@ -129,6 +130,93 @@ class TestSessionLoaderFindLatestSession:
assert result.exists()
assert result == latest
@pytest.mark.parametrize(
("cwd", "expected_id"),
[
pytest.param(
Path("/home/user/project-a"), "aaaaaaaa", id="get_latest_in_existing_a"
),
pytest.param(
Path("/home/user/project-b"), "bbbbbbbb", id="get_latest_in_existing_b"
),
pytest.param(
Path("/home/user/project-c"), None, id="get_latest_in_missing_c"
),
pytest.param(None, "aaaaaaaa", id="get_latest_globally"),
],
)
def test_find_latest_session_cwd_filtering(
self,
session_config: SessionLoggingConfig,
create_test_session,
cwd: Path | None,
expected_id: str | None,
) -> None:
session_dir = Path(session_config.save_dir)
create_test_session(
session_dir,
"aaaaaaaa-session",
working_directory=Path("/home/user/project-a"),
)
time.sleep(0.01)
create_test_session(
session_dir,
"bbbbbbbb-session",
working_directory=Path("/home/user/project-b"),
)
time.sleep(0.01)
second_b = create_test_session(
session_dir,
"bbbbbbbb-session",
working_directory=Path("/home/user/project-b"),
)
time.sleep(0.01)
second_a = create_test_session(
session_dir,
"aaaaaaaa-session",
working_directory=Path("/home/user/project-a"),
)
assert len(list(session_dir.glob("test_*"))) == 4
expected: Path | None
if expected_id == "aaaaaaaa":
expected = second_a
elif expected_id == "bbbbbbbb":
expected = second_b
elif expected_id is None:
expected = None
else:
raise NotImplementedError(expected_id)
result = SessionLoader.find_latest_session(
session_config, working_directory=cwd
)
assert result == expected
def test_find_latest_session_cwd_filtering_skips_invalid_metadata(
self, session_config: SessionLoggingConfig, create_test_session
) -> None:
session_dir = Path(session_config.save_dir)
expected = create_test_session(
session_dir,
"valid-cwd-session",
working_directory=Path("/home/user/project-a"),
)
time.sleep(0.01)
invalid_metadata_session = create_test_session(
session_dir,
"invalid-metadata",
working_directory=Path("/home/user/project-a"),
)
(invalid_metadata_session / "meta.json").write_text("{}")
result = SessionLoader.find_latest_session(
session_config, working_directory=Path("/home/user/project-a")
)
assert result == expected
def test_find_latest_session_nonexistent_save_dir(self) -> None:
"""Test finding latest session when save directory doesn't exist."""
# Modify config to point to non-existent directory

View file

@ -119,7 +119,7 @@
</text><text class="terminal-r1" x="1464" y="142" textLength="12.2" clip-path="url(#terminal-line-5)">
</text><text class="terminal-r1" x="1464" y="166.4" textLength="12.2" clip-path="url(#terminal-line-6)">
</text><text class="terminal-r1" x="1464" y="190.8" textLength="12.2" clip-path="url(#terminal-line-7)">
</text><text class="terminal-r1" x="0" y="215.2" textLength="134.2" clip-path="url(#terminal-line-8)">&#160;&#160;⡠⣒⠄&#160;&#160;⡔⢄⠔⡄</text><text class="terminal-r2" x="170.8" y="215.2" textLength="146.4" clip-path="url(#terminal-line-8)">Mistral&#160;Vibe</text><text class="terminal-r1" x="317.2" y="215.2" textLength="122" clip-path="url(#terminal-line-8)">&#160;v0.0.0&#160;·&#160;</text><text class="terminal-r3" x="439.2" y="215.2" textLength="183" clip-path="url(#terminal-line-8)">devstral-latest</text><text class="terminal-r1" x="622.2" y="215.2" textLength="256.2" clip-path="url(#terminal-line-8)">&#160;·&#160;[Subscription]&#160;Pro</text><text class="terminal-r1" x="1464" y="215.2" textLength="12.2" clip-path="url(#terminal-line-8)">
</text><text class="terminal-r1" x="0" y="215.2" textLength="134.2" clip-path="url(#terminal-line-8)">&#160;&#160;⡠⣒⠄&#160;&#160;⡔⢄⠔⡄</text><text class="terminal-r2" x="170.8" y="215.2" textLength="146.4" clip-path="url(#terminal-line-8)">Mistral&#160;Vibe</text><text class="terminal-r1" x="317.2" y="215.2" textLength="122" clip-path="url(#terminal-line-8)">&#160;v0.0.0&#160;·&#160;</text><text class="terminal-r3" x="439.2" y="215.2" textLength="244" clip-path="url(#terminal-line-8)">devstral-latest[off]</text><text class="terminal-r1" x="683.2" y="215.2" textLength="256.2" clip-path="url(#terminal-line-8)">&#160;·&#160;[Subscription]&#160;Pro</text><text class="terminal-r1" x="1464" y="215.2" textLength="12.2" clip-path="url(#terminal-line-8)">
</text><text class="terminal-r1" x="0" y="239.6" textLength="134.2" clip-path="url(#terminal-line-9)">&#160;⢸⠸⣀⡔⢉⠱⣃⡢⣂⡣</text><text class="terminal-r1" x="170.8" y="239.6" textLength="414.8" clip-path="url(#terminal-line-9)">1&#160;model&#160;·&#160;0&#160;MCP&#160;servers&#160;·&#160;0&#160;skills</text><text class="terminal-r1" x="1464" y="239.6" textLength="12.2" clip-path="url(#terminal-line-9)">
</text><text class="terminal-r1" x="0" y="264" textLength="134.2" clip-path="url(#terminal-line-10)">&#160;&#160;⠉⠒⠣⠤⠵⠤⠬⠮⠆</text><text class="terminal-r1" x="170.8" y="264" textLength="61" clip-path="url(#terminal-line-10)">Type&#160;</text><text class="terminal-r3" x="231.8" y="264" textLength="61" clip-path="url(#terminal-line-10)">/help</text><text class="terminal-r1" x="292.8" y="264" textLength="256.2" clip-path="url(#terminal-line-10)">&#160;for&#160;more&#160;information</text><text class="terminal-r1" x="1464" y="264" textLength="12.2" clip-path="url(#terminal-line-10)">
</text><text class="terminal-r1" x="1464" y="288.4" textLength="12.2" clip-path="url(#terminal-line-11)">

Before

Width:  |  Height:  |  Size: 9.4 KiB

After

Width:  |  Height:  |  Size: 9.4 KiB

Before After
Before After

View file

@ -153,7 +153,7 @@
</text><text class="terminal-r1" x="1464" y="239.6" textLength="12.2" clip-path="url(#terminal-line-9)">
</text><text class="terminal-r1" x="1464" y="264" textLength="12.2" clip-path="url(#terminal-line-10)">
</text><text class="terminal-r1" x="1464" y="288.4" textLength="12.2" clip-path="url(#terminal-line-11)">
</text><text class="terminal-r1" x="0" y="312.8" textLength="134.2" clip-path="url(#terminal-line-12)">&#160;&#160;⡠⣒⠄&#160;&#160;⡔⢄⠔⡄</text><text class="terminal-r2" x="170.8" y="312.8" textLength="146.4" clip-path="url(#terminal-line-12)">Mistral&#160;Vibe</text><text class="terminal-r1" x="317.2" y="312.8" textLength="122" clip-path="url(#terminal-line-12)">&#160;v0.0.0&#160;·&#160;</text><text class="terminal-r3" x="439.2" y="312.8" textLength="183" clip-path="url(#terminal-line-12)">devstral-latest</text><text class="terminal-r1" x="622.2" y="312.8" textLength="256.2" clip-path="url(#terminal-line-12)">&#160;·&#160;[Subscription]&#160;Pro</text><text class="terminal-r1" x="1464" y="312.8" textLength="12.2" clip-path="url(#terminal-line-12)">
</text><text class="terminal-r1" x="0" y="312.8" textLength="134.2" clip-path="url(#terminal-line-12)">&#160;&#160;⡠⣒⠄&#160;&#160;⡔⢄⠔⡄</text><text class="terminal-r2" x="170.8" y="312.8" textLength="146.4" clip-path="url(#terminal-line-12)">Mistral&#160;Vibe</text><text class="terminal-r1" x="317.2" y="312.8" textLength="122" clip-path="url(#terminal-line-12)">&#160;v0.0.0&#160;·&#160;</text><text class="terminal-r3" x="439.2" y="312.8" textLength="244" clip-path="url(#terminal-line-12)">devstral-latest[off]</text><text class="terminal-r1" x="683.2" y="312.8" textLength="256.2" clip-path="url(#terminal-line-12)">&#160;·&#160;[Subscription]&#160;Pro</text><text class="terminal-r1" x="1464" y="312.8" textLength="12.2" clip-path="url(#terminal-line-12)">
</text><text class="terminal-r1" x="0" y="337.2" textLength="134.2" clip-path="url(#terminal-line-13)">&#160;⢸⠸⣀⡔⢉⠱⣃⡢⣂⡣</text><text class="terminal-r1" x="170.8" y="337.2" textLength="414.8" clip-path="url(#terminal-line-13)">1&#160;model&#160;·&#160;0&#160;MCP&#160;servers&#160;·&#160;0&#160;skills</text><text class="terminal-r1" x="1464" y="337.2" textLength="12.2" clip-path="url(#terminal-line-13)">
</text><text class="terminal-r1" x="0" y="361.6" textLength="134.2" clip-path="url(#terminal-line-14)">&#160;&#160;⠉⠒⠣⠤⠵⠤⠬⠮⠆</text><text class="terminal-r1" x="170.8" y="361.6" textLength="61" clip-path="url(#terminal-line-14)">Type&#160;</text><text class="terminal-r3" x="231.8" y="361.6" textLength="61" clip-path="url(#terminal-line-14)">/help</text><text class="terminal-r1" x="292.8" y="361.6" textLength="256.2" clip-path="url(#terminal-line-14)">&#160;for&#160;more&#160;information</text><text class="terminal-r1" x="1464" y="361.6" textLength="12.2" clip-path="url(#terminal-line-14)">
</text><text class="terminal-r1" x="1464" y="386" textLength="12.2" clip-path="url(#terminal-line-15)">

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 13 KiB

Before After
Before After

View file

@ -180,7 +180,7 @@
</text><text class="terminal-r1" x="1464" y="434.8" textLength="12.2" clip-path="url(#terminal-line-17)">
</text><text class="terminal-r1" x="1464" y="459.2" textLength="12.2" clip-path="url(#terminal-line-18)">
</text><text class="terminal-r1" x="1464" y="483.6" textLength="12.2" clip-path="url(#terminal-line-19)">
</text><text class="terminal-r1" x="0" y="508" textLength="134.2" clip-path="url(#terminal-line-20)">&#160;&#160;⡠⣒⠄&#160;&#160;⡔⢄⠔⡄</text><text class="terminal-r2" x="170.8" y="508" textLength="146.4" clip-path="url(#terminal-line-20)">Mistral&#160;Vibe</text><text class="terminal-r1" x="317.2" y="508" textLength="122" clip-path="url(#terminal-line-20)">&#160;v0.0.0&#160;·&#160;</text><text class="terminal-r3" x="439.2" y="508" textLength="183" clip-path="url(#terminal-line-20)">devstral-latest</text><text class="terminal-r1" x="622.2" y="508" textLength="256.2" clip-path="url(#terminal-line-20)">&#160;·&#160;[Subscription]&#160;Pro</text><text class="terminal-r1" x="1464" y="508" textLength="12.2" clip-path="url(#terminal-line-20)">
</text><text class="terminal-r1" x="0" y="508" textLength="134.2" clip-path="url(#terminal-line-20)">&#160;&#160;⡠⣒⠄&#160;&#160;⡔⢄⠔⡄</text><text class="terminal-r2" x="170.8" y="508" textLength="146.4" clip-path="url(#terminal-line-20)">Mistral&#160;Vibe</text><text class="terminal-r1" x="317.2" y="508" textLength="122" clip-path="url(#terminal-line-20)">&#160;v0.0.0&#160;·&#160;</text><text class="terminal-r3" x="439.2" y="508" textLength="244" clip-path="url(#terminal-line-20)">devstral-latest[off]</text><text class="terminal-r1" x="683.2" y="508" textLength="256.2" clip-path="url(#terminal-line-20)">&#160;·&#160;[Subscription]&#160;Pro</text><text class="terminal-r1" x="1464" y="508" textLength="12.2" clip-path="url(#terminal-line-20)">
</text><text class="terminal-r1" x="0" y="532.4" textLength="134.2" clip-path="url(#terminal-line-21)">&#160;⢸⠸⣀⡔⢉⠱⣃⡢⣂⡣</text><text class="terminal-r1" x="170.8" y="532.4" textLength="414.8" clip-path="url(#terminal-line-21)">1&#160;model&#160;·&#160;0&#160;MCP&#160;servers&#160;·&#160;0&#160;skills</text><text class="terminal-r1" x="1464" y="532.4" textLength="12.2" clip-path="url(#terminal-line-21)">
</text><text class="terminal-r1" x="0" y="556.8" textLength="134.2" clip-path="url(#terminal-line-22)">&#160;&#160;⠉⠒⠣⠤⠵⠤⠬⠮⠆</text><text class="terminal-r1" x="170.8" y="556.8" textLength="61" clip-path="url(#terminal-line-22)">Type&#160;</text><text class="terminal-r3" x="231.8" y="556.8" textLength="61" clip-path="url(#terminal-line-22)">/help</text><text class="terminal-r1" x="292.8" y="556.8" textLength="256.2" clip-path="url(#terminal-line-22)">&#160;for&#160;more&#160;information</text><text class="terminal-r1" x="1464" y="556.8" textLength="12.2" clip-path="url(#terminal-line-22)">
</text><text class="terminal-r1" x="1464" y="581.2" textLength="12.2" clip-path="url(#terminal-line-23)">

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 13 KiB

Before After
Before After

View file

@ -180,7 +180,7 @@
</text><text class="terminal-r1" x="1464" y="312.8" textLength="12.2" clip-path="url(#terminal-line-12)">
</text><text class="terminal-r1" x="1464" y="337.2" textLength="12.2" clip-path="url(#terminal-line-13)">
</text><text class="terminal-r1" x="1464" y="361.6" textLength="12.2" clip-path="url(#terminal-line-14)">
</text><text class="terminal-r1" x="0" y="386" textLength="134.2" clip-path="url(#terminal-line-15)">&#160;&#160;⡠⣒⠄&#160;&#160;⡔⢄⠔⡄</text><text class="terminal-r2" x="170.8" y="386" textLength="146.4" clip-path="url(#terminal-line-15)">Mistral&#160;Vibe</text><text class="terminal-r1" x="317.2" y="386" textLength="122" clip-path="url(#terminal-line-15)">&#160;v0.0.0&#160;·&#160;</text><text class="terminal-r3" x="439.2" y="386" textLength="183" clip-path="url(#terminal-line-15)">devstral-latest</text><text class="terminal-r1" x="622.2" y="386" textLength="256.2" clip-path="url(#terminal-line-15)">&#160;·&#160;[Subscription]&#160;Pro</text><text class="terminal-r1" x="1464" y="386" textLength="12.2" clip-path="url(#terminal-line-15)">
</text><text class="terminal-r1" x="0" y="386" textLength="134.2" clip-path="url(#terminal-line-15)">&#160;&#160;⡠⣒⠄&#160;&#160;⡔⢄⠔⡄</text><text class="terminal-r2" x="170.8" y="386" textLength="146.4" clip-path="url(#terminal-line-15)">Mistral&#160;Vibe</text><text class="terminal-r1" x="317.2" y="386" textLength="122" clip-path="url(#terminal-line-15)">&#160;v0.0.0&#160;·&#160;</text><text class="terminal-r3" x="439.2" y="386" textLength="244" clip-path="url(#terminal-line-15)">devstral-latest[off]</text><text class="terminal-r1" x="683.2" y="386" textLength="256.2" clip-path="url(#terminal-line-15)">&#160;·&#160;[Subscription]&#160;Pro</text><text class="terminal-r1" x="1464" y="386" textLength="12.2" clip-path="url(#terminal-line-15)">
</text><text class="terminal-r1" x="0" y="410.4" textLength="134.2" clip-path="url(#terminal-line-16)">&#160;⢸⠸⣀⡔⢉⠱⣃⡢⣂⡣</text><text class="terminal-r1" x="170.8" y="410.4" textLength="414.8" clip-path="url(#terminal-line-16)">1&#160;model&#160;·&#160;0&#160;MCP&#160;servers&#160;·&#160;0&#160;skills</text><text class="terminal-r1" x="1464" y="410.4" textLength="12.2" clip-path="url(#terminal-line-16)">
</text><text class="terminal-r1" x="0" y="434.8" textLength="134.2" clip-path="url(#terminal-line-17)">&#160;&#160;⠉⠒⠣⠤⠵⠤⠬⠮⠆</text><text class="terminal-r1" x="170.8" y="434.8" textLength="61" clip-path="url(#terminal-line-17)">Type&#160;</text><text class="terminal-r3" x="231.8" y="434.8" textLength="61" clip-path="url(#terminal-line-17)">/help</text><text class="terminal-r1" x="292.8" y="434.8" textLength="256.2" clip-path="url(#terminal-line-17)">&#160;for&#160;more&#160;information</text><text class="terminal-r1" x="1464" y="434.8" textLength="12.2" clip-path="url(#terminal-line-17)">
</text><text class="terminal-r1" x="1464" y="459.2" textLength="12.2" clip-path="url(#terminal-line-18)">

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 15 KiB

Before After
Before After

View file

@ -181,7 +181,7 @@
</text><text class="terminal-r1" x="1220" y="483.6" textLength="12.2" clip-path="url(#terminal-line-19)">
</text><text class="terminal-r1" x="1220" y="508" textLength="12.2" clip-path="url(#terminal-line-20)">
</text><text class="terminal-r1" x="1220" y="532.4" textLength="12.2" clip-path="url(#terminal-line-21)">
</text><text class="terminal-r1" x="0" y="556.8" textLength="134.2" clip-path="url(#terminal-line-22)">&#160;&#160;⡠⣒⠄&#160;&#160;⡔⢄⠔⡄</text><text class="terminal-r2" x="170.8" y="556.8" textLength="146.4" clip-path="url(#terminal-line-22)">Mistral&#160;Vibe</text><text class="terminal-r1" x="317.2" y="556.8" textLength="122" clip-path="url(#terminal-line-22)">&#160;v0.0.0&#160;·&#160;</text><text class="terminal-r3" x="439.2" y="556.8" textLength="183" clip-path="url(#terminal-line-22)">devstral-latest</text><text class="terminal-r1" x="622.2" y="556.8" textLength="256.2" clip-path="url(#terminal-line-22)">&#160;·&#160;[Subscription]&#160;Pro</text><text class="terminal-r1" x="1220" y="556.8" textLength="12.2" clip-path="url(#terminal-line-22)">
</text><text class="terminal-r1" x="0" y="556.8" textLength="134.2" clip-path="url(#terminal-line-22)">&#160;&#160;⡠⣒⠄&#160;&#160;⡔⢄⠔⡄</text><text class="terminal-r2" x="170.8" y="556.8" textLength="146.4" clip-path="url(#terminal-line-22)">Mistral&#160;Vibe</text><text class="terminal-r1" x="317.2" y="556.8" textLength="122" clip-path="url(#terminal-line-22)">&#160;v0.0.0&#160;·&#160;</text><text class="terminal-r3" x="439.2" y="556.8" textLength="244" clip-path="url(#terminal-line-22)">devstral-latest[off]</text><text class="terminal-r1" x="683.2" y="556.8" textLength="256.2" clip-path="url(#terminal-line-22)">&#160;·&#160;[Subscription]&#160;Pro</text><text class="terminal-r1" x="1220" y="556.8" textLength="12.2" clip-path="url(#terminal-line-22)">
</text><text class="terminal-r1" x="0" y="581.2" textLength="134.2" clip-path="url(#terminal-line-23)">&#160;⢸⠸⣀⡔⢉⠱⣃⡢⣂⡣</text><text class="terminal-r1" x="170.8" y="581.2" textLength="414.8" clip-path="url(#terminal-line-23)">1&#160;model&#160;·&#160;0&#160;MCP&#160;servers&#160;·&#160;0&#160;skills</text><text class="terminal-r1" x="1220" y="581.2" textLength="12.2" clip-path="url(#terminal-line-23)">
</text><text class="terminal-r1" x="0" y="605.6" textLength="134.2" clip-path="url(#terminal-line-24)">&#160;&#160;⠉⠒⠣⠤⠵⠤⠬⠮⠆</text><text class="terminal-r1" x="170.8" y="605.6" textLength="61" clip-path="url(#terminal-line-24)">Type&#160;</text><text class="terminal-r3" x="231.8" y="605.6" textLength="61" clip-path="url(#terminal-line-24)">/help</text><text class="terminal-r1" x="292.8" y="605.6" textLength="256.2" clip-path="url(#terminal-line-24)">&#160;for&#160;more&#160;information</text><text class="terminal-r1" x="1220" y="605.6" textLength="12.2" clip-path="url(#terminal-line-24)">
</text><text class="terminal-r1" x="1220" y="630" textLength="12.2" clip-path="url(#terminal-line-25)">

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 13 KiB

Before After
Before After

View file

@ -161,7 +161,7 @@
</g>
<g transform="translate(9, 41)" clip-path="url(#terminal-clip-terminal)">
<rect fill="#608ab1" x="36.6" y="709.1" width="85.4" height="24.65" shape-rendering="crispEdges"/><rect fill="#608ab1" x="122" y="709.1" width="183" height="24.65" shape-rendering="crispEdges"/><rect fill="#608ab1" x="305" y="709.1" width="878.4" height="24.65" shape-rendering="crispEdges"/>
<rect fill="#608ab1" x="36.6" y="684.7" width="85.4" height="24.65" shape-rendering="crispEdges"/><rect fill="#608ab1" x="122" y="684.7" width="183" height="24.65" shape-rendering="crispEdges"/><rect fill="#608ab1" x="305" y="684.7" width="878.4" height="24.65" shape-rendering="crispEdges"/>
<g class="terminal-matrix">
<text class="terminal-r1" x="1220" y="20" textLength="12.2" clip-path="url(#terminal-line-0)">
</text><text class="terminal-r1" x="1220" y="44.4" textLength="12.2" clip-path="url(#terminal-line-1)">
@ -181,18 +181,18 @@
</text><text class="terminal-r1" x="1220" y="386" textLength="12.2" clip-path="url(#terminal-line-15)">
</text><text class="terminal-r1" x="1220" y="410.4" textLength="12.2" clip-path="url(#terminal-line-16)">
</text><text class="terminal-r1" x="1220" y="434.8" textLength="12.2" clip-path="url(#terminal-line-17)">
</text><text class="terminal-r1" x="1220" y="459.2" textLength="12.2" clip-path="url(#terminal-line-18)">
</text><text class="terminal-r1" x="0" y="483.6" textLength="134.2" clip-path="url(#terminal-line-19)">&#160;&#160;⡠⣒⠄&#160;&#160;⡔⢄⠔⡄</text><text class="terminal-r2" x="170.8" y="483.6" textLength="146.4" clip-path="url(#terminal-line-19)">Mistral&#160;Vibe</text><text class="terminal-r1" x="317.2" y="483.6" textLength="122" clip-path="url(#terminal-line-19)">&#160;v0.0.0&#160;·&#160;</text><text class="terminal-r3" x="439.2" y="483.6" textLength="183" clip-path="url(#terminal-line-19)">devstral-latest</text><text class="terminal-r1" x="622.2" y="483.6" textLength="256.2" clip-path="url(#terminal-line-19)">&#160;·&#160;[Subscription]&#160;Pro</text><text class="terminal-r1" x="1220" y="483.6" textLength="12.2" clip-path="url(#terminal-line-19)">
</text><text class="terminal-r1" x="0" y="508" textLength="134.2" clip-path="url(#terminal-line-20)">&#160;⢸⠸⣀⡔⢉⠱⣃⡢⣂⡣</text><text class="terminal-r1" x="170.8" y="508" textLength="414.8" clip-path="url(#terminal-line-20)">1&#160;model&#160;·&#160;0&#160;MCP&#160;servers&#160;·&#160;0&#160;skills</text><text class="terminal-r1" x="1220" y="508" textLength="12.2" clip-path="url(#terminal-line-20)">
</text><text class="terminal-r1" x="0" y="532.4" textLength="134.2" clip-path="url(#terminal-line-21)">&#160;&#160;⠉⠒⠣⠤⠵⠤⠬⠮⠆</text><text class="terminal-r1" x="170.8" y="532.4" textLength="61" clip-path="url(#terminal-line-21)">Type&#160;</text><text class="terminal-r3" x="231.8" y="532.4" textLength="61" clip-path="url(#terminal-line-21)">/help</text><text class="terminal-r1" x="292.8" y="532.4" textLength="256.2" clip-path="url(#terminal-line-21)">&#160;for&#160;more&#160;information</text><text class="terminal-r1" x="1220" y="532.4" textLength="12.2" clip-path="url(#terminal-line-21)">
</text><text class="terminal-r1" x="1220" y="556.8" textLength="12.2" clip-path="url(#terminal-line-22)">
</text><text class="terminal-r4" x="24.4" y="581.2" textLength="12.2" clip-path="url(#terminal-line-23)"></text><text class="terminal-r1" x="48.8" y="581.2" textLength="280.6" clip-path="url(#terminal-line-23)">Configuration&#160;opened...</text><text class="terminal-r1" x="1220" y="581.2" textLength="12.2" clip-path="url(#terminal-line-23)">
</text><text class="terminal-r1" x="0" y="459.2" textLength="134.2" clip-path="url(#terminal-line-18)">&#160;&#160;⡠⣒⠄&#160;&#160;⡔⢄⠔⡄</text><text class="terminal-r2" x="170.8" y="459.2" textLength="146.4" clip-path="url(#terminal-line-18)">Mistral&#160;Vibe</text><text class="terminal-r1" x="317.2" y="459.2" textLength="122" clip-path="url(#terminal-line-18)">&#160;v0.0.0&#160;·&#160;</text><text class="terminal-r3" x="439.2" y="459.2" textLength="244" clip-path="url(#terminal-line-18)">devstral-latest[off]</text><text class="terminal-r1" x="683.2" y="459.2" textLength="256.2" clip-path="url(#terminal-line-18)">&#160;·&#160;[Subscription]&#160;Pro</text><text class="terminal-r1" x="1220" y="459.2" textLength="12.2" clip-path="url(#terminal-line-18)">
</text><text class="terminal-r1" x="0" y="483.6" textLength="134.2" clip-path="url(#terminal-line-19)">&#160;⢸⠸⣀⡔⢉⠱⣃⡢⣂⡣</text><text class="terminal-r1" x="170.8" y="483.6" textLength="414.8" clip-path="url(#terminal-line-19)">1&#160;model&#160;·&#160;0&#160;MCP&#160;servers&#160;·&#160;0&#160;skills</text><text class="terminal-r1" x="1220" y="483.6" textLength="12.2" clip-path="url(#terminal-line-19)">
</text><text class="terminal-r1" x="0" y="508" textLength="134.2" clip-path="url(#terminal-line-20)">&#160;&#160;⠉⠒⠣⠤⠵⠤⠬⠮⠆</text><text class="terminal-r1" x="170.8" y="508" textLength="61" clip-path="url(#terminal-line-20)">Type&#160;</text><text class="terminal-r3" x="231.8" y="508" textLength="61" clip-path="url(#terminal-line-20)">/help</text><text class="terminal-r1" x="292.8" y="508" textLength="256.2" clip-path="url(#terminal-line-20)">&#160;for&#160;more&#160;information</text><text class="terminal-r1" x="1220" y="508" textLength="12.2" clip-path="url(#terminal-line-20)">
</text><text class="terminal-r1" x="1220" y="532.4" textLength="12.2" clip-path="url(#terminal-line-21)">
</text><text class="terminal-r4" x="24.4" y="556.8" textLength="12.2" clip-path="url(#terminal-line-22)"></text><text class="terminal-r1" x="48.8" y="556.8" textLength="280.6" clip-path="url(#terminal-line-22)">Configuration&#160;opened...</text><text class="terminal-r1" x="1220" y="556.8" textLength="12.2" clip-path="url(#terminal-line-22)">
</text><text class="terminal-r1" x="1220" y="581.2" textLength="12.2" clip-path="url(#terminal-line-23)">
</text><text class="terminal-r1" x="1220" y="605.6" textLength="12.2" clip-path="url(#terminal-line-24)">
</text><text class="terminal-r1" x="1220" y="630" textLength="12.2" clip-path="url(#terminal-line-25)">
</text><text class="terminal-r4" x="0" y="654.4" textLength="1220" clip-path="url(#terminal-line-26)">┌──────────────────────────────────────────────────────────────────────────────────────────────────┐</text><text class="terminal-r1" x="1220" y="654.4" textLength="12.2" clip-path="url(#terminal-line-26)">
</text><text class="terminal-r4" x="0" y="678.8" textLength="12.2" clip-path="url(#terminal-line-27)"></text><text class="terminal-r5" x="24.4" y="678.8" textLength="97.6" clip-path="url(#terminal-line-27)">Settings</text><text class="terminal-r4" x="1207.8" y="678.8" textLength="12.2" clip-path="url(#terminal-line-27)"></text><text class="terminal-r1" x="1220" y="678.8" textLength="12.2" clip-path="url(#terminal-line-27)">
</text><text class="terminal-r4" x="0" y="703.2" textLength="12.2" clip-path="url(#terminal-line-28)"></text><text class="terminal-r4" x="1207.8" y="703.2" textLength="12.2" clip-path="url(#terminal-line-28)"></text><text class="terminal-r1" x="1220" y="703.2" textLength="12.2" clip-path="url(#terminal-line-28)">
</text><text class="terminal-r4" x="0" y="727.6" textLength="12.2" clip-path="url(#terminal-line-29)"></text><text class="terminal-r6" x="36.6" y="727.6" textLength="85.4" clip-path="url(#terminal-line-29)">Model:&#160;</text><text class="terminal-r6" x="122" y="727.6" textLength="183" clip-path="url(#terminal-line-29)">devstral-latest</text><text class="terminal-r4" x="1207.8" y="727.6" textLength="12.2" clip-path="url(#terminal-line-29)"></text><text class="terminal-r1" x="1220" y="727.6" textLength="12.2" clip-path="url(#terminal-line-29)">
</text><text class="terminal-r4" x="0" y="630" textLength="1220" clip-path="url(#terminal-line-25)">┌──────────────────────────────────────────────────────────────────────────────────────────────────┐</text><text class="terminal-r1" x="1220" y="630" textLength="12.2" clip-path="url(#terminal-line-25)">
</text><text class="terminal-r4" x="0" y="654.4" textLength="12.2" clip-path="url(#terminal-line-26)"></text><text class="terminal-r5" x="24.4" y="654.4" textLength="97.6" clip-path="url(#terminal-line-26)">Settings</text><text class="terminal-r4" x="1207.8" y="654.4" textLength="12.2" clip-path="url(#terminal-line-26)"></text><text class="terminal-r1" x="1220" y="654.4" textLength="12.2" clip-path="url(#terminal-line-26)">
</text><text class="terminal-r4" x="0" y="678.8" textLength="12.2" clip-path="url(#terminal-line-27)"></text><text class="terminal-r4" x="1207.8" y="678.8" textLength="12.2" clip-path="url(#terminal-line-27)"></text><text class="terminal-r1" x="1220" y="678.8" textLength="12.2" clip-path="url(#terminal-line-27)">
</text><text class="terminal-r4" x="0" y="703.2" textLength="12.2" clip-path="url(#terminal-line-28)"></text><text class="terminal-r6" x="36.6" y="703.2" textLength="85.4" clip-path="url(#terminal-line-28)">Model:&#160;</text><text class="terminal-r6" x="122" y="703.2" textLength="183" clip-path="url(#terminal-line-28)">devstral-latest</text><text class="terminal-r4" x="1207.8" y="703.2" textLength="12.2" clip-path="url(#terminal-line-28)"></text><text class="terminal-r1" x="1220" y="703.2" textLength="12.2" clip-path="url(#terminal-line-28)">
</text><text class="terminal-r4" x="0" y="727.6" textLength="12.2" clip-path="url(#terminal-line-29)"></text><text class="terminal-r1" x="36.6" y="727.6" textLength="122" clip-path="url(#terminal-line-29)">Thinking:&#160;</text><text class="terminal-r6" x="158.6" y="727.6" textLength="36.6" clip-path="url(#terminal-line-29)">Off</text><text class="terminal-r4" x="1207.8" y="727.6" textLength="12.2" clip-path="url(#terminal-line-29)"></text><text class="terminal-r1" x="1220" y="727.6" textLength="12.2" clip-path="url(#terminal-line-29)">
</text><text class="terminal-r4" x="0" y="752" textLength="12.2" clip-path="url(#terminal-line-30)"></text><text class="terminal-r1" x="36.6" y="752" textLength="134.2" clip-path="url(#terminal-line-30)">Auto-copy:&#160;</text><text class="terminal-r7" x="170.8" y="752" textLength="24.4" clip-path="url(#terminal-line-30)">On</text><text class="terminal-r4" x="1207.8" y="752" textLength="12.2" clip-path="url(#terminal-line-30)"></text><text class="terminal-r1" x="1220" y="752" textLength="12.2" clip-path="url(#terminal-line-30)">
</text><text class="terminal-r4" x="0" y="776.4" textLength="12.2" clip-path="url(#terminal-line-31)"></text><text class="terminal-r1" x="36.6" y="776.4" textLength="671" clip-path="url(#terminal-line-31)">Autocomplete&#160;watcher&#160;(may&#160;delay&#160;first&#160;autocompletion):&#160;</text><text class="terminal-r8" x="707.6" y="776.4" textLength="36.6" clip-path="url(#terminal-line-31)">Off</text><text class="terminal-r4" x="1207.8" y="776.4" textLength="12.2" clip-path="url(#terminal-line-31)"></text><text class="terminal-r1" x="1220" y="776.4" textLength="12.2" clip-path="url(#terminal-line-31)">
</text><text class="terminal-r4" x="0" y="800.8" textLength="12.2" clip-path="url(#terminal-line-32)"></text><text class="terminal-r4" x="1207.8" y="800.8" textLength="12.2" clip-path="url(#terminal-line-32)"></text><text class="terminal-r1" x="1220" y="800.8" textLength="12.2" clip-path="url(#terminal-line-32)">

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 16 KiB

Before After
Before After

View file

@ -161,7 +161,7 @@
</g>
<g transform="translate(9, 41)" clip-path="url(#terminal-clip-terminal)">
<rect fill="#608ab1" x="36.6" y="733.5" width="134.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#608ab1" x="170.8" y="733.5" width="24.4" height="24.65" shape-rendering="crispEdges"/><rect fill="#608ab1" x="195.2" y="733.5" width="988.2" height="24.65" shape-rendering="crispEdges"/>
<rect fill="#608ab1" x="36.6" y="709.1" width="122" height="24.65" shape-rendering="crispEdges"/><rect fill="#608ab1" x="158.6" y="709.1" width="36.6" height="24.65" shape-rendering="crispEdges"/><rect fill="#608ab1" x="195.2" y="709.1" width="988.2" height="24.65" shape-rendering="crispEdges"/>
<g class="terminal-matrix">
<text class="terminal-r1" x="1220" y="20" textLength="12.2" clip-path="url(#terminal-line-0)">
</text><text class="terminal-r1" x="1220" y="44.4" textLength="12.2" clip-path="url(#terminal-line-1)">
@ -181,19 +181,19 @@
</text><text class="terminal-r1" x="1220" y="386" textLength="12.2" clip-path="url(#terminal-line-15)">
</text><text class="terminal-r1" x="1220" y="410.4" textLength="12.2" clip-path="url(#terminal-line-16)">
</text><text class="terminal-r1" x="1220" y="434.8" textLength="12.2" clip-path="url(#terminal-line-17)">
</text><text class="terminal-r1" x="1220" y="459.2" textLength="12.2" clip-path="url(#terminal-line-18)">
</text><text class="terminal-r1" x="0" y="483.6" textLength="134.2" clip-path="url(#terminal-line-19)">&#160;&#160;⡠⣒⠄&#160;&#160;⡔⢄⠔⡄</text><text class="terminal-r2" x="170.8" y="483.6" textLength="146.4" clip-path="url(#terminal-line-19)">Mistral&#160;Vibe</text><text class="terminal-r1" x="317.2" y="483.6" textLength="122" clip-path="url(#terminal-line-19)">&#160;v0.0.0&#160;·&#160;</text><text class="terminal-r3" x="439.2" y="483.6" textLength="183" clip-path="url(#terminal-line-19)">devstral-latest</text><text class="terminal-r1" x="622.2" y="483.6" textLength="256.2" clip-path="url(#terminal-line-19)">&#160;·&#160;[Subscription]&#160;Pro</text><text class="terminal-r1" x="1220" y="483.6" textLength="12.2" clip-path="url(#terminal-line-19)">
</text><text class="terminal-r1" x="0" y="508" textLength="134.2" clip-path="url(#terminal-line-20)">&#160;⢸⠸⣀⡔⢉⠱⣃⡢⣂⡣</text><text class="terminal-r1" x="170.8" y="508" textLength="414.8" clip-path="url(#terminal-line-20)">1&#160;model&#160;·&#160;0&#160;MCP&#160;servers&#160;·&#160;0&#160;skills</text><text class="terminal-r1" x="1220" y="508" textLength="12.2" clip-path="url(#terminal-line-20)">
</text><text class="terminal-r1" x="0" y="532.4" textLength="134.2" clip-path="url(#terminal-line-21)">&#160;&#160;⠉⠒⠣⠤⠵⠤⠬⠮⠆</text><text class="terminal-r1" x="170.8" y="532.4" textLength="61" clip-path="url(#terminal-line-21)">Type&#160;</text><text class="terminal-r3" x="231.8" y="532.4" textLength="61" clip-path="url(#terminal-line-21)">/help</text><text class="terminal-r1" x="292.8" y="532.4" textLength="256.2" clip-path="url(#terminal-line-21)">&#160;for&#160;more&#160;information</text><text class="terminal-r1" x="1220" y="532.4" textLength="12.2" clip-path="url(#terminal-line-21)">
</text><text class="terminal-r1" x="1220" y="556.8" textLength="12.2" clip-path="url(#terminal-line-22)">
</text><text class="terminal-r4" x="24.4" y="581.2" textLength="12.2" clip-path="url(#terminal-line-23)"></text><text class="terminal-r1" x="48.8" y="581.2" textLength="280.6" clip-path="url(#terminal-line-23)">Configuration&#160;opened...</text><text class="terminal-r1" x="1220" y="581.2" textLength="12.2" clip-path="url(#terminal-line-23)">
</text><text class="terminal-r1" x="0" y="459.2" textLength="134.2" clip-path="url(#terminal-line-18)">&#160;&#160;⡠⣒⠄&#160;&#160;⡔⢄⠔⡄</text><text class="terminal-r2" x="170.8" y="459.2" textLength="146.4" clip-path="url(#terminal-line-18)">Mistral&#160;Vibe</text><text class="terminal-r1" x="317.2" y="459.2" textLength="122" clip-path="url(#terminal-line-18)">&#160;v0.0.0&#160;·&#160;</text><text class="terminal-r3" x="439.2" y="459.2" textLength="244" clip-path="url(#terminal-line-18)">devstral-latest[off]</text><text class="terminal-r1" x="683.2" y="459.2" textLength="256.2" clip-path="url(#terminal-line-18)">&#160;·&#160;[Subscription]&#160;Pro</text><text class="terminal-r1" x="1220" y="459.2" textLength="12.2" clip-path="url(#terminal-line-18)">
</text><text class="terminal-r1" x="0" y="483.6" textLength="134.2" clip-path="url(#terminal-line-19)">&#160;⢸⠸⣀⡔⢉⠱⣃⡢⣂⡣</text><text class="terminal-r1" x="170.8" y="483.6" textLength="414.8" clip-path="url(#terminal-line-19)">1&#160;model&#160;·&#160;0&#160;MCP&#160;servers&#160;·&#160;0&#160;skills</text><text class="terminal-r1" x="1220" y="483.6" textLength="12.2" clip-path="url(#terminal-line-19)">
</text><text class="terminal-r1" x="0" y="508" textLength="134.2" clip-path="url(#terminal-line-20)">&#160;&#160;⠉⠒⠣⠤⠵⠤⠬⠮⠆</text><text class="terminal-r1" x="170.8" y="508" textLength="61" clip-path="url(#terminal-line-20)">Type&#160;</text><text class="terminal-r3" x="231.8" y="508" textLength="61" clip-path="url(#terminal-line-20)">/help</text><text class="terminal-r1" x="292.8" y="508" textLength="256.2" clip-path="url(#terminal-line-20)">&#160;for&#160;more&#160;information</text><text class="terminal-r1" x="1220" y="508" textLength="12.2" clip-path="url(#terminal-line-20)">
</text><text class="terminal-r1" x="1220" y="532.4" textLength="12.2" clip-path="url(#terminal-line-21)">
</text><text class="terminal-r4" x="24.4" y="556.8" textLength="12.2" clip-path="url(#terminal-line-22)"></text><text class="terminal-r1" x="48.8" y="556.8" textLength="280.6" clip-path="url(#terminal-line-22)">Configuration&#160;opened...</text><text class="terminal-r1" x="1220" y="556.8" textLength="12.2" clip-path="url(#terminal-line-22)">
</text><text class="terminal-r1" x="1220" y="581.2" textLength="12.2" clip-path="url(#terminal-line-23)">
</text><text class="terminal-r1" x="1220" y="605.6" textLength="12.2" clip-path="url(#terminal-line-24)">
</text><text class="terminal-r1" x="1220" y="630" textLength="12.2" clip-path="url(#terminal-line-25)">
</text><text class="terminal-r4" x="0" y="654.4" textLength="1220" clip-path="url(#terminal-line-26)">┌──────────────────────────────────────────────────────────────────────────────────────────────────┐</text><text class="terminal-r1" x="1220" y="654.4" textLength="12.2" clip-path="url(#terminal-line-26)">
</text><text class="terminal-r4" x="0" y="678.8" textLength="12.2" clip-path="url(#terminal-line-27)"></text><text class="terminal-r5" x="24.4" y="678.8" textLength="97.6" clip-path="url(#terminal-line-27)">Settings</text><text class="terminal-r4" x="1207.8" y="678.8" textLength="12.2" clip-path="url(#terminal-line-27)"></text><text class="terminal-r1" x="1220" y="678.8" textLength="12.2" clip-path="url(#terminal-line-27)">
</text><text class="terminal-r4" x="0" y="703.2" textLength="12.2" clip-path="url(#terminal-line-28)"></text><text class="terminal-r4" x="1207.8" y="703.2" textLength="12.2" clip-path="url(#terminal-line-28)"></text><text class="terminal-r1" x="1220" y="703.2" textLength="12.2" clip-path="url(#terminal-line-28)">
</text><text class="terminal-r4" x="0" y="727.6" textLength="12.2" clip-path="url(#terminal-line-29)"></text><text class="terminal-r1" x="36.6" y="727.6" textLength="85.4" clip-path="url(#terminal-line-29)">Model:&#160;</text><text class="terminal-r6" x="122" y="727.6" textLength="183" clip-path="url(#terminal-line-29)">devstral-latest</text><text class="terminal-r4" x="1207.8" y="727.6" textLength="12.2" clip-path="url(#terminal-line-29)"></text><text class="terminal-r1" x="1220" y="727.6" textLength="12.2" clip-path="url(#terminal-line-29)">
</text><text class="terminal-r4" x="0" y="752" textLength="12.2" clip-path="url(#terminal-line-30)"></text><text class="terminal-r6" x="36.6" y="752" textLength="134.2" clip-path="url(#terminal-line-30)">Auto-copy:&#160;</text><text class="terminal-r7" x="170.8" y="752" textLength="24.4" clip-path="url(#terminal-line-30)">On</text><text class="terminal-r4" x="1207.8" y="752" textLength="12.2" clip-path="url(#terminal-line-30)"></text><text class="terminal-r1" x="1220" y="752" textLength="12.2" clip-path="url(#terminal-line-30)">
</text><text class="terminal-r4" x="0" y="630" textLength="1220" clip-path="url(#terminal-line-25)">┌──────────────────────────────────────────────────────────────────────────────────────────────────┐</text><text class="terminal-r1" x="1220" y="630" textLength="12.2" clip-path="url(#terminal-line-25)">
</text><text class="terminal-r4" x="0" y="654.4" textLength="12.2" clip-path="url(#terminal-line-26)"></text><text class="terminal-r5" x="24.4" y="654.4" textLength="97.6" clip-path="url(#terminal-line-26)">Settings</text><text class="terminal-r4" x="1207.8" y="654.4" textLength="12.2" clip-path="url(#terminal-line-26)"></text><text class="terminal-r1" x="1220" y="654.4" textLength="12.2" clip-path="url(#terminal-line-26)">
</text><text class="terminal-r4" x="0" y="678.8" textLength="12.2" clip-path="url(#terminal-line-27)"></text><text class="terminal-r4" x="1207.8" y="678.8" textLength="12.2" clip-path="url(#terminal-line-27)"></text><text class="terminal-r1" x="1220" y="678.8" textLength="12.2" clip-path="url(#terminal-line-27)">
</text><text class="terminal-r4" x="0" y="703.2" textLength="12.2" clip-path="url(#terminal-line-28)"></text><text class="terminal-r1" x="36.6" y="703.2" textLength="85.4" clip-path="url(#terminal-line-28)">Model:&#160;</text><text class="terminal-r6" x="122" y="703.2" textLength="183" clip-path="url(#terminal-line-28)">devstral-latest</text><text class="terminal-r4" x="1207.8" y="703.2" textLength="12.2" clip-path="url(#terminal-line-28)"></text><text class="terminal-r1" x="1220" y="703.2" textLength="12.2" clip-path="url(#terminal-line-28)">
</text><text class="terminal-r4" x="0" y="727.6" textLength="12.2" clip-path="url(#terminal-line-29)"></text><text class="terminal-r6" x="36.6" y="727.6" textLength="122" clip-path="url(#terminal-line-29)">Thinking:&#160;</text><text class="terminal-r6" x="158.6" y="727.6" textLength="36.6" clip-path="url(#terminal-line-29)">Off</text><text class="terminal-r4" x="1207.8" y="727.6" textLength="12.2" clip-path="url(#terminal-line-29)"></text><text class="terminal-r1" x="1220" y="727.6" textLength="12.2" clip-path="url(#terminal-line-29)">
</text><text class="terminal-r4" x="0" y="752" textLength="12.2" clip-path="url(#terminal-line-30)"></text><text class="terminal-r1" x="36.6" y="752" textLength="134.2" clip-path="url(#terminal-line-30)">Auto-copy:&#160;</text><text class="terminal-r7" x="170.8" y="752" textLength="24.4" clip-path="url(#terminal-line-30)">On</text><text class="terminal-r4" x="1207.8" y="752" textLength="12.2" clip-path="url(#terminal-line-30)"></text><text class="terminal-r1" x="1220" y="752" textLength="12.2" clip-path="url(#terminal-line-30)">
</text><text class="terminal-r4" x="0" y="776.4" textLength="12.2" clip-path="url(#terminal-line-31)"></text><text class="terminal-r1" x="36.6" y="776.4" textLength="671" clip-path="url(#terminal-line-31)">Autocomplete&#160;watcher&#160;(may&#160;delay&#160;first&#160;autocompletion):&#160;</text><text class="terminal-r8" x="707.6" y="776.4" textLength="36.6" clip-path="url(#terminal-line-31)">Off</text><text class="terminal-r4" x="1207.8" y="776.4" textLength="12.2" clip-path="url(#terminal-line-31)"></text><text class="terminal-r1" x="1220" y="776.4" textLength="12.2" clip-path="url(#terminal-line-31)">
</text><text class="terminal-r4" x="0" y="800.8" textLength="12.2" clip-path="url(#terminal-line-32)"></text><text class="terminal-r4" x="1207.8" y="800.8" textLength="12.2" clip-path="url(#terminal-line-32)"></text><text class="terminal-r1" x="1220" y="800.8" textLength="12.2" clip-path="url(#terminal-line-32)">
</text><text class="terminal-r4" x="0" y="825.2" textLength="12.2" clip-path="url(#terminal-line-33)"></text><text class="terminal-r4" x="24.4" y="825.2" textLength="512.4" clip-path="url(#terminal-line-33)">↑↓&#160;Navigate&#160;&#160;Enter&#160;Select/Toggle&#160;&#160;Esc&#160;Exit</text><text class="terminal-r4" x="1207.8" y="825.2" textLength="12.2" clip-path="url(#terminal-line-33)"></text><text class="terminal-r1" x="1220" y="825.2" textLength="12.2" clip-path="url(#terminal-line-33)">

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 16 KiB

Before After
Before After

View file

@ -181,18 +181,18 @@
</text><text class="terminal-r1" x="1220" y="386" textLength="12.2" clip-path="url(#terminal-line-15)">
</text><text class="terminal-r1" x="1220" y="410.4" textLength="12.2" clip-path="url(#terminal-line-16)">
</text><text class="terminal-r1" x="1220" y="434.8" textLength="12.2" clip-path="url(#terminal-line-17)">
</text><text class="terminal-r1" x="1220" y="459.2" textLength="12.2" clip-path="url(#terminal-line-18)">
</text><text class="terminal-r1" x="0" y="483.6" textLength="134.2" clip-path="url(#terminal-line-19)">&#160;&#160;⡠⣒⠄&#160;&#160;⡔⢄⠔⡄</text><text class="terminal-r2" x="170.8" y="483.6" textLength="146.4" clip-path="url(#terminal-line-19)">Mistral&#160;Vibe</text><text class="terminal-r1" x="317.2" y="483.6" textLength="122" clip-path="url(#terminal-line-19)">&#160;v0.0.0&#160;·&#160;</text><text class="terminal-r3" x="439.2" y="483.6" textLength="183" clip-path="url(#terminal-line-19)">devstral-latest</text><text class="terminal-r1" x="622.2" y="483.6" textLength="256.2" clip-path="url(#terminal-line-19)">&#160;·&#160;[Subscription]&#160;Pro</text><text class="terminal-r1" x="1220" y="483.6" textLength="12.2" clip-path="url(#terminal-line-19)">
</text><text class="terminal-r1" x="0" y="508" textLength="134.2" clip-path="url(#terminal-line-20)">&#160;⢸⠸⣀⡔⢉⠱⣃⡢⣂⡣</text><text class="terminal-r1" x="170.8" y="508" textLength="414.8" clip-path="url(#terminal-line-20)">1&#160;model&#160;·&#160;0&#160;MCP&#160;servers&#160;·&#160;0&#160;skills</text><text class="terminal-r1" x="1220" y="508" textLength="12.2" clip-path="url(#terminal-line-20)">
</text><text class="terminal-r1" x="0" y="532.4" textLength="134.2" clip-path="url(#terminal-line-21)">&#160;&#160;⠉⠒⠣⠤⠵⠤⠬⠮⠆</text><text class="terminal-r1" x="170.8" y="532.4" textLength="61" clip-path="url(#terminal-line-21)">Type&#160;</text><text class="terminal-r3" x="231.8" y="532.4" textLength="61" clip-path="url(#terminal-line-21)">/help</text><text class="terminal-r1" x="292.8" y="532.4" textLength="256.2" clip-path="url(#terminal-line-21)">&#160;for&#160;more&#160;information</text><text class="terminal-r1" x="1220" y="532.4" textLength="12.2" clip-path="url(#terminal-line-21)">
</text><text class="terminal-r1" x="1220" y="556.8" textLength="12.2" clip-path="url(#terminal-line-22)">
</text><text class="terminal-r4" x="24.4" y="581.2" textLength="12.2" clip-path="url(#terminal-line-23)"></text><text class="terminal-r1" x="48.8" y="581.2" textLength="280.6" clip-path="url(#terminal-line-23)">Configuration&#160;opened...</text><text class="terminal-r1" x="1220" y="581.2" textLength="12.2" clip-path="url(#terminal-line-23)">
</text><text class="terminal-r1" x="0" y="459.2" textLength="134.2" clip-path="url(#terminal-line-18)">&#160;&#160;⡠⣒⠄&#160;&#160;⡔⢄⠔⡄</text><text class="terminal-r2" x="170.8" y="459.2" textLength="146.4" clip-path="url(#terminal-line-18)">Mistral&#160;Vibe</text><text class="terminal-r1" x="317.2" y="459.2" textLength="122" clip-path="url(#terminal-line-18)">&#160;v0.0.0&#160;·&#160;</text><text class="terminal-r3" x="439.2" y="459.2" textLength="244" clip-path="url(#terminal-line-18)">devstral-latest[off]</text><text class="terminal-r1" x="683.2" y="459.2" textLength="256.2" clip-path="url(#terminal-line-18)">&#160;·&#160;[Subscription]&#160;Pro</text><text class="terminal-r1" x="1220" y="459.2" textLength="12.2" clip-path="url(#terminal-line-18)">
</text><text class="terminal-r1" x="0" y="483.6" textLength="134.2" clip-path="url(#terminal-line-19)">&#160;⢸⠸⣀⡔⢉⠱⣃⡢⣂⡣</text><text class="terminal-r1" x="170.8" y="483.6" textLength="414.8" clip-path="url(#terminal-line-19)">1&#160;model&#160;·&#160;0&#160;MCP&#160;servers&#160;·&#160;0&#160;skills</text><text class="terminal-r1" x="1220" y="483.6" textLength="12.2" clip-path="url(#terminal-line-19)">
</text><text class="terminal-r1" x="0" y="508" textLength="134.2" clip-path="url(#terminal-line-20)">&#160;&#160;⠉⠒⠣⠤⠵⠤⠬⠮⠆</text><text class="terminal-r1" x="170.8" y="508" textLength="61" clip-path="url(#terminal-line-20)">Type&#160;</text><text class="terminal-r3" x="231.8" y="508" textLength="61" clip-path="url(#terminal-line-20)">/help</text><text class="terminal-r1" x="292.8" y="508" textLength="256.2" clip-path="url(#terminal-line-20)">&#160;for&#160;more&#160;information</text><text class="terminal-r1" x="1220" y="508" textLength="12.2" clip-path="url(#terminal-line-20)">
</text><text class="terminal-r1" x="1220" y="532.4" textLength="12.2" clip-path="url(#terminal-line-21)">
</text><text class="terminal-r4" x="24.4" y="556.8" textLength="12.2" clip-path="url(#terminal-line-22)"></text><text class="terminal-r1" x="48.8" y="556.8" textLength="280.6" clip-path="url(#terminal-line-22)">Configuration&#160;opened...</text><text class="terminal-r1" x="1220" y="556.8" textLength="12.2" clip-path="url(#terminal-line-22)">
</text><text class="terminal-r1" x="1220" y="581.2" textLength="12.2" clip-path="url(#terminal-line-23)">
</text><text class="terminal-r1" x="1220" y="605.6" textLength="12.2" clip-path="url(#terminal-line-24)">
</text><text class="terminal-r1" x="1220" y="630" textLength="12.2" clip-path="url(#terminal-line-25)">
</text><text class="terminal-r4" x="0" y="654.4" textLength="1220" clip-path="url(#terminal-line-26)">┌──────────────────────────────────────────────────────────────────────────────────────────────────┐</text><text class="terminal-r1" x="1220" y="654.4" textLength="12.2" clip-path="url(#terminal-line-26)">
</text><text class="terminal-r4" x="0" y="678.8" textLength="12.2" clip-path="url(#terminal-line-27)"></text><text class="terminal-r5" x="24.4" y="678.8" textLength="97.6" clip-path="url(#terminal-line-27)">Settings</text><text class="terminal-r4" x="1207.8" y="678.8" textLength="12.2" clip-path="url(#terminal-line-27)"></text><text class="terminal-r1" x="1220" y="678.8" textLength="12.2" clip-path="url(#terminal-line-27)">
</text><text class="terminal-r4" x="0" y="703.2" textLength="12.2" clip-path="url(#terminal-line-28)"></text><text class="terminal-r4" x="1207.8" y="703.2" textLength="12.2" clip-path="url(#terminal-line-28)"></text><text class="terminal-r1" x="1220" y="703.2" textLength="12.2" clip-path="url(#terminal-line-28)">
</text><text class="terminal-r4" x="0" y="727.6" textLength="12.2" clip-path="url(#terminal-line-29)"></text><text class="terminal-r1" x="36.6" y="727.6" textLength="85.4" clip-path="url(#terminal-line-29)">Model:&#160;</text><text class="terminal-r6" x="122" y="727.6" textLength="183" clip-path="url(#terminal-line-29)">devstral-latest</text><text class="terminal-r4" x="1207.8" y="727.6" textLength="12.2" clip-path="url(#terminal-line-29)"></text><text class="terminal-r1" x="1220" y="727.6" textLength="12.2" clip-path="url(#terminal-line-29)">
</text><text class="terminal-r4" x="0" y="630" textLength="1220" clip-path="url(#terminal-line-25)">┌──────────────────────────────────────────────────────────────────────────────────────────────────┐</text><text class="terminal-r1" x="1220" y="630" textLength="12.2" clip-path="url(#terminal-line-25)">
</text><text class="terminal-r4" x="0" y="654.4" textLength="12.2" clip-path="url(#terminal-line-26)"></text><text class="terminal-r5" x="24.4" y="654.4" textLength="97.6" clip-path="url(#terminal-line-26)">Settings</text><text class="terminal-r4" x="1207.8" y="654.4" textLength="12.2" clip-path="url(#terminal-line-26)"></text><text class="terminal-r1" x="1220" y="654.4" textLength="12.2" clip-path="url(#terminal-line-26)">
</text><text class="terminal-r4" x="0" y="678.8" textLength="12.2" clip-path="url(#terminal-line-27)"></text><text class="terminal-r4" x="1207.8" y="678.8" textLength="12.2" clip-path="url(#terminal-line-27)"></text><text class="terminal-r1" x="1220" y="678.8" textLength="12.2" clip-path="url(#terminal-line-27)">
</text><text class="terminal-r4" x="0" y="703.2" textLength="12.2" clip-path="url(#terminal-line-28)"></text><text class="terminal-r1" x="36.6" y="703.2" textLength="85.4" clip-path="url(#terminal-line-28)">Model:&#160;</text><text class="terminal-r6" x="122" y="703.2" textLength="183" clip-path="url(#terminal-line-28)">devstral-latest</text><text class="terminal-r4" x="1207.8" y="703.2" textLength="12.2" clip-path="url(#terminal-line-28)"></text><text class="terminal-r1" x="1220" y="703.2" textLength="12.2" clip-path="url(#terminal-line-28)">
</text><text class="terminal-r4" x="0" y="727.6" textLength="12.2" clip-path="url(#terminal-line-29)"></text><text class="terminal-r1" x="36.6" y="727.6" textLength="122" clip-path="url(#terminal-line-29)">Thinking:&#160;</text><text class="terminal-r6" x="158.6" y="727.6" textLength="36.6" clip-path="url(#terminal-line-29)">Off</text><text class="terminal-r4" x="1207.8" y="727.6" textLength="12.2" clip-path="url(#terminal-line-29)"></text><text class="terminal-r1" x="1220" y="727.6" textLength="12.2" clip-path="url(#terminal-line-29)">
</text><text class="terminal-r4" x="0" y="752" textLength="12.2" clip-path="url(#terminal-line-30)"></text><text class="terminal-r6" x="36.6" y="752" textLength="134.2" clip-path="url(#terminal-line-30)">Auto-copy:&#160;</text><text class="terminal-r7" x="170.8" y="752" textLength="36.6" clip-path="url(#terminal-line-30)">Off</text><text class="terminal-r4" x="1207.8" y="752" textLength="12.2" clip-path="url(#terminal-line-30)"></text><text class="terminal-r1" x="1220" y="752" textLength="12.2" clip-path="url(#terminal-line-30)">
</text><text class="terminal-r4" x="0" y="776.4" textLength="12.2" clip-path="url(#terminal-line-31)"></text><text class="terminal-r1" x="36.6" y="776.4" textLength="671" clip-path="url(#terminal-line-31)">Autocomplete&#160;watcher&#160;(may&#160;delay&#160;first&#160;autocompletion):&#160;</text><text class="terminal-r8" x="707.6" y="776.4" textLength="36.6" clip-path="url(#terminal-line-31)">Off</text><text class="terminal-r4" x="1207.8" y="776.4" textLength="12.2" clip-path="url(#terminal-line-31)"></text><text class="terminal-r1" x="1220" y="776.4" textLength="12.2" clip-path="url(#terminal-line-31)">
</text><text class="terminal-r4" x="0" y="800.8" textLength="12.2" clip-path="url(#terminal-line-32)"></text><text class="terminal-r4" x="1207.8" y="800.8" textLength="12.2" clip-path="url(#terminal-line-32)"></text><text class="terminal-r1" x="1220" y="800.8" textLength="12.2" clip-path="url(#terminal-line-32)">

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 16 KiB

Before After
Before After

View file

@ -179,7 +179,7 @@
</text><text class="terminal-r1" x="1220" y="386" textLength="12.2" clip-path="url(#terminal-line-15)">
</text><text class="terminal-r1" x="1220" y="410.4" textLength="12.2" clip-path="url(#terminal-line-16)">
</text><text class="terminal-r1" x="1220" y="434.8" textLength="12.2" clip-path="url(#terminal-line-17)">
</text><text class="terminal-r1" x="0" y="459.2" textLength="134.2" clip-path="url(#terminal-line-18)">&#160;&#160;⡠⣒⠄&#160;&#160;⡔⢄⠔⡄</text><text class="terminal-r2" x="170.8" y="459.2" textLength="146.4" clip-path="url(#terminal-line-18)">Mistral&#160;Vibe</text><text class="terminal-r1" x="317.2" y="459.2" textLength="122" clip-path="url(#terminal-line-18)">&#160;v0.0.0&#160;·&#160;</text><text class="terminal-r3" x="439.2" y="459.2" textLength="183" clip-path="url(#terminal-line-18)">devstral-latest</text><text class="terminal-r1" x="622.2" y="459.2" textLength="256.2" clip-path="url(#terminal-line-18)">&#160;·&#160;[Subscription]&#160;Pro</text><text class="terminal-r1" x="1220" y="459.2" textLength="12.2" clip-path="url(#terminal-line-18)">
</text><text class="terminal-r1" x="0" y="459.2" textLength="134.2" clip-path="url(#terminal-line-18)">&#160;&#160;⡠⣒⠄&#160;&#160;⡔⢄⠔⡄</text><text class="terminal-r2" x="170.8" y="459.2" textLength="146.4" clip-path="url(#terminal-line-18)">Mistral&#160;Vibe</text><text class="terminal-r1" x="317.2" y="459.2" textLength="122" clip-path="url(#terminal-line-18)">&#160;v0.0.0&#160;·&#160;</text><text class="terminal-r3" x="439.2" y="459.2" textLength="244" clip-path="url(#terminal-line-18)">devstral-latest[off]</text><text class="terminal-r1" x="683.2" y="459.2" textLength="256.2" clip-path="url(#terminal-line-18)">&#160;·&#160;[Subscription]&#160;Pro</text><text class="terminal-r1" x="1220" y="459.2" textLength="12.2" clip-path="url(#terminal-line-18)">
</text><text class="terminal-r1" x="0" y="483.6" textLength="134.2" clip-path="url(#terminal-line-19)">&#160;⢸⠸⣀⡔⢉⠱⣃⡢⣂⡣</text><text class="terminal-r1" x="170.8" y="483.6" textLength="414.8" clip-path="url(#terminal-line-19)">1&#160;model&#160;·&#160;0&#160;MCP&#160;servers&#160;·&#160;0&#160;skills</text><text class="terminal-r1" x="1220" y="483.6" textLength="12.2" clip-path="url(#terminal-line-19)">
</text><text class="terminal-r1" x="0" y="508" textLength="134.2" clip-path="url(#terminal-line-20)">&#160;&#160;⠉⠒⠣⠤⠵⠤⠬⠮⠆</text><text class="terminal-r1" x="170.8" y="508" textLength="61" clip-path="url(#terminal-line-20)">Type&#160;</text><text class="terminal-r3" x="231.8" y="508" textLength="61" clip-path="url(#terminal-line-20)">/help</text><text class="terminal-r1" x="292.8" y="508" textLength="256.2" clip-path="url(#terminal-line-20)">&#160;for&#160;more&#160;information</text><text class="terminal-r1" x="1220" y="508" textLength="12.2" clip-path="url(#terminal-line-20)">
</text><text class="terminal-r1" x="1220" y="532.4" textLength="12.2" clip-path="url(#terminal-line-21)">

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 15 KiB

Before After
Before After

View file

@ -183,7 +183,7 @@
</text><text class="terminal-r1" x="1464" y="532.4" textLength="12.2" clip-path="url(#terminal-line-21)">
</text><text class="terminal-r1" x="1464" y="556.8" textLength="12.2" clip-path="url(#terminal-line-22)">
</text><text class="terminal-r1" x="1464" y="581.2" textLength="12.2" clip-path="url(#terminal-line-23)">
</text><text class="terminal-r1" x="0" y="605.6" textLength="134.2" clip-path="url(#terminal-line-24)">&#160;&#160;⡠⣒⠄&#160;&#160;⡔⢄⠔⡄</text><text class="terminal-r2" x="170.8" y="605.6" textLength="146.4" clip-path="url(#terminal-line-24)">Mistral&#160;Vibe</text><text class="terminal-r1" x="317.2" y="605.6" textLength="122" clip-path="url(#terminal-line-24)">&#160;v0.0.0&#160;·&#160;</text><text class="terminal-r3" x="439.2" y="605.6" textLength="183" clip-path="url(#terminal-line-24)">devstral-latest</text><text class="terminal-r1" x="622.2" y="605.6" textLength="256.2" clip-path="url(#terminal-line-24)">&#160;·&#160;[Subscription]&#160;Pro</text><text class="terminal-r1" x="1464" y="605.6" textLength="12.2" clip-path="url(#terminal-line-24)">
</text><text class="terminal-r1" x="0" y="605.6" textLength="134.2" clip-path="url(#terminal-line-24)">&#160;&#160;⡠⣒⠄&#160;&#160;⡔⢄⠔⡄</text><text class="terminal-r2" x="170.8" y="605.6" textLength="146.4" clip-path="url(#terminal-line-24)">Mistral&#160;Vibe</text><text class="terminal-r1" x="317.2" y="605.6" textLength="122" clip-path="url(#terminal-line-24)">&#160;v0.0.0&#160;·&#160;</text><text class="terminal-r3" x="439.2" y="605.6" textLength="244" clip-path="url(#terminal-line-24)">devstral-latest[off]</text><text class="terminal-r1" x="683.2" y="605.6" textLength="256.2" clip-path="url(#terminal-line-24)">&#160;·&#160;[Subscription]&#160;Pro</text><text class="terminal-r1" x="1464" y="605.6" textLength="12.2" clip-path="url(#terminal-line-24)">
</text><text class="terminal-r1" x="0" y="630" textLength="134.2" clip-path="url(#terminal-line-25)">&#160;⢸⠸⣀⡔⢉⠱⣃⡢⣂⡣</text><text class="terminal-r1" x="170.8" y="630" textLength="414.8" clip-path="url(#terminal-line-25)">1&#160;model&#160;·&#160;0&#160;MCP&#160;servers&#160;·&#160;0&#160;skills</text><text class="terminal-r1" x="1464" y="630" textLength="12.2" clip-path="url(#terminal-line-25)">
</text><text class="terminal-r1" x="0" y="654.4" textLength="134.2" clip-path="url(#terminal-line-26)">&#160;&#160;⠉⠒⠣⠤⠵⠤⠬⠮⠆</text><text class="terminal-r1" x="170.8" y="654.4" textLength="61" clip-path="url(#terminal-line-26)">Type&#160;</text><text class="terminal-r3" x="231.8" y="654.4" textLength="61" clip-path="url(#terminal-line-26)">/help</text><text class="terminal-r1" x="292.8" y="654.4" textLength="256.2" clip-path="url(#terminal-line-26)">&#160;for&#160;more&#160;information</text><text class="terminal-r1" x="1464" y="654.4" textLength="12.2" clip-path="url(#terminal-line-26)">
</text><text class="terminal-r1" x="1464" y="678.8" textLength="12.2" clip-path="url(#terminal-line-27)">

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 13 KiB

Before After
Before After

View file

@ -187,7 +187,7 @@
</text><text class="terminal-r2" x="878.4" y="532.4" textLength="12.2" clip-path="url(#terminal-line-21)"></text><text class="terminal-r1" x="902.8" y="532.4" textLength="73.2" clip-path="url(#terminal-line-21)">passed</text><text class="terminal-r1" x="1464" y="532.4" textLength="12.2" clip-path="url(#terminal-line-21)">
</text><text class="terminal-r2" x="878.4" y="556.8" textLength="12.2" clip-path="url(#terminal-line-22)"></text><text class="terminal-r3" x="902.8" y="556.8" textLength="231.8" clip-path="url(#terminal-line-22)">2026-02-21&#160;10:28:53</text><text class="terminal-r7" x="1146.8" y="556.8" textLength="97.6" clip-path="url(#terminal-line-22)">CRITICAL</text><text class="terminal-r1" x="1244.4" y="556.8" textLength="207.4" clip-path="url(#terminal-line-22)">&#160;Out&#160;of&#160;memory&#160;&#160;&#160;</text><text class="terminal-r1" x="1464" y="556.8" textLength="12.2" clip-path="url(#terminal-line-22)">
</text><text class="terminal-r2" x="878.4" y="581.2" textLength="12.2" clip-path="url(#terminal-line-23)"></text><text class="terminal-r1" x="902.8" y="581.2" textLength="170.8" clip-path="url(#terminal-line-23)">error&#160;detected</text><text class="terminal-r1" x="1464" y="581.2" textLength="12.2" clip-path="url(#terminal-line-23)">
</text><text class="terminal-r1" x="0" y="605.6" textLength="134.2" clip-path="url(#terminal-line-24)">&#160;&#160;⡠⣒⠄&#160;&#160;⡔⢄⠔⡄</text><text class="terminal-r8" x="170.8" y="605.6" textLength="146.4" clip-path="url(#terminal-line-24)">Mistral&#160;Vibe</text><text class="terminal-r1" x="317.2" y="605.6" textLength="122" clip-path="url(#terminal-line-24)">&#160;v0.0.0&#160;·&#160;</text><text class="terminal-r4" x="439.2" y="605.6" textLength="183" clip-path="url(#terminal-line-24)">devstral-latest</text><text class="terminal-r1" x="622.2" y="605.6" textLength="256.2" clip-path="url(#terminal-line-24)">&#160;·&#160;[Subscription]&#160;Pro</text><text class="terminal-r2" x="878.4" y="605.6" textLength="12.2" clip-path="url(#terminal-line-24)"></text><text class="terminal-r1" x="1464" y="605.6" textLength="12.2" clip-path="url(#terminal-line-24)">
</text><text class="terminal-r1" x="0" y="605.6" textLength="134.2" clip-path="url(#terminal-line-24)">&#160;&#160;⡠⣒⠄&#160;&#160;⡔⢄⠔⡄</text><text class="terminal-r8" x="170.8" y="605.6" textLength="146.4" clip-path="url(#terminal-line-24)">Mistral&#160;Vibe</text><text class="terminal-r1" x="317.2" y="605.6" textLength="122" clip-path="url(#terminal-line-24)">&#160;v0.0.0&#160;·&#160;</text><text class="terminal-r4" x="439.2" y="605.6" textLength="244" clip-path="url(#terminal-line-24)">devstral-latest[off]</text><text class="terminal-r1" x="683.2" y="605.6" textLength="195.2" clip-path="url(#terminal-line-24)">&#160;·&#160;[Subscription</text><text class="terminal-r2" x="878.4" y="605.6" textLength="12.2" clip-path="url(#terminal-line-24)"></text><text class="terminal-r1" x="1464" y="605.6" textLength="12.2" clip-path="url(#terminal-line-24)">
</text><text class="terminal-r1" x="0" y="630" textLength="134.2" clip-path="url(#terminal-line-25)">&#160;⢸⠸⣀⡔⢉⠱⣃⡢⣂⡣</text><text class="terminal-r1" x="170.8" y="630" textLength="414.8" clip-path="url(#terminal-line-25)">1&#160;model&#160;·&#160;0&#160;MCP&#160;servers&#160;·&#160;0&#160;skills</text><text class="terminal-r2" x="878.4" y="630" textLength="12.2" clip-path="url(#terminal-line-25)"></text><text class="terminal-r1" x="1464" y="630" textLength="12.2" clip-path="url(#terminal-line-25)">
</text><text class="terminal-r1" x="0" y="654.4" textLength="134.2" clip-path="url(#terminal-line-26)">&#160;&#160;⠉⠒⠣⠤⠵⠤⠬⠮⠆</text><text class="terminal-r1" x="170.8" y="654.4" textLength="61" clip-path="url(#terminal-line-26)">Type&#160;</text><text class="terminal-r4" x="231.8" y="654.4" textLength="61" clip-path="url(#terminal-line-26)">/help</text><text class="terminal-r1" x="292.8" y="654.4" textLength="256.2" clip-path="url(#terminal-line-26)">&#160;for&#160;more&#160;information</text><text class="terminal-r2" x="878.4" y="654.4" textLength="12.2" clip-path="url(#terminal-line-26)"></text><text class="terminal-r1" x="1464" y="654.4" textLength="12.2" clip-path="url(#terminal-line-26)">
</text><text class="terminal-r2" x="878.4" y="678.8" textLength="12.2" clip-path="url(#terminal-line-27)"></text><text class="terminal-r1" x="1464" y="678.8" textLength="12.2" clip-path="url(#terminal-line-27)">

Before

Width:  |  Height:  |  Size: 22 KiB

After

Width:  |  Height:  |  Size: 22 KiB

Before After
Before After

View file

@ -186,7 +186,7 @@
</text><text class="terminal-r2" x="878.4" y="532.4" textLength="12.2" clip-path="url(#terminal-line-21)"></text><text class="terminal-r1" x="902.8" y="532.4" textLength="73.2" clip-path="url(#terminal-line-21)">passed</text><text class="terminal-r1" x="1464" y="532.4" textLength="12.2" clip-path="url(#terminal-line-21)">
</text><text class="terminal-r2" x="878.4" y="556.8" textLength="12.2" clip-path="url(#terminal-line-22)"></text><text class="terminal-r1" x="1464" y="556.8" textLength="12.2" clip-path="url(#terminal-line-22)">
</text><text class="terminal-r2" x="878.4" y="581.2" textLength="12.2" clip-path="url(#terminal-line-23)"></text><text class="terminal-r1" x="1464" y="581.2" textLength="12.2" clip-path="url(#terminal-line-23)">
</text><text class="terminal-r1" x="0" y="605.6" textLength="134.2" clip-path="url(#terminal-line-24)">&#160;&#160;⡠⣒⠄&#160;&#160;⡔⢄⠔⡄</text><text class="terminal-r7" x="170.8" y="605.6" textLength="146.4" clip-path="url(#terminal-line-24)">Mistral&#160;Vibe</text><text class="terminal-r1" x="317.2" y="605.6" textLength="122" clip-path="url(#terminal-line-24)">&#160;v0.0.0&#160;·&#160;</text><text class="terminal-r4" x="439.2" y="605.6" textLength="183" clip-path="url(#terminal-line-24)">devstral-latest</text><text class="terminal-r1" x="622.2" y="605.6" textLength="256.2" clip-path="url(#terminal-line-24)">&#160;·&#160;[Subscription]&#160;Pro</text><text class="terminal-r2" x="878.4" y="605.6" textLength="12.2" clip-path="url(#terminal-line-24)"></text><text class="terminal-r1" x="1464" y="605.6" textLength="12.2" clip-path="url(#terminal-line-24)">
</text><text class="terminal-r1" x="0" y="605.6" textLength="134.2" clip-path="url(#terminal-line-24)">&#160;&#160;⡠⣒⠄&#160;&#160;⡔⢄⠔⡄</text><text class="terminal-r7" x="170.8" y="605.6" textLength="146.4" clip-path="url(#terminal-line-24)">Mistral&#160;Vibe</text><text class="terminal-r1" x="317.2" y="605.6" textLength="122" clip-path="url(#terminal-line-24)">&#160;v0.0.0&#160;·&#160;</text><text class="terminal-r4" x="439.2" y="605.6" textLength="244" clip-path="url(#terminal-line-24)">devstral-latest[off]</text><text class="terminal-r1" x="683.2" y="605.6" textLength="195.2" clip-path="url(#terminal-line-24)">&#160;·&#160;[Subscription</text><text class="terminal-r2" x="878.4" y="605.6" textLength="12.2" clip-path="url(#terminal-line-24)"></text><text class="terminal-r1" x="1464" y="605.6" textLength="12.2" clip-path="url(#terminal-line-24)">
</text><text class="terminal-r1" x="0" y="630" textLength="134.2" clip-path="url(#terminal-line-25)">&#160;⢸⠸⣀⡔⢉⠱⣃⡢⣂⡣</text><text class="terminal-r1" x="170.8" y="630" textLength="414.8" clip-path="url(#terminal-line-25)">1&#160;model&#160;·&#160;0&#160;MCP&#160;servers&#160;·&#160;0&#160;skills</text><text class="terminal-r2" x="878.4" y="630" textLength="12.2" clip-path="url(#terminal-line-25)"></text><text class="terminal-r1" x="1464" y="630" textLength="12.2" clip-path="url(#terminal-line-25)">
</text><text class="terminal-r1" x="0" y="654.4" textLength="134.2" clip-path="url(#terminal-line-26)">&#160;&#160;⠉⠒⠣⠤⠵⠤⠬⠮⠆</text><text class="terminal-r1" x="170.8" y="654.4" textLength="61" clip-path="url(#terminal-line-26)">Type&#160;</text><text class="terminal-r4" x="231.8" y="654.4" textLength="61" clip-path="url(#terminal-line-26)">/help</text><text class="terminal-r1" x="292.8" y="654.4" textLength="256.2" clip-path="url(#terminal-line-26)">&#160;for&#160;more&#160;information</text><text class="terminal-r2" x="878.4" y="654.4" textLength="12.2" clip-path="url(#terminal-line-26)"></text><text class="terminal-r1" x="1464" y="654.4" textLength="12.2" clip-path="url(#terminal-line-26)">
</text><text class="terminal-r2" x="878.4" y="678.8" textLength="12.2" clip-path="url(#terminal-line-27)"></text><text class="terminal-r1" x="1464" y="678.8" textLength="12.2" clip-path="url(#terminal-line-27)">

Before

Width:  |  Height:  |  Size: 22 KiB

After

Width:  |  Height:  |  Size: 22 KiB

Before After
Before After

View file

@ -180,7 +180,7 @@
</text><text class="terminal-r1" x="1464" y="386" textLength="12.2" clip-path="url(#terminal-line-15)">
</text><text class="terminal-r1" x="1464" y="410.4" textLength="12.2" clip-path="url(#terminal-line-16)">
</text><text class="terminal-r1" x="1464" y="434.8" textLength="12.2" clip-path="url(#terminal-line-17)">
</text><text class="terminal-r1" x="0" y="459.2" textLength="134.2" clip-path="url(#terminal-line-18)">&#160;&#160;⡠⣒⠄&#160;&#160;⡔⢄⠔⡄</text><text class="terminal-r2" x="170.8" y="459.2" textLength="146.4" clip-path="url(#terminal-line-18)">Mistral&#160;Vibe</text><text class="terminal-r1" x="317.2" y="459.2" textLength="122" clip-path="url(#terminal-line-18)">&#160;v0.0.0&#160;·&#160;</text><text class="terminal-r3" x="439.2" y="459.2" textLength="183" clip-path="url(#terminal-line-18)">devstral-latest</text><text class="terminal-r1" x="622.2" y="459.2" textLength="256.2" clip-path="url(#terminal-line-18)">&#160;·&#160;[Subscription]&#160;Pro</text><text class="terminal-r1" x="1464" y="459.2" textLength="12.2" clip-path="url(#terminal-line-18)">
</text><text class="terminal-r1" x="0" y="459.2" textLength="134.2" clip-path="url(#terminal-line-18)">&#160;&#160;⡠⣒⠄&#160;&#160;⡔⢄⠔⡄</text><text class="terminal-r2" x="170.8" y="459.2" textLength="146.4" clip-path="url(#terminal-line-18)">Mistral&#160;Vibe</text><text class="terminal-r1" x="317.2" y="459.2" textLength="122" clip-path="url(#terminal-line-18)">&#160;v0.0.0&#160;·&#160;</text><text class="terminal-r3" x="439.2" y="459.2" textLength="244" clip-path="url(#terminal-line-18)">devstral-latest[off]</text><text class="terminal-r1" x="683.2" y="459.2" textLength="256.2" clip-path="url(#terminal-line-18)">&#160;·&#160;[Subscription]&#160;Pro</text><text class="terminal-r1" x="1464" y="459.2" textLength="12.2" clip-path="url(#terminal-line-18)">
</text><text class="terminal-r1" x="0" y="483.6" textLength="134.2" clip-path="url(#terminal-line-19)">&#160;⢸⠸⣀⡔⢉⠱⣃⡢⣂⡣</text><text class="terminal-r1" x="170.8" y="483.6" textLength="414.8" clip-path="url(#terminal-line-19)">1&#160;model&#160;·&#160;0&#160;MCP&#160;servers&#160;·&#160;0&#160;skills</text><text class="terminal-r1" x="1464" y="483.6" textLength="12.2" clip-path="url(#terminal-line-19)">
</text><text class="terminal-r1" x="0" y="508" textLength="134.2" clip-path="url(#terminal-line-20)">&#160;&#160;⠉⠒⠣⠤⠵⠤⠬⠮⠆</text><text class="terminal-r1" x="170.8" y="508" textLength="61" clip-path="url(#terminal-line-20)">Type&#160;</text><text class="terminal-r3" x="231.8" y="508" textLength="61" clip-path="url(#terminal-line-20)">/help</text><text class="terminal-r1" x="292.8" y="508" textLength="256.2" clip-path="url(#terminal-line-20)">&#160;for&#160;more&#160;information</text><text class="terminal-r1" x="1464" y="508" textLength="12.2" clip-path="url(#terminal-line-20)">
</text><text class="terminal-r1" x="1464" y="532.4" textLength="12.2" clip-path="url(#terminal-line-21)">

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 14 KiB

Before After
Before After

View file

@ -181,7 +181,7 @@
</text><text class="terminal-r1" x="1464" y="434.8" textLength="12.2" clip-path="url(#terminal-line-17)">
</text><text class="terminal-r1" x="1464" y="459.2" textLength="12.2" clip-path="url(#terminal-line-18)">
</text><text class="terminal-r1" x="1464" y="483.6" textLength="12.2" clip-path="url(#terminal-line-19)">
</text><text class="terminal-r1" x="0" y="508" textLength="134.2" clip-path="url(#terminal-line-20)">&#160;&#160;⡠⣒⠄&#160;&#160;⡔⢄⠔⡄</text><text class="terminal-r2" x="170.8" y="508" textLength="146.4" clip-path="url(#terminal-line-20)">Mistral&#160;Vibe</text><text class="terminal-r1" x="317.2" y="508" textLength="122" clip-path="url(#terminal-line-20)">&#160;v0.0.0&#160;·&#160;</text><text class="terminal-r3" x="439.2" y="508" textLength="183" clip-path="url(#terminal-line-20)">devstral-latest</text><text class="terminal-r1" x="622.2" y="508" textLength="256.2" clip-path="url(#terminal-line-20)">&#160;·&#160;[Subscription]&#160;Pro</text><text class="terminal-r1" x="1464" y="508" textLength="12.2" clip-path="url(#terminal-line-20)">
</text><text class="terminal-r1" x="0" y="508" textLength="134.2" clip-path="url(#terminal-line-20)">&#160;&#160;⡠⣒⠄&#160;&#160;⡔⢄⠔⡄</text><text class="terminal-r2" x="170.8" y="508" textLength="146.4" clip-path="url(#terminal-line-20)">Mistral&#160;Vibe</text><text class="terminal-r1" x="317.2" y="508" textLength="122" clip-path="url(#terminal-line-20)">&#160;v0.0.0&#160;·&#160;</text><text class="terminal-r3" x="439.2" y="508" textLength="244" clip-path="url(#terminal-line-20)">devstral-latest[off]</text><text class="terminal-r1" x="683.2" y="508" textLength="256.2" clip-path="url(#terminal-line-20)">&#160;·&#160;[Subscription]&#160;Pro</text><text class="terminal-r1" x="1464" y="508" textLength="12.2" clip-path="url(#terminal-line-20)">
</text><text class="terminal-r1" x="0" y="532.4" textLength="134.2" clip-path="url(#terminal-line-21)">&#160;⢸⠸⣀⡔⢉⠱⣃⡢⣂⡣</text><text class="terminal-r1" x="170.8" y="532.4" textLength="414.8" clip-path="url(#terminal-line-21)">1&#160;model&#160;·&#160;0&#160;MCP&#160;servers&#160;·&#160;0&#160;skills</text><text class="terminal-r1" x="1464" y="532.4" textLength="12.2" clip-path="url(#terminal-line-21)">
</text><text class="terminal-r1" x="0" y="556.8" textLength="134.2" clip-path="url(#terminal-line-22)">&#160;&#160;⠉⠒⠣⠤⠵⠤⠬⠮⠆</text><text class="terminal-r1" x="170.8" y="556.8" textLength="61" clip-path="url(#terminal-line-22)">Type&#160;</text><text class="terminal-r3" x="231.8" y="556.8" textLength="61" clip-path="url(#terminal-line-22)">/help</text><text class="terminal-r1" x="292.8" y="556.8" textLength="256.2" clip-path="url(#terminal-line-22)">&#160;for&#160;more&#160;information</text><text class="terminal-r1" x="1464" y="556.8" textLength="12.2" clip-path="url(#terminal-line-22)">
</text><text class="terminal-r1" x="1464" y="581.2" textLength="12.2" clip-path="url(#terminal-line-23)">

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 14 KiB

Before After
Before After

View file

@ -19,187 +19,187 @@
font-weight: 700;
}
.terminal-4926488215-matrix {
.terminal-matrix {
font-family: Fira Code, monospace;
font-size: 20px;
line-height: 24.4px;
font-variant-east-asian: full-width;
}
.terminal-4926488215-title {
.terminal-title {
font-size: 18px;
font-weight: bold;
font-family: arial;
}
.terminal-4926488215-r1 { fill: #c5c8c6 }
.terminal-4926488215-r2 { fill: #ff8205;font-weight: bold }
.terminal-4926488215-r3 { fill: #68a0b3 }
.terminal-4926488215-r4 { fill: #ff8205 }
.terminal-4926488215-r5 { fill: #9a9b99 }
.terminal-4926488215-r6 { fill: #608ab1;font-weight: bold }
.terminal-4926488215-r7 { fill: #c5c8c6;font-weight: bold }
.terminal-4926488215-r8 { fill: #9cafbd;font-weight: bold }
.terminal-4926488215-r9 { fill: #868887 }
.terminal-r1 { fill: #c5c8c6 }
.terminal-r2 { fill: #ff8205;font-weight: bold }
.terminal-r3 { fill: #68a0b3 }
.terminal-r4 { fill: #ff8205 }
.terminal-r5 { fill: #9a9b99 }
.terminal-r6 { fill: #608ab1;font-weight: bold }
.terminal-r7 { fill: #c5c8c6;font-weight: bold }
.terminal-r8 { fill: #9cafbd;font-weight: bold }
.terminal-r9 { fill: #868887 }
</style>
<defs>
<clipPath id="terminal-4926488215-clip-terminal">
<clipPath id="terminal-clip-terminal">
<rect x="0" y="0" width="1463.0" height="877.4" />
</clipPath>
<clipPath id="terminal-4926488215-line-0">
<clipPath id="terminal-line-0">
<rect x="0" y="1.5" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-4926488215-line-1">
<clipPath id="terminal-line-1">
<rect x="0" y="25.9" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-4926488215-line-2">
<clipPath id="terminal-line-2">
<rect x="0" y="50.3" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-4926488215-line-3">
<clipPath id="terminal-line-3">
<rect x="0" y="74.7" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-4926488215-line-4">
<clipPath id="terminal-line-4">
<rect x="0" y="99.1" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-4926488215-line-5">
<clipPath id="terminal-line-5">
<rect x="0" y="123.5" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-4926488215-line-6">
<clipPath id="terminal-line-6">
<rect x="0" y="147.9" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-4926488215-line-7">
<clipPath id="terminal-line-7">
<rect x="0" y="172.3" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-4926488215-line-8">
<clipPath id="terminal-line-8">
<rect x="0" y="196.7" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-4926488215-line-9">
<clipPath id="terminal-line-9">
<rect x="0" y="221.1" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-4926488215-line-10">
<clipPath id="terminal-line-10">
<rect x="0" y="245.5" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-4926488215-line-11">
<clipPath id="terminal-line-11">
<rect x="0" y="269.9" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-4926488215-line-12">
<clipPath id="terminal-line-12">
<rect x="0" y="294.3" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-4926488215-line-13">
<clipPath id="terminal-line-13">
<rect x="0" y="318.7" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-4926488215-line-14">
<clipPath id="terminal-line-14">
<rect x="0" y="343.1" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-4926488215-line-15">
<clipPath id="terminal-line-15">
<rect x="0" y="367.5" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-4926488215-line-16">
<clipPath id="terminal-line-16">
<rect x="0" y="391.9" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-4926488215-line-17">
<clipPath id="terminal-line-17">
<rect x="0" y="416.3" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-4926488215-line-18">
<clipPath id="terminal-line-18">
<rect x="0" y="440.7" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-4926488215-line-19">
<clipPath id="terminal-line-19">
<rect x="0" y="465.1" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-4926488215-line-20">
<clipPath id="terminal-line-20">
<rect x="0" y="489.5" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-4926488215-line-21">
<clipPath id="terminal-line-21">
<rect x="0" y="513.9" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-4926488215-line-22">
<clipPath id="terminal-line-22">
<rect x="0" y="538.3" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-4926488215-line-23">
<clipPath id="terminal-line-23">
<rect x="0" y="562.7" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-4926488215-line-24">
<clipPath id="terminal-line-24">
<rect x="0" y="587.1" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-4926488215-line-25">
<clipPath id="terminal-line-25">
<rect x="0" y="611.5" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-4926488215-line-26">
<clipPath id="terminal-line-26">
<rect x="0" y="635.9" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-4926488215-line-27">
<clipPath id="terminal-line-27">
<rect x="0" y="660.3" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-4926488215-line-28">
<clipPath id="terminal-line-28">
<rect x="0" y="684.7" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-4926488215-line-29">
<clipPath id="terminal-line-29">
<rect x="0" y="709.1" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-4926488215-line-30">
<clipPath id="terminal-line-30">
<rect x="0" y="733.5" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-4926488215-line-31">
<clipPath id="terminal-line-31">
<rect x="0" y="757.9" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-4926488215-line-32">
<clipPath id="terminal-line-32">
<rect x="0" y="782.3" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-4926488215-line-33">
<clipPath id="terminal-line-33">
<rect x="0" y="806.7" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-4926488215-line-34">
<clipPath id="terminal-line-34">
<rect x="0" y="831.1" width="1464" height="24.65"/>
</clipPath>
</defs>
<rect fill="#292929" stroke="rgba(255,255,255,0.35)" stroke-width="1" x="1" y="1" width="1480" height="926.4" rx="8"/><text class="terminal-4926488215-title" fill="#c5c8c6" text-anchor="middle" x="740" y="27">SnapshotTestAppWithMcpServers</text>
<rect fill="#292929" stroke="rgba(255,255,255,0.35)" stroke-width="1" x="1" y="1" width="1480" height="926.4" rx="8"/><text class="terminal-title" fill="#c5c8c6" text-anchor="middle" x="740" y="27">SnapshotTestAppWithMcpServers</text>
<g transform="translate(26,22)">
<circle cx="0" cy="0" r="7" fill="#ff5f57"/>
<circle cx="22" cy="0" r="7" fill="#febc2e"/>
<circle cx="44" cy="0" r="7" fill="#28c840"/>
</g>
<g transform="translate(9, 41)" clip-path="url(#terminal-4926488215-clip-terminal)">
<g transform="translate(9, 41)" clip-path="url(#terminal-clip-terminal)">
<rect fill="#608ab1" x="36.6" y="733.5" width="146.4" height="24.65" shape-rendering="crispEdges"/><rect fill="#608ab1" x="183" y="733.5" width="109.8" height="24.65" shape-rendering="crispEdges"/><rect fill="#608ab1" x="292.8" y="733.5" width="97.6" height="24.65" shape-rendering="crispEdges"/><rect fill="#608ab1" x="390.4" y="733.5" width="1037" height="24.65" shape-rendering="crispEdges"/>
<g class="terminal-4926488215-matrix">
<text class="terminal-4926488215-r1" x="1464" y="20" textLength="12.2" clip-path="url(#terminal-4926488215-line-0)">
</text><text class="terminal-4926488215-r1" x="1464" y="44.4" textLength="12.2" clip-path="url(#terminal-4926488215-line-1)">
</text><text class="terminal-4926488215-r1" x="1464" y="68.8" textLength="12.2" clip-path="url(#terminal-4926488215-line-2)">
</text><text class="terminal-4926488215-r1" x="1464" y="93.2" textLength="12.2" clip-path="url(#terminal-4926488215-line-3)">
</text><text class="terminal-4926488215-r1" x="1464" y="117.6" textLength="12.2" clip-path="url(#terminal-4926488215-line-4)">
</text><text class="terminal-4926488215-r1" x="1464" y="142" textLength="12.2" clip-path="url(#terminal-4926488215-line-5)">
</text><text class="terminal-4926488215-r1" x="1464" y="166.4" textLength="12.2" clip-path="url(#terminal-4926488215-line-6)">
</text><text class="terminal-4926488215-r1" x="1464" y="190.8" textLength="12.2" clip-path="url(#terminal-4926488215-line-7)">
</text><text class="terminal-4926488215-r1" x="1464" y="215.2" textLength="12.2" clip-path="url(#terminal-4926488215-line-8)">
</text><text class="terminal-4926488215-r1" x="1464" y="239.6" textLength="12.2" clip-path="url(#terminal-4926488215-line-9)">
</text><text class="terminal-4926488215-r1" x="1464" y="264" textLength="12.2" clip-path="url(#terminal-4926488215-line-10)">
</text><text class="terminal-4926488215-r1" x="1464" y="288.4" textLength="12.2" clip-path="url(#terminal-4926488215-line-11)">
</text><text class="terminal-4926488215-r1" x="1464" y="312.8" textLength="12.2" clip-path="url(#terminal-4926488215-line-12)">
</text><text class="terminal-4926488215-r1" x="1464" y="337.2" textLength="12.2" clip-path="url(#terminal-4926488215-line-13)">
</text><text class="terminal-4926488215-r1" x="1464" y="361.6" textLength="12.2" clip-path="url(#terminal-4926488215-line-14)">
</text><text class="terminal-4926488215-r1" x="1464" y="386" textLength="12.2" clip-path="url(#terminal-4926488215-line-15)">
</text><text class="terminal-4926488215-r1" x="1464" y="410.4" textLength="12.2" clip-path="url(#terminal-4926488215-line-16)">
</text><text class="terminal-4926488215-r1" x="0" y="434.8" textLength="134.2" clip-path="url(#terminal-4926488215-line-17)">&#160;&#160;⡠⣒⠄&#160;&#160;⡔⢄⠔⡄</text><text class="terminal-4926488215-r2" x="170.8" y="434.8" textLength="146.4" clip-path="url(#terminal-4926488215-line-17)">Mistral&#160;Vibe</text><text class="terminal-4926488215-r1" x="317.2" y="434.8" textLength="122" clip-path="url(#terminal-4926488215-line-17)">&#160;v0.0.0&#160;·&#160;</text><text class="terminal-4926488215-r3" x="439.2" y="434.8" textLength="183" clip-path="url(#terminal-4926488215-line-17)">devstral-latest</text><text class="terminal-4926488215-r1" x="622.2" y="434.8" textLength="256.2" clip-path="url(#terminal-4926488215-line-17)">&#160;·&#160;[Subscription]&#160;Pro</text><text class="terminal-4926488215-r1" x="1464" y="434.8" textLength="12.2" clip-path="url(#terminal-4926488215-line-17)">
</text><text class="terminal-4926488215-r1" x="0" y="459.2" textLength="134.2" clip-path="url(#terminal-4926488215-line-18)">&#160;⢸⠸⣀⡔⢉⠱⣃⡢⣂⡣</text><text class="terminal-4926488215-r1" x="170.8" y="459.2" textLength="414.8" clip-path="url(#terminal-4926488215-line-18)">1&#160;model&#160;·&#160;2&#160;MCP&#160;servers&#160;·&#160;0&#160;skills</text><text class="terminal-4926488215-r1" x="1464" y="459.2" textLength="12.2" clip-path="url(#terminal-4926488215-line-18)">
</text><text class="terminal-4926488215-r1" x="0" y="483.6" textLength="134.2" clip-path="url(#terminal-4926488215-line-19)">&#160;&#160;⠉⠒⠣⠤⠵⠤⠬⠮⠆</text><text class="terminal-4926488215-r1" x="170.8" y="483.6" textLength="61" clip-path="url(#terminal-4926488215-line-19)">Type&#160;</text><text class="terminal-4926488215-r3" x="231.8" y="483.6" textLength="61" clip-path="url(#terminal-4926488215-line-19)">/help</text><text class="terminal-4926488215-r1" x="292.8" y="483.6" textLength="256.2" clip-path="url(#terminal-4926488215-line-19)">&#160;for&#160;more&#160;information</text><text class="terminal-4926488215-r1" x="1464" y="483.6" textLength="12.2" clip-path="url(#terminal-4926488215-line-19)">
</text><text class="terminal-4926488215-r1" x="1464" y="508" textLength="12.2" clip-path="url(#terminal-4926488215-line-20)">
</text><text class="terminal-4926488215-r1" x="1464" y="532.4" textLength="12.2" clip-path="url(#terminal-4926488215-line-21)">
</text><text class="terminal-4926488215-r4" x="0" y="556.8" textLength="12.2" clip-path="url(#terminal-4926488215-line-22)"></text><text class="terminal-4926488215-r2" x="24.4" y="556.8" textLength="183" clip-path="url(#terminal-4926488215-line-22)">/mcp&#160;filesystem</text><text class="terminal-4926488215-r1" x="1464" y="556.8" textLength="12.2" clip-path="url(#terminal-4926488215-line-22)">
</text><text class="terminal-4926488215-r5" x="24.4" y="581.2" textLength="12.2" clip-path="url(#terminal-4926488215-line-23)"></text><text class="terminal-4926488215-r1" x="48.8" y="581.2" textLength="256.2" clip-path="url(#terminal-4926488215-line-23)">MCP&#160;servers&#160;opened...</text><text class="terminal-4926488215-r1" x="1464" y="581.2" textLength="12.2" clip-path="url(#terminal-4926488215-line-23)">
</text><text class="terminal-4926488215-r1" x="1464" y="605.6" textLength="12.2" clip-path="url(#terminal-4926488215-line-24)">
</text><text class="terminal-4926488215-r1" x="1464" y="630" textLength="12.2" clip-path="url(#terminal-4926488215-line-25)">
</text><text class="terminal-4926488215-r5" x="0" y="654.4" textLength="1464" clip-path="url(#terminal-4926488215-line-26)">┌──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐</text><text class="terminal-4926488215-r1" x="1464" y="654.4" textLength="12.2" clip-path="url(#terminal-4926488215-line-26)">
</text><text class="terminal-4926488215-r5" x="0" y="678.8" textLength="12.2" clip-path="url(#terminal-4926488215-line-27)"></text><text class="terminal-4926488215-r6" x="24.4" y="678.8" textLength="134.2" clip-path="url(#terminal-4926488215-line-27)">MCP&#160;Servers</text><text class="terminal-4926488215-r5" x="1451.8" y="678.8" textLength="12.2" clip-path="url(#terminal-4926488215-line-27)"></text><text class="terminal-4926488215-r1" x="1464" y="678.8" textLength="12.2" clip-path="url(#terminal-4926488215-line-27)">
</text><text class="terminal-4926488215-r5" x="0" y="703.2" textLength="12.2" clip-path="url(#terminal-4926488215-line-28)"></text><text class="terminal-4926488215-r5" x="1451.8" y="703.2" textLength="12.2" clip-path="url(#terminal-4926488215-line-28)"></text><text class="terminal-4926488215-r1" x="1464" y="703.2" textLength="12.2" clip-path="url(#terminal-4926488215-line-28)">
</text><text class="terminal-4926488215-r5" x="0" y="727.6" textLength="12.2" clip-path="url(#terminal-4926488215-line-29)"></text><text class="terminal-4926488215-r7" x="36.6" y="727.6" textLength="207.4" clip-path="url(#terminal-4926488215-line-29)">Local&#160;MCP&#160;Servers</text><text class="terminal-4926488215-r5" x="1451.8" y="727.6" textLength="12.2" clip-path="url(#terminal-4926488215-line-29)"></text><text class="terminal-4926488215-r1" x="1464" y="727.6" textLength="12.2" clip-path="url(#terminal-4926488215-line-29)">
</text><text class="terminal-4926488215-r5" x="0" y="752" textLength="12.2" clip-path="url(#terminal-4926488215-line-30)"></text><text class="terminal-4926488215-r7" x="36.6" y="752" textLength="146.4" clip-path="url(#terminal-4926488215-line-30)">&#160;&#160;filesystem</text><text class="terminal-4926488215-r8" x="183" y="752" textLength="109.8" clip-path="url(#terminal-4926488215-line-30)">&#160;&#160;[stdio]</text><text class="terminal-4926488215-r8" x="292.8" y="752" textLength="97.6" clip-path="url(#terminal-4926488215-line-30)">&#160;&#160;1&#160;tool</text><text class="terminal-4926488215-r5" x="1451.8" y="752" textLength="12.2" clip-path="url(#terminal-4926488215-line-30)"></text><text class="terminal-4926488215-r1" x="1464" y="752" textLength="12.2" clip-path="url(#terminal-4926488215-line-30)">
</text><text class="terminal-4926488215-r5" x="0" y="776.4" textLength="12.2" clip-path="url(#terminal-4926488215-line-31)"></text><text class="terminal-4926488215-r1" x="36.6" y="776.4" textLength="146.4" clip-path="url(#terminal-4926488215-line-31)">&#160;&#160;search&#160;&#160;&#160;&#160;</text><text class="terminal-4926488215-r9" x="183" y="776.4" textLength="109.8" clip-path="url(#terminal-4926488215-line-31)">&#160;&#160;[http]&#160;</text><text class="terminal-4926488215-r9" x="292.8" y="776.4" textLength="97.6" clip-path="url(#terminal-4926488215-line-31)">&#160;&#160;1&#160;tool</text><text class="terminal-4926488215-r5" x="1451.8" y="776.4" textLength="12.2" clip-path="url(#terminal-4926488215-line-31)"></text><text class="terminal-4926488215-r1" x="1464" y="776.4" textLength="12.2" clip-path="url(#terminal-4926488215-line-31)">
</text><text class="terminal-4926488215-r5" x="0" y="800.8" textLength="12.2" clip-path="url(#terminal-4926488215-line-32)"></text><text class="terminal-4926488215-r5" x="1451.8" y="800.8" textLength="12.2" clip-path="url(#terminal-4926488215-line-32)"></text><text class="terminal-4926488215-r1" x="1464" y="800.8" textLength="12.2" clip-path="url(#terminal-4926488215-line-32)">
</text><text class="terminal-4926488215-r5" x="0" y="825.2" textLength="12.2" clip-path="url(#terminal-4926488215-line-33)"></text><text class="terminal-4926488215-r5" x="24.4" y="825.2" textLength="622.2" clip-path="url(#terminal-4926488215-line-33)">↑↓&#160;Navigate&#160;&#160;Enter&#160;Show&#160;tools&#160;&#160;R&#160;Refresh&#160;&#160;Esc&#160;Close</text><text class="terminal-4926488215-r5" x="1451.8" y="825.2" textLength="12.2" clip-path="url(#terminal-4926488215-line-33)"></text><text class="terminal-4926488215-r1" x="1464" y="825.2" textLength="12.2" clip-path="url(#terminal-4926488215-line-33)">
</text><text class="terminal-4926488215-r5" x="0" y="849.6" textLength="1464" clip-path="url(#terminal-4926488215-line-34)">└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘</text><text class="terminal-4926488215-r1" x="1464" y="849.6" textLength="12.2" clip-path="url(#terminal-4926488215-line-34)">
</text><text class="terminal-4926488215-r5" x="0" y="874" textLength="158.6" clip-path="url(#terminal-4926488215-line-35)">/test/workdir</text><text class="terminal-4926488215-r5" x="1256.6" y="874" textLength="207.4" clip-path="url(#terminal-4926488215-line-35)">0%&#160;of&#160;200k&#160;tokens</text>
<g class="terminal-matrix">
<text class="terminal-r1" x="1464" y="20" textLength="12.2" clip-path="url(#terminal-line-0)">
</text><text class="terminal-r1" x="1464" y="44.4" textLength="12.2" clip-path="url(#terminal-line-1)">
</text><text class="terminal-r1" x="1464" y="68.8" textLength="12.2" clip-path="url(#terminal-line-2)">
</text><text class="terminal-r1" x="1464" y="93.2" textLength="12.2" clip-path="url(#terminal-line-3)">
</text><text class="terminal-r1" x="1464" y="117.6" textLength="12.2" clip-path="url(#terminal-line-4)">
</text><text class="terminal-r1" x="1464" y="142" textLength="12.2" clip-path="url(#terminal-line-5)">
</text><text class="terminal-r1" x="1464" y="166.4" textLength="12.2" clip-path="url(#terminal-line-6)">
</text><text class="terminal-r1" x="1464" y="190.8" textLength="12.2" clip-path="url(#terminal-line-7)">
</text><text class="terminal-r1" x="1464" y="215.2" textLength="12.2" clip-path="url(#terminal-line-8)">
</text><text class="terminal-r1" x="1464" y="239.6" textLength="12.2" clip-path="url(#terminal-line-9)">
</text><text class="terminal-r1" x="1464" y="264" textLength="12.2" clip-path="url(#terminal-line-10)">
</text><text class="terminal-r1" x="1464" y="288.4" textLength="12.2" clip-path="url(#terminal-line-11)">
</text><text class="terminal-r1" x="1464" y="312.8" textLength="12.2" clip-path="url(#terminal-line-12)">
</text><text class="terminal-r1" x="1464" y="337.2" textLength="12.2" clip-path="url(#terminal-line-13)">
</text><text class="terminal-r1" x="1464" y="361.6" textLength="12.2" clip-path="url(#terminal-line-14)">
</text><text class="terminal-r1" x="1464" y="386" textLength="12.2" clip-path="url(#terminal-line-15)">
</text><text class="terminal-r1" x="1464" y="410.4" textLength="12.2" clip-path="url(#terminal-line-16)">
</text><text class="terminal-r1" x="0" y="434.8" textLength="134.2" clip-path="url(#terminal-line-17)">&#160;&#160;⡠⣒⠄&#160;&#160;⡔⢄⠔⡄</text><text class="terminal-r2" x="170.8" y="434.8" textLength="146.4" clip-path="url(#terminal-line-17)">Mistral&#160;Vibe</text><text class="terminal-r1" x="317.2" y="434.8" textLength="122" clip-path="url(#terminal-line-17)">&#160;v0.0.0&#160;·&#160;</text><text class="terminal-r3" x="439.2" y="434.8" textLength="244" clip-path="url(#terminal-line-17)">devstral-latest[off]</text><text class="terminal-r1" x="683.2" y="434.8" textLength="256.2" clip-path="url(#terminal-line-17)">&#160;·&#160;[Subscription]&#160;Pro</text><text class="terminal-r1" x="1464" y="434.8" textLength="12.2" clip-path="url(#terminal-line-17)">
</text><text class="terminal-r1" x="0" y="459.2" textLength="134.2" clip-path="url(#terminal-line-18)">&#160;⢸⠸⣀⡔⢉⠱⣃⡢⣂⡣</text><text class="terminal-r1" x="170.8" y="459.2" textLength="414.8" clip-path="url(#terminal-line-18)">1&#160;model&#160;·&#160;2&#160;MCP&#160;servers&#160;·&#160;0&#160;skills</text><text class="terminal-r1" x="1464" y="459.2" textLength="12.2" clip-path="url(#terminal-line-18)">
</text><text class="terminal-r1" x="0" y="483.6" textLength="134.2" clip-path="url(#terminal-line-19)">&#160;&#160;⠉⠒⠣⠤⠵⠤⠬⠮⠆</text><text class="terminal-r1" x="170.8" y="483.6" textLength="61" clip-path="url(#terminal-line-19)">Type&#160;</text><text class="terminal-r3" x="231.8" y="483.6" textLength="61" clip-path="url(#terminal-line-19)">/help</text><text class="terminal-r1" x="292.8" y="483.6" textLength="256.2" clip-path="url(#terminal-line-19)">&#160;for&#160;more&#160;information</text><text class="terminal-r1" x="1464" y="483.6" textLength="12.2" clip-path="url(#terminal-line-19)">
</text><text class="terminal-r1" x="1464" y="508" textLength="12.2" clip-path="url(#terminal-line-20)">
</text><text class="terminal-r1" x="1464" y="532.4" textLength="12.2" clip-path="url(#terminal-line-21)">
</text><text class="terminal-r4" x="0" y="556.8" textLength="12.2" clip-path="url(#terminal-line-22)"></text><text class="terminal-r2" x="24.4" y="556.8" textLength="183" clip-path="url(#terminal-line-22)">/mcp&#160;filesystem</text><text class="terminal-r1" x="1464" y="556.8" textLength="12.2" clip-path="url(#terminal-line-22)">
</text><text class="terminal-r5" x="24.4" y="581.2" textLength="12.2" clip-path="url(#terminal-line-23)"></text><text class="terminal-r1" x="48.8" y="581.2" textLength="256.2" clip-path="url(#terminal-line-23)">MCP&#160;servers&#160;opened...</text><text class="terminal-r1" x="1464" y="581.2" textLength="12.2" clip-path="url(#terminal-line-23)">
</text><text class="terminal-r1" x="1464" y="605.6" textLength="12.2" clip-path="url(#terminal-line-24)">
</text><text class="terminal-r1" x="1464" y="630" textLength="12.2" clip-path="url(#terminal-line-25)">
</text><text class="terminal-r5" x="0" y="654.4" textLength="1464" clip-path="url(#terminal-line-26)">┌──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐</text><text class="terminal-r1" x="1464" y="654.4" textLength="12.2" clip-path="url(#terminal-line-26)">
</text><text class="terminal-r5" x="0" y="678.8" textLength="12.2" clip-path="url(#terminal-line-27)"></text><text class="terminal-r6" x="24.4" y="678.8" textLength="134.2" clip-path="url(#terminal-line-27)">MCP&#160;Servers</text><text class="terminal-r5" x="1451.8" y="678.8" textLength="12.2" clip-path="url(#terminal-line-27)"></text><text class="terminal-r1" x="1464" y="678.8" textLength="12.2" clip-path="url(#terminal-line-27)">
</text><text class="terminal-r5" x="0" y="703.2" textLength="12.2" clip-path="url(#terminal-line-28)"></text><text class="terminal-r5" x="1451.8" y="703.2" textLength="12.2" clip-path="url(#terminal-line-28)"></text><text class="terminal-r1" x="1464" y="703.2" textLength="12.2" clip-path="url(#terminal-line-28)">
</text><text class="terminal-r5" x="0" y="727.6" textLength="12.2" clip-path="url(#terminal-line-29)"></text><text class="terminal-r7" x="36.6" y="727.6" textLength="207.4" clip-path="url(#terminal-line-29)">Local&#160;MCP&#160;Servers</text><text class="terminal-r5" x="1451.8" y="727.6" textLength="12.2" clip-path="url(#terminal-line-29)"></text><text class="terminal-r1" x="1464" y="727.6" textLength="12.2" clip-path="url(#terminal-line-29)">
</text><text class="terminal-r5" x="0" y="752" textLength="12.2" clip-path="url(#terminal-line-30)"></text><text class="terminal-r7" x="36.6" y="752" textLength="146.4" clip-path="url(#terminal-line-30)">&#160;&#160;filesystem</text><text class="terminal-r8" x="183" y="752" textLength="109.8" clip-path="url(#terminal-line-30)">&#160;&#160;[stdio]</text><text class="terminal-r8" x="292.8" y="752" textLength="97.6" clip-path="url(#terminal-line-30)">&#160;&#160;1&#160;tool</text><text class="terminal-r5" x="1451.8" y="752" textLength="12.2" clip-path="url(#terminal-line-30)"></text><text class="terminal-r1" x="1464" y="752" textLength="12.2" clip-path="url(#terminal-line-30)">
</text><text class="terminal-r5" x="0" y="776.4" textLength="12.2" clip-path="url(#terminal-line-31)"></text><text class="terminal-r1" x="36.6" y="776.4" textLength="146.4" clip-path="url(#terminal-line-31)">&#160;&#160;search&#160;&#160;&#160;&#160;</text><text class="terminal-r9" x="183" y="776.4" textLength="109.8" clip-path="url(#terminal-line-31)">&#160;&#160;[http]&#160;</text><text class="terminal-r9" x="292.8" y="776.4" textLength="97.6" clip-path="url(#terminal-line-31)">&#160;&#160;1&#160;tool</text><text class="terminal-r5" x="1451.8" y="776.4" textLength="12.2" clip-path="url(#terminal-line-31)"></text><text class="terminal-r1" x="1464" y="776.4" textLength="12.2" clip-path="url(#terminal-line-31)">
</text><text class="terminal-r5" x="0" y="800.8" textLength="12.2" clip-path="url(#terminal-line-32)"></text><text class="terminal-r5" x="1451.8" y="800.8" textLength="12.2" clip-path="url(#terminal-line-32)"></text><text class="terminal-r1" x="1464" y="800.8" textLength="12.2" clip-path="url(#terminal-line-32)">
</text><text class="terminal-r5" x="0" y="825.2" textLength="12.2" clip-path="url(#terminal-line-33)"></text><text class="terminal-r5" x="24.4" y="825.2" textLength="878.4" clip-path="url(#terminal-line-33)">↑↓&#160;Navigate&#160;&#160;Enter&#160;Show&#160;tools&#160;&#160;D&#160;Disable&#160;&#160;E&#160;Enable&#160;&#160;R&#160;Refresh&#160;&#160;Esc&#160;Close</text><text class="terminal-r5" x="1451.8" y="825.2" textLength="12.2" clip-path="url(#terminal-line-33)"></text><text class="terminal-r1" x="1464" y="825.2" textLength="12.2" clip-path="url(#terminal-line-33)">
</text><text class="terminal-r5" x="0" y="849.6" textLength="1464" clip-path="url(#terminal-line-34)">└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘</text><text class="terminal-r1" x="1464" y="849.6" textLength="12.2" clip-path="url(#terminal-line-34)">
</text><text class="terminal-r5" x="0" y="874" textLength="158.6" clip-path="url(#terminal-line-35)">/test/workdir</text><text class="terminal-r5" x="1256.6" y="874" textLength="207.4" clip-path="url(#terminal-line-35)">0%&#160;of&#160;200k&#160;tokens</text>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 16 KiB

Before After
Before After

View file

@ -19,187 +19,187 @@
font-weight: 700;
}
.terminal-2811199383-matrix {
.terminal-matrix {
font-family: Fira Code, monospace;
font-size: 20px;
line-height: 24.4px;
font-variant-east-asian: full-width;
}
.terminal-2811199383-title {
.terminal-title {
font-size: 18px;
font-weight: bold;
font-family: arial;
}
.terminal-2811199383-r1 { fill: #c5c8c6 }
.terminal-2811199383-r2 { fill: #ff8205;font-weight: bold }
.terminal-2811199383-r3 { fill: #68a0b3 }
.terminal-2811199383-r4 { fill: #ff8205 }
.terminal-2811199383-r5 { fill: #9a9b99 }
.terminal-2811199383-r6 { fill: #608ab1;font-weight: bold }
.terminal-2811199383-r7 { fill: #c5c8c6;font-weight: bold }
.terminal-2811199383-r8 { fill: #9cafbd;font-weight: bold }
.terminal-2811199383-r9 { fill: #868887 }
.terminal-r1 { fill: #c5c8c6 }
.terminal-r2 { fill: #ff8205;font-weight: bold }
.terminal-r3 { fill: #68a0b3 }
.terminal-r4 { fill: #ff8205 }
.terminal-r5 { fill: #9a9b99 }
.terminal-r6 { fill: #608ab1;font-weight: bold }
.terminal-r7 { fill: #c5c8c6;font-weight: bold }
.terminal-r8 { fill: #9cafbd;font-weight: bold }
.terminal-r9 { fill: #868887 }
</style>
<defs>
<clipPath id="terminal-2811199383-clip-terminal">
<clipPath id="terminal-clip-terminal">
<rect x="0" y="0" width="1463.0" height="877.4" />
</clipPath>
<clipPath id="terminal-2811199383-line-0">
<clipPath id="terminal-line-0">
<rect x="0" y="1.5" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-2811199383-line-1">
<clipPath id="terminal-line-1">
<rect x="0" y="25.9" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-2811199383-line-2">
<clipPath id="terminal-line-2">
<rect x="0" y="50.3" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-2811199383-line-3">
<clipPath id="terminal-line-3">
<rect x="0" y="74.7" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-2811199383-line-4">
<clipPath id="terminal-line-4">
<rect x="0" y="99.1" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-2811199383-line-5">
<clipPath id="terminal-line-5">
<rect x="0" y="123.5" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-2811199383-line-6">
<clipPath id="terminal-line-6">
<rect x="0" y="147.9" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-2811199383-line-7">
<clipPath id="terminal-line-7">
<rect x="0" y="172.3" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-2811199383-line-8">
<clipPath id="terminal-line-8">
<rect x="0" y="196.7" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-2811199383-line-9">
<clipPath id="terminal-line-9">
<rect x="0" y="221.1" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-2811199383-line-10">
<clipPath id="terminal-line-10">
<rect x="0" y="245.5" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-2811199383-line-11">
<clipPath id="terminal-line-11">
<rect x="0" y="269.9" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-2811199383-line-12">
<clipPath id="terminal-line-12">
<rect x="0" y="294.3" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-2811199383-line-13">
<clipPath id="terminal-line-13">
<rect x="0" y="318.7" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-2811199383-line-14">
<clipPath id="terminal-line-14">
<rect x="0" y="343.1" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-2811199383-line-15">
<clipPath id="terminal-line-15">
<rect x="0" y="367.5" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-2811199383-line-16">
<clipPath id="terminal-line-16">
<rect x="0" y="391.9" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-2811199383-line-17">
<clipPath id="terminal-line-17">
<rect x="0" y="416.3" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-2811199383-line-18">
<clipPath id="terminal-line-18">
<rect x="0" y="440.7" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-2811199383-line-19">
<clipPath id="terminal-line-19">
<rect x="0" y="465.1" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-2811199383-line-20">
<clipPath id="terminal-line-20">
<rect x="0" y="489.5" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-2811199383-line-21">
<clipPath id="terminal-line-21">
<rect x="0" y="513.9" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-2811199383-line-22">
<clipPath id="terminal-line-22">
<rect x="0" y="538.3" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-2811199383-line-23">
<clipPath id="terminal-line-23">
<rect x="0" y="562.7" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-2811199383-line-24">
<clipPath id="terminal-line-24">
<rect x="0" y="587.1" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-2811199383-line-25">
<clipPath id="terminal-line-25">
<rect x="0" y="611.5" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-2811199383-line-26">
<clipPath id="terminal-line-26">
<rect x="0" y="635.9" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-2811199383-line-27">
<clipPath id="terminal-line-27">
<rect x="0" y="660.3" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-2811199383-line-28">
<clipPath id="terminal-line-28">
<rect x="0" y="684.7" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-2811199383-line-29">
<clipPath id="terminal-line-29">
<rect x="0" y="709.1" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-2811199383-line-30">
<clipPath id="terminal-line-30">
<rect x="0" y="733.5" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-2811199383-line-31">
<clipPath id="terminal-line-31">
<rect x="0" y="757.9" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-2811199383-line-32">
<clipPath id="terminal-line-32">
<rect x="0" y="782.3" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-2811199383-line-33">
<clipPath id="terminal-line-33">
<rect x="0" y="806.7" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-2811199383-line-34">
<clipPath id="terminal-line-34">
<rect x="0" y="831.1" width="1464" height="24.65"/>
</clipPath>
</defs>
<rect fill="#292929" stroke="rgba(255,255,255,0.35)" stroke-width="1" x="1" y="1" width="1480" height="926.4" rx="8"/><text class="terminal-2811199383-title" fill="#c5c8c6" text-anchor="middle" x="740" y="27">SnapshotTestAppWithBrokenMcpServer</text>
<rect fill="#292929" stroke="rgba(255,255,255,0.35)" stroke-width="1" x="1" y="1" width="1480" height="926.4" rx="8"/><text class="terminal-title" fill="#c5c8c6" text-anchor="middle" x="740" y="27">SnapshotTestAppWithBrokenMcpServer</text>
<g transform="translate(26,22)">
<circle cx="0" cy="0" r="7" fill="#ff5f57"/>
<circle cx="22" cy="0" r="7" fill="#febc2e"/>
<circle cx="44" cy="0" r="7" fill="#28c840"/>
</g>
<g transform="translate(9, 41)" clip-path="url(#terminal-2811199383-clip-terminal)">
<g transform="translate(9, 41)" clip-path="url(#terminal-clip-terminal)">
<rect fill="#608ab1" x="36.6" y="709.1" width="183" height="24.65" shape-rendering="crispEdges"/><rect fill="#608ab1" x="219.6" y="709.1" width="109.8" height="24.65" shape-rendering="crispEdges"/><rect fill="#608ab1" x="329.4" y="709.1" width="97.6" height="24.65" shape-rendering="crispEdges"/><rect fill="#608ab1" x="427" y="709.1" width="1000.4" height="24.65" shape-rendering="crispEdges"/>
<g class="terminal-2811199383-matrix">
<text class="terminal-2811199383-r1" x="1464" y="20" textLength="12.2" clip-path="url(#terminal-2811199383-line-0)">
</text><text class="terminal-2811199383-r1" x="1464" y="44.4" textLength="12.2" clip-path="url(#terminal-2811199383-line-1)">
</text><text class="terminal-2811199383-r1" x="1464" y="68.8" textLength="12.2" clip-path="url(#terminal-2811199383-line-2)">
</text><text class="terminal-2811199383-r1" x="1464" y="93.2" textLength="12.2" clip-path="url(#terminal-2811199383-line-3)">
</text><text class="terminal-2811199383-r1" x="1464" y="117.6" textLength="12.2" clip-path="url(#terminal-2811199383-line-4)">
</text><text class="terminal-2811199383-r1" x="1464" y="142" textLength="12.2" clip-path="url(#terminal-2811199383-line-5)">
</text><text class="terminal-2811199383-r1" x="1464" y="166.4" textLength="12.2" clip-path="url(#terminal-2811199383-line-6)">
</text><text class="terminal-2811199383-r1" x="1464" y="190.8" textLength="12.2" clip-path="url(#terminal-2811199383-line-7)">
</text><text class="terminal-2811199383-r1" x="1464" y="215.2" textLength="12.2" clip-path="url(#terminal-2811199383-line-8)">
</text><text class="terminal-2811199383-r1" x="1464" y="239.6" textLength="12.2" clip-path="url(#terminal-2811199383-line-9)">
</text><text class="terminal-2811199383-r1" x="1464" y="264" textLength="12.2" clip-path="url(#terminal-2811199383-line-10)">
</text><text class="terminal-2811199383-r1" x="1464" y="288.4" textLength="12.2" clip-path="url(#terminal-2811199383-line-11)">
</text><text class="terminal-2811199383-r1" x="1464" y="312.8" textLength="12.2" clip-path="url(#terminal-2811199383-line-12)">
</text><text class="terminal-2811199383-r1" x="1464" y="337.2" textLength="12.2" clip-path="url(#terminal-2811199383-line-13)">
</text><text class="terminal-2811199383-r1" x="1464" y="361.6" textLength="12.2" clip-path="url(#terminal-2811199383-line-14)">
</text><text class="terminal-2811199383-r1" x="1464" y="386" textLength="12.2" clip-path="url(#terminal-2811199383-line-15)">
</text><text class="terminal-2811199383-r1" x="0" y="410.4" textLength="134.2" clip-path="url(#terminal-2811199383-line-16)">&#160;&#160;⡠⣒⠄&#160;&#160;⡔⢄⠔⡄</text><text class="terminal-2811199383-r2" x="170.8" y="410.4" textLength="146.4" clip-path="url(#terminal-2811199383-line-16)">Mistral&#160;Vibe</text><text class="terminal-2811199383-r1" x="317.2" y="410.4" textLength="122" clip-path="url(#terminal-2811199383-line-16)">&#160;v0.0.0&#160;·&#160;</text><text class="terminal-2811199383-r3" x="439.2" y="410.4" textLength="183" clip-path="url(#terminal-2811199383-line-16)">devstral-latest</text><text class="terminal-2811199383-r1" x="622.2" y="410.4" textLength="256.2" clip-path="url(#terminal-2811199383-line-16)">&#160;·&#160;[Subscription]&#160;Pro</text><text class="terminal-2811199383-r1" x="1464" y="410.4" textLength="12.2" clip-path="url(#terminal-2811199383-line-16)">
</text><text class="terminal-2811199383-r1" x="0" y="434.8" textLength="134.2" clip-path="url(#terminal-2811199383-line-17)">&#160;⢸⠸⣀⡔⢉⠱⣃⡢⣂⡣</text><text class="terminal-2811199383-r1" x="170.8" y="434.8" textLength="414.8" clip-path="url(#terminal-2811199383-line-17)">1&#160;model&#160;·&#160;2&#160;MCP&#160;servers&#160;·&#160;0&#160;skills</text><text class="terminal-2811199383-r1" x="1464" y="434.8" textLength="12.2" clip-path="url(#terminal-2811199383-line-17)">
</text><text class="terminal-2811199383-r1" x="0" y="459.2" textLength="134.2" clip-path="url(#terminal-2811199383-line-18)">&#160;&#160;⠉⠒⠣⠤⠵⠤⠬⠮⠆</text><text class="terminal-2811199383-r1" x="170.8" y="459.2" textLength="61" clip-path="url(#terminal-2811199383-line-18)">Type&#160;</text><text class="terminal-2811199383-r3" x="231.8" y="459.2" textLength="61" clip-path="url(#terminal-2811199383-line-18)">/help</text><text class="terminal-2811199383-r1" x="292.8" y="459.2" textLength="256.2" clip-path="url(#terminal-2811199383-line-18)">&#160;for&#160;more&#160;information</text><text class="terminal-2811199383-r1" x="1464" y="459.2" textLength="12.2" clip-path="url(#terminal-2811199383-line-18)">
</text><text class="terminal-2811199383-r1" x="1464" y="483.6" textLength="12.2" clip-path="url(#terminal-2811199383-line-19)">
</text><text class="terminal-2811199383-r1" x="1464" y="508" textLength="12.2" clip-path="url(#terminal-2811199383-line-20)">
</text><text class="terminal-2811199383-r4" x="0" y="532.4" textLength="12.2" clip-path="url(#terminal-2811199383-line-21)"></text><text class="terminal-2811199383-r2" x="24.4" y="532.4" textLength="48.8" clip-path="url(#terminal-2811199383-line-21)">/mcp</text><text class="terminal-2811199383-r1" x="1464" y="532.4" textLength="12.2" clip-path="url(#terminal-2811199383-line-21)">
</text><text class="terminal-2811199383-r5" x="24.4" y="556.8" textLength="12.2" clip-path="url(#terminal-2811199383-line-22)"></text><text class="terminal-2811199383-r1" x="48.8" y="556.8" textLength="256.2" clip-path="url(#terminal-2811199383-line-22)">MCP&#160;servers&#160;opened...</text><text class="terminal-2811199383-r1" x="1464" y="556.8" textLength="12.2" clip-path="url(#terminal-2811199383-line-22)">
</text><text class="terminal-2811199383-r1" x="1464" y="581.2" textLength="12.2" clip-path="url(#terminal-2811199383-line-23)">
</text><text class="terminal-2811199383-r1" x="1464" y="605.6" textLength="12.2" clip-path="url(#terminal-2811199383-line-24)">
</text><text class="terminal-2811199383-r5" x="0" y="630" textLength="1464" clip-path="url(#terminal-2811199383-line-25)">┌──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐</text><text class="terminal-2811199383-r1" x="1464" y="630" textLength="12.2" clip-path="url(#terminal-2811199383-line-25)">
</text><text class="terminal-2811199383-r5" x="0" y="654.4" textLength="12.2" clip-path="url(#terminal-2811199383-line-26)"></text><text class="terminal-2811199383-r6" x="24.4" y="654.4" textLength="134.2" clip-path="url(#terminal-2811199383-line-26)">MCP&#160;Servers</text><text class="terminal-2811199383-r5" x="1451.8" y="654.4" textLength="12.2" clip-path="url(#terminal-2811199383-line-26)"></text><text class="terminal-2811199383-r1" x="1464" y="654.4" textLength="12.2" clip-path="url(#terminal-2811199383-line-26)">
</text><text class="terminal-2811199383-r5" x="0" y="678.8" textLength="12.2" clip-path="url(#terminal-2811199383-line-27)"></text><text class="terminal-2811199383-r5" x="1451.8" y="678.8" textLength="12.2" clip-path="url(#terminal-2811199383-line-27)"></text><text class="terminal-2811199383-r1" x="1464" y="678.8" textLength="12.2" clip-path="url(#terminal-2811199383-line-27)">
</text><text class="terminal-2811199383-r5" x="0" y="703.2" textLength="12.2" clip-path="url(#terminal-2811199383-line-28)"></text><text class="terminal-2811199383-r7" x="36.6" y="703.2" textLength="207.4" clip-path="url(#terminal-2811199383-line-28)">Local&#160;MCP&#160;Servers</text><text class="terminal-2811199383-r5" x="1451.8" y="703.2" textLength="12.2" clip-path="url(#terminal-2811199383-line-28)"></text><text class="terminal-2811199383-r1" x="1464" y="703.2" textLength="12.2" clip-path="url(#terminal-2811199383-line-28)">
</text><text class="terminal-2811199383-r5" x="0" y="727.6" textLength="12.2" clip-path="url(#terminal-2811199383-line-29)"></text><text class="terminal-2811199383-r7" x="36.6" y="727.6" textLength="183" clip-path="url(#terminal-2811199383-line-29)">&#160;&#160;filesystem&#160;&#160;&#160;</text><text class="terminal-2811199383-r8" x="219.6" y="727.6" textLength="109.8" clip-path="url(#terminal-2811199383-line-29)">&#160;&#160;[stdio]</text><text class="terminal-2811199383-r8" x="329.4" y="727.6" textLength="97.6" clip-path="url(#terminal-2811199383-line-29)">&#160;&#160;1&#160;tool</text><text class="terminal-2811199383-r5" x="1451.8" y="727.6" textLength="12.2" clip-path="url(#terminal-2811199383-line-29)"></text><text class="terminal-2811199383-r1" x="1464" y="727.6" textLength="12.2" clip-path="url(#terminal-2811199383-line-29)">
</text><text class="terminal-2811199383-r5" x="0" y="752" textLength="12.2" clip-path="url(#terminal-2811199383-line-30)"></text><text class="terminal-2811199383-r1" x="36.6" y="752" textLength="183" clip-path="url(#terminal-2811199383-line-30)">&#160;&#160;broken-server</text><text class="terminal-2811199383-r9" x="219.6" y="752" textLength="109.8" clip-path="url(#terminal-2811199383-line-30)">&#160;&#160;[stdio]</text><text class="terminal-2811199383-r9" x="329.4" y="752" textLength="122" clip-path="url(#terminal-2811199383-line-30)">&#160;&#160;no&#160;tools</text><text class="terminal-2811199383-r5" x="1451.8" y="752" textLength="12.2" clip-path="url(#terminal-2811199383-line-30)"></text><text class="terminal-2811199383-r1" x="1464" y="752" textLength="12.2" clip-path="url(#terminal-2811199383-line-30)">
</text><text class="terminal-2811199383-r5" x="0" y="776.4" textLength="12.2" clip-path="url(#terminal-2811199383-line-31)"></text><text class="terminal-2811199383-r1" x="36.6" y="776.4" textLength="183" clip-path="url(#terminal-2811199383-line-31)">&#160;&#160;search&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text class="terminal-2811199383-r9" x="219.6" y="776.4" textLength="109.8" clip-path="url(#terminal-2811199383-line-31)">&#160;&#160;[http]&#160;</text><text class="terminal-2811199383-r9" x="329.4" y="776.4" textLength="97.6" clip-path="url(#terminal-2811199383-line-31)">&#160;&#160;1&#160;tool</text><text class="terminal-2811199383-r5" x="1451.8" y="776.4" textLength="12.2" clip-path="url(#terminal-2811199383-line-31)"></text><text class="terminal-2811199383-r1" x="1464" y="776.4" textLength="12.2" clip-path="url(#terminal-2811199383-line-31)">
</text><text class="terminal-2811199383-r5" x="0" y="800.8" textLength="12.2" clip-path="url(#terminal-2811199383-line-32)"></text><text class="terminal-2811199383-r5" x="1451.8" y="800.8" textLength="12.2" clip-path="url(#terminal-2811199383-line-32)"></text><text class="terminal-2811199383-r1" x="1464" y="800.8" textLength="12.2" clip-path="url(#terminal-2811199383-line-32)">
</text><text class="terminal-2811199383-r5" x="0" y="825.2" textLength="12.2" clip-path="url(#terminal-2811199383-line-33)"></text><text class="terminal-2811199383-r5" x="24.4" y="825.2" textLength="622.2" clip-path="url(#terminal-2811199383-line-33)">↑↓&#160;Navigate&#160;&#160;Enter&#160;Show&#160;tools&#160;&#160;R&#160;Refresh&#160;&#160;Esc&#160;Close</text><text class="terminal-2811199383-r5" x="1451.8" y="825.2" textLength="12.2" clip-path="url(#terminal-2811199383-line-33)"></text><text class="terminal-2811199383-r1" x="1464" y="825.2" textLength="12.2" clip-path="url(#terminal-2811199383-line-33)">
</text><text class="terminal-2811199383-r5" x="0" y="849.6" textLength="1464" clip-path="url(#terminal-2811199383-line-34)">└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘</text><text class="terminal-2811199383-r1" x="1464" y="849.6" textLength="12.2" clip-path="url(#terminal-2811199383-line-34)">
</text><text class="terminal-2811199383-r5" x="0" y="874" textLength="158.6" clip-path="url(#terminal-2811199383-line-35)">/test/workdir</text><text class="terminal-2811199383-r5" x="1256.6" y="874" textLength="207.4" clip-path="url(#terminal-2811199383-line-35)">0%&#160;of&#160;200k&#160;tokens</text>
<g class="terminal-matrix">
<text class="terminal-r1" x="1464" y="20" textLength="12.2" clip-path="url(#terminal-line-0)">
</text><text class="terminal-r1" x="1464" y="44.4" textLength="12.2" clip-path="url(#terminal-line-1)">
</text><text class="terminal-r1" x="1464" y="68.8" textLength="12.2" clip-path="url(#terminal-line-2)">
</text><text class="terminal-r1" x="1464" y="93.2" textLength="12.2" clip-path="url(#terminal-line-3)">
</text><text class="terminal-r1" x="1464" y="117.6" textLength="12.2" clip-path="url(#terminal-line-4)">
</text><text class="terminal-r1" x="1464" y="142" textLength="12.2" clip-path="url(#terminal-line-5)">
</text><text class="terminal-r1" x="1464" y="166.4" textLength="12.2" clip-path="url(#terminal-line-6)">
</text><text class="terminal-r1" x="1464" y="190.8" textLength="12.2" clip-path="url(#terminal-line-7)">
</text><text class="terminal-r1" x="1464" y="215.2" textLength="12.2" clip-path="url(#terminal-line-8)">
</text><text class="terminal-r1" x="1464" y="239.6" textLength="12.2" clip-path="url(#terminal-line-9)">
</text><text class="terminal-r1" x="1464" y="264" textLength="12.2" clip-path="url(#terminal-line-10)">
</text><text class="terminal-r1" x="1464" y="288.4" textLength="12.2" clip-path="url(#terminal-line-11)">
</text><text class="terminal-r1" x="1464" y="312.8" textLength="12.2" clip-path="url(#terminal-line-12)">
</text><text class="terminal-r1" x="1464" y="337.2" textLength="12.2" clip-path="url(#terminal-line-13)">
</text><text class="terminal-r1" x="1464" y="361.6" textLength="12.2" clip-path="url(#terminal-line-14)">
</text><text class="terminal-r1" x="1464" y="386" textLength="12.2" clip-path="url(#terminal-line-15)">
</text><text class="terminal-r1" x="0" y="410.4" textLength="134.2" clip-path="url(#terminal-line-16)">&#160;&#160;⡠⣒⠄&#160;&#160;⡔⢄⠔⡄</text><text class="terminal-r2" x="170.8" y="410.4" textLength="146.4" clip-path="url(#terminal-line-16)">Mistral&#160;Vibe</text><text class="terminal-r1" x="317.2" y="410.4" textLength="122" clip-path="url(#terminal-line-16)">&#160;v0.0.0&#160;·&#160;</text><text class="terminal-r3" x="439.2" y="410.4" textLength="244" clip-path="url(#terminal-line-16)">devstral-latest[off]</text><text class="terminal-r1" x="683.2" y="410.4" textLength="256.2" clip-path="url(#terminal-line-16)">&#160;·&#160;[Subscription]&#160;Pro</text><text class="terminal-r1" x="1464" y="410.4" textLength="12.2" clip-path="url(#terminal-line-16)">
</text><text class="terminal-r1" x="0" y="434.8" textLength="134.2" clip-path="url(#terminal-line-17)">&#160;⢸⠸⣀⡔⢉⠱⣃⡢⣂⡣</text><text class="terminal-r1" x="170.8" y="434.8" textLength="414.8" clip-path="url(#terminal-line-17)">1&#160;model&#160;·&#160;2&#160;MCP&#160;servers&#160;·&#160;0&#160;skills</text><text class="terminal-r1" x="1464" y="434.8" textLength="12.2" clip-path="url(#terminal-line-17)">
</text><text class="terminal-r1" x="0" y="459.2" textLength="134.2" clip-path="url(#terminal-line-18)">&#160;&#160;⠉⠒⠣⠤⠵⠤⠬⠮⠆</text><text class="terminal-r1" x="170.8" y="459.2" textLength="61" clip-path="url(#terminal-line-18)">Type&#160;</text><text class="terminal-r3" x="231.8" y="459.2" textLength="61" clip-path="url(#terminal-line-18)">/help</text><text class="terminal-r1" x="292.8" y="459.2" textLength="256.2" clip-path="url(#terminal-line-18)">&#160;for&#160;more&#160;information</text><text class="terminal-r1" x="1464" y="459.2" textLength="12.2" clip-path="url(#terminal-line-18)">
</text><text class="terminal-r1" x="1464" y="483.6" textLength="12.2" clip-path="url(#terminal-line-19)">
</text><text class="terminal-r1" x="1464" y="508" textLength="12.2" clip-path="url(#terminal-line-20)">
</text><text class="terminal-r4" x="0" y="532.4" textLength="12.2" clip-path="url(#terminal-line-21)"></text><text class="terminal-r2" x="24.4" y="532.4" textLength="48.8" clip-path="url(#terminal-line-21)">/mcp</text><text class="terminal-r1" x="1464" y="532.4" textLength="12.2" clip-path="url(#terminal-line-21)">
</text><text class="terminal-r5" x="24.4" y="556.8" textLength="12.2" clip-path="url(#terminal-line-22)"></text><text class="terminal-r1" x="48.8" y="556.8" textLength="256.2" clip-path="url(#terminal-line-22)">MCP&#160;servers&#160;opened...</text><text class="terminal-r1" x="1464" y="556.8" textLength="12.2" clip-path="url(#terminal-line-22)">
</text><text class="terminal-r1" x="1464" y="581.2" textLength="12.2" clip-path="url(#terminal-line-23)">
</text><text class="terminal-r1" x="1464" y="605.6" textLength="12.2" clip-path="url(#terminal-line-24)">
</text><text class="terminal-r5" x="0" y="630" textLength="1464" clip-path="url(#terminal-line-25)">┌──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐</text><text class="terminal-r1" x="1464" y="630" textLength="12.2" clip-path="url(#terminal-line-25)">
</text><text class="terminal-r5" x="0" y="654.4" textLength="12.2" clip-path="url(#terminal-line-26)"></text><text class="terminal-r6" x="24.4" y="654.4" textLength="134.2" clip-path="url(#terminal-line-26)">MCP&#160;Servers</text><text class="terminal-r5" x="1451.8" y="654.4" textLength="12.2" clip-path="url(#terminal-line-26)"></text><text class="terminal-r1" x="1464" y="654.4" textLength="12.2" clip-path="url(#terminal-line-26)">
</text><text class="terminal-r5" x="0" y="678.8" textLength="12.2" clip-path="url(#terminal-line-27)"></text><text class="terminal-r5" x="1451.8" y="678.8" textLength="12.2" clip-path="url(#terminal-line-27)"></text><text class="terminal-r1" x="1464" y="678.8" textLength="12.2" clip-path="url(#terminal-line-27)">
</text><text class="terminal-r5" x="0" y="703.2" textLength="12.2" clip-path="url(#terminal-line-28)"></text><text class="terminal-r7" x="36.6" y="703.2" textLength="207.4" clip-path="url(#terminal-line-28)">Local&#160;MCP&#160;Servers</text><text class="terminal-r5" x="1451.8" y="703.2" textLength="12.2" clip-path="url(#terminal-line-28)"></text><text class="terminal-r1" x="1464" y="703.2" textLength="12.2" clip-path="url(#terminal-line-28)">
</text><text class="terminal-r5" x="0" y="727.6" textLength="12.2" clip-path="url(#terminal-line-29)"></text><text class="terminal-r7" x="36.6" y="727.6" textLength="183" clip-path="url(#terminal-line-29)">&#160;&#160;filesystem&#160;&#160;&#160;</text><text class="terminal-r8" x="219.6" y="727.6" textLength="109.8" clip-path="url(#terminal-line-29)">&#160;&#160;[stdio]</text><text class="terminal-r8" x="329.4" y="727.6" textLength="97.6" clip-path="url(#terminal-line-29)">&#160;&#160;1&#160;tool</text><text class="terminal-r5" x="1451.8" y="727.6" textLength="12.2" clip-path="url(#terminal-line-29)"></text><text class="terminal-r1" x="1464" y="727.6" textLength="12.2" clip-path="url(#terminal-line-29)">
</text><text class="terminal-r5" x="0" y="752" textLength="12.2" clip-path="url(#terminal-line-30)"></text><text class="terminal-r1" x="36.6" y="752" textLength="183" clip-path="url(#terminal-line-30)">&#160;&#160;broken-server</text><text class="terminal-r9" x="219.6" y="752" textLength="109.8" clip-path="url(#terminal-line-30)">&#160;&#160;[stdio]</text><text class="terminal-r9" x="329.4" y="752" textLength="122" clip-path="url(#terminal-line-30)">&#160;&#160;no&#160;tools</text><text class="terminal-r5" x="1451.8" y="752" textLength="12.2" clip-path="url(#terminal-line-30)"></text><text class="terminal-r1" x="1464" y="752" textLength="12.2" clip-path="url(#terminal-line-30)">
</text><text class="terminal-r5" x="0" y="776.4" textLength="12.2" clip-path="url(#terminal-line-31)"></text><text class="terminal-r1" x="36.6" y="776.4" textLength="183" clip-path="url(#terminal-line-31)">&#160;&#160;search&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text class="terminal-r9" x="219.6" y="776.4" textLength="109.8" clip-path="url(#terminal-line-31)">&#160;&#160;[http]&#160;</text><text class="terminal-r9" x="329.4" y="776.4" textLength="97.6" clip-path="url(#terminal-line-31)">&#160;&#160;1&#160;tool</text><text class="terminal-r5" x="1451.8" y="776.4" textLength="12.2" clip-path="url(#terminal-line-31)"></text><text class="terminal-r1" x="1464" y="776.4" textLength="12.2" clip-path="url(#terminal-line-31)">
</text><text class="terminal-r5" x="0" y="800.8" textLength="12.2" clip-path="url(#terminal-line-32)"></text><text class="terminal-r5" x="1451.8" y="800.8" textLength="12.2" clip-path="url(#terminal-line-32)"></text><text class="terminal-r1" x="1464" y="800.8" textLength="12.2" clip-path="url(#terminal-line-32)">
</text><text class="terminal-r5" x="0" y="825.2" textLength="12.2" clip-path="url(#terminal-line-33)"></text><text class="terminal-r5" x="24.4" y="825.2" textLength="878.4" clip-path="url(#terminal-line-33)">↑↓&#160;Navigate&#160;&#160;Enter&#160;Show&#160;tools&#160;&#160;D&#160;Disable&#160;&#160;E&#160;Enable&#160;&#160;R&#160;Refresh&#160;&#160;Esc&#160;Close</text><text class="terminal-r5" x="1451.8" y="825.2" textLength="12.2" clip-path="url(#terminal-line-33)"></text><text class="terminal-r1" x="1464" y="825.2" textLength="12.2" clip-path="url(#terminal-line-33)">
</text><text class="terminal-r5" x="0" y="849.6" textLength="1464" clip-path="url(#terminal-line-34)">└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘</text><text class="terminal-r1" x="1464" y="849.6" textLength="12.2" clip-path="url(#terminal-line-34)">
</text><text class="terminal-r5" x="0" y="874" textLength="158.6" clip-path="url(#terminal-line-35)">/test/workdir</text><text class="terminal-r5" x="1256.6" y="874" textLength="207.4" clip-path="url(#terminal-line-35)">0%&#160;of&#160;200k&#160;tokens</text>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 19 KiB

After

Width:  |  Height:  |  Size: 17 KiB

Before After
Before After

View file

@ -19,188 +19,188 @@
font-weight: 700;
}
.terminal-6499786123-matrix {
.terminal-matrix {
font-family: Fira Code, monospace;
font-size: 20px;
line-height: 24.4px;
font-variant-east-asian: full-width;
}
.terminal-6499786123-title {
.terminal-title {
font-size: 18px;
font-weight: bold;
font-family: arial;
}
.terminal-6499786123-r1 { fill: #c5c8c6 }
.terminal-6499786123-r2 { fill: #ff8205;font-weight: bold }
.terminal-6499786123-r3 { fill: #68a0b3 }
.terminal-6499786123-r4 { fill: #ff8205 }
.terminal-6499786123-r5 { fill: #9a9b99 }
.terminal-6499786123-r6 { fill: #608ab1;font-weight: bold }
.terminal-6499786123-r7 { fill: #c5c8c6;font-weight: bold }
.terminal-6499786123-r8 { fill: #9cafbd;font-weight: bold }
.terminal-6499786123-r9 { fill: #868887 }
.terminal-6499786123-r10 { fill: #98a84b }
.terminal-r1 { fill: #c5c8c6 }
.terminal-r2 { fill: #ff8205;font-weight: bold }
.terminal-r3 { fill: #68a0b3 }
.terminal-r4 { fill: #ff8205 }
.terminal-r5 { fill: #9a9b99 }
.terminal-r6 { fill: #608ab1;font-weight: bold }
.terminal-r7 { fill: #c5c8c6;font-weight: bold }
.terminal-r8 { fill: #9cafbd;font-weight: bold }
.terminal-r9 { fill: #868887 }
.terminal-r10 { fill: #98a84b }
</style>
<defs>
<clipPath id="terminal-6499786123-clip-terminal">
<clipPath id="terminal-clip-terminal">
<rect x="0" y="0" width="1463.0" height="877.4" />
</clipPath>
<clipPath id="terminal-6499786123-line-0">
<clipPath id="terminal-line-0">
<rect x="0" y="1.5" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-6499786123-line-1">
<clipPath id="terminal-line-1">
<rect x="0" y="25.9" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-6499786123-line-2">
<clipPath id="terminal-line-2">
<rect x="0" y="50.3" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-6499786123-line-3">
<clipPath id="terminal-line-3">
<rect x="0" y="74.7" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-6499786123-line-4">
<clipPath id="terminal-line-4">
<rect x="0" y="99.1" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-6499786123-line-5">
<clipPath id="terminal-line-5">
<rect x="0" y="123.5" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-6499786123-line-6">
<clipPath id="terminal-line-6">
<rect x="0" y="147.9" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-6499786123-line-7">
<clipPath id="terminal-line-7">
<rect x="0" y="172.3" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-6499786123-line-8">
<clipPath id="terminal-line-8">
<rect x="0" y="196.7" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-6499786123-line-9">
<clipPath id="terminal-line-9">
<rect x="0" y="221.1" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-6499786123-line-10">
<clipPath id="terminal-line-10">
<rect x="0" y="245.5" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-6499786123-line-11">
<clipPath id="terminal-line-11">
<rect x="0" y="269.9" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-6499786123-line-12">
<clipPath id="terminal-line-12">
<rect x="0" y="294.3" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-6499786123-line-13">
<clipPath id="terminal-line-13">
<rect x="0" y="318.7" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-6499786123-line-14">
<clipPath id="terminal-line-14">
<rect x="0" y="343.1" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-6499786123-line-15">
<clipPath id="terminal-line-15">
<rect x="0" y="367.5" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-6499786123-line-16">
<clipPath id="terminal-line-16">
<rect x="0" y="391.9" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-6499786123-line-17">
<clipPath id="terminal-line-17">
<rect x="0" y="416.3" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-6499786123-line-18">
<clipPath id="terminal-line-18">
<rect x="0" y="440.7" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-6499786123-line-19">
<clipPath id="terminal-line-19">
<rect x="0" y="465.1" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-6499786123-line-20">
<clipPath id="terminal-line-20">
<rect x="0" y="489.5" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-6499786123-line-21">
<clipPath id="terminal-line-21">
<rect x="0" y="513.9" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-6499786123-line-22">
<clipPath id="terminal-line-22">
<rect x="0" y="538.3" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-6499786123-line-23">
<clipPath id="terminal-line-23">
<rect x="0" y="562.7" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-6499786123-line-24">
<clipPath id="terminal-line-24">
<rect x="0" y="587.1" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-6499786123-line-25">
<clipPath id="terminal-line-25">
<rect x="0" y="611.5" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-6499786123-line-26">
<clipPath id="terminal-line-26">
<rect x="0" y="635.9" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-6499786123-line-27">
<clipPath id="terminal-line-27">
<rect x="0" y="660.3" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-6499786123-line-28">
<clipPath id="terminal-line-28">
<rect x="0" y="684.7" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-6499786123-line-29">
<clipPath id="terminal-line-29">
<rect x="0" y="709.1" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-6499786123-line-30">
<clipPath id="terminal-line-30">
<rect x="0" y="733.5" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-6499786123-line-31">
<clipPath id="terminal-line-31">
<rect x="0" y="757.9" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-6499786123-line-32">
<clipPath id="terminal-line-32">
<rect x="0" y="782.3" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-6499786123-line-33">
<clipPath id="terminal-line-33">
<rect x="0" y="806.7" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-6499786123-line-34">
<clipPath id="terminal-line-34">
<rect x="0" y="831.1" width="1464" height="24.65"/>
</clipPath>
</defs>
<rect fill="#292929" stroke="rgba(255,255,255,0.35)" stroke-width="1" x="1" y="1" width="1480" height="926.4" rx="8"/><text class="terminal-6499786123-title" fill="#c5c8c6" text-anchor="middle" x="740" y="27">SnapshotTestAppWithConnectors</text>
<rect fill="#292929" stroke="rgba(255,255,255,0.35)" stroke-width="1" x="1" y="1" width="1480" height="926.4" rx="8"/><text class="terminal-title" fill="#c5c8c6" text-anchor="middle" x="740" y="27">SnapshotTestAppWithConnectors</text>
<g transform="translate(26,22)">
<circle cx="0" cy="0" r="7" fill="#ff5f57"/>
<circle cx="22" cy="0" r="7" fill="#febc2e"/>
<circle cx="44" cy="0" r="7" fill="#28c840"/>
</g>
<g transform="translate(9, 41)" clip-path="url(#terminal-6499786123-clip-terminal)">
<g transform="translate(9, 41)" clip-path="url(#terminal-clip-terminal)">
<rect fill="#608ab1" x="36.6" y="660.3" width="146.4" height="24.65" shape-rendering="crispEdges"/><rect fill="#608ab1" x="183" y="660.3" width="109.8" height="24.65" shape-rendering="crispEdges"/><rect fill="#608ab1" x="292.8" y="660.3" width="97.6" height="24.65" shape-rendering="crispEdges"/><rect fill="#608ab1" x="390.4" y="660.3" width="1037" height="24.65" shape-rendering="crispEdges"/>
<g class="terminal-6499786123-matrix">
<text class="terminal-6499786123-r1" x="1464" y="20" textLength="12.2" clip-path="url(#terminal-6499786123-line-0)">
</text><text class="terminal-6499786123-r1" x="1464" y="44.4" textLength="12.2" clip-path="url(#terminal-6499786123-line-1)">
</text><text class="terminal-6499786123-r1" x="1464" y="68.8" textLength="12.2" clip-path="url(#terminal-6499786123-line-2)">
</text><text class="terminal-6499786123-r1" x="1464" y="93.2" textLength="12.2" clip-path="url(#terminal-6499786123-line-3)">
</text><text class="terminal-6499786123-r1" x="1464" y="117.6" textLength="12.2" clip-path="url(#terminal-6499786123-line-4)">
</text><text class="terminal-6499786123-r1" x="1464" y="142" textLength="12.2" clip-path="url(#terminal-6499786123-line-5)">
</text><text class="terminal-6499786123-r1" x="1464" y="166.4" textLength="12.2" clip-path="url(#terminal-6499786123-line-6)">
</text><text class="terminal-6499786123-r1" x="1464" y="190.8" textLength="12.2" clip-path="url(#terminal-6499786123-line-7)">
</text><text class="terminal-6499786123-r1" x="1464" y="215.2" textLength="12.2" clip-path="url(#terminal-6499786123-line-8)">
</text><text class="terminal-6499786123-r1" x="1464" y="239.6" textLength="12.2" clip-path="url(#terminal-6499786123-line-9)">
</text><text class="terminal-6499786123-r1" x="1464" y="264" textLength="12.2" clip-path="url(#terminal-6499786123-line-10)">
</text><text class="terminal-6499786123-r1" x="1464" y="288.4" textLength="12.2" clip-path="url(#terminal-6499786123-line-11)">
</text><text class="terminal-6499786123-r1" x="1464" y="312.8" textLength="12.2" clip-path="url(#terminal-6499786123-line-12)">
</text><text class="terminal-6499786123-r1" x="1464" y="337.2" textLength="12.2" clip-path="url(#terminal-6499786123-line-13)">
</text><text class="terminal-6499786123-r1" x="0" y="361.6" textLength="134.2" clip-path="url(#terminal-6499786123-line-14)">&#160;&#160;⡠⣒⠄&#160;&#160;⡔⢄⠔⡄</text><text class="terminal-6499786123-r2" x="170.8" y="361.6" textLength="146.4" clip-path="url(#terminal-6499786123-line-14)">Mistral&#160;Vibe</text><text class="terminal-6499786123-r1" x="317.2" y="361.6" textLength="122" clip-path="url(#terminal-6499786123-line-14)">&#160;v0.0.0&#160;·&#160;</text><text class="terminal-6499786123-r3" x="439.2" y="361.6" textLength="183" clip-path="url(#terminal-6499786123-line-14)">devstral-latest</text><text class="terminal-6499786123-r1" x="622.2" y="361.6" textLength="256.2" clip-path="url(#terminal-6499786123-line-14)">&#160;·&#160;[Subscription]&#160;Pro</text><text class="terminal-6499786123-r1" x="1464" y="361.6" textLength="12.2" clip-path="url(#terminal-6499786123-line-14)">
</text><text class="terminal-6499786123-r1" x="0" y="386" textLength="134.2" clip-path="url(#terminal-6499786123-line-15)">&#160;⢸⠸⣀⡔⢉⠱⣃⡢⣂⡣</text><text class="terminal-6499786123-r1" x="170.8" y="386" textLength="585.6" clip-path="url(#terminal-6499786123-line-15)">1&#160;model&#160;·&#160;2&#160;connectors&#160;·&#160;1&#160;MCP&#160;server&#160;·&#160;0&#160;skills</text><text class="terminal-6499786123-r1" x="1464" y="386" textLength="12.2" clip-path="url(#terminal-6499786123-line-15)">
</text><text class="terminal-6499786123-r1" x="0" y="410.4" textLength="134.2" clip-path="url(#terminal-6499786123-line-16)">&#160;&#160;⠉⠒⠣⠤⠵⠤⠬⠮⠆</text><text class="terminal-6499786123-r1" x="170.8" y="410.4" textLength="61" clip-path="url(#terminal-6499786123-line-16)">Type&#160;</text><text class="terminal-6499786123-r3" x="231.8" y="410.4" textLength="61" clip-path="url(#terminal-6499786123-line-16)">/help</text><text class="terminal-6499786123-r1" x="292.8" y="410.4" textLength="256.2" clip-path="url(#terminal-6499786123-line-16)">&#160;for&#160;more&#160;information</text><text class="terminal-6499786123-r1" x="1464" y="410.4" textLength="12.2" clip-path="url(#terminal-6499786123-line-16)">
</text><text class="terminal-6499786123-r1" x="1464" y="434.8" textLength="12.2" clip-path="url(#terminal-6499786123-line-17)">
</text><text class="terminal-6499786123-r1" x="1464" y="459.2" textLength="12.2" clip-path="url(#terminal-6499786123-line-18)">
</text><text class="terminal-6499786123-r4" x="0" y="483.6" textLength="12.2" clip-path="url(#terminal-6499786123-line-19)"></text><text class="terminal-6499786123-r2" x="24.4" y="483.6" textLength="48.8" clip-path="url(#terminal-6499786123-line-19)">/mcp</text><text class="terminal-6499786123-r1" x="1464" y="483.6" textLength="12.2" clip-path="url(#terminal-6499786123-line-19)">
</text><text class="terminal-6499786123-r5" x="24.4" y="508" textLength="12.2" clip-path="url(#terminal-6499786123-line-20)"></text><text class="terminal-6499786123-r1" x="48.8" y="508" textLength="256.2" clip-path="url(#terminal-6499786123-line-20)">MCP&#160;servers&#160;opened...</text><text class="terminal-6499786123-r1" x="1464" y="508" textLength="12.2" clip-path="url(#terminal-6499786123-line-20)">
</text><text class="terminal-6499786123-r1" x="1464" y="532.4" textLength="12.2" clip-path="url(#terminal-6499786123-line-21)">
</text><text class="terminal-6499786123-r1" x="1464" y="556.8" textLength="12.2" clip-path="url(#terminal-6499786123-line-22)">
</text><text class="terminal-6499786123-r5" x="0" y="581.2" textLength="1464" clip-path="url(#terminal-6499786123-line-23)">┌──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐</text><text class="terminal-6499786123-r1" x="1464" y="581.2" textLength="12.2" clip-path="url(#terminal-6499786123-line-23)">
</text><text class="terminal-6499786123-r5" x="0" y="605.6" textLength="12.2" clip-path="url(#terminal-6499786123-line-24)"></text><text class="terminal-6499786123-r6" x="24.4" y="605.6" textLength="292.8" clip-path="url(#terminal-6499786123-line-24)">MCP&#160;Servers&#160;&amp;&#160;Connectors</text><text class="terminal-6499786123-r5" x="1451.8" y="605.6" textLength="12.2" clip-path="url(#terminal-6499786123-line-24)"></text><text class="terminal-6499786123-r1" x="1464" y="605.6" textLength="12.2" clip-path="url(#terminal-6499786123-line-24)">
</text><text class="terminal-6499786123-r5" x="0" y="630" textLength="12.2" clip-path="url(#terminal-6499786123-line-25)"></text><text class="terminal-6499786123-r5" x="1451.8" y="630" textLength="12.2" clip-path="url(#terminal-6499786123-line-25)"></text><text class="terminal-6499786123-r1" x="1464" y="630" textLength="12.2" clip-path="url(#terminal-6499786123-line-25)">
</text><text class="terminal-6499786123-r5" x="0" y="654.4" textLength="12.2" clip-path="url(#terminal-6499786123-line-26)"></text><text class="terminal-6499786123-r7" x="36.6" y="654.4" textLength="207.4" clip-path="url(#terminal-6499786123-line-26)">Local&#160;MCP&#160;Servers</text><text class="terminal-6499786123-r5" x="1451.8" y="654.4" textLength="12.2" clip-path="url(#terminal-6499786123-line-26)"></text><text class="terminal-6499786123-r1" x="1464" y="654.4" textLength="12.2" clip-path="url(#terminal-6499786123-line-26)">
</text><text class="terminal-6499786123-r5" x="0" y="678.8" textLength="12.2" clip-path="url(#terminal-6499786123-line-27)"></text><text class="terminal-6499786123-r7" x="36.6" y="678.8" textLength="146.4" clip-path="url(#terminal-6499786123-line-27)">&#160;&#160;filesystem</text><text class="terminal-6499786123-r8" x="183" y="678.8" textLength="109.8" clip-path="url(#terminal-6499786123-line-27)">&#160;&#160;[stdio]</text><text class="terminal-6499786123-r8" x="292.8" y="678.8" textLength="97.6" clip-path="url(#terminal-6499786123-line-27)">&#160;&#160;1&#160;tool</text><text class="terminal-6499786123-r5" x="1451.8" y="678.8" textLength="12.2" clip-path="url(#terminal-6499786123-line-27)"></text><text class="terminal-6499786123-r1" x="1464" y="678.8" textLength="12.2" clip-path="url(#terminal-6499786123-line-27)">
</text><text class="terminal-6499786123-r5" x="0" y="703.2" textLength="12.2" clip-path="url(#terminal-6499786123-line-28)"></text><text class="terminal-6499786123-r5" x="1451.8" y="703.2" textLength="12.2" clip-path="url(#terminal-6499786123-line-28)"></text><text class="terminal-6499786123-r1" x="1464" y="703.2" textLength="12.2" clip-path="url(#terminal-6499786123-line-28)">
</text><text class="terminal-6499786123-r5" x="0" y="727.6" textLength="12.2" clip-path="url(#terminal-6499786123-line-29)"></text><text class="terminal-6499786123-r7" x="36.6" y="727.6" textLength="244" clip-path="url(#terminal-6499786123-line-29)">Workspace&#160;Connectors</text><text class="terminal-6499786123-r5" x="1451.8" y="727.6" textLength="12.2" clip-path="url(#terminal-6499786123-line-29)"></text><text class="terminal-6499786123-r1" x="1464" y="727.6" textLength="12.2" clip-path="url(#terminal-6499786123-line-29)">
</text><text class="terminal-6499786123-r5" x="0" y="752" textLength="12.2" clip-path="url(#terminal-6499786123-line-30)"></text><text class="terminal-6499786123-r1" x="36.6" y="752" textLength="85.4" clip-path="url(#terminal-6499786123-line-30)">&#160;&#160;gmail</text><text class="terminal-6499786123-r9" x="122" y="752" textLength="158.6" clip-path="url(#terminal-6499786123-line-30)">&#160;&#160;[connector]</text><text class="terminal-6499786123-r9" x="280.6" y="752" textLength="109.8" clip-path="url(#terminal-6499786123-line-30)">&#160;&#160;3&#160;tools</text><text class="terminal-6499786123-r10" x="414.8" y="752" textLength="12.2" clip-path="url(#terminal-6499786123-line-30)"></text><text class="terminal-6499786123-r9" x="427" y="752" textLength="122" clip-path="url(#terminal-6499786123-line-30)">&#160;connected</text><text class="terminal-6499786123-r5" x="1451.8" y="752" textLength="12.2" clip-path="url(#terminal-6499786123-line-30)"></text><text class="terminal-6499786123-r1" x="1464" y="752" textLength="12.2" clip-path="url(#terminal-6499786123-line-30)">
</text><text class="terminal-6499786123-r5" x="0" y="776.4" textLength="12.2" clip-path="url(#terminal-6499786123-line-31)"></text><text class="terminal-6499786123-r1" x="36.6" y="776.4" textLength="85.4" clip-path="url(#terminal-6499786123-line-31)">&#160;&#160;slack</text><text class="terminal-6499786123-r9" x="122" y="776.4" textLength="158.6" clip-path="url(#terminal-6499786123-line-31)">&#160;&#160;[connector]</text><text class="terminal-6499786123-r9" x="280.6" y="776.4" textLength="109.8" clip-path="url(#terminal-6499786123-line-31)">&#160;&#160;2&#160;tools</text><text class="terminal-6499786123-r10" x="414.8" y="776.4" textLength="12.2" clip-path="url(#terminal-6499786123-line-31)"></text><text class="terminal-6499786123-r9" x="427" y="776.4" textLength="122" clip-path="url(#terminal-6499786123-line-31)">&#160;connected</text><text class="terminal-6499786123-r5" x="1451.8" y="776.4" textLength="12.2" clip-path="url(#terminal-6499786123-line-31)"></text><text class="terminal-6499786123-r1" x="1464" y="776.4" textLength="12.2" clip-path="url(#terminal-6499786123-line-31)">
</text><text class="terminal-6499786123-r5" x="0" y="800.8" textLength="12.2" clip-path="url(#terminal-6499786123-line-32)"></text><text class="terminal-6499786123-r5" x="1451.8" y="800.8" textLength="12.2" clip-path="url(#terminal-6499786123-line-32)"></text><text class="terminal-6499786123-r1" x="1464" y="800.8" textLength="12.2" clip-path="url(#terminal-6499786123-line-32)">
</text><text class="terminal-6499786123-r5" x="0" y="825.2" textLength="12.2" clip-path="url(#terminal-6499786123-line-33)"></text><text class="terminal-6499786123-r5" x="24.4" y="825.2" textLength="622.2" clip-path="url(#terminal-6499786123-line-33)">↑↓&#160;Navigate&#160;&#160;Enter&#160;Show&#160;tools&#160;&#160;R&#160;Refresh&#160;&#160;Esc&#160;Close</text><text class="terminal-6499786123-r5" x="1451.8" y="825.2" textLength="12.2" clip-path="url(#terminal-6499786123-line-33)"></text><text class="terminal-6499786123-r1" x="1464" y="825.2" textLength="12.2" clip-path="url(#terminal-6499786123-line-33)">
</text><text class="terminal-6499786123-r5" x="0" y="849.6" textLength="1464" clip-path="url(#terminal-6499786123-line-34)">└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘</text><text class="terminal-6499786123-r1" x="1464" y="849.6" textLength="12.2" clip-path="url(#terminal-6499786123-line-34)">
</text><text class="terminal-6499786123-r5" x="0" y="874" textLength="158.6" clip-path="url(#terminal-6499786123-line-35)">/test/workdir</text><text class="terminal-6499786123-r5" x="1256.6" y="874" textLength="207.4" clip-path="url(#terminal-6499786123-line-35)">0%&#160;of&#160;200k&#160;tokens</text>
<g class="terminal-matrix">
<text class="terminal-r1" x="1464" y="20" textLength="12.2" clip-path="url(#terminal-line-0)">
</text><text class="terminal-r1" x="1464" y="44.4" textLength="12.2" clip-path="url(#terminal-line-1)">
</text><text class="terminal-r1" x="1464" y="68.8" textLength="12.2" clip-path="url(#terminal-line-2)">
</text><text class="terminal-r1" x="1464" y="93.2" textLength="12.2" clip-path="url(#terminal-line-3)">
</text><text class="terminal-r1" x="1464" y="117.6" textLength="12.2" clip-path="url(#terminal-line-4)">
</text><text class="terminal-r1" x="1464" y="142" textLength="12.2" clip-path="url(#terminal-line-5)">
</text><text class="terminal-r1" x="1464" y="166.4" textLength="12.2" clip-path="url(#terminal-line-6)">
</text><text class="terminal-r1" x="1464" y="190.8" textLength="12.2" clip-path="url(#terminal-line-7)">
</text><text class="terminal-r1" x="1464" y="215.2" textLength="12.2" clip-path="url(#terminal-line-8)">
</text><text class="terminal-r1" x="1464" y="239.6" textLength="12.2" clip-path="url(#terminal-line-9)">
</text><text class="terminal-r1" x="1464" y="264" textLength="12.2" clip-path="url(#terminal-line-10)">
</text><text class="terminal-r1" x="1464" y="288.4" textLength="12.2" clip-path="url(#terminal-line-11)">
</text><text class="terminal-r1" x="1464" y="312.8" textLength="12.2" clip-path="url(#terminal-line-12)">
</text><text class="terminal-r1" x="1464" y="337.2" textLength="12.2" clip-path="url(#terminal-line-13)">
</text><text class="terminal-r1" x="0" y="361.6" textLength="134.2" clip-path="url(#terminal-line-14)">&#160;&#160;⡠⣒⠄&#160;&#160;⡔⢄⠔⡄</text><text class="terminal-r2" x="170.8" y="361.6" textLength="146.4" clip-path="url(#terminal-line-14)">Mistral&#160;Vibe</text><text class="terminal-r1" x="317.2" y="361.6" textLength="122" clip-path="url(#terminal-line-14)">&#160;v0.0.0&#160;·&#160;</text><text class="terminal-r3" x="439.2" y="361.6" textLength="244" clip-path="url(#terminal-line-14)">devstral-latest[off]</text><text class="terminal-r1" x="683.2" y="361.6" textLength="256.2" clip-path="url(#terminal-line-14)">&#160;·&#160;[Subscription]&#160;Pro</text><text class="terminal-r1" x="1464" y="361.6" textLength="12.2" clip-path="url(#terminal-line-14)">
</text><text class="terminal-r1" x="0" y="386" textLength="134.2" clip-path="url(#terminal-line-15)">&#160;⢸⠸⣀⡔⢉⠱⣃⡢⣂⡣</text><text class="terminal-r1" x="170.8" y="386" textLength="585.6" clip-path="url(#terminal-line-15)">1&#160;model&#160;·&#160;2&#160;connectors&#160;·&#160;1&#160;MCP&#160;server&#160;·&#160;0&#160;skills</text><text class="terminal-r1" x="1464" y="386" textLength="12.2" clip-path="url(#terminal-line-15)">
</text><text class="terminal-r1" x="0" y="410.4" textLength="134.2" clip-path="url(#terminal-line-16)">&#160;&#160;⠉⠒⠣⠤⠵⠤⠬⠮⠆</text><text class="terminal-r1" x="170.8" y="410.4" textLength="61" clip-path="url(#terminal-line-16)">Type&#160;</text><text class="terminal-r3" x="231.8" y="410.4" textLength="61" clip-path="url(#terminal-line-16)">/help</text><text class="terminal-r1" x="292.8" y="410.4" textLength="256.2" clip-path="url(#terminal-line-16)">&#160;for&#160;more&#160;information</text><text class="terminal-r1" x="1464" y="410.4" textLength="12.2" clip-path="url(#terminal-line-16)">
</text><text class="terminal-r1" x="1464" y="434.8" textLength="12.2" clip-path="url(#terminal-line-17)">
</text><text class="terminal-r1" x="1464" y="459.2" textLength="12.2" clip-path="url(#terminal-line-18)">
</text><text class="terminal-r4" x="0" y="483.6" textLength="12.2" clip-path="url(#terminal-line-19)"></text><text class="terminal-r2" x="24.4" y="483.6" textLength="48.8" clip-path="url(#terminal-line-19)">/mcp</text><text class="terminal-r1" x="1464" y="483.6" textLength="12.2" clip-path="url(#terminal-line-19)">
</text><text class="terminal-r5" x="24.4" y="508" textLength="12.2" clip-path="url(#terminal-line-20)"></text><text class="terminal-r1" x="48.8" y="508" textLength="256.2" clip-path="url(#terminal-line-20)">MCP&#160;servers&#160;opened...</text><text class="terminal-r1" x="1464" y="508" textLength="12.2" clip-path="url(#terminal-line-20)">
</text><text class="terminal-r1" x="1464" y="532.4" textLength="12.2" clip-path="url(#terminal-line-21)">
</text><text class="terminal-r1" x="1464" y="556.8" textLength="12.2" clip-path="url(#terminal-line-22)">
</text><text class="terminal-r5" x="0" y="581.2" textLength="1464" clip-path="url(#terminal-line-23)">┌──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐</text><text class="terminal-r1" x="1464" y="581.2" textLength="12.2" clip-path="url(#terminal-line-23)">
</text><text class="terminal-r5" x="0" y="605.6" textLength="12.2" clip-path="url(#terminal-line-24)"></text><text class="terminal-r6" x="24.4" y="605.6" textLength="292.8" clip-path="url(#terminal-line-24)">MCP&#160;Servers&#160;&amp;&#160;Connectors</text><text class="terminal-r5" x="1451.8" y="605.6" textLength="12.2" clip-path="url(#terminal-line-24)"></text><text class="terminal-r1" x="1464" y="605.6" textLength="12.2" clip-path="url(#terminal-line-24)">
</text><text class="terminal-r5" x="0" y="630" textLength="12.2" clip-path="url(#terminal-line-25)"></text><text class="terminal-r5" x="1451.8" y="630" textLength="12.2" clip-path="url(#terminal-line-25)"></text><text class="terminal-r1" x="1464" y="630" textLength="12.2" clip-path="url(#terminal-line-25)">
</text><text class="terminal-r5" x="0" y="654.4" textLength="12.2" clip-path="url(#terminal-line-26)"></text><text class="terminal-r7" x="36.6" y="654.4" textLength="207.4" clip-path="url(#terminal-line-26)">Local&#160;MCP&#160;Servers</text><text class="terminal-r5" x="1451.8" y="654.4" textLength="12.2" clip-path="url(#terminal-line-26)"></text><text class="terminal-r1" x="1464" y="654.4" textLength="12.2" clip-path="url(#terminal-line-26)">
</text><text class="terminal-r5" x="0" y="678.8" textLength="12.2" clip-path="url(#terminal-line-27)"></text><text class="terminal-r7" x="36.6" y="678.8" textLength="146.4" clip-path="url(#terminal-line-27)">&#160;&#160;filesystem</text><text class="terminal-r8" x="183" y="678.8" textLength="109.8" clip-path="url(#terminal-line-27)">&#160;&#160;[stdio]</text><text class="terminal-r8" x="292.8" y="678.8" textLength="97.6" clip-path="url(#terminal-line-27)">&#160;&#160;1&#160;tool</text><text class="terminal-r5" x="1451.8" y="678.8" textLength="12.2" clip-path="url(#terminal-line-27)"></text><text class="terminal-r1" x="1464" y="678.8" textLength="12.2" clip-path="url(#terminal-line-27)">
</text><text class="terminal-r5" x="0" y="703.2" textLength="12.2" clip-path="url(#terminal-line-28)"></text><text class="terminal-r5" x="1451.8" y="703.2" textLength="12.2" clip-path="url(#terminal-line-28)"></text><text class="terminal-r1" x="1464" y="703.2" textLength="12.2" clip-path="url(#terminal-line-28)">
</text><text class="terminal-r5" x="0" y="727.6" textLength="12.2" clip-path="url(#terminal-line-29)"></text><text class="terminal-r7" x="36.6" y="727.6" textLength="244" clip-path="url(#terminal-line-29)">Workspace&#160;Connectors</text><text class="terminal-r5" x="1451.8" y="727.6" textLength="12.2" clip-path="url(#terminal-line-29)"></text><text class="terminal-r1" x="1464" y="727.6" textLength="12.2" clip-path="url(#terminal-line-29)">
</text><text class="terminal-r5" x="0" y="752" textLength="12.2" clip-path="url(#terminal-line-30)"></text><text class="terminal-r1" x="36.6" y="752" textLength="85.4" clip-path="url(#terminal-line-30)">&#160;&#160;gmail</text><text class="terminal-r9" x="122" y="752" textLength="158.6" clip-path="url(#terminal-line-30)">&#160;&#160;[connector]</text><text class="terminal-r9" x="280.6" y="752" textLength="109.8" clip-path="url(#terminal-line-30)">&#160;&#160;3&#160;tools</text><text class="terminal-r10" x="414.8" y="752" textLength="12.2" clip-path="url(#terminal-line-30)"></text><text class="terminal-r9" x="427" y="752" textLength="122" clip-path="url(#terminal-line-30)">&#160;connected</text><text class="terminal-r5" x="1451.8" y="752" textLength="12.2" clip-path="url(#terminal-line-30)"></text><text class="terminal-r1" x="1464" y="752" textLength="12.2" clip-path="url(#terminal-line-30)">
</text><text class="terminal-r5" x="0" y="776.4" textLength="12.2" clip-path="url(#terminal-line-31)"></text><text class="terminal-r1" x="36.6" y="776.4" textLength="85.4" clip-path="url(#terminal-line-31)">&#160;&#160;slack</text><text class="terminal-r9" x="122" y="776.4" textLength="158.6" clip-path="url(#terminal-line-31)">&#160;&#160;[connector]</text><text class="terminal-r9" x="280.6" y="776.4" textLength="109.8" clip-path="url(#terminal-line-31)">&#160;&#160;2&#160;tools</text><text class="terminal-r10" x="414.8" y="776.4" textLength="12.2" clip-path="url(#terminal-line-31)"></text><text class="terminal-r9" x="427" y="776.4" textLength="122" clip-path="url(#terminal-line-31)">&#160;connected</text><text class="terminal-r5" x="1451.8" y="776.4" textLength="12.2" clip-path="url(#terminal-line-31)"></text><text class="terminal-r1" x="1464" y="776.4" textLength="12.2" clip-path="url(#terminal-line-31)">
</text><text class="terminal-r5" x="0" y="800.8" textLength="12.2" clip-path="url(#terminal-line-32)"></text><text class="terminal-r5" x="1451.8" y="800.8" textLength="12.2" clip-path="url(#terminal-line-32)"></text><text class="terminal-r1" x="1464" y="800.8" textLength="12.2" clip-path="url(#terminal-line-32)">
</text><text class="terminal-r5" x="0" y="825.2" textLength="12.2" clip-path="url(#terminal-line-33)"></text><text class="terminal-r5" x="24.4" y="825.2" textLength="878.4" clip-path="url(#terminal-line-33)">↑↓&#160;Navigate&#160;&#160;Enter&#160;Show&#160;tools&#160;&#160;D&#160;Disable&#160;&#160;E&#160;Enable&#160;&#160;R&#160;Refresh&#160;&#160;Esc&#160;Close</text><text class="terminal-r5" x="1451.8" y="825.2" textLength="12.2" clip-path="url(#terminal-line-33)"></text><text class="terminal-r1" x="1464" y="825.2" textLength="12.2" clip-path="url(#terminal-line-33)">
</text><text class="terminal-r5" x="0" y="849.6" textLength="1464" clip-path="url(#terminal-line-34)">└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘</text><text class="terminal-r1" x="1464" y="849.6" textLength="12.2" clip-path="url(#terminal-line-34)">
</text><text class="terminal-r5" x="0" y="874" textLength="158.6" clip-path="url(#terminal-line-35)">/test/workdir</text><text class="terminal-r5" x="1256.6" y="874" textLength="207.4" clip-path="url(#terminal-line-35)">0%&#160;of&#160;200k&#160;tokens</text>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 18 KiB

Before After
Before After

View file

@ -19,189 +19,189 @@
font-weight: 700;
}
.terminal-4242019355-matrix {
.terminal-matrix {
font-family: Fira Code, monospace;
font-size: 20px;
line-height: 24.4px;
font-variant-east-asian: full-width;
}
.terminal-4242019355-title {
.terminal-title {
font-size: 18px;
font-weight: bold;
font-family: arial;
}
.terminal-4242019355-r1 { fill: #c5c8c6 }
.terminal-4242019355-r2 { fill: #ff8205;font-weight: bold }
.terminal-4242019355-r3 { fill: #68a0b3 }
.terminal-4242019355-r4 { fill: #ff8205 }
.terminal-4242019355-r5 { fill: #9a9b99 }
.terminal-4242019355-r6 { fill: #608ab1;font-weight: bold }
.terminal-4242019355-r7 { fill: #c5c8c6;font-weight: bold }
.terminal-4242019355-r8 { fill: #9cafbd;font-weight: bold }
.terminal-4242019355-r9 { fill: #98a84b;font-weight: bold }
.terminal-4242019355-r10 { fill: #868887 }
.terminal-4242019355-r11 { fill: #98a84b }
.terminal-r1 { fill: #c5c8c6 }
.terminal-r2 { fill: #ff8205;font-weight: bold }
.terminal-r3 { fill: #68a0b3 }
.terminal-r4 { fill: #ff8205 }
.terminal-r5 { fill: #9a9b99 }
.terminal-r6 { fill: #608ab1;font-weight: bold }
.terminal-r7 { fill: #c5c8c6;font-weight: bold }
.terminal-r8 { fill: #9cafbd;font-weight: bold }
.terminal-r9 { fill: #98a84b;font-weight: bold }
.terminal-r10 { fill: #868887 }
.terminal-r11 { fill: #98a84b }
</style>
<defs>
<clipPath id="terminal-4242019355-clip-terminal">
<clipPath id="terminal-clip-terminal">
<rect x="0" y="0" width="1463.0" height="877.4" />
</clipPath>
<clipPath id="terminal-4242019355-line-0">
<clipPath id="terminal-line-0">
<rect x="0" y="1.5" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-4242019355-line-1">
<clipPath id="terminal-line-1">
<rect x="0" y="25.9" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-4242019355-line-2">
<clipPath id="terminal-line-2">
<rect x="0" y="50.3" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-4242019355-line-3">
<clipPath id="terminal-line-3">
<rect x="0" y="74.7" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-4242019355-line-4">
<clipPath id="terminal-line-4">
<rect x="0" y="99.1" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-4242019355-line-5">
<clipPath id="terminal-line-5">
<rect x="0" y="123.5" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-4242019355-line-6">
<clipPath id="terminal-line-6">
<rect x="0" y="147.9" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-4242019355-line-7">
<clipPath id="terminal-line-7">
<rect x="0" y="172.3" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-4242019355-line-8">
<clipPath id="terminal-line-8">
<rect x="0" y="196.7" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-4242019355-line-9">
<clipPath id="terminal-line-9">
<rect x="0" y="221.1" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-4242019355-line-10">
<clipPath id="terminal-line-10">
<rect x="0" y="245.5" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-4242019355-line-11">
<clipPath id="terminal-line-11">
<rect x="0" y="269.9" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-4242019355-line-12">
<clipPath id="terminal-line-12">
<rect x="0" y="294.3" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-4242019355-line-13">
<clipPath id="terminal-line-13">
<rect x="0" y="318.7" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-4242019355-line-14">
<clipPath id="terminal-line-14">
<rect x="0" y="343.1" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-4242019355-line-15">
<clipPath id="terminal-line-15">
<rect x="0" y="367.5" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-4242019355-line-16">
<clipPath id="terminal-line-16">
<rect x="0" y="391.9" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-4242019355-line-17">
<clipPath id="terminal-line-17">
<rect x="0" y="416.3" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-4242019355-line-18">
<clipPath id="terminal-line-18">
<rect x="0" y="440.7" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-4242019355-line-19">
<clipPath id="terminal-line-19">
<rect x="0" y="465.1" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-4242019355-line-20">
<clipPath id="terminal-line-20">
<rect x="0" y="489.5" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-4242019355-line-21">
<clipPath id="terminal-line-21">
<rect x="0" y="513.9" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-4242019355-line-22">
<clipPath id="terminal-line-22">
<rect x="0" y="538.3" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-4242019355-line-23">
<clipPath id="terminal-line-23">
<rect x="0" y="562.7" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-4242019355-line-24">
<clipPath id="terminal-line-24">
<rect x="0" y="587.1" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-4242019355-line-25">
<clipPath id="terminal-line-25">
<rect x="0" y="611.5" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-4242019355-line-26">
<clipPath id="terminal-line-26">
<rect x="0" y="635.9" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-4242019355-line-27">
<clipPath id="terminal-line-27">
<rect x="0" y="660.3" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-4242019355-line-28">
<clipPath id="terminal-line-28">
<rect x="0" y="684.7" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-4242019355-line-29">
<clipPath id="terminal-line-29">
<rect x="0" y="709.1" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-4242019355-line-30">
<clipPath id="terminal-line-30">
<rect x="0" y="733.5" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-4242019355-line-31">
<clipPath id="terminal-line-31">
<rect x="0" y="757.9" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-4242019355-line-32">
<clipPath id="terminal-line-32">
<rect x="0" y="782.3" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-4242019355-line-33">
<clipPath id="terminal-line-33">
<rect x="0" y="806.7" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-4242019355-line-34">
<clipPath id="terminal-line-34">
<rect x="0" y="831.1" width="1464" height="24.65"/>
</clipPath>
</defs>
<rect fill="#292929" stroke="rgba(255,255,255,0.35)" stroke-width="1" x="1" y="1" width="1480" height="926.4" rx="8"/><text class="terminal-4242019355-title" fill="#c5c8c6" text-anchor="middle" x="740" y="27">SnapshotTestAppConnectorsOnly</text>
<rect fill="#292929" stroke="rgba(255,255,255,0.35)" stroke-width="1" x="1" y="1" width="1480" height="926.4" rx="8"/><text class="terminal-title" fill="#c5c8c6" text-anchor="middle" x="740" y="27">SnapshotTestAppConnectorsOnly</text>
<g transform="translate(26,22)">
<circle cx="0" cy="0" r="7" fill="#ff5f57"/>
<circle cx="22" cy="0" r="7" fill="#febc2e"/>
<circle cx="44" cy="0" r="7" fill="#28c840"/>
</g>
<g transform="translate(9, 41)" clip-path="url(#terminal-4242019355-clip-terminal)">
<g transform="translate(9, 41)" clip-path="url(#terminal-clip-terminal)">
<rect fill="#608ab1" x="36.6" y="733.5" width="85.4" height="24.65" shape-rendering="crispEdges"/><rect fill="#608ab1" x="122" y="733.5" width="158.6" height="24.65" shape-rendering="crispEdges"/><rect fill="#608ab1" x="280.6" y="733.5" width="109.8" height="24.65" shape-rendering="crispEdges"/><rect fill="#608ab1" x="390.4" y="733.5" width="24.4" height="24.65" shape-rendering="crispEdges"/><rect fill="#608ab1" x="414.8" y="733.5" width="12.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#608ab1" x="427" y="733.5" width="122" height="24.65" shape-rendering="crispEdges"/><rect fill="#608ab1" x="549" y="733.5" width="878.4" height="24.65" shape-rendering="crispEdges"/>
<g class="terminal-4242019355-matrix">
<text class="terminal-4242019355-r1" x="1464" y="20" textLength="12.2" clip-path="url(#terminal-4242019355-line-0)">
</text><text class="terminal-4242019355-r1" x="1464" y="44.4" textLength="12.2" clip-path="url(#terminal-4242019355-line-1)">
</text><text class="terminal-4242019355-r1" x="1464" y="68.8" textLength="12.2" clip-path="url(#terminal-4242019355-line-2)">
</text><text class="terminal-4242019355-r1" x="1464" y="93.2" textLength="12.2" clip-path="url(#terminal-4242019355-line-3)">
</text><text class="terminal-4242019355-r1" x="1464" y="117.6" textLength="12.2" clip-path="url(#terminal-4242019355-line-4)">
</text><text class="terminal-4242019355-r1" x="1464" y="142" textLength="12.2" clip-path="url(#terminal-4242019355-line-5)">
</text><text class="terminal-4242019355-r1" x="1464" y="166.4" textLength="12.2" clip-path="url(#terminal-4242019355-line-6)">
</text><text class="terminal-4242019355-r1" x="1464" y="190.8" textLength="12.2" clip-path="url(#terminal-4242019355-line-7)">
</text><text class="terminal-4242019355-r1" x="1464" y="215.2" textLength="12.2" clip-path="url(#terminal-4242019355-line-8)">
</text><text class="terminal-4242019355-r1" x="1464" y="239.6" textLength="12.2" clip-path="url(#terminal-4242019355-line-9)">
</text><text class="terminal-4242019355-r1" x="1464" y="264" textLength="12.2" clip-path="url(#terminal-4242019355-line-10)">
</text><text class="terminal-4242019355-r1" x="1464" y="288.4" textLength="12.2" clip-path="url(#terminal-4242019355-line-11)">
</text><text class="terminal-4242019355-r1" x="1464" y="312.8" textLength="12.2" clip-path="url(#terminal-4242019355-line-12)">
</text><text class="terminal-4242019355-r1" x="1464" y="337.2" textLength="12.2" clip-path="url(#terminal-4242019355-line-13)">
</text><text class="terminal-4242019355-r1" x="1464" y="361.6" textLength="12.2" clip-path="url(#terminal-4242019355-line-14)">
</text><text class="terminal-4242019355-r1" x="1464" y="386" textLength="12.2" clip-path="url(#terminal-4242019355-line-15)">
</text><text class="terminal-4242019355-r1" x="1464" y="410.4" textLength="12.2" clip-path="url(#terminal-4242019355-line-16)">
</text><text class="terminal-4242019355-r1" x="0" y="434.8" textLength="134.2" clip-path="url(#terminal-4242019355-line-17)">&#160;&#160;⡠⣒⠄&#160;&#160;⡔⢄⠔⡄</text><text class="terminal-4242019355-r2" x="170.8" y="434.8" textLength="146.4" clip-path="url(#terminal-4242019355-line-17)">Mistral&#160;Vibe</text><text class="terminal-4242019355-r1" x="317.2" y="434.8" textLength="122" clip-path="url(#terminal-4242019355-line-17)">&#160;v0.0.0&#160;·&#160;</text><text class="terminal-4242019355-r3" x="439.2" y="434.8" textLength="183" clip-path="url(#terminal-4242019355-line-17)">devstral-latest</text><text class="terminal-4242019355-r1" x="622.2" y="434.8" textLength="256.2" clip-path="url(#terminal-4242019355-line-17)">&#160;·&#160;[Subscription]&#160;Pro</text><text class="terminal-4242019355-r1" x="1464" y="434.8" textLength="12.2" clip-path="url(#terminal-4242019355-line-17)">
</text><text class="terminal-4242019355-r1" x="0" y="459.2" textLength="134.2" clip-path="url(#terminal-4242019355-line-18)">&#160;⢸⠸⣀⡔⢉⠱⣃⡢⣂⡣</text><text class="terminal-4242019355-r1" x="170.8" y="459.2" textLength="597.8" clip-path="url(#terminal-4242019355-line-18)">1&#160;model&#160;·&#160;2&#160;connectors&#160;·&#160;0&#160;MCP&#160;servers&#160;·&#160;0&#160;skills</text><text class="terminal-4242019355-r1" x="1464" y="459.2" textLength="12.2" clip-path="url(#terminal-4242019355-line-18)">
</text><text class="terminal-4242019355-r1" x="0" y="483.6" textLength="134.2" clip-path="url(#terminal-4242019355-line-19)">&#160;&#160;⠉⠒⠣⠤⠵⠤⠬⠮⠆</text><text class="terminal-4242019355-r1" x="170.8" y="483.6" textLength="61" clip-path="url(#terminal-4242019355-line-19)">Type&#160;</text><text class="terminal-4242019355-r3" x="231.8" y="483.6" textLength="61" clip-path="url(#terminal-4242019355-line-19)">/help</text><text class="terminal-4242019355-r1" x="292.8" y="483.6" textLength="256.2" clip-path="url(#terminal-4242019355-line-19)">&#160;for&#160;more&#160;information</text><text class="terminal-4242019355-r1" x="1464" y="483.6" textLength="12.2" clip-path="url(#terminal-4242019355-line-19)">
</text><text class="terminal-4242019355-r1" x="1464" y="508" textLength="12.2" clip-path="url(#terminal-4242019355-line-20)">
</text><text class="terminal-4242019355-r1" x="1464" y="532.4" textLength="12.2" clip-path="url(#terminal-4242019355-line-21)">
</text><text class="terminal-4242019355-r4" x="0" y="556.8" textLength="12.2" clip-path="url(#terminal-4242019355-line-22)"></text><text class="terminal-4242019355-r2" x="24.4" y="556.8" textLength="48.8" clip-path="url(#terminal-4242019355-line-22)">/mcp</text><text class="terminal-4242019355-r1" x="1464" y="556.8" textLength="12.2" clip-path="url(#terminal-4242019355-line-22)">
</text><text class="terminal-4242019355-r5" x="24.4" y="581.2" textLength="12.2" clip-path="url(#terminal-4242019355-line-23)"></text><text class="terminal-4242019355-r1" x="48.8" y="581.2" textLength="256.2" clip-path="url(#terminal-4242019355-line-23)">MCP&#160;servers&#160;opened...</text><text class="terminal-4242019355-r1" x="1464" y="581.2" textLength="12.2" clip-path="url(#terminal-4242019355-line-23)">
</text><text class="terminal-4242019355-r1" x="1464" y="605.6" textLength="12.2" clip-path="url(#terminal-4242019355-line-24)">
</text><text class="terminal-4242019355-r1" x="1464" y="630" textLength="12.2" clip-path="url(#terminal-4242019355-line-25)">
</text><text class="terminal-4242019355-r5" x="0" y="654.4" textLength="1464" clip-path="url(#terminal-4242019355-line-26)">┌──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐</text><text class="terminal-4242019355-r1" x="1464" y="654.4" textLength="12.2" clip-path="url(#terminal-4242019355-line-26)">
</text><text class="terminal-4242019355-r5" x="0" y="678.8" textLength="12.2" clip-path="url(#terminal-4242019355-line-27)"></text><text class="terminal-4242019355-r6" x="24.4" y="678.8" textLength="292.8" clip-path="url(#terminal-4242019355-line-27)">MCP&#160;Servers&#160;&amp;&#160;Connectors</text><text class="terminal-4242019355-r5" x="1451.8" y="678.8" textLength="12.2" clip-path="url(#terminal-4242019355-line-27)"></text><text class="terminal-4242019355-r1" x="1464" y="678.8" textLength="12.2" clip-path="url(#terminal-4242019355-line-27)">
</text><text class="terminal-4242019355-r5" x="0" y="703.2" textLength="12.2" clip-path="url(#terminal-4242019355-line-28)"></text><text class="terminal-4242019355-r5" x="1451.8" y="703.2" textLength="12.2" clip-path="url(#terminal-4242019355-line-28)"></text><text class="terminal-4242019355-r1" x="1464" y="703.2" textLength="12.2" clip-path="url(#terminal-4242019355-line-28)">
</text><text class="terminal-4242019355-r5" x="0" y="727.6" textLength="12.2" clip-path="url(#terminal-4242019355-line-29)"></text><text class="terminal-4242019355-r7" x="36.6" y="727.6" textLength="244" clip-path="url(#terminal-4242019355-line-29)">Workspace&#160;Connectors</text><text class="terminal-4242019355-r5" x="1451.8" y="727.6" textLength="12.2" clip-path="url(#terminal-4242019355-line-29)"></text><text class="terminal-4242019355-r1" x="1464" y="727.6" textLength="12.2" clip-path="url(#terminal-4242019355-line-29)">
</text><text class="terminal-4242019355-r5" x="0" y="752" textLength="12.2" clip-path="url(#terminal-4242019355-line-30)"></text><text class="terminal-4242019355-r7" x="36.6" y="752" textLength="85.4" clip-path="url(#terminal-4242019355-line-30)">&#160;&#160;gmail</text><text class="terminal-4242019355-r8" x="122" y="752" textLength="158.6" clip-path="url(#terminal-4242019355-line-30)">&#160;&#160;[connector]</text><text class="terminal-4242019355-r8" x="280.6" y="752" textLength="109.8" clip-path="url(#terminal-4242019355-line-30)">&#160;&#160;3&#160;tools</text><text class="terminal-4242019355-r9" x="414.8" y="752" textLength="12.2" clip-path="url(#terminal-4242019355-line-30)"></text><text class="terminal-4242019355-r8" x="427" y="752" textLength="122" clip-path="url(#terminal-4242019355-line-30)">&#160;connected</text><text class="terminal-4242019355-r5" x="1451.8" y="752" textLength="12.2" clip-path="url(#terminal-4242019355-line-30)"></text><text class="terminal-4242019355-r1" x="1464" y="752" textLength="12.2" clip-path="url(#terminal-4242019355-line-30)">
</text><text class="terminal-4242019355-r5" x="0" y="776.4" textLength="12.2" clip-path="url(#terminal-4242019355-line-31)"></text><text class="terminal-4242019355-r1" x="36.6" y="776.4" textLength="85.4" clip-path="url(#terminal-4242019355-line-31)">&#160;&#160;slack</text><text class="terminal-4242019355-r10" x="122" y="776.4" textLength="158.6" clip-path="url(#terminal-4242019355-line-31)">&#160;&#160;[connector]</text><text class="terminal-4242019355-r10" x="280.6" y="776.4" textLength="109.8" clip-path="url(#terminal-4242019355-line-31)">&#160;&#160;2&#160;tools</text><text class="terminal-4242019355-r11" x="414.8" y="776.4" textLength="12.2" clip-path="url(#terminal-4242019355-line-31)"></text><text class="terminal-4242019355-r10" x="427" y="776.4" textLength="122" clip-path="url(#terminal-4242019355-line-31)">&#160;connected</text><text class="terminal-4242019355-r5" x="1451.8" y="776.4" textLength="12.2" clip-path="url(#terminal-4242019355-line-31)"></text><text class="terminal-4242019355-r1" x="1464" y="776.4" textLength="12.2" clip-path="url(#terminal-4242019355-line-31)">
</text><text class="terminal-4242019355-r5" x="0" y="800.8" textLength="12.2" clip-path="url(#terminal-4242019355-line-32)"></text><text class="terminal-4242019355-r5" x="1451.8" y="800.8" textLength="12.2" clip-path="url(#terminal-4242019355-line-32)"></text><text class="terminal-4242019355-r1" x="1464" y="800.8" textLength="12.2" clip-path="url(#terminal-4242019355-line-32)">
</text><text class="terminal-4242019355-r5" x="0" y="825.2" textLength="12.2" clip-path="url(#terminal-4242019355-line-33)"></text><text class="terminal-4242019355-r5" x="24.4" y="825.2" textLength="622.2" clip-path="url(#terminal-4242019355-line-33)">↑↓&#160;Navigate&#160;&#160;Enter&#160;Show&#160;tools&#160;&#160;R&#160;Refresh&#160;&#160;Esc&#160;Close</text><text class="terminal-4242019355-r5" x="1451.8" y="825.2" textLength="12.2" clip-path="url(#terminal-4242019355-line-33)"></text><text class="terminal-4242019355-r1" x="1464" y="825.2" textLength="12.2" clip-path="url(#terminal-4242019355-line-33)">
</text><text class="terminal-4242019355-r5" x="0" y="849.6" textLength="1464" clip-path="url(#terminal-4242019355-line-34)">└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘</text><text class="terminal-4242019355-r1" x="1464" y="849.6" textLength="12.2" clip-path="url(#terminal-4242019355-line-34)">
</text><text class="terminal-4242019355-r5" x="0" y="874" textLength="158.6" clip-path="url(#terminal-4242019355-line-35)">/test/workdir</text><text class="terminal-4242019355-r5" x="1256.6" y="874" textLength="207.4" clip-path="url(#terminal-4242019355-line-35)">0%&#160;of&#160;200k&#160;tokens</text>
<g class="terminal-matrix">
<text class="terminal-r1" x="1464" y="20" textLength="12.2" clip-path="url(#terminal-line-0)">
</text><text class="terminal-r1" x="1464" y="44.4" textLength="12.2" clip-path="url(#terminal-line-1)">
</text><text class="terminal-r1" x="1464" y="68.8" textLength="12.2" clip-path="url(#terminal-line-2)">
</text><text class="terminal-r1" x="1464" y="93.2" textLength="12.2" clip-path="url(#terminal-line-3)">
</text><text class="terminal-r1" x="1464" y="117.6" textLength="12.2" clip-path="url(#terminal-line-4)">
</text><text class="terminal-r1" x="1464" y="142" textLength="12.2" clip-path="url(#terminal-line-5)">
</text><text class="terminal-r1" x="1464" y="166.4" textLength="12.2" clip-path="url(#terminal-line-6)">
</text><text class="terminal-r1" x="1464" y="190.8" textLength="12.2" clip-path="url(#terminal-line-7)">
</text><text class="terminal-r1" x="1464" y="215.2" textLength="12.2" clip-path="url(#terminal-line-8)">
</text><text class="terminal-r1" x="1464" y="239.6" textLength="12.2" clip-path="url(#terminal-line-9)">
</text><text class="terminal-r1" x="1464" y="264" textLength="12.2" clip-path="url(#terminal-line-10)">
</text><text class="terminal-r1" x="1464" y="288.4" textLength="12.2" clip-path="url(#terminal-line-11)">
</text><text class="terminal-r1" x="1464" y="312.8" textLength="12.2" clip-path="url(#terminal-line-12)">
</text><text class="terminal-r1" x="1464" y="337.2" textLength="12.2" clip-path="url(#terminal-line-13)">
</text><text class="terminal-r1" x="1464" y="361.6" textLength="12.2" clip-path="url(#terminal-line-14)">
</text><text class="terminal-r1" x="1464" y="386" textLength="12.2" clip-path="url(#terminal-line-15)">
</text><text class="terminal-r1" x="1464" y="410.4" textLength="12.2" clip-path="url(#terminal-line-16)">
</text><text class="terminal-r1" x="0" y="434.8" textLength="134.2" clip-path="url(#terminal-line-17)">&#160;&#160;⡠⣒⠄&#160;&#160;⡔⢄⠔⡄</text><text class="terminal-r2" x="170.8" y="434.8" textLength="146.4" clip-path="url(#terminal-line-17)">Mistral&#160;Vibe</text><text class="terminal-r1" x="317.2" y="434.8" textLength="122" clip-path="url(#terminal-line-17)">&#160;v0.0.0&#160;·&#160;</text><text class="terminal-r3" x="439.2" y="434.8" textLength="244" clip-path="url(#terminal-line-17)">devstral-latest[off]</text><text class="terminal-r1" x="683.2" y="434.8" textLength="256.2" clip-path="url(#terminal-line-17)">&#160;·&#160;[Subscription]&#160;Pro</text><text class="terminal-r1" x="1464" y="434.8" textLength="12.2" clip-path="url(#terminal-line-17)">
</text><text class="terminal-r1" x="0" y="459.2" textLength="134.2" clip-path="url(#terminal-line-18)">&#160;⢸⠸⣀⡔⢉⠱⣃⡢⣂⡣</text><text class="terminal-r1" x="170.8" y="459.2" textLength="597.8" clip-path="url(#terminal-line-18)">1&#160;model&#160;·&#160;2&#160;connectors&#160;·&#160;0&#160;MCP&#160;servers&#160;·&#160;0&#160;skills</text><text class="terminal-r1" x="1464" y="459.2" textLength="12.2" clip-path="url(#terminal-line-18)">
</text><text class="terminal-r1" x="0" y="483.6" textLength="134.2" clip-path="url(#terminal-line-19)">&#160;&#160;⠉⠒⠣⠤⠵⠤⠬⠮⠆</text><text class="terminal-r1" x="170.8" y="483.6" textLength="61" clip-path="url(#terminal-line-19)">Type&#160;</text><text class="terminal-r3" x="231.8" y="483.6" textLength="61" clip-path="url(#terminal-line-19)">/help</text><text class="terminal-r1" x="292.8" y="483.6" textLength="256.2" clip-path="url(#terminal-line-19)">&#160;for&#160;more&#160;information</text><text class="terminal-r1" x="1464" y="483.6" textLength="12.2" clip-path="url(#terminal-line-19)">
</text><text class="terminal-r1" x="1464" y="508" textLength="12.2" clip-path="url(#terminal-line-20)">
</text><text class="terminal-r1" x="1464" y="532.4" textLength="12.2" clip-path="url(#terminal-line-21)">
</text><text class="terminal-r4" x="0" y="556.8" textLength="12.2" clip-path="url(#terminal-line-22)"></text><text class="terminal-r2" x="24.4" y="556.8" textLength="48.8" clip-path="url(#terminal-line-22)">/mcp</text><text class="terminal-r1" x="1464" y="556.8" textLength="12.2" clip-path="url(#terminal-line-22)">
</text><text class="terminal-r5" x="24.4" y="581.2" textLength="12.2" clip-path="url(#terminal-line-23)"></text><text class="terminal-r1" x="48.8" y="581.2" textLength="256.2" clip-path="url(#terminal-line-23)">MCP&#160;servers&#160;opened...</text><text class="terminal-r1" x="1464" y="581.2" textLength="12.2" clip-path="url(#terminal-line-23)">
</text><text class="terminal-r1" x="1464" y="605.6" textLength="12.2" clip-path="url(#terminal-line-24)">
</text><text class="terminal-r1" x="1464" y="630" textLength="12.2" clip-path="url(#terminal-line-25)">
</text><text class="terminal-r5" x="0" y="654.4" textLength="1464" clip-path="url(#terminal-line-26)">┌──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐</text><text class="terminal-r1" x="1464" y="654.4" textLength="12.2" clip-path="url(#terminal-line-26)">
</text><text class="terminal-r5" x="0" y="678.8" textLength="12.2" clip-path="url(#terminal-line-27)"></text><text class="terminal-r6" x="24.4" y="678.8" textLength="292.8" clip-path="url(#terminal-line-27)">MCP&#160;Servers&#160;&amp;&#160;Connectors</text><text class="terminal-r5" x="1451.8" y="678.8" textLength="12.2" clip-path="url(#terminal-line-27)"></text><text class="terminal-r1" x="1464" y="678.8" textLength="12.2" clip-path="url(#terminal-line-27)">
</text><text class="terminal-r5" x="0" y="703.2" textLength="12.2" clip-path="url(#terminal-line-28)"></text><text class="terminal-r5" x="1451.8" y="703.2" textLength="12.2" clip-path="url(#terminal-line-28)"></text><text class="terminal-r1" x="1464" y="703.2" textLength="12.2" clip-path="url(#terminal-line-28)">
</text><text class="terminal-r5" x="0" y="727.6" textLength="12.2" clip-path="url(#terminal-line-29)"></text><text class="terminal-r7" x="36.6" y="727.6" textLength="244" clip-path="url(#terminal-line-29)">Workspace&#160;Connectors</text><text class="terminal-r5" x="1451.8" y="727.6" textLength="12.2" clip-path="url(#terminal-line-29)"></text><text class="terminal-r1" x="1464" y="727.6" textLength="12.2" clip-path="url(#terminal-line-29)">
</text><text class="terminal-r5" x="0" y="752" textLength="12.2" clip-path="url(#terminal-line-30)"></text><text class="terminal-r7" x="36.6" y="752" textLength="85.4" clip-path="url(#terminal-line-30)">&#160;&#160;gmail</text><text class="terminal-r8" x="122" y="752" textLength="158.6" clip-path="url(#terminal-line-30)">&#160;&#160;[connector]</text><text class="terminal-r8" x="280.6" y="752" textLength="109.8" clip-path="url(#terminal-line-30)">&#160;&#160;3&#160;tools</text><text class="terminal-r9" x="414.8" y="752" textLength="12.2" clip-path="url(#terminal-line-30)"></text><text class="terminal-r8" x="427" y="752" textLength="122" clip-path="url(#terminal-line-30)">&#160;connected</text><text class="terminal-r5" x="1451.8" y="752" textLength="12.2" clip-path="url(#terminal-line-30)"></text><text class="terminal-r1" x="1464" y="752" textLength="12.2" clip-path="url(#terminal-line-30)">
</text><text class="terminal-r5" x="0" y="776.4" textLength="12.2" clip-path="url(#terminal-line-31)"></text><text class="terminal-r1" x="36.6" y="776.4" textLength="85.4" clip-path="url(#terminal-line-31)">&#160;&#160;slack</text><text class="terminal-r10" x="122" y="776.4" textLength="158.6" clip-path="url(#terminal-line-31)">&#160;&#160;[connector]</text><text class="terminal-r10" x="280.6" y="776.4" textLength="109.8" clip-path="url(#terminal-line-31)">&#160;&#160;2&#160;tools</text><text class="terminal-r11" x="414.8" y="776.4" textLength="12.2" clip-path="url(#terminal-line-31)"></text><text class="terminal-r10" x="427" y="776.4" textLength="122" clip-path="url(#terminal-line-31)">&#160;connected</text><text class="terminal-r5" x="1451.8" y="776.4" textLength="12.2" clip-path="url(#terminal-line-31)"></text><text class="terminal-r1" x="1464" y="776.4" textLength="12.2" clip-path="url(#terminal-line-31)">
</text><text class="terminal-r5" x="0" y="800.8" textLength="12.2" clip-path="url(#terminal-line-32)"></text><text class="terminal-r5" x="1451.8" y="800.8" textLength="12.2" clip-path="url(#terminal-line-32)"></text><text class="terminal-r1" x="1464" y="800.8" textLength="12.2" clip-path="url(#terminal-line-32)">
</text><text class="terminal-r5" x="0" y="825.2" textLength="12.2" clip-path="url(#terminal-line-33)"></text><text class="terminal-r5" x="24.4" y="825.2" textLength="878.4" clip-path="url(#terminal-line-33)">↑↓&#160;Navigate&#160;&#160;Enter&#160;Show&#160;tools&#160;&#160;D&#160;Disable&#160;&#160;E&#160;Enable&#160;&#160;R&#160;Refresh&#160;&#160;Esc&#160;Close</text><text class="terminal-r5" x="1451.8" y="825.2" textLength="12.2" clip-path="url(#terminal-line-33)"></text><text class="terminal-r1" x="1464" y="825.2" textLength="12.2" clip-path="url(#terminal-line-33)">
</text><text class="terminal-r5" x="0" y="849.6" textLength="1464" clip-path="url(#terminal-line-34)">└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘</text><text class="terminal-r1" x="1464" y="849.6" textLength="12.2" clip-path="url(#terminal-line-34)">
</text><text class="terminal-r5" x="0" y="874" textLength="158.6" clip-path="url(#terminal-line-35)">/test/workdir</text><text class="terminal-r5" x="1256.6" y="874" textLength="207.4" clip-path="url(#terminal-line-35)">0%&#160;of&#160;200k&#160;tokens</text>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 19 KiB

After

Width:  |  Height:  |  Size: 17 KiB

Before After
Before After

View file

@ -181,7 +181,7 @@
</text><text class="terminal-r1" x="1464" y="337.2" textLength="12.2" clip-path="url(#terminal-line-13)">
</text><text class="terminal-r1" x="1464" y="361.6" textLength="12.2" clip-path="url(#terminal-line-14)">
</text><text class="terminal-r1" x="1464" y="386" textLength="12.2" clip-path="url(#terminal-line-15)">
</text><text class="terminal-r1" x="0" y="410.4" textLength="134.2" clip-path="url(#terminal-line-16)">&#160;&#160;⡠⣒⠄&#160;&#160;⡔⢄⠔⡄</text><text class="terminal-r2" x="170.8" y="410.4" textLength="146.4" clip-path="url(#terminal-line-16)">Mistral&#160;Vibe</text><text class="terminal-r1" x="317.2" y="410.4" textLength="122" clip-path="url(#terminal-line-16)">&#160;v0.0.0&#160;·&#160;</text><text class="terminal-r3" x="439.2" y="410.4" textLength="183" clip-path="url(#terminal-line-16)">devstral-latest</text><text class="terminal-r1" x="622.2" y="410.4" textLength="256.2" clip-path="url(#terminal-line-16)">&#160;·&#160;[Subscription]&#160;Pro</text><text class="terminal-r1" x="1464" y="410.4" textLength="12.2" clip-path="url(#terminal-line-16)">
</text><text class="terminal-r1" x="0" y="410.4" textLength="134.2" clip-path="url(#terminal-line-16)">&#160;&#160;⡠⣒⠄&#160;&#160;⡔⢄⠔⡄</text><text class="terminal-r2" x="170.8" y="410.4" textLength="146.4" clip-path="url(#terminal-line-16)">Mistral&#160;Vibe</text><text class="terminal-r1" x="317.2" y="410.4" textLength="122" clip-path="url(#terminal-line-16)">&#160;v0.0.0&#160;·&#160;</text><text class="terminal-r3" x="439.2" y="410.4" textLength="244" clip-path="url(#terminal-line-16)">devstral-latest[off]</text><text class="terminal-r1" x="683.2" y="410.4" textLength="256.2" clip-path="url(#terminal-line-16)">&#160;·&#160;[Subscription]&#160;Pro</text><text class="terminal-r1" x="1464" y="410.4" textLength="12.2" clip-path="url(#terminal-line-16)">
</text><text class="terminal-r1" x="0" y="434.8" textLength="134.2" clip-path="url(#terminal-line-17)">&#160;⢸⠸⣀⡔⢉⠱⣃⡢⣂⡣</text><text class="terminal-r1" x="170.8" y="434.8" textLength="597.8" clip-path="url(#terminal-line-17)">1&#160;model&#160;·&#160;3&#160;connectors&#160;·&#160;0&#160;MCP&#160;servers&#160;·&#160;0&#160;skills</text><text class="terminal-r1" x="1464" y="434.8" textLength="12.2" clip-path="url(#terminal-line-17)">
</text><text class="terminal-r1" x="0" y="459.2" textLength="134.2" clip-path="url(#terminal-line-18)">&#160;&#160;⠉⠒⠣⠤⠵⠤⠬⠮⠆</text><text class="terminal-r1" x="170.8" y="459.2" textLength="61" clip-path="url(#terminal-line-18)">Type&#160;</text><text class="terminal-r3" x="231.8" y="459.2" textLength="61" clip-path="url(#terminal-line-18)">/help</text><text class="terminal-r1" x="292.8" y="459.2" textLength="256.2" clip-path="url(#terminal-line-18)">&#160;for&#160;more&#160;information</text><text class="terminal-r1" x="1464" y="459.2" textLength="12.2" clip-path="url(#terminal-line-18)">
</text><text class="terminal-r1" x="1464" y="483.6" textLength="12.2" clip-path="url(#terminal-line-19)">
@ -198,7 +198,7 @@
</text><text class="terminal-r5" x="0" y="752" textLength="12.2" clip-path="url(#terminal-line-30)"></text><text class="terminal-r1" x="36.6" y="752" textLength="85.4" clip-path="url(#terminal-line-30)">&#160;&#160;beta&#160;</text><text class="terminal-r10" x="122" y="752" textLength="158.6" clip-path="url(#terminal-line-30)">&#160;&#160;[connector]</text><text class="terminal-r10" x="280.6" y="752" textLength="122" clip-path="url(#terminal-line-30)">&#160;&#160;no&#160;tools</text><text class="terminal-r10" x="427" y="752" textLength="12.2" clip-path="url(#terminal-line-30)"></text><text class="terminal-r10" x="439.2" y="752" textLength="170.8" clip-path="url(#terminal-line-30)">&#160;not&#160;connected</text><text class="terminal-r5" x="1451.8" y="752" textLength="12.2" clip-path="url(#terminal-line-30)"></text><text class="terminal-r1" x="1464" y="752" textLength="12.2" clip-path="url(#terminal-line-30)">
</text><text class="terminal-r5" x="0" y="776.4" textLength="12.2" clip-path="url(#terminal-line-31)"></text><text class="terminal-r1" x="36.6" y="776.4" textLength="85.4" clip-path="url(#terminal-line-31)">&#160;&#160;zeta&#160;</text><text class="terminal-r10" x="122" y="776.4" textLength="158.6" clip-path="url(#terminal-line-31)">&#160;&#160;[connector]</text><text class="terminal-r10" x="280.6" y="776.4" textLength="122" clip-path="url(#terminal-line-31)">&#160;&#160;no&#160;tools</text><text class="terminal-r10" x="427" y="776.4" textLength="12.2" clip-path="url(#terminal-line-31)"></text><text class="terminal-r10" x="439.2" y="776.4" textLength="170.8" clip-path="url(#terminal-line-31)">&#160;not&#160;connected</text><text class="terminal-r5" x="1451.8" y="776.4" textLength="12.2" clip-path="url(#terminal-line-31)"></text><text class="terminal-r1" x="1464" y="776.4" textLength="12.2" clip-path="url(#terminal-line-31)">
</text><text class="terminal-r5" x="0" y="800.8" textLength="12.2" clip-path="url(#terminal-line-32)"></text><text class="terminal-r5" x="1451.8" y="800.8" textLength="12.2" clip-path="url(#terminal-line-32)"></text><text class="terminal-r1" x="1464" y="800.8" textLength="12.2" clip-path="url(#terminal-line-32)">
</text><text class="terminal-r5" x="0" y="825.2" textLength="12.2" clip-path="url(#terminal-line-33)"></text><text class="terminal-r5" x="24.4" y="825.2" textLength="622.2" clip-path="url(#terminal-line-33)">↑↓&#160;Navigate&#160;&#160;Enter&#160;Show&#160;tools&#160;&#160;R&#160;Refresh&#160;&#160;Esc&#160;Close</text><text class="terminal-r5" x="1451.8" y="825.2" textLength="12.2" clip-path="url(#terminal-line-33)"></text><text class="terminal-r1" x="1464" y="825.2" textLength="12.2" clip-path="url(#terminal-line-33)">
</text><text class="terminal-r5" x="0" y="825.2" textLength="12.2" clip-path="url(#terminal-line-33)"></text><text class="terminal-r5" x="24.4" y="825.2" textLength="878.4" clip-path="url(#terminal-line-33)">↑↓&#160;Navigate&#160;&#160;Enter&#160;Show&#160;tools&#160;&#160;D&#160;Disable&#160;&#160;E&#160;Enable&#160;&#160;R&#160;Refresh&#160;&#160;Esc&#160;Close</text><text class="terminal-r5" x="1451.8" y="825.2" textLength="12.2" clip-path="url(#terminal-line-33)"></text><text class="terminal-r1" x="1464" y="825.2" textLength="12.2" clip-path="url(#terminal-line-33)">
</text><text class="terminal-r5" x="0" y="849.6" textLength="1464" clip-path="url(#terminal-line-34)">└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘</text><text class="terminal-r1" x="1464" y="849.6" textLength="12.2" clip-path="url(#terminal-line-34)">
</text><text class="terminal-r5" x="0" y="874" textLength="158.6" clip-path="url(#terminal-line-35)">/test/workdir</text><text class="terminal-r5" x="1256.6" y="874" textLength="207.4" clip-path="url(#terminal-line-35)">0%&#160;of&#160;200k&#160;tokens</text>
</g>

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 18 KiB

Before After
Before After

View file

@ -19,185 +19,185 @@
font-weight: 700;
}
.terminal-1928557542-matrix {
.terminal-matrix {
font-family: Fira Code, monospace;
font-size: 20px;
line-height: 24.4px;
font-variant-east-asian: full-width;
}
.terminal-1928557542-title {
.terminal-title {
font-size: 18px;
font-weight: bold;
font-family: arial;
}
.terminal-1928557542-r1 { fill: #c5c8c6 }
.terminal-1928557542-r2 { fill: #ff8205;font-weight: bold }
.terminal-1928557542-r3 { fill: #68a0b3 }
.terminal-1928557542-r4 { fill: #ff8205 }
.terminal-1928557542-r5 { fill: #9a9b99 }
.terminal-1928557542-r6 { fill: #608ab1;font-weight: bold }
.terminal-1928557542-r7 { fill: #c5c8c6;font-weight: bold }
.terminal-r1 { fill: #c5c8c6 }
.terminal-r2 { fill: #ff8205;font-weight: bold }
.terminal-r3 { fill: #68a0b3 }
.terminal-r4 { fill: #ff8205 }
.terminal-r5 { fill: #9a9b99 }
.terminal-r6 { fill: #608ab1;font-weight: bold }
.terminal-r7 { fill: #c5c8c6;font-weight: bold }
</style>
<defs>
<clipPath id="terminal-1928557542-clip-terminal">
<clipPath id="terminal-clip-terminal">
<rect x="0" y="0" width="1463.0" height="877.4" />
</clipPath>
<clipPath id="terminal-1928557542-line-0">
<clipPath id="terminal-line-0">
<rect x="0" y="1.5" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-1928557542-line-1">
<clipPath id="terminal-line-1">
<rect x="0" y="25.9" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-1928557542-line-2">
<clipPath id="terminal-line-2">
<rect x="0" y="50.3" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-1928557542-line-3">
<clipPath id="terminal-line-3">
<rect x="0" y="74.7" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-1928557542-line-4">
<clipPath id="terminal-line-4">
<rect x="0" y="99.1" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-1928557542-line-5">
<clipPath id="terminal-line-5">
<rect x="0" y="123.5" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-1928557542-line-6">
<clipPath id="terminal-line-6">
<rect x="0" y="147.9" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-1928557542-line-7">
<clipPath id="terminal-line-7">
<rect x="0" y="172.3" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-1928557542-line-8">
<clipPath id="terminal-line-8">
<rect x="0" y="196.7" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-1928557542-line-9">
<clipPath id="terminal-line-9">
<rect x="0" y="221.1" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-1928557542-line-10">
<clipPath id="terminal-line-10">
<rect x="0" y="245.5" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-1928557542-line-11">
<clipPath id="terminal-line-11">
<rect x="0" y="269.9" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-1928557542-line-12">
<clipPath id="terminal-line-12">
<rect x="0" y="294.3" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-1928557542-line-13">
<clipPath id="terminal-line-13">
<rect x="0" y="318.7" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-1928557542-line-14">
<clipPath id="terminal-line-14">
<rect x="0" y="343.1" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-1928557542-line-15">
<clipPath id="terminal-line-15">
<rect x="0" y="367.5" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-1928557542-line-16">
<clipPath id="terminal-line-16">
<rect x="0" y="391.9" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-1928557542-line-17">
<clipPath id="terminal-line-17">
<rect x="0" y="416.3" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-1928557542-line-18">
<clipPath id="terminal-line-18">
<rect x="0" y="440.7" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-1928557542-line-19">
<clipPath id="terminal-line-19">
<rect x="0" y="465.1" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-1928557542-line-20">
<clipPath id="terminal-line-20">
<rect x="0" y="489.5" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-1928557542-line-21">
<clipPath id="terminal-line-21">
<rect x="0" y="513.9" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-1928557542-line-22">
<clipPath id="terminal-line-22">
<rect x="0" y="538.3" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-1928557542-line-23">
<clipPath id="terminal-line-23">
<rect x="0" y="562.7" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-1928557542-line-24">
<clipPath id="terminal-line-24">
<rect x="0" y="587.1" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-1928557542-line-25">
<clipPath id="terminal-line-25">
<rect x="0" y="611.5" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-1928557542-line-26">
<clipPath id="terminal-line-26">
<rect x="0" y="635.9" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-1928557542-line-27">
<clipPath id="terminal-line-27">
<rect x="0" y="660.3" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-1928557542-line-28">
<clipPath id="terminal-line-28">
<rect x="0" y="684.7" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-1928557542-line-29">
<clipPath id="terminal-line-29">
<rect x="0" y="709.1" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-1928557542-line-30">
<clipPath id="terminal-line-30">
<rect x="0" y="733.5" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-1928557542-line-31">
<clipPath id="terminal-line-31">
<rect x="0" y="757.9" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-1928557542-line-32">
<clipPath id="terminal-line-32">
<rect x="0" y="782.3" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-1928557542-line-33">
<clipPath id="terminal-line-33">
<rect x="0" y="806.7" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-1928557542-line-34">
<clipPath id="terminal-line-34">
<rect x="0" y="831.1" width="1464" height="24.65"/>
</clipPath>
</defs>
<rect fill="#292929" stroke="rgba(255,255,255,0.35)" stroke-width="1" x="1" y="1" width="1480" height="926.4" rx="8"/><text class="terminal-1928557542-title" fill="#c5c8c6" text-anchor="middle" x="740" y="27">SnapshotTestAppWithConnectors</text>
<rect fill="#292929" stroke="rgba(255,255,255,0.35)" stroke-width="1" x="1" y="1" width="1480" height="926.4" rx="8"/><text class="terminal-title" fill="#c5c8c6" text-anchor="middle" x="740" y="27">SnapshotTestAppWithConnectors</text>
<g transform="translate(26,22)">
<circle cx="0" cy="0" r="7" fill="#ff5f57"/>
<circle cx="22" cy="0" r="7" fill="#febc2e"/>
<circle cx="44" cy="0" r="7" fill="#28c840"/>
</g>
<g transform="translate(9, 41)" clip-path="url(#terminal-1928557542-clip-terminal)">
<g transform="translate(9, 41)" clip-path="url(#terminal-clip-terminal)">
<rect fill="#608ab1" x="36.6" y="733.5" width="183" height="24.65" shape-rendering="crispEdges"/><rect fill="#608ab1" x="219.6" y="733.5" width="317.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#608ab1" x="536.8" y="733.5" width="890.6" height="24.65" shape-rendering="crispEdges"/>
<g class="terminal-1928557542-matrix">
<text class="terminal-1928557542-r1" x="1464" y="20" textLength="12.2" clip-path="url(#terminal-1928557542-line-0)">
</text><text class="terminal-1928557542-r1" x="1464" y="44.4" textLength="12.2" clip-path="url(#terminal-1928557542-line-1)">
</text><text class="terminal-1928557542-r1" x="1464" y="68.8" textLength="12.2" clip-path="url(#terminal-1928557542-line-2)">
</text><text class="terminal-1928557542-r1" x="1464" y="93.2" textLength="12.2" clip-path="url(#terminal-1928557542-line-3)">
</text><text class="terminal-1928557542-r1" x="1464" y="117.6" textLength="12.2" clip-path="url(#terminal-1928557542-line-4)">
</text><text class="terminal-1928557542-r1" x="1464" y="142" textLength="12.2" clip-path="url(#terminal-1928557542-line-5)">
</text><text class="terminal-1928557542-r1" x="1464" y="166.4" textLength="12.2" clip-path="url(#terminal-1928557542-line-6)">
</text><text class="terminal-1928557542-r1" x="1464" y="190.8" textLength="12.2" clip-path="url(#terminal-1928557542-line-7)">
</text><text class="terminal-1928557542-r1" x="1464" y="215.2" textLength="12.2" clip-path="url(#terminal-1928557542-line-8)">
</text><text class="terminal-1928557542-r1" x="1464" y="239.6" textLength="12.2" clip-path="url(#terminal-1928557542-line-9)">
</text><text class="terminal-1928557542-r1" x="1464" y="264" textLength="12.2" clip-path="url(#terminal-1928557542-line-10)">
</text><text class="terminal-1928557542-r1" x="1464" y="288.4" textLength="12.2" clip-path="url(#terminal-1928557542-line-11)">
</text><text class="terminal-1928557542-r1" x="1464" y="312.8" textLength="12.2" clip-path="url(#terminal-1928557542-line-12)">
</text><text class="terminal-1928557542-r1" x="1464" y="337.2" textLength="12.2" clip-path="url(#terminal-1928557542-line-13)">
</text><text class="terminal-1928557542-r1" x="1464" y="361.6" textLength="12.2" clip-path="url(#terminal-1928557542-line-14)">
</text><text class="terminal-1928557542-r1" x="1464" y="386" textLength="12.2" clip-path="url(#terminal-1928557542-line-15)">
</text><text class="terminal-1928557542-r1" x="1464" y="410.4" textLength="12.2" clip-path="url(#terminal-1928557542-line-16)">
</text><text class="terminal-1928557542-r1" x="1464" y="434.8" textLength="12.2" clip-path="url(#terminal-1928557542-line-17)">
</text><text class="terminal-1928557542-r1" x="0" y="459.2" textLength="134.2" clip-path="url(#terminal-1928557542-line-18)">&#160;&#160;⡠⣒⠄&#160;&#160;⡔⢄⠔⡄</text><text class="terminal-1928557542-r2" x="170.8" y="459.2" textLength="146.4" clip-path="url(#terminal-1928557542-line-18)">Mistral&#160;Vibe</text><text class="terminal-1928557542-r1" x="317.2" y="459.2" textLength="122" clip-path="url(#terminal-1928557542-line-18)">&#160;v0.0.0&#160;·&#160;</text><text class="terminal-1928557542-r3" x="439.2" y="459.2" textLength="183" clip-path="url(#terminal-1928557542-line-18)">devstral-latest</text><text class="terminal-1928557542-r1" x="622.2" y="459.2" textLength="256.2" clip-path="url(#terminal-1928557542-line-18)">&#160;·&#160;[Subscription]&#160;Pro</text><text class="terminal-1928557542-r1" x="1464" y="459.2" textLength="12.2" clip-path="url(#terminal-1928557542-line-18)">
</text><text class="terminal-1928557542-r1" x="0" y="483.6" textLength="134.2" clip-path="url(#terminal-1928557542-line-19)">&#160;⢸⠸⣀⡔⢉⠱⣃⡢⣂⡣</text><text class="terminal-1928557542-r1" x="170.8" y="483.6" textLength="585.6" clip-path="url(#terminal-1928557542-line-19)">1&#160;model&#160;·&#160;2&#160;connectors&#160;·&#160;1&#160;MCP&#160;server&#160;·&#160;0&#160;skills</text><text class="terminal-1928557542-r1" x="1464" y="483.6" textLength="12.2" clip-path="url(#terminal-1928557542-line-19)">
</text><text class="terminal-1928557542-r1" x="0" y="508" textLength="134.2" clip-path="url(#terminal-1928557542-line-20)">&#160;&#160;⠉⠒⠣⠤⠵⠤⠬⠮⠆</text><text class="terminal-1928557542-r1" x="170.8" y="508" textLength="61" clip-path="url(#terminal-1928557542-line-20)">Type&#160;</text><text class="terminal-1928557542-r3" x="231.8" y="508" textLength="61" clip-path="url(#terminal-1928557542-line-20)">/help</text><text class="terminal-1928557542-r1" x="292.8" y="508" textLength="256.2" clip-path="url(#terminal-1928557542-line-20)">&#160;for&#160;more&#160;information</text><text class="terminal-1928557542-r1" x="1464" y="508" textLength="12.2" clip-path="url(#terminal-1928557542-line-20)">
</text><text class="terminal-1928557542-r1" x="1464" y="532.4" textLength="12.2" clip-path="url(#terminal-1928557542-line-21)">
</text><text class="terminal-1928557542-r1" x="1464" y="556.8" textLength="12.2" clip-path="url(#terminal-1928557542-line-22)">
</text><text class="terminal-1928557542-r4" x="0" y="581.2" textLength="12.2" clip-path="url(#terminal-1928557542-line-23)"></text><text class="terminal-1928557542-r2" x="24.4" y="581.2" textLength="48.8" clip-path="url(#terminal-1928557542-line-23)">/mcp</text><text class="terminal-1928557542-r1" x="1464" y="581.2" textLength="12.2" clip-path="url(#terminal-1928557542-line-23)">
</text><text class="terminal-1928557542-r5" x="24.4" y="605.6" textLength="12.2" clip-path="url(#terminal-1928557542-line-24)"></text><text class="terminal-1928557542-r1" x="48.8" y="605.6" textLength="256.2" clip-path="url(#terminal-1928557542-line-24)">MCP&#160;servers&#160;opened...</text><text class="terminal-1928557542-r1" x="1464" y="605.6" textLength="12.2" clip-path="url(#terminal-1928557542-line-24)">
</text><text class="terminal-1928557542-r1" x="1464" y="630" textLength="12.2" clip-path="url(#terminal-1928557542-line-25)">
</text><text class="terminal-1928557542-r1" x="1464" y="654.4" textLength="12.2" clip-path="url(#terminal-1928557542-line-26)">
</text><text class="terminal-1928557542-r5" x="0" y="678.8" textLength="1464" clip-path="url(#terminal-1928557542-line-27)">┌──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐</text><text class="terminal-1928557542-r1" x="1464" y="678.8" textLength="12.2" clip-path="url(#terminal-1928557542-line-27)">
</text><text class="terminal-1928557542-r5" x="0" y="703.2" textLength="12.2" clip-path="url(#terminal-1928557542-line-28)"></text><text class="terminal-1928557542-r6" x="24.4" y="703.2" textLength="195.2" clip-path="url(#terminal-1928557542-line-28)">Connector:&#160;slack</text><text class="terminal-1928557542-r5" x="1451.8" y="703.2" textLength="12.2" clip-path="url(#terminal-1928557542-line-28)"></text><text class="terminal-1928557542-r1" x="1464" y="703.2" textLength="12.2" clip-path="url(#terminal-1928557542-line-28)">
</text><text class="terminal-1928557542-r5" x="0" y="727.6" textLength="12.2" clip-path="url(#terminal-1928557542-line-29)"></text><text class="terminal-1928557542-r5" x="1451.8" y="727.6" textLength="12.2" clip-path="url(#terminal-1928557542-line-29)"></text><text class="terminal-1928557542-r1" x="1464" y="727.6" textLength="12.2" clip-path="url(#terminal-1928557542-line-29)">
</text><text class="terminal-1928557542-r5" x="0" y="752" textLength="12.2" clip-path="url(#terminal-1928557542-line-30)"></text><text class="terminal-1928557542-r7" x="36.6" y="752" textLength="183" clip-path="url(#terminal-1928557542-line-30)">search_messages</text><text class="terminal-1928557542-r7" x="219.6" y="752" textLength="317.2" clip-path="url(#terminal-1928557542-line-30)">&#160;&#160;-&#160;&#160;Search&#160;Slack&#160;messages</text><text class="terminal-1928557542-r5" x="1451.8" y="752" textLength="12.2" clip-path="url(#terminal-1928557542-line-30)"></text><text class="terminal-1928557542-r1" x="1464" y="752" textLength="12.2" clip-path="url(#terminal-1928557542-line-30)">
</text><text class="terminal-1928557542-r5" x="0" y="776.4" textLength="12.2" clip-path="url(#terminal-1928557542-line-31)"></text><text class="terminal-1928557542-r7" x="36.6" y="776.4" textLength="146.4" clip-path="url(#terminal-1928557542-line-31)">send_message</text><text class="terminal-1928557542-r1" x="183" y="776.4" textLength="305" clip-path="url(#terminal-1928557542-line-31)">&#160;&#160;-&#160;&#160;Send&#160;a&#160;Slack&#160;message</text><text class="terminal-1928557542-r5" x="1451.8" y="776.4" textLength="12.2" clip-path="url(#terminal-1928557542-line-31)"></text><text class="terminal-1928557542-r1" x="1464" y="776.4" textLength="12.2" clip-path="url(#terminal-1928557542-line-31)">
</text><text class="terminal-1928557542-r5" x="0" y="800.8" textLength="12.2" clip-path="url(#terminal-1928557542-line-32)"></text><text class="terminal-1928557542-r5" x="1451.8" y="800.8" textLength="12.2" clip-path="url(#terminal-1928557542-line-32)"></text><text class="terminal-1928557542-r1" x="1464" y="800.8" textLength="12.2" clip-path="url(#terminal-1928557542-line-32)">
</text><text class="terminal-1928557542-r5" x="0" y="825.2" textLength="12.2" clip-path="url(#terminal-1928557542-line-33)"></text><text class="terminal-1928557542-r5" x="24.4" y="825.2" textLength="597.8" clip-path="url(#terminal-1928557542-line-33)">↑↓&#160;Navigate&#160;&#160;Backspace&#160;Back&#160;&#160;R&#160;Refresh&#160;&#160;Esc&#160;Close</text><text class="terminal-1928557542-r5" x="1451.8" y="825.2" textLength="12.2" clip-path="url(#terminal-1928557542-line-33)"></text><text class="terminal-1928557542-r1" x="1464" y="825.2" textLength="12.2" clip-path="url(#terminal-1928557542-line-33)">
</text><text class="terminal-1928557542-r5" x="0" y="849.6" textLength="1464" clip-path="url(#terminal-1928557542-line-34)">└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘</text><text class="terminal-1928557542-r1" x="1464" y="849.6" textLength="12.2" clip-path="url(#terminal-1928557542-line-34)">
</text><text class="terminal-1928557542-r5" x="0" y="874" textLength="158.6" clip-path="url(#terminal-1928557542-line-35)">/test/workdir</text><text class="terminal-1928557542-r5" x="1256.6" y="874" textLength="207.4" clip-path="url(#terminal-1928557542-line-35)">0%&#160;of&#160;200k&#160;tokens</text>
<g class="terminal-matrix">
<text class="terminal-r1" x="1464" y="20" textLength="12.2" clip-path="url(#terminal-line-0)">
</text><text class="terminal-r1" x="1464" y="44.4" textLength="12.2" clip-path="url(#terminal-line-1)">
</text><text class="terminal-r1" x="1464" y="68.8" textLength="12.2" clip-path="url(#terminal-line-2)">
</text><text class="terminal-r1" x="1464" y="93.2" textLength="12.2" clip-path="url(#terminal-line-3)">
</text><text class="terminal-r1" x="1464" y="117.6" textLength="12.2" clip-path="url(#terminal-line-4)">
</text><text class="terminal-r1" x="1464" y="142" textLength="12.2" clip-path="url(#terminal-line-5)">
</text><text class="terminal-r1" x="1464" y="166.4" textLength="12.2" clip-path="url(#terminal-line-6)">
</text><text class="terminal-r1" x="1464" y="190.8" textLength="12.2" clip-path="url(#terminal-line-7)">
</text><text class="terminal-r1" x="1464" y="215.2" textLength="12.2" clip-path="url(#terminal-line-8)">
</text><text class="terminal-r1" x="1464" y="239.6" textLength="12.2" clip-path="url(#terminal-line-9)">
</text><text class="terminal-r1" x="1464" y="264" textLength="12.2" clip-path="url(#terminal-line-10)">
</text><text class="terminal-r1" x="1464" y="288.4" textLength="12.2" clip-path="url(#terminal-line-11)">
</text><text class="terminal-r1" x="1464" y="312.8" textLength="12.2" clip-path="url(#terminal-line-12)">
</text><text class="terminal-r1" x="1464" y="337.2" textLength="12.2" clip-path="url(#terminal-line-13)">
</text><text class="terminal-r1" x="1464" y="361.6" textLength="12.2" clip-path="url(#terminal-line-14)">
</text><text class="terminal-r1" x="1464" y="386" textLength="12.2" clip-path="url(#terminal-line-15)">
</text><text class="terminal-r1" x="1464" y="410.4" textLength="12.2" clip-path="url(#terminal-line-16)">
</text><text class="terminal-r1" x="1464" y="434.8" textLength="12.2" clip-path="url(#terminal-line-17)">
</text><text class="terminal-r1" x="0" y="459.2" textLength="134.2" clip-path="url(#terminal-line-18)">&#160;&#160;⡠⣒⠄&#160;&#160;⡔⢄⠔⡄</text><text class="terminal-r2" x="170.8" y="459.2" textLength="146.4" clip-path="url(#terminal-line-18)">Mistral&#160;Vibe</text><text class="terminal-r1" x="317.2" y="459.2" textLength="122" clip-path="url(#terminal-line-18)">&#160;v0.0.0&#160;·&#160;</text><text class="terminal-r3" x="439.2" y="459.2" textLength="244" clip-path="url(#terminal-line-18)">devstral-latest[off]</text><text class="terminal-r1" x="683.2" y="459.2" textLength="256.2" clip-path="url(#terminal-line-18)">&#160;·&#160;[Subscription]&#160;Pro</text><text class="terminal-r1" x="1464" y="459.2" textLength="12.2" clip-path="url(#terminal-line-18)">
</text><text class="terminal-r1" x="0" y="483.6" textLength="134.2" clip-path="url(#terminal-line-19)">&#160;⢸⠸⣀⡔⢉⠱⣃⡢⣂⡣</text><text class="terminal-r1" x="170.8" y="483.6" textLength="585.6" clip-path="url(#terminal-line-19)">1&#160;model&#160;·&#160;2&#160;connectors&#160;·&#160;1&#160;MCP&#160;server&#160;·&#160;0&#160;skills</text><text class="terminal-r1" x="1464" y="483.6" textLength="12.2" clip-path="url(#terminal-line-19)">
</text><text class="terminal-r1" x="0" y="508" textLength="134.2" clip-path="url(#terminal-line-20)">&#160;&#160;⠉⠒⠣⠤⠵⠤⠬⠮⠆</text><text class="terminal-r1" x="170.8" y="508" textLength="61" clip-path="url(#terminal-line-20)">Type&#160;</text><text class="terminal-r3" x="231.8" y="508" textLength="61" clip-path="url(#terminal-line-20)">/help</text><text class="terminal-r1" x="292.8" y="508" textLength="256.2" clip-path="url(#terminal-line-20)">&#160;for&#160;more&#160;information</text><text class="terminal-r1" x="1464" y="508" textLength="12.2" clip-path="url(#terminal-line-20)">
</text><text class="terminal-r1" x="1464" y="532.4" textLength="12.2" clip-path="url(#terminal-line-21)">
</text><text class="terminal-r1" x="1464" y="556.8" textLength="12.2" clip-path="url(#terminal-line-22)">
</text><text class="terminal-r4" x="0" y="581.2" textLength="12.2" clip-path="url(#terminal-line-23)"></text><text class="terminal-r2" x="24.4" y="581.2" textLength="48.8" clip-path="url(#terminal-line-23)">/mcp</text><text class="terminal-r1" x="1464" y="581.2" textLength="12.2" clip-path="url(#terminal-line-23)">
</text><text class="terminal-r5" x="24.4" y="605.6" textLength="12.2" clip-path="url(#terminal-line-24)"></text><text class="terminal-r1" x="48.8" y="605.6" textLength="256.2" clip-path="url(#terminal-line-24)">MCP&#160;servers&#160;opened...</text><text class="terminal-r1" x="1464" y="605.6" textLength="12.2" clip-path="url(#terminal-line-24)">
</text><text class="terminal-r1" x="1464" y="630" textLength="12.2" clip-path="url(#terminal-line-25)">
</text><text class="terminal-r1" x="1464" y="654.4" textLength="12.2" clip-path="url(#terminal-line-26)">
</text><text class="terminal-r5" x="0" y="678.8" textLength="1464" clip-path="url(#terminal-line-27)">┌──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐</text><text class="terminal-r1" x="1464" y="678.8" textLength="12.2" clip-path="url(#terminal-line-27)">
</text><text class="terminal-r5" x="0" y="703.2" textLength="12.2" clip-path="url(#terminal-line-28)"></text><text class="terminal-r6" x="24.4" y="703.2" textLength="195.2" clip-path="url(#terminal-line-28)">Connector:&#160;slack</text><text class="terminal-r5" x="1451.8" y="703.2" textLength="12.2" clip-path="url(#terminal-line-28)"></text><text class="terminal-r1" x="1464" y="703.2" textLength="12.2" clip-path="url(#terminal-line-28)">
</text><text class="terminal-r5" x="0" y="727.6" textLength="12.2" clip-path="url(#terminal-line-29)"></text><text class="terminal-r5" x="1451.8" y="727.6" textLength="12.2" clip-path="url(#terminal-line-29)"></text><text class="terminal-r1" x="1464" y="727.6" textLength="12.2" clip-path="url(#terminal-line-29)">
</text><text class="terminal-r5" x="0" y="752" textLength="12.2" clip-path="url(#terminal-line-30)"></text><text class="terminal-r7" x="36.6" y="752" textLength="183" clip-path="url(#terminal-line-30)">search_messages</text><text class="terminal-r7" x="219.6" y="752" textLength="317.2" clip-path="url(#terminal-line-30)">&#160;&#160;-&#160;&#160;Search&#160;Slack&#160;messages</text><text class="terminal-r5" x="1451.8" y="752" textLength="12.2" clip-path="url(#terminal-line-30)"></text><text class="terminal-r1" x="1464" y="752" textLength="12.2" clip-path="url(#terminal-line-30)">
</text><text class="terminal-r5" x="0" y="776.4" textLength="12.2" clip-path="url(#terminal-line-31)"></text><text class="terminal-r7" x="36.6" y="776.4" textLength="146.4" clip-path="url(#terminal-line-31)">send_message</text><text class="terminal-r1" x="183" y="776.4" textLength="305" clip-path="url(#terminal-line-31)">&#160;&#160;-&#160;&#160;Send&#160;a&#160;Slack&#160;message</text><text class="terminal-r5" x="1451.8" y="776.4" textLength="12.2" clip-path="url(#terminal-line-31)"></text><text class="terminal-r1" x="1464" y="776.4" textLength="12.2" clip-path="url(#terminal-line-31)">
</text><text class="terminal-r5" x="0" y="800.8" textLength="12.2" clip-path="url(#terminal-line-32)"></text><text class="terminal-r5" x="1451.8" y="800.8" textLength="12.2" clip-path="url(#terminal-line-32)"></text><text class="terminal-r1" x="1464" y="800.8" textLength="12.2" clip-path="url(#terminal-line-32)">
</text><text class="terminal-r5" x="0" y="825.2" textLength="12.2" clip-path="url(#terminal-line-33)"></text><text class="terminal-r5" x="24.4" y="825.2" textLength="854" clip-path="url(#terminal-line-33)">↑↓&#160;Navigate&#160;&#160;D&#160;Disable&#160;&#160;E&#160;Enable&#160;&#160;Backspace&#160;Back&#160;&#160;R&#160;Refresh&#160;&#160;Esc&#160;Close</text><text class="terminal-r5" x="1451.8" y="825.2" textLength="12.2" clip-path="url(#terminal-line-33)"></text><text class="terminal-r1" x="1464" y="825.2" textLength="12.2" clip-path="url(#terminal-line-33)">
</text><text class="terminal-r5" x="0" y="849.6" textLength="1464" clip-path="url(#terminal-line-34)">└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘</text><text class="terminal-r1" x="1464" y="849.6" textLength="12.2" clip-path="url(#terminal-line-34)">
</text><text class="terminal-r5" x="0" y="874" textLength="158.6" clip-path="url(#terminal-line-35)">/test/workdir</text><text class="terminal-r5" x="1256.6" y="874" textLength="207.4" clip-path="url(#terminal-line-35)">0%&#160;of&#160;200k&#160;tokens</text>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 17 KiB

After

Width:  |  Height:  |  Size: 15 KiB

Before After
Before After

View file

@ -19,185 +19,185 @@
font-weight: 700;
}
.terminal-4237726511-matrix {
.terminal-matrix {
font-family: Fira Code, monospace;
font-size: 20px;
line-height: 24.4px;
font-variant-east-asian: full-width;
}
.terminal-4237726511-title {
.terminal-title {
font-size: 18px;
font-weight: bold;
font-family: arial;
}
.terminal-4237726511-r1 { fill: #c5c8c6 }
.terminal-4237726511-r2 { fill: #ff8205;font-weight: bold }
.terminal-4237726511-r3 { fill: #68a0b3 }
.terminal-4237726511-r4 { fill: #ff8205 }
.terminal-4237726511-r5 { fill: #9a9b99 }
.terminal-4237726511-r6 { fill: #608ab1;font-weight: bold }
.terminal-4237726511-r7 { fill: #c5c8c6;font-weight: bold }
.terminal-r1 { fill: #c5c8c6 }
.terminal-r2 { fill: #ff8205;font-weight: bold }
.terminal-r3 { fill: #68a0b3 }
.terminal-r4 { fill: #ff8205 }
.terminal-r5 { fill: #9a9b99 }
.terminal-r6 { fill: #608ab1;font-weight: bold }
.terminal-r7 { fill: #c5c8c6;font-weight: bold }
</style>
<defs>
<clipPath id="terminal-4237726511-clip-terminal">
<clipPath id="terminal-clip-terminal">
<rect x="0" y="0" width="1463.0" height="877.4" />
</clipPath>
<clipPath id="terminal-4237726511-line-0">
<clipPath id="terminal-line-0">
<rect x="0" y="1.5" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-4237726511-line-1">
<clipPath id="terminal-line-1">
<rect x="0" y="25.9" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-4237726511-line-2">
<clipPath id="terminal-line-2">
<rect x="0" y="50.3" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-4237726511-line-3">
<clipPath id="terminal-line-3">
<rect x="0" y="74.7" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-4237726511-line-4">
<clipPath id="terminal-line-4">
<rect x="0" y="99.1" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-4237726511-line-5">
<clipPath id="terminal-line-5">
<rect x="0" y="123.5" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-4237726511-line-6">
<clipPath id="terminal-line-6">
<rect x="0" y="147.9" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-4237726511-line-7">
<clipPath id="terminal-line-7">
<rect x="0" y="172.3" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-4237726511-line-8">
<clipPath id="terminal-line-8">
<rect x="0" y="196.7" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-4237726511-line-9">
<clipPath id="terminal-line-9">
<rect x="0" y="221.1" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-4237726511-line-10">
<clipPath id="terminal-line-10">
<rect x="0" y="245.5" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-4237726511-line-11">
<clipPath id="terminal-line-11">
<rect x="0" y="269.9" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-4237726511-line-12">
<clipPath id="terminal-line-12">
<rect x="0" y="294.3" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-4237726511-line-13">
<clipPath id="terminal-line-13">
<rect x="0" y="318.7" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-4237726511-line-14">
<clipPath id="terminal-line-14">
<rect x="0" y="343.1" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-4237726511-line-15">
<clipPath id="terminal-line-15">
<rect x="0" y="367.5" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-4237726511-line-16">
<clipPath id="terminal-line-16">
<rect x="0" y="391.9" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-4237726511-line-17">
<clipPath id="terminal-line-17">
<rect x="0" y="416.3" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-4237726511-line-18">
<clipPath id="terminal-line-18">
<rect x="0" y="440.7" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-4237726511-line-19">
<clipPath id="terminal-line-19">
<rect x="0" y="465.1" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-4237726511-line-20">
<clipPath id="terminal-line-20">
<rect x="0" y="489.5" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-4237726511-line-21">
<clipPath id="terminal-line-21">
<rect x="0" y="513.9" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-4237726511-line-22">
<clipPath id="terminal-line-22">
<rect x="0" y="538.3" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-4237726511-line-23">
<clipPath id="terminal-line-23">
<rect x="0" y="562.7" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-4237726511-line-24">
<clipPath id="terminal-line-24">
<rect x="0" y="587.1" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-4237726511-line-25">
<clipPath id="terminal-line-25">
<rect x="0" y="611.5" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-4237726511-line-26">
<clipPath id="terminal-line-26">
<rect x="0" y="635.9" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-4237726511-line-27">
<clipPath id="terminal-line-27">
<rect x="0" y="660.3" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-4237726511-line-28">
<clipPath id="terminal-line-28">
<rect x="0" y="684.7" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-4237726511-line-29">
<clipPath id="terminal-line-29">
<rect x="0" y="709.1" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-4237726511-line-30">
<clipPath id="terminal-line-30">
<rect x="0" y="733.5" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-4237726511-line-31">
<clipPath id="terminal-line-31">
<rect x="0" y="757.9" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-4237726511-line-32">
<clipPath id="terminal-line-32">
<rect x="0" y="782.3" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-4237726511-line-33">
<clipPath id="terminal-line-33">
<rect x="0" y="806.7" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-4237726511-line-34">
<clipPath id="terminal-line-34">
<rect x="0" y="831.1" width="1464" height="24.65"/>
</clipPath>
</defs>
<rect fill="#292929" stroke="rgba(255,255,255,0.35)" stroke-width="1" x="1" y="1" width="1480" height="926.4" rx="8"/><text class="terminal-4237726511-title" fill="#c5c8c6" text-anchor="middle" x="740" y="27">SnapshotTestAppWithMcpServers</text>
<rect fill="#292929" stroke="rgba(255,255,255,0.35)" stroke-width="1" x="1" y="1" width="1480" height="926.4" rx="8"/><text class="terminal-title" fill="#c5c8c6" text-anchor="middle" x="740" y="27">SnapshotTestAppWithMcpServers</text>
<g transform="translate(26,22)">
<circle cx="0" cy="0" r="7" fill="#ff5f57"/>
<circle cx="22" cy="0" r="7" fill="#febc2e"/>
<circle cx="44" cy="0" r="7" fill="#28c840"/>
</g>
<g transform="translate(9, 41)" clip-path="url(#terminal-4237726511-clip-terminal)">
<g transform="translate(9, 41)" clip-path="url(#terminal-clip-terminal)">
<rect fill="#608ab1" x="36.6" y="757.9" width="109.8" height="24.65" shape-rendering="crispEdges"/><rect fill="#608ab1" x="146.4" y="757.9" width="378.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#608ab1" x="524.6" y="757.9" width="902.8" height="24.65" shape-rendering="crispEdges"/>
<g class="terminal-4237726511-matrix">
<text class="terminal-4237726511-r1" x="1464" y="20" textLength="12.2" clip-path="url(#terminal-4237726511-line-0)">
</text><text class="terminal-4237726511-r1" x="1464" y="44.4" textLength="12.2" clip-path="url(#terminal-4237726511-line-1)">
</text><text class="terminal-4237726511-r1" x="1464" y="68.8" textLength="12.2" clip-path="url(#terminal-4237726511-line-2)">
</text><text class="terminal-4237726511-r1" x="1464" y="93.2" textLength="12.2" clip-path="url(#terminal-4237726511-line-3)">
</text><text class="terminal-4237726511-r1" x="1464" y="117.6" textLength="12.2" clip-path="url(#terminal-4237726511-line-4)">
</text><text class="terminal-4237726511-r1" x="1464" y="142" textLength="12.2" clip-path="url(#terminal-4237726511-line-5)">
</text><text class="terminal-4237726511-r1" x="1464" y="166.4" textLength="12.2" clip-path="url(#terminal-4237726511-line-6)">
</text><text class="terminal-4237726511-r1" x="1464" y="190.8" textLength="12.2" clip-path="url(#terminal-4237726511-line-7)">
</text><text class="terminal-4237726511-r1" x="1464" y="215.2" textLength="12.2" clip-path="url(#terminal-4237726511-line-8)">
</text><text class="terminal-4237726511-r1" x="1464" y="239.6" textLength="12.2" clip-path="url(#terminal-4237726511-line-9)">
</text><text class="terminal-4237726511-r1" x="1464" y="264" textLength="12.2" clip-path="url(#terminal-4237726511-line-10)">
</text><text class="terminal-4237726511-r1" x="1464" y="288.4" textLength="12.2" clip-path="url(#terminal-4237726511-line-11)">
</text><text class="terminal-4237726511-r1" x="1464" y="312.8" textLength="12.2" clip-path="url(#terminal-4237726511-line-12)">
</text><text class="terminal-4237726511-r1" x="1464" y="337.2" textLength="12.2" clip-path="url(#terminal-4237726511-line-13)">
</text><text class="terminal-4237726511-r1" x="1464" y="361.6" textLength="12.2" clip-path="url(#terminal-4237726511-line-14)">
</text><text class="terminal-4237726511-r1" x="1464" y="386" textLength="12.2" clip-path="url(#terminal-4237726511-line-15)">
</text><text class="terminal-4237726511-r1" x="1464" y="410.4" textLength="12.2" clip-path="url(#terminal-4237726511-line-16)">
</text><text class="terminal-4237726511-r1" x="1464" y="434.8" textLength="12.2" clip-path="url(#terminal-4237726511-line-17)">
</text><text class="terminal-4237726511-r1" x="1464" y="459.2" textLength="12.2" clip-path="url(#terminal-4237726511-line-18)">
</text><text class="terminal-4237726511-r1" x="0" y="483.6" textLength="134.2" clip-path="url(#terminal-4237726511-line-19)">&#160;&#160;⡠⣒⠄&#160;&#160;⡔⢄⠔⡄</text><text class="terminal-4237726511-r2" x="170.8" y="483.6" textLength="146.4" clip-path="url(#terminal-4237726511-line-19)">Mistral&#160;Vibe</text><text class="terminal-4237726511-r1" x="317.2" y="483.6" textLength="122" clip-path="url(#terminal-4237726511-line-19)">&#160;v0.0.0&#160;·&#160;</text><text class="terminal-4237726511-r3" x="439.2" y="483.6" textLength="183" clip-path="url(#terminal-4237726511-line-19)">devstral-latest</text><text class="terminal-4237726511-r1" x="622.2" y="483.6" textLength="256.2" clip-path="url(#terminal-4237726511-line-19)">&#160;·&#160;[Subscription]&#160;Pro</text><text class="terminal-4237726511-r1" x="1464" y="483.6" textLength="12.2" clip-path="url(#terminal-4237726511-line-19)">
</text><text class="terminal-4237726511-r1" x="0" y="508" textLength="134.2" clip-path="url(#terminal-4237726511-line-20)">&#160;⢸⠸⣀⡔⢉⠱⣃⡢⣂⡣</text><text class="terminal-4237726511-r1" x="170.8" y="508" textLength="414.8" clip-path="url(#terminal-4237726511-line-20)">1&#160;model&#160;·&#160;2&#160;MCP&#160;servers&#160;·&#160;0&#160;skills</text><text class="terminal-4237726511-r1" x="1464" y="508" textLength="12.2" clip-path="url(#terminal-4237726511-line-20)">
</text><text class="terminal-4237726511-r1" x="0" y="532.4" textLength="134.2" clip-path="url(#terminal-4237726511-line-21)">&#160;&#160;⠉⠒⠣⠤⠵⠤⠬⠮⠆</text><text class="terminal-4237726511-r1" x="170.8" y="532.4" textLength="61" clip-path="url(#terminal-4237726511-line-21)">Type&#160;</text><text class="terminal-4237726511-r3" x="231.8" y="532.4" textLength="61" clip-path="url(#terminal-4237726511-line-21)">/help</text><text class="terminal-4237726511-r1" x="292.8" y="532.4" textLength="256.2" clip-path="url(#terminal-4237726511-line-21)">&#160;for&#160;more&#160;information</text><text class="terminal-4237726511-r1" x="1464" y="532.4" textLength="12.2" clip-path="url(#terminal-4237726511-line-21)">
</text><text class="terminal-4237726511-r1" x="1464" y="556.8" textLength="12.2" clip-path="url(#terminal-4237726511-line-22)">
</text><text class="terminal-4237726511-r1" x="1464" y="581.2" textLength="12.2" clip-path="url(#terminal-4237726511-line-23)">
</text><text class="terminal-4237726511-r4" x="0" y="605.6" textLength="12.2" clip-path="url(#terminal-4237726511-line-24)"></text><text class="terminal-4237726511-r2" x="24.4" y="605.6" textLength="48.8" clip-path="url(#terminal-4237726511-line-24)">/mcp</text><text class="terminal-4237726511-r1" x="1464" y="605.6" textLength="12.2" clip-path="url(#terminal-4237726511-line-24)">
</text><text class="terminal-4237726511-r5" x="24.4" y="630" textLength="12.2" clip-path="url(#terminal-4237726511-line-25)"></text><text class="terminal-4237726511-r1" x="48.8" y="630" textLength="256.2" clip-path="url(#terminal-4237726511-line-25)">MCP&#160;servers&#160;opened...</text><text class="terminal-4237726511-r1" x="1464" y="630" textLength="12.2" clip-path="url(#terminal-4237726511-line-25)">
</text><text class="terminal-4237726511-r1" x="1464" y="654.4" textLength="12.2" clip-path="url(#terminal-4237726511-line-26)">
</text><text class="terminal-4237726511-r1" x="1464" y="678.8" textLength="12.2" clip-path="url(#terminal-4237726511-line-27)">
</text><text class="terminal-4237726511-r5" x="0" y="703.2" textLength="1464" clip-path="url(#terminal-4237726511-line-28)">┌──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐</text><text class="terminal-4237726511-r1" x="1464" y="703.2" textLength="12.2" clip-path="url(#terminal-4237726511-line-28)">
</text><text class="terminal-4237726511-r5" x="0" y="727.6" textLength="12.2" clip-path="url(#terminal-4237726511-line-29)"></text><text class="terminal-4237726511-r6" x="24.4" y="727.6" textLength="268.4" clip-path="url(#terminal-4237726511-line-29)">MCP&#160;Server:&#160;filesystem</text><text class="terminal-4237726511-r5" x="1451.8" y="727.6" textLength="12.2" clip-path="url(#terminal-4237726511-line-29)"></text><text class="terminal-4237726511-r1" x="1464" y="727.6" textLength="12.2" clip-path="url(#terminal-4237726511-line-29)">
</text><text class="terminal-4237726511-r5" x="0" y="752" textLength="12.2" clip-path="url(#terminal-4237726511-line-30)"></text><text class="terminal-4237726511-r5" x="1451.8" y="752" textLength="12.2" clip-path="url(#terminal-4237726511-line-30)"></text><text class="terminal-4237726511-r1" x="1464" y="752" textLength="12.2" clip-path="url(#terminal-4237726511-line-30)">
</text><text class="terminal-4237726511-r5" x="0" y="776.4" textLength="12.2" clip-path="url(#terminal-4237726511-line-31)"></text><text class="terminal-4237726511-r7" x="36.6" y="776.4" textLength="109.8" clip-path="url(#terminal-4237726511-line-31)">fake_tool</text><text class="terminal-4237726511-r7" x="146.4" y="776.4" textLength="378.2" clip-path="url(#terminal-4237726511-line-31)">&#160;&#160;-&#160;&#160;A&#160;fake&#160;tool&#160;for&#160;filesystem</text><text class="terminal-4237726511-r5" x="1451.8" y="776.4" textLength="12.2" clip-path="url(#terminal-4237726511-line-31)"></text><text class="terminal-4237726511-r1" x="1464" y="776.4" textLength="12.2" clip-path="url(#terminal-4237726511-line-31)">
</text><text class="terminal-4237726511-r5" x="0" y="800.8" textLength="12.2" clip-path="url(#terminal-4237726511-line-32)"></text><text class="terminal-4237726511-r5" x="1451.8" y="800.8" textLength="12.2" clip-path="url(#terminal-4237726511-line-32)"></text><text class="terminal-4237726511-r1" x="1464" y="800.8" textLength="12.2" clip-path="url(#terminal-4237726511-line-32)">
</text><text class="terminal-4237726511-r5" x="0" y="825.2" textLength="12.2" clip-path="url(#terminal-4237726511-line-33)"></text><text class="terminal-4237726511-r5" x="24.4" y="825.2" textLength="597.8" clip-path="url(#terminal-4237726511-line-33)">↑↓&#160;Navigate&#160;&#160;Backspace&#160;Back&#160;&#160;R&#160;Refresh&#160;&#160;Esc&#160;Close</text><text class="terminal-4237726511-r5" x="1451.8" y="825.2" textLength="12.2" clip-path="url(#terminal-4237726511-line-33)"></text><text class="terminal-4237726511-r1" x="1464" y="825.2" textLength="12.2" clip-path="url(#terminal-4237726511-line-33)">
</text><text class="terminal-4237726511-r5" x="0" y="849.6" textLength="1464" clip-path="url(#terminal-4237726511-line-34)">└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘</text><text class="terminal-4237726511-r1" x="1464" y="849.6" textLength="12.2" clip-path="url(#terminal-4237726511-line-34)">
</text><text class="terminal-4237726511-r5" x="0" y="874" textLength="158.6" clip-path="url(#terminal-4237726511-line-35)">/test/workdir</text><text class="terminal-4237726511-r5" x="1256.6" y="874" textLength="207.4" clip-path="url(#terminal-4237726511-line-35)">0%&#160;of&#160;200k&#160;tokens</text>
<g class="terminal-matrix">
<text class="terminal-r1" x="1464" y="20" textLength="12.2" clip-path="url(#terminal-line-0)">
</text><text class="terminal-r1" x="1464" y="44.4" textLength="12.2" clip-path="url(#terminal-line-1)">
</text><text class="terminal-r1" x="1464" y="68.8" textLength="12.2" clip-path="url(#terminal-line-2)">
</text><text class="terminal-r1" x="1464" y="93.2" textLength="12.2" clip-path="url(#terminal-line-3)">
</text><text class="terminal-r1" x="1464" y="117.6" textLength="12.2" clip-path="url(#terminal-line-4)">
</text><text class="terminal-r1" x="1464" y="142" textLength="12.2" clip-path="url(#terminal-line-5)">
</text><text class="terminal-r1" x="1464" y="166.4" textLength="12.2" clip-path="url(#terminal-line-6)">
</text><text class="terminal-r1" x="1464" y="190.8" textLength="12.2" clip-path="url(#terminal-line-7)">
</text><text class="terminal-r1" x="1464" y="215.2" textLength="12.2" clip-path="url(#terminal-line-8)">
</text><text class="terminal-r1" x="1464" y="239.6" textLength="12.2" clip-path="url(#terminal-line-9)">
</text><text class="terminal-r1" x="1464" y="264" textLength="12.2" clip-path="url(#terminal-line-10)">
</text><text class="terminal-r1" x="1464" y="288.4" textLength="12.2" clip-path="url(#terminal-line-11)">
</text><text class="terminal-r1" x="1464" y="312.8" textLength="12.2" clip-path="url(#terminal-line-12)">
</text><text class="terminal-r1" x="1464" y="337.2" textLength="12.2" clip-path="url(#terminal-line-13)">
</text><text class="terminal-r1" x="1464" y="361.6" textLength="12.2" clip-path="url(#terminal-line-14)">
</text><text class="terminal-r1" x="1464" y="386" textLength="12.2" clip-path="url(#terminal-line-15)">
</text><text class="terminal-r1" x="1464" y="410.4" textLength="12.2" clip-path="url(#terminal-line-16)">
</text><text class="terminal-r1" x="1464" y="434.8" textLength="12.2" clip-path="url(#terminal-line-17)">
</text><text class="terminal-r1" x="1464" y="459.2" textLength="12.2" clip-path="url(#terminal-line-18)">
</text><text class="terminal-r1" x="0" y="483.6" textLength="134.2" clip-path="url(#terminal-line-19)">&#160;&#160;⡠⣒⠄&#160;&#160;⡔⢄⠔⡄</text><text class="terminal-r2" x="170.8" y="483.6" textLength="146.4" clip-path="url(#terminal-line-19)">Mistral&#160;Vibe</text><text class="terminal-r1" x="317.2" y="483.6" textLength="122" clip-path="url(#terminal-line-19)">&#160;v0.0.0&#160;·&#160;</text><text class="terminal-r3" x="439.2" y="483.6" textLength="244" clip-path="url(#terminal-line-19)">devstral-latest[off]</text><text class="terminal-r1" x="683.2" y="483.6" textLength="256.2" clip-path="url(#terminal-line-19)">&#160;·&#160;[Subscription]&#160;Pro</text><text class="terminal-r1" x="1464" y="483.6" textLength="12.2" clip-path="url(#terminal-line-19)">
</text><text class="terminal-r1" x="0" y="508" textLength="134.2" clip-path="url(#terminal-line-20)">&#160;⢸⠸⣀⡔⢉⠱⣃⡢⣂⡣</text><text class="terminal-r1" x="170.8" y="508" textLength="414.8" clip-path="url(#terminal-line-20)">1&#160;model&#160;·&#160;2&#160;MCP&#160;servers&#160;·&#160;0&#160;skills</text><text class="terminal-r1" x="1464" y="508" textLength="12.2" clip-path="url(#terminal-line-20)">
</text><text class="terminal-r1" x="0" y="532.4" textLength="134.2" clip-path="url(#terminal-line-21)">&#160;&#160;⠉⠒⠣⠤⠵⠤⠬⠮⠆</text><text class="terminal-r1" x="170.8" y="532.4" textLength="61" clip-path="url(#terminal-line-21)">Type&#160;</text><text class="terminal-r3" x="231.8" y="532.4" textLength="61" clip-path="url(#terminal-line-21)">/help</text><text class="terminal-r1" x="292.8" y="532.4" textLength="256.2" clip-path="url(#terminal-line-21)">&#160;for&#160;more&#160;information</text><text class="terminal-r1" x="1464" y="532.4" textLength="12.2" clip-path="url(#terminal-line-21)">
</text><text class="terminal-r1" x="1464" y="556.8" textLength="12.2" clip-path="url(#terminal-line-22)">
</text><text class="terminal-r1" x="1464" y="581.2" textLength="12.2" clip-path="url(#terminal-line-23)">
</text><text class="terminal-r4" x="0" y="605.6" textLength="12.2" clip-path="url(#terminal-line-24)"></text><text class="terminal-r2" x="24.4" y="605.6" textLength="48.8" clip-path="url(#terminal-line-24)">/mcp</text><text class="terminal-r1" x="1464" y="605.6" textLength="12.2" clip-path="url(#terminal-line-24)">
</text><text class="terminal-r5" x="24.4" y="630" textLength="12.2" clip-path="url(#terminal-line-25)"></text><text class="terminal-r1" x="48.8" y="630" textLength="256.2" clip-path="url(#terminal-line-25)">MCP&#160;servers&#160;opened...</text><text class="terminal-r1" x="1464" y="630" textLength="12.2" clip-path="url(#terminal-line-25)">
</text><text class="terminal-r1" x="1464" y="654.4" textLength="12.2" clip-path="url(#terminal-line-26)">
</text><text class="terminal-r1" x="1464" y="678.8" textLength="12.2" clip-path="url(#terminal-line-27)">
</text><text class="terminal-r5" x="0" y="703.2" textLength="1464" clip-path="url(#terminal-line-28)">┌──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐</text><text class="terminal-r1" x="1464" y="703.2" textLength="12.2" clip-path="url(#terminal-line-28)">
</text><text class="terminal-r5" x="0" y="727.6" textLength="12.2" clip-path="url(#terminal-line-29)"></text><text class="terminal-r6" x="24.4" y="727.6" textLength="268.4" clip-path="url(#terminal-line-29)">MCP&#160;Server:&#160;filesystem</text><text class="terminal-r5" x="1451.8" y="727.6" textLength="12.2" clip-path="url(#terminal-line-29)"></text><text class="terminal-r1" x="1464" y="727.6" textLength="12.2" clip-path="url(#terminal-line-29)">
</text><text class="terminal-r5" x="0" y="752" textLength="12.2" clip-path="url(#terminal-line-30)"></text><text class="terminal-r5" x="1451.8" y="752" textLength="12.2" clip-path="url(#terminal-line-30)"></text><text class="terminal-r1" x="1464" y="752" textLength="12.2" clip-path="url(#terminal-line-30)">
</text><text class="terminal-r5" x="0" y="776.4" textLength="12.2" clip-path="url(#terminal-line-31)"></text><text class="terminal-r7" x="36.6" y="776.4" textLength="109.8" clip-path="url(#terminal-line-31)">fake_tool</text><text class="terminal-r7" x="146.4" y="776.4" textLength="378.2" clip-path="url(#terminal-line-31)">&#160;&#160;-&#160;&#160;A&#160;fake&#160;tool&#160;for&#160;filesystem</text><text class="terminal-r5" x="1451.8" y="776.4" textLength="12.2" clip-path="url(#terminal-line-31)"></text><text class="terminal-r1" x="1464" y="776.4" textLength="12.2" clip-path="url(#terminal-line-31)">
</text><text class="terminal-r5" x="0" y="800.8" textLength="12.2" clip-path="url(#terminal-line-32)"></text><text class="terminal-r5" x="1451.8" y="800.8" textLength="12.2" clip-path="url(#terminal-line-32)"></text><text class="terminal-r1" x="1464" y="800.8" textLength="12.2" clip-path="url(#terminal-line-32)">
</text><text class="terminal-r5" x="0" y="825.2" textLength="12.2" clip-path="url(#terminal-line-33)"></text><text class="terminal-r5" x="24.4" y="825.2" textLength="854" clip-path="url(#terminal-line-33)">↑↓&#160;Navigate&#160;&#160;D&#160;Disable&#160;&#160;E&#160;Enable&#160;&#160;Backspace&#160;Back&#160;&#160;R&#160;Refresh&#160;&#160;Esc&#160;Close</text><text class="terminal-r5" x="1451.8" y="825.2" textLength="12.2" clip-path="url(#terminal-line-33)"></text><text class="terminal-r1" x="1464" y="825.2" textLength="12.2" clip-path="url(#terminal-line-33)">
</text><text class="terminal-r5" x="0" y="849.6" textLength="1464" clip-path="url(#terminal-line-34)">└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘</text><text class="terminal-r1" x="1464" y="849.6" textLength="12.2" clip-path="url(#terminal-line-34)">
</text><text class="terminal-r5" x="0" y="874" textLength="158.6" clip-path="url(#terminal-line-35)">/test/workdir</text><text class="terminal-r5" x="1256.6" y="874" textLength="207.4" clip-path="url(#terminal-line-35)">0%&#160;of&#160;200k&#160;tokens</text>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 17 KiB

After

Width:  |  Height:  |  Size: 15 KiB

Before After
Before After

View file

@ -19,183 +19,183 @@
font-weight: 700;
}
.terminal-7514237046-matrix {
.terminal-matrix {
font-family: Fira Code, monospace;
font-size: 20px;
line-height: 24.4px;
font-variant-east-asian: full-width;
}
.terminal-7514237046-title {
.terminal-title {
font-size: 18px;
font-weight: bold;
font-family: arial;
}
.terminal-7514237046-r1 { fill: #c5c8c6 }
.terminal-7514237046-r2 { fill: #ff8205;font-weight: bold }
.terminal-7514237046-r3 { fill: #68a0b3 }
.terminal-7514237046-r4 { fill: #ff8205 }
.terminal-7514237046-r5 { fill: #9a9b99 }
.terminal-r1 { fill: #c5c8c6 }
.terminal-r2 { fill: #ff8205;font-weight: bold }
.terminal-r3 { fill: #68a0b3 }
.terminal-r4 { fill: #ff8205 }
.terminal-r5 { fill: #9a9b99 }
</style>
<defs>
<clipPath id="terminal-7514237046-clip-terminal">
<clipPath id="terminal-clip-terminal">
<rect x="0" y="0" width="1463.0" height="877.4" />
</clipPath>
<clipPath id="terminal-7514237046-line-0">
<clipPath id="terminal-line-0">
<rect x="0" y="1.5" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-7514237046-line-1">
<clipPath id="terminal-line-1">
<rect x="0" y="25.9" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-7514237046-line-2">
<clipPath id="terminal-line-2">
<rect x="0" y="50.3" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-7514237046-line-3">
<clipPath id="terminal-line-3">
<rect x="0" y="74.7" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-7514237046-line-4">
<clipPath id="terminal-line-4">
<rect x="0" y="99.1" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-7514237046-line-5">
<clipPath id="terminal-line-5">
<rect x="0" y="123.5" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-7514237046-line-6">
<clipPath id="terminal-line-6">
<rect x="0" y="147.9" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-7514237046-line-7">
<clipPath id="terminal-line-7">
<rect x="0" y="172.3" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-7514237046-line-8">
<clipPath id="terminal-line-8">
<rect x="0" y="196.7" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-7514237046-line-9">
<clipPath id="terminal-line-9">
<rect x="0" y="221.1" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-7514237046-line-10">
<clipPath id="terminal-line-10">
<rect x="0" y="245.5" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-7514237046-line-11">
<clipPath id="terminal-line-11">
<rect x="0" y="269.9" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-7514237046-line-12">
<clipPath id="terminal-line-12">
<rect x="0" y="294.3" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-7514237046-line-13">
<clipPath id="terminal-line-13">
<rect x="0" y="318.7" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-7514237046-line-14">
<clipPath id="terminal-line-14">
<rect x="0" y="343.1" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-7514237046-line-15">
<clipPath id="terminal-line-15">
<rect x="0" y="367.5" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-7514237046-line-16">
<clipPath id="terminal-line-16">
<rect x="0" y="391.9" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-7514237046-line-17">
<clipPath id="terminal-line-17">
<rect x="0" y="416.3" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-7514237046-line-18">
<clipPath id="terminal-line-18">
<rect x="0" y="440.7" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-7514237046-line-19">
<clipPath id="terminal-line-19">
<rect x="0" y="465.1" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-7514237046-line-20">
<clipPath id="terminal-line-20">
<rect x="0" y="489.5" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-7514237046-line-21">
<clipPath id="terminal-line-21">
<rect x="0" y="513.9" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-7514237046-line-22">
<clipPath id="terminal-line-22">
<rect x="0" y="538.3" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-7514237046-line-23">
<clipPath id="terminal-line-23">
<rect x="0" y="562.7" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-7514237046-line-24">
<clipPath id="terminal-line-24">
<rect x="0" y="587.1" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-7514237046-line-25">
<clipPath id="terminal-line-25">
<rect x="0" y="611.5" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-7514237046-line-26">
<clipPath id="terminal-line-26">
<rect x="0" y="635.9" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-7514237046-line-27">
<clipPath id="terminal-line-27">
<rect x="0" y="660.3" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-7514237046-line-28">
<clipPath id="terminal-line-28">
<rect x="0" y="684.7" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-7514237046-line-29">
<clipPath id="terminal-line-29">
<rect x="0" y="709.1" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-7514237046-line-30">
<clipPath id="terminal-line-30">
<rect x="0" y="733.5" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-7514237046-line-31">
<clipPath id="terminal-line-31">
<rect x="0" y="757.9" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-7514237046-line-32">
<clipPath id="terminal-line-32">
<rect x="0" y="782.3" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-7514237046-line-33">
<clipPath id="terminal-line-33">
<rect x="0" y="806.7" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-7514237046-line-34">
<clipPath id="terminal-line-34">
<rect x="0" y="831.1" width="1464" height="24.65"/>
</clipPath>
</defs>
<rect fill="#292929" stroke="rgba(255,255,255,0.35)" stroke-width="1" x="1" y="1" width="1480" height="926.4" rx="8"/><text class="terminal-7514237046-title" fill="#c5c8c6" text-anchor="middle" x="740" y="27">SnapshotTestAppWithMcpServers</text>
<rect fill="#292929" stroke="rgba(255,255,255,0.35)" stroke-width="1" x="1" y="1" width="1480" height="926.4" rx="8"/><text class="terminal-title" fill="#c5c8c6" text-anchor="middle" x="740" y="27">SnapshotTestAppWithMcpServers</text>
<g transform="translate(26,22)">
<circle cx="0" cy="0" r="7" fill="#ff5f57"/>
<circle cx="22" cy="0" r="7" fill="#febc2e"/>
<circle cx="44" cy="0" r="7" fill="#28c840"/>
</g>
<g transform="translate(9, 41)" clip-path="url(#terminal-7514237046-clip-terminal)">
<g transform="translate(9, 41)" clip-path="url(#terminal-clip-terminal)">
<g class="terminal-7514237046-matrix">
<text class="terminal-7514237046-r1" x="1464" y="20" textLength="12.2" clip-path="url(#terminal-7514237046-line-0)">
</text><text class="terminal-7514237046-r1" x="1464" y="44.4" textLength="12.2" clip-path="url(#terminal-7514237046-line-1)">
</text><text class="terminal-7514237046-r1" x="1464" y="68.8" textLength="12.2" clip-path="url(#terminal-7514237046-line-2)">
</text><text class="terminal-7514237046-r1" x="1464" y="93.2" textLength="12.2" clip-path="url(#terminal-7514237046-line-3)">
</text><text class="terminal-7514237046-r1" x="1464" y="117.6" textLength="12.2" clip-path="url(#terminal-7514237046-line-4)">
</text><text class="terminal-7514237046-r1" x="1464" y="142" textLength="12.2" clip-path="url(#terminal-7514237046-line-5)">
</text><text class="terminal-7514237046-r1" x="1464" y="166.4" textLength="12.2" clip-path="url(#terminal-7514237046-line-6)">
</text><text class="terminal-7514237046-r1" x="1464" y="190.8" textLength="12.2" clip-path="url(#terminal-7514237046-line-7)">
</text><text class="terminal-7514237046-r1" x="1464" y="215.2" textLength="12.2" clip-path="url(#terminal-7514237046-line-8)">
</text><text class="terminal-7514237046-r1" x="1464" y="239.6" textLength="12.2" clip-path="url(#terminal-7514237046-line-9)">
</text><text class="terminal-7514237046-r1" x="1464" y="264" textLength="12.2" clip-path="url(#terminal-7514237046-line-10)">
</text><text class="terminal-7514237046-r1" x="1464" y="288.4" textLength="12.2" clip-path="url(#terminal-7514237046-line-11)">
</text><text class="terminal-7514237046-r1" x="1464" y="312.8" textLength="12.2" clip-path="url(#terminal-7514237046-line-12)">
</text><text class="terminal-7514237046-r1" x="1464" y="337.2" textLength="12.2" clip-path="url(#terminal-7514237046-line-13)">
</text><text class="terminal-7514237046-r1" x="1464" y="361.6" textLength="12.2" clip-path="url(#terminal-7514237046-line-14)">
</text><text class="terminal-7514237046-r1" x="1464" y="386" textLength="12.2" clip-path="url(#terminal-7514237046-line-15)">
</text><text class="terminal-7514237046-r1" x="1464" y="410.4" textLength="12.2" clip-path="url(#terminal-7514237046-line-16)">
</text><text class="terminal-7514237046-r1" x="1464" y="434.8" textLength="12.2" clip-path="url(#terminal-7514237046-line-17)">
</text><text class="terminal-7514237046-r1" x="1464" y="459.2" textLength="12.2" clip-path="url(#terminal-7514237046-line-18)">
</text><text class="terminal-7514237046-r1" x="1464" y="483.6" textLength="12.2" clip-path="url(#terminal-7514237046-line-19)">
</text><text class="terminal-7514237046-r1" x="0" y="508" textLength="134.2" clip-path="url(#terminal-7514237046-line-20)">&#160;&#160;⡠⣒⠄&#160;&#160;⡔⢄⠔⡄</text><text class="terminal-7514237046-r2" x="170.8" y="508" textLength="146.4" clip-path="url(#terminal-7514237046-line-20)">Mistral&#160;Vibe</text><text class="terminal-7514237046-r1" x="317.2" y="508" textLength="122" clip-path="url(#terminal-7514237046-line-20)">&#160;v0.0.0&#160;·&#160;</text><text class="terminal-7514237046-r3" x="439.2" y="508" textLength="183" clip-path="url(#terminal-7514237046-line-20)">devstral-latest</text><text class="terminal-7514237046-r1" x="622.2" y="508" textLength="256.2" clip-path="url(#terminal-7514237046-line-20)">&#160;·&#160;[Subscription]&#160;Pro</text><text class="terminal-7514237046-r1" x="1464" y="508" textLength="12.2" clip-path="url(#terminal-7514237046-line-20)">
</text><text class="terminal-7514237046-r1" x="0" y="532.4" textLength="134.2" clip-path="url(#terminal-7514237046-line-21)">&#160;⢸⠸⣀⡔⢉⠱⣃⡢⣂⡣</text><text class="terminal-7514237046-r1" x="170.8" y="532.4" textLength="414.8" clip-path="url(#terminal-7514237046-line-21)">1&#160;model&#160;·&#160;2&#160;MCP&#160;servers&#160;·&#160;0&#160;skills</text><text class="terminal-7514237046-r1" x="1464" y="532.4" textLength="12.2" clip-path="url(#terminal-7514237046-line-21)">
</text><text class="terminal-7514237046-r1" x="0" y="556.8" textLength="134.2" clip-path="url(#terminal-7514237046-line-22)">&#160;&#160;⠉⠒⠣⠤⠵⠤⠬⠮⠆</text><text class="terminal-7514237046-r1" x="170.8" y="556.8" textLength="61" clip-path="url(#terminal-7514237046-line-22)">Type&#160;</text><text class="terminal-7514237046-r3" x="231.8" y="556.8" textLength="61" clip-path="url(#terminal-7514237046-line-22)">/help</text><text class="terminal-7514237046-r1" x="292.8" y="556.8" textLength="256.2" clip-path="url(#terminal-7514237046-line-22)">&#160;for&#160;more&#160;information</text><text class="terminal-7514237046-r1" x="1464" y="556.8" textLength="12.2" clip-path="url(#terminal-7514237046-line-22)">
</text><text class="terminal-7514237046-r1" x="1464" y="581.2" textLength="12.2" clip-path="url(#terminal-7514237046-line-23)">
</text><text class="terminal-7514237046-r1" x="1464" y="605.6" textLength="12.2" clip-path="url(#terminal-7514237046-line-24)">
</text><text class="terminal-7514237046-r4" x="0" y="630" textLength="12.2" clip-path="url(#terminal-7514237046-line-25)"></text><text class="terminal-7514237046-r2" x="24.4" y="630" textLength="48.8" clip-path="url(#terminal-7514237046-line-25)">/mcp</text><text class="terminal-7514237046-r1" x="1464" y="630" textLength="12.2" clip-path="url(#terminal-7514237046-line-25)">
</text><text class="terminal-7514237046-r5" x="24.4" y="654.4" textLength="12.2" clip-path="url(#terminal-7514237046-line-26)"></text><text class="terminal-7514237046-r1" x="48.8" y="654.4" textLength="256.2" clip-path="url(#terminal-7514237046-line-26)">MCP&#160;servers&#160;opened...</text><text class="terminal-7514237046-r1" x="1464" y="654.4" textLength="12.2" clip-path="url(#terminal-7514237046-line-26)">
</text><text class="terminal-7514237046-r5" x="24.4" y="678.8" textLength="12.2" clip-path="url(#terminal-7514237046-line-27)"></text><text class="terminal-7514237046-r1" x="48.8" y="678.8" textLength="231.8" clip-path="url(#terminal-7514237046-line-27)">MCP&#160;servers&#160;closed.</text><text class="terminal-7514237046-r1" x="1464" y="678.8" textLength="12.2" clip-path="url(#terminal-7514237046-line-27)">
</text><text class="terminal-7514237046-r1" x="1464" y="703.2" textLength="12.2" clip-path="url(#terminal-7514237046-line-28)">
</text><text class="terminal-7514237046-r1" x="1464" y="727.6" textLength="12.2" clip-path="url(#terminal-7514237046-line-29)">
</text><text class="terminal-7514237046-r5" x="0" y="752" textLength="1464" clip-path="url(#terminal-7514237046-line-30)">┌────────────────────────────────────────────────────────────────────────────────────────────────────────────&#160;default&#160;─┐</text><text class="terminal-7514237046-r1" x="1464" y="752" textLength="12.2" clip-path="url(#terminal-7514237046-line-30)">
</text><text class="terminal-7514237046-r5" x="0" y="776.4" textLength="12.2" clip-path="url(#terminal-7514237046-line-31)"></text><text class="terminal-7514237046-r2" x="24.4" y="776.4" textLength="12.2" clip-path="url(#terminal-7514237046-line-31)">&gt;</text><text class="terminal-7514237046-r5" x="1451.8" y="776.4" textLength="12.2" clip-path="url(#terminal-7514237046-line-31)"></text><text class="terminal-7514237046-r1" x="1464" y="776.4" textLength="12.2" clip-path="url(#terminal-7514237046-line-31)">
</text><text class="terminal-7514237046-r5" x="0" y="800.8" textLength="12.2" clip-path="url(#terminal-7514237046-line-32)"></text><text class="terminal-7514237046-r5" x="1451.8" y="800.8" textLength="12.2" clip-path="url(#terminal-7514237046-line-32)"></text><text class="terminal-7514237046-r1" x="1464" y="800.8" textLength="12.2" clip-path="url(#terminal-7514237046-line-32)">
</text><text class="terminal-7514237046-r5" x="0" y="825.2" textLength="12.2" clip-path="url(#terminal-7514237046-line-33)"></text><text class="terminal-7514237046-r5" x="1451.8" y="825.2" textLength="12.2" clip-path="url(#terminal-7514237046-line-33)"></text><text class="terminal-7514237046-r1" x="1464" y="825.2" textLength="12.2" clip-path="url(#terminal-7514237046-line-33)">
</text><text class="terminal-7514237046-r5" x="0" y="849.6" textLength="1464" clip-path="url(#terminal-7514237046-line-34)">└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘</text><text class="terminal-7514237046-r1" x="1464" y="849.6" textLength="12.2" clip-path="url(#terminal-7514237046-line-34)">
</text><text class="terminal-7514237046-r5" x="0" y="874" textLength="158.6" clip-path="url(#terminal-7514237046-line-35)">/test/workdir</text><text class="terminal-7514237046-r5" x="1256.6" y="874" textLength="207.4" clip-path="url(#terminal-7514237046-line-35)">0%&#160;of&#160;200k&#160;tokens</text>
<g class="terminal-matrix">
<text class="terminal-r1" x="1464" y="20" textLength="12.2" clip-path="url(#terminal-line-0)">
</text><text class="terminal-r1" x="1464" y="44.4" textLength="12.2" clip-path="url(#terminal-line-1)">
</text><text class="terminal-r1" x="1464" y="68.8" textLength="12.2" clip-path="url(#terminal-line-2)">
</text><text class="terminal-r1" x="1464" y="93.2" textLength="12.2" clip-path="url(#terminal-line-3)">
</text><text class="terminal-r1" x="1464" y="117.6" textLength="12.2" clip-path="url(#terminal-line-4)">
</text><text class="terminal-r1" x="1464" y="142" textLength="12.2" clip-path="url(#terminal-line-5)">
</text><text class="terminal-r1" x="1464" y="166.4" textLength="12.2" clip-path="url(#terminal-line-6)">
</text><text class="terminal-r1" x="1464" y="190.8" textLength="12.2" clip-path="url(#terminal-line-7)">
</text><text class="terminal-r1" x="1464" y="215.2" textLength="12.2" clip-path="url(#terminal-line-8)">
</text><text class="terminal-r1" x="1464" y="239.6" textLength="12.2" clip-path="url(#terminal-line-9)">
</text><text class="terminal-r1" x="1464" y="264" textLength="12.2" clip-path="url(#terminal-line-10)">
</text><text class="terminal-r1" x="1464" y="288.4" textLength="12.2" clip-path="url(#terminal-line-11)">
</text><text class="terminal-r1" x="1464" y="312.8" textLength="12.2" clip-path="url(#terminal-line-12)">
</text><text class="terminal-r1" x="1464" y="337.2" textLength="12.2" clip-path="url(#terminal-line-13)">
</text><text class="terminal-r1" x="1464" y="361.6" textLength="12.2" clip-path="url(#terminal-line-14)">
</text><text class="terminal-r1" x="1464" y="386" textLength="12.2" clip-path="url(#terminal-line-15)">
</text><text class="terminal-r1" x="1464" y="410.4" textLength="12.2" clip-path="url(#terminal-line-16)">
</text><text class="terminal-r1" x="1464" y="434.8" textLength="12.2" clip-path="url(#terminal-line-17)">
</text><text class="terminal-r1" x="1464" y="459.2" textLength="12.2" clip-path="url(#terminal-line-18)">
</text><text class="terminal-r1" x="1464" y="483.6" textLength="12.2" clip-path="url(#terminal-line-19)">
</text><text class="terminal-r1" x="0" y="508" textLength="134.2" clip-path="url(#terminal-line-20)">&#160;&#160;⡠⣒⠄&#160;&#160;⡔⢄⠔⡄</text><text class="terminal-r2" x="170.8" y="508" textLength="146.4" clip-path="url(#terminal-line-20)">Mistral&#160;Vibe</text><text class="terminal-r1" x="317.2" y="508" textLength="122" clip-path="url(#terminal-line-20)">&#160;v0.0.0&#160;·&#160;</text><text class="terminal-r3" x="439.2" y="508" textLength="244" clip-path="url(#terminal-line-20)">devstral-latest[off]</text><text class="terminal-r1" x="683.2" y="508" textLength="256.2" clip-path="url(#terminal-line-20)">&#160;·&#160;[Subscription]&#160;Pro</text><text class="terminal-r1" x="1464" y="508" textLength="12.2" clip-path="url(#terminal-line-20)">
</text><text class="terminal-r1" x="0" y="532.4" textLength="134.2" clip-path="url(#terminal-line-21)">&#160;⢸⠸⣀⡔⢉⠱⣃⡢⣂⡣</text><text class="terminal-r1" x="170.8" y="532.4" textLength="414.8" clip-path="url(#terminal-line-21)">1&#160;model&#160;·&#160;2&#160;MCP&#160;servers&#160;·&#160;0&#160;skills</text><text class="terminal-r1" x="1464" y="532.4" textLength="12.2" clip-path="url(#terminal-line-21)">
</text><text class="terminal-r1" x="0" y="556.8" textLength="134.2" clip-path="url(#terminal-line-22)">&#160;&#160;⠉⠒⠣⠤⠵⠤⠬⠮⠆</text><text class="terminal-r1" x="170.8" y="556.8" textLength="61" clip-path="url(#terminal-line-22)">Type&#160;</text><text class="terminal-r3" x="231.8" y="556.8" textLength="61" clip-path="url(#terminal-line-22)">/help</text><text class="terminal-r1" x="292.8" y="556.8" textLength="256.2" clip-path="url(#terminal-line-22)">&#160;for&#160;more&#160;information</text><text class="terminal-r1" x="1464" y="556.8" textLength="12.2" clip-path="url(#terminal-line-22)">
</text><text class="terminal-r1" x="1464" y="581.2" textLength="12.2" clip-path="url(#terminal-line-23)">
</text><text class="terminal-r1" x="1464" y="605.6" textLength="12.2" clip-path="url(#terminal-line-24)">
</text><text class="terminal-r4" x="0" y="630" textLength="12.2" clip-path="url(#terminal-line-25)"></text><text class="terminal-r2" x="24.4" y="630" textLength="48.8" clip-path="url(#terminal-line-25)">/mcp</text><text class="terminal-r1" x="1464" y="630" textLength="12.2" clip-path="url(#terminal-line-25)">
</text><text class="terminal-r5" x="24.4" y="654.4" textLength="12.2" clip-path="url(#terminal-line-26)"></text><text class="terminal-r1" x="48.8" y="654.4" textLength="256.2" clip-path="url(#terminal-line-26)">MCP&#160;servers&#160;opened...</text><text class="terminal-r1" x="1464" y="654.4" textLength="12.2" clip-path="url(#terminal-line-26)">
</text><text class="terminal-r5" x="24.4" y="678.8" textLength="12.2" clip-path="url(#terminal-line-27)"></text><text class="terminal-r1" x="48.8" y="678.8" textLength="231.8" clip-path="url(#terminal-line-27)">MCP&#160;servers&#160;closed.</text><text class="terminal-r1" x="1464" y="678.8" textLength="12.2" clip-path="url(#terminal-line-27)">
</text><text class="terminal-r1" x="1464" y="703.2" textLength="12.2" clip-path="url(#terminal-line-28)">
</text><text class="terminal-r1" x="1464" y="727.6" textLength="12.2" clip-path="url(#terminal-line-29)">
</text><text class="terminal-r5" x="0" y="752" textLength="1464" clip-path="url(#terminal-line-30)">┌────────────────────────────────────────────────────────────────────────────────────────────────────────────&#160;default&#160;─┐</text><text class="terminal-r1" x="1464" y="752" textLength="12.2" clip-path="url(#terminal-line-30)">
</text><text class="terminal-r5" x="0" y="776.4" textLength="12.2" clip-path="url(#terminal-line-31)"></text><text class="terminal-r2" x="24.4" y="776.4" textLength="12.2" clip-path="url(#terminal-line-31)">&gt;</text><text class="terminal-r5" x="1451.8" y="776.4" textLength="12.2" clip-path="url(#terminal-line-31)"></text><text class="terminal-r1" x="1464" y="776.4" textLength="12.2" clip-path="url(#terminal-line-31)">
</text><text class="terminal-r5" x="0" y="800.8" textLength="12.2" clip-path="url(#terminal-line-32)"></text><text class="terminal-r5" x="1451.8" y="800.8" textLength="12.2" clip-path="url(#terminal-line-32)"></text><text class="terminal-r1" x="1464" y="800.8" textLength="12.2" clip-path="url(#terminal-line-32)">
</text><text class="terminal-r5" x="0" y="825.2" textLength="12.2" clip-path="url(#terminal-line-33)"></text><text class="terminal-r5" x="1451.8" y="825.2" textLength="12.2" clip-path="url(#terminal-line-33)"></text><text class="terminal-r1" x="1464" y="825.2" textLength="12.2" clip-path="url(#terminal-line-33)">
</text><text class="terminal-r5" x="0" y="849.6" textLength="1464" clip-path="url(#terminal-line-34)">└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘</text><text class="terminal-r1" x="1464" y="849.6" textLength="12.2" clip-path="url(#terminal-line-34)">
</text><text class="terminal-r5" x="0" y="874" textLength="158.6" clip-path="url(#terminal-line-35)">/test/workdir</text><text class="terminal-r5" x="1256.6" y="874" textLength="207.4" clip-path="url(#terminal-line-35)">0%&#160;of&#160;200k&#160;tokens</text>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 14 KiB

Before After
Before After

View file

@ -181,7 +181,7 @@
</text><text class="terminal-9108451134-r1" x="1464" y="459.2" textLength="12.2" clip-path="url(#terminal-9108451134-line-18)">
</text><text class="terminal-9108451134-r1" x="1464" y="483.6" textLength="12.2" clip-path="url(#terminal-9108451134-line-19)">
</text><text class="terminal-9108451134-r1" x="1464" y="508" textLength="12.2" clip-path="url(#terminal-9108451134-line-20)">
</text><text class="terminal-9108451134-r1" x="0" y="532.4" textLength="134.2" clip-path="url(#terminal-9108451134-line-21)">&#160;&#160;⡠⣒⠄&#160;&#160;⡔⢄⠔⡄</text><text class="terminal-9108451134-r2" x="170.8" y="532.4" textLength="146.4" clip-path="url(#terminal-9108451134-line-21)">Mistral&#160;Vibe</text><text class="terminal-9108451134-r1" x="317.2" y="532.4" textLength="122" clip-path="url(#terminal-9108451134-line-21)">&#160;v0.0.0&#160;·&#160;</text><text class="terminal-9108451134-r3" x="439.2" y="532.4" textLength="183" clip-path="url(#terminal-9108451134-line-21)">devstral-latest</text><text class="terminal-9108451134-r1" x="622.2" y="532.4" textLength="256.2" clip-path="url(#terminal-9108451134-line-21)">&#160;·&#160;[Subscription]&#160;Pro</text><text class="terminal-9108451134-r1" x="1464" y="532.4" textLength="12.2" clip-path="url(#terminal-9108451134-line-21)">
</text><text class="terminal-9108451134-r1" x="0" y="532.4" textLength="134.2" clip-path="url(#terminal-9108451134-line-21)">&#160;&#160;⡠⣒⠄&#160;&#160;⡔⢄⠔⡄</text><text class="terminal-9108451134-r2" x="170.8" y="532.4" textLength="146.4" clip-path="url(#terminal-9108451134-line-21)">Mistral&#160;Vibe</text><text class="terminal-9108451134-r1" x="317.2" y="532.4" textLength="122" clip-path="url(#terminal-9108451134-line-21)">&#160;v0.0.0&#160;·&#160;</text><text class="terminal-9108451134-r3" x="439.2" y="532.4" textLength="244" clip-path="url(#terminal-9108451134-line-21)">devstral-latest[off]</text><text class="terminal-9108451134-r1" x="683.2" y="532.4" textLength="256.2" clip-path="url(#terminal-9108451134-line-21)">&#160;·&#160;[Subscription]&#160;Pro</text><text class="terminal-9108451134-r1" x="1464" y="532.4" textLength="12.2" clip-path="url(#terminal-9108451134-line-21)">
</text><text class="terminal-9108451134-r1" x="0" y="556.8" textLength="134.2" clip-path="url(#terminal-9108451134-line-22)">&#160;⢸⠸⣀⡔⢉⠱⣃⡢⣂⡣</text><text class="terminal-9108451134-r1" x="170.8" y="556.8" textLength="414.8" clip-path="url(#terminal-9108451134-line-22)">1&#160;model&#160;·&#160;0&#160;MCP&#160;servers&#160;·&#160;0&#160;skills</text><text class="terminal-9108451134-r1" x="1464" y="556.8" textLength="12.2" clip-path="url(#terminal-9108451134-line-22)">
</text><text class="terminal-9108451134-r1" x="0" y="581.2" textLength="134.2" clip-path="url(#terminal-9108451134-line-23)">&#160;&#160;⠉⠒⠣⠤⠵⠤⠬⠮⠆</text><text class="terminal-9108451134-r1" x="170.8" y="581.2" textLength="61" clip-path="url(#terminal-9108451134-line-23)">Type&#160;</text><text class="terminal-9108451134-r3" x="231.8" y="581.2" textLength="61" clip-path="url(#terminal-9108451134-line-23)">/help</text><text class="terminal-9108451134-r1" x="292.8" y="581.2" textLength="256.2" clip-path="url(#terminal-9108451134-line-23)">&#160;for&#160;more&#160;information</text><text class="terminal-9108451134-r1" x="1464" y="581.2" textLength="12.2" clip-path="url(#terminal-9108451134-line-23)">
</text><text class="terminal-9108451134-r1" x="1464" y="605.6" textLength="12.2" clip-path="url(#terminal-9108451134-line-24)">

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 15 KiB

Before After
Before After

View file

@ -19,187 +19,187 @@
font-weight: 700;
}
.terminal-606925797-matrix {
.terminal-matrix {
font-family: Fira Code, monospace;
font-size: 20px;
line-height: 24.4px;
font-variant-east-asian: full-width;
}
.terminal-606925797-title {
.terminal-title {
font-size: 18px;
font-weight: bold;
font-family: arial;
}
.terminal-606925797-r1 { fill: #c5c8c6 }
.terminal-606925797-r2 { fill: #ff8205;font-weight: bold }
.terminal-606925797-r3 { fill: #68a0b3 }
.terminal-606925797-r4 { fill: #ff8205 }
.terminal-606925797-r5 { fill: #9a9b99 }
.terminal-606925797-r6 { fill: #608ab1;font-weight: bold }
.terminal-606925797-r7 { fill: #c5c8c6;font-weight: bold }
.terminal-606925797-r8 { fill: #9cafbd;font-weight: bold }
.terminal-606925797-r9 { fill: #868887 }
.terminal-r1 { fill: #c5c8c6 }
.terminal-r2 { fill: #ff8205;font-weight: bold }
.terminal-r3 { fill: #68a0b3 }
.terminal-r4 { fill: #ff8205 }
.terminal-r5 { fill: #9a9b99 }
.terminal-r6 { fill: #608ab1;font-weight: bold }
.terminal-r7 { fill: #c5c8c6;font-weight: bold }
.terminal-r8 { fill: #9cafbd;font-weight: bold }
.terminal-r9 { fill: #868887 }
</style>
<defs>
<clipPath id="terminal-606925797-clip-terminal">
<clipPath id="terminal-clip-terminal">
<rect x="0" y="0" width="1463.0" height="877.4" />
</clipPath>
<clipPath id="terminal-606925797-line-0">
<clipPath id="terminal-line-0">
<rect x="0" y="1.5" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-606925797-line-1">
<clipPath id="terminal-line-1">
<rect x="0" y="25.9" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-606925797-line-2">
<clipPath id="terminal-line-2">
<rect x="0" y="50.3" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-606925797-line-3">
<clipPath id="terminal-line-3">
<rect x="0" y="74.7" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-606925797-line-4">
<clipPath id="terminal-line-4">
<rect x="0" y="99.1" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-606925797-line-5">
<clipPath id="terminal-line-5">
<rect x="0" y="123.5" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-606925797-line-6">
<clipPath id="terminal-line-6">
<rect x="0" y="147.9" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-606925797-line-7">
<clipPath id="terminal-line-7">
<rect x="0" y="172.3" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-606925797-line-8">
<clipPath id="terminal-line-8">
<rect x="0" y="196.7" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-606925797-line-9">
<clipPath id="terminal-line-9">
<rect x="0" y="221.1" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-606925797-line-10">
<clipPath id="terminal-line-10">
<rect x="0" y="245.5" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-606925797-line-11">
<clipPath id="terminal-line-11">
<rect x="0" y="269.9" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-606925797-line-12">
<clipPath id="terminal-line-12">
<rect x="0" y="294.3" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-606925797-line-13">
<clipPath id="terminal-line-13">
<rect x="0" y="318.7" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-606925797-line-14">
<clipPath id="terminal-line-14">
<rect x="0" y="343.1" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-606925797-line-15">
<clipPath id="terminal-line-15">
<rect x="0" y="367.5" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-606925797-line-16">
<clipPath id="terminal-line-16">
<rect x="0" y="391.9" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-606925797-line-17">
<clipPath id="terminal-line-17">
<rect x="0" y="416.3" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-606925797-line-18">
<clipPath id="terminal-line-18">
<rect x="0" y="440.7" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-606925797-line-19">
<clipPath id="terminal-line-19">
<rect x="0" y="465.1" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-606925797-line-20">
<clipPath id="terminal-line-20">
<rect x="0" y="489.5" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-606925797-line-21">
<clipPath id="terminal-line-21">
<rect x="0" y="513.9" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-606925797-line-22">
<clipPath id="terminal-line-22">
<rect x="0" y="538.3" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-606925797-line-23">
<clipPath id="terminal-line-23">
<rect x="0" y="562.7" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-606925797-line-24">
<clipPath id="terminal-line-24">
<rect x="0" y="587.1" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-606925797-line-25">
<clipPath id="terminal-line-25">
<rect x="0" y="611.5" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-606925797-line-26">
<clipPath id="terminal-line-26">
<rect x="0" y="635.9" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-606925797-line-27">
<clipPath id="terminal-line-27">
<rect x="0" y="660.3" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-606925797-line-28">
<clipPath id="terminal-line-28">
<rect x="0" y="684.7" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-606925797-line-29">
<clipPath id="terminal-line-29">
<rect x="0" y="709.1" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-606925797-line-30">
<clipPath id="terminal-line-30">
<rect x="0" y="733.5" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-606925797-line-31">
<clipPath id="terminal-line-31">
<rect x="0" y="757.9" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-606925797-line-32">
<clipPath id="terminal-line-32">
<rect x="0" y="782.3" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-606925797-line-33">
<clipPath id="terminal-line-33">
<rect x="0" y="806.7" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-606925797-line-34">
<clipPath id="terminal-line-34">
<rect x="0" y="831.1" width="1464" height="24.65"/>
</clipPath>
</defs>
<rect fill="#292929" stroke="rgba(255,255,255,0.35)" stroke-width="1" x="1" y="1" width="1480" height="926.4" rx="8"/><text class="terminal-606925797-title" fill="#c5c8c6" text-anchor="middle" x="740" y="27">SnapshotTestAppWithMcpServers</text>
<rect fill="#292929" stroke="rgba(255,255,255,0.35)" stroke-width="1" x="1" y="1" width="1480" height="926.4" rx="8"/><text class="terminal-title" fill="#c5c8c6" text-anchor="middle" x="740" y="27">SnapshotTestAppWithMcpServers</text>
<g transform="translate(26,22)">
<circle cx="0" cy="0" r="7" fill="#ff5f57"/>
<circle cx="22" cy="0" r="7" fill="#febc2e"/>
<circle cx="44" cy="0" r="7" fill="#28c840"/>
</g>
<g transform="translate(9, 41)" clip-path="url(#terminal-606925797-clip-terminal)">
<g transform="translate(9, 41)" clip-path="url(#terminal-clip-terminal)">
<rect fill="#608ab1" x="36.6" y="733.5" width="146.4" height="24.65" shape-rendering="crispEdges"/><rect fill="#608ab1" x="183" y="733.5" width="109.8" height="24.65" shape-rendering="crispEdges"/><rect fill="#608ab1" x="292.8" y="733.5" width="97.6" height="24.65" shape-rendering="crispEdges"/><rect fill="#608ab1" x="390.4" y="733.5" width="1037" height="24.65" shape-rendering="crispEdges"/>
<g class="terminal-606925797-matrix">
<text class="terminal-606925797-r1" x="1464" y="20" textLength="12.2" clip-path="url(#terminal-606925797-line-0)">
</text><text class="terminal-606925797-r1" x="1464" y="44.4" textLength="12.2" clip-path="url(#terminal-606925797-line-1)">
</text><text class="terminal-606925797-r1" x="1464" y="68.8" textLength="12.2" clip-path="url(#terminal-606925797-line-2)">
</text><text class="terminal-606925797-r1" x="1464" y="93.2" textLength="12.2" clip-path="url(#terminal-606925797-line-3)">
</text><text class="terminal-606925797-r1" x="1464" y="117.6" textLength="12.2" clip-path="url(#terminal-606925797-line-4)">
</text><text class="terminal-606925797-r1" x="1464" y="142" textLength="12.2" clip-path="url(#terminal-606925797-line-5)">
</text><text class="terminal-606925797-r1" x="1464" y="166.4" textLength="12.2" clip-path="url(#terminal-606925797-line-6)">
</text><text class="terminal-606925797-r1" x="1464" y="190.8" textLength="12.2" clip-path="url(#terminal-606925797-line-7)">
</text><text class="terminal-606925797-r1" x="1464" y="215.2" textLength="12.2" clip-path="url(#terminal-606925797-line-8)">
</text><text class="terminal-606925797-r1" x="1464" y="239.6" textLength="12.2" clip-path="url(#terminal-606925797-line-9)">
</text><text class="terminal-606925797-r1" x="1464" y="264" textLength="12.2" clip-path="url(#terminal-606925797-line-10)">
</text><text class="terminal-606925797-r1" x="1464" y="288.4" textLength="12.2" clip-path="url(#terminal-606925797-line-11)">
</text><text class="terminal-606925797-r1" x="1464" y="312.8" textLength="12.2" clip-path="url(#terminal-606925797-line-12)">
</text><text class="terminal-606925797-r1" x="1464" y="337.2" textLength="12.2" clip-path="url(#terminal-606925797-line-13)">
</text><text class="terminal-606925797-r1" x="1464" y="361.6" textLength="12.2" clip-path="url(#terminal-606925797-line-14)">
</text><text class="terminal-606925797-r1" x="1464" y="386" textLength="12.2" clip-path="url(#terminal-606925797-line-15)">
</text><text class="terminal-606925797-r1" x="1464" y="410.4" textLength="12.2" clip-path="url(#terminal-606925797-line-16)">
</text><text class="terminal-606925797-r1" x="0" y="434.8" textLength="134.2" clip-path="url(#terminal-606925797-line-17)">&#160;&#160;⡠⣒⠄&#160;&#160;⡔⢄⠔⡄</text><text class="terminal-606925797-r2" x="170.8" y="434.8" textLength="146.4" clip-path="url(#terminal-606925797-line-17)">Mistral&#160;Vibe</text><text class="terminal-606925797-r1" x="317.2" y="434.8" textLength="122" clip-path="url(#terminal-606925797-line-17)">&#160;v0.0.0&#160;·&#160;</text><text class="terminal-606925797-r3" x="439.2" y="434.8" textLength="183" clip-path="url(#terminal-606925797-line-17)">devstral-latest</text><text class="terminal-606925797-r1" x="622.2" y="434.8" textLength="256.2" clip-path="url(#terminal-606925797-line-17)">&#160;·&#160;[Subscription]&#160;Pro</text><text class="terminal-606925797-r1" x="1464" y="434.8" textLength="12.2" clip-path="url(#terminal-606925797-line-17)">
</text><text class="terminal-606925797-r1" x="0" y="459.2" textLength="134.2" clip-path="url(#terminal-606925797-line-18)">&#160;⢸⠸⣀⡔⢉⠱⣃⡢⣂⡣</text><text class="terminal-606925797-r1" x="170.8" y="459.2" textLength="414.8" clip-path="url(#terminal-606925797-line-18)">1&#160;model&#160;·&#160;2&#160;MCP&#160;servers&#160;·&#160;0&#160;skills</text><text class="terminal-606925797-r1" x="1464" y="459.2" textLength="12.2" clip-path="url(#terminal-606925797-line-18)">
</text><text class="terminal-606925797-r1" x="0" y="483.6" textLength="134.2" clip-path="url(#terminal-606925797-line-19)">&#160;&#160;⠉⠒⠣⠤⠵⠤⠬⠮⠆</text><text class="terminal-606925797-r1" x="170.8" y="483.6" textLength="61" clip-path="url(#terminal-606925797-line-19)">Type&#160;</text><text class="terminal-606925797-r3" x="231.8" y="483.6" textLength="61" clip-path="url(#terminal-606925797-line-19)">/help</text><text class="terminal-606925797-r1" x="292.8" y="483.6" textLength="256.2" clip-path="url(#terminal-606925797-line-19)">&#160;for&#160;more&#160;information</text><text class="terminal-606925797-r1" x="1464" y="483.6" textLength="12.2" clip-path="url(#terminal-606925797-line-19)">
</text><text class="terminal-606925797-r1" x="1464" y="508" textLength="12.2" clip-path="url(#terminal-606925797-line-20)">
</text><text class="terminal-606925797-r1" x="1464" y="532.4" textLength="12.2" clip-path="url(#terminal-606925797-line-21)">
</text><text class="terminal-606925797-r4" x="0" y="556.8" textLength="12.2" clip-path="url(#terminal-606925797-line-22)"></text><text class="terminal-606925797-r2" x="24.4" y="556.8" textLength="48.8" clip-path="url(#terminal-606925797-line-22)">/mcp</text><text class="terminal-606925797-r1" x="1464" y="556.8" textLength="12.2" clip-path="url(#terminal-606925797-line-22)">
</text><text class="terminal-606925797-r5" x="24.4" y="581.2" textLength="12.2" clip-path="url(#terminal-606925797-line-23)"></text><text class="terminal-606925797-r1" x="48.8" y="581.2" textLength="256.2" clip-path="url(#terminal-606925797-line-23)">MCP&#160;servers&#160;opened...</text><text class="terminal-606925797-r1" x="1464" y="581.2" textLength="12.2" clip-path="url(#terminal-606925797-line-23)">
</text><text class="terminal-606925797-r1" x="1464" y="605.6" textLength="12.2" clip-path="url(#terminal-606925797-line-24)">
</text><text class="terminal-606925797-r1" x="1464" y="630" textLength="12.2" clip-path="url(#terminal-606925797-line-25)">
</text><text class="terminal-606925797-r5" x="0" y="654.4" textLength="1464" clip-path="url(#terminal-606925797-line-26)">┌──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐</text><text class="terminal-606925797-r1" x="1464" y="654.4" textLength="12.2" clip-path="url(#terminal-606925797-line-26)">
</text><text class="terminal-606925797-r5" x="0" y="678.8" textLength="12.2" clip-path="url(#terminal-606925797-line-27)"></text><text class="terminal-606925797-r6" x="24.4" y="678.8" textLength="134.2" clip-path="url(#terminal-606925797-line-27)">MCP&#160;Servers</text><text class="terminal-606925797-r5" x="1451.8" y="678.8" textLength="12.2" clip-path="url(#terminal-606925797-line-27)"></text><text class="terminal-606925797-r1" x="1464" y="678.8" textLength="12.2" clip-path="url(#terminal-606925797-line-27)">
</text><text class="terminal-606925797-r5" x="0" y="703.2" textLength="12.2" clip-path="url(#terminal-606925797-line-28)"></text><text class="terminal-606925797-r5" x="1451.8" y="703.2" textLength="12.2" clip-path="url(#terminal-606925797-line-28)"></text><text class="terminal-606925797-r1" x="1464" y="703.2" textLength="12.2" clip-path="url(#terminal-606925797-line-28)">
</text><text class="terminal-606925797-r5" x="0" y="727.6" textLength="12.2" clip-path="url(#terminal-606925797-line-29)"></text><text class="terminal-606925797-r7" x="36.6" y="727.6" textLength="207.4" clip-path="url(#terminal-606925797-line-29)">Local&#160;MCP&#160;Servers</text><text class="terminal-606925797-r5" x="1451.8" y="727.6" textLength="12.2" clip-path="url(#terminal-606925797-line-29)"></text><text class="terminal-606925797-r1" x="1464" y="727.6" textLength="12.2" clip-path="url(#terminal-606925797-line-29)">
</text><text class="terminal-606925797-r5" x="0" y="752" textLength="12.2" clip-path="url(#terminal-606925797-line-30)"></text><text class="terminal-606925797-r7" x="36.6" y="752" textLength="146.4" clip-path="url(#terminal-606925797-line-30)">&#160;&#160;filesystem</text><text class="terminal-606925797-r8" x="183" y="752" textLength="109.8" clip-path="url(#terminal-606925797-line-30)">&#160;&#160;[stdio]</text><text class="terminal-606925797-r8" x="292.8" y="752" textLength="97.6" clip-path="url(#terminal-606925797-line-30)">&#160;&#160;1&#160;tool</text><text class="terminal-606925797-r5" x="1451.8" y="752" textLength="12.2" clip-path="url(#terminal-606925797-line-30)"></text><text class="terminal-606925797-r1" x="1464" y="752" textLength="12.2" clip-path="url(#terminal-606925797-line-30)">
</text><text class="terminal-606925797-r5" x="0" y="776.4" textLength="12.2" clip-path="url(#terminal-606925797-line-31)"></text><text class="terminal-606925797-r1" x="36.6" y="776.4" textLength="146.4" clip-path="url(#terminal-606925797-line-31)">&#160;&#160;search&#160;&#160;&#160;&#160;</text><text class="terminal-606925797-r9" x="183" y="776.4" textLength="109.8" clip-path="url(#terminal-606925797-line-31)">&#160;&#160;[http]&#160;</text><text class="terminal-606925797-r9" x="292.8" y="776.4" textLength="97.6" clip-path="url(#terminal-606925797-line-31)">&#160;&#160;1&#160;tool</text><text class="terminal-606925797-r5" x="1451.8" y="776.4" textLength="12.2" clip-path="url(#terminal-606925797-line-31)"></text><text class="terminal-606925797-r1" x="1464" y="776.4" textLength="12.2" clip-path="url(#terminal-606925797-line-31)">
</text><text class="terminal-606925797-r5" x="0" y="800.8" textLength="12.2" clip-path="url(#terminal-606925797-line-32)"></text><text class="terminal-606925797-r5" x="1451.8" y="800.8" textLength="12.2" clip-path="url(#terminal-606925797-line-32)"></text><text class="terminal-606925797-r1" x="1464" y="800.8" textLength="12.2" clip-path="url(#terminal-606925797-line-32)">
</text><text class="terminal-606925797-r5" x="0" y="825.2" textLength="12.2" clip-path="url(#terminal-606925797-line-33)"></text><text class="terminal-606925797-r5" x="24.4" y="825.2" textLength="622.2" clip-path="url(#terminal-606925797-line-33)">↑↓&#160;Navigate&#160;&#160;Enter&#160;Show&#160;tools&#160;&#160;R&#160;Refresh&#160;&#160;Esc&#160;Close</text><text class="terminal-606925797-r5" x="1451.8" y="825.2" textLength="12.2" clip-path="url(#terminal-606925797-line-33)"></text><text class="terminal-606925797-r1" x="1464" y="825.2" textLength="12.2" clip-path="url(#terminal-606925797-line-33)">
</text><text class="terminal-606925797-r5" x="0" y="849.6" textLength="1464" clip-path="url(#terminal-606925797-line-34)">└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘</text><text class="terminal-606925797-r1" x="1464" y="849.6" textLength="12.2" clip-path="url(#terminal-606925797-line-34)">
</text><text class="terminal-606925797-r5" x="0" y="874" textLength="158.6" clip-path="url(#terminal-606925797-line-35)">/test/workdir</text><text class="terminal-606925797-r5" x="1256.6" y="874" textLength="207.4" clip-path="url(#terminal-606925797-line-35)">0%&#160;of&#160;200k&#160;tokens</text>
<g class="terminal-matrix">
<text class="terminal-r1" x="1464" y="20" textLength="12.2" clip-path="url(#terminal-line-0)">
</text><text class="terminal-r1" x="1464" y="44.4" textLength="12.2" clip-path="url(#terminal-line-1)">
</text><text class="terminal-r1" x="1464" y="68.8" textLength="12.2" clip-path="url(#terminal-line-2)">
</text><text class="terminal-r1" x="1464" y="93.2" textLength="12.2" clip-path="url(#terminal-line-3)">
</text><text class="terminal-r1" x="1464" y="117.6" textLength="12.2" clip-path="url(#terminal-line-4)">
</text><text class="terminal-r1" x="1464" y="142" textLength="12.2" clip-path="url(#terminal-line-5)">
</text><text class="terminal-r1" x="1464" y="166.4" textLength="12.2" clip-path="url(#terminal-line-6)">
</text><text class="terminal-r1" x="1464" y="190.8" textLength="12.2" clip-path="url(#terminal-line-7)">
</text><text class="terminal-r1" x="1464" y="215.2" textLength="12.2" clip-path="url(#terminal-line-8)">
</text><text class="terminal-r1" x="1464" y="239.6" textLength="12.2" clip-path="url(#terminal-line-9)">
</text><text class="terminal-r1" x="1464" y="264" textLength="12.2" clip-path="url(#terminal-line-10)">
</text><text class="terminal-r1" x="1464" y="288.4" textLength="12.2" clip-path="url(#terminal-line-11)">
</text><text class="terminal-r1" x="1464" y="312.8" textLength="12.2" clip-path="url(#terminal-line-12)">
</text><text class="terminal-r1" x="1464" y="337.2" textLength="12.2" clip-path="url(#terminal-line-13)">
</text><text class="terminal-r1" x="1464" y="361.6" textLength="12.2" clip-path="url(#terminal-line-14)">
</text><text class="terminal-r1" x="1464" y="386" textLength="12.2" clip-path="url(#terminal-line-15)">
</text><text class="terminal-r1" x="1464" y="410.4" textLength="12.2" clip-path="url(#terminal-line-16)">
</text><text class="terminal-r1" x="0" y="434.8" textLength="134.2" clip-path="url(#terminal-line-17)">&#160;&#160;⡠⣒⠄&#160;&#160;⡔⢄⠔⡄</text><text class="terminal-r2" x="170.8" y="434.8" textLength="146.4" clip-path="url(#terminal-line-17)">Mistral&#160;Vibe</text><text class="terminal-r1" x="317.2" y="434.8" textLength="122" clip-path="url(#terminal-line-17)">&#160;v0.0.0&#160;·&#160;</text><text class="terminal-r3" x="439.2" y="434.8" textLength="244" clip-path="url(#terminal-line-17)">devstral-latest[off]</text><text class="terminal-r1" x="683.2" y="434.8" textLength="256.2" clip-path="url(#terminal-line-17)">&#160;·&#160;[Subscription]&#160;Pro</text><text class="terminal-r1" x="1464" y="434.8" textLength="12.2" clip-path="url(#terminal-line-17)">
</text><text class="terminal-r1" x="0" y="459.2" textLength="134.2" clip-path="url(#terminal-line-18)">&#160;⢸⠸⣀⡔⢉⠱⣃⡢⣂⡣</text><text class="terminal-r1" x="170.8" y="459.2" textLength="414.8" clip-path="url(#terminal-line-18)">1&#160;model&#160;·&#160;2&#160;MCP&#160;servers&#160;·&#160;0&#160;skills</text><text class="terminal-r1" x="1464" y="459.2" textLength="12.2" clip-path="url(#terminal-line-18)">
</text><text class="terminal-r1" x="0" y="483.6" textLength="134.2" clip-path="url(#terminal-line-19)">&#160;&#160;⠉⠒⠣⠤⠵⠤⠬⠮⠆</text><text class="terminal-r1" x="170.8" y="483.6" textLength="61" clip-path="url(#terminal-line-19)">Type&#160;</text><text class="terminal-r3" x="231.8" y="483.6" textLength="61" clip-path="url(#terminal-line-19)">/help</text><text class="terminal-r1" x="292.8" y="483.6" textLength="256.2" clip-path="url(#terminal-line-19)">&#160;for&#160;more&#160;information</text><text class="terminal-r1" x="1464" y="483.6" textLength="12.2" clip-path="url(#terminal-line-19)">
</text><text class="terminal-r1" x="1464" y="508" textLength="12.2" clip-path="url(#terminal-line-20)">
</text><text class="terminal-r1" x="1464" y="532.4" textLength="12.2" clip-path="url(#terminal-line-21)">
</text><text class="terminal-r4" x="0" y="556.8" textLength="12.2" clip-path="url(#terminal-line-22)"></text><text class="terminal-r2" x="24.4" y="556.8" textLength="48.8" clip-path="url(#terminal-line-22)">/mcp</text><text class="terminal-r1" x="1464" y="556.8" textLength="12.2" clip-path="url(#terminal-line-22)">
</text><text class="terminal-r5" x="24.4" y="581.2" textLength="12.2" clip-path="url(#terminal-line-23)"></text><text class="terminal-r1" x="48.8" y="581.2" textLength="256.2" clip-path="url(#terminal-line-23)">MCP&#160;servers&#160;opened...</text><text class="terminal-r1" x="1464" y="581.2" textLength="12.2" clip-path="url(#terminal-line-23)">
</text><text class="terminal-r1" x="1464" y="605.6" textLength="12.2" clip-path="url(#terminal-line-24)">
</text><text class="terminal-r1" x="1464" y="630" textLength="12.2" clip-path="url(#terminal-line-25)">
</text><text class="terminal-r5" x="0" y="654.4" textLength="1464" clip-path="url(#terminal-line-26)">┌──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐</text><text class="terminal-r1" x="1464" y="654.4" textLength="12.2" clip-path="url(#terminal-line-26)">
</text><text class="terminal-r5" x="0" y="678.8" textLength="12.2" clip-path="url(#terminal-line-27)"></text><text class="terminal-r6" x="24.4" y="678.8" textLength="134.2" clip-path="url(#terminal-line-27)">MCP&#160;Servers</text><text class="terminal-r5" x="1451.8" y="678.8" textLength="12.2" clip-path="url(#terminal-line-27)"></text><text class="terminal-r1" x="1464" y="678.8" textLength="12.2" clip-path="url(#terminal-line-27)">
</text><text class="terminal-r5" x="0" y="703.2" textLength="12.2" clip-path="url(#terminal-line-28)"></text><text class="terminal-r5" x="1451.8" y="703.2" textLength="12.2" clip-path="url(#terminal-line-28)"></text><text class="terminal-r1" x="1464" y="703.2" textLength="12.2" clip-path="url(#terminal-line-28)">
</text><text class="terminal-r5" x="0" y="727.6" textLength="12.2" clip-path="url(#terminal-line-29)"></text><text class="terminal-r7" x="36.6" y="727.6" textLength="207.4" clip-path="url(#terminal-line-29)">Local&#160;MCP&#160;Servers</text><text class="terminal-r5" x="1451.8" y="727.6" textLength="12.2" clip-path="url(#terminal-line-29)"></text><text class="terminal-r1" x="1464" y="727.6" textLength="12.2" clip-path="url(#terminal-line-29)">
</text><text class="terminal-r5" x="0" y="752" textLength="12.2" clip-path="url(#terminal-line-30)"></text><text class="terminal-r7" x="36.6" y="752" textLength="146.4" clip-path="url(#terminal-line-30)">&#160;&#160;filesystem</text><text class="terminal-r8" x="183" y="752" textLength="109.8" clip-path="url(#terminal-line-30)">&#160;&#160;[stdio]</text><text class="terminal-r8" x="292.8" y="752" textLength="97.6" clip-path="url(#terminal-line-30)">&#160;&#160;1&#160;tool</text><text class="terminal-r5" x="1451.8" y="752" textLength="12.2" clip-path="url(#terminal-line-30)"></text><text class="terminal-r1" x="1464" y="752" textLength="12.2" clip-path="url(#terminal-line-30)">
</text><text class="terminal-r5" x="0" y="776.4" textLength="12.2" clip-path="url(#terminal-line-31)"></text><text class="terminal-r1" x="36.6" y="776.4" textLength="146.4" clip-path="url(#terminal-line-31)">&#160;&#160;search&#160;&#160;&#160;&#160;</text><text class="terminal-r9" x="183" y="776.4" textLength="109.8" clip-path="url(#terminal-line-31)">&#160;&#160;[http]&#160;</text><text class="terminal-r9" x="292.8" y="776.4" textLength="97.6" clip-path="url(#terminal-line-31)">&#160;&#160;1&#160;tool</text><text class="terminal-r5" x="1451.8" y="776.4" textLength="12.2" clip-path="url(#terminal-line-31)"></text><text class="terminal-r1" x="1464" y="776.4" textLength="12.2" clip-path="url(#terminal-line-31)">
</text><text class="terminal-r5" x="0" y="800.8" textLength="12.2" clip-path="url(#terminal-line-32)"></text><text class="terminal-r5" x="1451.8" y="800.8" textLength="12.2" clip-path="url(#terminal-line-32)"></text><text class="terminal-r1" x="1464" y="800.8" textLength="12.2" clip-path="url(#terminal-line-32)">
</text><text class="terminal-r5" x="0" y="825.2" textLength="12.2" clip-path="url(#terminal-line-33)"></text><text class="terminal-r5" x="24.4" y="825.2" textLength="878.4" clip-path="url(#terminal-line-33)">↑↓&#160;Navigate&#160;&#160;Enter&#160;Show&#160;tools&#160;&#160;D&#160;Disable&#160;&#160;E&#160;Enable&#160;&#160;R&#160;Refresh&#160;&#160;Esc&#160;Close</text><text class="terminal-r5" x="1451.8" y="825.2" textLength="12.2" clip-path="url(#terminal-line-33)"></text><text class="terminal-r1" x="1464" y="825.2" textLength="12.2" clip-path="url(#terminal-line-33)">
</text><text class="terminal-r5" x="0" y="849.6" textLength="1464" clip-path="url(#terminal-line-34)">└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘</text><text class="terminal-r1" x="1464" y="849.6" textLength="12.2" clip-path="url(#terminal-line-34)">
</text><text class="terminal-r5" x="0" y="874" textLength="158.6" clip-path="url(#terminal-line-35)">/test/workdir</text><text class="terminal-r5" x="1256.6" y="874" textLength="207.4" clip-path="url(#terminal-line-35)">0%&#160;of&#160;200k&#160;tokens</text>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 16 KiB

Before After
Before After

View file

@ -19,187 +19,187 @@
font-weight: 700;
}
.terminal-9601757275-matrix {
.terminal-matrix {
font-family: Fira Code, monospace;
font-size: 20px;
line-height: 24.4px;
font-variant-east-asian: full-width;
}
.terminal-9601757275-title {
.terminal-title {
font-size: 18px;
font-weight: bold;
font-family: arial;
}
.terminal-9601757275-r1 { fill: #c5c8c6 }
.terminal-9601757275-r2 { fill: #ff8205;font-weight: bold }
.terminal-9601757275-r3 { fill: #68a0b3 }
.terminal-9601757275-r4 { fill: #ff8205 }
.terminal-9601757275-r5 { fill: #9a9b99 }
.terminal-9601757275-r6 { fill: #608ab1;font-weight: bold }
.terminal-9601757275-r7 { fill: #c5c8c6;font-weight: bold }
.terminal-9601757275-r8 { fill: #868887 }
.terminal-9601757275-r9 { fill: #9cafbd;font-weight: bold }
.terminal-r1 { fill: #c5c8c6 }
.terminal-r2 { fill: #ff8205;font-weight: bold }
.terminal-r3 { fill: #68a0b3 }
.terminal-r4 { fill: #ff8205 }
.terminal-r5 { fill: #9a9b99 }
.terminal-r6 { fill: #608ab1;font-weight: bold }
.terminal-r7 { fill: #c5c8c6;font-weight: bold }
.terminal-r8 { fill: #868887 }
.terminal-r9 { fill: #9cafbd;font-weight: bold }
</style>
<defs>
<clipPath id="terminal-9601757275-clip-terminal">
<clipPath id="terminal-clip-terminal">
<rect x="0" y="0" width="1463.0" height="877.4" />
</clipPath>
<clipPath id="terminal-9601757275-line-0">
<clipPath id="terminal-line-0">
<rect x="0" y="1.5" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-9601757275-line-1">
<clipPath id="terminal-line-1">
<rect x="0" y="25.9" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-9601757275-line-2">
<clipPath id="terminal-line-2">
<rect x="0" y="50.3" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-9601757275-line-3">
<clipPath id="terminal-line-3">
<rect x="0" y="74.7" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-9601757275-line-4">
<clipPath id="terminal-line-4">
<rect x="0" y="99.1" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-9601757275-line-5">
<clipPath id="terminal-line-5">
<rect x="0" y="123.5" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-9601757275-line-6">
<clipPath id="terminal-line-6">
<rect x="0" y="147.9" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-9601757275-line-7">
<clipPath id="terminal-line-7">
<rect x="0" y="172.3" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-9601757275-line-8">
<clipPath id="terminal-line-8">
<rect x="0" y="196.7" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-9601757275-line-9">
<clipPath id="terminal-line-9">
<rect x="0" y="221.1" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-9601757275-line-10">
<clipPath id="terminal-line-10">
<rect x="0" y="245.5" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-9601757275-line-11">
<clipPath id="terminal-line-11">
<rect x="0" y="269.9" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-9601757275-line-12">
<clipPath id="terminal-line-12">
<rect x="0" y="294.3" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-9601757275-line-13">
<clipPath id="terminal-line-13">
<rect x="0" y="318.7" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-9601757275-line-14">
<clipPath id="terminal-line-14">
<rect x="0" y="343.1" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-9601757275-line-15">
<clipPath id="terminal-line-15">
<rect x="0" y="367.5" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-9601757275-line-16">
<clipPath id="terminal-line-16">
<rect x="0" y="391.9" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-9601757275-line-17">
<clipPath id="terminal-line-17">
<rect x="0" y="416.3" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-9601757275-line-18">
<clipPath id="terminal-line-18">
<rect x="0" y="440.7" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-9601757275-line-19">
<clipPath id="terminal-line-19">
<rect x="0" y="465.1" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-9601757275-line-20">
<clipPath id="terminal-line-20">
<rect x="0" y="489.5" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-9601757275-line-21">
<clipPath id="terminal-line-21">
<rect x="0" y="513.9" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-9601757275-line-22">
<clipPath id="terminal-line-22">
<rect x="0" y="538.3" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-9601757275-line-23">
<clipPath id="terminal-line-23">
<rect x="0" y="562.7" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-9601757275-line-24">
<clipPath id="terminal-line-24">
<rect x="0" y="587.1" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-9601757275-line-25">
<clipPath id="terminal-line-25">
<rect x="0" y="611.5" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-9601757275-line-26">
<clipPath id="terminal-line-26">
<rect x="0" y="635.9" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-9601757275-line-27">
<clipPath id="terminal-line-27">
<rect x="0" y="660.3" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-9601757275-line-28">
<clipPath id="terminal-line-28">
<rect x="0" y="684.7" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-9601757275-line-29">
<clipPath id="terminal-line-29">
<rect x="0" y="709.1" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-9601757275-line-30">
<clipPath id="terminal-line-30">
<rect x="0" y="733.5" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-9601757275-line-31">
<clipPath id="terminal-line-31">
<rect x="0" y="757.9" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-9601757275-line-32">
<clipPath id="terminal-line-32">
<rect x="0" y="782.3" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-9601757275-line-33">
<clipPath id="terminal-line-33">
<rect x="0" y="806.7" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-9601757275-line-34">
<clipPath id="terminal-line-34">
<rect x="0" y="831.1" width="1464" height="24.65"/>
</clipPath>
</defs>
<rect fill="#292929" stroke="rgba(255,255,255,0.35)" stroke-width="1" x="1" y="1" width="1480" height="926.4" rx="8"/><text class="terminal-9601757275-title" fill="#c5c8c6" text-anchor="middle" x="740" y="27">SnapshotTestAppWithMcpServers</text>
<rect fill="#292929" stroke="rgba(255,255,255,0.35)" stroke-width="1" x="1" y="1" width="1480" height="926.4" rx="8"/><text class="terminal-title" fill="#c5c8c6" text-anchor="middle" x="740" y="27">SnapshotTestAppWithMcpServers</text>
<g transform="translate(26,22)">
<circle cx="0" cy="0" r="7" fill="#ff5f57"/>
<circle cx="22" cy="0" r="7" fill="#febc2e"/>
<circle cx="44" cy="0" r="7" fill="#28c840"/>
</g>
<g transform="translate(9, 41)" clip-path="url(#terminal-9601757275-clip-terminal)">
<g transform="translate(9, 41)" clip-path="url(#terminal-clip-terminal)">
<rect fill="#608ab1" x="36.6" y="757.9" width="146.4" height="24.65" shape-rendering="crispEdges"/><rect fill="#608ab1" x="183" y="757.9" width="109.8" height="24.65" shape-rendering="crispEdges"/><rect fill="#608ab1" x="292.8" y="757.9" width="97.6" height="24.65" shape-rendering="crispEdges"/><rect fill="#608ab1" x="390.4" y="757.9" width="1037" height="24.65" shape-rendering="crispEdges"/>
<g class="terminal-9601757275-matrix">
<text class="terminal-9601757275-r1" x="1464" y="20" textLength="12.2" clip-path="url(#terminal-9601757275-line-0)">
</text><text class="terminal-9601757275-r1" x="1464" y="44.4" textLength="12.2" clip-path="url(#terminal-9601757275-line-1)">
</text><text class="terminal-9601757275-r1" x="1464" y="68.8" textLength="12.2" clip-path="url(#terminal-9601757275-line-2)">
</text><text class="terminal-9601757275-r1" x="1464" y="93.2" textLength="12.2" clip-path="url(#terminal-9601757275-line-3)">
</text><text class="terminal-9601757275-r1" x="1464" y="117.6" textLength="12.2" clip-path="url(#terminal-9601757275-line-4)">
</text><text class="terminal-9601757275-r1" x="1464" y="142" textLength="12.2" clip-path="url(#terminal-9601757275-line-5)">
</text><text class="terminal-9601757275-r1" x="1464" y="166.4" textLength="12.2" clip-path="url(#terminal-9601757275-line-6)">
</text><text class="terminal-9601757275-r1" x="1464" y="190.8" textLength="12.2" clip-path="url(#terminal-9601757275-line-7)">
</text><text class="terminal-9601757275-r1" x="1464" y="215.2" textLength="12.2" clip-path="url(#terminal-9601757275-line-8)">
</text><text class="terminal-9601757275-r1" x="1464" y="239.6" textLength="12.2" clip-path="url(#terminal-9601757275-line-9)">
</text><text class="terminal-9601757275-r1" x="1464" y="264" textLength="12.2" clip-path="url(#terminal-9601757275-line-10)">
</text><text class="terminal-9601757275-r1" x="1464" y="288.4" textLength="12.2" clip-path="url(#terminal-9601757275-line-11)">
</text><text class="terminal-9601757275-r1" x="1464" y="312.8" textLength="12.2" clip-path="url(#terminal-9601757275-line-12)">
</text><text class="terminal-9601757275-r1" x="1464" y="337.2" textLength="12.2" clip-path="url(#terminal-9601757275-line-13)">
</text><text class="terminal-9601757275-r1" x="1464" y="361.6" textLength="12.2" clip-path="url(#terminal-9601757275-line-14)">
</text><text class="terminal-9601757275-r1" x="1464" y="386" textLength="12.2" clip-path="url(#terminal-9601757275-line-15)">
</text><text class="terminal-9601757275-r1" x="1464" y="410.4" textLength="12.2" clip-path="url(#terminal-9601757275-line-16)">
</text><text class="terminal-9601757275-r1" x="0" y="434.8" textLength="134.2" clip-path="url(#terminal-9601757275-line-17)">&#160;&#160;⡠⣒⠄&#160;&#160;⡔⢄⠔⡄</text><text class="terminal-9601757275-r2" x="170.8" y="434.8" textLength="146.4" clip-path="url(#terminal-9601757275-line-17)">Mistral&#160;Vibe</text><text class="terminal-9601757275-r1" x="317.2" y="434.8" textLength="122" clip-path="url(#terminal-9601757275-line-17)">&#160;v0.0.0&#160;·&#160;</text><text class="terminal-9601757275-r3" x="439.2" y="434.8" textLength="183" clip-path="url(#terminal-9601757275-line-17)">devstral-latest</text><text class="terminal-9601757275-r1" x="622.2" y="434.8" textLength="256.2" clip-path="url(#terminal-9601757275-line-17)">&#160;·&#160;[Subscription]&#160;Pro</text><text class="terminal-9601757275-r1" x="1464" y="434.8" textLength="12.2" clip-path="url(#terminal-9601757275-line-17)">
</text><text class="terminal-9601757275-r1" x="0" y="459.2" textLength="134.2" clip-path="url(#terminal-9601757275-line-18)">&#160;⢸⠸⣀⡔⢉⠱⣃⡢⣂⡣</text><text class="terminal-9601757275-r1" x="170.8" y="459.2" textLength="414.8" clip-path="url(#terminal-9601757275-line-18)">1&#160;model&#160;·&#160;2&#160;MCP&#160;servers&#160;·&#160;0&#160;skills</text><text class="terminal-9601757275-r1" x="1464" y="459.2" textLength="12.2" clip-path="url(#terminal-9601757275-line-18)">
</text><text class="terminal-9601757275-r1" x="0" y="483.6" textLength="134.2" clip-path="url(#terminal-9601757275-line-19)">&#160;&#160;⠉⠒⠣⠤⠵⠤⠬⠮⠆</text><text class="terminal-9601757275-r1" x="170.8" y="483.6" textLength="61" clip-path="url(#terminal-9601757275-line-19)">Type&#160;</text><text class="terminal-9601757275-r3" x="231.8" y="483.6" textLength="61" clip-path="url(#terminal-9601757275-line-19)">/help</text><text class="terminal-9601757275-r1" x="292.8" y="483.6" textLength="256.2" clip-path="url(#terminal-9601757275-line-19)">&#160;for&#160;more&#160;information</text><text class="terminal-9601757275-r1" x="1464" y="483.6" textLength="12.2" clip-path="url(#terminal-9601757275-line-19)">
</text><text class="terminal-9601757275-r1" x="1464" y="508" textLength="12.2" clip-path="url(#terminal-9601757275-line-20)">
</text><text class="terminal-9601757275-r1" x="1464" y="532.4" textLength="12.2" clip-path="url(#terminal-9601757275-line-21)">
</text><text class="terminal-9601757275-r4" x="0" y="556.8" textLength="12.2" clip-path="url(#terminal-9601757275-line-22)"></text><text class="terminal-9601757275-r2" x="24.4" y="556.8" textLength="48.8" clip-path="url(#terminal-9601757275-line-22)">/mcp</text><text class="terminal-9601757275-r1" x="1464" y="556.8" textLength="12.2" clip-path="url(#terminal-9601757275-line-22)">
</text><text class="terminal-9601757275-r5" x="24.4" y="581.2" textLength="12.2" clip-path="url(#terminal-9601757275-line-23)"></text><text class="terminal-9601757275-r1" x="48.8" y="581.2" textLength="256.2" clip-path="url(#terminal-9601757275-line-23)">MCP&#160;servers&#160;opened...</text><text class="terminal-9601757275-r1" x="1464" y="581.2" textLength="12.2" clip-path="url(#terminal-9601757275-line-23)">
</text><text class="terminal-9601757275-r1" x="1464" y="605.6" textLength="12.2" clip-path="url(#terminal-9601757275-line-24)">
</text><text class="terminal-9601757275-r1" x="1464" y="630" textLength="12.2" clip-path="url(#terminal-9601757275-line-25)">
</text><text class="terminal-9601757275-r5" x="0" y="654.4" textLength="1464" clip-path="url(#terminal-9601757275-line-26)">┌──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐</text><text class="terminal-9601757275-r1" x="1464" y="654.4" textLength="12.2" clip-path="url(#terminal-9601757275-line-26)">
</text><text class="terminal-9601757275-r5" x="0" y="678.8" textLength="12.2" clip-path="url(#terminal-9601757275-line-27)"></text><text class="terminal-9601757275-r6" x="24.4" y="678.8" textLength="134.2" clip-path="url(#terminal-9601757275-line-27)">MCP&#160;Servers</text><text class="terminal-9601757275-r5" x="1451.8" y="678.8" textLength="12.2" clip-path="url(#terminal-9601757275-line-27)"></text><text class="terminal-9601757275-r1" x="1464" y="678.8" textLength="12.2" clip-path="url(#terminal-9601757275-line-27)">
</text><text class="terminal-9601757275-r5" x="0" y="703.2" textLength="12.2" clip-path="url(#terminal-9601757275-line-28)"></text><text class="terminal-9601757275-r5" x="1451.8" y="703.2" textLength="12.2" clip-path="url(#terminal-9601757275-line-28)"></text><text class="terminal-9601757275-r1" x="1464" y="703.2" textLength="12.2" clip-path="url(#terminal-9601757275-line-28)">
</text><text class="terminal-9601757275-r5" x="0" y="727.6" textLength="12.2" clip-path="url(#terminal-9601757275-line-29)"></text><text class="terminal-9601757275-r7" x="36.6" y="727.6" textLength="207.4" clip-path="url(#terminal-9601757275-line-29)">Local&#160;MCP&#160;Servers</text><text class="terminal-9601757275-r5" x="1451.8" y="727.6" textLength="12.2" clip-path="url(#terminal-9601757275-line-29)"></text><text class="terminal-9601757275-r1" x="1464" y="727.6" textLength="12.2" clip-path="url(#terminal-9601757275-line-29)">
</text><text class="terminal-9601757275-r5" x="0" y="752" textLength="12.2" clip-path="url(#terminal-9601757275-line-30)"></text><text class="terminal-9601757275-r1" x="36.6" y="752" textLength="146.4" clip-path="url(#terminal-9601757275-line-30)">&#160;&#160;filesystem</text><text class="terminal-9601757275-r8" x="183" y="752" textLength="109.8" clip-path="url(#terminal-9601757275-line-30)">&#160;&#160;[stdio]</text><text class="terminal-9601757275-r8" x="292.8" y="752" textLength="97.6" clip-path="url(#terminal-9601757275-line-30)">&#160;&#160;1&#160;tool</text><text class="terminal-9601757275-r5" x="1451.8" y="752" textLength="12.2" clip-path="url(#terminal-9601757275-line-30)"></text><text class="terminal-9601757275-r1" x="1464" y="752" textLength="12.2" clip-path="url(#terminal-9601757275-line-30)">
</text><text class="terminal-9601757275-r5" x="0" y="776.4" textLength="12.2" clip-path="url(#terminal-9601757275-line-31)"></text><text class="terminal-9601757275-r7" x="36.6" y="776.4" textLength="146.4" clip-path="url(#terminal-9601757275-line-31)">&#160;&#160;search&#160;&#160;&#160;&#160;</text><text class="terminal-9601757275-r9" x="183" y="776.4" textLength="109.8" clip-path="url(#terminal-9601757275-line-31)">&#160;&#160;[http]&#160;</text><text class="terminal-9601757275-r9" x="292.8" y="776.4" textLength="97.6" clip-path="url(#terminal-9601757275-line-31)">&#160;&#160;1&#160;tool</text><text class="terminal-9601757275-r5" x="1451.8" y="776.4" textLength="12.2" clip-path="url(#terminal-9601757275-line-31)"></text><text class="terminal-9601757275-r1" x="1464" y="776.4" textLength="12.2" clip-path="url(#terminal-9601757275-line-31)">
</text><text class="terminal-9601757275-r5" x="0" y="800.8" textLength="12.2" clip-path="url(#terminal-9601757275-line-32)"></text><text class="terminal-9601757275-r5" x="1451.8" y="800.8" textLength="12.2" clip-path="url(#terminal-9601757275-line-32)"></text><text class="terminal-9601757275-r1" x="1464" y="800.8" textLength="12.2" clip-path="url(#terminal-9601757275-line-32)">
</text><text class="terminal-9601757275-r5" x="0" y="825.2" textLength="12.2" clip-path="url(#terminal-9601757275-line-33)"></text><text class="terminal-9601757275-r5" x="24.4" y="825.2" textLength="622.2" clip-path="url(#terminal-9601757275-line-33)">↑↓&#160;Navigate&#160;&#160;Enter&#160;Show&#160;tools&#160;&#160;R&#160;Refresh&#160;&#160;Esc&#160;Close</text><text class="terminal-9601757275-r5" x="1451.8" y="825.2" textLength="12.2" clip-path="url(#terminal-9601757275-line-33)"></text><text class="terminal-9601757275-r1" x="1464" y="825.2" textLength="12.2" clip-path="url(#terminal-9601757275-line-33)">
</text><text class="terminal-9601757275-r5" x="0" y="849.6" textLength="1464" clip-path="url(#terminal-9601757275-line-34)">└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘</text><text class="terminal-9601757275-r1" x="1464" y="849.6" textLength="12.2" clip-path="url(#terminal-9601757275-line-34)">
</text><text class="terminal-9601757275-r5" x="0" y="874" textLength="158.6" clip-path="url(#terminal-9601757275-line-35)">/test/workdir</text><text class="terminal-9601757275-r5" x="1256.6" y="874" textLength="207.4" clip-path="url(#terminal-9601757275-line-35)">0%&#160;of&#160;200k&#160;tokens</text>
<g class="terminal-matrix">
<text class="terminal-r1" x="1464" y="20" textLength="12.2" clip-path="url(#terminal-line-0)">
</text><text class="terminal-r1" x="1464" y="44.4" textLength="12.2" clip-path="url(#terminal-line-1)">
</text><text class="terminal-r1" x="1464" y="68.8" textLength="12.2" clip-path="url(#terminal-line-2)">
</text><text class="terminal-r1" x="1464" y="93.2" textLength="12.2" clip-path="url(#terminal-line-3)">
</text><text class="terminal-r1" x="1464" y="117.6" textLength="12.2" clip-path="url(#terminal-line-4)">
</text><text class="terminal-r1" x="1464" y="142" textLength="12.2" clip-path="url(#terminal-line-5)">
</text><text class="terminal-r1" x="1464" y="166.4" textLength="12.2" clip-path="url(#terminal-line-6)">
</text><text class="terminal-r1" x="1464" y="190.8" textLength="12.2" clip-path="url(#terminal-line-7)">
</text><text class="terminal-r1" x="1464" y="215.2" textLength="12.2" clip-path="url(#terminal-line-8)">
</text><text class="terminal-r1" x="1464" y="239.6" textLength="12.2" clip-path="url(#terminal-line-9)">
</text><text class="terminal-r1" x="1464" y="264" textLength="12.2" clip-path="url(#terminal-line-10)">
</text><text class="terminal-r1" x="1464" y="288.4" textLength="12.2" clip-path="url(#terminal-line-11)">
</text><text class="terminal-r1" x="1464" y="312.8" textLength="12.2" clip-path="url(#terminal-line-12)">
</text><text class="terminal-r1" x="1464" y="337.2" textLength="12.2" clip-path="url(#terminal-line-13)">
</text><text class="terminal-r1" x="1464" y="361.6" textLength="12.2" clip-path="url(#terminal-line-14)">
</text><text class="terminal-r1" x="1464" y="386" textLength="12.2" clip-path="url(#terminal-line-15)">
</text><text class="terminal-r1" x="1464" y="410.4" textLength="12.2" clip-path="url(#terminal-line-16)">
</text><text class="terminal-r1" x="0" y="434.8" textLength="134.2" clip-path="url(#terminal-line-17)">&#160;&#160;⡠⣒⠄&#160;&#160;⡔⢄⠔⡄</text><text class="terminal-r2" x="170.8" y="434.8" textLength="146.4" clip-path="url(#terminal-line-17)">Mistral&#160;Vibe</text><text class="terminal-r1" x="317.2" y="434.8" textLength="122" clip-path="url(#terminal-line-17)">&#160;v0.0.0&#160;·&#160;</text><text class="terminal-r3" x="439.2" y="434.8" textLength="244" clip-path="url(#terminal-line-17)">devstral-latest[off]</text><text class="terminal-r1" x="683.2" y="434.8" textLength="256.2" clip-path="url(#terminal-line-17)">&#160;·&#160;[Subscription]&#160;Pro</text><text class="terminal-r1" x="1464" y="434.8" textLength="12.2" clip-path="url(#terminal-line-17)">
</text><text class="terminal-r1" x="0" y="459.2" textLength="134.2" clip-path="url(#terminal-line-18)">&#160;⢸⠸⣀⡔⢉⠱⣃⡢⣂⡣</text><text class="terminal-r1" x="170.8" y="459.2" textLength="414.8" clip-path="url(#terminal-line-18)">1&#160;model&#160;·&#160;2&#160;MCP&#160;servers&#160;·&#160;0&#160;skills</text><text class="terminal-r1" x="1464" y="459.2" textLength="12.2" clip-path="url(#terminal-line-18)">
</text><text class="terminal-r1" x="0" y="483.6" textLength="134.2" clip-path="url(#terminal-line-19)">&#160;&#160;⠉⠒⠣⠤⠵⠤⠬⠮⠆</text><text class="terminal-r1" x="170.8" y="483.6" textLength="61" clip-path="url(#terminal-line-19)">Type&#160;</text><text class="terminal-r3" x="231.8" y="483.6" textLength="61" clip-path="url(#terminal-line-19)">/help</text><text class="terminal-r1" x="292.8" y="483.6" textLength="256.2" clip-path="url(#terminal-line-19)">&#160;for&#160;more&#160;information</text><text class="terminal-r1" x="1464" y="483.6" textLength="12.2" clip-path="url(#terminal-line-19)">
</text><text class="terminal-r1" x="1464" y="508" textLength="12.2" clip-path="url(#terminal-line-20)">
</text><text class="terminal-r1" x="1464" y="532.4" textLength="12.2" clip-path="url(#terminal-line-21)">
</text><text class="terminal-r4" x="0" y="556.8" textLength="12.2" clip-path="url(#terminal-line-22)"></text><text class="terminal-r2" x="24.4" y="556.8" textLength="48.8" clip-path="url(#terminal-line-22)">/mcp</text><text class="terminal-r1" x="1464" y="556.8" textLength="12.2" clip-path="url(#terminal-line-22)">
</text><text class="terminal-r5" x="24.4" y="581.2" textLength="12.2" clip-path="url(#terminal-line-23)"></text><text class="terminal-r1" x="48.8" y="581.2" textLength="256.2" clip-path="url(#terminal-line-23)">MCP&#160;servers&#160;opened...</text><text class="terminal-r1" x="1464" y="581.2" textLength="12.2" clip-path="url(#terminal-line-23)">
</text><text class="terminal-r1" x="1464" y="605.6" textLength="12.2" clip-path="url(#terminal-line-24)">
</text><text class="terminal-r1" x="1464" y="630" textLength="12.2" clip-path="url(#terminal-line-25)">
</text><text class="terminal-r5" x="0" y="654.4" textLength="1464" clip-path="url(#terminal-line-26)">┌──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐</text><text class="terminal-r1" x="1464" y="654.4" textLength="12.2" clip-path="url(#terminal-line-26)">
</text><text class="terminal-r5" x="0" y="678.8" textLength="12.2" clip-path="url(#terminal-line-27)"></text><text class="terminal-r6" x="24.4" y="678.8" textLength="134.2" clip-path="url(#terminal-line-27)">MCP&#160;Servers</text><text class="terminal-r5" x="1451.8" y="678.8" textLength="12.2" clip-path="url(#terminal-line-27)"></text><text class="terminal-r1" x="1464" y="678.8" textLength="12.2" clip-path="url(#terminal-line-27)">
</text><text class="terminal-r5" x="0" y="703.2" textLength="12.2" clip-path="url(#terminal-line-28)"></text><text class="terminal-r5" x="1451.8" y="703.2" textLength="12.2" clip-path="url(#terminal-line-28)"></text><text class="terminal-r1" x="1464" y="703.2" textLength="12.2" clip-path="url(#terminal-line-28)">
</text><text class="terminal-r5" x="0" y="727.6" textLength="12.2" clip-path="url(#terminal-line-29)"></text><text class="terminal-r7" x="36.6" y="727.6" textLength="207.4" clip-path="url(#terminal-line-29)">Local&#160;MCP&#160;Servers</text><text class="terminal-r5" x="1451.8" y="727.6" textLength="12.2" clip-path="url(#terminal-line-29)"></text><text class="terminal-r1" x="1464" y="727.6" textLength="12.2" clip-path="url(#terminal-line-29)">
</text><text class="terminal-r5" x="0" y="752" textLength="12.2" clip-path="url(#terminal-line-30)"></text><text class="terminal-r1" x="36.6" y="752" textLength="146.4" clip-path="url(#terminal-line-30)">&#160;&#160;filesystem</text><text class="terminal-r8" x="183" y="752" textLength="109.8" clip-path="url(#terminal-line-30)">&#160;&#160;[stdio]</text><text class="terminal-r8" x="292.8" y="752" textLength="97.6" clip-path="url(#terminal-line-30)">&#160;&#160;1&#160;tool</text><text class="terminal-r5" x="1451.8" y="752" textLength="12.2" clip-path="url(#terminal-line-30)"></text><text class="terminal-r1" x="1464" y="752" textLength="12.2" clip-path="url(#terminal-line-30)">
</text><text class="terminal-r5" x="0" y="776.4" textLength="12.2" clip-path="url(#terminal-line-31)"></text><text class="terminal-r7" x="36.6" y="776.4" textLength="146.4" clip-path="url(#terminal-line-31)">&#160;&#160;search&#160;&#160;&#160;&#160;</text><text class="terminal-r9" x="183" y="776.4" textLength="109.8" clip-path="url(#terminal-line-31)">&#160;&#160;[http]&#160;</text><text class="terminal-r9" x="292.8" y="776.4" textLength="97.6" clip-path="url(#terminal-line-31)">&#160;&#160;1&#160;tool</text><text class="terminal-r5" x="1451.8" y="776.4" textLength="12.2" clip-path="url(#terminal-line-31)"></text><text class="terminal-r1" x="1464" y="776.4" textLength="12.2" clip-path="url(#terminal-line-31)">
</text><text class="terminal-r5" x="0" y="800.8" textLength="12.2" clip-path="url(#terminal-line-32)"></text><text class="terminal-r5" x="1451.8" y="800.8" textLength="12.2" clip-path="url(#terminal-line-32)"></text><text class="terminal-r1" x="1464" y="800.8" textLength="12.2" clip-path="url(#terminal-line-32)">
</text><text class="terminal-r5" x="0" y="825.2" textLength="12.2" clip-path="url(#terminal-line-33)"></text><text class="terminal-r5" x="24.4" y="825.2" textLength="878.4" clip-path="url(#terminal-line-33)">↑↓&#160;Navigate&#160;&#160;Enter&#160;Show&#160;tools&#160;&#160;D&#160;Disable&#160;&#160;E&#160;Enable&#160;&#160;R&#160;Refresh&#160;&#160;Esc&#160;Close</text><text class="terminal-r5" x="1451.8" y="825.2" textLength="12.2" clip-path="url(#terminal-line-33)"></text><text class="terminal-r1" x="1464" y="825.2" textLength="12.2" clip-path="url(#terminal-line-33)">
</text><text class="terminal-r5" x="0" y="849.6" textLength="1464" clip-path="url(#terminal-line-34)">└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘</text><text class="terminal-r1" x="1464" y="849.6" textLength="12.2" clip-path="url(#terminal-line-34)">
</text><text class="terminal-r5" x="0" y="874" textLength="158.6" clip-path="url(#terminal-line-35)">/test/workdir</text><text class="terminal-r5" x="1256.6" y="874" textLength="207.4" clip-path="url(#terminal-line-35)">0%&#160;of&#160;200k&#160;tokens</text>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 16 KiB

Before After
Before After

View file

@ -19,187 +19,187 @@
font-weight: 700;
}
.terminal-3878668141-matrix {
.terminal-matrix {
font-family: Fira Code, monospace;
font-size: 20px;
line-height: 24.4px;
font-variant-east-asian: full-width;
}
.terminal-3878668141-title {
.terminal-title {
font-size: 18px;
font-weight: bold;
font-family: arial;
}
.terminal-3878668141-r1 { fill: #c5c8c6 }
.terminal-3878668141-r2 { fill: #ff8205;font-weight: bold }
.terminal-3878668141-r3 { fill: #68a0b3 }
.terminal-3878668141-r4 { fill: #ff8205 }
.terminal-3878668141-r5 { fill: #9a9b99 }
.terminal-3878668141-r6 { fill: #608ab1;font-weight: bold }
.terminal-3878668141-r7 { fill: #c5c8c6;font-weight: bold }
.terminal-3878668141-r8 { fill: #9cafbd;font-weight: bold }
.terminal-3878668141-r9 { fill: #868887 }
.terminal-r1 { fill: #c5c8c6 }
.terminal-r2 { fill: #ff8205;font-weight: bold }
.terminal-r3 { fill: #68a0b3 }
.terminal-r4 { fill: #ff8205 }
.terminal-r5 { fill: #9a9b99 }
.terminal-r6 { fill: #608ab1;font-weight: bold }
.terminal-r7 { fill: #c5c8c6;font-weight: bold }
.terminal-r8 { fill: #9cafbd;font-weight: bold }
.terminal-r9 { fill: #868887 }
</style>
<defs>
<clipPath id="terminal-3878668141-clip-terminal">
<clipPath id="terminal-clip-terminal">
<rect x="0" y="0" width="1463.0" height="877.4" />
</clipPath>
<clipPath id="terminal-3878668141-line-0">
<clipPath id="terminal-line-0">
<rect x="0" y="1.5" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-3878668141-line-1">
<clipPath id="terminal-line-1">
<rect x="0" y="25.9" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-3878668141-line-2">
<clipPath id="terminal-line-2">
<rect x="0" y="50.3" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-3878668141-line-3">
<clipPath id="terminal-line-3">
<rect x="0" y="74.7" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-3878668141-line-4">
<clipPath id="terminal-line-4">
<rect x="0" y="99.1" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-3878668141-line-5">
<clipPath id="terminal-line-5">
<rect x="0" y="123.5" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-3878668141-line-6">
<clipPath id="terminal-line-6">
<rect x="0" y="147.9" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-3878668141-line-7">
<clipPath id="terminal-line-7">
<rect x="0" y="172.3" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-3878668141-line-8">
<clipPath id="terminal-line-8">
<rect x="0" y="196.7" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-3878668141-line-9">
<clipPath id="terminal-line-9">
<rect x="0" y="221.1" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-3878668141-line-10">
<clipPath id="terminal-line-10">
<rect x="0" y="245.5" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-3878668141-line-11">
<clipPath id="terminal-line-11">
<rect x="0" y="269.9" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-3878668141-line-12">
<clipPath id="terminal-line-12">
<rect x="0" y="294.3" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-3878668141-line-13">
<clipPath id="terminal-line-13">
<rect x="0" y="318.7" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-3878668141-line-14">
<clipPath id="terminal-line-14">
<rect x="0" y="343.1" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-3878668141-line-15">
<clipPath id="terminal-line-15">
<rect x="0" y="367.5" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-3878668141-line-16">
<clipPath id="terminal-line-16">
<rect x="0" y="391.9" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-3878668141-line-17">
<clipPath id="terminal-line-17">
<rect x="0" y="416.3" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-3878668141-line-18">
<clipPath id="terminal-line-18">
<rect x="0" y="440.7" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-3878668141-line-19">
<clipPath id="terminal-line-19">
<rect x="0" y="465.1" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-3878668141-line-20">
<clipPath id="terminal-line-20">
<rect x="0" y="489.5" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-3878668141-line-21">
<clipPath id="terminal-line-21">
<rect x="0" y="513.9" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-3878668141-line-22">
<clipPath id="terminal-line-22">
<rect x="0" y="538.3" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-3878668141-line-23">
<clipPath id="terminal-line-23">
<rect x="0" y="562.7" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-3878668141-line-24">
<clipPath id="terminal-line-24">
<rect x="0" y="587.1" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-3878668141-line-25">
<clipPath id="terminal-line-25">
<rect x="0" y="611.5" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-3878668141-line-26">
<clipPath id="terminal-line-26">
<rect x="0" y="635.9" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-3878668141-line-27">
<clipPath id="terminal-line-27">
<rect x="0" y="660.3" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-3878668141-line-28">
<clipPath id="terminal-line-28">
<rect x="0" y="684.7" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-3878668141-line-29">
<clipPath id="terminal-line-29">
<rect x="0" y="709.1" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-3878668141-line-30">
<clipPath id="terminal-line-30">
<rect x="0" y="733.5" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-3878668141-line-31">
<clipPath id="terminal-line-31">
<rect x="0" y="757.9" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-3878668141-line-32">
<clipPath id="terminal-line-32">
<rect x="0" y="782.3" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-3878668141-line-33">
<clipPath id="terminal-line-33">
<rect x="0" y="806.7" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-3878668141-line-34">
<clipPath id="terminal-line-34">
<rect x="0" y="831.1" width="1464" height="24.65"/>
</clipPath>
</defs>
<rect fill="#292929" stroke="rgba(255,255,255,0.35)" stroke-width="1" x="1" y="1" width="1480" height="926.4" rx="8"/><text class="terminal-3878668141-title" fill="#c5c8c6" text-anchor="middle" x="740" y="27">SnapshotTestAppWithMcpServers</text>
<rect fill="#292929" stroke="rgba(255,255,255,0.35)" stroke-width="1" x="1" y="1" width="1480" height="926.4" rx="8"/><text class="terminal-title" fill="#c5c8c6" text-anchor="middle" x="740" y="27">SnapshotTestAppWithMcpServers</text>
<g transform="translate(26,22)">
<circle cx="0" cy="0" r="7" fill="#ff5f57"/>
<circle cx="22" cy="0" r="7" fill="#febc2e"/>
<circle cx="44" cy="0" r="7" fill="#28c840"/>
</g>
<g transform="translate(9, 41)" clip-path="url(#terminal-3878668141-clip-terminal)">
<g transform="translate(9, 41)" clip-path="url(#terminal-clip-terminal)">
<rect fill="#608ab1" x="36.6" y="733.5" width="146.4" height="24.65" shape-rendering="crispEdges"/><rect fill="#608ab1" x="183" y="733.5" width="109.8" height="24.65" shape-rendering="crispEdges"/><rect fill="#608ab1" x="292.8" y="733.5" width="97.6" height="24.65" shape-rendering="crispEdges"/><rect fill="#608ab1" x="390.4" y="733.5" width="1037" height="24.65" shape-rendering="crispEdges"/>
<g class="terminal-3878668141-matrix">
<text class="terminal-3878668141-r1" x="1464" y="20" textLength="12.2" clip-path="url(#terminal-3878668141-line-0)">
</text><text class="terminal-3878668141-r1" x="1464" y="44.4" textLength="12.2" clip-path="url(#terminal-3878668141-line-1)">
</text><text class="terminal-3878668141-r1" x="1464" y="68.8" textLength="12.2" clip-path="url(#terminal-3878668141-line-2)">
</text><text class="terminal-3878668141-r1" x="1464" y="93.2" textLength="12.2" clip-path="url(#terminal-3878668141-line-3)">
</text><text class="terminal-3878668141-r1" x="1464" y="117.6" textLength="12.2" clip-path="url(#terminal-3878668141-line-4)">
</text><text class="terminal-3878668141-r1" x="1464" y="142" textLength="12.2" clip-path="url(#terminal-3878668141-line-5)">
</text><text class="terminal-3878668141-r1" x="1464" y="166.4" textLength="12.2" clip-path="url(#terminal-3878668141-line-6)">
</text><text class="terminal-3878668141-r1" x="1464" y="190.8" textLength="12.2" clip-path="url(#terminal-3878668141-line-7)">
</text><text class="terminal-3878668141-r1" x="1464" y="215.2" textLength="12.2" clip-path="url(#terminal-3878668141-line-8)">
</text><text class="terminal-3878668141-r1" x="1464" y="239.6" textLength="12.2" clip-path="url(#terminal-3878668141-line-9)">
</text><text class="terminal-3878668141-r1" x="1464" y="264" textLength="12.2" clip-path="url(#terminal-3878668141-line-10)">
</text><text class="terminal-3878668141-r1" x="1464" y="288.4" textLength="12.2" clip-path="url(#terminal-3878668141-line-11)">
</text><text class="terminal-3878668141-r1" x="1464" y="312.8" textLength="12.2" clip-path="url(#terminal-3878668141-line-12)">
</text><text class="terminal-3878668141-r1" x="1464" y="337.2" textLength="12.2" clip-path="url(#terminal-3878668141-line-13)">
</text><text class="terminal-3878668141-r1" x="1464" y="361.6" textLength="12.2" clip-path="url(#terminal-3878668141-line-14)">
</text><text class="terminal-3878668141-r1" x="1464" y="386" textLength="12.2" clip-path="url(#terminal-3878668141-line-15)">
</text><text class="terminal-3878668141-r1" x="1464" y="410.4" textLength="12.2" clip-path="url(#terminal-3878668141-line-16)">
</text><text class="terminal-3878668141-r1" x="0" y="434.8" textLength="134.2" clip-path="url(#terminal-3878668141-line-17)">&#160;&#160;⡠⣒⠄&#160;&#160;⡔⢄⠔⡄</text><text class="terminal-3878668141-r2" x="170.8" y="434.8" textLength="146.4" clip-path="url(#terminal-3878668141-line-17)">Mistral&#160;Vibe</text><text class="terminal-3878668141-r1" x="317.2" y="434.8" textLength="122" clip-path="url(#terminal-3878668141-line-17)">&#160;v0.0.0&#160;·&#160;</text><text class="terminal-3878668141-r3" x="439.2" y="434.8" textLength="183" clip-path="url(#terminal-3878668141-line-17)">devstral-latest</text><text class="terminal-3878668141-r1" x="622.2" y="434.8" textLength="256.2" clip-path="url(#terminal-3878668141-line-17)">&#160;·&#160;[Subscription]&#160;Pro</text><text class="terminal-3878668141-r1" x="1464" y="434.8" textLength="12.2" clip-path="url(#terminal-3878668141-line-17)">
</text><text class="terminal-3878668141-r1" x="0" y="459.2" textLength="134.2" clip-path="url(#terminal-3878668141-line-18)">&#160;⢸⠸⣀⡔⢉⠱⣃⡢⣂⡣</text><text class="terminal-3878668141-r1" x="170.8" y="459.2" textLength="414.8" clip-path="url(#terminal-3878668141-line-18)">1&#160;model&#160;·&#160;2&#160;MCP&#160;servers&#160;·&#160;0&#160;skills</text><text class="terminal-3878668141-r1" x="1464" y="459.2" textLength="12.2" clip-path="url(#terminal-3878668141-line-18)">
</text><text class="terminal-3878668141-r1" x="0" y="483.6" textLength="134.2" clip-path="url(#terminal-3878668141-line-19)">&#160;&#160;⠉⠒⠣⠤⠵⠤⠬⠮⠆</text><text class="terminal-3878668141-r1" x="170.8" y="483.6" textLength="61" clip-path="url(#terminal-3878668141-line-19)">Type&#160;</text><text class="terminal-3878668141-r3" x="231.8" y="483.6" textLength="61" clip-path="url(#terminal-3878668141-line-19)">/help</text><text class="terminal-3878668141-r1" x="292.8" y="483.6" textLength="256.2" clip-path="url(#terminal-3878668141-line-19)">&#160;for&#160;more&#160;information</text><text class="terminal-3878668141-r1" x="1464" y="483.6" textLength="12.2" clip-path="url(#terminal-3878668141-line-19)">
</text><text class="terminal-3878668141-r1" x="1464" y="508" textLength="12.2" clip-path="url(#terminal-3878668141-line-20)">
</text><text class="terminal-3878668141-r1" x="1464" y="532.4" textLength="12.2" clip-path="url(#terminal-3878668141-line-21)">
</text><text class="terminal-3878668141-r4" x="0" y="556.8" textLength="12.2" clip-path="url(#terminal-3878668141-line-22)"></text><text class="terminal-3878668141-r2" x="24.4" y="556.8" textLength="48.8" clip-path="url(#terminal-3878668141-line-22)">/mcp</text><text class="terminal-3878668141-r1" x="1464" y="556.8" textLength="12.2" clip-path="url(#terminal-3878668141-line-22)">
</text><text class="terminal-3878668141-r5" x="24.4" y="581.2" textLength="12.2" clip-path="url(#terminal-3878668141-line-23)"></text><text class="terminal-3878668141-r1" x="48.8" y="581.2" textLength="256.2" clip-path="url(#terminal-3878668141-line-23)">MCP&#160;servers&#160;opened...</text><text class="terminal-3878668141-r1" x="1464" y="581.2" textLength="12.2" clip-path="url(#terminal-3878668141-line-23)">
</text><text class="terminal-3878668141-r1" x="1464" y="605.6" textLength="12.2" clip-path="url(#terminal-3878668141-line-24)">
</text><text class="terminal-3878668141-r1" x="1464" y="630" textLength="12.2" clip-path="url(#terminal-3878668141-line-25)">
</text><text class="terminal-3878668141-r5" x="0" y="654.4" textLength="1464" clip-path="url(#terminal-3878668141-line-26)">┌──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐</text><text class="terminal-3878668141-r1" x="1464" y="654.4" textLength="12.2" clip-path="url(#terminal-3878668141-line-26)">
</text><text class="terminal-3878668141-r5" x="0" y="678.8" textLength="12.2" clip-path="url(#terminal-3878668141-line-27)"></text><text class="terminal-3878668141-r6" x="24.4" y="678.8" textLength="134.2" clip-path="url(#terminal-3878668141-line-27)">MCP&#160;Servers</text><text class="terminal-3878668141-r5" x="1451.8" y="678.8" textLength="12.2" clip-path="url(#terminal-3878668141-line-27)"></text><text class="terminal-3878668141-r1" x="1464" y="678.8" textLength="12.2" clip-path="url(#terminal-3878668141-line-27)">
</text><text class="terminal-3878668141-r5" x="0" y="703.2" textLength="12.2" clip-path="url(#terminal-3878668141-line-28)"></text><text class="terminal-3878668141-r5" x="1451.8" y="703.2" textLength="12.2" clip-path="url(#terminal-3878668141-line-28)"></text><text class="terminal-3878668141-r1" x="1464" y="703.2" textLength="12.2" clip-path="url(#terminal-3878668141-line-28)">
</text><text class="terminal-3878668141-r5" x="0" y="727.6" textLength="12.2" clip-path="url(#terminal-3878668141-line-29)"></text><text class="terminal-3878668141-r7" x="36.6" y="727.6" textLength="207.4" clip-path="url(#terminal-3878668141-line-29)">Local&#160;MCP&#160;Servers</text><text class="terminal-3878668141-r5" x="1451.8" y="727.6" textLength="12.2" clip-path="url(#terminal-3878668141-line-29)"></text><text class="terminal-3878668141-r1" x="1464" y="727.6" textLength="12.2" clip-path="url(#terminal-3878668141-line-29)">
</text><text class="terminal-3878668141-r5" x="0" y="752" textLength="12.2" clip-path="url(#terminal-3878668141-line-30)"></text><text class="terminal-3878668141-r7" x="36.6" y="752" textLength="146.4" clip-path="url(#terminal-3878668141-line-30)">&#160;&#160;filesystem</text><text class="terminal-3878668141-r8" x="183" y="752" textLength="109.8" clip-path="url(#terminal-3878668141-line-30)">&#160;&#160;[stdio]</text><text class="terminal-3878668141-r8" x="292.8" y="752" textLength="97.6" clip-path="url(#terminal-3878668141-line-30)">&#160;&#160;1&#160;tool</text><text class="terminal-3878668141-r5" x="1451.8" y="752" textLength="12.2" clip-path="url(#terminal-3878668141-line-30)"></text><text class="terminal-3878668141-r1" x="1464" y="752" textLength="12.2" clip-path="url(#terminal-3878668141-line-30)">
</text><text class="terminal-3878668141-r5" x="0" y="776.4" textLength="12.2" clip-path="url(#terminal-3878668141-line-31)"></text><text class="terminal-3878668141-r1" x="36.6" y="776.4" textLength="146.4" clip-path="url(#terminal-3878668141-line-31)">&#160;&#160;search&#160;&#160;&#160;&#160;</text><text class="terminal-3878668141-r9" x="183" y="776.4" textLength="109.8" clip-path="url(#terminal-3878668141-line-31)">&#160;&#160;[http]&#160;</text><text class="terminal-3878668141-r9" x="292.8" y="776.4" textLength="97.6" clip-path="url(#terminal-3878668141-line-31)">&#160;&#160;1&#160;tool</text><text class="terminal-3878668141-r5" x="1451.8" y="776.4" textLength="12.2" clip-path="url(#terminal-3878668141-line-31)"></text><text class="terminal-3878668141-r1" x="1464" y="776.4" textLength="12.2" clip-path="url(#terminal-3878668141-line-31)">
</text><text class="terminal-3878668141-r5" x="0" y="800.8" textLength="12.2" clip-path="url(#terminal-3878668141-line-32)"></text><text class="terminal-3878668141-r5" x="1451.8" y="800.8" textLength="12.2" clip-path="url(#terminal-3878668141-line-32)"></text><text class="terminal-3878668141-r1" x="1464" y="800.8" textLength="12.2" clip-path="url(#terminal-3878668141-line-32)">
</text><text class="terminal-3878668141-r5" x="0" y="825.2" textLength="12.2" clip-path="url(#terminal-3878668141-line-33)"></text><text class="terminal-3878668141-r5" x="24.4" y="825.2" textLength="768.6" clip-path="url(#terminal-3878668141-line-33)">Refreshed.&#160;&#160;↑↓&#160;Navigate&#160;&#160;Enter&#160;Show&#160;tools&#160;&#160;R&#160;Refresh&#160;&#160;Esc&#160;Close</text><text class="terminal-3878668141-r5" x="1451.8" y="825.2" textLength="12.2" clip-path="url(#terminal-3878668141-line-33)"></text><text class="terminal-3878668141-r1" x="1464" y="825.2" textLength="12.2" clip-path="url(#terminal-3878668141-line-33)">
</text><text class="terminal-3878668141-r5" x="0" y="849.6" textLength="1464" clip-path="url(#terminal-3878668141-line-34)">└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘</text><text class="terminal-3878668141-r1" x="1464" y="849.6" textLength="12.2" clip-path="url(#terminal-3878668141-line-34)">
</text><text class="terminal-3878668141-r5" x="0" y="874" textLength="158.6" clip-path="url(#terminal-3878668141-line-35)">/test/workdir</text><text class="terminal-3878668141-r5" x="1256.6" y="874" textLength="207.4" clip-path="url(#terminal-3878668141-line-35)">0%&#160;of&#160;200k&#160;tokens</text>
<g class="terminal-matrix">
<text class="terminal-r1" x="1464" y="20" textLength="12.2" clip-path="url(#terminal-line-0)">
</text><text class="terminal-r1" x="1464" y="44.4" textLength="12.2" clip-path="url(#terminal-line-1)">
</text><text class="terminal-r1" x="1464" y="68.8" textLength="12.2" clip-path="url(#terminal-line-2)">
</text><text class="terminal-r1" x="1464" y="93.2" textLength="12.2" clip-path="url(#terminal-line-3)">
</text><text class="terminal-r1" x="1464" y="117.6" textLength="12.2" clip-path="url(#terminal-line-4)">
</text><text class="terminal-r1" x="1464" y="142" textLength="12.2" clip-path="url(#terminal-line-5)">
</text><text class="terminal-r1" x="1464" y="166.4" textLength="12.2" clip-path="url(#terminal-line-6)">
</text><text class="terminal-r1" x="1464" y="190.8" textLength="12.2" clip-path="url(#terminal-line-7)">
</text><text class="terminal-r1" x="1464" y="215.2" textLength="12.2" clip-path="url(#terminal-line-8)">
</text><text class="terminal-r1" x="1464" y="239.6" textLength="12.2" clip-path="url(#terminal-line-9)">
</text><text class="terminal-r1" x="1464" y="264" textLength="12.2" clip-path="url(#terminal-line-10)">
</text><text class="terminal-r1" x="1464" y="288.4" textLength="12.2" clip-path="url(#terminal-line-11)">
</text><text class="terminal-r1" x="1464" y="312.8" textLength="12.2" clip-path="url(#terminal-line-12)">
</text><text class="terminal-r1" x="1464" y="337.2" textLength="12.2" clip-path="url(#terminal-line-13)">
</text><text class="terminal-r1" x="1464" y="361.6" textLength="12.2" clip-path="url(#terminal-line-14)">
</text><text class="terminal-r1" x="1464" y="386" textLength="12.2" clip-path="url(#terminal-line-15)">
</text><text class="terminal-r1" x="1464" y="410.4" textLength="12.2" clip-path="url(#terminal-line-16)">
</text><text class="terminal-r1" x="0" y="434.8" textLength="134.2" clip-path="url(#terminal-line-17)">&#160;&#160;⡠⣒⠄&#160;&#160;⡔⢄⠔⡄</text><text class="terminal-r2" x="170.8" y="434.8" textLength="146.4" clip-path="url(#terminal-line-17)">Mistral&#160;Vibe</text><text class="terminal-r1" x="317.2" y="434.8" textLength="122" clip-path="url(#terminal-line-17)">&#160;v0.0.0&#160;·&#160;</text><text class="terminal-r3" x="439.2" y="434.8" textLength="244" clip-path="url(#terminal-line-17)">devstral-latest[off]</text><text class="terminal-r1" x="683.2" y="434.8" textLength="256.2" clip-path="url(#terminal-line-17)">&#160;·&#160;[Subscription]&#160;Pro</text><text class="terminal-r1" x="1464" y="434.8" textLength="12.2" clip-path="url(#terminal-line-17)">
</text><text class="terminal-r1" x="0" y="459.2" textLength="134.2" clip-path="url(#terminal-line-18)">&#160;⢸⠸⣀⡔⢉⠱⣃⡢⣂⡣</text><text class="terminal-r1" x="170.8" y="459.2" textLength="414.8" clip-path="url(#terminal-line-18)">1&#160;model&#160;·&#160;2&#160;MCP&#160;servers&#160;·&#160;0&#160;skills</text><text class="terminal-r1" x="1464" y="459.2" textLength="12.2" clip-path="url(#terminal-line-18)">
</text><text class="terminal-r1" x="0" y="483.6" textLength="134.2" clip-path="url(#terminal-line-19)">&#160;&#160;⠉⠒⠣⠤⠵⠤⠬⠮⠆</text><text class="terminal-r1" x="170.8" y="483.6" textLength="61" clip-path="url(#terminal-line-19)">Type&#160;</text><text class="terminal-r3" x="231.8" y="483.6" textLength="61" clip-path="url(#terminal-line-19)">/help</text><text class="terminal-r1" x="292.8" y="483.6" textLength="256.2" clip-path="url(#terminal-line-19)">&#160;for&#160;more&#160;information</text><text class="terminal-r1" x="1464" y="483.6" textLength="12.2" clip-path="url(#terminal-line-19)">
</text><text class="terminal-r1" x="1464" y="508" textLength="12.2" clip-path="url(#terminal-line-20)">
</text><text class="terminal-r1" x="1464" y="532.4" textLength="12.2" clip-path="url(#terminal-line-21)">
</text><text class="terminal-r4" x="0" y="556.8" textLength="12.2" clip-path="url(#terminal-line-22)"></text><text class="terminal-r2" x="24.4" y="556.8" textLength="48.8" clip-path="url(#terminal-line-22)">/mcp</text><text class="terminal-r1" x="1464" y="556.8" textLength="12.2" clip-path="url(#terminal-line-22)">
</text><text class="terminal-r5" x="24.4" y="581.2" textLength="12.2" clip-path="url(#terminal-line-23)"></text><text class="terminal-r1" x="48.8" y="581.2" textLength="256.2" clip-path="url(#terminal-line-23)">MCP&#160;servers&#160;opened...</text><text class="terminal-r1" x="1464" y="581.2" textLength="12.2" clip-path="url(#terminal-line-23)">
</text><text class="terminal-r1" x="1464" y="605.6" textLength="12.2" clip-path="url(#terminal-line-24)">
</text><text class="terminal-r1" x="1464" y="630" textLength="12.2" clip-path="url(#terminal-line-25)">
</text><text class="terminal-r5" x="0" y="654.4" textLength="1464" clip-path="url(#terminal-line-26)">┌──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐</text><text class="terminal-r1" x="1464" y="654.4" textLength="12.2" clip-path="url(#terminal-line-26)">
</text><text class="terminal-r5" x="0" y="678.8" textLength="12.2" clip-path="url(#terminal-line-27)"></text><text class="terminal-r6" x="24.4" y="678.8" textLength="134.2" clip-path="url(#terminal-line-27)">MCP&#160;Servers</text><text class="terminal-r5" x="1451.8" y="678.8" textLength="12.2" clip-path="url(#terminal-line-27)"></text><text class="terminal-r1" x="1464" y="678.8" textLength="12.2" clip-path="url(#terminal-line-27)">
</text><text class="terminal-r5" x="0" y="703.2" textLength="12.2" clip-path="url(#terminal-line-28)"></text><text class="terminal-r5" x="1451.8" y="703.2" textLength="12.2" clip-path="url(#terminal-line-28)"></text><text class="terminal-r1" x="1464" y="703.2" textLength="12.2" clip-path="url(#terminal-line-28)">
</text><text class="terminal-r5" x="0" y="727.6" textLength="12.2" clip-path="url(#terminal-line-29)"></text><text class="terminal-r7" x="36.6" y="727.6" textLength="207.4" clip-path="url(#terminal-line-29)">Local&#160;MCP&#160;Servers</text><text class="terminal-r5" x="1451.8" y="727.6" textLength="12.2" clip-path="url(#terminal-line-29)"></text><text class="terminal-r1" x="1464" y="727.6" textLength="12.2" clip-path="url(#terminal-line-29)">
</text><text class="terminal-r5" x="0" y="752" textLength="12.2" clip-path="url(#terminal-line-30)"></text><text class="terminal-r7" x="36.6" y="752" textLength="146.4" clip-path="url(#terminal-line-30)">&#160;&#160;filesystem</text><text class="terminal-r8" x="183" y="752" textLength="109.8" clip-path="url(#terminal-line-30)">&#160;&#160;[stdio]</text><text class="terminal-r8" x="292.8" y="752" textLength="97.6" clip-path="url(#terminal-line-30)">&#160;&#160;1&#160;tool</text><text class="terminal-r5" x="1451.8" y="752" textLength="12.2" clip-path="url(#terminal-line-30)"></text><text class="terminal-r1" x="1464" y="752" textLength="12.2" clip-path="url(#terminal-line-30)">
</text><text class="terminal-r5" x="0" y="776.4" textLength="12.2" clip-path="url(#terminal-line-31)"></text><text class="terminal-r1" x="36.6" y="776.4" textLength="146.4" clip-path="url(#terminal-line-31)">&#160;&#160;search&#160;&#160;&#160;&#160;</text><text class="terminal-r9" x="183" y="776.4" textLength="109.8" clip-path="url(#terminal-line-31)">&#160;&#160;[http]&#160;</text><text class="terminal-r9" x="292.8" y="776.4" textLength="97.6" clip-path="url(#terminal-line-31)">&#160;&#160;1&#160;tool</text><text class="terminal-r5" x="1451.8" y="776.4" textLength="12.2" clip-path="url(#terminal-line-31)"></text><text class="terminal-r1" x="1464" y="776.4" textLength="12.2" clip-path="url(#terminal-line-31)">
</text><text class="terminal-r5" x="0" y="800.8" textLength="12.2" clip-path="url(#terminal-line-32)"></text><text class="terminal-r5" x="1451.8" y="800.8" textLength="12.2" clip-path="url(#terminal-line-32)"></text><text class="terminal-r1" x="1464" y="800.8" textLength="12.2" clip-path="url(#terminal-line-32)">
</text><text class="terminal-r5" x="0" y="825.2" textLength="12.2" clip-path="url(#terminal-line-33)"></text><text class="terminal-r5" x="24.4" y="825.2" textLength="1024.8" clip-path="url(#terminal-line-33)">Refreshed.&#160;&#160;↑↓&#160;Navigate&#160;&#160;Enter&#160;Show&#160;tools&#160;&#160;D&#160;Disable&#160;&#160;E&#160;Enable&#160;&#160;R&#160;Refresh&#160;&#160;Esc&#160;Close</text><text class="terminal-r5" x="1451.8" y="825.2" textLength="12.2" clip-path="url(#terminal-line-33)"></text><text class="terminal-r1" x="1464" y="825.2" textLength="12.2" clip-path="url(#terminal-line-33)">
</text><text class="terminal-r5" x="0" y="849.6" textLength="1464" clip-path="url(#terminal-line-34)">└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘</text><text class="terminal-r1" x="1464" y="849.6" textLength="12.2" clip-path="url(#terminal-line-34)">
</text><text class="terminal-r5" x="0" y="874" textLength="158.6" clip-path="url(#terminal-line-35)">/test/workdir</text><text class="terminal-r5" x="1256.6" y="874" textLength="207.4" clip-path="url(#terminal-line-35)">0%&#160;of&#160;200k&#160;tokens</text>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 16 KiB

Before After
Before After

View file

@ -19,185 +19,185 @@
font-weight: 700;
}
.terminal-5744808340-matrix {
.terminal-matrix {
font-family: Fira Code, monospace;
font-size: 20px;
line-height: 24.4px;
font-variant-east-asian: full-width;
}
.terminal-5744808340-title {
.terminal-title {
font-size: 18px;
font-weight: bold;
font-family: arial;
}
.terminal-5744808340-r1 { fill: #c5c8c6 }
.terminal-5744808340-r2 { fill: #ff8205;font-weight: bold }
.terminal-5744808340-r3 { fill: #68a0b3 }
.terminal-5744808340-r4 { fill: #ff8205 }
.terminal-5744808340-r5 { fill: #9a9b99 }
.terminal-5744808340-r6 { fill: #608ab1;font-weight: bold }
.terminal-5744808340-r7 { fill: #c5c8c6;font-weight: bold }
.terminal-r1 { fill: #c5c8c6 }
.terminal-r2 { fill: #ff8205;font-weight: bold }
.terminal-r3 { fill: #68a0b3 }
.terminal-r4 { fill: #ff8205 }
.terminal-r5 { fill: #9a9b99 }
.terminal-r6 { fill: #608ab1;font-weight: bold }
.terminal-r7 { fill: #c5c8c6;font-weight: bold }
</style>
<defs>
<clipPath id="terminal-5744808340-clip-terminal">
<clipPath id="terminal-clip-terminal">
<rect x="0" y="0" width="1463.0" height="877.4" />
</clipPath>
<clipPath id="terminal-5744808340-line-0">
<clipPath id="terminal-line-0">
<rect x="0" y="1.5" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-5744808340-line-1">
<clipPath id="terminal-line-1">
<rect x="0" y="25.9" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-5744808340-line-2">
<clipPath id="terminal-line-2">
<rect x="0" y="50.3" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-5744808340-line-3">
<clipPath id="terminal-line-3">
<rect x="0" y="74.7" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-5744808340-line-4">
<clipPath id="terminal-line-4">
<rect x="0" y="99.1" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-5744808340-line-5">
<clipPath id="terminal-line-5">
<rect x="0" y="123.5" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-5744808340-line-6">
<clipPath id="terminal-line-6">
<rect x="0" y="147.9" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-5744808340-line-7">
<clipPath id="terminal-line-7">
<rect x="0" y="172.3" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-5744808340-line-8">
<clipPath id="terminal-line-8">
<rect x="0" y="196.7" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-5744808340-line-9">
<clipPath id="terminal-line-9">
<rect x="0" y="221.1" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-5744808340-line-10">
<clipPath id="terminal-line-10">
<rect x="0" y="245.5" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-5744808340-line-11">
<clipPath id="terminal-line-11">
<rect x="0" y="269.9" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-5744808340-line-12">
<clipPath id="terminal-line-12">
<rect x="0" y="294.3" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-5744808340-line-13">
<clipPath id="terminal-line-13">
<rect x="0" y="318.7" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-5744808340-line-14">
<clipPath id="terminal-line-14">
<rect x="0" y="343.1" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-5744808340-line-15">
<clipPath id="terminal-line-15">
<rect x="0" y="367.5" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-5744808340-line-16">
<clipPath id="terminal-line-16">
<rect x="0" y="391.9" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-5744808340-line-17">
<clipPath id="terminal-line-17">
<rect x="0" y="416.3" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-5744808340-line-18">
<clipPath id="terminal-line-18">
<rect x="0" y="440.7" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-5744808340-line-19">
<clipPath id="terminal-line-19">
<rect x="0" y="465.1" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-5744808340-line-20">
<clipPath id="terminal-line-20">
<rect x="0" y="489.5" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-5744808340-line-21">
<clipPath id="terminal-line-21">
<rect x="0" y="513.9" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-5744808340-line-22">
<clipPath id="terminal-line-22">
<rect x="0" y="538.3" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-5744808340-line-23">
<clipPath id="terminal-line-23">
<rect x="0" y="562.7" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-5744808340-line-24">
<clipPath id="terminal-line-24">
<rect x="0" y="587.1" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-5744808340-line-25">
<clipPath id="terminal-line-25">
<rect x="0" y="611.5" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-5744808340-line-26">
<clipPath id="terminal-line-26">
<rect x="0" y="635.9" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-5744808340-line-27">
<clipPath id="terminal-line-27">
<rect x="0" y="660.3" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-5744808340-line-28">
<clipPath id="terminal-line-28">
<rect x="0" y="684.7" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-5744808340-line-29">
<clipPath id="terminal-line-29">
<rect x="0" y="709.1" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-5744808340-line-30">
<clipPath id="terminal-line-30">
<rect x="0" y="733.5" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-5744808340-line-31">
<clipPath id="terminal-line-31">
<rect x="0" y="757.9" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-5744808340-line-32">
<clipPath id="terminal-line-32">
<rect x="0" y="782.3" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-5744808340-line-33">
<clipPath id="terminal-line-33">
<rect x="0" y="806.7" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-5744808340-line-34">
<clipPath id="terminal-line-34">
<rect x="0" y="831.1" width="1464" height="24.65"/>
</clipPath>
</defs>
<rect fill="#292929" stroke="rgba(255,255,255,0.35)" stroke-width="1" x="1" y="1" width="1480" height="926.4" rx="8"/><text class="terminal-5744808340-title" fill="#c5c8c6" text-anchor="middle" x="740" y="27">SnapshotTestAppWithMcpServers</text>
<rect fill="#292929" stroke="rgba(255,255,255,0.35)" stroke-width="1" x="1" y="1" width="1480" height="926.4" rx="8"/><text class="terminal-title" fill="#c5c8c6" text-anchor="middle" x="740" y="27">SnapshotTestAppWithMcpServers</text>
<g transform="translate(26,22)">
<circle cx="0" cy="0" r="7" fill="#ff5f57"/>
<circle cx="22" cy="0" r="7" fill="#febc2e"/>
<circle cx="44" cy="0" r="7" fill="#28c840"/>
</g>
<g transform="translate(9, 41)" clip-path="url(#terminal-5744808340-clip-terminal)">
<g transform="translate(9, 41)" clip-path="url(#terminal-clip-terminal)">
<rect fill="#608ab1" x="36.6" y="757.9" width="109.8" height="24.65" shape-rendering="crispEdges"/><rect fill="#608ab1" x="146.4" y="757.9" width="378.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#608ab1" x="524.6" y="757.9" width="902.8" height="24.65" shape-rendering="crispEdges"/>
<g class="terminal-5744808340-matrix">
<text class="terminal-5744808340-r1" x="1464" y="20" textLength="12.2" clip-path="url(#terminal-5744808340-line-0)">
</text><text class="terminal-5744808340-r1" x="1464" y="44.4" textLength="12.2" clip-path="url(#terminal-5744808340-line-1)">
</text><text class="terminal-5744808340-r1" x="1464" y="68.8" textLength="12.2" clip-path="url(#terminal-5744808340-line-2)">
</text><text class="terminal-5744808340-r1" x="1464" y="93.2" textLength="12.2" clip-path="url(#terminal-5744808340-line-3)">
</text><text class="terminal-5744808340-r1" x="1464" y="117.6" textLength="12.2" clip-path="url(#terminal-5744808340-line-4)">
</text><text class="terminal-5744808340-r1" x="1464" y="142" textLength="12.2" clip-path="url(#terminal-5744808340-line-5)">
</text><text class="terminal-5744808340-r1" x="1464" y="166.4" textLength="12.2" clip-path="url(#terminal-5744808340-line-6)">
</text><text class="terminal-5744808340-r1" x="1464" y="190.8" textLength="12.2" clip-path="url(#terminal-5744808340-line-7)">
</text><text class="terminal-5744808340-r1" x="1464" y="215.2" textLength="12.2" clip-path="url(#terminal-5744808340-line-8)">
</text><text class="terminal-5744808340-r1" x="1464" y="239.6" textLength="12.2" clip-path="url(#terminal-5744808340-line-9)">
</text><text class="terminal-5744808340-r1" x="1464" y="264" textLength="12.2" clip-path="url(#terminal-5744808340-line-10)">
</text><text class="terminal-5744808340-r1" x="1464" y="288.4" textLength="12.2" clip-path="url(#terminal-5744808340-line-11)">
</text><text class="terminal-5744808340-r1" x="1464" y="312.8" textLength="12.2" clip-path="url(#terminal-5744808340-line-12)">
</text><text class="terminal-5744808340-r1" x="1464" y="337.2" textLength="12.2" clip-path="url(#terminal-5744808340-line-13)">
</text><text class="terminal-5744808340-r1" x="1464" y="361.6" textLength="12.2" clip-path="url(#terminal-5744808340-line-14)">
</text><text class="terminal-5744808340-r1" x="1464" y="386" textLength="12.2" clip-path="url(#terminal-5744808340-line-15)">
</text><text class="terminal-5744808340-r1" x="1464" y="410.4" textLength="12.2" clip-path="url(#terminal-5744808340-line-16)">
</text><text class="terminal-5744808340-r1" x="1464" y="434.8" textLength="12.2" clip-path="url(#terminal-5744808340-line-17)">
</text><text class="terminal-5744808340-r1" x="1464" y="459.2" textLength="12.2" clip-path="url(#terminal-5744808340-line-18)">
</text><text class="terminal-5744808340-r1" x="0" y="483.6" textLength="134.2" clip-path="url(#terminal-5744808340-line-19)">&#160;&#160;⡠⣒⠄&#160;&#160;⡔⢄⠔⡄</text><text class="terminal-5744808340-r2" x="170.8" y="483.6" textLength="146.4" clip-path="url(#terminal-5744808340-line-19)">Mistral&#160;Vibe</text><text class="terminal-5744808340-r1" x="317.2" y="483.6" textLength="122" clip-path="url(#terminal-5744808340-line-19)">&#160;v0.0.0&#160;·&#160;</text><text class="terminal-5744808340-r3" x="439.2" y="483.6" textLength="183" clip-path="url(#terminal-5744808340-line-19)">devstral-latest</text><text class="terminal-5744808340-r1" x="622.2" y="483.6" textLength="256.2" clip-path="url(#terminal-5744808340-line-19)">&#160;·&#160;[Subscription]&#160;Pro</text><text class="terminal-5744808340-r1" x="1464" y="483.6" textLength="12.2" clip-path="url(#terminal-5744808340-line-19)">
</text><text class="terminal-5744808340-r1" x="0" y="508" textLength="134.2" clip-path="url(#terminal-5744808340-line-20)">&#160;⢸⠸⣀⡔⢉⠱⣃⡢⣂⡣</text><text class="terminal-5744808340-r1" x="170.8" y="508" textLength="414.8" clip-path="url(#terminal-5744808340-line-20)">1&#160;model&#160;·&#160;2&#160;MCP&#160;servers&#160;·&#160;0&#160;skills</text><text class="terminal-5744808340-r1" x="1464" y="508" textLength="12.2" clip-path="url(#terminal-5744808340-line-20)">
</text><text class="terminal-5744808340-r1" x="0" y="532.4" textLength="134.2" clip-path="url(#terminal-5744808340-line-21)">&#160;&#160;⠉⠒⠣⠤⠵⠤⠬⠮⠆</text><text class="terminal-5744808340-r1" x="170.8" y="532.4" textLength="61" clip-path="url(#terminal-5744808340-line-21)">Type&#160;</text><text class="terminal-5744808340-r3" x="231.8" y="532.4" textLength="61" clip-path="url(#terminal-5744808340-line-21)">/help</text><text class="terminal-5744808340-r1" x="292.8" y="532.4" textLength="256.2" clip-path="url(#terminal-5744808340-line-21)">&#160;for&#160;more&#160;information</text><text class="terminal-5744808340-r1" x="1464" y="532.4" textLength="12.2" clip-path="url(#terminal-5744808340-line-21)">
</text><text class="terminal-5744808340-r1" x="1464" y="556.8" textLength="12.2" clip-path="url(#terminal-5744808340-line-22)">
</text><text class="terminal-5744808340-r1" x="1464" y="581.2" textLength="12.2" clip-path="url(#terminal-5744808340-line-23)">
</text><text class="terminal-5744808340-r4" x="0" y="605.6" textLength="12.2" clip-path="url(#terminal-5744808340-line-24)"></text><text class="terminal-5744808340-r2" x="24.4" y="605.6" textLength="183" clip-path="url(#terminal-5744808340-line-24)">/mcp&#160;filesystem</text><text class="terminal-5744808340-r1" x="1464" y="605.6" textLength="12.2" clip-path="url(#terminal-5744808340-line-24)">
</text><text class="terminal-5744808340-r5" x="24.4" y="630" textLength="12.2" clip-path="url(#terminal-5744808340-line-25)"></text><text class="terminal-5744808340-r1" x="48.8" y="630" textLength="256.2" clip-path="url(#terminal-5744808340-line-25)">MCP&#160;servers&#160;opened...</text><text class="terminal-5744808340-r1" x="1464" y="630" textLength="12.2" clip-path="url(#terminal-5744808340-line-25)">
</text><text class="terminal-5744808340-r1" x="1464" y="654.4" textLength="12.2" clip-path="url(#terminal-5744808340-line-26)">
</text><text class="terminal-5744808340-r1" x="1464" y="678.8" textLength="12.2" clip-path="url(#terminal-5744808340-line-27)">
</text><text class="terminal-5744808340-r5" x="0" y="703.2" textLength="1464" clip-path="url(#terminal-5744808340-line-28)">┌──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐</text><text class="terminal-5744808340-r1" x="1464" y="703.2" textLength="12.2" clip-path="url(#terminal-5744808340-line-28)">
</text><text class="terminal-5744808340-r5" x="0" y="727.6" textLength="12.2" clip-path="url(#terminal-5744808340-line-29)"></text><text class="terminal-5744808340-r6" x="24.4" y="727.6" textLength="268.4" clip-path="url(#terminal-5744808340-line-29)">MCP&#160;Server:&#160;filesystem</text><text class="terminal-5744808340-r5" x="1451.8" y="727.6" textLength="12.2" clip-path="url(#terminal-5744808340-line-29)"></text><text class="terminal-5744808340-r1" x="1464" y="727.6" textLength="12.2" clip-path="url(#terminal-5744808340-line-29)">
</text><text class="terminal-5744808340-r5" x="0" y="752" textLength="12.2" clip-path="url(#terminal-5744808340-line-30)"></text><text class="terminal-5744808340-r5" x="1451.8" y="752" textLength="12.2" clip-path="url(#terminal-5744808340-line-30)"></text><text class="terminal-5744808340-r1" x="1464" y="752" textLength="12.2" clip-path="url(#terminal-5744808340-line-30)">
</text><text class="terminal-5744808340-r5" x="0" y="776.4" textLength="12.2" clip-path="url(#terminal-5744808340-line-31)"></text><text class="terminal-5744808340-r7" x="36.6" y="776.4" textLength="109.8" clip-path="url(#terminal-5744808340-line-31)">fake_tool</text><text class="terminal-5744808340-r7" x="146.4" y="776.4" textLength="378.2" clip-path="url(#terminal-5744808340-line-31)">&#160;&#160;-&#160;&#160;A&#160;fake&#160;tool&#160;for&#160;filesystem</text><text class="terminal-5744808340-r5" x="1451.8" y="776.4" textLength="12.2" clip-path="url(#terminal-5744808340-line-31)"></text><text class="terminal-5744808340-r1" x="1464" y="776.4" textLength="12.2" clip-path="url(#terminal-5744808340-line-31)">
</text><text class="terminal-5744808340-r5" x="0" y="800.8" textLength="12.2" clip-path="url(#terminal-5744808340-line-32)"></text><text class="terminal-5744808340-r5" x="1451.8" y="800.8" textLength="12.2" clip-path="url(#terminal-5744808340-line-32)"></text><text class="terminal-5744808340-r1" x="1464" y="800.8" textLength="12.2" clip-path="url(#terminal-5744808340-line-32)">
</text><text class="terminal-5744808340-r5" x="0" y="825.2" textLength="12.2" clip-path="url(#terminal-5744808340-line-33)"></text><text class="terminal-5744808340-r5" x="24.4" y="825.2" textLength="597.8" clip-path="url(#terminal-5744808340-line-33)">↑↓&#160;Navigate&#160;&#160;Backspace&#160;Back&#160;&#160;R&#160;Refresh&#160;&#160;Esc&#160;Close</text><text class="terminal-5744808340-r5" x="1451.8" y="825.2" textLength="12.2" clip-path="url(#terminal-5744808340-line-33)"></text><text class="terminal-5744808340-r1" x="1464" y="825.2" textLength="12.2" clip-path="url(#terminal-5744808340-line-33)">
</text><text class="terminal-5744808340-r5" x="0" y="849.6" textLength="1464" clip-path="url(#terminal-5744808340-line-34)">└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘</text><text class="terminal-5744808340-r1" x="1464" y="849.6" textLength="12.2" clip-path="url(#terminal-5744808340-line-34)">
</text><text class="terminal-5744808340-r5" x="0" y="874" textLength="158.6" clip-path="url(#terminal-5744808340-line-35)">/test/workdir</text><text class="terminal-5744808340-r5" x="1256.6" y="874" textLength="207.4" clip-path="url(#terminal-5744808340-line-35)">0%&#160;of&#160;200k&#160;tokens</text>
<g class="terminal-matrix">
<text class="terminal-r1" x="1464" y="20" textLength="12.2" clip-path="url(#terminal-line-0)">
</text><text class="terminal-r1" x="1464" y="44.4" textLength="12.2" clip-path="url(#terminal-line-1)">
</text><text class="terminal-r1" x="1464" y="68.8" textLength="12.2" clip-path="url(#terminal-line-2)">
</text><text class="terminal-r1" x="1464" y="93.2" textLength="12.2" clip-path="url(#terminal-line-3)">
</text><text class="terminal-r1" x="1464" y="117.6" textLength="12.2" clip-path="url(#terminal-line-4)">
</text><text class="terminal-r1" x="1464" y="142" textLength="12.2" clip-path="url(#terminal-line-5)">
</text><text class="terminal-r1" x="1464" y="166.4" textLength="12.2" clip-path="url(#terminal-line-6)">
</text><text class="terminal-r1" x="1464" y="190.8" textLength="12.2" clip-path="url(#terminal-line-7)">
</text><text class="terminal-r1" x="1464" y="215.2" textLength="12.2" clip-path="url(#terminal-line-8)">
</text><text class="terminal-r1" x="1464" y="239.6" textLength="12.2" clip-path="url(#terminal-line-9)">
</text><text class="terminal-r1" x="1464" y="264" textLength="12.2" clip-path="url(#terminal-line-10)">
</text><text class="terminal-r1" x="1464" y="288.4" textLength="12.2" clip-path="url(#terminal-line-11)">
</text><text class="terminal-r1" x="1464" y="312.8" textLength="12.2" clip-path="url(#terminal-line-12)">
</text><text class="terminal-r1" x="1464" y="337.2" textLength="12.2" clip-path="url(#terminal-line-13)">
</text><text class="terminal-r1" x="1464" y="361.6" textLength="12.2" clip-path="url(#terminal-line-14)">
</text><text class="terminal-r1" x="1464" y="386" textLength="12.2" clip-path="url(#terminal-line-15)">
</text><text class="terminal-r1" x="1464" y="410.4" textLength="12.2" clip-path="url(#terminal-line-16)">
</text><text class="terminal-r1" x="1464" y="434.8" textLength="12.2" clip-path="url(#terminal-line-17)">
</text><text class="terminal-r1" x="1464" y="459.2" textLength="12.2" clip-path="url(#terminal-line-18)">
</text><text class="terminal-r1" x="0" y="483.6" textLength="134.2" clip-path="url(#terminal-line-19)">&#160;&#160;⡠⣒⠄&#160;&#160;⡔⢄⠔⡄</text><text class="terminal-r2" x="170.8" y="483.6" textLength="146.4" clip-path="url(#terminal-line-19)">Mistral&#160;Vibe</text><text class="terminal-r1" x="317.2" y="483.6" textLength="122" clip-path="url(#terminal-line-19)">&#160;v0.0.0&#160;·&#160;</text><text class="terminal-r3" x="439.2" y="483.6" textLength="244" clip-path="url(#terminal-line-19)">devstral-latest[off]</text><text class="terminal-r1" x="683.2" y="483.6" textLength="256.2" clip-path="url(#terminal-line-19)">&#160;·&#160;[Subscription]&#160;Pro</text><text class="terminal-r1" x="1464" y="483.6" textLength="12.2" clip-path="url(#terminal-line-19)">
</text><text class="terminal-r1" x="0" y="508" textLength="134.2" clip-path="url(#terminal-line-20)">&#160;⢸⠸⣀⡔⢉⠱⣃⡢⣂⡣</text><text class="terminal-r1" x="170.8" y="508" textLength="414.8" clip-path="url(#terminal-line-20)">1&#160;model&#160;·&#160;2&#160;MCP&#160;servers&#160;·&#160;0&#160;skills</text><text class="terminal-r1" x="1464" y="508" textLength="12.2" clip-path="url(#terminal-line-20)">
</text><text class="terminal-r1" x="0" y="532.4" textLength="134.2" clip-path="url(#terminal-line-21)">&#160;&#160;⠉⠒⠣⠤⠵⠤⠬⠮⠆</text><text class="terminal-r1" x="170.8" y="532.4" textLength="61" clip-path="url(#terminal-line-21)">Type&#160;</text><text class="terminal-r3" x="231.8" y="532.4" textLength="61" clip-path="url(#terminal-line-21)">/help</text><text class="terminal-r1" x="292.8" y="532.4" textLength="256.2" clip-path="url(#terminal-line-21)">&#160;for&#160;more&#160;information</text><text class="terminal-r1" x="1464" y="532.4" textLength="12.2" clip-path="url(#terminal-line-21)">
</text><text class="terminal-r1" x="1464" y="556.8" textLength="12.2" clip-path="url(#terminal-line-22)">
</text><text class="terminal-r1" x="1464" y="581.2" textLength="12.2" clip-path="url(#terminal-line-23)">
</text><text class="terminal-r4" x="0" y="605.6" textLength="12.2" clip-path="url(#terminal-line-24)"></text><text class="terminal-r2" x="24.4" y="605.6" textLength="183" clip-path="url(#terminal-line-24)">/mcp&#160;filesystem</text><text class="terminal-r1" x="1464" y="605.6" textLength="12.2" clip-path="url(#terminal-line-24)">
</text><text class="terminal-r5" x="24.4" y="630" textLength="12.2" clip-path="url(#terminal-line-25)"></text><text class="terminal-r1" x="48.8" y="630" textLength="256.2" clip-path="url(#terminal-line-25)">MCP&#160;servers&#160;opened...</text><text class="terminal-r1" x="1464" y="630" textLength="12.2" clip-path="url(#terminal-line-25)">
</text><text class="terminal-r1" x="1464" y="654.4" textLength="12.2" clip-path="url(#terminal-line-26)">
</text><text class="terminal-r1" x="1464" y="678.8" textLength="12.2" clip-path="url(#terminal-line-27)">
</text><text class="terminal-r5" x="0" y="703.2" textLength="1464" clip-path="url(#terminal-line-28)">┌──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐</text><text class="terminal-r1" x="1464" y="703.2" textLength="12.2" clip-path="url(#terminal-line-28)">
</text><text class="terminal-r5" x="0" y="727.6" textLength="12.2" clip-path="url(#terminal-line-29)"></text><text class="terminal-r6" x="24.4" y="727.6" textLength="268.4" clip-path="url(#terminal-line-29)">MCP&#160;Server:&#160;filesystem</text><text class="terminal-r5" x="1451.8" y="727.6" textLength="12.2" clip-path="url(#terminal-line-29)"></text><text class="terminal-r1" x="1464" y="727.6" textLength="12.2" clip-path="url(#terminal-line-29)">
</text><text class="terminal-r5" x="0" y="752" textLength="12.2" clip-path="url(#terminal-line-30)"></text><text class="terminal-r5" x="1451.8" y="752" textLength="12.2" clip-path="url(#terminal-line-30)"></text><text class="terminal-r1" x="1464" y="752" textLength="12.2" clip-path="url(#terminal-line-30)">
</text><text class="terminal-r5" x="0" y="776.4" textLength="12.2" clip-path="url(#terminal-line-31)"></text><text class="terminal-r7" x="36.6" y="776.4" textLength="109.8" clip-path="url(#terminal-line-31)">fake_tool</text><text class="terminal-r7" x="146.4" y="776.4" textLength="378.2" clip-path="url(#terminal-line-31)">&#160;&#160;-&#160;&#160;A&#160;fake&#160;tool&#160;for&#160;filesystem</text><text class="terminal-r5" x="1451.8" y="776.4" textLength="12.2" clip-path="url(#terminal-line-31)"></text><text class="terminal-r1" x="1464" y="776.4" textLength="12.2" clip-path="url(#terminal-line-31)">
</text><text class="terminal-r5" x="0" y="800.8" textLength="12.2" clip-path="url(#terminal-line-32)"></text><text class="terminal-r5" x="1451.8" y="800.8" textLength="12.2" clip-path="url(#terminal-line-32)"></text><text class="terminal-r1" x="1464" y="800.8" textLength="12.2" clip-path="url(#terminal-line-32)">
</text><text class="terminal-r5" x="0" y="825.2" textLength="12.2" clip-path="url(#terminal-line-33)"></text><text class="terminal-r5" x="24.4" y="825.2" textLength="854" clip-path="url(#terminal-line-33)">↑↓&#160;Navigate&#160;&#160;D&#160;Disable&#160;&#160;E&#160;Enable&#160;&#160;Backspace&#160;Back&#160;&#160;R&#160;Refresh&#160;&#160;Esc&#160;Close</text><text class="terminal-r5" x="1451.8" y="825.2" textLength="12.2" clip-path="url(#terminal-line-33)"></text><text class="terminal-r1" x="1464" y="825.2" textLength="12.2" clip-path="url(#terminal-line-33)">
</text><text class="terminal-r5" x="0" y="849.6" textLength="1464" clip-path="url(#terminal-line-34)">└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘</text><text class="terminal-r1" x="1464" y="849.6" textLength="12.2" clip-path="url(#terminal-line-34)">
</text><text class="terminal-r5" x="0" y="874" textLength="158.6" clip-path="url(#terminal-line-35)">/test/workdir</text><text class="terminal-r5" x="1256.6" y="874" textLength="207.4" clip-path="url(#terminal-line-35)">0%&#160;of&#160;200k&#160;tokens</text>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 17 KiB

After

Width:  |  Height:  |  Size: 15 KiB

Before After
Before After

View file

@ -19,188 +19,188 @@
font-weight: 700;
}
.terminal-4913728344-matrix {
.terminal-matrix {
font-family: Fira Code, monospace;
font-size: 20px;
line-height: 24.4px;
font-variant-east-asian: full-width;
}
.terminal-4913728344-title {
.terminal-title {
font-size: 18px;
font-weight: bold;
font-family: arial;
}
.terminal-4913728344-r1 { fill: #c5c8c6 }
.terminal-4913728344-r2 { fill: #ff8205;font-weight: bold }
.terminal-4913728344-r3 { fill: #68a0b3 }
.terminal-4913728344-r4 { fill: #ff8205 }
.terminal-4913728344-r5 { fill: #9a9b99 }
.terminal-4913728344-r6 { fill: #608ab1;font-weight: bold }
.terminal-4913728344-r7 { fill: #c5c8c6;font-weight: bold }
.terminal-4913728344-r8 { fill: #9cafbd;font-weight: bold }
.terminal-4913728344-r9 { fill: #868887 }
.terminal-4913728344-r10 { fill: #98a84b }
.terminal-r1 { fill: #c5c8c6 }
.terminal-r2 { fill: #ff8205;font-weight: bold }
.terminal-r3 { fill: #68a0b3 }
.terminal-r4 { fill: #ff8205 }
.terminal-r5 { fill: #9a9b99 }
.terminal-r6 { fill: #608ab1;font-weight: bold }
.terminal-r7 { fill: #c5c8c6;font-weight: bold }
.terminal-r8 { fill: #9cafbd;font-weight: bold }
.terminal-r9 { fill: #868887 }
.terminal-r10 { fill: #98a84b }
</style>
<defs>
<clipPath id="terminal-4913728344-clip-terminal">
<clipPath id="terminal-clip-terminal">
<rect x="0" y="0" width="1463.0" height="877.4" />
</clipPath>
<clipPath id="terminal-4913728344-line-0">
<clipPath id="terminal-line-0">
<rect x="0" y="1.5" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-4913728344-line-1">
<clipPath id="terminal-line-1">
<rect x="0" y="25.9" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-4913728344-line-2">
<clipPath id="terminal-line-2">
<rect x="0" y="50.3" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-4913728344-line-3">
<clipPath id="terminal-line-3">
<rect x="0" y="74.7" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-4913728344-line-4">
<clipPath id="terminal-line-4">
<rect x="0" y="99.1" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-4913728344-line-5">
<clipPath id="terminal-line-5">
<rect x="0" y="123.5" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-4913728344-line-6">
<clipPath id="terminal-line-6">
<rect x="0" y="147.9" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-4913728344-line-7">
<clipPath id="terminal-line-7">
<rect x="0" y="172.3" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-4913728344-line-8">
<clipPath id="terminal-line-8">
<rect x="0" y="196.7" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-4913728344-line-9">
<clipPath id="terminal-line-9">
<rect x="0" y="221.1" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-4913728344-line-10">
<clipPath id="terminal-line-10">
<rect x="0" y="245.5" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-4913728344-line-11">
<clipPath id="terminal-line-11">
<rect x="0" y="269.9" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-4913728344-line-12">
<clipPath id="terminal-line-12">
<rect x="0" y="294.3" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-4913728344-line-13">
<clipPath id="terminal-line-13">
<rect x="0" y="318.7" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-4913728344-line-14">
<clipPath id="terminal-line-14">
<rect x="0" y="343.1" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-4913728344-line-15">
<clipPath id="terminal-line-15">
<rect x="0" y="367.5" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-4913728344-line-16">
<clipPath id="terminal-line-16">
<rect x="0" y="391.9" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-4913728344-line-17">
<clipPath id="terminal-line-17">
<rect x="0" y="416.3" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-4913728344-line-18">
<clipPath id="terminal-line-18">
<rect x="0" y="440.7" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-4913728344-line-19">
<clipPath id="terminal-line-19">
<rect x="0" y="465.1" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-4913728344-line-20">
<clipPath id="terminal-line-20">
<rect x="0" y="489.5" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-4913728344-line-21">
<clipPath id="terminal-line-21">
<rect x="0" y="513.9" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-4913728344-line-22">
<clipPath id="terminal-line-22">
<rect x="0" y="538.3" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-4913728344-line-23">
<clipPath id="terminal-line-23">
<rect x="0" y="562.7" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-4913728344-line-24">
<clipPath id="terminal-line-24">
<rect x="0" y="587.1" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-4913728344-line-25">
<clipPath id="terminal-line-25">
<rect x="0" y="611.5" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-4913728344-line-26">
<clipPath id="terminal-line-26">
<rect x="0" y="635.9" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-4913728344-line-27">
<clipPath id="terminal-line-27">
<rect x="0" y="660.3" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-4913728344-line-28">
<clipPath id="terminal-line-28">
<rect x="0" y="684.7" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-4913728344-line-29">
<clipPath id="terminal-line-29">
<rect x="0" y="709.1" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-4913728344-line-30">
<clipPath id="terminal-line-30">
<rect x="0" y="733.5" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-4913728344-line-31">
<clipPath id="terminal-line-31">
<rect x="0" y="757.9" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-4913728344-line-32">
<clipPath id="terminal-line-32">
<rect x="0" y="782.3" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-4913728344-line-33">
<clipPath id="terminal-line-33">
<rect x="0" y="806.7" width="1464" height="24.65"/>
</clipPath>
<clipPath id="terminal-4913728344-line-34">
<clipPath id="terminal-line-34">
<rect x="0" y="831.1" width="1464" height="24.65"/>
</clipPath>
</defs>
<rect fill="#292929" stroke="rgba(255,255,255,0.35)" stroke-width="1" x="1" y="1" width="1480" height="926.4" rx="8"/><text class="terminal-4913728344-title" fill="#c5c8c6" text-anchor="middle" x="740" y="27">SnapshotTestAppWithConnectors</text>
<rect fill="#292929" stroke="rgba(255,255,255,0.35)" stroke-width="1" x="1" y="1" width="1480" height="926.4" rx="8"/><text class="terminal-title" fill="#c5c8c6" text-anchor="middle" x="740" y="27">SnapshotTestAppWithConnectors</text>
<g transform="translate(26,22)">
<circle cx="0" cy="0" r="7" fill="#ff5f57"/>
<circle cx="22" cy="0" r="7" fill="#febc2e"/>
<circle cx="44" cy="0" r="7" fill="#28c840"/>
</g>
<g transform="translate(9, 41)" clip-path="url(#terminal-4913728344-clip-terminal)">
<g transform="translate(9, 41)" clip-path="url(#terminal-clip-terminal)">
<rect fill="#608ab1" x="36.6" y="660.3" width="146.4" height="24.65" shape-rendering="crispEdges"/><rect fill="#608ab1" x="183" y="660.3" width="109.8" height="24.65" shape-rendering="crispEdges"/><rect fill="#608ab1" x="292.8" y="660.3" width="97.6" height="24.65" shape-rendering="crispEdges"/><rect fill="#608ab1" x="390.4" y="660.3" width="1037" height="24.65" shape-rendering="crispEdges"/>
<g class="terminal-4913728344-matrix">
<text class="terminal-4913728344-r1" x="1464" y="20" textLength="12.2" clip-path="url(#terminal-4913728344-line-0)">
</text><text class="terminal-4913728344-r1" x="1464" y="44.4" textLength="12.2" clip-path="url(#terminal-4913728344-line-1)">
</text><text class="terminal-4913728344-r1" x="1464" y="68.8" textLength="12.2" clip-path="url(#terminal-4913728344-line-2)">
</text><text class="terminal-4913728344-r1" x="1464" y="93.2" textLength="12.2" clip-path="url(#terminal-4913728344-line-3)">
</text><text class="terminal-4913728344-r1" x="1464" y="117.6" textLength="12.2" clip-path="url(#terminal-4913728344-line-4)">
</text><text class="terminal-4913728344-r1" x="1464" y="142" textLength="12.2" clip-path="url(#terminal-4913728344-line-5)">
</text><text class="terminal-4913728344-r1" x="1464" y="166.4" textLength="12.2" clip-path="url(#terminal-4913728344-line-6)">
</text><text class="terminal-4913728344-r1" x="1464" y="190.8" textLength="12.2" clip-path="url(#terminal-4913728344-line-7)">
</text><text class="terminal-4913728344-r1" x="1464" y="215.2" textLength="12.2" clip-path="url(#terminal-4913728344-line-8)">
</text><text class="terminal-4913728344-r1" x="1464" y="239.6" textLength="12.2" clip-path="url(#terminal-4913728344-line-9)">
</text><text class="terminal-4913728344-r1" x="1464" y="264" textLength="12.2" clip-path="url(#terminal-4913728344-line-10)">
</text><text class="terminal-4913728344-r1" x="1464" y="288.4" textLength="12.2" clip-path="url(#terminal-4913728344-line-11)">
</text><text class="terminal-4913728344-r1" x="1464" y="312.8" textLength="12.2" clip-path="url(#terminal-4913728344-line-12)">
</text><text class="terminal-4913728344-r1" x="1464" y="337.2" textLength="12.2" clip-path="url(#terminal-4913728344-line-13)">
</text><text class="terminal-4913728344-r1" x="0" y="361.6" textLength="134.2" clip-path="url(#terminal-4913728344-line-14)">&#160;&#160;⡠⣒⠄&#160;&#160;⡔⢄⠔⡄</text><text class="terminal-4913728344-r2" x="170.8" y="361.6" textLength="146.4" clip-path="url(#terminal-4913728344-line-14)">Mistral&#160;Vibe</text><text class="terminal-4913728344-r1" x="317.2" y="361.6" textLength="122" clip-path="url(#terminal-4913728344-line-14)">&#160;v0.0.0&#160;·&#160;</text><text class="terminal-4913728344-r3" x="439.2" y="361.6" textLength="183" clip-path="url(#terminal-4913728344-line-14)">devstral-latest</text><text class="terminal-4913728344-r1" x="622.2" y="361.6" textLength="256.2" clip-path="url(#terminal-4913728344-line-14)">&#160;·&#160;[Subscription]&#160;Pro</text><text class="terminal-4913728344-r1" x="1464" y="361.6" textLength="12.2" clip-path="url(#terminal-4913728344-line-14)">
</text><text class="terminal-4913728344-r1" x="0" y="386" textLength="134.2" clip-path="url(#terminal-4913728344-line-15)">&#160;⢸⠸⣀⡔⢉⠱⣃⡢⣂⡣</text><text class="terminal-4913728344-r1" x="170.8" y="386" textLength="585.6" clip-path="url(#terminal-4913728344-line-15)">1&#160;model&#160;·&#160;2&#160;connectors&#160;·&#160;1&#160;MCP&#160;server&#160;·&#160;0&#160;skills</text><text class="terminal-4913728344-r1" x="1464" y="386" textLength="12.2" clip-path="url(#terminal-4913728344-line-15)">
</text><text class="terminal-4913728344-r1" x="0" y="410.4" textLength="134.2" clip-path="url(#terminal-4913728344-line-16)">&#160;&#160;⠉⠒⠣⠤⠵⠤⠬⠮⠆</text><text class="terminal-4913728344-r1" x="170.8" y="410.4" textLength="61" clip-path="url(#terminal-4913728344-line-16)">Type&#160;</text><text class="terminal-4913728344-r3" x="231.8" y="410.4" textLength="61" clip-path="url(#terminal-4913728344-line-16)">/help</text><text class="terminal-4913728344-r1" x="292.8" y="410.4" textLength="256.2" clip-path="url(#terminal-4913728344-line-16)">&#160;for&#160;more&#160;information</text><text class="terminal-4913728344-r1" x="1464" y="410.4" textLength="12.2" clip-path="url(#terminal-4913728344-line-16)">
</text><text class="terminal-4913728344-r1" x="1464" y="434.8" textLength="12.2" clip-path="url(#terminal-4913728344-line-17)">
</text><text class="terminal-4913728344-r1" x="1464" y="459.2" textLength="12.2" clip-path="url(#terminal-4913728344-line-18)">
</text><text class="terminal-4913728344-r4" x="0" y="483.6" textLength="12.2" clip-path="url(#terminal-4913728344-line-19)"></text><text class="terminal-4913728344-r2" x="24.4" y="483.6" textLength="48.8" clip-path="url(#terminal-4913728344-line-19)">/mcp</text><text class="terminal-4913728344-r1" x="1464" y="483.6" textLength="12.2" clip-path="url(#terminal-4913728344-line-19)">
</text><text class="terminal-4913728344-r5" x="24.4" y="508" textLength="12.2" clip-path="url(#terminal-4913728344-line-20)"></text><text class="terminal-4913728344-r1" x="48.8" y="508" textLength="256.2" clip-path="url(#terminal-4913728344-line-20)">MCP&#160;servers&#160;opened...</text><text class="terminal-4913728344-r1" x="1464" y="508" textLength="12.2" clip-path="url(#terminal-4913728344-line-20)">
</text><text class="terminal-4913728344-r1" x="1464" y="532.4" textLength="12.2" clip-path="url(#terminal-4913728344-line-21)">
</text><text class="terminal-4913728344-r1" x="1464" y="556.8" textLength="12.2" clip-path="url(#terminal-4913728344-line-22)">
</text><text class="terminal-4913728344-r5" x="0" y="581.2" textLength="1464" clip-path="url(#terminal-4913728344-line-23)">┌──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐</text><text class="terminal-4913728344-r1" x="1464" y="581.2" textLength="12.2" clip-path="url(#terminal-4913728344-line-23)">
</text><text class="terminal-4913728344-r5" x="0" y="605.6" textLength="12.2" clip-path="url(#terminal-4913728344-line-24)"></text><text class="terminal-4913728344-r6" x="24.4" y="605.6" textLength="292.8" clip-path="url(#terminal-4913728344-line-24)">MCP&#160;Servers&#160;&amp;&#160;Connectors</text><text class="terminal-4913728344-r5" x="1451.8" y="605.6" textLength="12.2" clip-path="url(#terminal-4913728344-line-24)"></text><text class="terminal-4913728344-r1" x="1464" y="605.6" textLength="12.2" clip-path="url(#terminal-4913728344-line-24)">
</text><text class="terminal-4913728344-r5" x="0" y="630" textLength="12.2" clip-path="url(#terminal-4913728344-line-25)"></text><text class="terminal-4913728344-r5" x="1451.8" y="630" textLength="12.2" clip-path="url(#terminal-4913728344-line-25)"></text><text class="terminal-4913728344-r1" x="1464" y="630" textLength="12.2" clip-path="url(#terminal-4913728344-line-25)">
</text><text class="terminal-4913728344-r5" x="0" y="654.4" textLength="12.2" clip-path="url(#terminal-4913728344-line-26)"></text><text class="terminal-4913728344-r7" x="36.6" y="654.4" textLength="207.4" clip-path="url(#terminal-4913728344-line-26)">Local&#160;MCP&#160;Servers</text><text class="terminal-4913728344-r5" x="1451.8" y="654.4" textLength="12.2" clip-path="url(#terminal-4913728344-line-26)"></text><text class="terminal-4913728344-r1" x="1464" y="654.4" textLength="12.2" clip-path="url(#terminal-4913728344-line-26)">
</text><text class="terminal-4913728344-r5" x="0" y="678.8" textLength="12.2" clip-path="url(#terminal-4913728344-line-27)"></text><text class="terminal-4913728344-r7" x="36.6" y="678.8" textLength="146.4" clip-path="url(#terminal-4913728344-line-27)">&#160;&#160;filesystem</text><text class="terminal-4913728344-r8" x="183" y="678.8" textLength="109.8" clip-path="url(#terminal-4913728344-line-27)">&#160;&#160;[stdio]</text><text class="terminal-4913728344-r8" x="292.8" y="678.8" textLength="97.6" clip-path="url(#terminal-4913728344-line-27)">&#160;&#160;1&#160;tool</text><text class="terminal-4913728344-r5" x="1451.8" y="678.8" textLength="12.2" clip-path="url(#terminal-4913728344-line-27)"></text><text class="terminal-4913728344-r1" x="1464" y="678.8" textLength="12.2" clip-path="url(#terminal-4913728344-line-27)">
</text><text class="terminal-4913728344-r5" x="0" y="703.2" textLength="12.2" clip-path="url(#terminal-4913728344-line-28)"></text><text class="terminal-4913728344-r5" x="1451.8" y="703.2" textLength="12.2" clip-path="url(#terminal-4913728344-line-28)"></text><text class="terminal-4913728344-r1" x="1464" y="703.2" textLength="12.2" clip-path="url(#terminal-4913728344-line-28)">
</text><text class="terminal-4913728344-r5" x="0" y="727.6" textLength="12.2" clip-path="url(#terminal-4913728344-line-29)"></text><text class="terminal-4913728344-r7" x="36.6" y="727.6" textLength="244" clip-path="url(#terminal-4913728344-line-29)">Workspace&#160;Connectors</text><text class="terminal-4913728344-r5" x="1451.8" y="727.6" textLength="12.2" clip-path="url(#terminal-4913728344-line-29)"></text><text class="terminal-4913728344-r1" x="1464" y="727.6" textLength="12.2" clip-path="url(#terminal-4913728344-line-29)">
</text><text class="terminal-4913728344-r5" x="0" y="752" textLength="12.2" clip-path="url(#terminal-4913728344-line-30)"></text><text class="terminal-4913728344-r1" x="36.6" y="752" textLength="85.4" clip-path="url(#terminal-4913728344-line-30)">&#160;&#160;gmail</text><text class="terminal-4913728344-r9" x="122" y="752" textLength="158.6" clip-path="url(#terminal-4913728344-line-30)">&#160;&#160;[connector]</text><text class="terminal-4913728344-r9" x="280.6" y="752" textLength="109.8" clip-path="url(#terminal-4913728344-line-30)">&#160;&#160;3&#160;tools</text><text class="terminal-4913728344-r10" x="414.8" y="752" textLength="12.2" clip-path="url(#terminal-4913728344-line-30)"></text><text class="terminal-4913728344-r9" x="427" y="752" textLength="122" clip-path="url(#terminal-4913728344-line-30)">&#160;connected</text><text class="terminal-4913728344-r5" x="1451.8" y="752" textLength="12.2" clip-path="url(#terminal-4913728344-line-30)"></text><text class="terminal-4913728344-r1" x="1464" y="752" textLength="12.2" clip-path="url(#terminal-4913728344-line-30)">
</text><text class="terminal-4913728344-r5" x="0" y="776.4" textLength="12.2" clip-path="url(#terminal-4913728344-line-31)"></text><text class="terminal-4913728344-r1" x="36.6" y="776.4" textLength="85.4" clip-path="url(#terminal-4913728344-line-31)">&#160;&#160;slack</text><text class="terminal-4913728344-r9" x="122" y="776.4" textLength="158.6" clip-path="url(#terminal-4913728344-line-31)">&#160;&#160;[connector]</text><text class="terminal-4913728344-r9" x="280.6" y="776.4" textLength="109.8" clip-path="url(#terminal-4913728344-line-31)">&#160;&#160;2&#160;tools</text><text class="terminal-4913728344-r10" x="414.8" y="776.4" textLength="12.2" clip-path="url(#terminal-4913728344-line-31)"></text><text class="terminal-4913728344-r9" x="427" y="776.4" textLength="122" clip-path="url(#terminal-4913728344-line-31)">&#160;connected</text><text class="terminal-4913728344-r5" x="1451.8" y="776.4" textLength="12.2" clip-path="url(#terminal-4913728344-line-31)"></text><text class="terminal-4913728344-r1" x="1464" y="776.4" textLength="12.2" clip-path="url(#terminal-4913728344-line-31)">
</text><text class="terminal-4913728344-r5" x="0" y="800.8" textLength="12.2" clip-path="url(#terminal-4913728344-line-32)"></text><text class="terminal-4913728344-r5" x="1451.8" y="800.8" textLength="12.2" clip-path="url(#terminal-4913728344-line-32)"></text><text class="terminal-4913728344-r1" x="1464" y="800.8" textLength="12.2" clip-path="url(#terminal-4913728344-line-32)">
</text><text class="terminal-4913728344-r5" x="0" y="825.2" textLength="12.2" clip-path="url(#terminal-4913728344-line-33)"></text><text class="terminal-4913728344-r5" x="24.4" y="825.2" textLength="622.2" clip-path="url(#terminal-4913728344-line-33)">↑↓&#160;Navigate&#160;&#160;Enter&#160;Show&#160;tools&#160;&#160;R&#160;Refresh&#160;&#160;Esc&#160;Close</text><text class="terminal-4913728344-r5" x="1451.8" y="825.2" textLength="12.2" clip-path="url(#terminal-4913728344-line-33)"></text><text class="terminal-4913728344-r1" x="1464" y="825.2" textLength="12.2" clip-path="url(#terminal-4913728344-line-33)">
</text><text class="terminal-4913728344-r5" x="0" y="849.6" textLength="1464" clip-path="url(#terminal-4913728344-line-34)">└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘</text><text class="terminal-4913728344-r1" x="1464" y="849.6" textLength="12.2" clip-path="url(#terminal-4913728344-line-34)">
</text><text class="terminal-4913728344-r5" x="0" y="874" textLength="158.6" clip-path="url(#terminal-4913728344-line-35)">/test/workdir</text><text class="terminal-4913728344-r5" x="1256.6" y="874" textLength="207.4" clip-path="url(#terminal-4913728344-line-35)">0%&#160;of&#160;200k&#160;tokens</text>
<g class="terminal-matrix">
<text class="terminal-r1" x="1464" y="20" textLength="12.2" clip-path="url(#terminal-line-0)">
</text><text class="terminal-r1" x="1464" y="44.4" textLength="12.2" clip-path="url(#terminal-line-1)">
</text><text class="terminal-r1" x="1464" y="68.8" textLength="12.2" clip-path="url(#terminal-line-2)">
</text><text class="terminal-r1" x="1464" y="93.2" textLength="12.2" clip-path="url(#terminal-line-3)">
</text><text class="terminal-r1" x="1464" y="117.6" textLength="12.2" clip-path="url(#terminal-line-4)">
</text><text class="terminal-r1" x="1464" y="142" textLength="12.2" clip-path="url(#terminal-line-5)">
</text><text class="terminal-r1" x="1464" y="166.4" textLength="12.2" clip-path="url(#terminal-line-6)">
</text><text class="terminal-r1" x="1464" y="190.8" textLength="12.2" clip-path="url(#terminal-line-7)">
</text><text class="terminal-r1" x="1464" y="215.2" textLength="12.2" clip-path="url(#terminal-line-8)">
</text><text class="terminal-r1" x="1464" y="239.6" textLength="12.2" clip-path="url(#terminal-line-9)">
</text><text class="terminal-r1" x="1464" y="264" textLength="12.2" clip-path="url(#terminal-line-10)">
</text><text class="terminal-r1" x="1464" y="288.4" textLength="12.2" clip-path="url(#terminal-line-11)">
</text><text class="terminal-r1" x="1464" y="312.8" textLength="12.2" clip-path="url(#terminal-line-12)">
</text><text class="terminal-r1" x="1464" y="337.2" textLength="12.2" clip-path="url(#terminal-line-13)">
</text><text class="terminal-r1" x="0" y="361.6" textLength="134.2" clip-path="url(#terminal-line-14)">&#160;&#160;⡠⣒⠄&#160;&#160;⡔⢄⠔⡄</text><text class="terminal-r2" x="170.8" y="361.6" textLength="146.4" clip-path="url(#terminal-line-14)">Mistral&#160;Vibe</text><text class="terminal-r1" x="317.2" y="361.6" textLength="122" clip-path="url(#terminal-line-14)">&#160;v0.0.0&#160;·&#160;</text><text class="terminal-r3" x="439.2" y="361.6" textLength="244" clip-path="url(#terminal-line-14)">devstral-latest[off]</text><text class="terminal-r1" x="683.2" y="361.6" textLength="256.2" clip-path="url(#terminal-line-14)">&#160;·&#160;[Subscription]&#160;Pro</text><text class="terminal-r1" x="1464" y="361.6" textLength="12.2" clip-path="url(#terminal-line-14)">
</text><text class="terminal-r1" x="0" y="386" textLength="134.2" clip-path="url(#terminal-line-15)">&#160;⢸⠸⣀⡔⢉⠱⣃⡢⣂⡣</text><text class="terminal-r1" x="170.8" y="386" textLength="585.6" clip-path="url(#terminal-line-15)">1&#160;model&#160;·&#160;2&#160;connectors&#160;·&#160;1&#160;MCP&#160;server&#160;·&#160;0&#160;skills</text><text class="terminal-r1" x="1464" y="386" textLength="12.2" clip-path="url(#terminal-line-15)">
</text><text class="terminal-r1" x="0" y="410.4" textLength="134.2" clip-path="url(#terminal-line-16)">&#160;&#160;⠉⠒⠣⠤⠵⠤⠬⠮⠆</text><text class="terminal-r1" x="170.8" y="410.4" textLength="61" clip-path="url(#terminal-line-16)">Type&#160;</text><text class="terminal-r3" x="231.8" y="410.4" textLength="61" clip-path="url(#terminal-line-16)">/help</text><text class="terminal-r1" x="292.8" y="410.4" textLength="256.2" clip-path="url(#terminal-line-16)">&#160;for&#160;more&#160;information</text><text class="terminal-r1" x="1464" y="410.4" textLength="12.2" clip-path="url(#terminal-line-16)">
</text><text class="terminal-r1" x="1464" y="434.8" textLength="12.2" clip-path="url(#terminal-line-17)">
</text><text class="terminal-r1" x="1464" y="459.2" textLength="12.2" clip-path="url(#terminal-line-18)">
</text><text class="terminal-r4" x="0" y="483.6" textLength="12.2" clip-path="url(#terminal-line-19)"></text><text class="terminal-r2" x="24.4" y="483.6" textLength="48.8" clip-path="url(#terminal-line-19)">/mcp</text><text class="terminal-r1" x="1464" y="483.6" textLength="12.2" clip-path="url(#terminal-line-19)">
</text><text class="terminal-r5" x="24.4" y="508" textLength="12.2" clip-path="url(#terminal-line-20)"></text><text class="terminal-r1" x="48.8" y="508" textLength="256.2" clip-path="url(#terminal-line-20)">MCP&#160;servers&#160;opened...</text><text class="terminal-r1" x="1464" y="508" textLength="12.2" clip-path="url(#terminal-line-20)">
</text><text class="terminal-r1" x="1464" y="532.4" textLength="12.2" clip-path="url(#terminal-line-21)">
</text><text class="terminal-r1" x="1464" y="556.8" textLength="12.2" clip-path="url(#terminal-line-22)">
</text><text class="terminal-r5" x="0" y="581.2" textLength="1464" clip-path="url(#terminal-line-23)">┌──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐</text><text class="terminal-r1" x="1464" y="581.2" textLength="12.2" clip-path="url(#terminal-line-23)">
</text><text class="terminal-r5" x="0" y="605.6" textLength="12.2" clip-path="url(#terminal-line-24)"></text><text class="terminal-r6" x="24.4" y="605.6" textLength="292.8" clip-path="url(#terminal-line-24)">MCP&#160;Servers&#160;&amp;&#160;Connectors</text><text class="terminal-r5" x="1451.8" y="605.6" textLength="12.2" clip-path="url(#terminal-line-24)"></text><text class="terminal-r1" x="1464" y="605.6" textLength="12.2" clip-path="url(#terminal-line-24)">
</text><text class="terminal-r5" x="0" y="630" textLength="12.2" clip-path="url(#terminal-line-25)"></text><text class="terminal-r5" x="1451.8" y="630" textLength="12.2" clip-path="url(#terminal-line-25)"></text><text class="terminal-r1" x="1464" y="630" textLength="12.2" clip-path="url(#terminal-line-25)">
</text><text class="terminal-r5" x="0" y="654.4" textLength="12.2" clip-path="url(#terminal-line-26)"></text><text class="terminal-r7" x="36.6" y="654.4" textLength="207.4" clip-path="url(#terminal-line-26)">Local&#160;MCP&#160;Servers</text><text class="terminal-r5" x="1451.8" y="654.4" textLength="12.2" clip-path="url(#terminal-line-26)"></text><text class="terminal-r1" x="1464" y="654.4" textLength="12.2" clip-path="url(#terminal-line-26)">
</text><text class="terminal-r5" x="0" y="678.8" textLength="12.2" clip-path="url(#terminal-line-27)"></text><text class="terminal-r7" x="36.6" y="678.8" textLength="146.4" clip-path="url(#terminal-line-27)">&#160;&#160;filesystem</text><text class="terminal-r8" x="183" y="678.8" textLength="109.8" clip-path="url(#terminal-line-27)">&#160;&#160;[stdio]</text><text class="terminal-r8" x="292.8" y="678.8" textLength="97.6" clip-path="url(#terminal-line-27)">&#160;&#160;1&#160;tool</text><text class="terminal-r5" x="1451.8" y="678.8" textLength="12.2" clip-path="url(#terminal-line-27)"></text><text class="terminal-r1" x="1464" y="678.8" textLength="12.2" clip-path="url(#terminal-line-27)">
</text><text class="terminal-r5" x="0" y="703.2" textLength="12.2" clip-path="url(#terminal-line-28)"></text><text class="terminal-r5" x="1451.8" y="703.2" textLength="12.2" clip-path="url(#terminal-line-28)"></text><text class="terminal-r1" x="1464" y="703.2" textLength="12.2" clip-path="url(#terminal-line-28)">
</text><text class="terminal-r5" x="0" y="727.6" textLength="12.2" clip-path="url(#terminal-line-29)"></text><text class="terminal-r7" x="36.6" y="727.6" textLength="244" clip-path="url(#terminal-line-29)">Workspace&#160;Connectors</text><text class="terminal-r5" x="1451.8" y="727.6" textLength="12.2" clip-path="url(#terminal-line-29)"></text><text class="terminal-r1" x="1464" y="727.6" textLength="12.2" clip-path="url(#terminal-line-29)">
</text><text class="terminal-r5" x="0" y="752" textLength="12.2" clip-path="url(#terminal-line-30)"></text><text class="terminal-r1" x="36.6" y="752" textLength="85.4" clip-path="url(#terminal-line-30)">&#160;&#160;gmail</text><text class="terminal-r9" x="122" y="752" textLength="158.6" clip-path="url(#terminal-line-30)">&#160;&#160;[connector]</text><text class="terminal-r9" x="280.6" y="752" textLength="109.8" clip-path="url(#terminal-line-30)">&#160;&#160;3&#160;tools</text><text class="terminal-r10" x="414.8" y="752" textLength="12.2" clip-path="url(#terminal-line-30)"></text><text class="terminal-r9" x="427" y="752" textLength="122" clip-path="url(#terminal-line-30)">&#160;connected</text><text class="terminal-r5" x="1451.8" y="752" textLength="12.2" clip-path="url(#terminal-line-30)"></text><text class="terminal-r1" x="1464" y="752" textLength="12.2" clip-path="url(#terminal-line-30)">
</text><text class="terminal-r5" x="0" y="776.4" textLength="12.2" clip-path="url(#terminal-line-31)"></text><text class="terminal-r1" x="36.6" y="776.4" textLength="85.4" clip-path="url(#terminal-line-31)">&#160;&#160;slack</text><text class="terminal-r9" x="122" y="776.4" textLength="158.6" clip-path="url(#terminal-line-31)">&#160;&#160;[connector]</text><text class="terminal-r9" x="280.6" y="776.4" textLength="109.8" clip-path="url(#terminal-line-31)">&#160;&#160;2&#160;tools</text><text class="terminal-r10" x="414.8" y="776.4" textLength="12.2" clip-path="url(#terminal-line-31)"></text><text class="terminal-r9" x="427" y="776.4" textLength="122" clip-path="url(#terminal-line-31)">&#160;connected</text><text class="terminal-r5" x="1451.8" y="776.4" textLength="12.2" clip-path="url(#terminal-line-31)"></text><text class="terminal-r1" x="1464" y="776.4" textLength="12.2" clip-path="url(#terminal-line-31)">
</text><text class="terminal-r5" x="0" y="800.8" textLength="12.2" clip-path="url(#terminal-line-32)"></text><text class="terminal-r5" x="1451.8" y="800.8" textLength="12.2" clip-path="url(#terminal-line-32)"></text><text class="terminal-r1" x="1464" y="800.8" textLength="12.2" clip-path="url(#terminal-line-32)">
</text><text class="terminal-r5" x="0" y="825.2" textLength="12.2" clip-path="url(#terminal-line-33)"></text><text class="terminal-r5" x="24.4" y="825.2" textLength="878.4" clip-path="url(#terminal-line-33)">↑↓&#160;Navigate&#160;&#160;Enter&#160;Show&#160;tools&#160;&#160;D&#160;Disable&#160;&#160;E&#160;Enable&#160;&#160;R&#160;Refresh&#160;&#160;Esc&#160;Close</text><text class="terminal-r5" x="1451.8" y="825.2" textLength="12.2" clip-path="url(#terminal-line-33)"></text><text class="terminal-r1" x="1464" y="825.2" textLength="12.2" clip-path="url(#terminal-line-33)">
</text><text class="terminal-r5" x="0" y="849.6" textLength="1464" clip-path="url(#terminal-line-34)">└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘</text><text class="terminal-r1" x="1464" y="849.6" textLength="12.2" clip-path="url(#terminal-line-34)">
</text><text class="terminal-r5" x="0" y="874" textLength="158.6" clip-path="url(#terminal-line-35)">/test/workdir</text><text class="terminal-r5" x="1256.6" y="874" textLength="207.4" clip-path="url(#terminal-line-35)">0%&#160;of&#160;200k&#160;tokens</text>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 18 KiB

Before After
Before After

View file

@ -183,7 +183,7 @@
</text><text class="terminal-r1" x="1220" y="532.4" textLength="12.2" clip-path="url(#terminal-line-21)">
</text><text class="terminal-r1" x="1220" y="556.8" textLength="12.2" clip-path="url(#terminal-line-22)">
</text><text class="terminal-r1" x="1220" y="581.2" textLength="12.2" clip-path="url(#terminal-line-23)">
</text><text class="terminal-r1" x="0" y="605.6" textLength="134.2" clip-path="url(#terminal-line-24)">&#160;&#160;⡠⣒⠄&#160;&#160;⡔⢄⠔⡄</text><text class="terminal-r2" x="170.8" y="605.6" textLength="146.4" clip-path="url(#terminal-line-24)">Mistral&#160;Vibe</text><text class="terminal-r1" x="317.2" y="605.6" textLength="122" clip-path="url(#terminal-line-24)">&#160;v0.0.0&#160;·&#160;</text><text class="terminal-r3" x="439.2" y="605.6" textLength="97.6" clip-path="url(#terminal-line-24)">devstral</text><text class="terminal-r1" x="536.8" y="605.6" textLength="256.2" clip-path="url(#terminal-line-24)">&#160;·&#160;[Subscription]&#160;Pro</text><text class="terminal-r1" x="1220" y="605.6" textLength="12.2" clip-path="url(#terminal-line-24)">
</text><text class="terminal-r1" x="0" y="605.6" textLength="134.2" clip-path="url(#terminal-line-24)">&#160;&#160;⡠⣒⠄&#160;&#160;⡔⢄⠔⡄</text><text class="terminal-r2" x="170.8" y="605.6" textLength="146.4" clip-path="url(#terminal-line-24)">Mistral&#160;Vibe</text><text class="terminal-r1" x="317.2" y="605.6" textLength="122" clip-path="url(#terminal-line-24)">&#160;v0.0.0&#160;·&#160;</text><text class="terminal-r3" x="439.2" y="605.6" textLength="158.6" clip-path="url(#terminal-line-24)">devstral[off]</text><text class="terminal-r1" x="597.8" y="605.6" textLength="256.2" clip-path="url(#terminal-line-24)">&#160;·&#160;[Subscription]&#160;Pro</text><text class="terminal-r1" x="1220" y="605.6" textLength="12.2" clip-path="url(#terminal-line-24)">
</text><text class="terminal-r1" x="0" y="630" textLength="134.2" clip-path="url(#terminal-line-25)">&#160;⢸⠸⣀⡔⢉⠱⣃⡢⣂⡣</text><text class="terminal-r1" x="170.8" y="630" textLength="427" clip-path="url(#terminal-line-25)">5&#160;models&#160;·&#160;0&#160;MCP&#160;servers&#160;·&#160;0&#160;skills</text><text class="terminal-r1" x="1220" y="630" textLength="12.2" clip-path="url(#terminal-line-25)">
</text><text class="terminal-r1" x="0" y="654.4" textLength="134.2" clip-path="url(#terminal-line-26)">&#160;&#160;⠉⠒⠣⠤⠵⠤⠬⠮⠆</text><text class="terminal-r1" x="170.8" y="654.4" textLength="61" clip-path="url(#terminal-line-26)">Type&#160;</text><text class="terminal-r3" x="231.8" y="654.4" textLength="61" clip-path="url(#terminal-line-26)">/help</text><text class="terminal-r1" x="292.8" y="654.4" textLength="256.2" clip-path="url(#terminal-line-26)">&#160;for&#160;more&#160;information</text><text class="terminal-r1" x="1220" y="654.4" textLength="12.2" clip-path="url(#terminal-line-26)">
</text><text class="terminal-r1" x="1220" y="678.8" textLength="12.2" clip-path="url(#terminal-line-27)">

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 13 KiB

Before After
Before After

View file

@ -181,7 +181,7 @@
</text><text class="terminal-r1" x="1220" y="410.4" textLength="12.2" clip-path="url(#terminal-line-16)">
</text><text class="terminal-r1" x="1220" y="434.8" textLength="12.2" clip-path="url(#terminal-line-17)">
</text><text class="terminal-r1" x="1220" y="459.2" textLength="12.2" clip-path="url(#terminal-line-18)">
</text><text class="terminal-r1" x="0" y="483.6" textLength="134.2" clip-path="url(#terminal-line-19)">&#160;&#160;⡠⣒⠄&#160;&#160;⡔⢄⠔⡄</text><text class="terminal-r2" x="170.8" y="483.6" textLength="146.4" clip-path="url(#terminal-line-19)">Mistral&#160;Vibe</text><text class="terminal-r1" x="317.2" y="483.6" textLength="122" clip-path="url(#terminal-line-19)">&#160;v0.0.0&#160;·&#160;</text><text class="terminal-r3" x="439.2" y="483.6" textLength="97.6" clip-path="url(#terminal-line-19)">devstral</text><text class="terminal-r1" x="536.8" y="483.6" textLength="256.2" clip-path="url(#terminal-line-19)">&#160;·&#160;[Subscription]&#160;Pro</text><text class="terminal-r1" x="1220" y="483.6" textLength="12.2" clip-path="url(#terminal-line-19)">
</text><text class="terminal-r1" x="0" y="483.6" textLength="134.2" clip-path="url(#terminal-line-19)">&#160;&#160;⡠⣒⠄&#160;&#160;⡔⢄⠔⡄</text><text class="terminal-r2" x="170.8" y="483.6" textLength="146.4" clip-path="url(#terminal-line-19)">Mistral&#160;Vibe</text><text class="terminal-r1" x="317.2" y="483.6" textLength="122" clip-path="url(#terminal-line-19)">&#160;v0.0.0&#160;·&#160;</text><text class="terminal-r3" x="439.2" y="483.6" textLength="158.6" clip-path="url(#terminal-line-19)">devstral[off]</text><text class="terminal-r1" x="597.8" y="483.6" textLength="256.2" clip-path="url(#terminal-line-19)">&#160;·&#160;[Subscription]&#160;Pro</text><text class="terminal-r1" x="1220" y="483.6" textLength="12.2" clip-path="url(#terminal-line-19)">
</text><text class="terminal-r1" x="0" y="508" textLength="134.2" clip-path="url(#terminal-line-20)">&#160;⢸⠸⣀⡔⢉⠱⣃⡢⣂⡣</text><text class="terminal-r1" x="170.8" y="508" textLength="427" clip-path="url(#terminal-line-20)">5&#160;models&#160;·&#160;0&#160;MCP&#160;servers&#160;·&#160;0&#160;skills</text><text class="terminal-r1" x="1220" y="508" textLength="12.2" clip-path="url(#terminal-line-20)">
</text><text class="terminal-r1" x="0" y="532.4" textLength="134.2" clip-path="url(#terminal-line-21)">&#160;&#160;⠉⠒⠣⠤⠵⠤⠬⠮⠆</text><text class="terminal-r1" x="170.8" y="532.4" textLength="61" clip-path="url(#terminal-line-21)">Type&#160;</text><text class="terminal-r3" x="231.8" y="532.4" textLength="61" clip-path="url(#terminal-line-21)">/help</text><text class="terminal-r1" x="292.8" y="532.4" textLength="256.2" clip-path="url(#terminal-line-21)">&#160;for&#160;more&#160;information</text><text class="terminal-r1" x="1220" y="532.4" textLength="12.2" clip-path="url(#terminal-line-21)">
</text><text class="terminal-r1" x="1220" y="556.8" textLength="12.2" clip-path="url(#terminal-line-22)">

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 15 KiB

Before After
Before After

View file

@ -181,7 +181,7 @@
</text><text class="terminal-r1" x="1220" y="410.4" textLength="12.2" clip-path="url(#terminal-line-16)">
</text><text class="terminal-r1" x="1220" y="434.8" textLength="12.2" clip-path="url(#terminal-line-17)">
</text><text class="terminal-r1" x="1220" y="459.2" textLength="12.2" clip-path="url(#terminal-line-18)">
</text><text class="terminal-r1" x="0" y="483.6" textLength="134.2" clip-path="url(#terminal-line-19)">&#160;&#160;⡠⣒⠄&#160;&#160;⡔⢄⠔⡄</text><text class="terminal-r2" x="170.8" y="483.6" textLength="146.4" clip-path="url(#terminal-line-19)">Mistral&#160;Vibe</text><text class="terminal-r1" x="317.2" y="483.6" textLength="122" clip-path="url(#terminal-line-19)">&#160;v0.0.0&#160;·&#160;</text><text class="terminal-r3" x="439.2" y="483.6" textLength="97.6" clip-path="url(#terminal-line-19)">devstral</text><text class="terminal-r1" x="536.8" y="483.6" textLength="256.2" clip-path="url(#terminal-line-19)">&#160;·&#160;[Subscription]&#160;Pro</text><text class="terminal-r1" x="1220" y="483.6" textLength="12.2" clip-path="url(#terminal-line-19)">
</text><text class="terminal-r1" x="0" y="483.6" textLength="134.2" clip-path="url(#terminal-line-19)">&#160;&#160;⡠⣒⠄&#160;&#160;⡔⢄⠔⡄</text><text class="terminal-r2" x="170.8" y="483.6" textLength="146.4" clip-path="url(#terminal-line-19)">Mistral&#160;Vibe</text><text class="terminal-r1" x="317.2" y="483.6" textLength="122" clip-path="url(#terminal-line-19)">&#160;v0.0.0&#160;·&#160;</text><text class="terminal-r3" x="439.2" y="483.6" textLength="158.6" clip-path="url(#terminal-line-19)">devstral[off]</text><text class="terminal-r1" x="597.8" y="483.6" textLength="256.2" clip-path="url(#terminal-line-19)">&#160;·&#160;[Subscription]&#160;Pro</text><text class="terminal-r1" x="1220" y="483.6" textLength="12.2" clip-path="url(#terminal-line-19)">
</text><text class="terminal-r1" x="0" y="508" textLength="134.2" clip-path="url(#terminal-line-20)">&#160;⢸⠸⣀⡔⢉⠱⣃⡢⣂⡣</text><text class="terminal-r1" x="170.8" y="508" textLength="427" clip-path="url(#terminal-line-20)">5&#160;models&#160;·&#160;0&#160;MCP&#160;servers&#160;·&#160;0&#160;skills</text><text class="terminal-r1" x="1220" y="508" textLength="12.2" clip-path="url(#terminal-line-20)">
</text><text class="terminal-r1" x="0" y="532.4" textLength="134.2" clip-path="url(#terminal-line-21)">&#160;&#160;⠉⠒⠣⠤⠵⠤⠬⠮⠆</text><text class="terminal-r1" x="170.8" y="532.4" textLength="61" clip-path="url(#terminal-line-21)">Type&#160;</text><text class="terminal-r3" x="231.8" y="532.4" textLength="61" clip-path="url(#terminal-line-21)">/help</text><text class="terminal-r1" x="292.8" y="532.4" textLength="256.2" clip-path="url(#terminal-line-21)">&#160;for&#160;more&#160;information</text><text class="terminal-r1" x="1220" y="532.4" textLength="12.2" clip-path="url(#terminal-line-21)">
</text><text class="terminal-r1" x="1220" y="556.8" textLength="12.2" clip-path="url(#terminal-line-22)">

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 15 KiB

Before After
Before After

View file

@ -182,7 +182,7 @@
</text><text class="terminal-r1" x="1220" y="508" textLength="12.2" clip-path="url(#terminal-line-20)">
</text><text class="terminal-r1" x="1220" y="532.4" textLength="12.2" clip-path="url(#terminal-line-21)">
</text><text class="terminal-r1" x="1220" y="556.8" textLength="12.2" clip-path="url(#terminal-line-22)">
</text><text class="terminal-r1" x="0" y="581.2" textLength="134.2" clip-path="url(#terminal-line-23)">&#160;&#160;⡠⣒⠄&#160;&#160;⡔⢄⠔⡄</text><text class="terminal-r2" x="170.8" y="581.2" textLength="146.4" clip-path="url(#terminal-line-23)">Mistral&#160;Vibe</text><text class="terminal-r1" x="317.2" y="581.2" textLength="122" clip-path="url(#terminal-line-23)">&#160;v0.0.0&#160;·&#160;</text><text class="terminal-r3" x="439.2" y="581.2" textLength="183" clip-path="url(#terminal-line-23)">devstral-latest</text><text class="terminal-r1" x="622.2" y="581.2" textLength="256.2" clip-path="url(#terminal-line-23)">&#160;·&#160;[Subscription]&#160;Pro</text><text class="terminal-r1" x="1220" y="581.2" textLength="12.2" clip-path="url(#terminal-line-23)">
</text><text class="terminal-r1" x="0" y="581.2" textLength="134.2" clip-path="url(#terminal-line-23)">&#160;&#160;⡠⣒⠄&#160;&#160;⡔⢄⠔⡄</text><text class="terminal-r2" x="170.8" y="581.2" textLength="146.4" clip-path="url(#terminal-line-23)">Mistral&#160;Vibe</text><text class="terminal-r1" x="317.2" y="581.2" textLength="122" clip-path="url(#terminal-line-23)">&#160;v0.0.0&#160;·&#160;</text><text class="terminal-r3" x="439.2" y="581.2" textLength="244" clip-path="url(#terminal-line-23)">devstral-latest[off]</text><text class="terminal-r1" x="683.2" y="581.2" textLength="256.2" clip-path="url(#terminal-line-23)">&#160;·&#160;[Subscription]&#160;Pro</text><text class="terminal-r1" x="1220" y="581.2" textLength="12.2" clip-path="url(#terminal-line-23)">
</text><text class="terminal-r1" x="0" y="605.6" textLength="134.2" clip-path="url(#terminal-line-24)">&#160;⢸⠸⣀⡔⢉⠱⣃⡢⣂⡣</text><text class="terminal-r1" x="170.8" y="605.6" textLength="414.8" clip-path="url(#terminal-line-24)">1&#160;model&#160;·&#160;0&#160;MCP&#160;servers&#160;·&#160;0&#160;skills</text><text class="terminal-r1" x="1220" y="605.6" textLength="12.2" clip-path="url(#terminal-line-24)">
</text><text class="terminal-r1" x="0" y="630" textLength="134.2" clip-path="url(#terminal-line-25)">&#160;&#160;⠉⠒⠣⠤⠵⠤⠬⠮⠆</text><text class="terminal-r1" x="170.8" y="630" textLength="61" clip-path="url(#terminal-line-25)">Type&#160;</text><text class="terminal-r3" x="231.8" y="630" textLength="61" clip-path="url(#terminal-line-25)">/help</text><text class="terminal-r1" x="292.8" y="630" textLength="256.2" clip-path="url(#terminal-line-25)">&#160;for&#160;more&#160;information</text><text class="terminal-r1" x="1220" y="630" textLength="12.2" clip-path="url(#terminal-line-25)">
</text><text class="terminal-r1" x="1220" y="654.4" textLength="12.2" clip-path="url(#terminal-line-26)">

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 13 KiB

Before After
Before After

View file

@ -184,7 +184,7 @@
</text><text class="terminal-r1" x="1464" y="532.4" textLength="12.2" clip-path="url(#terminal-line-21)">
</text><text class="terminal-r1" x="1464" y="556.8" textLength="12.2" clip-path="url(#terminal-line-22)">
</text><text class="terminal-r1" x="1464" y="581.2" textLength="12.2" clip-path="url(#terminal-line-23)">
</text><text class="terminal-r1" x="0" y="605.6" textLength="134.2" clip-path="url(#terminal-line-24)">&#160;&#160;⡠⣒⠄&#160;&#160;⡔⢄⠔⡄</text><text class="terminal-r2" x="170.8" y="605.6" textLength="146.4" clip-path="url(#terminal-line-24)">Mistral&#160;Vibe</text><text class="terminal-r1" x="317.2" y="605.6" textLength="122" clip-path="url(#terminal-line-24)">&#160;v0.0.0&#160;·&#160;</text><text class="terminal-r3" x="439.2" y="605.6" textLength="183" clip-path="url(#terminal-line-24)">devstral-latest</text><text class="terminal-r1" x="622.2" y="605.6" textLength="256.2" clip-path="url(#terminal-line-24)">&#160;·&#160;[Subscription]&#160;Pro</text><text class="terminal-r1" x="1464" y="605.6" textLength="12.2" clip-path="url(#terminal-line-24)">
</text><text class="terminal-r1" x="0" y="605.6" textLength="134.2" clip-path="url(#terminal-line-24)">&#160;&#160;⡠⣒⠄&#160;&#160;⡔⢄⠔⡄</text><text class="terminal-r2" x="170.8" y="605.6" textLength="146.4" clip-path="url(#terminal-line-24)">Mistral&#160;Vibe</text><text class="terminal-r1" x="317.2" y="605.6" textLength="122" clip-path="url(#terminal-line-24)">&#160;v0.0.0&#160;·&#160;</text><text class="terminal-r3" x="439.2" y="605.6" textLength="244" clip-path="url(#terminal-line-24)">devstral-latest[off]</text><text class="terminal-r1" x="683.2" y="605.6" textLength="256.2" clip-path="url(#terminal-line-24)">&#160;·&#160;[Subscription]&#160;Pro</text><text class="terminal-r1" x="1464" y="605.6" textLength="12.2" clip-path="url(#terminal-line-24)">
</text><text class="terminal-r1" x="0" y="630" textLength="134.2" clip-path="url(#terminal-line-25)">&#160;⢸⠸⣀⡔⢉⠱⣃⡢⣂⡣</text><text class="terminal-r1" x="170.8" y="630" textLength="414.8" clip-path="url(#terminal-line-25)">1&#160;model&#160;·&#160;0&#160;MCP&#160;servers&#160;·&#160;0&#160;skills</text><text class="terminal-r1" x="1464" y="630" textLength="12.2" clip-path="url(#terminal-line-25)">
</text><text class="terminal-r1" x="0" y="654.4" textLength="134.2" clip-path="url(#terminal-line-26)">&#160;&#160;⠉⠒⠣⠤⠵⠤⠬⠮⠆</text><text class="terminal-r1" x="170.8" y="654.4" textLength="61" clip-path="url(#terminal-line-26)">Type&#160;</text><text class="terminal-r3" x="231.8" y="654.4" textLength="61" clip-path="url(#terminal-line-26)">/help</text><text class="terminal-r1" x="292.8" y="654.4" textLength="256.2" clip-path="url(#terminal-line-26)">&#160;for&#160;more&#160;information</text><text class="terminal-r1" x="1464" y="654.4" textLength="12.2" clip-path="url(#terminal-line-26)">
</text><text class="terminal-r1" x="1464" y="678.8" textLength="12.2" clip-path="url(#terminal-line-27)">

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 13 KiB

Before After
Before After

View file

@ -184,7 +184,7 @@
</text><text class="terminal-r1" x="1464" y="532.4" textLength="12.2" clip-path="url(#terminal-line-21)">
</text><text class="terminal-r1" x="1464" y="556.8" textLength="12.2" clip-path="url(#terminal-line-22)">
</text><text class="terminal-r1" x="1464" y="581.2" textLength="12.2" clip-path="url(#terminal-line-23)">
</text><text class="terminal-r1" x="0" y="605.6" textLength="134.2" clip-path="url(#terminal-line-24)">&#160;&#160;⡠⣒⠄&#160;&#160;⡔⢄⠔⡄</text><text class="terminal-r2" x="170.8" y="605.6" textLength="146.4" clip-path="url(#terminal-line-24)">Mistral&#160;Vibe</text><text class="terminal-r1" x="317.2" y="605.6" textLength="122" clip-path="url(#terminal-line-24)">&#160;v0.0.0&#160;·&#160;</text><text class="terminal-r3" x="439.2" y="605.6" textLength="183" clip-path="url(#terminal-line-24)">devstral-latest</text><text class="terminal-r1" x="622.2" y="605.6" textLength="256.2" clip-path="url(#terminal-line-24)">&#160;·&#160;[Subscription]&#160;Pro</text><text class="terminal-r1" x="1464" y="605.6" textLength="12.2" clip-path="url(#terminal-line-24)">
</text><text class="terminal-r1" x="0" y="605.6" textLength="134.2" clip-path="url(#terminal-line-24)">&#160;&#160;⡠⣒⠄&#160;&#160;⡔⢄⠔⡄</text><text class="terminal-r2" x="170.8" y="605.6" textLength="146.4" clip-path="url(#terminal-line-24)">Mistral&#160;Vibe</text><text class="terminal-r1" x="317.2" y="605.6" textLength="122" clip-path="url(#terminal-line-24)">&#160;v0.0.0&#160;·&#160;</text><text class="terminal-r3" x="439.2" y="605.6" textLength="244" clip-path="url(#terminal-line-24)">devstral-latest[off]</text><text class="terminal-r1" x="683.2" y="605.6" textLength="256.2" clip-path="url(#terminal-line-24)">&#160;·&#160;[Subscription]&#160;Pro</text><text class="terminal-r1" x="1464" y="605.6" textLength="12.2" clip-path="url(#terminal-line-24)">
</text><text class="terminal-r1" x="0" y="630" textLength="134.2" clip-path="url(#terminal-line-25)">&#160;⢸⠸⣀⡔⢉⠱⣃⡢⣂⡣</text><text class="terminal-r1" x="170.8" y="630" textLength="414.8" clip-path="url(#terminal-line-25)">1&#160;model&#160;·&#160;0&#160;MCP&#160;servers&#160;·&#160;0&#160;skills</text><text class="terminal-r1" x="1464" y="630" textLength="12.2" clip-path="url(#terminal-line-25)">
</text><text class="terminal-r1" x="0" y="654.4" textLength="134.2" clip-path="url(#terminal-line-26)">&#160;&#160;⠉⠒⠣⠤⠵⠤⠬⠮⠆</text><text class="terminal-r1" x="170.8" y="654.4" textLength="61" clip-path="url(#terminal-line-26)">Type&#160;</text><text class="terminal-r3" x="231.8" y="654.4" textLength="61" clip-path="url(#terminal-line-26)">/help</text><text class="terminal-r1" x="292.8" y="654.4" textLength="256.2" clip-path="url(#terminal-line-26)">&#160;for&#160;more&#160;information</text><text class="terminal-r1" x="1464" y="654.4" textLength="12.2" clip-path="url(#terminal-line-26)">
</text><text class="terminal-r1" x="1464" y="678.8" textLength="12.2" clip-path="url(#terminal-line-27)">

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 13 KiB

Before After
Before After

View file

@ -184,7 +184,7 @@
</text><text class="terminal-r1" x="1464" y="532.4" textLength="12.2" clip-path="url(#terminal-line-21)">
</text><text class="terminal-r1" x="1464" y="556.8" textLength="12.2" clip-path="url(#terminal-line-22)">
</text><text class="terminal-r1" x="1464" y="581.2" textLength="12.2" clip-path="url(#terminal-line-23)">
</text><text class="terminal-r1" x="0" y="605.6" textLength="134.2" clip-path="url(#terminal-line-24)">&#160;&#160;⡠⣒⠄&#160;&#160;⡔⢄⠔⡄</text><text class="terminal-r2" x="170.8" y="605.6" textLength="146.4" clip-path="url(#terminal-line-24)">Mistral&#160;Vibe</text><text class="terminal-r1" x="317.2" y="605.6" textLength="122" clip-path="url(#terminal-line-24)">&#160;v0.0.0&#160;·&#160;</text><text class="terminal-r3" x="439.2" y="605.6" textLength="183" clip-path="url(#terminal-line-24)">devstral-latest</text><text class="terminal-r1" x="622.2" y="605.6" textLength="256.2" clip-path="url(#terminal-line-24)">&#160;·&#160;[Subscription]&#160;Pro</text><text class="terminal-r1" x="1464" y="605.6" textLength="12.2" clip-path="url(#terminal-line-24)">
</text><text class="terminal-r1" x="0" y="605.6" textLength="134.2" clip-path="url(#terminal-line-24)">&#160;&#160;⡠⣒⠄&#160;&#160;⡔⢄⠔⡄</text><text class="terminal-r2" x="170.8" y="605.6" textLength="146.4" clip-path="url(#terminal-line-24)">Mistral&#160;Vibe</text><text class="terminal-r1" x="317.2" y="605.6" textLength="122" clip-path="url(#terminal-line-24)">&#160;v0.0.0&#160;·&#160;</text><text class="terminal-r3" x="439.2" y="605.6" textLength="244" clip-path="url(#terminal-line-24)">devstral-latest[off]</text><text class="terminal-r1" x="683.2" y="605.6" textLength="256.2" clip-path="url(#terminal-line-24)">&#160;·&#160;[Subscription]&#160;Pro</text><text class="terminal-r1" x="1464" y="605.6" textLength="12.2" clip-path="url(#terminal-line-24)">
</text><text class="terminal-r1" x="0" y="630" textLength="134.2" clip-path="url(#terminal-line-25)">&#160;⢸⠸⣀⡔⢉⠱⣃⡢⣂⡣</text><text class="terminal-r1" x="170.8" y="630" textLength="414.8" clip-path="url(#terminal-line-25)">1&#160;model&#160;·&#160;0&#160;MCP&#160;servers&#160;·&#160;0&#160;skills</text><text class="terminal-r1" x="1464" y="630" textLength="12.2" clip-path="url(#terminal-line-25)">
</text><text class="terminal-r1" x="0" y="654.4" textLength="134.2" clip-path="url(#terminal-line-26)">&#160;&#160;⠉⠒⠣⠤⠵⠤⠬⠮⠆</text><text class="terminal-r1" x="170.8" y="654.4" textLength="61" clip-path="url(#terminal-line-26)">Type&#160;</text><text class="terminal-r3" x="231.8" y="654.4" textLength="61" clip-path="url(#terminal-line-26)">/help</text><text class="terminal-r1" x="292.8" y="654.4" textLength="256.2" clip-path="url(#terminal-line-26)">&#160;for&#160;more&#160;information</text><text class="terminal-r1" x="1464" y="654.4" textLength="12.2" clip-path="url(#terminal-line-26)">
</text><text class="terminal-r1" x="1464" y="678.8" textLength="12.2" clip-path="url(#terminal-line-27)">

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 13 KiB

Before After
Before After

View file

@ -183,7 +183,7 @@
</text><text class="terminal-r1" x="1464" y="532.4" textLength="12.2" clip-path="url(#terminal-line-21)">
</text><text class="terminal-r1" x="1464" y="556.8" textLength="12.2" clip-path="url(#terminal-line-22)">
</text><text class="terminal-r1" x="1464" y="581.2" textLength="12.2" clip-path="url(#terminal-line-23)">
</text><text class="terminal-r1" x="0" y="605.6" textLength="134.2" clip-path="url(#terminal-line-24)">&#160;&#160;⡠⣒⠄&#160;&#160;⡔⢄⠔⡄</text><text class="terminal-r2" x="170.8" y="605.6" textLength="146.4" clip-path="url(#terminal-line-24)">Mistral&#160;Vibe</text><text class="terminal-r1" x="317.2" y="605.6" textLength="122" clip-path="url(#terminal-line-24)">&#160;v0.0.0&#160;·&#160;</text><text class="terminal-r3" x="439.2" y="605.6" textLength="183" clip-path="url(#terminal-line-24)">devstral-latest</text><text class="terminal-r1" x="622.2" y="605.6" textLength="256.2" clip-path="url(#terminal-line-24)">&#160;·&#160;[Subscription]&#160;Pro</text><text class="terminal-r1" x="1464" y="605.6" textLength="12.2" clip-path="url(#terminal-line-24)">
</text><text class="terminal-r1" x="0" y="605.6" textLength="134.2" clip-path="url(#terminal-line-24)">&#160;&#160;⡠⣒⠄&#160;&#160;⡔⢄⠔⡄</text><text class="terminal-r2" x="170.8" y="605.6" textLength="146.4" clip-path="url(#terminal-line-24)">Mistral&#160;Vibe</text><text class="terminal-r1" x="317.2" y="605.6" textLength="122" clip-path="url(#terminal-line-24)">&#160;v0.0.0&#160;·&#160;</text><text class="terminal-r3" x="439.2" y="605.6" textLength="244" clip-path="url(#terminal-line-24)">devstral-latest[off]</text><text class="terminal-r1" x="683.2" y="605.6" textLength="256.2" clip-path="url(#terminal-line-24)">&#160;·&#160;[Subscription]&#160;Pro</text><text class="terminal-r1" x="1464" y="605.6" textLength="12.2" clip-path="url(#terminal-line-24)">
</text><text class="terminal-r1" x="0" y="630" textLength="134.2" clip-path="url(#terminal-line-25)">&#160;⢸⠸⣀⡔⢉⠱⣃⡢⣂⡣</text><text class="terminal-r1" x="170.8" y="630" textLength="414.8" clip-path="url(#terminal-line-25)">1&#160;model&#160;·&#160;0&#160;MCP&#160;servers&#160;·&#160;0&#160;skills</text><text class="terminal-r1" x="1464" y="630" textLength="12.2" clip-path="url(#terminal-line-25)">
</text><text class="terminal-r1" x="0" y="654.4" textLength="134.2" clip-path="url(#terminal-line-26)">&#160;&#160;⠉⠒⠣⠤⠵⠤⠬⠮⠆</text><text class="terminal-r1" x="170.8" y="654.4" textLength="61" clip-path="url(#terminal-line-26)">Type&#160;</text><text class="terminal-r3" x="231.8" y="654.4" textLength="61" clip-path="url(#terminal-line-26)">/help</text><text class="terminal-r1" x="292.8" y="654.4" textLength="256.2" clip-path="url(#terminal-line-26)">&#160;for&#160;more&#160;information</text><text class="terminal-r1" x="1464" y="654.4" textLength="12.2" clip-path="url(#terminal-line-26)">
</text><text class="terminal-r1" x="1464" y="678.8" textLength="12.2" clip-path="url(#terminal-line-27)">

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 13 KiB

Before After
Before After

View file

@ -183,7 +183,7 @@
</text><text class="terminal-r1" x="1464" y="532.4" textLength="12.2" clip-path="url(#terminal-line-21)">
</text><text class="terminal-r1" x="1464" y="556.8" textLength="12.2" clip-path="url(#terminal-line-22)">
</text><text class="terminal-r1" x="1464" y="581.2" textLength="12.2" clip-path="url(#terminal-line-23)">
</text><text class="terminal-r1" x="0" y="605.6" textLength="134.2" clip-path="url(#terminal-line-24)">&#160;&#160;⡠⣒⠄&#160;&#160;⡔⢄⠔⡄</text><text class="terminal-r2" x="170.8" y="605.6" textLength="146.4" clip-path="url(#terminal-line-24)">Mistral&#160;Vibe</text><text class="terminal-r1" x="317.2" y="605.6" textLength="122" clip-path="url(#terminal-line-24)">&#160;v0.0.0&#160;·&#160;</text><text class="terminal-r3" x="439.2" y="605.6" textLength="183" clip-path="url(#terminal-line-24)">devstral-latest</text><text class="terminal-r1" x="622.2" y="605.6" textLength="256.2" clip-path="url(#terminal-line-24)">&#160;·&#160;[Subscription]&#160;Pro</text><text class="terminal-r1" x="1464" y="605.6" textLength="12.2" clip-path="url(#terminal-line-24)">
</text><text class="terminal-r1" x="0" y="605.6" textLength="134.2" clip-path="url(#terminal-line-24)">&#160;&#160;⡠⣒⠄&#160;&#160;⡔⢄⠔⡄</text><text class="terminal-r2" x="170.8" y="605.6" textLength="146.4" clip-path="url(#terminal-line-24)">Mistral&#160;Vibe</text><text class="terminal-r1" x="317.2" y="605.6" textLength="122" clip-path="url(#terminal-line-24)">&#160;v0.0.0&#160;·&#160;</text><text class="terminal-r3" x="439.2" y="605.6" textLength="244" clip-path="url(#terminal-line-24)">devstral-latest[off]</text><text class="terminal-r1" x="683.2" y="605.6" textLength="256.2" clip-path="url(#terminal-line-24)">&#160;·&#160;[Subscription]&#160;Pro</text><text class="terminal-r1" x="1464" y="605.6" textLength="12.2" clip-path="url(#terminal-line-24)">
</text><text class="terminal-r1" x="0" y="630" textLength="134.2" clip-path="url(#terminal-line-25)">&#160;⢸⠸⣀⡔⢉⠱⣃⡢⣂⡣</text><text class="terminal-r1" x="170.8" y="630" textLength="414.8" clip-path="url(#terminal-line-25)">1&#160;model&#160;·&#160;0&#160;MCP&#160;servers&#160;·&#160;0&#160;skills</text><text class="terminal-r1" x="1464" y="630" textLength="12.2" clip-path="url(#terminal-line-25)">
</text><text class="terminal-r1" x="0" y="654.4" textLength="134.2" clip-path="url(#terminal-line-26)">&#160;&#160;⠉⠒⠣⠤⠵⠤⠬⠮⠆</text><text class="terminal-r1" x="170.8" y="654.4" textLength="61" clip-path="url(#terminal-line-26)">Type&#160;</text><text class="terminal-r3" x="231.8" y="654.4" textLength="61" clip-path="url(#terminal-line-26)">/help</text><text class="terminal-r1" x="292.8" y="654.4" textLength="256.2" clip-path="url(#terminal-line-26)">&#160;for&#160;more&#160;information</text><text class="terminal-r1" x="1464" y="654.4" textLength="12.2" clip-path="url(#terminal-line-26)">
</text><text class="terminal-r1" x="1464" y="678.8" textLength="12.2" clip-path="url(#terminal-line-27)">

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 13 KiB

Before After
Before After

View file

@ -180,7 +180,7 @@
</text><text class="terminal-r1" x="1464" y="434.8" textLength="12.2" clip-path="url(#terminal-line-17)">
</text><text class="terminal-r1" x="1464" y="459.2" textLength="12.2" clip-path="url(#terminal-line-18)">
</text><text class="terminal-r1" x="1464" y="483.6" textLength="12.2" clip-path="url(#terminal-line-19)">
</text><text class="terminal-r1" x="0" y="508" textLength="134.2" clip-path="url(#terminal-line-20)">&#160;&#160;⡠⣒⠄&#160;&#160;⡔⢄⠔⡄</text><text class="terminal-r2" x="170.8" y="508" textLength="146.4" clip-path="url(#terminal-line-20)">Mistral&#160;Vibe</text><text class="terminal-r1" x="317.2" y="508" textLength="122" clip-path="url(#terminal-line-20)">&#160;v0.0.0&#160;·&#160;</text><text class="terminal-r3" x="439.2" y="508" textLength="183" clip-path="url(#terminal-line-20)">devstral-latest</text><text class="terminal-r1" x="622.2" y="508" textLength="256.2" clip-path="url(#terminal-line-20)">&#160;·&#160;[Subscription]&#160;Pro</text><text class="terminal-r1" x="1464" y="508" textLength="12.2" clip-path="url(#terminal-line-20)">
</text><text class="terminal-r1" x="0" y="508" textLength="134.2" clip-path="url(#terminal-line-20)">&#160;&#160;⡠⣒⠄&#160;&#160;⡔⢄⠔⡄</text><text class="terminal-r2" x="170.8" y="508" textLength="146.4" clip-path="url(#terminal-line-20)">Mistral&#160;Vibe</text><text class="terminal-r1" x="317.2" y="508" textLength="122" clip-path="url(#terminal-line-20)">&#160;v0.0.0&#160;·&#160;</text><text class="terminal-r3" x="439.2" y="508" textLength="244" clip-path="url(#terminal-line-20)">devstral-latest[off]</text><text class="terminal-r1" x="683.2" y="508" textLength="256.2" clip-path="url(#terminal-line-20)">&#160;·&#160;[Subscription]&#160;Pro</text><text class="terminal-r1" x="1464" y="508" textLength="12.2" clip-path="url(#terminal-line-20)">
</text><text class="terminal-r1" x="0" y="532.4" textLength="134.2" clip-path="url(#terminal-line-21)">&#160;⢸⠸⣀⡔⢉⠱⣃⡢⣂⡣</text><text class="terminal-r1" x="170.8" y="532.4" textLength="414.8" clip-path="url(#terminal-line-21)">1&#160;model&#160;·&#160;0&#160;MCP&#160;servers&#160;·&#160;0&#160;skills</text><text class="terminal-r1" x="1464" y="532.4" textLength="12.2" clip-path="url(#terminal-line-21)">
</text><text class="terminal-r1" x="0" y="556.8" textLength="134.2" clip-path="url(#terminal-line-22)">&#160;&#160;⠉⠒⠣⠤⠵⠤⠬⠮⠆</text><text class="terminal-r1" x="170.8" y="556.8" textLength="61" clip-path="url(#terminal-line-22)">Type&#160;</text><text class="terminal-r3" x="231.8" y="556.8" textLength="61" clip-path="url(#terminal-line-22)">/help</text><text class="terminal-r1" x="292.8" y="556.8" textLength="256.2" clip-path="url(#terminal-line-22)">&#160;for&#160;more&#160;information</text><text class="terminal-r1" x="1464" y="556.8" textLength="12.2" clip-path="url(#terminal-line-22)">
</text><text class="terminal-r1" x="1464" y="581.2" textLength="12.2" clip-path="url(#terminal-line-23)">

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 13 KiB

Before After
Before After

View file

@ -182,7 +182,7 @@
</text><text class="terminal-r1" x="1464" y="434.8" textLength="12.2" clip-path="url(#terminal-line-17)">
</text><text class="terminal-r1" x="1464" y="459.2" textLength="12.2" clip-path="url(#terminal-line-18)">
</text><text class="terminal-r1" x="1464" y="483.6" textLength="12.2" clip-path="url(#terminal-line-19)">
</text><text class="terminal-r1" x="0" y="508" textLength="134.2" clip-path="url(#terminal-line-20)">&#160;&#160;⡠⣒⠄&#160;&#160;⡔⢄⠔⡄</text><text class="terminal-r2" x="170.8" y="508" textLength="146.4" clip-path="url(#terminal-line-20)">Mistral&#160;Vibe</text><text class="terminal-r1" x="317.2" y="508" textLength="122" clip-path="url(#terminal-line-20)">&#160;v0.0.0&#160;·&#160;</text><text class="terminal-r3" x="439.2" y="508" textLength="183" clip-path="url(#terminal-line-20)">devstral-latest</text><text class="terminal-r1" x="622.2" y="508" textLength="256.2" clip-path="url(#terminal-line-20)">&#160;·&#160;[Subscription]&#160;Pro</text><text class="terminal-r1" x="1464" y="508" textLength="12.2" clip-path="url(#terminal-line-20)">
</text><text class="terminal-r1" x="0" y="508" textLength="134.2" clip-path="url(#terminal-line-20)">&#160;&#160;⡠⣒⠄&#160;&#160;⡔⢄⠔⡄</text><text class="terminal-r2" x="170.8" y="508" textLength="146.4" clip-path="url(#terminal-line-20)">Mistral&#160;Vibe</text><text class="terminal-r1" x="317.2" y="508" textLength="122" clip-path="url(#terminal-line-20)">&#160;v0.0.0&#160;·&#160;</text><text class="terminal-r3" x="439.2" y="508" textLength="244" clip-path="url(#terminal-line-20)">devstral-latest[off]</text><text class="terminal-r1" x="683.2" y="508" textLength="256.2" clip-path="url(#terminal-line-20)">&#160;·&#160;[Subscription]&#160;Pro</text><text class="terminal-r1" x="1464" y="508" textLength="12.2" clip-path="url(#terminal-line-20)">
</text><text class="terminal-r1" x="0" y="532.4" textLength="134.2" clip-path="url(#terminal-line-21)">&#160;⢸⠸⣀⡔⢉⠱⣃⡢⣂⡣</text><text class="terminal-r1" x="170.8" y="532.4" textLength="414.8" clip-path="url(#terminal-line-21)">1&#160;model&#160;·&#160;0&#160;MCP&#160;servers&#160;·&#160;0&#160;skills</text><text class="terminal-r1" x="1464" y="532.4" textLength="12.2" clip-path="url(#terminal-line-21)">
</text><text class="terminal-r1" x="0" y="556.8" textLength="134.2" clip-path="url(#terminal-line-22)">&#160;&#160;⠉⠒⠣⠤⠵⠤⠬⠮⠆</text><text class="terminal-r1" x="170.8" y="556.8" textLength="61" clip-path="url(#terminal-line-22)">Type&#160;</text><text class="terminal-r3" x="231.8" y="556.8" textLength="61" clip-path="url(#terminal-line-22)">/help</text><text class="terminal-r1" x="292.8" y="556.8" textLength="256.2" clip-path="url(#terminal-line-22)">&#160;for&#160;more&#160;information</text><text class="terminal-r1" x="1464" y="556.8" textLength="12.2" clip-path="url(#terminal-line-22)">
</text><text class="terminal-r1" x="1464" y="581.2" textLength="12.2" clip-path="url(#terminal-line-23)">
@ -191,7 +191,7 @@
</text><text class="terminal-r1" x="1464" y="654.4" textLength="12.2" clip-path="url(#terminal-line-26)">
</text><text class="terminal-r1" x="0" y="678.8" textLength="268.4" clip-path="url(#terminal-line-27)">Hello!&#160;I&#160;can&#160;help&#160;you.</text><text class="terminal-r1" x="1464" y="678.8" textLength="12.2" clip-path="url(#terminal-line-27)">
</text><text class="terminal-r1" x="1464" y="703.2" textLength="12.2" clip-path="url(#terminal-line-28)">
</text><text class="terminal-r5" x="12.2" y="727.6" textLength="36.6" clip-path="url(#terminal-line-29)">▂▅▇</text><text class="terminal-r1" x="48.8" y="727.6" textLength="122" clip-path="url(#terminal-line-29)">&#160;speaking&#160;</text><text class="terminal-r6" x="170.8" y="727.6" textLength="134.2" clip-path="url(#terminal-line-29)">esc&#160;to&#160;stop</text><text class="terminal-r1" x="1464" y="727.6" textLength="12.2" clip-path="url(#terminal-line-29)">
</text><text class="terminal-r5" x="12.2" y="727.6" textLength="36.6" clip-path="url(#terminal-line-29)">▂▅▇</text><text class="terminal-r1" x="48.8" y="727.6" textLength="122" clip-path="url(#terminal-line-29)">&#160;speaking&#160;</text><text class="terminal-r6" x="170.8" y="727.6" textLength="219.6" clip-path="url(#terminal-line-29)">Esc/Ctrl+C&#160;to&#160;stop</text><text class="terminal-r1" x="1464" y="727.6" textLength="12.2" clip-path="url(#terminal-line-29)">
</text><text class="terminal-r7" x="0" y="752" textLength="1464" clip-path="url(#terminal-line-30)">┌────────────────────────────────────────────────────────────────────────────────────────────────────────────&#160;default&#160;─┐</text><text class="terminal-r1" x="1464" y="752" textLength="12.2" clip-path="url(#terminal-line-30)">
</text><text class="terminal-r7" x="0" y="776.4" textLength="12.2" clip-path="url(#terminal-line-31)"></text><text class="terminal-r2" x="24.4" y="776.4" textLength="12.2" clip-path="url(#terminal-line-31)">&gt;</text><text class="terminal-r7" x="1451.8" y="776.4" textLength="12.2" clip-path="url(#terminal-line-31)"></text><text class="terminal-r1" x="1464" y="776.4" textLength="12.2" clip-path="url(#terminal-line-31)">
</text><text class="terminal-r7" x="0" y="800.8" textLength="12.2" clip-path="url(#terminal-line-32)"></text><text class="terminal-r7" x="1451.8" y="800.8" textLength="12.2" clip-path="url(#terminal-line-32)"></text><text class="terminal-r1" x="1464" y="800.8" textLength="12.2" clip-path="url(#terminal-line-32)">

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 14 KiB

Before After
Before After

View file

@ -182,7 +182,7 @@
</text><text class="terminal-r1" x="1464" y="434.8" textLength="12.2" clip-path="url(#terminal-line-17)">
</text><text class="terminal-r1" x="1464" y="459.2" textLength="12.2" clip-path="url(#terminal-line-18)">
</text><text class="terminal-r1" x="1464" y="483.6" textLength="12.2" clip-path="url(#terminal-line-19)">
</text><text class="terminal-r1" x="0" y="508" textLength="134.2" clip-path="url(#terminal-line-20)">&#160;&#160;⡠⣒⠄&#160;&#160;⡔⢄⠔⡄</text><text class="terminal-r2" x="170.8" y="508" textLength="146.4" clip-path="url(#terminal-line-20)">Mistral&#160;Vibe</text><text class="terminal-r1" x="317.2" y="508" textLength="122" clip-path="url(#terminal-line-20)">&#160;v0.0.0&#160;·&#160;</text><text class="terminal-r3" x="439.2" y="508" textLength="183" clip-path="url(#terminal-line-20)">devstral-latest</text><text class="terminal-r1" x="622.2" y="508" textLength="256.2" clip-path="url(#terminal-line-20)">&#160;·&#160;[Subscription]&#160;Pro</text><text class="terminal-r1" x="1464" y="508" textLength="12.2" clip-path="url(#terminal-line-20)">
</text><text class="terminal-r1" x="0" y="508" textLength="134.2" clip-path="url(#terminal-line-20)">&#160;&#160;⡠⣒⠄&#160;&#160;⡔⢄⠔⡄</text><text class="terminal-r2" x="170.8" y="508" textLength="146.4" clip-path="url(#terminal-line-20)">Mistral&#160;Vibe</text><text class="terminal-r1" x="317.2" y="508" textLength="122" clip-path="url(#terminal-line-20)">&#160;v0.0.0&#160;·&#160;</text><text class="terminal-r3" x="439.2" y="508" textLength="244" clip-path="url(#terminal-line-20)">devstral-latest[off]</text><text class="terminal-r1" x="683.2" y="508" textLength="256.2" clip-path="url(#terminal-line-20)">&#160;·&#160;[Subscription]&#160;Pro</text><text class="terminal-r1" x="1464" y="508" textLength="12.2" clip-path="url(#terminal-line-20)">
</text><text class="terminal-r1" x="0" y="532.4" textLength="134.2" clip-path="url(#terminal-line-21)">&#160;⢸⠸⣀⡔⢉⠱⣃⡢⣂⡣</text><text class="terminal-r1" x="170.8" y="532.4" textLength="414.8" clip-path="url(#terminal-line-21)">1&#160;model&#160;·&#160;0&#160;MCP&#160;servers&#160;·&#160;0&#160;skills</text><text class="terminal-r1" x="1464" y="532.4" textLength="12.2" clip-path="url(#terminal-line-21)">
</text><text class="terminal-r1" x="0" y="556.8" textLength="134.2" clip-path="url(#terminal-line-22)">&#160;&#160;⠉⠒⠣⠤⠵⠤⠬⠮⠆</text><text class="terminal-r1" x="170.8" y="556.8" textLength="61" clip-path="url(#terminal-line-22)">Type&#160;</text><text class="terminal-r3" x="231.8" y="556.8" textLength="61" clip-path="url(#terminal-line-22)">/help</text><text class="terminal-r1" x="292.8" y="556.8" textLength="256.2" clip-path="url(#terminal-line-22)">&#160;for&#160;more&#160;information</text><text class="terminal-r1" x="1464" y="556.8" textLength="12.2" clip-path="url(#terminal-line-22)">
</text><text class="terminal-r1" x="1464" y="581.2" textLength="12.2" clip-path="url(#terminal-line-23)">
@ -191,7 +191,7 @@
</text><text class="terminal-r1" x="1464" y="654.4" textLength="12.2" clip-path="url(#terminal-line-26)">
</text><text class="terminal-r1" x="0" y="678.8" textLength="268.4" clip-path="url(#terminal-line-27)">Hello!&#160;I&#160;can&#160;help&#160;you.</text><text class="terminal-r1" x="1464" y="678.8" textLength="12.2" clip-path="url(#terminal-line-27)">
</text><text class="terminal-r1" x="1464" y="703.2" textLength="12.2" clip-path="url(#terminal-line-28)">
</text><text class="terminal-r5" x="12.2" y="727.6" textLength="12.2" clip-path="url(#terminal-line-29)"></text><text class="terminal-r1" x="24.4" y="727.6" textLength="158.6" clip-path="url(#terminal-line-29)">&#160;summarizing&#160;</text><text class="terminal-r6" x="183" y="727.6" textLength="134.2" clip-path="url(#terminal-line-29)">esc&#160;to&#160;stop</text><text class="terminal-r1" x="1464" y="727.6" textLength="12.2" clip-path="url(#terminal-line-29)">
</text><text class="terminal-r5" x="12.2" y="727.6" textLength="12.2" clip-path="url(#terminal-line-29)"></text><text class="terminal-r1" x="24.4" y="727.6" textLength="158.6" clip-path="url(#terminal-line-29)">&#160;summarizing&#160;</text><text class="terminal-r6" x="183" y="727.6" textLength="219.6" clip-path="url(#terminal-line-29)">Esc/Ctrl+C&#160;to&#160;stop</text><text class="terminal-r1" x="1464" y="727.6" textLength="12.2" clip-path="url(#terminal-line-29)">
</text><text class="terminal-r7" x="0" y="752" textLength="1464" clip-path="url(#terminal-line-30)">┌────────────────────────────────────────────────────────────────────────────────────────────────────────────&#160;default&#160;─┐</text><text class="terminal-r1" x="1464" y="752" textLength="12.2" clip-path="url(#terminal-line-30)">
</text><text class="terminal-r7" x="0" y="776.4" textLength="12.2" clip-path="url(#terminal-line-31)"></text><text class="terminal-r2" x="24.4" y="776.4" textLength="12.2" clip-path="url(#terminal-line-31)">&gt;</text><text class="terminal-r7" x="1451.8" y="776.4" textLength="12.2" clip-path="url(#terminal-line-31)"></text><text class="terminal-r1" x="1464" y="776.4" textLength="12.2" clip-path="url(#terminal-line-31)">
</text><text class="terminal-r7" x="0" y="800.8" textLength="12.2" clip-path="url(#terminal-line-32)"></text><text class="terminal-r7" x="1451.8" y="800.8" textLength="12.2" clip-path="url(#terminal-line-32)"></text><text class="terminal-r1" x="1464" y="800.8" textLength="12.2" clip-path="url(#terminal-line-32)">

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 14 KiB

Before After
Before After

Some files were not shown because too many files have changed in this diff Show more