janito 2.6.1__py3-none-any.whl → 2.8.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.
Files changed (118) hide show
  1. janito/__init__.py +6 -7
  2. janito/__main__.py +4 -5
  3. janito/_version.py +55 -58
  4. janito/agent/setup_agent.py +308 -241
  5. janito/agent/templates/profiles/{system_prompt_template_software developer.txt.j2 → system_prompt_template_Developer_with_Python_Tools.txt.j2} +43 -39
  6. janito/agent/templates/profiles/system_prompt_template_developer.txt.j2 +3 -12
  7. janito/cli/__init__.py +9 -10
  8. janito/cli/chat_mode/bindings.py +38 -38
  9. janito/cli/chat_mode/chat_entry.py +21 -23
  10. janito/cli/chat_mode/prompt_style.py +22 -25
  11. janito/cli/chat_mode/script_runner.py +158 -154
  12. janito/cli/chat_mode/session.py +80 -35
  13. janito/cli/chat_mode/session_profile_select.py +61 -52
  14. janito/cli/chat_mode/shell/commands/__init__.py +1 -5
  15. janito/cli/chat_mode/shell/commands/_priv_check.py +1 -0
  16. janito/cli/chat_mode/shell/commands/bang.py +10 -3
  17. janito/cli/chat_mode/shell/commands/conversation_restart.py +24 -7
  18. janito/cli/chat_mode/shell/commands/execute.py +22 -7
  19. janito/cli/chat_mode/shell/commands/help.py +4 -1
  20. janito/cli/chat_mode/shell/commands/model.py +13 -5
  21. janito/cli/chat_mode/shell/commands/privileges.py +21 -0
  22. janito/cli/chat_mode/shell/commands/prompt.py +0 -2
  23. janito/cli/chat_mode/shell/commands/read.py +22 -5
  24. janito/cli/chat_mode/shell/commands/tools.py +15 -4
  25. janito/cli/chat_mode/shell/commands/write.py +22 -5
  26. janito/cli/chat_mode/shell/input_history.py +3 -1
  27. janito/cli/chat_mode/shell/session/manager.py +0 -2
  28. janito/cli/chat_mode/toolbar.py +25 -19
  29. janito/cli/cli_commands/list_models.py +1 -1
  30. janito/cli/cli_commands/list_providers.py +1 -0
  31. janito/cli/cli_commands/list_tools.py +35 -7
  32. janito/cli/cli_commands/model_utils.py +5 -3
  33. janito/cli/cli_commands/show_config.py +12 -0
  34. janito/cli/cli_commands/show_system_prompt.py +23 -9
  35. janito/cli/config.py +0 -13
  36. janito/cli/core/getters.py +2 -0
  37. janito/cli/core/runner.py +25 -8
  38. janito/cli/core/setters.py +13 -76
  39. janito/cli/main_cli.py +9 -25
  40. janito/cli/prompt_core.py +19 -18
  41. janito/cli/prompt_setup.py +6 -3
  42. janito/cli/rich_terminal_reporter.py +19 -5
  43. janito/cli/single_shot_mode/handler.py +104 -95
  44. janito/cli/verbose_output.py +5 -1
  45. janito/config_manager.py +4 -0
  46. janito/drivers/azure_openai/driver.py +27 -30
  47. janito/drivers/driver_registry.py +27 -27
  48. janito/drivers/openai/driver.py +452 -436
  49. janito/formatting_token.py +12 -4
  50. janito/llm/agent.py +15 -6
  51. janito/llm/driver.py +1 -0
  52. janito/provider_registry.py +139 -178
  53. janito/providers/__init__.py +2 -0
  54. janito/providers/anthropic/model_info.py +40 -41
  55. janito/providers/anthropic/provider.py +75 -80
  56. janito/providers/azure_openai/provider.py +9 -4
  57. janito/providers/deepseek/provider.py +5 -4
  58. janito/providers/google/model_info.py +4 -2
  59. janito/providers/google/provider.py +11 -5
  60. janito/providers/groq/__init__.py +1 -0
  61. janito/providers/groq/model_info.py +46 -0
  62. janito/providers/groq/provider.py +76 -0
  63. janito/providers/moonshotai/__init__.py +1 -0
  64. janito/providers/moonshotai/model_info.py +15 -0
  65. janito/providers/moonshotai/provider.py +89 -0
  66. janito/providers/openai/provider.py +6 -7
  67. janito/tools/__init__.py +2 -0
  68. janito/tools/adapters/local/__init__.py +67 -66
  69. janito/tools/adapters/local/adapter.py +21 -4
  70. janito/tools/adapters/local/ask_user.py +1 -0
  71. janito/tools/adapters/local/copy_file.py +1 -0
  72. janito/tools/adapters/local/create_directory.py +1 -0
  73. janito/tools/adapters/local/create_file.py +1 -0
  74. janito/tools/adapters/local/delete_text_in_file.py +2 -1
  75. janito/tools/adapters/local/fetch_url.py +1 -0
  76. janito/tools/adapters/local/find_files.py +7 -6
  77. janito/tools/adapters/local/get_file_outline/core.py +1 -0
  78. janito/tools/adapters/local/get_file_outline/java_outline.py +22 -15
  79. janito/tools/adapters/local/get_file_outline/search_outline.py +1 -0
  80. janito/tools/adapters/local/move_file.py +4 -3
  81. janito/tools/adapters/local/open_html_in_browser.py +15 -5
  82. janito/tools/adapters/local/open_url.py +1 -0
  83. janito/tools/adapters/local/python_code_run.py +1 -0
  84. janito/tools/adapters/local/python_command_run.py +1 -0
  85. janito/tools/adapters/local/python_file_run.py +1 -0
  86. janito/tools/adapters/local/read_files.py +55 -40
  87. janito/tools/adapters/local/remove_directory.py +1 -0
  88. janito/tools/adapters/local/remove_file.py +1 -0
  89. janito/tools/adapters/local/replace_text_in_file.py +4 -3
  90. janito/tools/adapters/local/run_bash_command.py +1 -0
  91. janito/tools/adapters/local/run_powershell_command.py +1 -0
  92. janito/tools/adapters/local/search_text/core.py +18 -17
  93. janito/tools/adapters/local/search_text/match_lines.py +5 -5
  94. janito/tools/adapters/local/search_text/pattern_utils.py +1 -1
  95. janito/tools/adapters/local/search_text/traverse_directory.py +7 -7
  96. janito/tools/adapters/local/validate_file_syntax/core.py +1 -1
  97. janito/tools/adapters/local/validate_file_syntax/html_validator.py +8 -1
  98. janito/tools/disabled_tools.py +68 -0
  99. janito/tools/path_security.py +18 -11
  100. janito/tools/permissions.py +6 -0
  101. janito/tools/permissions_parse.py +4 -3
  102. janito/tools/tool_base.py +11 -5
  103. janito/tools/tool_use_tracker.py +1 -4
  104. janito/tools/tool_utils.py +1 -1
  105. janito/tools/tools_adapter.py +57 -25
  106. {janito-2.6.1.dist-info → janito-2.8.0.dist-info}/METADATA +411 -417
  107. janito-2.8.0.dist-info/RECORD +202 -0
  108. janito/cli/chat_mode/shell/commands/livelogs.py +0 -49
  109. janito/drivers/mistralai/driver.py +0 -41
  110. janito/providers/mistralai/model_info.py +0 -37
  111. janito/providers/mistralai/provider.py +0 -72
  112. janito/providers/provider_static_info.py +0 -18
  113. janito-2.6.1.dist-info/RECORD +0 -199
  114. /janito/agent/templates/profiles/{system_prompt_template_assistant.txt.j2 → system_prompt_template_model_conversation_without_tools_or_context.txt.j2} +0 -0
  115. {janito-2.6.1.dist-info → janito-2.8.0.dist-info}/WHEEL +0 -0
  116. {janito-2.6.1.dist-info → janito-2.8.0.dist-info}/entry_points.txt +0 -0
  117. {janito-2.6.1.dist-info → janito-2.8.0.dist-info}/licenses/LICENSE +0 -0
  118. {janito-2.6.1.dist-info → janito-2.8.0.dist-info}/top_level.txt +0 -0
@@ -1,80 +1,75 @@
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.tools import get_local_tools_adapter
6
- from janito.providers.registry import LLMProviderRegistry
7
-
8
- from .model_info import MODEL_SPECS
9
-
10
- from janito.llm.provider import LLMProvider
11
- from janito.llm.model import LLMModelInfo
12
- from janito.llm.auth import LLMAuthManager
13
- from janito.llm.driver_config import LLMDriverConfig
14
- from janito.tools import get_local_tools_adapter
15
- from janito.providers.registry import LLMProviderRegistry
16
- from .model_info import MODEL_SPECS
17
- from janito.drivers.openai.driver import OpenAIModelDriver
18
-
19
- class AnthropicProvider(LLMProvider):
20
- name = "anthropic"
21
- maintainer = "Needs maintainer"
22
- MODEL_SPECS = MODEL_SPECS
23
- DEFAULT_MODEL = "claude-3-7-sonnet-20250219"
24
-
25
- def __init__(
26
- self, auth_manager: LLMAuthManager = None, config: LLMDriverConfig = None
27
- ):
28
- self._tools_adapter = get_local_tools_adapter()
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=None)
33
- if not getattr(self._driver_config, 'model', None):
34
- self._driver_config.model = self.DEFAULT_MODEL
35
- if not self._driver_config.api_key:
36
- self._driver_config.api_key = self._api_key
37
- # Set the Anthropic OpenAI-compatible API endpoint
38
- self._driver_config.base_url = "https://api.anthropic.com/v1/"
39
- self.fill_missing_device_info(self._driver_config)
40
- self._driver = None # to be provided by factory/agent
41
-
42
- @property
43
- def driver(self) -> OpenAIModelDriver:
44
- if not self.available:
45
- raise ImportError(f"AnthropicProvider unavailable: {self.unavailable_reason}")
46
- return self._driver
47
-
48
- @property
49
- def available(self):
50
- return OpenAIModelDriver.available
51
-
52
- @property
53
- def unavailable_reason(self):
54
- return OpenAIModelDriver.unavailable_reason
55
-
56
- def create_driver(self):
57
- """
58
- Creates and returns a new OpenAIModelDriver instance configured for Anthropic API.
59
- """
60
- driver = OpenAIModelDriver(
61
- tools_adapter=self._tools_adapter, provider_name=self.name
62
- )
63
- driver.config = self._driver_config
64
- return driver
65
-
66
- @property
67
- def model_name(self):
68
- return self._driver_config.model
69
-
70
- @property
71
- def driver_config(self):
72
- """Public, read-only access to the provider's LLMDriverConfig object."""
73
- return self._driver_config
74
-
75
- def execute_tool(self, tool_name: str, event_bus, *args, **kwargs):
76
- self._tools_adapter.event_bus = event_bus
77
- return self._tools_adapter.execute_by_name(tool_name, *args, **kwargs)
78
-
79
-
80
- LLMProviderRegistry.register(AnthropicProvider.name, AnthropicProvider)
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.tools import get_local_tools_adapter
6
+ from janito.providers.registry import LLMProviderRegistry
7
+ from .model_info import MODEL_SPECS
8
+ from janito.drivers.openai.driver import OpenAIModelDriver
9
+
10
+
11
+ class AnthropicProvider(LLMProvider):
12
+ name = "anthropic"
13
+ NAME = "anthropic"
14
+ MAINTAINER = "Alberto Minetti <alberto.minetti@gmail.com>"
15
+ MODEL_SPECS = MODEL_SPECS
16
+ DEFAULT_MODEL = "claude-3-7-sonnet-20250219"
17
+
18
+ def __init__(
19
+ self, auth_manager: LLMAuthManager = None, config: LLMDriverConfig = None
20
+ ):
21
+ self._tools_adapter = get_local_tools_adapter()
22
+ self.auth_manager = auth_manager or LLMAuthManager()
23
+ self._api_key = self.auth_manager.get_credentials(type(self).NAME)
24
+ self._tools_adapter = get_local_tools_adapter()
25
+ self._driver_config = config or LLMDriverConfig(model=None)
26
+ if not getattr(self._driver_config, "model", None):
27
+ self._driver_config.model = self.DEFAULT_MODEL
28
+ if not self._driver_config.api_key:
29
+ self._driver_config.api_key = self._api_key
30
+ # Set the Anthropic OpenAI-compatible API endpoint
31
+ self._driver_config.base_url = "https://api.anthropic.com/v1/"
32
+ self.fill_missing_device_info(self._driver_config)
33
+ self._driver = None # to be provided by factory/agent
34
+
35
+ @property
36
+ def driver(self) -> OpenAIModelDriver:
37
+ if not self.available:
38
+ raise ImportError(
39
+ f"AnthropicProvider unavailable: {self.unavailable_reason}"
40
+ )
41
+ return self._driver
42
+
43
+ @property
44
+ def available(self):
45
+ return OpenAIModelDriver.available
46
+
47
+ @property
48
+ def unavailable_reason(self):
49
+ return OpenAIModelDriver.unavailable_reason
50
+
51
+ def create_driver(self):
52
+ """
53
+ Creates and returns a new OpenAIModelDriver instance configured for Anthropic API.
54
+ """
55
+ driver = OpenAIModelDriver(
56
+ tools_adapter=self._tools_adapter, provider_name=self.name
57
+ )
58
+ driver.config = self._driver_config
59
+ return driver
60
+
61
+ @property
62
+ def model_name(self):
63
+ return self._driver_config.model
64
+
65
+ @property
66
+ def driver_config(self):
67
+ """Public, read-only access to the provider's LLMDriverConfig object."""
68
+ return self._driver_config
69
+
70
+ def execute_tool(self, tool_name: str, event_bus, *args, **kwargs):
71
+ self._tools_adapter.event_bus = event_bus
72
+ return self._tools_adapter.execute_by_name(tool_name, *args, **kwargs)
73
+
74
+
75
+ LLMProviderRegistry.register(AnthropicProvider.NAME, AnthropicProvider)
@@ -16,7 +16,8 @@ maintainer = "João Pinto <lamego.pinto@gmail.com>"
16
16
 
17
17
  class AzureOpenAIProvider(LLMProvider):
18
18
  name = "azure_openai"
19
- maintainer = "João Pinto <lamego.pinto@gmail.com>"
19
+ NAME = "azure_openai"
20
+ MAINTAINER = "João Pinto <lamego.pinto@gmail.com>"
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).name)
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 {name: model_info.to_dict() for name, model_info in self.MODEL_SPECS.items()}
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.name, 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 DeepseekProvider(LLMProvider):
15
+ class DeepSeekProvider(LLMProvider):
16
16
  name = "deepseek"
17
- maintainer = "Needs maintainer"
17
+ NAME = "deepseek"
18
+ MAINTAINER = "João Pinto <lamego.pinto@gmail.com>"
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).name)
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(DeepseekProvider.name, DeepseekProvider)
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
- "gemini-2.5-pro": LLMModelInfo(
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={"description": "Google Gemini 2.5 Flash-Lite Preview (OpenAI-compatible endpoint)"},
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
- maintainer = "João Pinto <lamego.pinto@gmail.com>"
19
+ NAME = "google"
20
+ MAINTAINER = "João Pinto <lamego.pinto@gmail.com>"
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, 'model', None):
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 = "https://generativelanguage.googleapis.com/v1beta/openai/"
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(f"GoogleOpenAIProvider unavailable: {self.unavailable_reason}")
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.name, GoogleProvider)
89
+ LLMProviderRegistry.register(GoogleProvider.NAME, GoogleProvider)
@@ -0,0 +1 @@
1
+ from .provider import GroqProvider
@@ -0,0 +1,46 @@
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_parallel_tool_calls": True,
42
+ "supports_stream_options": False,
43
+ "supports_include_usage": False,
44
+ },
45
+ )
46
+ }
@@ -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)
@@ -0,0 +1 @@
1
+ # MoonshotAI provider package
@@ -0,0 +1,15 @@
1
+ from janito.llm.model import LLMModelInfo
2
+
3
+ MOONSHOTAI_MODEL_SPECS = {
4
+ "kimi-k2-0711-preview": LLMModelInfo(
5
+ name="kimi-k2-0711-preview",
6
+ context=128000,
7
+ max_input=100000,
8
+ max_cot="N/A",
9
+ max_response=4096,
10
+ thinking_supported=False,
11
+ default_temp=0.2,
12
+ open="moonshotai",
13
+ driver="OpenAIModelDriver",
14
+ ),
15
+ }
@@ -0,0 +1,89 @@
1
+ from janito.llm.provider import LLMProvider
2
+ from janito.llm.auth import LLMAuthManager
3
+ from janito.llm.driver_config import LLMDriverConfig
4
+ from janito.drivers.openai.driver import OpenAIModelDriver
5
+ from janito.tools import get_local_tools_adapter
6
+ from janito.providers.registry import LLMProviderRegistry
7
+ from .model_info import MOONSHOTAI_MODEL_SPECS
8
+
9
+
10
+ class MoonshotAIProvider(LLMProvider):
11
+ name = "moonshotai"
12
+ NAME = "moonshotai"
13
+ MAINTAINER = "João Pinto <lamego.pinto@gmail.com>"
14
+ MODEL_SPECS = MOONSHOTAI_MODEL_SPECS
15
+ DEFAULT_MODEL = "kimi-k2-0711-preview"
16
+
17
+ def __init__(
18
+ self, auth_manager: LLMAuthManager = None, config: LLMDriverConfig = None
19
+ ):
20
+ if not self.available:
21
+ self._tools_adapter = get_local_tools_adapter()
22
+ self._driver = None
23
+ else:
24
+ self.auth_manager = auth_manager or LLMAuthManager()
25
+ self._api_key = self.auth_manager.get_credentials(type(self).name)
26
+ self._tools_adapter = get_local_tools_adapter()
27
+ self._driver_config = config or LLMDriverConfig(model=None)
28
+ if not self._driver_config.model:
29
+ self._driver_config.model = self.DEFAULT_MODEL
30
+ if not self._driver_config.api_key:
31
+ self._driver_config.api_key = self._api_key
32
+ # Set only the correct token parameter for the model
33
+ model_name = self._driver_config.model
34
+ model_spec = self.MODEL_SPECS.get(model_name)
35
+ if hasattr(self._driver_config, "max_tokens"):
36
+ self._driver_config.max_tokens = None
37
+ if hasattr(self._driver_config, "max_completion_tokens"):
38
+ self._driver_config.max_completion_tokens = None
39
+ if model_spec:
40
+ if getattr(model_spec, "thinking_supported", False):
41
+ max_cot = getattr(model_spec, "max_cot", None)
42
+ if max_cot and max_cot != "N/A":
43
+ self._driver_config.max_completion_tokens = int(max_cot)
44
+ else:
45
+ max_response = getattr(model_spec, "max_response", None)
46
+ if max_response and max_response != "N/A":
47
+ self._driver_config.max_tokens = int(max_response)
48
+ self.fill_missing_device_info(self._driver_config)
49
+ self._driver = None
50
+ # Set MoonshotAI base_url
51
+ self._driver_config.base_url = "https://api.moonshot.ai/v1"
52
+
53
+ @property
54
+ def driver(self) -> OpenAIModelDriver:
55
+ if not self.available:
56
+ raise ImportError(
57
+ f"MoonshotAIProvider unavailable: {self.unavailable_reason}"
58
+ )
59
+ return self._driver
60
+
61
+ @property
62
+ def available(self):
63
+ return OpenAIModelDriver.available
64
+
65
+ @property
66
+ def unavailable_reason(self):
67
+ return OpenAIModelDriver.unavailable_reason
68
+
69
+ def create_driver(self):
70
+ driver = OpenAIModelDriver(
71
+ tools_adapter=self._tools_adapter, provider_name=self.name
72
+ )
73
+ driver.config = self._driver_config
74
+ return driver
75
+
76
+ @property
77
+ def model_name(self):
78
+ return self._driver_config.model
79
+
80
+ @property
81
+ def driver_config(self):
82
+ return self._driver_config
83
+
84
+ def execute_tool(self, tool_name: str, event_bus, *args, **kwargs):
85
+ self._tools_adapter.event_bus = event_bus
86
+ return self._tools_adapter.execute_by_name(tool_name, *args, **kwargs)
87
+
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
- maintainer = "João Pinto <lamego.pinto@gmail.com>"
17
+ NAME = "openai"
18
+ MAINTAINER = "João Pinto <lamego.pinto@gmail.com>"
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).name)
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.name
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.name, 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)