janito 2.7.0__py3-none-any.whl → 2.9.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- janito/__init__.py +0 -1
- janito/__main__.py +0 -1
- janito/_version.py +0 -3
- janito/agent/setup_agent.py +77 -10
- janito/agent/templates/profiles/{system_prompt_template_plain_software_developer.txt.j2 → system_prompt_template_Developer_with_Python_Tools.txt.j2} +5 -1
- janito/agent/templates/profiles/system_prompt_template_developer.txt.j2 +3 -12
- janito/cli/__init__.py +0 -1
- janito/cli/chat_mode/bindings.py +1 -1
- janito/cli/chat_mode/chat_entry.py +0 -2
- janito/cli/chat_mode/prompt_style.py +0 -3
- janito/cli/chat_mode/script_runner.py +9 -5
- janito/cli/chat_mode/session.py +100 -37
- janito/cli/chat_mode/session_profile_select.py +61 -52
- janito/cli/chat_mode/shell/commands/__init__.py +1 -5
- janito/cli/chat_mode/shell/commands/_priv_check.py +1 -0
- janito/cli/chat_mode/shell/commands/_priv_status.py +13 -0
- janito/cli/chat_mode/shell/commands/bang.py +10 -3
- janito/cli/chat_mode/shell/commands/conversation_restart.py +24 -7
- janito/cli/chat_mode/shell/commands/execute.py +22 -7
- janito/cli/chat_mode/shell/commands/help.py +4 -1
- janito/cli/chat_mode/shell/commands/model.py +13 -5
- janito/cli/chat_mode/shell/commands/privileges.py +21 -0
- janito/cli/chat_mode/shell/commands/prompt.py +0 -2
- janito/cli/chat_mode/shell/commands/read.py +22 -5
- janito/cli/chat_mode/shell/commands/tools.py +15 -4
- janito/cli/chat_mode/shell/commands/write.py +22 -5
- janito/cli/chat_mode/shell/input_history.py +3 -1
- janito/cli/chat_mode/shell/session/manager.py +0 -2
- janito/cli/chat_mode/toolbar.py +25 -19
- janito/cli/cli_commands/list_config.py +31 -0
- janito/cli/cli_commands/list_models.py +1 -1
- janito/cli/cli_commands/list_profiles.py +79 -0
- janito/cli/cli_commands/list_providers.py +1 -0
- janito/cli/cli_commands/list_tools.py +35 -7
- janito/cli/cli_commands/model_utils.py +5 -3
- janito/cli/cli_commands/show_config.py +16 -11
- janito/cli/cli_commands/show_system_prompt.py +23 -9
- janito/cli/config.py +0 -13
- janito/cli/core/getters.py +16 -1
- janito/cli/core/runner.py +25 -8
- janito/cli/core/setters.py +13 -76
- janito/cli/main_cli.py +60 -27
- janito/cli/prompt_core.py +19 -18
- janito/cli/prompt_setup.py +6 -3
- janito/cli/rich_terminal_reporter.py +19 -5
- janito/cli/single_shot_mode/handler.py +14 -5
- janito/cli/verbose_output.py +5 -1
- janito/config.py +1 -0
- janito/config_manager.py +15 -2
- janito/drivers/azure_openai/driver.py +27 -30
- janito/drivers/openai/driver.py +53 -36
- janito/formatting_token.py +12 -4
- janito/llm/agent.py +15 -6
- janito/llm/driver.py +1 -0
- janito/llm/provider.py +1 -1
- janito/provider_registry.py +31 -70
- janito/providers/__init__.py +1 -0
- janito/providers/anthropic/model_info.py +0 -1
- janito/providers/anthropic/provider.py +9 -14
- janito/providers/azure_openai/provider.py +10 -5
- janito/providers/deepseek/provider.py +5 -4
- janito/providers/google/model_info.py +4 -2
- janito/providers/google/provider.py +11 -5
- janito/providers/groq/__init__.py +1 -0
- janito/providers/groq/model_info.py +45 -0
- janito/providers/groq/provider.py +76 -0
- janito/providers/moonshotai/provider.py +11 -4
- janito/providers/openai/model_info.py +0 -1
- janito/providers/openai/provider.py +6 -7
- janito/tools/__init__.py +2 -0
- janito/tools/adapters/local/__init__.py +2 -1
- janito/tools/adapters/local/adapter.py +21 -4
- janito/tools/adapters/local/ask_user.py +1 -0
- janito/tools/adapters/local/copy_file.py +1 -0
- janito/tools/adapters/local/create_directory.py +1 -0
- janito/tools/adapters/local/create_file.py +1 -0
- janito/tools/adapters/local/delete_text_in_file.py +2 -1
- janito/tools/adapters/local/fetch_url.py +1 -0
- janito/tools/adapters/local/find_files.py +7 -6
- janito/tools/adapters/local/get_file_outline/core.py +1 -0
- janito/tools/adapters/local/get_file_outline/java_outline.py +22 -15
- janito/tools/adapters/local/get_file_outline/search_outline.py +1 -0
- janito/tools/adapters/local/move_file.py +1 -0
- janito/tools/adapters/local/open_html_in_browser.py +15 -5
- janito/tools/adapters/local/open_url.py +1 -0
- janito/tools/adapters/local/python_code_run.py +1 -0
- janito/tools/adapters/local/python_command_run.py +1 -0
- janito/tools/adapters/local/python_file_run.py +1 -0
- janito/tools/adapters/local/read_files.py +19 -4
- janito/tools/adapters/local/remove_directory.py +1 -0
- janito/tools/adapters/local/remove_file.py +1 -0
- janito/tools/adapters/local/replace_text_in_file.py +4 -3
- janito/tools/adapters/local/run_bash_command.py +1 -0
- janito/tools/adapters/local/run_powershell_command.py +1 -0
- janito/tools/adapters/local/search_text/core.py +18 -17
- janito/tools/adapters/local/search_text/match_lines.py +5 -5
- janito/tools/adapters/local/search_text/pattern_utils.py +1 -1
- janito/tools/adapters/local/search_text/traverse_directory.py +7 -7
- janito/tools/adapters/local/validate_file_syntax/core.py +1 -1
- janito/tools/adapters/local/validate_file_syntax/html_validator.py +8 -1
- janito/tools/disabled_tools.py +68 -0
- janito/tools/path_security.py +18 -11
- janito/tools/permissions.py +6 -0
- janito/tools/permissions_parse.py +4 -3
- janito/tools/tool_base.py +11 -5
- janito/tools/tool_use_tracker.py +1 -4
- janito/tools/tool_utils.py +1 -1
- janito/tools/tools_adapter.py +57 -25
- {janito-2.7.0.dist-info → janito-2.9.0.dist-info}/METADATA +11 -19
- janito-2.9.0.dist-info/RECORD +205 -0
- janito/cli/chat_mode/shell/commands/livelogs.py +0 -49
- janito/drivers/mistralai/driver.py +0 -41
- janito/providers/mistralai/model_info.py +0 -37
- janito/providers/mistralai/provider.py +0 -72
- janito/providers/provider_static_info.py +0 -21
- janito-2.7.0.dist-info/RECORD +0 -202
- /janito/agent/templates/profiles/{system_prompt_template_assistant.txt.j2 → system_prompt_template_model_conversation_without_tools_or_context.txt.j2} +0 -0
- {janito-2.7.0.dist-info → janito-2.9.0.dist-info}/WHEEL +0 -0
- {janito-2.7.0.dist-info → janito-2.9.0.dist-info}/entry_points.txt +0 -0
- {janito-2.7.0.dist-info → janito-2.9.0.dist-info}/licenses/LICENSE +0 -0
- {janito-2.7.0.dist-info → janito-2.9.0.dist-info}/top_level.txt +0 -0
@@ -11,12 +11,13 @@ from janito.drivers.azure_openai.driver import AzureOpenAIModelDriver
|
|
11
11
|
|
12
12
|
available = AzureOpenAIModelDriver.available
|
13
13
|
unavailable_reason = AzureOpenAIModelDriver.unavailable_reason
|
14
|
-
maintainer = "João Pinto <
|
14
|
+
maintainer = "João Pinto <janito@ikignosis.org>"
|
15
15
|
|
16
16
|
|
17
17
|
class AzureOpenAIProvider(LLMProvider):
|
18
18
|
name = "azure_openai"
|
19
|
-
|
19
|
+
NAME = "azure_openai"
|
20
|
+
MAINTAINER = "João Pinto <janito@ikignosis.org>"
|
20
21
|
MODEL_SPECS = MODEL_SPECS
|
21
22
|
DEFAULT_MODEL = "azure_openai_deployment"
|
22
23
|
|
@@ -30,7 +31,7 @@ class AzureOpenAIProvider(LLMProvider):
|
|
30
31
|
self._driver = None
|
31
32
|
return
|
32
33
|
self._auth_manager = auth_manager or LLMAuthManager()
|
33
|
-
self._api_key = self._auth_manager.get_credentials(type(self).
|
34
|
+
self._api_key = self._auth_manager.get_credentials(type(self).NAME)
|
34
35
|
self._tools_adapter = get_local_tools_adapter()
|
35
36
|
self._driver_config = config or LLMDriverConfig(model=None)
|
36
37
|
if not self._driver_config.model:
|
@@ -41,6 +42,7 @@ class AzureOpenAIProvider(LLMProvider):
|
|
41
42
|
self._driver_config.extra["api_version"] = "2023-05-15"
|
42
43
|
# Inject azure_deployment_name from config if present
|
43
44
|
from janito.config import config as global_config
|
45
|
+
|
44
46
|
deployment_name = global_config.get("azure_deployment_name")
|
45
47
|
if deployment_name:
|
46
48
|
self._driver_config.extra["azure_deployment_name"] = deployment_name
|
@@ -76,7 +78,10 @@ class AzureOpenAIProvider(LLMProvider):
|
|
76
78
|
"""
|
77
79
|
if model_name is None:
|
78
80
|
# Return all known specs, but note: only static ones are listed
|
79
|
-
return {
|
81
|
+
return {
|
82
|
+
name: model_info.to_dict()
|
83
|
+
for name, model_info in self.MODEL_SPECS.items()
|
84
|
+
}
|
80
85
|
if model_name in self.MODEL_SPECS:
|
81
86
|
return self.MODEL_SPECS[model_name].to_dict()
|
82
87
|
# Accept any deployment name as a valid model
|
@@ -120,4 +125,4 @@ class AzureOpenAIProvider(LLMProvider):
|
|
120
125
|
return self._tools_adapter.execute_by_name(tool_name, *args, **kwargs)
|
121
126
|
|
122
127
|
|
123
|
-
LLMProviderRegistry.register(AzureOpenAIProvider.
|
128
|
+
LLMProviderRegistry.register(AzureOpenAIProvider.NAME, AzureOpenAIProvider)
|
@@ -12,9 +12,10 @@ available = OpenAIModelDriver.available
|
|
12
12
|
unavailable_reason = OpenAIModelDriver.unavailable_reason
|
13
13
|
|
14
14
|
|
15
|
-
class
|
15
|
+
class DeepSeekProvider(LLMProvider):
|
16
16
|
name = "deepseek"
|
17
|
-
|
17
|
+
NAME = "deepseek"
|
18
|
+
MAINTAINER = "João Pinto <janito@ikignosis.org>"
|
18
19
|
MODEL_SPECS = MODEL_SPECS
|
19
20
|
DEFAULT_MODEL = "deepseek-chat" # Options: deepseek-chat, deepseek-reasoner
|
20
21
|
|
@@ -28,7 +29,7 @@ class DeepseekProvider(LLMProvider):
|
|
28
29
|
self._driver = None
|
29
30
|
else:
|
30
31
|
self.auth_manager = auth_manager or LLMAuthManager()
|
31
|
-
self._api_key = self.auth_manager.get_credentials(type(self).
|
32
|
+
self._api_key = self.auth_manager.get_credentials(type(self).NAME)
|
32
33
|
self._tools_adapter = get_local_tools_adapter()
|
33
34
|
self._driver_config = config or LLMDriverConfig(model=None)
|
34
35
|
if not self._driver_config.model:
|
@@ -91,4 +92,4 @@ class DeepseekProvider(LLMProvider):
|
|
91
92
|
return self._tools_adapter.execute_by_name(tool_name, *args, **kwargs)
|
92
93
|
|
93
94
|
|
94
|
-
LLMProviderRegistry.register(
|
95
|
+
LLMProviderRegistry.register(DeepSeekProvider.NAME, DeepSeekProvider)
|
@@ -10,7 +10,7 @@ MODEL_SPECS = {
|
|
10
10
|
max_cot=24576,
|
11
11
|
thinking_supported=True,
|
12
12
|
),
|
13
|
-
|
13
|
+
"gemini-2.5-pro": LLMModelInfo(
|
14
14
|
name="gemini-2.5-pro",
|
15
15
|
other={"description": "Google Gemini 2.5 Pro (OpenAI-compatible endpoint)"},
|
16
16
|
open="google",
|
@@ -21,7 +21,9 @@ MODEL_SPECS = {
|
|
21
21
|
),
|
22
22
|
"gemini-2.5-flash-lite-preview-06-17": LLMModelInfo(
|
23
23
|
name="gemini-2.5-flash-lite-preview-06-17",
|
24
|
-
other={
|
24
|
+
other={
|
25
|
+
"description": "Google Gemini 2.5 Flash-Lite Preview (OpenAI-compatible endpoint)"
|
26
|
+
},
|
25
27
|
open="google",
|
26
28
|
driver="OpenAIModelDriver",
|
27
29
|
max_response=64000,
|
@@ -13,9 +13,11 @@ try:
|
|
13
13
|
except ImportError:
|
14
14
|
MODEL_SPECS = {}
|
15
15
|
|
16
|
+
|
16
17
|
class GoogleProvider(LLMProvider):
|
17
18
|
name = "google"
|
18
|
-
|
19
|
+
NAME = "google"
|
20
|
+
MAINTAINER = "João Pinto <janito@ikignosis.org>"
|
19
21
|
MODEL_SPECS = MODEL_SPECS
|
20
22
|
DEFAULT_MODEL = "gemini-2.5-flash" # Default Gemini model
|
21
23
|
|
@@ -33,19 +35,23 @@ class GoogleProvider(LLMProvider):
|
|
33
35
|
self._tools_adapter = get_local_tools_adapter()
|
34
36
|
self._driver_config = config or LLMDriverConfig(model=None)
|
35
37
|
# Only set default if model is not set by CLI/config
|
36
|
-
if not getattr(self._driver_config,
|
38
|
+
if not getattr(self._driver_config, "model", None):
|
37
39
|
self._driver_config.model = self.DEFAULT_MODEL
|
38
40
|
if not self._driver_config.api_key:
|
39
41
|
self._driver_config.api_key = self._api_key
|
40
42
|
# Set the Gemini API endpoint for OpenAI compatibility
|
41
|
-
self._driver_config.base_url =
|
43
|
+
self._driver_config.base_url = (
|
44
|
+
"https://generativelanguage.googleapis.com/v1beta/openai/"
|
45
|
+
)
|
42
46
|
self.fill_missing_device_info(self._driver_config)
|
43
47
|
self._driver = None # to be provided by factory/agent
|
44
48
|
|
45
49
|
@property
|
46
50
|
def driver(self) -> OpenAIModelDriver:
|
47
51
|
if not self.available:
|
48
|
-
raise ImportError(
|
52
|
+
raise ImportError(
|
53
|
+
f"GoogleOpenAIProvider unavailable: {self.unavailable_reason}"
|
54
|
+
)
|
49
55
|
return self._driver
|
50
56
|
|
51
57
|
@property
|
@@ -80,4 +86,4 @@ class GoogleProvider(LLMProvider):
|
|
80
86
|
return self._tools_adapter.execute_by_name(tool_name, *args, **kwargs)
|
81
87
|
|
82
88
|
|
83
|
-
LLMProviderRegistry.register(GoogleProvider.
|
89
|
+
LLMProviderRegistry.register(GoogleProvider.NAME, GoogleProvider)
|
@@ -0,0 +1 @@
|
|
1
|
+
from .provider import GroqProvider
|
@@ -0,0 +1,45 @@
|
|
1
|
+
# Groq provider model specifications
|
2
|
+
from janito.llm.model import LLMModelInfo
|
3
|
+
|
4
|
+
MODEL_SPECS = {
|
5
|
+
"moonshotai/kimi-k2-instruct": LLMModelInfo(
|
6
|
+
name="moonshotai/kimi-k2-instruct",
|
7
|
+
context=128000,
|
8
|
+
max_input=122880,
|
9
|
+
max_cot="N/A",
|
10
|
+
max_response=4096,
|
11
|
+
thinking_supported=False,
|
12
|
+
default_temp=0.2,
|
13
|
+
open="groq",
|
14
|
+
driver="GroqModelDriver",
|
15
|
+
other={
|
16
|
+
"description": "Kimi K2 Instruct model by Moonshot AI",
|
17
|
+
"supports_tools": True,
|
18
|
+
"supports_streaming": True,
|
19
|
+
"supports_vision": False,
|
20
|
+
"supports_system_prompt": True,
|
21
|
+
"supports_temperature": True,
|
22
|
+
"supports_top_p": True,
|
23
|
+
"supports_frequency_penalty": True,
|
24
|
+
"supports_presence_penalty": True,
|
25
|
+
"supports_stop_sequences": True,
|
26
|
+
"supports_max_tokens": True,
|
27
|
+
"supports_seed": False,
|
28
|
+
"supports_json_mode": True,
|
29
|
+
"supports_logprobs": False,
|
30
|
+
"supports_top_logprobs": False,
|
31
|
+
"supports_response_format": True,
|
32
|
+
"supports_n": False,
|
33
|
+
"supports_best_of": False,
|
34
|
+
"supports_echo": False,
|
35
|
+
"supports_logit_bias": False,
|
36
|
+
"supports_user": False,
|
37
|
+
"supports_assistant": False,
|
38
|
+
"supports_system": False,
|
39
|
+
"supports_functions": True,
|
40
|
+
"supports_tool_calls": True,
|
41
|
+
"supports_stream_options": False,
|
42
|
+
"supports_include_usage": False,
|
43
|
+
},
|
44
|
+
)
|
45
|
+
}
|
@@ -0,0 +1,76 @@
|
|
1
|
+
from janito.llm.provider import LLMProvider
|
2
|
+
from janito.llm.model import LLMModelInfo
|
3
|
+
from janito.llm.auth import LLMAuthManager
|
4
|
+
from janito.llm.driver_config import LLMDriverConfig
|
5
|
+
from janito.drivers.openai.driver import OpenAIModelDriver
|
6
|
+
from janito.tools import get_local_tools_adapter
|
7
|
+
from janito.providers.registry import LLMProviderRegistry
|
8
|
+
from .model_info import MODEL_SPECS
|
9
|
+
from queue import Queue
|
10
|
+
|
11
|
+
available = OpenAIModelDriver.available
|
12
|
+
unavailable_reason = OpenAIModelDriver.unavailable_reason
|
13
|
+
|
14
|
+
|
15
|
+
class GroqProvider(LLMProvider):
|
16
|
+
name = "groq"
|
17
|
+
NAME = "groq"
|
18
|
+
MAINTAINER = "Groq Inc. <support@groq.com>"
|
19
|
+
MODEL_SPECS = MODEL_SPECS
|
20
|
+
DEFAULT_MODEL = "moonshotai/kimi-k2-instruct"
|
21
|
+
|
22
|
+
def __init__(
|
23
|
+
self, auth_manager: LLMAuthManager = None, config: LLMDriverConfig = None
|
24
|
+
):
|
25
|
+
if not self.available:
|
26
|
+
self._tools_adapter = get_local_tools_adapter()
|
27
|
+
self._driver = None
|
28
|
+
else:
|
29
|
+
self.auth_manager = auth_manager or LLMAuthManager()
|
30
|
+
self._api_key = self.auth_manager.get_credentials(type(self).NAME)
|
31
|
+
self._tools_adapter = get_local_tools_adapter()
|
32
|
+
self._driver_config = config or LLMDriverConfig(model=self.DEFAULT_MODEL)
|
33
|
+
if not self._driver_config.model:
|
34
|
+
self._driver_config.model = self.DEFAULT_MODEL
|
35
|
+
|
36
|
+
if not self._driver_config.api_key:
|
37
|
+
self._driver_config.api_key = self._api_key
|
38
|
+
self._driver_config.base_url = "https://api.groq.com/openai/v1"
|
39
|
+
self.fill_missing_device_info(self._driver_config)
|
40
|
+
self._driver = None
|
41
|
+
|
42
|
+
@property
|
43
|
+
def driver(self) -> OpenAIModelDriver:
|
44
|
+
if not self.available:
|
45
|
+
raise ImportError(f"GroqProvider unavailable: {self.unavailable_reason}")
|
46
|
+
return self._driver
|
47
|
+
|
48
|
+
@property
|
49
|
+
def available(self):
|
50
|
+
return available
|
51
|
+
|
52
|
+
@property
|
53
|
+
def unavailable_reason(self):
|
54
|
+
return unavailable_reason
|
55
|
+
|
56
|
+
def create_driver(self):
|
57
|
+
driver = OpenAIModelDriver(
|
58
|
+
tools_adapter=self._tools_adapter, provider_name=self.NAME
|
59
|
+
)
|
60
|
+
driver.config = self._driver_config
|
61
|
+
return driver
|
62
|
+
|
63
|
+
@property
|
64
|
+
def model_name(self):
|
65
|
+
return self._driver_config.model
|
66
|
+
|
67
|
+
@property
|
68
|
+
def driver_config(self):
|
69
|
+
return self._driver_config
|
70
|
+
|
71
|
+
def execute_tool(self, tool_name: str, event_bus, *args, **kwargs):
|
72
|
+
self._tools_adapter.event_bus = event_bus
|
73
|
+
return self._tools_adapter.execute_by_name(tool_name, *args, **kwargs)
|
74
|
+
|
75
|
+
|
76
|
+
LLMProviderRegistry.register(GroqProvider.NAME, GroqProvider)
|
@@ -6,13 +6,17 @@ from janito.tools import get_local_tools_adapter
|
|
6
6
|
from janito.providers.registry import LLMProviderRegistry
|
7
7
|
from .model_info import MOONSHOTAI_MODEL_SPECS
|
8
8
|
|
9
|
+
|
9
10
|
class MoonshotAIProvider(LLMProvider):
|
10
11
|
name = "moonshotai"
|
11
|
-
|
12
|
+
NAME = "moonshotai"
|
13
|
+
MAINTAINER = "João Pinto <janito@ikignosis.org>"
|
12
14
|
MODEL_SPECS = MOONSHOTAI_MODEL_SPECS
|
13
15
|
DEFAULT_MODEL = "kimi-k2-0711-preview"
|
14
16
|
|
15
|
-
def __init__(
|
17
|
+
def __init__(
|
18
|
+
self, auth_manager: LLMAuthManager = None, config: LLMDriverConfig = None
|
19
|
+
):
|
16
20
|
if not self.available:
|
17
21
|
self._tools_adapter = get_local_tools_adapter()
|
18
22
|
self._driver = None
|
@@ -49,7 +53,9 @@ class MoonshotAIProvider(LLMProvider):
|
|
49
53
|
@property
|
50
54
|
def driver(self) -> OpenAIModelDriver:
|
51
55
|
if not self.available:
|
52
|
-
raise ImportError(
|
56
|
+
raise ImportError(
|
57
|
+
f"MoonshotAIProvider unavailable: {self.unavailable_reason}"
|
58
|
+
)
|
53
59
|
return self._driver
|
54
60
|
|
55
61
|
@property
|
@@ -79,4 +85,5 @@ class MoonshotAIProvider(LLMProvider):
|
|
79
85
|
self._tools_adapter.event_bus = event_bus
|
80
86
|
return self._tools_adapter.execute_by_name(tool_name, *args, **kwargs)
|
81
87
|
|
82
|
-
|
88
|
+
|
89
|
+
LLMProviderRegistry.register(MoonshotAIProvider.NAME, MoonshotAIProvider)
|
@@ -14,11 +14,10 @@ unavailable_reason = OpenAIModelDriver.unavailable_reason
|
|
14
14
|
|
15
15
|
class OpenAIProvider(LLMProvider):
|
16
16
|
name = "openai"
|
17
|
-
|
17
|
+
NAME = "openai"
|
18
|
+
MAINTAINER = "João Pinto <janito@ikignosis.org>"
|
18
19
|
MODEL_SPECS = MODEL_SPECS
|
19
|
-
DEFAULT_MODEL =
|
20
|
-
"gpt-4.1" # Options: gpt-4.1, gpt-4o, o3-mini, o4-mini,
|
21
|
-
)
|
20
|
+
DEFAULT_MODEL = "gpt-4.1" # Options: gpt-4.1, gpt-4o, o3-mini, o4-mini,
|
22
21
|
|
23
22
|
def __init__(
|
24
23
|
self, auth_manager: LLMAuthManager = None, config: LLMDriverConfig = None
|
@@ -31,7 +30,7 @@ class OpenAIProvider(LLMProvider):
|
|
31
30
|
self._driver = None
|
32
31
|
else:
|
33
32
|
self.auth_manager = auth_manager or LLMAuthManager()
|
34
|
-
self._api_key = self.auth_manager.get_credentials(type(self).
|
33
|
+
self._api_key = self.auth_manager.get_credentials(type(self).NAME)
|
35
34
|
self._tools_adapter = get_local_tools_adapter()
|
36
35
|
self._driver_config = config or LLMDriverConfig(model=None)
|
37
36
|
if not self._driver_config.model:
|
@@ -77,7 +76,7 @@ class OpenAIProvider(LLMProvider):
|
|
77
76
|
Creates and returns a new OpenAIModelDriver instance with input/output queues.
|
78
77
|
"""
|
79
78
|
driver = OpenAIModelDriver(
|
80
|
-
tools_adapter=self._tools_adapter, provider_name=self.
|
79
|
+
tools_adapter=self._tools_adapter, provider_name=self.NAME
|
81
80
|
)
|
82
81
|
driver.config = self._driver_config
|
83
82
|
# NOTE: The caller is responsible for calling driver.start() if background processing is needed.
|
@@ -108,4 +107,4 @@ class OpenAIProvider(LLMProvider):
|
|
108
107
|
return self._tools_adapter.execute_by_name(tool_name, *args, **kwargs)
|
109
108
|
|
110
109
|
|
111
|
-
LLMProviderRegistry.register(OpenAIProvider.
|
110
|
+
LLMProviderRegistry.register(OpenAIProvider.NAME, OpenAIProvider)
|
janito/tools/__init__.py
CHANGED
@@ -7,6 +7,7 @@ from janito.tools.adapters.local import (
|
|
7
7
|
def get_local_tools_adapter(workdir=None, allowed_permissions=None):
|
8
8
|
# Use set_verbose_tools on the returned adapter to set verbosity as needed
|
9
9
|
import os
|
10
|
+
|
10
11
|
if workdir is not None and not os.path.exists(workdir):
|
11
12
|
os.makedirs(workdir, exist_ok=True)
|
12
13
|
# Permissions are now managed globally; ignore allowed_permissions argument except for backward compatibility
|
@@ -16,6 +17,7 @@ def get_local_tools_adapter(workdir=None, allowed_permissions=None):
|
|
16
17
|
if workdir is not None:
|
17
18
|
try:
|
18
19
|
import os
|
20
|
+
|
19
21
|
if not os.path.exists(workdir):
|
20
22
|
os.makedirs(workdir, exist_ok=True)
|
21
23
|
os.chdir(workdir)
|
@@ -31,9 +31,11 @@ from janito.tools.permissions import get_global_allowed_permissions
|
|
31
31
|
# Singleton tools adapter with all standard tools registered
|
32
32
|
local_tools_adapter = LocalToolsAdapter(workdir=os.getcwd())
|
33
33
|
|
34
|
+
|
34
35
|
def get_local_tools_adapter(workdir=None):
|
35
36
|
return LocalToolsAdapter(workdir=workdir or os.getcwd())
|
36
37
|
|
38
|
+
|
37
39
|
# Register tools
|
38
40
|
for tool_class in [
|
39
41
|
AskUserTool,
|
@@ -63,4 +65,3 @@ for tool_class in [
|
|
63
65
|
local_tools_adapter.register_tool(tool_class)
|
64
66
|
|
65
67
|
# DEBUG: Print registered tools at startup
|
66
|
-
|
@@ -40,6 +40,7 @@ class LocalToolsAdapter(ToolsAdapter):
|
|
40
40
|
# to UI components even if the caller did not supply a custom bus.
|
41
41
|
if event_bus is None:
|
42
42
|
from janito.event_bus.bus import event_bus as global_event_bus
|
43
|
+
|
43
44
|
event_bus = global_event_bus
|
44
45
|
|
45
46
|
super().__init__(tools=tools, event_bus=event_bus)
|
@@ -48,6 +49,7 @@ class LocalToolsAdapter(ToolsAdapter):
|
|
48
49
|
self._tools: Dict[str, Dict[str, Any]] = {}
|
49
50
|
|
50
51
|
import os
|
52
|
+
|
51
53
|
self.workdir = workdir or os.getcwd()
|
52
54
|
# Ensure *some* workdir is set – fallback to CWD.
|
53
55
|
if not self.workdir:
|
@@ -93,27 +95,39 @@ class LocalToolsAdapter(ToolsAdapter):
|
|
93
95
|
# Lookup helpers used by ToolsAdapterBase
|
94
96
|
# ------------------------------------------------------------------
|
95
97
|
def get_tool(self, name: str):
|
96
|
-
|
98
|
+
from janito.tools.disabled_tools import is_tool_disabled
|
99
|
+
|
100
|
+
if name in self._tools and not is_tool_disabled(name):
|
101
|
+
return self._tools[name]["instance"]
|
102
|
+
return None
|
97
103
|
|
98
104
|
def list_tools(self):
|
105
|
+
from janito.tools.disabled_tools import is_tool_disabled
|
106
|
+
|
99
107
|
return [
|
100
108
|
name
|
101
109
|
for name, entry in self._tools.items()
|
102
|
-
if self.is_tool_allowed(entry["instance"])
|
110
|
+
if self.is_tool_allowed(entry["instance"]) and not is_tool_disabled(name)
|
103
111
|
]
|
104
112
|
|
105
113
|
def get_tool_classes(self):
|
114
|
+
from janito.tools.disabled_tools import is_tool_disabled
|
115
|
+
|
106
116
|
return [
|
107
117
|
entry["class"]
|
108
118
|
for entry in self._tools.values()
|
109
119
|
if self.is_tool_allowed(entry["instance"])
|
120
|
+
and not is_tool_disabled(entry["instance"].tool_name)
|
110
121
|
]
|
111
122
|
|
112
123
|
def get_tools(self):
|
124
|
+
from janito.tools.disabled_tools import is_tool_disabled
|
125
|
+
|
113
126
|
return [
|
114
127
|
entry["instance"]
|
115
128
|
for entry in self._tools.values()
|
116
129
|
if self.is_tool_allowed(entry["instance"])
|
130
|
+
and not is_tool_disabled(entry["instance"].tool_name)
|
117
131
|
]
|
118
132
|
|
119
133
|
# ------------------------------------------------------------------
|
@@ -125,7 +139,9 @@ class LocalToolsAdapter(ToolsAdapter):
|
|
125
139
|
raise TypeError(f"Tool '{tool}' must implement a callable 'run' method.")
|
126
140
|
tool_name = getattr(tool, "tool_name", None)
|
127
141
|
if not tool_name or not isinstance(tool_name, str):
|
128
|
-
raise ValueError(
|
142
|
+
raise ValueError(
|
143
|
+
f"Tool '{tool}' must provide a 'tool_name' (str) attribute."
|
144
|
+
)
|
129
145
|
if tool_name in self._tools:
|
130
146
|
raise ValueError(f"Tool '{tool_name}' is already registered.")
|
131
147
|
self._tools[tool_name] = {
|
@@ -139,6 +155,7 @@ class LocalToolsAdapter(ToolsAdapter):
|
|
139
155
|
# Decorator helper for quick registration of local tools
|
140
156
|
# -------------------------------------------------------------------------
|
141
157
|
|
158
|
+
|
142
159
|
def register_local_tool(tool=None):
|
143
160
|
"""Class decorator that registers the tool on the *singleton* adapter.
|
144
161
|
|
@@ -150,7 +167,7 @@ def register_local_tool(tool=None):
|
|
150
167
|
"""
|
151
168
|
|
152
169
|
def decorator(cls):
|
153
|
-
|
170
|
+
# Register the tool on a *fresh* adapter instance to avoid circular
|
154
171
|
# import issues during package initialisation. This keeps behaviour
|
155
172
|
# identical to the original implementation while still allowing
|
156
173
|
# immediate use via the singleton in janito.tools.adapters.local.
|
@@ -19,6 +19,7 @@ class DeleteTextInFileTool(ToolBase):
|
|
19
19
|
Returns:
|
20
20
|
str: Status message indicating the result.
|
21
21
|
"""
|
22
|
+
|
22
23
|
permissions = ToolPermissions(read=True, write=True)
|
23
24
|
tool_name = "delete_text_in_file"
|
24
25
|
|
@@ -62,7 +63,7 @@ class DeleteTextInFileTool(ToolBase):
|
|
62
63
|
return tr(
|
63
64
|
"Deleted {count} block(s) between markers in {path}. ",
|
64
65
|
count=deleted_blocks,
|
65
|
-
path=path
|
66
|
+
path=path,
|
66
67
|
) + (f"\n{validation_result}" if validation_result else "")
|
67
68
|
except Exception as e:
|
68
69
|
self.report_error(tr(" ❌ Error: {error}", error=e), ReportAction.REPLACE)
|
@@ -61,7 +61,9 @@ class FindFilesTool(ToolBase):
|
|
61
61
|
break
|
62
62
|
return dir_output
|
63
63
|
|
64
|
-
def _handle_directory_path(
|
64
|
+
def _handle_directory_path(
|
65
|
+
self, directory, patterns, max_depth, include_gitignored
|
66
|
+
):
|
65
67
|
dir_output = set()
|
66
68
|
for root, dirs, files in walk_dir_with_gitignore(
|
67
69
|
directory,
|
@@ -73,9 +75,7 @@ class FindFilesTool(ToolBase):
|
|
73
75
|
dir_output.update(self._match_directories(root, dirs, pat))
|
74
76
|
else:
|
75
77
|
dir_output.update(self._match_files(root, files, pat))
|
76
|
-
dir_output.update(
|
77
|
-
self._match_dirs_without_slash(root, dirs, pat)
|
78
|
-
)
|
78
|
+
dir_output.update(self._match_dirs_without_slash(root, dirs, pat))
|
79
79
|
return dir_output
|
80
80
|
|
81
81
|
def _report_search(self, pattern, disp_path, depth_msg):
|
@@ -131,9 +131,10 @@ class FindFilesTool(ToolBase):
|
|
131
131
|
if os.path.isfile(directory):
|
132
132
|
dir_output = self._handle_path(directory, patterns)
|
133
133
|
elif os.path.isdir(directory):
|
134
|
-
dir_output = self._handle_directory_path(
|
134
|
+
dir_output = self._handle_directory_path(
|
135
|
+
directory, patterns, max_depth, include_gitignored
|
136
|
+
)
|
135
137
|
self._report_success(len(dir_output))
|
136
138
|
results.extend(self._format_output(directory, dir_output))
|
137
139
|
result = "\n".join(results)
|
138
140
|
return result
|
139
|
-
|
@@ -1,6 +1,7 @@
|
|
1
1
|
import re
|
2
2
|
from typing import List, Dict
|
3
3
|
|
4
|
+
|
4
5
|
def parse_java_outline(lines: List[str]) -> List[Dict]:
|
5
6
|
"""
|
6
7
|
Parses Java source code lines and extracts classes and methods with their signatures.
|
@@ -9,19 +10,23 @@ def parse_java_outline(lines: List[str]) -> List[Dict]:
|
|
9
10
|
outline = []
|
10
11
|
class_pattern = re.compile(r"\bclass\s+(\w+)(\s*<[^>]+>)?")
|
11
12
|
# Match methods with or without visibility modifiers (including package-private)
|
12
|
-
method_pattern = re.compile(
|
13
|
+
method_pattern = re.compile(
|
14
|
+
r"^(?:\s*(public|protected|private)\s+)?(?:static\s+)?([\w<>\[\]]+)\s+(\w+)\s*\(([^)]*)\)"
|
15
|
+
)
|
13
16
|
current_class = None
|
14
17
|
for idx, line in enumerate(lines, 1):
|
15
18
|
class_match = class_pattern.search(line)
|
16
19
|
if class_match:
|
17
20
|
class_name = class_match.group(1)
|
18
21
|
generics = class_match.group(2) or ""
|
19
|
-
outline.append(
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
22
|
+
outline.append(
|
23
|
+
{
|
24
|
+
"type": "class",
|
25
|
+
"name": class_name,
|
26
|
+
"generics": generics.strip("<>") if generics else None,
|
27
|
+
"line": idx,
|
28
|
+
}
|
29
|
+
)
|
25
30
|
current_class = class_name
|
26
31
|
else:
|
27
32
|
method_match = method_pattern.search(line)
|
@@ -29,12 +34,14 @@ def parse_java_outline(lines: List[str]) -> List[Dict]:
|
|
29
34
|
return_type = method_match.group(2)
|
30
35
|
method_name = method_match.group(3)
|
31
36
|
params = method_match.group(4)
|
32
|
-
outline.append(
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
37
|
+
outline.append(
|
38
|
+
{
|
39
|
+
"type": "method",
|
40
|
+
"class": current_class,
|
41
|
+
"name": method_name,
|
42
|
+
"return_type": return_type,
|
43
|
+
"parameters": params.strip(),
|
44
|
+
"line": idx,
|
45
|
+
}
|
46
|
+
)
|
40
47
|
return outline
|