v1.3.3
This commit is contained in:
parent
08d8e85447
commit
4d449be276
14 changed files with 65 additions and 46 deletions
2
.vscode/launch.json
vendored
2
.vscode/launch.json
vendored
|
|
@ -1,5 +1,5 @@
|
||||||
{
|
{
|
||||||
"version": "1.3.2",
|
"version": "1.3.3",
|
||||||
"configurations": [
|
"configurations": [
|
||||||
{
|
{
|
||||||
"name": "ACP Server",
|
"name": "ACP Server",
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file.
|
||||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||||
|
|
||||||
|
## [1.3.3] - 2025-12-26
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- Fix config desyncing issues
|
||||||
|
|
||||||
## [1.3.2] - 2025-12-24
|
## [1.3.2] - 2025-12-24
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
id = "mistral-vibe"
|
id = "mistral-vibe"
|
||||||
name = "Mistral Vibe"
|
name = "Mistral Vibe"
|
||||||
description = "Mistral's open-source coding assistant"
|
description = "Mistral's open-source coding assistant"
|
||||||
version = "1.3.2"
|
version = "1.3.3"
|
||||||
schema_version = 1
|
schema_version = 1
|
||||||
authors = ["Mistral AI"]
|
authors = ["Mistral AI"]
|
||||||
repository = "https://github.com/mistralai/mistral-vibe"
|
repository = "https://github.com/mistralai/mistral-vibe"
|
||||||
|
|
@ -11,25 +11,25 @@ name = "Mistral Vibe"
|
||||||
icon = "./icons/mistral_vibe.svg"
|
icon = "./icons/mistral_vibe.svg"
|
||||||
|
|
||||||
[agent_servers.mistral-vibe.targets.darwin-aarch64]
|
[agent_servers.mistral-vibe.targets.darwin-aarch64]
|
||||||
archive = "https://github.com/mistralai/mistral-vibe/releases/download/v1.3.2/vibe-acp-darwin-aarch64-1.3.2.zip"
|
archive = "https://github.com/mistralai/mistral-vibe/releases/download/v1.3.3/vibe-acp-darwin-aarch64-1.3.3.zip"
|
||||||
cmd = "./vibe-acp"
|
cmd = "./vibe-acp"
|
||||||
|
|
||||||
[agent_servers.mistral-vibe.targets.darwin-x86_64]
|
[agent_servers.mistral-vibe.targets.darwin-x86_64]
|
||||||
archive = "https://github.com/mistralai/mistral-vibe/releases/download/v1.3.2/vibe-acp-darwin-x86_64-1.3.2.zip"
|
archive = "https://github.com/mistralai/mistral-vibe/releases/download/v1.3.3/vibe-acp-darwin-x86_64-1.3.3.zip"
|
||||||
cmd = "./vibe-acp"
|
cmd = "./vibe-acp"
|
||||||
|
|
||||||
[agent_servers.mistral-vibe.targets.linux-aarch64]
|
[agent_servers.mistral-vibe.targets.linux-aarch64]
|
||||||
archive = "https://github.com/mistralai/mistral-vibe/releases/download/v1.3.2/vibe-acp-linux-aarch64-1.3.2.zip"
|
archive = "https://github.com/mistralai/mistral-vibe/releases/download/v1.3.3/vibe-acp-linux-aarch64-1.3.3.zip"
|
||||||
cmd = "./vibe-acp"
|
cmd = "./vibe-acp"
|
||||||
|
|
||||||
[agent_servers.mistral-vibe.targets.linux-x86_64]
|
[agent_servers.mistral-vibe.targets.linux-x86_64]
|
||||||
archive = "https://github.com/mistralai/mistral-vibe/releases/download/v1.3.2/vibe-acp-linux-x86_64-1.3.2.zip"
|
archive = "https://github.com/mistralai/mistral-vibe/releases/download/v1.3.3/vibe-acp-linux-x86_64-1.3.3.zip"
|
||||||
cmd = "./vibe-acp"
|
cmd = "./vibe-acp"
|
||||||
|
|
||||||
[agent_servers.mistral-vibe.targets.windows-aarch64]
|
[agent_servers.mistral-vibe.targets.windows-aarch64]
|
||||||
archive = "https://github.com/mistralai/mistral-vibe/releases/download/v1.3.2/vibe-acp-windows-aarch64-1.3.2.zip"
|
archive = "https://github.com/mistralai/mistral-vibe/releases/download/v1.3.3/vibe-acp-windows-aarch64-1.3.3.zip"
|
||||||
cmd = "./vibe-acp.exe"
|
cmd = "./vibe-acp.exe"
|
||||||
|
|
||||||
[agent_servers.mistral-vibe.targets.windows-x86_64]
|
[agent_servers.mistral-vibe.targets.windows-x86_64]
|
||||||
archive = "https://github.com/mistralai/mistral-vibe/releases/download/v1.3.2/vibe-acp-windows-x86_64-1.3.2.zip"
|
archive = "https://github.com/mistralai/mistral-vibe/releases/download/v1.3.3/vibe-acp-windows-x86_64-1.3.3.zip"
|
||||||
cmd = "./vibe-acp.exe"
|
cmd = "./vibe-acp.exe"
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
[project]
|
[project]
|
||||||
name = "mistral-vibe"
|
name = "mistral-vibe"
|
||||||
version = "1.3.2"
|
version = "1.3.3"
|
||||||
description = "Minimal CLI coding agent by Mistral"
|
description = "Minimal CLI coding agent by Mistral"
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
requires-python = ">=3.12"
|
requires-python = ">=3.12"
|
||||||
|
|
|
||||||
|
|
@ -41,7 +41,7 @@ class TestACPInitialize:
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
assert response.agentInfo == Implementation(
|
assert response.agentInfo == Implementation(
|
||||||
name="@mistralai/mistral-vibe", title="Mistral Vibe", version="1.3.2"
|
name="@mistralai/mistral-vibe", title="Mistral Vibe", version="1.3.3"
|
||||||
)
|
)
|
||||||
|
|
||||||
assert response.authMethods == []
|
assert response.authMethods == []
|
||||||
|
|
@ -63,7 +63,7 @@ class TestACPInitialize:
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
assert response.agentInfo == Implementation(
|
assert response.agentInfo == Implementation(
|
||||||
name="@mistralai/mistral-vibe", title="Mistral Vibe", version="1.3.2"
|
name="@mistralai/mistral-vibe", title="Mistral Vibe", version="1.3.3"
|
||||||
)
|
)
|
||||||
|
|
||||||
assert response.authMethods is not None
|
assert response.authMethods is not None
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@ def config() -> VibeConfig:
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def skill_manager(config: VibeConfig) -> SkillManager:
|
def skill_manager(config: VibeConfig) -> SkillManager:
|
||||||
return SkillManager(config)
|
return SkillManager(lambda: config)
|
||||||
|
|
||||||
|
|
||||||
class TestSkillManagerDiscovery:
|
class TestSkillManagerDiscovery:
|
||||||
|
|
@ -38,7 +38,7 @@ class TestSkillManagerDiscovery:
|
||||||
include_project_context=False,
|
include_project_context=False,
|
||||||
skill_paths=[skills_dir],
|
skill_paths=[skills_dir],
|
||||||
)
|
)
|
||||||
manager = SkillManager(config)
|
manager = SkillManager(lambda: config)
|
||||||
|
|
||||||
assert "test-skill" in manager.available_skills
|
assert "test-skill" in manager.available_skills
|
||||||
assert manager.available_skills["test-skill"].description == "A test skill"
|
assert manager.available_skills["test-skill"].description == "A test skill"
|
||||||
|
|
@ -54,7 +54,7 @@ class TestSkillManagerDiscovery:
|
||||||
include_project_context=False,
|
include_project_context=False,
|
||||||
skill_paths=[skills_dir],
|
skill_paths=[skills_dir],
|
||||||
)
|
)
|
||||||
manager = SkillManager(config)
|
manager = SkillManager(lambda: config)
|
||||||
|
|
||||||
assert len(manager.available_skills) == 3
|
assert len(manager.available_skills) == 3
|
||||||
assert "skill-one" in manager.available_skills
|
assert "skill-one" in manager.available_skills
|
||||||
|
|
@ -76,7 +76,7 @@ class TestSkillManagerDiscovery:
|
||||||
include_project_context=False,
|
include_project_context=False,
|
||||||
skill_paths=[skills_dir],
|
skill_paths=[skills_dir],
|
||||||
)
|
)
|
||||||
manager = SkillManager(config)
|
manager = SkillManager(lambda: config)
|
||||||
|
|
||||||
skills = manager.available_skills
|
skills = manager.available_skills
|
||||||
assert len(skills) == 1
|
assert len(skills) == 1
|
||||||
|
|
@ -96,7 +96,7 @@ class TestSkillManagerDiscovery:
|
||||||
include_project_context=False,
|
include_project_context=False,
|
||||||
skill_paths=[skills_dir],
|
skill_paths=[skills_dir],
|
||||||
)
|
)
|
||||||
manager = SkillManager(config)
|
manager = SkillManager(lambda: config)
|
||||||
|
|
||||||
skills = manager.available_skills
|
skills = manager.available_skills
|
||||||
assert len(skills) == 1
|
assert len(skills) == 1
|
||||||
|
|
@ -121,7 +121,7 @@ class TestSkillManagerParsing:
|
||||||
include_project_context=False,
|
include_project_context=False,
|
||||||
skill_paths=[skills_dir],
|
skill_paths=[skills_dir],
|
||||||
)
|
)
|
||||||
manager = SkillManager(config)
|
manager = SkillManager(lambda: config)
|
||||||
|
|
||||||
skill = manager.get_skill("full-skill")
|
skill = manager.get_skill("full-skill")
|
||||||
assert skill is not None
|
assert skill is not None
|
||||||
|
|
@ -141,7 +141,7 @@ class TestSkillManagerParsing:
|
||||||
include_project_context=False,
|
include_project_context=False,
|
||||||
skill_paths=[skills_dir],
|
skill_paths=[skills_dir],
|
||||||
)
|
)
|
||||||
manager = SkillManager(config)
|
manager = SkillManager(lambda: config)
|
||||||
|
|
||||||
skill = manager.get_skill("test-skill")
|
skill = manager.get_skill("test-skill")
|
||||||
assert skill is not None
|
assert skill is not None
|
||||||
|
|
@ -163,7 +163,7 @@ class TestSkillManagerParsing:
|
||||||
include_project_context=False,
|
include_project_context=False,
|
||||||
skill_paths=[skills_dir],
|
skill_paths=[skills_dir],
|
||||||
)
|
)
|
||||||
manager = SkillManager(config)
|
manager = SkillManager(lambda: config)
|
||||||
|
|
||||||
skills = manager.available_skills
|
skills = manager.available_skills
|
||||||
assert len(skills) == 1
|
assert len(skills) == 1
|
||||||
|
|
@ -185,7 +185,7 @@ class TestSkillManagerParsing:
|
||||||
include_project_context=False,
|
include_project_context=False,
|
||||||
skill_paths=[skills_dir],
|
skill_paths=[skills_dir],
|
||||||
)
|
)
|
||||||
manager = SkillManager(config)
|
manager = SkillManager(lambda: config)
|
||||||
|
|
||||||
skills = manager.available_skills
|
skills = manager.available_skills
|
||||||
assert len(skills) == 1
|
assert len(skills) == 1
|
||||||
|
|
@ -209,7 +209,7 @@ class TestSkillManagerSearchPaths:
|
||||||
include_project_context=False,
|
include_project_context=False,
|
||||||
skill_paths=[skills_dir_1, skills_dir_2],
|
skill_paths=[skills_dir_1, skills_dir_2],
|
||||||
)
|
)
|
||||||
manager = SkillManager(config)
|
manager = SkillManager(lambda: config)
|
||||||
|
|
||||||
skills = manager.available_skills
|
skills = manager.available_skills
|
||||||
assert len(skills) == 2
|
assert len(skills) == 2
|
||||||
|
|
@ -232,7 +232,7 @@ class TestSkillManagerSearchPaths:
|
||||||
include_project_context=False,
|
include_project_context=False,
|
||||||
skill_paths=[skills_dir_1, skills_dir_2],
|
skill_paths=[skills_dir_1, skills_dir_2],
|
||||||
)
|
)
|
||||||
manager = SkillManager(config)
|
manager = SkillManager(lambda: config)
|
||||||
|
|
||||||
skills = manager.available_skills
|
skills = manager.available_skills
|
||||||
assert len(skills) == 1
|
assert len(skills) == 1
|
||||||
|
|
@ -249,7 +249,7 @@ class TestSkillManagerSearchPaths:
|
||||||
include_project_context=False,
|
include_project_context=False,
|
||||||
skill_paths=[skills_dir, tmp_path / "nonexistent"],
|
skill_paths=[skills_dir, tmp_path / "nonexistent"],
|
||||||
)
|
)
|
||||||
manager = SkillManager(config)
|
manager = SkillManager(lambda: config)
|
||||||
|
|
||||||
assert len(manager.available_skills) == 1
|
assert len(manager.available_skills) == 1
|
||||||
assert "valid-skill" in manager.available_skills
|
assert "valid-skill" in manager.available_skills
|
||||||
|
|
@ -265,7 +265,7 @@ class TestSkillManagerGetSkill:
|
||||||
include_project_context=False,
|
include_project_context=False,
|
||||||
skill_paths=[skills_dir],
|
skill_paths=[skills_dir],
|
||||||
)
|
)
|
||||||
manager = SkillManager(config)
|
manager = SkillManager(lambda: config)
|
||||||
|
|
||||||
skill = manager.get_skill("test-skill")
|
skill = manager.get_skill("test-skill")
|
||||||
assert skill is not None
|
assert skill is not None
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,7 @@ def test_get_universal_system_prompt_includes_windows_prompt_on_windows(
|
||||||
include_model_info=False,
|
include_model_info=False,
|
||||||
include_commit_signature=False,
|
include_commit_signature=False,
|
||||||
)
|
)
|
||||||
tool_manager = ToolManager(config)
|
tool_manager = ToolManager(lambda: config)
|
||||||
|
|
||||||
prompt = get_universal_system_prompt(tool_manager, config)
|
prompt = get_universal_system_prompt(tool_manager, config)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,7 @@ def config():
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def tool_manager(config):
|
def tool_manager(config):
|
||||||
return ToolManager(config)
|
return ToolManager(lambda: config)
|
||||||
|
|
||||||
|
|
||||||
def test_returns_default_config_when_no_overrides(tool_manager):
|
def test_returns_default_config_when_no_overrides(tool_manager):
|
||||||
|
|
@ -39,7 +39,7 @@ def test_merges_user_overrides_with_defaults():
|
||||||
include_project_context=False,
|
include_project_context=False,
|
||||||
tools={"bash": BaseToolConfig(permission=ToolPermission.ALWAYS)},
|
tools={"bash": BaseToolConfig(permission=ToolPermission.ALWAYS)},
|
||||||
)
|
)
|
||||||
manager = ToolManager(vibe_config)
|
manager = ToolManager(lambda: vibe_config)
|
||||||
|
|
||||||
config = manager.get_tool_config("bash")
|
config = manager.get_tool_config("bash")
|
||||||
|
|
||||||
|
|
@ -58,7 +58,7 @@ def test_preserves_tool_specific_fields_from_overrides():
|
||||||
tools={"bash": BaseToolConfig(permission=ToolPermission.ASK)},
|
tools={"bash": BaseToolConfig(permission=ToolPermission.ASK)},
|
||||||
)
|
)
|
||||||
vibe_config.tools["bash"].__pydantic_extra__ = {"default_timeout": 600}
|
vibe_config.tools["bash"].__pydantic_extra__ = {"default_timeout": 600}
|
||||||
manager = ToolManager(vibe_config)
|
manager = ToolManager(lambda: vibe_config)
|
||||||
|
|
||||||
config = manager.get_tool_config("bash")
|
config = manager.get_tool_config("bash")
|
||||||
|
|
||||||
|
|
@ -80,7 +80,7 @@ def test_applies_workdir_from_vibe_config(tmp_path):
|
||||||
include_project_context=False,
|
include_project_context=False,
|
||||||
workdir=tmp_path,
|
workdir=tmp_path,
|
||||||
)
|
)
|
||||||
manager = ToolManager(vibe_config)
|
manager = ToolManager(lambda: vibe_config)
|
||||||
|
|
||||||
config = manager.get_tool_config("bash")
|
config = manager.get_tool_config("bash")
|
||||||
|
|
||||||
|
|
|
||||||
2
uv.lock
generated
2
uv.lock
generated
|
|
@ -661,7 +661,7 @@ wheels = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "mistral-vibe"
|
name = "mistral-vibe"
|
||||||
version = "1.3.2"
|
version = "1.3.3"
|
||||||
source = { editable = "." }
|
source = { editable = "." }
|
||||||
dependencies = [
|
dependencies = [
|
||||||
{ name = "agent-client-protocol" },
|
{ name = "agent-client-protocol" },
|
||||||
|
|
|
||||||
|
|
@ -3,4 +3,4 @@ from __future__ import annotations
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
VIBE_ROOT = Path(__file__).parent
|
VIBE_ROOT = Path(__file__).parent
|
||||||
__version__ = "1.3.2"
|
__version__ = "1.3.3"
|
||||||
|
|
|
||||||
|
|
@ -74,7 +74,7 @@ class BottomApp(StrEnum):
|
||||||
Input = auto()
|
Input = auto()
|
||||||
|
|
||||||
|
|
||||||
class VibeApp(App):
|
class VibeApp(App): # noqa: PLR0904
|
||||||
ENABLE_COMMAND_PALETTE = False
|
ENABLE_COMMAND_PALETTE = False
|
||||||
CSS_PATH = "app.tcss"
|
CSS_PATH = "app.tcss"
|
||||||
|
|
||||||
|
|
@ -104,7 +104,7 @@ class VibeApp(App):
|
||||||
**kwargs: Any,
|
**kwargs: Any,
|
||||||
) -> None:
|
) -> None:
|
||||||
super().__init__(**kwargs)
|
super().__init__(**kwargs)
|
||||||
self.config = config
|
self._config = config
|
||||||
self._current_agent_mode = initial_mode
|
self._current_agent_mode = initial_mode
|
||||||
self.enable_streaming = enable_streaming
|
self.enable_streaming = enable_streaming
|
||||||
self.agent: Agent | None = None
|
self.agent: Agent | None = None
|
||||||
|
|
@ -147,6 +147,10 @@ class VibeApp(App):
|
||||||
self._last_escape_time: float | None = None
|
self._last_escape_time: float | None = None
|
||||||
self._terminal_theme = capture_terminal_theme()
|
self._terminal_theme = capture_terminal_theme()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def config(self) -> VibeConfig:
|
||||||
|
return self.agent.config if self.agent else self._config
|
||||||
|
|
||||||
def compose(self) -> ComposeResult:
|
def compose(self) -> ComposeResult:
|
||||||
with VerticalScroll(id="chat"):
|
with VerticalScroll(id="chat"):
|
||||||
yield WelcomeBanner(self.config)
|
yield WelcomeBanner(self.config)
|
||||||
|
|
@ -704,8 +708,8 @@ class VibeApp(App):
|
||||||
|
|
||||||
if self.agent:
|
if self.agent:
|
||||||
await self.agent.reload_with_initial_messages(config=new_config)
|
await self.agent.reload_with_initial_messages(config=new_config)
|
||||||
|
else:
|
||||||
self.config = new_config
|
self._config = new_config
|
||||||
if self._context_progress:
|
if self._context_progress:
|
||||||
if self.config.auto_compact_threshold > 0:
|
if self.config.auto_compact_threshold > 0:
|
||||||
current_tokens = (
|
current_tokens = (
|
||||||
|
|
|
||||||
|
|
@ -104,8 +104,8 @@ class Agent:
|
||||||
self._max_turns = max_turns
|
self._max_turns = max_turns
|
||||||
self._max_price = max_price
|
self._max_price = max_price
|
||||||
|
|
||||||
self.tool_manager = ToolManager(config)
|
self.tool_manager = ToolManager(lambda: self.config)
|
||||||
self.skill_manager = SkillManager(config)
|
self.skill_manager = SkillManager(lambda: self.config)
|
||||||
self.format_handler = APIToolFormatHandler()
|
self.format_handler = APIToolFormatHandler()
|
||||||
|
|
||||||
self.backend_factory = lambda: backend or self._select_backend()
|
self.backend_factory = lambda: backend or self._select_backend()
|
||||||
|
|
@ -870,8 +870,8 @@ class Agent:
|
||||||
if max_price is not None:
|
if max_price is not None:
|
||||||
self._max_price = max_price
|
self._max_price = max_price
|
||||||
|
|
||||||
self.tool_manager = ToolManager(self.config)
|
self.tool_manager = ToolManager(lambda: self.config)
|
||||||
self.skill_manager = SkillManager(self.config)
|
self.skill_manager = SkillManager(lambda: self.config)
|
||||||
|
|
||||||
new_system_prompt = get_universal_system_prompt(
|
new_system_prompt = get_universal_system_prompt(
|
||||||
self.tool_manager, self.config, self.skill_manager
|
self.tool_manager, self.config, self.skill_manager
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from collections.abc import Callable
|
||||||
from logging import getLogger
|
from logging import getLogger
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import TYPE_CHECKING
|
from typing import TYPE_CHECKING
|
||||||
|
|
@ -16,9 +17,9 @@ logger = getLogger("vibe")
|
||||||
|
|
||||||
|
|
||||||
class SkillManager:
|
class SkillManager:
|
||||||
def __init__(self, config: VibeConfig) -> None:
|
def __init__(self, config_getter: Callable[[], VibeConfig]) -> None:
|
||||||
self._config = config
|
self._config_getter = config_getter
|
||||||
self._search_paths = self._compute_search_paths(config)
|
self._search_paths = self._compute_search_paths(self._config)
|
||||||
self.available_skills = self._discover_skills()
|
self.available_skills = self._discover_skills()
|
||||||
|
|
||||||
if self.available_skills:
|
if self.available_skills:
|
||||||
|
|
@ -28,6 +29,10 @@ class SkillManager:
|
||||||
len(self._search_paths),
|
len(self._search_paths),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def _config(self) -> VibeConfig:
|
||||||
|
return self._config_getter()
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _compute_search_paths(config: VibeConfig) -> list[Path]:
|
def _compute_search_paths(config: VibeConfig) -> list[Path]:
|
||||||
paths: list[Path] = []
|
paths: list[Path] = []
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
from collections.abc import Iterator
|
from collections.abc import Callable, Iterator
|
||||||
import importlib.util
|
import importlib.util
|
||||||
import inspect
|
import inspect
|
||||||
from logging import getLogger
|
from logging import getLogger
|
||||||
|
|
@ -38,16 +38,20 @@ class ToolManager:
|
||||||
should have its own ToolManager instance.
|
should have its own ToolManager instance.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, config: VibeConfig) -> None:
|
def __init__(self, config_getter: Callable[[], VibeConfig]) -> None:
|
||||||
self._config = config
|
self._config_getter = config_getter
|
||||||
self._instances: dict[str, BaseTool] = {}
|
self._instances: dict[str, BaseTool] = {}
|
||||||
self._search_paths: list[Path] = self._compute_search_paths(config)
|
self._search_paths: list[Path] = self._compute_search_paths(self._config)
|
||||||
|
|
||||||
self._available: dict[str, type[BaseTool]] = {
|
self._available: dict[str, type[BaseTool]] = {
|
||||||
cls.get_name(): cls for cls in self._iter_tool_classes(self._search_paths)
|
cls.get_name(): cls for cls in self._iter_tool_classes(self._search_paths)
|
||||||
}
|
}
|
||||||
self._integrate_mcp()
|
self._integrate_mcp()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def _config(self) -> VibeConfig:
|
||||||
|
return self._config_getter()
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _compute_search_paths(config: VibeConfig) -> list[Path]:
|
def _compute_search_paths(config: VibeConfig) -> list[Path]:
|
||||||
paths: list[Path] = [DEFAULT_TOOL_DIR.path]
|
paths: list[Path] = [DEFAULT_TOOL_DIR.path]
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue