v2.9.0 (#641)
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>
244
AGENTS.md
|
|
@ -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.
|
||||
|
|
|
|||
47
CHANGELOG.md
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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
|
|
@ -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 == []
|
||||
101
tests/acp/test_close_session.py
Normal 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,
|
||||
)
|
||||
|
|
@ -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:
|
||||
|
|
|
|||
192
tests/acp/test_fork_session.py
Normal 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)
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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
|
|
@ -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()
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
53
tests/acp/test_telemetry_notification.py
Normal 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
|
||||
)
|
||||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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",
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
||||
|
|
|
|||
520
tests/backend/data/openai_responses.py
Normal 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),
|
||||
],
|
||||
)
|
||||
]
|
||||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
1322
tests/backend/test_openai_responses_adapter.py
Normal 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
|
||||
|
|
|
|||
|
|
@ -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
|
|
@ -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
|
||||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
53
tests/cli/test_copy_command.py
Normal 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
|
||||
)
|
||||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
||||
|
|
|
|||
149
tests/cli/test_feedback_bar_manager.py
Normal 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
|
||||
|
|
@ -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:
|
||||
|
|
|
|||
194
tests/cli/test_programmatic_setup.py
Normal 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()
|
||||
73
tests/cli/test_stderr_guard.py
Normal 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
|
||||
|
|
@ -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"
|
||||
|
|
|
|||
188
tests/cli/test_ui_teleport_availability.py
Normal 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
|
||||
12
tests/cli/textual_ui/test_completion_popup.py
Normal 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
|
||||
81
tests/cli/textual_ui/test_event_handler_hooks.py
Normal 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
|
||||
169
tests/cli/textual_ui/test_quit_confirmation.py
Normal 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")
|
||||
|
|
@ -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
|
||||
)
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
79
tests/core/session/test_session_id.py
Normal 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
|
||||
493
tests/core/test_config_layer.py
Normal 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()
|
||||
|
|
@ -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
|
|
@ -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 == []
|
||||
|
|
@ -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"
|
||||
|
|
|
|||
81
tests/core/test_scratchpad.py
Normal 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)
|
||||
|
|
@ -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)
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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}"
|
||||
)
|
||||
|
|
|
|||
87
tests/e2e/test_cli_tui_hooks.py
Normal 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"]
|
||||
|
|
@ -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())
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)">  ⡠⣒⠄  ⡔⢄⠔⡄</text><text class="terminal-r2" x="170.8" y="215.2" textLength="146.4" clip-path="url(#terminal-line-8)">Mistral Vibe</text><text class="terminal-r1" x="317.2" y="215.2" textLength="122" clip-path="url(#terminal-line-8)"> v0.0.0 · </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)"> · [Subscription] 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)">  ⡠⣒⠄  ⡔⢄⠔⡄</text><text class="terminal-r2" x="170.8" y="215.2" textLength="146.4" clip-path="url(#terminal-line-8)">Mistral Vibe</text><text class="terminal-r1" x="317.2" y="215.2" textLength="122" clip-path="url(#terminal-line-8)"> v0.0.0 · </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)"> · [Subscription] 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)"> ⢸⠸⣀⡔⢉⠱⣃⡢⣂⡣</text><text class="terminal-r1" x="170.8" y="239.6" textLength="414.8" clip-path="url(#terminal-line-9)">1 model · 0 MCP servers · 0 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)">  ⠉⠒⠣⠤⠵⠤⠬⠮⠆</text><text class="terminal-r1" x="170.8" y="264" textLength="61" clip-path="url(#terminal-line-10)">Type </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)"> for more 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 |
|
|
@ -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)">  ⡠⣒⠄  ⡔⢄⠔⡄</text><text class="terminal-r2" x="170.8" y="312.8" textLength="146.4" clip-path="url(#terminal-line-12)">Mistral Vibe</text><text class="terminal-r1" x="317.2" y="312.8" textLength="122" clip-path="url(#terminal-line-12)"> v0.0.0 · </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)"> · [Subscription] 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)">  ⡠⣒⠄  ⡔⢄⠔⡄</text><text class="terminal-r2" x="170.8" y="312.8" textLength="146.4" clip-path="url(#terminal-line-12)">Mistral Vibe</text><text class="terminal-r1" x="317.2" y="312.8" textLength="122" clip-path="url(#terminal-line-12)"> v0.0.0 · </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)"> · [Subscription] 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)"> ⢸⠸⣀⡔⢉⠱⣃⡢⣂⡣</text><text class="terminal-r1" x="170.8" y="337.2" textLength="414.8" clip-path="url(#terminal-line-13)">1 model · 0 MCP servers · 0 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)">  ⠉⠒⠣⠤⠵⠤⠬⠮⠆</text><text class="terminal-r1" x="170.8" y="361.6" textLength="61" clip-path="url(#terminal-line-14)">Type </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)"> for more 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 |
|
|
@ -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)">  ⡠⣒⠄  ⡔⢄⠔⡄</text><text class="terminal-r2" x="170.8" y="508" textLength="146.4" clip-path="url(#terminal-line-20)">Mistral Vibe</text><text class="terminal-r1" x="317.2" y="508" textLength="122" clip-path="url(#terminal-line-20)"> v0.0.0 · </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)"> · [Subscription] 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)">  ⡠⣒⠄  ⡔⢄⠔⡄</text><text class="terminal-r2" x="170.8" y="508" textLength="146.4" clip-path="url(#terminal-line-20)">Mistral Vibe</text><text class="terminal-r1" x="317.2" y="508" textLength="122" clip-path="url(#terminal-line-20)"> v0.0.0 · </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)"> · [Subscription] 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)"> ⢸⠸⣀⡔⢉⠱⣃⡢⣂⡣</text><text class="terminal-r1" x="170.8" y="532.4" textLength="414.8" clip-path="url(#terminal-line-21)">1 model · 0 MCP servers · 0 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)">  ⠉⠒⠣⠤⠵⠤⠬⠮⠆</text><text class="terminal-r1" x="170.8" y="556.8" textLength="61" clip-path="url(#terminal-line-22)">Type </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)"> for more 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 |
|
|
@ -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)">  ⡠⣒⠄  ⡔⢄⠔⡄</text><text class="terminal-r2" x="170.8" y="386" textLength="146.4" clip-path="url(#terminal-line-15)">Mistral Vibe</text><text class="terminal-r1" x="317.2" y="386" textLength="122" clip-path="url(#terminal-line-15)"> v0.0.0 · </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)"> · [Subscription] 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)">  ⡠⣒⠄  ⡔⢄⠔⡄</text><text class="terminal-r2" x="170.8" y="386" textLength="146.4" clip-path="url(#terminal-line-15)">Mistral Vibe</text><text class="terminal-r1" x="317.2" y="386" textLength="122" clip-path="url(#terminal-line-15)"> v0.0.0 · </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)"> · [Subscription] 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)"> ⢸⠸⣀⡔⢉⠱⣃⡢⣂⡣</text><text class="terminal-r1" x="170.8" y="410.4" textLength="414.8" clip-path="url(#terminal-line-16)">1 model · 0 MCP servers · 0 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)">  ⠉⠒⠣⠤⠵⠤⠬⠮⠆</text><text class="terminal-r1" x="170.8" y="434.8" textLength="61" clip-path="url(#terminal-line-17)">Type </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)"> for more 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 |
|
|
@ -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)">  ⡠⣒⠄  ⡔⢄⠔⡄</text><text class="terminal-r2" x="170.8" y="556.8" textLength="146.4" clip-path="url(#terminal-line-22)">Mistral Vibe</text><text class="terminal-r1" x="317.2" y="556.8" textLength="122" clip-path="url(#terminal-line-22)"> v0.0.0 · </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)"> · [Subscription] 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)">  ⡠⣒⠄  ⡔⢄⠔⡄</text><text class="terminal-r2" x="170.8" y="556.8" textLength="146.4" clip-path="url(#terminal-line-22)">Mistral Vibe</text><text class="terminal-r1" x="317.2" y="556.8" textLength="122" clip-path="url(#terminal-line-22)"> v0.0.0 · </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)"> · [Subscription] 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)"> ⢸⠸⣀⡔⢉⠱⣃⡢⣂⡣</text><text class="terminal-r1" x="170.8" y="581.2" textLength="414.8" clip-path="url(#terminal-line-23)">1 model · 0 MCP servers · 0 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)">  ⠉⠒⠣⠤⠵⠤⠬⠮⠆</text><text class="terminal-r1" x="170.8" y="605.6" textLength="61" clip-path="url(#terminal-line-24)">Type </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)"> for more 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 |
|
|
@ -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)">  ⡠⣒⠄  ⡔⢄⠔⡄</text><text class="terminal-r2" x="170.8" y="483.6" textLength="146.4" clip-path="url(#terminal-line-19)">Mistral Vibe</text><text class="terminal-r1" x="317.2" y="483.6" textLength="122" clip-path="url(#terminal-line-19)"> v0.0.0 · </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)"> · [Subscription] 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)"> ⢸⠸⣀⡔⢉⠱⣃⡢⣂⡣</text><text class="terminal-r1" x="170.8" y="508" textLength="414.8" clip-path="url(#terminal-line-20)">1 model · 0 MCP servers · 0 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)">  ⠉⠒⠣⠤⠵⠤⠬⠮⠆</text><text class="terminal-r1" x="170.8" y="532.4" textLength="61" clip-path="url(#terminal-line-21)">Type </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)"> for more 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 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)">  ⡠⣒⠄  ⡔⢄⠔⡄</text><text class="terminal-r2" x="170.8" y="459.2" textLength="146.4" clip-path="url(#terminal-line-18)">Mistral Vibe</text><text class="terminal-r1" x="317.2" y="459.2" textLength="122" clip-path="url(#terminal-line-18)"> v0.0.0 · </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)"> · [Subscription] 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)"> ⢸⠸⣀⡔⢉⠱⣃⡢⣂⡣</text><text class="terminal-r1" x="170.8" y="483.6" textLength="414.8" clip-path="url(#terminal-line-19)">1 model · 0 MCP servers · 0 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)">  ⠉⠒⠣⠤⠵⠤⠬⠮⠆</text><text class="terminal-r1" x="170.8" y="508" textLength="61" clip-path="url(#terminal-line-20)">Type </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)"> for more 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 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: </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: </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: </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: </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 watcher (may delay first autocompletion): </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 |
|
|
@ -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)">  ⡠⣒⠄  ⡔⢄⠔⡄</text><text class="terminal-r2" x="170.8" y="483.6" textLength="146.4" clip-path="url(#terminal-line-19)">Mistral Vibe</text><text class="terminal-r1" x="317.2" y="483.6" textLength="122" clip-path="url(#terminal-line-19)"> v0.0.0 · </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)"> · [Subscription] 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)"> ⢸⠸⣀⡔⢉⠱⣃⡢⣂⡣</text><text class="terminal-r1" x="170.8" y="508" textLength="414.8" clip-path="url(#terminal-line-20)">1 model · 0 MCP servers · 0 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)">  ⠉⠒⠣⠤⠵⠤⠬⠮⠆</text><text class="terminal-r1" x="170.8" y="532.4" textLength="61" clip-path="url(#terminal-line-21)">Type </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)"> for more 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 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)">  ⡠⣒⠄  ⡔⢄⠔⡄</text><text class="terminal-r2" x="170.8" y="459.2" textLength="146.4" clip-path="url(#terminal-line-18)">Mistral Vibe</text><text class="terminal-r1" x="317.2" y="459.2" textLength="122" clip-path="url(#terminal-line-18)"> v0.0.0 · </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)"> · [Subscription] 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)"> ⢸⠸⣀⡔⢉⠱⣃⡢⣂⡣</text><text class="terminal-r1" x="170.8" y="483.6" textLength="414.8" clip-path="url(#terminal-line-19)">1 model · 0 MCP servers · 0 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)">  ⠉⠒⠣⠤⠵⠤⠬⠮⠆</text><text class="terminal-r1" x="170.8" y="508" textLength="61" clip-path="url(#terminal-line-20)">Type </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)"> for more 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 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: </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: </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: </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: </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: </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 watcher (may delay first autocompletion): </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)">↑↓ Navigate  Enter Select/Toggle  Esc 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 |
|
|
@ -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)">  ⡠⣒⠄  ⡔⢄⠔⡄</text><text class="terminal-r2" x="170.8" y="483.6" textLength="146.4" clip-path="url(#terminal-line-19)">Mistral Vibe</text><text class="terminal-r1" x="317.2" y="483.6" textLength="122" clip-path="url(#terminal-line-19)"> v0.0.0 · </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)"> · [Subscription] 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)"> ⢸⠸⣀⡔⢉⠱⣃⡢⣂⡣</text><text class="terminal-r1" x="170.8" y="508" textLength="414.8" clip-path="url(#terminal-line-20)">1 model · 0 MCP servers · 0 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)">  ⠉⠒⠣⠤⠵⠤⠬⠮⠆</text><text class="terminal-r1" x="170.8" y="532.4" textLength="61" clip-path="url(#terminal-line-21)">Type </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)"> for more 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 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)">  ⡠⣒⠄  ⡔⢄⠔⡄</text><text class="terminal-r2" x="170.8" y="459.2" textLength="146.4" clip-path="url(#terminal-line-18)">Mistral Vibe</text><text class="terminal-r1" x="317.2" y="459.2" textLength="122" clip-path="url(#terminal-line-18)"> v0.0.0 · </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)"> · [Subscription] 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)"> ⢸⠸⣀⡔⢉⠱⣃⡢⣂⡣</text><text class="terminal-r1" x="170.8" y="483.6" textLength="414.8" clip-path="url(#terminal-line-19)">1 model · 0 MCP servers · 0 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)">  ⠉⠒⠣⠤⠵⠤⠬⠮⠆</text><text class="terminal-r1" x="170.8" y="508" textLength="61" clip-path="url(#terminal-line-20)">Type </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)"> for more 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 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: </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: </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: </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: </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 watcher (may delay first autocompletion): </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 |
|
|
@ -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)">  ⡠⣒⠄  ⡔⢄⠔⡄</text><text class="terminal-r2" x="170.8" y="459.2" textLength="146.4" clip-path="url(#terminal-line-18)">Mistral Vibe</text><text class="terminal-r1" x="317.2" y="459.2" textLength="122" clip-path="url(#terminal-line-18)"> v0.0.0 · </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)"> · [Subscription] 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)">  ⡠⣒⠄  ⡔⢄⠔⡄</text><text class="terminal-r2" x="170.8" y="459.2" textLength="146.4" clip-path="url(#terminal-line-18)">Mistral Vibe</text><text class="terminal-r1" x="317.2" y="459.2" textLength="122" clip-path="url(#terminal-line-18)"> v0.0.0 · </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)"> · [Subscription] 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)"> ⢸⠸⣀⡔⢉⠱⣃⡢⣂⡣</text><text class="terminal-r1" x="170.8" y="483.6" textLength="414.8" clip-path="url(#terminal-line-19)">1 model · 0 MCP servers · 0 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)">  ⠉⠒⠣⠤⠵⠤⠬⠮⠆</text><text class="terminal-r1" x="170.8" y="508" textLength="61" clip-path="url(#terminal-line-20)">Type </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)"> for more 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 |
|
|
@ -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)">  ⡠⣒⠄  ⡔⢄⠔⡄</text><text class="terminal-r2" x="170.8" y="605.6" textLength="146.4" clip-path="url(#terminal-line-24)">Mistral Vibe</text><text class="terminal-r1" x="317.2" y="605.6" textLength="122" clip-path="url(#terminal-line-24)"> v0.0.0 · </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)"> · [Subscription] 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)">  ⡠⣒⠄  ⡔⢄⠔⡄</text><text class="terminal-r2" x="170.8" y="605.6" textLength="146.4" clip-path="url(#terminal-line-24)">Mistral Vibe</text><text class="terminal-r1" x="317.2" y="605.6" textLength="122" clip-path="url(#terminal-line-24)"> v0.0.0 · </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)"> · [Subscription] 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)"> ⢸⠸⣀⡔⢉⠱⣃⡢⣂⡣</text><text class="terminal-r1" x="170.8" y="630" textLength="414.8" clip-path="url(#terminal-line-25)">1 model · 0 MCP servers · 0 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)">  ⠉⠒⠣⠤⠵⠤⠬⠮⠆</text><text class="terminal-r1" x="170.8" y="654.4" textLength="61" clip-path="url(#terminal-line-26)">Type </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)"> for more 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 |
|
|
@ -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 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)"> Out of memory   </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 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)">  ⡠⣒⠄  ⡔⢄⠔⡄</text><text class="terminal-r8" x="170.8" y="605.6" textLength="146.4" clip-path="url(#terminal-line-24)">Mistral Vibe</text><text class="terminal-r1" x="317.2" y="605.6" textLength="122" clip-path="url(#terminal-line-24)"> v0.0.0 · </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)"> · [Subscription] 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)">  ⡠⣒⠄  ⡔⢄⠔⡄</text><text class="terminal-r8" x="170.8" y="605.6" textLength="146.4" clip-path="url(#terminal-line-24)">Mistral Vibe</text><text class="terminal-r1" x="317.2" y="605.6" textLength="122" clip-path="url(#terminal-line-24)"> v0.0.0 · </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)"> · [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)"> ⢸⠸⣀⡔⢉⠱⣃⡢⣂⡣</text><text class="terminal-r1" x="170.8" y="630" textLength="414.8" clip-path="url(#terminal-line-25)">1 model · 0 MCP servers · 0 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)">  ⠉⠒⠣⠤⠵⠤⠬⠮⠆</text><text class="terminal-r1" x="170.8" y="654.4" textLength="61" clip-path="url(#terminal-line-26)">Type </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)"> for more 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 |
|
|
@ -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)">  ⡠⣒⠄  ⡔⢄⠔⡄</text><text class="terminal-r7" x="170.8" y="605.6" textLength="146.4" clip-path="url(#terminal-line-24)">Mistral Vibe</text><text class="terminal-r1" x="317.2" y="605.6" textLength="122" clip-path="url(#terminal-line-24)"> v0.0.0 · </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)"> · [Subscription] 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)">  ⡠⣒⠄  ⡔⢄⠔⡄</text><text class="terminal-r7" x="170.8" y="605.6" textLength="146.4" clip-path="url(#terminal-line-24)">Mistral Vibe</text><text class="terminal-r1" x="317.2" y="605.6" textLength="122" clip-path="url(#terminal-line-24)"> v0.0.0 · </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)"> · [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)"> ⢸⠸⣀⡔⢉⠱⣃⡢⣂⡣</text><text class="terminal-r1" x="170.8" y="630" textLength="414.8" clip-path="url(#terminal-line-25)">1 model · 0 MCP servers · 0 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)">  ⠉⠒⠣⠤⠵⠤⠬⠮⠆</text><text class="terminal-r1" x="170.8" y="654.4" textLength="61" clip-path="url(#terminal-line-26)">Type </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)"> for more 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 |
|
|
@ -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)">  ⡠⣒⠄  ⡔⢄⠔⡄</text><text class="terminal-r2" x="170.8" y="459.2" textLength="146.4" clip-path="url(#terminal-line-18)">Mistral Vibe</text><text class="terminal-r1" x="317.2" y="459.2" textLength="122" clip-path="url(#terminal-line-18)"> v0.0.0 · </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)"> · [Subscription] 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)">  ⡠⣒⠄  ⡔⢄⠔⡄</text><text class="terminal-r2" x="170.8" y="459.2" textLength="146.4" clip-path="url(#terminal-line-18)">Mistral Vibe</text><text class="terminal-r1" x="317.2" y="459.2" textLength="122" clip-path="url(#terminal-line-18)"> v0.0.0 · </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)"> · [Subscription] 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)"> ⢸⠸⣀⡔⢉⠱⣃⡢⣂⡣</text><text class="terminal-r1" x="170.8" y="483.6" textLength="414.8" clip-path="url(#terminal-line-19)">1 model · 0 MCP servers · 0 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)">  ⠉⠒⠣⠤⠵⠤⠬⠮⠆</text><text class="terminal-r1" x="170.8" y="508" textLength="61" clip-path="url(#terminal-line-20)">Type </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)"> for more 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 |
|
|
@ -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)">  ⡠⣒⠄  ⡔⢄⠔⡄</text><text class="terminal-r2" x="170.8" y="508" textLength="146.4" clip-path="url(#terminal-line-20)">Mistral Vibe</text><text class="terminal-r1" x="317.2" y="508" textLength="122" clip-path="url(#terminal-line-20)"> v0.0.0 · </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)"> · [Subscription] 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)">  ⡠⣒⠄  ⡔⢄⠔⡄</text><text class="terminal-r2" x="170.8" y="508" textLength="146.4" clip-path="url(#terminal-line-20)">Mistral Vibe</text><text class="terminal-r1" x="317.2" y="508" textLength="122" clip-path="url(#terminal-line-20)"> v0.0.0 · </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)"> · [Subscription] 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)"> ⢸⠸⣀⡔⢉⠱⣃⡢⣂⡣</text><text class="terminal-r1" x="170.8" y="532.4" textLength="414.8" clip-path="url(#terminal-line-21)">1 model · 0 MCP servers · 0 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)">  ⠉⠒⠣⠤⠵⠤⠬⠮⠆</text><text class="terminal-r1" x="170.8" y="556.8" textLength="61" clip-path="url(#terminal-line-22)">Type </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)"> for more 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 |
|
|
@ -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)">  ⡠⣒⠄  ⡔⢄⠔⡄</text><text class="terminal-4926488215-r2" x="170.8" y="434.8" textLength="146.4" clip-path="url(#terminal-4926488215-line-17)">Mistral Vibe</text><text class="terminal-4926488215-r1" x="317.2" y="434.8" textLength="122" clip-path="url(#terminal-4926488215-line-17)"> v0.0.0 · </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)"> · [Subscription] 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)"> ⢸⠸⣀⡔⢉⠱⣃⡢⣂⡣</text><text class="terminal-4926488215-r1" x="170.8" y="459.2" textLength="414.8" clip-path="url(#terminal-4926488215-line-18)">1 model · 2 MCP servers · 0 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)">  ⠉⠒⠣⠤⠵⠤⠬⠮⠆</text><text class="terminal-4926488215-r1" x="170.8" y="483.6" textLength="61" clip-path="url(#terminal-4926488215-line-19)">Type </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)"> for more 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 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 servers 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 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 MCP 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)">  filesystem</text><text class="terminal-4926488215-r8" x="183" y="752" textLength="109.8" clip-path="url(#terminal-4926488215-line-30)">  [stdio]</text><text class="terminal-4926488215-r8" x="292.8" y="752" textLength="97.6" clip-path="url(#terminal-4926488215-line-30)">  1 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)">  search    </text><text class="terminal-4926488215-r9" x="183" y="776.4" textLength="109.8" clip-path="url(#terminal-4926488215-line-31)">  [http] </text><text class="terminal-4926488215-r9" x="292.8" y="776.4" textLength="97.6" clip-path="url(#terminal-4926488215-line-31)">  1 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)">↑↓ Navigate  Enter Show tools  R Refresh  Esc 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% of 200k 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)">  ⡠⣒⠄  ⡔⢄⠔⡄</text><text class="terminal-r2" x="170.8" y="434.8" textLength="146.4" clip-path="url(#terminal-line-17)">Mistral Vibe</text><text class="terminal-r1" x="317.2" y="434.8" textLength="122" clip-path="url(#terminal-line-17)"> v0.0.0 · </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)"> · [Subscription] 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)"> ⢸⠸⣀⡔⢉⠱⣃⡢⣂⡣</text><text class="terminal-r1" x="170.8" y="459.2" textLength="414.8" clip-path="url(#terminal-line-18)">1 model · 2 MCP servers · 0 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)">  ⠉⠒⠣⠤⠵⠤⠬⠮⠆</text><text class="terminal-r1" x="170.8" y="483.6" textLength="61" clip-path="url(#terminal-line-19)">Type </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)"> for more 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 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 servers 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 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 MCP 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)">  filesystem</text><text class="terminal-r8" x="183" y="752" textLength="109.8" clip-path="url(#terminal-line-30)">  [stdio]</text><text class="terminal-r8" x="292.8" y="752" textLength="97.6" clip-path="url(#terminal-line-30)">  1 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)">  search    </text><text class="terminal-r9" x="183" y="776.4" textLength="109.8" clip-path="url(#terminal-line-31)">  [http] </text><text class="terminal-r9" x="292.8" y="776.4" textLength="97.6" clip-path="url(#terminal-line-31)">  1 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)">↑↓ Navigate  Enter Show tools  D Disable  E Enable  R Refresh  Esc 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% of 200k tokens</text>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 16 KiB |
|
|
@ -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)">  ⡠⣒⠄  ⡔⢄⠔⡄</text><text class="terminal-2811199383-r2" x="170.8" y="410.4" textLength="146.4" clip-path="url(#terminal-2811199383-line-16)">Mistral Vibe</text><text class="terminal-2811199383-r1" x="317.2" y="410.4" textLength="122" clip-path="url(#terminal-2811199383-line-16)"> v0.0.0 · </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)"> · [Subscription] 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)"> ⢸⠸⣀⡔⢉⠱⣃⡢⣂⡣</text><text class="terminal-2811199383-r1" x="170.8" y="434.8" textLength="414.8" clip-path="url(#terminal-2811199383-line-17)">1 model · 2 MCP servers · 0 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)">  ⠉⠒⠣⠤⠵⠤⠬⠮⠆</text><text class="terminal-2811199383-r1" x="170.8" y="459.2" textLength="61" clip-path="url(#terminal-2811199383-line-18)">Type </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)"> for more 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 servers 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 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 MCP 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)">  filesystem   </text><text class="terminal-2811199383-r8" x="219.6" y="727.6" textLength="109.8" clip-path="url(#terminal-2811199383-line-29)">  [stdio]</text><text class="terminal-2811199383-r8" x="329.4" y="727.6" textLength="97.6" clip-path="url(#terminal-2811199383-line-29)">  1 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)">  broken-server</text><text class="terminal-2811199383-r9" x="219.6" y="752" textLength="109.8" clip-path="url(#terminal-2811199383-line-30)">  [stdio]</text><text class="terminal-2811199383-r9" x="329.4" y="752" textLength="122" clip-path="url(#terminal-2811199383-line-30)">  no 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)">  search       </text><text class="terminal-2811199383-r9" x="219.6" y="776.4" textLength="109.8" clip-path="url(#terminal-2811199383-line-31)">  [http] </text><text class="terminal-2811199383-r9" x="329.4" y="776.4" textLength="97.6" clip-path="url(#terminal-2811199383-line-31)">  1 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)">↑↓ Navigate  Enter Show tools  R Refresh  Esc 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% of 200k 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)">  ⡠⣒⠄  ⡔⢄⠔⡄</text><text class="terminal-r2" x="170.8" y="410.4" textLength="146.4" clip-path="url(#terminal-line-16)">Mistral Vibe</text><text class="terminal-r1" x="317.2" y="410.4" textLength="122" clip-path="url(#terminal-line-16)"> v0.0.0 · </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)"> · [Subscription] 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)"> ⢸⠸⣀⡔⢉⠱⣃⡢⣂⡣</text><text class="terminal-r1" x="170.8" y="434.8" textLength="414.8" clip-path="url(#terminal-line-17)">1 model · 2 MCP servers · 0 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)">  ⠉⠒⠣⠤⠵⠤⠬⠮⠆</text><text class="terminal-r1" x="170.8" y="459.2" textLength="61" clip-path="url(#terminal-line-18)">Type </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)"> for more 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 servers 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 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 MCP 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)">  filesystem   </text><text class="terminal-r8" x="219.6" y="727.6" textLength="109.8" clip-path="url(#terminal-line-29)">  [stdio]</text><text class="terminal-r8" x="329.4" y="727.6" textLength="97.6" clip-path="url(#terminal-line-29)">  1 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)">  broken-server</text><text class="terminal-r9" x="219.6" y="752" textLength="109.8" clip-path="url(#terminal-line-30)">  [stdio]</text><text class="terminal-r9" x="329.4" y="752" textLength="122" clip-path="url(#terminal-line-30)">  no 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)">  search       </text><text class="terminal-r9" x="219.6" y="776.4" textLength="109.8" clip-path="url(#terminal-line-31)">  [http] </text><text class="terminal-r9" x="329.4" y="776.4" textLength="97.6" clip-path="url(#terminal-line-31)">  1 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)">↑↓ Navigate  Enter Show tools  D Disable  E Enable  R Refresh  Esc 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% of 200k tokens</text>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 17 KiB |
|
|
@ -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)">  ⡠⣒⠄  ⡔⢄⠔⡄</text><text class="terminal-6499786123-r2" x="170.8" y="361.6" textLength="146.4" clip-path="url(#terminal-6499786123-line-14)">Mistral Vibe</text><text class="terminal-6499786123-r1" x="317.2" y="361.6" textLength="122" clip-path="url(#terminal-6499786123-line-14)"> v0.0.0 · </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)"> · [Subscription] 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)"> ⢸⠸⣀⡔⢉⠱⣃⡢⣂⡣</text><text class="terminal-6499786123-r1" x="170.8" y="386" textLength="585.6" clip-path="url(#terminal-6499786123-line-15)">1 model · 2 connectors · 1 MCP server · 0 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)">  ⠉⠒⠣⠤⠵⠤⠬⠮⠆</text><text class="terminal-6499786123-r1" x="170.8" y="410.4" textLength="61" clip-path="url(#terminal-6499786123-line-16)">Type </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)"> for more 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 servers 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 Servers & 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 MCP 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)">  filesystem</text><text class="terminal-6499786123-r8" x="183" y="678.8" textLength="109.8" clip-path="url(#terminal-6499786123-line-27)">  [stdio]</text><text class="terminal-6499786123-r8" x="292.8" y="678.8" textLength="97.6" clip-path="url(#terminal-6499786123-line-27)">  1 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 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)">  gmail</text><text class="terminal-6499786123-r9" x="122" y="752" textLength="158.6" clip-path="url(#terminal-6499786123-line-30)">  [connector]</text><text class="terminal-6499786123-r9" x="280.6" y="752" textLength="109.8" clip-path="url(#terminal-6499786123-line-30)">  3 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)"> 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)">  slack</text><text class="terminal-6499786123-r9" x="122" y="776.4" textLength="158.6" clip-path="url(#terminal-6499786123-line-31)">  [connector]</text><text class="terminal-6499786123-r9" x="280.6" y="776.4" textLength="109.8" clip-path="url(#terminal-6499786123-line-31)">  2 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)"> 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)">↑↓ Navigate  Enter Show tools  R Refresh  Esc 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% of 200k 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)">  ⡠⣒⠄  ⡔⢄⠔⡄</text><text class="terminal-r2" x="170.8" y="361.6" textLength="146.4" clip-path="url(#terminal-line-14)">Mistral Vibe</text><text class="terminal-r1" x="317.2" y="361.6" textLength="122" clip-path="url(#terminal-line-14)"> v0.0.0 · </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)"> · [Subscription] 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)"> ⢸⠸⣀⡔⢉⠱⣃⡢⣂⡣</text><text class="terminal-r1" x="170.8" y="386" textLength="585.6" clip-path="url(#terminal-line-15)">1 model · 2 connectors · 1 MCP server · 0 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)">  ⠉⠒⠣⠤⠵⠤⠬⠮⠆</text><text class="terminal-r1" x="170.8" y="410.4" textLength="61" clip-path="url(#terminal-line-16)">Type </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)"> for more 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 servers 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 Servers & 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 MCP 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)">  filesystem</text><text class="terminal-r8" x="183" y="678.8" textLength="109.8" clip-path="url(#terminal-line-27)">  [stdio]</text><text class="terminal-r8" x="292.8" y="678.8" textLength="97.6" clip-path="url(#terminal-line-27)">  1 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 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)">  gmail</text><text class="terminal-r9" x="122" y="752" textLength="158.6" clip-path="url(#terminal-line-30)">  [connector]</text><text class="terminal-r9" x="280.6" y="752" textLength="109.8" clip-path="url(#terminal-line-30)">  3 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)"> 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)">  slack</text><text class="terminal-r9" x="122" y="776.4" textLength="158.6" clip-path="url(#terminal-line-31)">  [connector]</text><text class="terminal-r9" x="280.6" y="776.4" textLength="109.8" clip-path="url(#terminal-line-31)">  2 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)"> 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)">↑↓ Navigate  Enter Show tools  D Disable  E Enable  R Refresh  Esc 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% of 200k tokens</text>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 18 KiB |
|
|
@ -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)">  ⡠⣒⠄  ⡔⢄⠔⡄</text><text class="terminal-4242019355-r2" x="170.8" y="434.8" textLength="146.4" clip-path="url(#terminal-4242019355-line-17)">Mistral Vibe</text><text class="terminal-4242019355-r1" x="317.2" y="434.8" textLength="122" clip-path="url(#terminal-4242019355-line-17)"> v0.0.0 · </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)"> · [Subscription] 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)"> ⢸⠸⣀⡔⢉⠱⣃⡢⣂⡣</text><text class="terminal-4242019355-r1" x="170.8" y="459.2" textLength="597.8" clip-path="url(#terminal-4242019355-line-18)">1 model · 2 connectors · 0 MCP servers · 0 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)">  ⠉⠒⠣⠤⠵⠤⠬⠮⠆</text><text class="terminal-4242019355-r1" x="170.8" y="483.6" textLength="61" clip-path="url(#terminal-4242019355-line-19)">Type </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)"> for more 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 servers 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 Servers & 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 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)">  gmail</text><text class="terminal-4242019355-r8" x="122" y="752" textLength="158.6" clip-path="url(#terminal-4242019355-line-30)">  [connector]</text><text class="terminal-4242019355-r8" x="280.6" y="752" textLength="109.8" clip-path="url(#terminal-4242019355-line-30)">  3 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)"> 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)">  slack</text><text class="terminal-4242019355-r10" x="122" y="776.4" textLength="158.6" clip-path="url(#terminal-4242019355-line-31)">  [connector]</text><text class="terminal-4242019355-r10" x="280.6" y="776.4" textLength="109.8" clip-path="url(#terminal-4242019355-line-31)">  2 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)"> 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)">↑↓ Navigate  Enter Show tools  R Refresh  Esc 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% of 200k 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)">  ⡠⣒⠄  ⡔⢄⠔⡄</text><text class="terminal-r2" x="170.8" y="434.8" textLength="146.4" clip-path="url(#terminal-line-17)">Mistral Vibe</text><text class="terminal-r1" x="317.2" y="434.8" textLength="122" clip-path="url(#terminal-line-17)"> v0.0.0 · </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)"> · [Subscription] 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)"> ⢸⠸⣀⡔⢉⠱⣃⡢⣂⡣</text><text class="terminal-r1" x="170.8" y="459.2" textLength="597.8" clip-path="url(#terminal-line-18)">1 model · 2 connectors · 0 MCP servers · 0 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)">  ⠉⠒⠣⠤⠵⠤⠬⠮⠆</text><text class="terminal-r1" x="170.8" y="483.6" textLength="61" clip-path="url(#terminal-line-19)">Type </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)"> for more 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 servers 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 Servers & 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 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)">  gmail</text><text class="terminal-r8" x="122" y="752" textLength="158.6" clip-path="url(#terminal-line-30)">  [connector]</text><text class="terminal-r8" x="280.6" y="752" textLength="109.8" clip-path="url(#terminal-line-30)">  3 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)"> 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)">  slack</text><text class="terminal-r10" x="122" y="776.4" textLength="158.6" clip-path="url(#terminal-line-31)">  [connector]</text><text class="terminal-r10" x="280.6" y="776.4" textLength="109.8" clip-path="url(#terminal-line-31)">  2 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)"> 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)">↑↓ Navigate  Enter Show tools  D Disable  E Enable  R Refresh  Esc 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% of 200k tokens</text>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 17 KiB |
|
|
@ -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)">  ⡠⣒⠄  ⡔⢄⠔⡄</text><text class="terminal-r2" x="170.8" y="410.4" textLength="146.4" clip-path="url(#terminal-line-16)">Mistral Vibe</text><text class="terminal-r1" x="317.2" y="410.4" textLength="122" clip-path="url(#terminal-line-16)"> v0.0.0 · </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)"> · [Subscription] 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)">  ⡠⣒⠄  ⡔⢄⠔⡄</text><text class="terminal-r2" x="170.8" y="410.4" textLength="146.4" clip-path="url(#terminal-line-16)">Mistral Vibe</text><text class="terminal-r1" x="317.2" y="410.4" textLength="122" clip-path="url(#terminal-line-16)"> v0.0.0 · </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)"> · [Subscription] 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)"> ⢸⠸⣀⡔⢉⠱⣃⡢⣂⡣</text><text class="terminal-r1" x="170.8" y="434.8" textLength="597.8" clip-path="url(#terminal-line-17)">1 model · 3 connectors · 0 MCP servers · 0 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)">  ⠉⠒⠣⠤⠵⠤⠬⠮⠆</text><text class="terminal-r1" x="170.8" y="459.2" textLength="61" clip-path="url(#terminal-line-18)">Type </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)"> for more 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)">  beta </text><text class="terminal-r10" x="122" y="752" textLength="158.6" clip-path="url(#terminal-line-30)">  [connector]</text><text class="terminal-r10" x="280.6" y="752" textLength="122" clip-path="url(#terminal-line-30)">  no 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)"> not 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)">  zeta </text><text class="terminal-r10" x="122" y="776.4" textLength="158.6" clip-path="url(#terminal-line-31)">  [connector]</text><text class="terminal-r10" x="280.6" y="776.4" textLength="122" clip-path="url(#terminal-line-31)">  no 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)"> not 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)">↑↓ Navigate  Enter Show tools  R Refresh  Esc 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)">↑↓ Navigate  Enter Show tools  D Disable  E Enable  R Refresh  Esc 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% of 200k tokens</text>
|
||||
</g>
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 18 KiB |
|
|
@ -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)">  ⡠⣒⠄  ⡔⢄⠔⡄</text><text class="terminal-1928557542-r2" x="170.8" y="459.2" textLength="146.4" clip-path="url(#terminal-1928557542-line-18)">Mistral Vibe</text><text class="terminal-1928557542-r1" x="317.2" y="459.2" textLength="122" clip-path="url(#terminal-1928557542-line-18)"> v0.0.0 · </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)"> · [Subscription] 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)"> ⢸⠸⣀⡔⢉⠱⣃⡢⣂⡣</text><text class="terminal-1928557542-r1" x="170.8" y="483.6" textLength="585.6" clip-path="url(#terminal-1928557542-line-19)">1 model · 2 connectors · 1 MCP server · 0 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)">  ⠉⠒⠣⠤⠵⠤⠬⠮⠆</text><text class="terminal-1928557542-r1" x="170.8" y="508" textLength="61" clip-path="url(#terminal-1928557542-line-20)">Type </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)"> for more 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 servers 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: 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)">  -  Search Slack 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)">  -  Send a Slack 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)">↑↓ Navigate  Backspace Back  R Refresh  Esc 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% of 200k 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)">  ⡠⣒⠄  ⡔⢄⠔⡄</text><text class="terminal-r2" x="170.8" y="459.2" textLength="146.4" clip-path="url(#terminal-line-18)">Mistral Vibe</text><text class="terminal-r1" x="317.2" y="459.2" textLength="122" clip-path="url(#terminal-line-18)"> v0.0.0 · </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)"> · [Subscription] 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)"> ⢸⠸⣀⡔⢉⠱⣃⡢⣂⡣</text><text class="terminal-r1" x="170.8" y="483.6" textLength="585.6" clip-path="url(#terminal-line-19)">1 model · 2 connectors · 1 MCP server · 0 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)">  ⠉⠒⠣⠤⠵⠤⠬⠮⠆</text><text class="terminal-r1" x="170.8" y="508" textLength="61" clip-path="url(#terminal-line-20)">Type </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)"> for more 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 servers 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: 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)">  -  Search Slack 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)">  -  Send a Slack 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)">↑↓ Navigate  D Disable  E Enable  Backspace Back  R Refresh  Esc 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% of 200k tokens</text>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 15 KiB |
|
|
@ -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)">  ⡠⣒⠄  ⡔⢄⠔⡄</text><text class="terminal-4237726511-r2" x="170.8" y="483.6" textLength="146.4" clip-path="url(#terminal-4237726511-line-19)">Mistral Vibe</text><text class="terminal-4237726511-r1" x="317.2" y="483.6" textLength="122" clip-path="url(#terminal-4237726511-line-19)"> v0.0.0 · </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)"> · [Subscription] 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)"> ⢸⠸⣀⡔⢉⠱⣃⡢⣂⡣</text><text class="terminal-4237726511-r1" x="170.8" y="508" textLength="414.8" clip-path="url(#terminal-4237726511-line-20)">1 model · 2 MCP servers · 0 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)">  ⠉⠒⠣⠤⠵⠤⠬⠮⠆</text><text class="terminal-4237726511-r1" x="170.8" y="532.4" textLength="61" clip-path="url(#terminal-4237726511-line-21)">Type </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)"> for more 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 servers 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 Server: 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)">  -  A fake tool for 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)">↑↓ Navigate  Backspace Back  R Refresh  Esc 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% of 200k 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)">  ⡠⣒⠄  ⡔⢄⠔⡄</text><text class="terminal-r2" x="170.8" y="483.6" textLength="146.4" clip-path="url(#terminal-line-19)">Mistral Vibe</text><text class="terminal-r1" x="317.2" y="483.6" textLength="122" clip-path="url(#terminal-line-19)"> v0.0.0 · </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)"> · [Subscription] 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)"> ⢸⠸⣀⡔⢉⠱⣃⡢⣂⡣</text><text class="terminal-r1" x="170.8" y="508" textLength="414.8" clip-path="url(#terminal-line-20)">1 model · 2 MCP servers · 0 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)">  ⠉⠒⠣⠤⠵⠤⠬⠮⠆</text><text class="terminal-r1" x="170.8" y="532.4" textLength="61" clip-path="url(#terminal-line-21)">Type </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)"> for more 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 servers 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 Server: 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)">  -  A fake tool for 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)">↑↓ Navigate  D Disable  E Enable  Backspace Back  R Refresh  Esc 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% of 200k tokens</text>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 15 KiB |
|
|
@ -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)">  ⡠⣒⠄  ⡔⢄⠔⡄</text><text class="terminal-7514237046-r2" x="170.8" y="508" textLength="146.4" clip-path="url(#terminal-7514237046-line-20)">Mistral Vibe</text><text class="terminal-7514237046-r1" x="317.2" y="508" textLength="122" clip-path="url(#terminal-7514237046-line-20)"> v0.0.0 · </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)"> · [Subscription] 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)"> ⢸⠸⣀⡔⢉⠱⣃⡢⣂⡣</text><text class="terminal-7514237046-r1" x="170.8" y="532.4" textLength="414.8" clip-path="url(#terminal-7514237046-line-21)">1 model · 2 MCP servers · 0 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)">  ⠉⠒⠣⠤⠵⠤⠬⠮⠆</text><text class="terminal-7514237046-r1" x="170.8" y="556.8" textLength="61" clip-path="url(#terminal-7514237046-line-22)">Type </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)"> for more 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 servers 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 servers 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)">┌──────────────────────────────────────────────────────────────────────────────────────────────────────────── default ─┐</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)">></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% of 200k 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)">  ⡠⣒⠄  ⡔⢄⠔⡄</text><text class="terminal-r2" x="170.8" y="508" textLength="146.4" clip-path="url(#terminal-line-20)">Mistral Vibe</text><text class="terminal-r1" x="317.2" y="508" textLength="122" clip-path="url(#terminal-line-20)"> v0.0.0 · </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)"> · [Subscription] 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)"> ⢸⠸⣀⡔⢉⠱⣃⡢⣂⡣</text><text class="terminal-r1" x="170.8" y="532.4" textLength="414.8" clip-path="url(#terminal-line-21)">1 model · 2 MCP servers · 0 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)">  ⠉⠒⠣⠤⠵⠤⠬⠮⠆</text><text class="terminal-r1" x="170.8" y="556.8" textLength="61" clip-path="url(#terminal-line-22)">Type </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)"> for more 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 servers 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 servers 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)">┌──────────────────────────────────────────────────────────────────────────────────────────────────────────── default ─┐</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)">></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% of 200k tokens</text>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 14 KiB |
|
|
@ -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)">  ⡠⣒⠄  ⡔⢄⠔⡄</text><text class="terminal-9108451134-r2" x="170.8" y="532.4" textLength="146.4" clip-path="url(#terminal-9108451134-line-21)">Mistral Vibe</text><text class="terminal-9108451134-r1" x="317.2" y="532.4" textLength="122" clip-path="url(#terminal-9108451134-line-21)"> v0.0.0 · </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)"> · [Subscription] 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)">  ⡠⣒⠄  ⡔⢄⠔⡄</text><text class="terminal-9108451134-r2" x="170.8" y="532.4" textLength="146.4" clip-path="url(#terminal-9108451134-line-21)">Mistral Vibe</text><text class="terminal-9108451134-r1" x="317.2" y="532.4" textLength="122" clip-path="url(#terminal-9108451134-line-21)"> v0.0.0 · </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)"> · [Subscription] 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)"> ⢸⠸⣀⡔⢉⠱⣃⡢⣂⡣</text><text class="terminal-9108451134-r1" x="170.8" y="556.8" textLength="414.8" clip-path="url(#terminal-9108451134-line-22)">1 model · 0 MCP servers · 0 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)">  ⠉⠒⠣⠤⠵⠤⠬⠮⠆</text><text class="terminal-9108451134-r1" x="170.8" y="581.2" textLength="61" clip-path="url(#terminal-9108451134-line-23)">Type </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)"> for more 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 |
|
|
@ -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)">  ⡠⣒⠄  ⡔⢄⠔⡄</text><text class="terminal-606925797-r2" x="170.8" y="434.8" textLength="146.4" clip-path="url(#terminal-606925797-line-17)">Mistral Vibe</text><text class="terminal-606925797-r1" x="317.2" y="434.8" textLength="122" clip-path="url(#terminal-606925797-line-17)"> v0.0.0 · </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)"> · [Subscription] 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)"> ⢸⠸⣀⡔⢉⠱⣃⡢⣂⡣</text><text class="terminal-606925797-r1" x="170.8" y="459.2" textLength="414.8" clip-path="url(#terminal-606925797-line-18)">1 model · 2 MCP servers · 0 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)">  ⠉⠒⠣⠤⠵⠤⠬⠮⠆</text><text class="terminal-606925797-r1" x="170.8" y="483.6" textLength="61" clip-path="url(#terminal-606925797-line-19)">Type </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)"> for more 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 servers 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 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 MCP 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)">  filesystem</text><text class="terminal-606925797-r8" x="183" y="752" textLength="109.8" clip-path="url(#terminal-606925797-line-30)">  [stdio]</text><text class="terminal-606925797-r8" x="292.8" y="752" textLength="97.6" clip-path="url(#terminal-606925797-line-30)">  1 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)">  search    </text><text class="terminal-606925797-r9" x="183" y="776.4" textLength="109.8" clip-path="url(#terminal-606925797-line-31)">  [http] </text><text class="terminal-606925797-r9" x="292.8" y="776.4" textLength="97.6" clip-path="url(#terminal-606925797-line-31)">  1 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)">↑↓ Navigate  Enter Show tools  R Refresh  Esc 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% of 200k 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)">  ⡠⣒⠄  ⡔⢄⠔⡄</text><text class="terminal-r2" x="170.8" y="434.8" textLength="146.4" clip-path="url(#terminal-line-17)">Mistral Vibe</text><text class="terminal-r1" x="317.2" y="434.8" textLength="122" clip-path="url(#terminal-line-17)"> v0.0.0 · </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)"> · [Subscription] 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)"> ⢸⠸⣀⡔⢉⠱⣃⡢⣂⡣</text><text class="terminal-r1" x="170.8" y="459.2" textLength="414.8" clip-path="url(#terminal-line-18)">1 model · 2 MCP servers · 0 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)">  ⠉⠒⠣⠤⠵⠤⠬⠮⠆</text><text class="terminal-r1" x="170.8" y="483.6" textLength="61" clip-path="url(#terminal-line-19)">Type </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)"> for more 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 servers 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 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 MCP 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)">  filesystem</text><text class="terminal-r8" x="183" y="752" textLength="109.8" clip-path="url(#terminal-line-30)">  [stdio]</text><text class="terminal-r8" x="292.8" y="752" textLength="97.6" clip-path="url(#terminal-line-30)">  1 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)">  search    </text><text class="terminal-r9" x="183" y="776.4" textLength="109.8" clip-path="url(#terminal-line-31)">  [http] </text><text class="terminal-r9" x="292.8" y="776.4" textLength="97.6" clip-path="url(#terminal-line-31)">  1 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)">↑↓ Navigate  Enter Show tools  D Disable  E Enable  R Refresh  Esc 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% of 200k tokens</text>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 16 KiB |
|
|
@ -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)">  ⡠⣒⠄  ⡔⢄⠔⡄</text><text class="terminal-9601757275-r2" x="170.8" y="434.8" textLength="146.4" clip-path="url(#terminal-9601757275-line-17)">Mistral Vibe</text><text class="terminal-9601757275-r1" x="317.2" y="434.8" textLength="122" clip-path="url(#terminal-9601757275-line-17)"> v0.0.0 · </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)"> · [Subscription] 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)"> ⢸⠸⣀⡔⢉⠱⣃⡢⣂⡣</text><text class="terminal-9601757275-r1" x="170.8" y="459.2" textLength="414.8" clip-path="url(#terminal-9601757275-line-18)">1 model · 2 MCP servers · 0 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)">  ⠉⠒⠣⠤⠵⠤⠬⠮⠆</text><text class="terminal-9601757275-r1" x="170.8" y="483.6" textLength="61" clip-path="url(#terminal-9601757275-line-19)">Type </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)"> for more 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 servers 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 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 MCP 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)">  filesystem</text><text class="terminal-9601757275-r8" x="183" y="752" textLength="109.8" clip-path="url(#terminal-9601757275-line-30)">  [stdio]</text><text class="terminal-9601757275-r8" x="292.8" y="752" textLength="97.6" clip-path="url(#terminal-9601757275-line-30)">  1 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)">  search    </text><text class="terminal-9601757275-r9" x="183" y="776.4" textLength="109.8" clip-path="url(#terminal-9601757275-line-31)">  [http] </text><text class="terminal-9601757275-r9" x="292.8" y="776.4" textLength="97.6" clip-path="url(#terminal-9601757275-line-31)">  1 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)">↑↓ Navigate  Enter Show tools  R Refresh  Esc 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% of 200k 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)">  ⡠⣒⠄  ⡔⢄⠔⡄</text><text class="terminal-r2" x="170.8" y="434.8" textLength="146.4" clip-path="url(#terminal-line-17)">Mistral Vibe</text><text class="terminal-r1" x="317.2" y="434.8" textLength="122" clip-path="url(#terminal-line-17)"> v0.0.0 · </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)"> · [Subscription] 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)"> ⢸⠸⣀⡔⢉⠱⣃⡢⣂⡣</text><text class="terminal-r1" x="170.8" y="459.2" textLength="414.8" clip-path="url(#terminal-line-18)">1 model · 2 MCP servers · 0 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)">  ⠉⠒⠣⠤⠵⠤⠬⠮⠆</text><text class="terminal-r1" x="170.8" y="483.6" textLength="61" clip-path="url(#terminal-line-19)">Type </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)"> for more 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 servers 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 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 MCP 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)">  filesystem</text><text class="terminal-r8" x="183" y="752" textLength="109.8" clip-path="url(#terminal-line-30)">  [stdio]</text><text class="terminal-r8" x="292.8" y="752" textLength="97.6" clip-path="url(#terminal-line-30)">  1 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)">  search    </text><text class="terminal-r9" x="183" y="776.4" textLength="109.8" clip-path="url(#terminal-line-31)">  [http] </text><text class="terminal-r9" x="292.8" y="776.4" textLength="97.6" clip-path="url(#terminal-line-31)">  1 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)">↑↓ Navigate  Enter Show tools  D Disable  E Enable  R Refresh  Esc 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% of 200k tokens</text>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 16 KiB |
|
|
@ -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)">  ⡠⣒⠄  ⡔⢄⠔⡄</text><text class="terminal-3878668141-r2" x="170.8" y="434.8" textLength="146.4" clip-path="url(#terminal-3878668141-line-17)">Mistral Vibe</text><text class="terminal-3878668141-r1" x="317.2" y="434.8" textLength="122" clip-path="url(#terminal-3878668141-line-17)"> v0.0.0 · </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)"> · [Subscription] 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)"> ⢸⠸⣀⡔⢉⠱⣃⡢⣂⡣</text><text class="terminal-3878668141-r1" x="170.8" y="459.2" textLength="414.8" clip-path="url(#terminal-3878668141-line-18)">1 model · 2 MCP servers · 0 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)">  ⠉⠒⠣⠤⠵⠤⠬⠮⠆</text><text class="terminal-3878668141-r1" x="170.8" y="483.6" textLength="61" clip-path="url(#terminal-3878668141-line-19)">Type </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)"> for more 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 servers 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 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 MCP 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)">  filesystem</text><text class="terminal-3878668141-r8" x="183" y="752" textLength="109.8" clip-path="url(#terminal-3878668141-line-30)">  [stdio]</text><text class="terminal-3878668141-r8" x="292.8" y="752" textLength="97.6" clip-path="url(#terminal-3878668141-line-30)">  1 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)">  search    </text><text class="terminal-3878668141-r9" x="183" y="776.4" textLength="109.8" clip-path="url(#terminal-3878668141-line-31)">  [http] </text><text class="terminal-3878668141-r9" x="292.8" y="776.4" textLength="97.6" clip-path="url(#terminal-3878668141-line-31)">  1 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.  ↑↓ Navigate  Enter Show tools  R Refresh  Esc 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% of 200k 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)">  ⡠⣒⠄  ⡔⢄⠔⡄</text><text class="terminal-r2" x="170.8" y="434.8" textLength="146.4" clip-path="url(#terminal-line-17)">Mistral Vibe</text><text class="terminal-r1" x="317.2" y="434.8" textLength="122" clip-path="url(#terminal-line-17)"> v0.0.0 · </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)"> · [Subscription] 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)"> ⢸⠸⣀⡔⢉⠱⣃⡢⣂⡣</text><text class="terminal-r1" x="170.8" y="459.2" textLength="414.8" clip-path="url(#terminal-line-18)">1 model · 2 MCP servers · 0 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)">  ⠉⠒⠣⠤⠵⠤⠬⠮⠆</text><text class="terminal-r1" x="170.8" y="483.6" textLength="61" clip-path="url(#terminal-line-19)">Type </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)"> for more 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 servers 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 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 MCP 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)">  filesystem</text><text class="terminal-r8" x="183" y="752" textLength="109.8" clip-path="url(#terminal-line-30)">  [stdio]</text><text class="terminal-r8" x="292.8" y="752" textLength="97.6" clip-path="url(#terminal-line-30)">  1 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)">  search    </text><text class="terminal-r9" x="183" y="776.4" textLength="109.8" clip-path="url(#terminal-line-31)">  [http] </text><text class="terminal-r9" x="292.8" y="776.4" textLength="97.6" clip-path="url(#terminal-line-31)">  1 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.  ↑↓ Navigate  Enter Show tools  D Disable  E Enable  R Refresh  Esc 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% of 200k tokens</text>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 16 KiB |
|
|
@ -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)">  ⡠⣒⠄  ⡔⢄⠔⡄</text><text class="terminal-5744808340-r2" x="170.8" y="483.6" textLength="146.4" clip-path="url(#terminal-5744808340-line-19)">Mistral Vibe</text><text class="terminal-5744808340-r1" x="317.2" y="483.6" textLength="122" clip-path="url(#terminal-5744808340-line-19)"> v0.0.0 · </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)"> · [Subscription] 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)"> ⢸⠸⣀⡔⢉⠱⣃⡢⣂⡣</text><text class="terminal-5744808340-r1" x="170.8" y="508" textLength="414.8" clip-path="url(#terminal-5744808340-line-20)">1 model · 2 MCP servers · 0 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)">  ⠉⠒⠣⠤⠵⠤⠬⠮⠆</text><text class="terminal-5744808340-r1" x="170.8" y="532.4" textLength="61" clip-path="url(#terminal-5744808340-line-21)">Type </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)"> for more 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 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 servers 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 Server: 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)">  -  A fake tool for 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)">↑↓ Navigate  Backspace Back  R Refresh  Esc 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% of 200k 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)">  ⡠⣒⠄  ⡔⢄⠔⡄</text><text class="terminal-r2" x="170.8" y="483.6" textLength="146.4" clip-path="url(#terminal-line-19)">Mistral Vibe</text><text class="terminal-r1" x="317.2" y="483.6" textLength="122" clip-path="url(#terminal-line-19)"> v0.0.0 · </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)"> · [Subscription] 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)"> ⢸⠸⣀⡔⢉⠱⣃⡢⣂⡣</text><text class="terminal-r1" x="170.8" y="508" textLength="414.8" clip-path="url(#terminal-line-20)">1 model · 2 MCP servers · 0 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)">  ⠉⠒⠣⠤⠵⠤⠬⠮⠆</text><text class="terminal-r1" x="170.8" y="532.4" textLength="61" clip-path="url(#terminal-line-21)">Type </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)"> for more 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 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 servers 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 Server: 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)">  -  A fake tool for 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)">↑↓ Navigate  D Disable  E Enable  Backspace Back  R Refresh  Esc 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% of 200k tokens</text>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 15 KiB |
|
|
@ -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)">  ⡠⣒⠄  ⡔⢄⠔⡄</text><text class="terminal-4913728344-r2" x="170.8" y="361.6" textLength="146.4" clip-path="url(#terminal-4913728344-line-14)">Mistral Vibe</text><text class="terminal-4913728344-r1" x="317.2" y="361.6" textLength="122" clip-path="url(#terminal-4913728344-line-14)"> v0.0.0 · </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)"> · [Subscription] 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)"> ⢸⠸⣀⡔⢉⠱⣃⡢⣂⡣</text><text class="terminal-4913728344-r1" x="170.8" y="386" textLength="585.6" clip-path="url(#terminal-4913728344-line-15)">1 model · 2 connectors · 1 MCP server · 0 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)">  ⠉⠒⠣⠤⠵⠤⠬⠮⠆</text><text class="terminal-4913728344-r1" x="170.8" y="410.4" textLength="61" clip-path="url(#terminal-4913728344-line-16)">Type </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)"> for more 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 servers 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 Servers & 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 MCP 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)">  filesystem</text><text class="terminal-4913728344-r8" x="183" y="678.8" textLength="109.8" clip-path="url(#terminal-4913728344-line-27)">  [stdio]</text><text class="terminal-4913728344-r8" x="292.8" y="678.8" textLength="97.6" clip-path="url(#terminal-4913728344-line-27)">  1 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 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)">  gmail</text><text class="terminal-4913728344-r9" x="122" y="752" textLength="158.6" clip-path="url(#terminal-4913728344-line-30)">  [connector]</text><text class="terminal-4913728344-r9" x="280.6" y="752" textLength="109.8" clip-path="url(#terminal-4913728344-line-30)">  3 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)"> 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)">  slack</text><text class="terminal-4913728344-r9" x="122" y="776.4" textLength="158.6" clip-path="url(#terminal-4913728344-line-31)">  [connector]</text><text class="terminal-4913728344-r9" x="280.6" y="776.4" textLength="109.8" clip-path="url(#terminal-4913728344-line-31)">  2 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)"> 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)">↑↓ Navigate  Enter Show tools  R Refresh  Esc 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% of 200k 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)">  ⡠⣒⠄  ⡔⢄⠔⡄</text><text class="terminal-r2" x="170.8" y="361.6" textLength="146.4" clip-path="url(#terminal-line-14)">Mistral Vibe</text><text class="terminal-r1" x="317.2" y="361.6" textLength="122" clip-path="url(#terminal-line-14)"> v0.0.0 · </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)"> · [Subscription] 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)"> ⢸⠸⣀⡔⢉⠱⣃⡢⣂⡣</text><text class="terminal-r1" x="170.8" y="386" textLength="585.6" clip-path="url(#terminal-line-15)">1 model · 2 connectors · 1 MCP server · 0 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)">  ⠉⠒⠣⠤⠵⠤⠬⠮⠆</text><text class="terminal-r1" x="170.8" y="410.4" textLength="61" clip-path="url(#terminal-line-16)">Type </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)"> for more 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 servers 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 Servers & 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 MCP 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)">  filesystem</text><text class="terminal-r8" x="183" y="678.8" textLength="109.8" clip-path="url(#terminal-line-27)">  [stdio]</text><text class="terminal-r8" x="292.8" y="678.8" textLength="97.6" clip-path="url(#terminal-line-27)">  1 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 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)">  gmail</text><text class="terminal-r9" x="122" y="752" textLength="158.6" clip-path="url(#terminal-line-30)">  [connector]</text><text class="terminal-r9" x="280.6" y="752" textLength="109.8" clip-path="url(#terminal-line-30)">  3 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)"> 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)">  slack</text><text class="terminal-r9" x="122" y="776.4" textLength="158.6" clip-path="url(#terminal-line-31)">  [connector]</text><text class="terminal-r9" x="280.6" y="776.4" textLength="109.8" clip-path="url(#terminal-line-31)">  2 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)"> 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)">↑↓ Navigate  Enter Show tools  D Disable  E Enable  R Refresh  Esc 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% of 200k tokens</text>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 18 KiB |
|
|
@ -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)">  ⡠⣒⠄  ⡔⢄⠔⡄</text><text class="terminal-r2" x="170.8" y="605.6" textLength="146.4" clip-path="url(#terminal-line-24)">Mistral Vibe</text><text class="terminal-r1" x="317.2" y="605.6" textLength="122" clip-path="url(#terminal-line-24)"> v0.0.0 · </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)"> · [Subscription] 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)">  ⡠⣒⠄  ⡔⢄⠔⡄</text><text class="terminal-r2" x="170.8" y="605.6" textLength="146.4" clip-path="url(#terminal-line-24)">Mistral Vibe</text><text class="terminal-r1" x="317.2" y="605.6" textLength="122" clip-path="url(#terminal-line-24)"> v0.0.0 · </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)"> · [Subscription] 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)"> ⢸⠸⣀⡔⢉⠱⣃⡢⣂⡣</text><text class="terminal-r1" x="170.8" y="630" textLength="427" clip-path="url(#terminal-line-25)">5 models · 0 MCP servers · 0 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)">  ⠉⠒⠣⠤⠵⠤⠬⠮⠆</text><text class="terminal-r1" x="170.8" y="654.4" textLength="61" clip-path="url(#terminal-line-26)">Type </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)"> for more 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 |
|
|
@ -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)">  ⡠⣒⠄  ⡔⢄⠔⡄</text><text class="terminal-r2" x="170.8" y="483.6" textLength="146.4" clip-path="url(#terminal-line-19)">Mistral Vibe</text><text class="terminal-r1" x="317.2" y="483.6" textLength="122" clip-path="url(#terminal-line-19)"> v0.0.0 · </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)"> · [Subscription] 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)">  ⡠⣒⠄  ⡔⢄⠔⡄</text><text class="terminal-r2" x="170.8" y="483.6" textLength="146.4" clip-path="url(#terminal-line-19)">Mistral Vibe</text><text class="terminal-r1" x="317.2" y="483.6" textLength="122" clip-path="url(#terminal-line-19)"> v0.0.0 · </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)"> · [Subscription] 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)"> ⢸⠸⣀⡔⢉⠱⣃⡢⣂⡣</text><text class="terminal-r1" x="170.8" y="508" textLength="427" clip-path="url(#terminal-line-20)">5 models · 0 MCP servers · 0 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)">  ⠉⠒⠣⠤⠵⠤⠬⠮⠆</text><text class="terminal-r1" x="170.8" y="532.4" textLength="61" clip-path="url(#terminal-line-21)">Type </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)"> for more 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 |
|
|
@ -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)">  ⡠⣒⠄  ⡔⢄⠔⡄</text><text class="terminal-r2" x="170.8" y="483.6" textLength="146.4" clip-path="url(#terminal-line-19)">Mistral Vibe</text><text class="terminal-r1" x="317.2" y="483.6" textLength="122" clip-path="url(#terminal-line-19)"> v0.0.0 · </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)"> · [Subscription] 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)">  ⡠⣒⠄  ⡔⢄⠔⡄</text><text class="terminal-r2" x="170.8" y="483.6" textLength="146.4" clip-path="url(#terminal-line-19)">Mistral Vibe</text><text class="terminal-r1" x="317.2" y="483.6" textLength="122" clip-path="url(#terminal-line-19)"> v0.0.0 · </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)"> · [Subscription] 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)"> ⢸⠸⣀⡔⢉⠱⣃⡢⣂⡣</text><text class="terminal-r1" x="170.8" y="508" textLength="427" clip-path="url(#terminal-line-20)">5 models · 0 MCP servers · 0 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)">  ⠉⠒⠣⠤⠵⠤⠬⠮⠆</text><text class="terminal-r1" x="170.8" y="532.4" textLength="61" clip-path="url(#terminal-line-21)">Type </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)"> for more 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 |
|
|
@ -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)">  ⡠⣒⠄  ⡔⢄⠔⡄</text><text class="terminal-r2" x="170.8" y="581.2" textLength="146.4" clip-path="url(#terminal-line-23)">Mistral Vibe</text><text class="terminal-r1" x="317.2" y="581.2" textLength="122" clip-path="url(#terminal-line-23)"> v0.0.0 · </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)"> · [Subscription] 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)">  ⡠⣒⠄  ⡔⢄⠔⡄</text><text class="terminal-r2" x="170.8" y="581.2" textLength="146.4" clip-path="url(#terminal-line-23)">Mistral Vibe</text><text class="terminal-r1" x="317.2" y="581.2" textLength="122" clip-path="url(#terminal-line-23)"> v0.0.0 · </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)"> · [Subscription] 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)"> ⢸⠸⣀⡔⢉⠱⣃⡢⣂⡣</text><text class="terminal-r1" x="170.8" y="605.6" textLength="414.8" clip-path="url(#terminal-line-24)">1 model · 0 MCP servers · 0 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)">  ⠉⠒⠣⠤⠵⠤⠬⠮⠆</text><text class="terminal-r1" x="170.8" y="630" textLength="61" clip-path="url(#terminal-line-25)">Type </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)"> for more 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 |
|
|
@ -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)">  ⡠⣒⠄  ⡔⢄⠔⡄</text><text class="terminal-r2" x="170.8" y="605.6" textLength="146.4" clip-path="url(#terminal-line-24)">Mistral Vibe</text><text class="terminal-r1" x="317.2" y="605.6" textLength="122" clip-path="url(#terminal-line-24)"> v0.0.0 · </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)"> · [Subscription] 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)">  ⡠⣒⠄  ⡔⢄⠔⡄</text><text class="terminal-r2" x="170.8" y="605.6" textLength="146.4" clip-path="url(#terminal-line-24)">Mistral Vibe</text><text class="terminal-r1" x="317.2" y="605.6" textLength="122" clip-path="url(#terminal-line-24)"> v0.0.0 · </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)"> · [Subscription] 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)"> ⢸⠸⣀⡔⢉⠱⣃⡢⣂⡣</text><text class="terminal-r1" x="170.8" y="630" textLength="414.8" clip-path="url(#terminal-line-25)">1 model · 0 MCP servers · 0 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)">  ⠉⠒⠣⠤⠵⠤⠬⠮⠆</text><text class="terminal-r1" x="170.8" y="654.4" textLength="61" clip-path="url(#terminal-line-26)">Type </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)"> for more 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 |
|
|
@ -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)">  ⡠⣒⠄  ⡔⢄⠔⡄</text><text class="terminal-r2" x="170.8" y="605.6" textLength="146.4" clip-path="url(#terminal-line-24)">Mistral Vibe</text><text class="terminal-r1" x="317.2" y="605.6" textLength="122" clip-path="url(#terminal-line-24)"> v0.0.0 · </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)"> · [Subscription] 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)">  ⡠⣒⠄  ⡔⢄⠔⡄</text><text class="terminal-r2" x="170.8" y="605.6" textLength="146.4" clip-path="url(#terminal-line-24)">Mistral Vibe</text><text class="terminal-r1" x="317.2" y="605.6" textLength="122" clip-path="url(#terminal-line-24)"> v0.0.0 · </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)"> · [Subscription] 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)"> ⢸⠸⣀⡔⢉⠱⣃⡢⣂⡣</text><text class="terminal-r1" x="170.8" y="630" textLength="414.8" clip-path="url(#terminal-line-25)">1 model · 0 MCP servers · 0 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)">  ⠉⠒⠣⠤⠵⠤⠬⠮⠆</text><text class="terminal-r1" x="170.8" y="654.4" textLength="61" clip-path="url(#terminal-line-26)">Type </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)"> for more 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 |
|
|
@ -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)">  ⡠⣒⠄  ⡔⢄⠔⡄</text><text class="terminal-r2" x="170.8" y="605.6" textLength="146.4" clip-path="url(#terminal-line-24)">Mistral Vibe</text><text class="terminal-r1" x="317.2" y="605.6" textLength="122" clip-path="url(#terminal-line-24)"> v0.0.0 · </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)"> · [Subscription] 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)">  ⡠⣒⠄  ⡔⢄⠔⡄</text><text class="terminal-r2" x="170.8" y="605.6" textLength="146.4" clip-path="url(#terminal-line-24)">Mistral Vibe</text><text class="terminal-r1" x="317.2" y="605.6" textLength="122" clip-path="url(#terminal-line-24)"> v0.0.0 · </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)"> · [Subscription] 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)"> ⢸⠸⣀⡔⢉⠱⣃⡢⣂⡣</text><text class="terminal-r1" x="170.8" y="630" textLength="414.8" clip-path="url(#terminal-line-25)">1 model · 0 MCP servers · 0 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)">  ⠉⠒⠣⠤⠵⠤⠬⠮⠆</text><text class="terminal-r1" x="170.8" y="654.4" textLength="61" clip-path="url(#terminal-line-26)">Type </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)"> for more 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 |
|
|
@ -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)">  ⡠⣒⠄  ⡔⢄⠔⡄</text><text class="terminal-r2" x="170.8" y="605.6" textLength="146.4" clip-path="url(#terminal-line-24)">Mistral Vibe</text><text class="terminal-r1" x="317.2" y="605.6" textLength="122" clip-path="url(#terminal-line-24)"> v0.0.0 · </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)"> · [Subscription] 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)">  ⡠⣒⠄  ⡔⢄⠔⡄</text><text class="terminal-r2" x="170.8" y="605.6" textLength="146.4" clip-path="url(#terminal-line-24)">Mistral Vibe</text><text class="terminal-r1" x="317.2" y="605.6" textLength="122" clip-path="url(#terminal-line-24)"> v0.0.0 · </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)"> · [Subscription] 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)"> ⢸⠸⣀⡔⢉⠱⣃⡢⣂⡣</text><text class="terminal-r1" x="170.8" y="630" textLength="414.8" clip-path="url(#terminal-line-25)">1 model · 0 MCP servers · 0 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)">  ⠉⠒⠣⠤⠵⠤⠬⠮⠆</text><text class="terminal-r1" x="170.8" y="654.4" textLength="61" clip-path="url(#terminal-line-26)">Type </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)"> for more 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 |
|
|
@ -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)">  ⡠⣒⠄  ⡔⢄⠔⡄</text><text class="terminal-r2" x="170.8" y="605.6" textLength="146.4" clip-path="url(#terminal-line-24)">Mistral Vibe</text><text class="terminal-r1" x="317.2" y="605.6" textLength="122" clip-path="url(#terminal-line-24)"> v0.0.0 · </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)"> · [Subscription] 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)">  ⡠⣒⠄  ⡔⢄⠔⡄</text><text class="terminal-r2" x="170.8" y="605.6" textLength="146.4" clip-path="url(#terminal-line-24)">Mistral Vibe</text><text class="terminal-r1" x="317.2" y="605.6" textLength="122" clip-path="url(#terminal-line-24)"> v0.0.0 · </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)"> · [Subscription] 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)"> ⢸⠸⣀⡔⢉⠱⣃⡢⣂⡣</text><text class="terminal-r1" x="170.8" y="630" textLength="414.8" clip-path="url(#terminal-line-25)">1 model · 0 MCP servers · 0 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)">  ⠉⠒⠣⠤⠵⠤⠬⠮⠆</text><text class="terminal-r1" x="170.8" y="654.4" textLength="61" clip-path="url(#terminal-line-26)">Type </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)"> for more 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 |
|
|
@ -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)">  ⡠⣒⠄  ⡔⢄⠔⡄</text><text class="terminal-r2" x="170.8" y="508" textLength="146.4" clip-path="url(#terminal-line-20)">Mistral Vibe</text><text class="terminal-r1" x="317.2" y="508" textLength="122" clip-path="url(#terminal-line-20)"> v0.0.0 · </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)"> · [Subscription] 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)">  ⡠⣒⠄  ⡔⢄⠔⡄</text><text class="terminal-r2" x="170.8" y="508" textLength="146.4" clip-path="url(#terminal-line-20)">Mistral Vibe</text><text class="terminal-r1" x="317.2" y="508" textLength="122" clip-path="url(#terminal-line-20)"> v0.0.0 · </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)"> · [Subscription] 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)"> ⢸⠸⣀⡔⢉⠱⣃⡢⣂⡣</text><text class="terminal-r1" x="170.8" y="532.4" textLength="414.8" clip-path="url(#terminal-line-21)">1 model · 0 MCP servers · 0 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)">  ⠉⠒⠣⠤⠵⠤⠬⠮⠆</text><text class="terminal-r1" x="170.8" y="556.8" textLength="61" clip-path="url(#terminal-line-22)">Type </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)"> for more 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 |
|
|
@ -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)">  ⡠⣒⠄  ⡔⢄⠔⡄</text><text class="terminal-r2" x="170.8" y="508" textLength="146.4" clip-path="url(#terminal-line-20)">Mistral Vibe</text><text class="terminal-r1" x="317.2" y="508" textLength="122" clip-path="url(#terminal-line-20)"> v0.0.0 · </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)"> · [Subscription] 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)">  ⡠⣒⠄  ⡔⢄⠔⡄</text><text class="terminal-r2" x="170.8" y="508" textLength="146.4" clip-path="url(#terminal-line-20)">Mistral Vibe</text><text class="terminal-r1" x="317.2" y="508" textLength="122" clip-path="url(#terminal-line-20)"> v0.0.0 · </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)"> · [Subscription] 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)"> ⢸⠸⣀⡔⢉⠱⣃⡢⣂⡣</text><text class="terminal-r1" x="170.8" y="532.4" textLength="414.8" clip-path="url(#terminal-line-21)">1 model · 0 MCP servers · 0 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)">  ⠉⠒⠣⠤⠵⠤⠬⠮⠆</text><text class="terminal-r1" x="170.8" y="556.8" textLength="61" clip-path="url(#terminal-line-22)">Type </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)"> for more 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! I can help 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)"> speaking </text><text class="terminal-r6" x="170.8" y="727.6" textLength="134.2" clip-path="url(#terminal-line-29)">esc to 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)"> speaking </text><text class="terminal-r6" x="170.8" y="727.6" textLength="219.6" clip-path="url(#terminal-line-29)">Esc/Ctrl+C to 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)">┌──────────────────────────────────────────────────────────────────────────────────────────────────────────── default ─┐</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)">></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 |
|
|
@ -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)">  ⡠⣒⠄  ⡔⢄⠔⡄</text><text class="terminal-r2" x="170.8" y="508" textLength="146.4" clip-path="url(#terminal-line-20)">Mistral Vibe</text><text class="terminal-r1" x="317.2" y="508" textLength="122" clip-path="url(#terminal-line-20)"> v0.0.0 · </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)"> · [Subscription] 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)">  ⡠⣒⠄  ⡔⢄⠔⡄</text><text class="terminal-r2" x="170.8" y="508" textLength="146.4" clip-path="url(#terminal-line-20)">Mistral Vibe</text><text class="terminal-r1" x="317.2" y="508" textLength="122" clip-path="url(#terminal-line-20)"> v0.0.0 · </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)"> · [Subscription] 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)"> ⢸⠸⣀⡔⢉⠱⣃⡢⣂⡣</text><text class="terminal-r1" x="170.8" y="532.4" textLength="414.8" clip-path="url(#terminal-line-21)">1 model · 0 MCP servers · 0 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)">  ⠉⠒⠣⠤⠵⠤⠬⠮⠆</text><text class="terminal-r1" x="170.8" y="556.8" textLength="61" clip-path="url(#terminal-line-22)">Type </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)"> for more 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! I can help 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)"> summarizing </text><text class="terminal-r6" x="183" y="727.6" textLength="134.2" clip-path="url(#terminal-line-29)">esc to 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)"> summarizing </text><text class="terminal-r6" x="183" y="727.6" textLength="219.6" clip-path="url(#terminal-line-29)">Esc/Ctrl+C to 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)">┌──────────────────────────────────────────────────────────────────────────────────────────────────────────── default ─┐</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)">></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 |