janito 1.14.2__py3-none-any.whl → 2.0.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 (282) hide show
  1. janito/__init__.py +6 -1
  2. janito/__main__.py +1 -1
  3. janito/agent/setup_agent.py +139 -0
  4. janito/agent/templates/profiles/{system_prompt_template_base.txt.j2 → system_prompt_template_main.txt.j2} +1 -1
  5. janito/cli/__init__.py +9 -0
  6. janito/cli/chat_mode/bindings.py +37 -0
  7. janito/cli/chat_mode/chat_entry.py +23 -0
  8. janito/cli/chat_mode/prompt_style.py +19 -0
  9. janito/cli/chat_mode/session.py +272 -0
  10. janito/{shell/prompt/completer.py → cli/chat_mode/shell/autocomplete.py} +7 -6
  11. janito/cli/chat_mode/shell/commands/__init__.py +55 -0
  12. janito/cli/chat_mode/shell/commands/base.py +9 -0
  13. janito/cli/chat_mode/shell/commands/clear.py +12 -0
  14. janito/{shell → cli/chat_mode/shell}/commands/conversation_restart.py +34 -30
  15. janito/cli/chat_mode/shell/commands/edit.py +25 -0
  16. janito/cli/chat_mode/shell/commands/help.py +16 -0
  17. janito/cli/chat_mode/shell/commands/history_view.py +93 -0
  18. janito/cli/chat_mode/shell/commands/lang.py +25 -0
  19. janito/cli/chat_mode/shell/commands/last.py +137 -0
  20. janito/cli/chat_mode/shell/commands/livelogs.py +49 -0
  21. janito/cli/chat_mode/shell/commands/multi.py +51 -0
  22. janito/cli/chat_mode/shell/commands/prompt.py +64 -0
  23. janito/cli/chat_mode/shell/commands/role.py +36 -0
  24. janito/cli/chat_mode/shell/commands/session.py +40 -0
  25. janito/{shell → cli/chat_mode/shell}/commands/session_control.py +2 -2
  26. janito/cli/chat_mode/shell/commands/termweb_log.py +92 -0
  27. janito/cli/chat_mode/shell/commands/tools.py +32 -0
  28. janito/{shell → cli/chat_mode/shell}/commands/utility.py +4 -7
  29. janito/{shell → cli/chat_mode/shell}/commands/verbose.py +5 -5
  30. janito/cli/chat_mode/shell/session/__init__.py +1 -0
  31. janito/{shell → cli/chat_mode/shell}/session/manager.py +9 -1
  32. janito/cli/chat_mode/toolbar.py +90 -0
  33. janito/cli/cli_commands/list_models.py +35 -0
  34. janito/cli/cli_commands/list_providers.py +9 -0
  35. janito/cli/cli_commands/list_tools.py +53 -0
  36. janito/cli/cli_commands/model_selection.py +50 -0
  37. janito/cli/cli_commands/model_utils.py +84 -0
  38. janito/cli/cli_commands/set_api_key.py +19 -0
  39. janito/cli/cli_commands/show_config.py +51 -0
  40. janito/cli/cli_commands/show_system_prompt.py +62 -0
  41. janito/cli/config.py +28 -0
  42. janito/cli/console.py +3 -0
  43. janito/cli/core/__init__.py +4 -0
  44. janito/cli/core/event_logger.py +59 -0
  45. janito/cli/core/getters.py +31 -0
  46. janito/cli/core/runner.py +141 -0
  47. janito/cli/core/setters.py +174 -0
  48. janito/cli/core/unsetters.py +54 -0
  49. janito/cli/main.py +8 -196
  50. janito/cli/main_cli.py +312 -0
  51. janito/cli/prompt_core.py +230 -0
  52. janito/cli/prompt_handler.py +6 -0
  53. janito/cli/rich_terminal_reporter.py +101 -0
  54. janito/cli/single_shot_mode/__init__.py +6 -0
  55. janito/cli/single_shot_mode/handler.py +137 -0
  56. janito/cli/termweb_starter.py +73 -24
  57. janito/cli/utils.py +25 -0
  58. janito/cli/verbose_output.py +196 -0
  59. janito/config.py +5 -0
  60. janito/config_manager.py +110 -0
  61. janito/conversation_history.py +30 -0
  62. janito/{agent/tools_utils/dir_walk_utils.py → dir_walk_utils.py} +3 -2
  63. janito/driver_events.py +98 -0
  64. janito/drivers/anthropic/driver.py +113 -0
  65. janito/drivers/azure_openai/driver.py +36 -0
  66. janito/drivers/driver_registry.py +33 -0
  67. janito/drivers/google_genai/driver.py +54 -0
  68. janito/drivers/google_genai/schema_generator.py +67 -0
  69. janito/drivers/mistralai/driver.py +41 -0
  70. janito/drivers/openai/driver.py +334 -0
  71. janito/event_bus/__init__.py +2 -0
  72. janito/event_bus/bus.py +68 -0
  73. janito/event_bus/event.py +15 -0
  74. janito/event_bus/handler.py +31 -0
  75. janito/event_bus/queue_bus.py +57 -0
  76. janito/exceptions.py +23 -0
  77. janito/formatting_token.py +54 -0
  78. janito/i18n/pt.py +1 -0
  79. janito/llm/__init__.py +5 -0
  80. janito/llm/agent.py +443 -0
  81. janito/llm/auth.py +62 -0
  82. janito/llm/driver.py +239 -0
  83. janito/llm/driver_config.py +34 -0
  84. janito/llm/driver_config_builder.py +34 -0
  85. janito/llm/driver_input.py +12 -0
  86. janito/llm/message_parts.py +60 -0
  87. janito/llm/model.py +38 -0
  88. janito/llm/provider.py +187 -0
  89. janito/perf_singleton.py +3 -0
  90. janito/performance_collector.py +167 -0
  91. janito/provider_config.py +98 -0
  92. janito/provider_registry.py +152 -0
  93. janito/providers/__init__.py +7 -0
  94. janito/providers/anthropic/model_info.py +22 -0
  95. janito/providers/anthropic/provider.py +65 -0
  96. janito/providers/azure_openai/model_info.py +15 -0
  97. janito/providers/azure_openai/provider.py +72 -0
  98. janito/providers/deepseek/__init__.py +1 -0
  99. janito/providers/deepseek/model_info.py +16 -0
  100. janito/providers/deepseek/provider.py +91 -0
  101. janito/providers/google/__init__.py +1 -0
  102. janito/providers/google/model_info.py +40 -0
  103. janito/providers/google/provider.py +69 -0
  104. janito/providers/mistralai/model_info.py +37 -0
  105. janito/providers/mistralai/provider.py +69 -0
  106. janito/providers/openai/__init__.py +1 -0
  107. janito/providers/openai/model_info.py +137 -0
  108. janito/providers/openai/provider.py +107 -0
  109. janito/providers/openai/schema_generator.py +63 -0
  110. janito/providers/provider_static_info.py +21 -0
  111. janito/providers/registry.py +26 -0
  112. janito/report_events.py +38 -0
  113. janito/termweb/app.py +1 -1
  114. janito/tools/__init__.py +16 -0
  115. janito/tools/adapters/__init__.py +1 -0
  116. janito/tools/adapters/local/__init__.py +54 -0
  117. janito/tools/adapters/local/adapter.py +92 -0
  118. janito/{agent/tools → tools/adapters/local}/ask_user.py +30 -13
  119. janito/tools/adapters/local/copy_file.py +84 -0
  120. janito/{agent/tools → tools/adapters/local}/create_directory.py +11 -10
  121. janito/tools/adapters/local/create_file.py +82 -0
  122. janito/tools/adapters/local/delete_text_in_file.py +136 -0
  123. janito/{agent/tools → tools/adapters/local}/fetch_url.py +18 -19
  124. janito/tools/adapters/local/find_files.py +140 -0
  125. janito/tools/adapters/local/get_file_outline/core.py +151 -0
  126. janito/{agent/tools → tools/adapters/local}/get_file_outline/python_outline.py +125 -0
  127. janito/tools/adapters/local/get_file_outline/python_outline_v2.py +156 -0
  128. janito/{agent/tools → tools/adapters/local}/get_file_outline/search_outline.py +12 -7
  129. janito/{agent/tools → tools/adapters/local}/move_file.py +13 -9
  130. janito/{agent/tools → tools/adapters/local}/open_url.py +7 -5
  131. janito/tools/adapters/local/python_code_run.py +165 -0
  132. janito/tools/adapters/local/python_command_run.py +163 -0
  133. janito/tools/adapters/local/python_file_run.py +162 -0
  134. janito/{agent/tools → tools/adapters/local}/remove_directory.py +15 -9
  135. janito/{agent/tools → tools/adapters/local}/remove_file.py +17 -14
  136. janito/{agent/tools → tools/adapters/local}/replace_text_in_file.py +27 -22
  137. janito/tools/adapters/local/run_bash_command.py +176 -0
  138. janito/tools/adapters/local/run_powershell_command.py +219 -0
  139. janito/{agent/tools → tools/adapters/local}/search_text/core.py +32 -12
  140. janito/{agent/tools → tools/adapters/local}/search_text/match_lines.py +13 -4
  141. janito/{agent/tools → tools/adapters/local}/search_text/pattern_utils.py +12 -4
  142. janito/{agent/tools → tools/adapters/local}/search_text/traverse_directory.py +15 -2
  143. janito/{agent/tools → tools/adapters/local}/validate_file_syntax/core.py +12 -11
  144. janito/{agent/tools → tools/adapters/local}/validate_file_syntax/css_validator.py +1 -1
  145. janito/{agent/tools → tools/adapters/local}/validate_file_syntax/html_validator.py +1 -1
  146. janito/{agent/tools → tools/adapters/local}/validate_file_syntax/js_validator.py +1 -1
  147. janito/{agent/tools → tools/adapters/local}/validate_file_syntax/json_validator.py +1 -1
  148. janito/{agent/tools → tools/adapters/local}/validate_file_syntax/markdown_validator.py +1 -1
  149. janito/{agent/tools → tools/adapters/local}/validate_file_syntax/ps1_validator.py +1 -1
  150. janito/{agent/tools → tools/adapters/local}/validate_file_syntax/python_validator.py +1 -1
  151. janito/{agent/tools → tools/adapters/local}/validate_file_syntax/xml_validator.py +1 -1
  152. janito/{agent/tools → tools/adapters/local}/validate_file_syntax/yaml_validator.py +1 -1
  153. janito/{agent/tools/get_lines.py → tools/adapters/local/view_file.py} +45 -27
  154. janito/tools/inspect_registry.py +17 -0
  155. janito/tools/tool_base.py +105 -0
  156. janito/tools/tool_events.py +58 -0
  157. janito/tools/tool_run_exception.py +12 -0
  158. janito/{agent → tools}/tool_use_tracker.py +2 -4
  159. janito/{agent/tools_utils/utils.py → tools/tool_utils.py} +18 -9
  160. janito/tools/tools_adapter.py +207 -0
  161. janito/tools/tools_schema.py +104 -0
  162. janito/utils.py +11 -0
  163. janito/version.py +4 -0
  164. janito-2.0.0.dist-info/METADATA +232 -0
  165. janito-2.0.0.dist-info/RECORD +180 -0
  166. janito/agent/__init__.py +0 -0
  167. janito/agent/api_exceptions.py +0 -4
  168. janito/agent/config.py +0 -147
  169. janito/agent/config_defaults.py +0 -12
  170. janito/agent/config_utils.py +0 -0
  171. janito/agent/content_handler.py +0 -0
  172. janito/agent/conversation.py +0 -238
  173. janito/agent/conversation_api.py +0 -306
  174. janito/agent/conversation_exceptions.py +0 -18
  175. janito/agent/conversation_tool_calls.py +0 -39
  176. janito/agent/conversation_ui.py +0 -17
  177. janito/agent/event.py +0 -24
  178. janito/agent/event_dispatcher.py +0 -24
  179. janito/agent/event_handler_protocol.py +0 -5
  180. janito/agent/event_system.py +0 -15
  181. janito/agent/llm_conversation_history.py +0 -82
  182. janito/agent/message_handler.py +0 -20
  183. janito/agent/message_handler_protocol.py +0 -5
  184. janito/agent/openai_client.py +0 -149
  185. janito/agent/openai_schema_generator.py +0 -187
  186. janito/agent/profile_manager.py +0 -96
  187. janito/agent/queued_message_handler.py +0 -50
  188. janito/agent/rich_live.py +0 -32
  189. janito/agent/rich_message_handler.py +0 -115
  190. janito/agent/runtime_config.py +0 -36
  191. janito/agent/test_handler_protocols.py +0 -47
  192. janito/agent/test_openai_schema_generator.py +0 -93
  193. janito/agent/tests/__init__.py +0 -1
  194. janito/agent/tool_base.py +0 -63
  195. janito/agent/tool_executor.py +0 -122
  196. janito/agent/tool_registry.py +0 -49
  197. janito/agent/tools/__init__.py +0 -47
  198. janito/agent/tools/create_file.py +0 -59
  199. janito/agent/tools/delete_text_in_file.py +0 -97
  200. janito/agent/tools/find_files.py +0 -106
  201. janito/agent/tools/get_file_outline/core.py +0 -81
  202. janito/agent/tools/present_choices.py +0 -64
  203. janito/agent/tools/python_command_runner.py +0 -201
  204. janito/agent/tools/python_file_runner.py +0 -199
  205. janito/agent/tools/python_stdin_runner.py +0 -208
  206. janito/agent/tools/replace_file.py +0 -72
  207. janito/agent/tools/run_bash_command.py +0 -218
  208. janito/agent/tools/run_powershell_command.py +0 -251
  209. janito/agent/tools_utils/__init__.py +0 -1
  210. janito/agent/tools_utils/action_type.py +0 -7
  211. janito/agent/tools_utils/test_gitignore_utils.py +0 -46
  212. janito/cli/_livereload_log_utils.py +0 -13
  213. janito/cli/_print_config.py +0 -96
  214. janito/cli/_termweb_log_utils.py +0 -17
  215. janito/cli/_utils.py +0 -9
  216. janito/cli/arg_parser.py +0 -272
  217. janito/cli/cli_main.py +0 -281
  218. janito/cli/config_commands.py +0 -211
  219. janito/cli/config_runner.py +0 -35
  220. janito/cli/formatting_runner.py +0 -12
  221. janito/cli/livereload_starter.py +0 -60
  222. janito/cli/logging_setup.py +0 -38
  223. janito/cli/one_shot.py +0 -80
  224. janito/livereload/app.py +0 -25
  225. janito/rich_utils.py +0 -59
  226. janito/shell/__init__.py +0 -0
  227. janito/shell/commands/__init__.py +0 -61
  228. janito/shell/commands/config.py +0 -22
  229. janito/shell/commands/edit.py +0 -24
  230. janito/shell/commands/history_view.py +0 -18
  231. janito/shell/commands/lang.py +0 -19
  232. janito/shell/commands/livelogs.py +0 -42
  233. janito/shell/commands/prompt.py +0 -62
  234. janito/shell/commands/termweb_log.py +0 -94
  235. janito/shell/commands/tools.py +0 -26
  236. janito/shell/commands/track.py +0 -36
  237. janito/shell/main.py +0 -326
  238. janito/shell/prompt/load_prompt.py +0 -57
  239. janito/shell/prompt/session_setup.py +0 -57
  240. janito/shell/session/config.py +0 -109
  241. janito/shell/session/history.py +0 -0
  242. janito/shell/ui/interactive.py +0 -226
  243. janito/termweb/static/editor.css +0 -158
  244. janito/termweb/static/editor.css.bak +0 -145
  245. janito/termweb/static/editor.html +0 -46
  246. janito/termweb/static/editor.html.bak +0 -46
  247. janito/termweb/static/editor.js +0 -265
  248. janito/termweb/static/editor.js.bak +0 -259
  249. janito/termweb/static/explorer.html.bak +0 -59
  250. janito/termweb/static/favicon.ico +0 -0
  251. janito/termweb/static/favicon.ico.bak +0 -0
  252. janito/termweb/static/index.html +0 -53
  253. janito/termweb/static/index.html.bak +0 -54
  254. janito/termweb/static/index.html.bak.bak +0 -175
  255. janito/termweb/static/landing.html.bak +0 -36
  256. janito/termweb/static/termicon.svg +0 -1
  257. janito/termweb/static/termweb.css +0 -214
  258. janito/termweb/static/termweb.css.bak +0 -237
  259. janito/termweb/static/termweb.js +0 -162
  260. janito/termweb/static/termweb.js.bak +0 -168
  261. janito/termweb/static/termweb.js.bak.bak +0 -157
  262. janito/termweb/static/termweb_quickopen.js +0 -135
  263. janito/termweb/static/termweb_quickopen.js.bak +0 -125
  264. janito/tests/test_rich_utils.py +0 -44
  265. janito/web/__init__.py +0 -0
  266. janito/web/__main__.py +0 -25
  267. janito/web/app.py +0 -145
  268. janito-1.14.2.dist-info/METADATA +0 -306
  269. janito-1.14.2.dist-info/RECORD +0 -162
  270. janito-1.14.2.dist-info/licenses/LICENSE +0 -21
  271. /janito/{shell → cli/chat_mode/shell}/input_history.py +0 -0
  272. /janito/{shell/commands/session.py → cli/chat_mode/shell/session/history.py} +0 -0
  273. /janito/{agent/tools_utils/formatting.py → formatting.py} +0 -0
  274. /janito/{agent/tools_utils/gitignore_utils.py → gitignore_utils.py} +0 -0
  275. /janito/{agent/platform_discovery.py → platform_discovery.py} +0 -0
  276. /janito/{agent/tools → tools/adapters/local}/get_file_outline/__init__.py +0 -0
  277. /janito/{agent/tools → tools/adapters/local}/get_file_outline/markdown_outline.py +0 -0
  278. /janito/{agent/tools → tools/adapters/local}/search_text/__init__.py +0 -0
  279. /janito/{agent/tools → tools/adapters/local}/validate_file_syntax/__init__.py +0 -0
  280. {janito-1.14.2.dist-info → janito-2.0.0.dist-info}/WHEEL +0 -0
  281. {janito-1.14.2.dist-info → janito-2.0.0.dist-info}/entry_points.txt +0 -0
  282. {janito-1.14.2.dist-info → janito-2.0.0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,91 @@
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 DeepseekProvider(LLMProvider):
16
+ name = "deepseek"
17
+ maintainer = "Needs maintainer"
18
+ MODEL_SPECS = MODEL_SPECS
19
+ DEFAULT_MODEL = "deepseek-chat" # Options: deepseek-chat, deepseek-coder
20
+
21
+ def __init__(
22
+ self, auth_manager: LLMAuthManager = None, config: LLMDriverConfig = None
23
+ ):
24
+ if not self.available:
25
+ self._driver = None
26
+ else:
27
+ self.auth_manager = auth_manager or LLMAuthManager()
28
+ self._api_key = self.auth_manager.get_credentials(type(self).name)
29
+ self._tools_adapter = get_local_tools_adapter()
30
+ self._driver_config = config or LLMDriverConfig(model=None)
31
+ if not self._driver_config.model:
32
+ self._driver_config.model = self.DEFAULT_MODEL
33
+ if not self._driver_config.api_key:
34
+ self._driver_config.api_key = self._api_key
35
+ # Set DeepSeek public endpoint as default base_url if not provided
36
+ if not getattr(self._driver_config, "base_url", None):
37
+ self._driver_config.base_url = "https://api.deepseek.com/v1"
38
+ self.fill_missing_device_info(self._driver_config)
39
+ self._driver = None # to be provided by factory/agent
40
+
41
+ @property
42
+ def driver(self) -> OpenAIModelDriver:
43
+ if not self.available:
44
+ raise ImportError(f"OpenAIProvider unavailable: {self.unavailable_reason}")
45
+ return self._driver
46
+
47
+ @property
48
+ def available(self):
49
+ return available
50
+
51
+ @property
52
+ def unavailable_reason(self):
53
+ return unavailable_reason
54
+
55
+ def create_driver(self):
56
+ """
57
+ Creates and returns a new OpenAIModelDriver instance with input/output queues.
58
+ """
59
+ driver = OpenAIModelDriver(
60
+ tools_adapter=self._tools_adapter, provider_name=self.name
61
+ )
62
+ driver.config = self._driver_config
63
+ # NOTE: The caller is responsible for calling driver.start() if background processing is needed.
64
+ return driver
65
+
66
+ def create_agent(self, tools_adapter=None, agent_name: str = None, **kwargs):
67
+ from janito.llm.agent import LLMAgent
68
+
69
+ # Always create a new driver with the passed-in tools_adapter
70
+ if tools_adapter is None:
71
+ tools_adapter = get_local_tools_adapter()
72
+ # Should use new-style driver construction via queues/factory (handled elsewhere)
73
+ raise NotImplementedError(
74
+ "create_agent must be constructed via new factory using input/output queues and config."
75
+ )
76
+
77
+ @property
78
+ def model_name(self):
79
+ return self._driver_config.model
80
+
81
+ @property
82
+ def driver_config(self):
83
+ """Public, read-only access to the provider's LLMDriverConfig object."""
84
+ return self._driver_config
85
+
86
+ def execute_tool(self, tool_name: str, event_bus, *args, **kwargs):
87
+ self._tools_adapter.event_bus = event_bus
88
+ return self._tools_adapter.execute_by_name(tool_name, *args, **kwargs)
89
+
90
+
91
+ LLMProviderRegistry.register(DeepseekProvider.name, DeepseekProvider)
@@ -0,0 +1 @@
1
+ from .provider import GoogleProvider
@@ -0,0 +1,40 @@
1
+ from janito.llm.model import LLMModelInfo
2
+
3
+ MODEL_SPECS = {
4
+ "gemini-2.5-pro-preview-05-06": LLMModelInfo(
5
+ name="gemini-2.5-pro-preview-05-06",
6
+ context=131072,
7
+ max_input=131072,
8
+ max_cot="N/A",
9
+ max_response=32768,
10
+ thinking_supported=True,
11
+ default_temp=0.2,
12
+ open="google",
13
+ driver="GoogleGenaiModelDriver",
14
+ other={"preview": True},
15
+ ),
16
+ "gemini-2.5-flash-preview-05-20": LLMModelInfo(
17
+ name="gemini-2.5-flash-preview-05-20",
18
+ context=1000000,
19
+ max_input=1000000,
20
+ max_cot="N/A",
21
+ max_response=65536,
22
+ thinking_supported=True,
23
+ default_temp=0.2,
24
+ open="google",
25
+ driver="GoogleGenaiModelDriver",
26
+ other={"preview": True, "flash": True},
27
+ ),
28
+ "gemini-2.5-flash-preview-04-17": LLMModelInfo(
29
+ name="gemini-2.5-flash-preview-04-17",
30
+ context=1000000,
31
+ max_input=1000000,
32
+ max_cot="N/A",
33
+ max_response=65536,
34
+ thinking_supported=True,
35
+ default_temp=0.2,
36
+ open="google",
37
+ driver="GoogleGenaiModelDriver",
38
+ other={"preview": True, "flash": True},
39
+ ),
40
+ }
@@ -0,0 +1,69 @@
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.google_genai.driver import GoogleGenaiModelDriver
6
+ from janito.tools.adapters.local.adapter import LocalToolsAdapter
7
+ from janito.providers.registry import LLMProviderRegistry
8
+
9
+ from .model_info import MODEL_SPECS
10
+
11
+ from janito.drivers.google_genai.driver import GoogleGenaiModelDriver
12
+
13
+ available = GoogleGenaiModelDriver.available
14
+ unavailable_reason = GoogleGenaiModelDriver.unavailable_reason
15
+ maintainer = "Needs maintainer"
16
+
17
+
18
+ class GoogleProvider(LLMProvider):
19
+ MODEL_SPECS = MODEL_SPECS
20
+ maintainer = "Needs maintainer"
21
+ """
22
+ Provider for Google LLMs via google-google.
23
+ Default model: 'gemini-2.5-pro-preview-05-06'.
24
+ """
25
+ name = "google"
26
+ DEFAULT_MODEL = "gemini-2.5-flash-preview-04-17"
27
+
28
+ def __init__(self, config: LLMDriverConfig = None):
29
+ if not self.available:
30
+ self._driver = None
31
+ return
32
+ self._auth_manager = LLMAuthManager()
33
+ self._api_key = self._auth_manager.get_credentials(type(self).name)
34
+ self._tools_adapter = LocalToolsAdapter()
35
+ self._info = config or LLMDriverConfig(model=None)
36
+ if not self._info.model:
37
+ self._info.model = self.DEFAULT_MODEL
38
+ if not self._info.api_key:
39
+ self._info.api_key = self._api_key
40
+ self.fill_missing_device_info(self._info)
41
+ self._driver = GoogleGenaiModelDriver(tools_adapter=self._tools_adapter)
42
+
43
+ @property
44
+ def driver(self) -> GoogleGenaiModelDriver:
45
+ if not self.available:
46
+ raise ImportError(f"GoogleProvider unavailable: {self.unavailable_reason}")
47
+ return self._driver
48
+
49
+ @property
50
+ def available(self):
51
+ return available
52
+
53
+ @property
54
+ def unavailable_reason(self):
55
+ return unavailable_reason
56
+
57
+ def create_agent(self, tools_adapter=None, agent_name: str = None, **kwargs):
58
+ from janito.llm.agent import LLMAgent
59
+
60
+ # Always create a new driver with the passed-in tools_adapter
61
+ driver = GoogleGenaiModelDriver(tools_adapter=tools_adapter)
62
+ return LLMAgent(self, tools_adapter, agent_name=agent_name, **kwargs)
63
+
64
+ def execute_tool(self, tool_name: str, event_bus, *args, **kwargs):
65
+ self._tools_adapter.event_bus = event_bus
66
+ return self._tools_adapter.execute_by_name(tool_name, *args, **kwargs)
67
+
68
+
69
+ LLMProviderRegistry.register(GoogleProvider.name, GoogleProvider)
@@ -0,0 +1,37 @@
1
+ from janito.llm.model import LLMModelInfo
2
+
3
+ MODEL_SPECS = {
4
+ "mistral-medium-latest": LLMModelInfo(
5
+ name="mistral-medium-latest",
6
+ context=32000,
7
+ max_input=32000,
8
+ max_cot="N/A",
9
+ max_response=8192,
10
+ thinking_supported=True,
11
+ default_temp=0.2,
12
+ open="mistralai",
13
+ driver="MistralAIModelDriver",
14
+ ),
15
+ "mistral-large-latest": LLMModelInfo(
16
+ name="mistral-large-latest",
17
+ context=64000,
18
+ max_input=64000,
19
+ max_cot="N/A",
20
+ max_response=16384,
21
+ thinking_supported=True,
22
+ default_temp=0.2,
23
+ open="mistralai",
24
+ driver="MistralAIModelDriver",
25
+ ),
26
+ "mistral-small-latest": LLMModelInfo(
27
+ name="mistral-small-latest",
28
+ context=16000,
29
+ max_input=16000,
30
+ max_cot="N/A",
31
+ max_response=4096,
32
+ thinking_supported=False,
33
+ default_temp=0.2,
34
+ open="mistralai",
35
+ driver="MistralAIModelDriver",
36
+ ),
37
+ }
@@ -0,0 +1,69 @@
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.mistralai.driver import MistralAIModelDriver
6
+ from janito.tools.adapters.local.adapter import LocalToolsAdapter
7
+ from janito.providers.registry import LLMProviderRegistry
8
+
9
+ from .model_info import MODEL_SPECS
10
+
11
+ from janito.drivers.mistralai.driver import MistralAIModelDriver
12
+
13
+ available = MistralAIModelDriver.available
14
+ unavailable_reason = MistralAIModelDriver.unavailable_reason
15
+
16
+
17
+ class MistralAIProvider(LLMProvider):
18
+ MODEL_SPECS = MODEL_SPECS
19
+ name = "mistralai"
20
+ maintainer = "Needs maintainer"
21
+
22
+ DEFAULT_MODEL = "mistral-medium-latest"
23
+
24
+ def __init__(
25
+ self, config: LLMDriverConfig = None, auth_manager: LLMAuthManager = None
26
+ ):
27
+ if not self.available:
28
+ self._driver = None
29
+ return
30
+ self.auth_manager = auth_manager or LLMAuthManager()
31
+ self._api_key = self.auth_manager.get_credentials(type(self).name)
32
+ self._tools_adapter = LocalToolsAdapter()
33
+ self._info = config or LLMDriverConfig(model=None)
34
+ if not self._info.model:
35
+ self._info.model = self.DEFAULT_MODEL
36
+ if not self._info.api_key:
37
+ self._info.api_key = self._api_key
38
+ self.fill_missing_device_info(self._info)
39
+ self._driver = MistralAIModelDriver(tools_adapter=self._tools_adapter)
40
+
41
+ @property
42
+ def driver(self):
43
+ if not self.available:
44
+ raise ImportError(
45
+ f"MistralAIProvider unavailable: {self.unavailable_reason}"
46
+ )
47
+ return self._driver
48
+
49
+ @property
50
+ def available(self):
51
+ return available
52
+
53
+ @property
54
+ def unavailable_reason(self):
55
+ return unavailable_reason
56
+
57
+ def create_agent(self, tools_adapter=None, agent_name: str = None, **kwargs):
58
+ from janito.llm.agent import LLMAgent
59
+
60
+ # Always create a new driver with the passed-in tools_adapter
61
+ driver = MistralAIModelDriver(tools_adapter=tools_adapter)
62
+ return LLMAgent(self, tools_adapter, agent_name=agent_name, **kwargs)
63
+
64
+ def execute_tool(self, tool_name: str, event_bus, *args, **kwargs):
65
+ self._tools_adapter.event_bus = event_bus
66
+ return self._tools_adapter.execute_by_name(tool_name, *args, **kwargs)
67
+
68
+
69
+ LLMProviderRegistry.register(MistralAIProvider.name, MistralAIProvider)
@@ -0,0 +1 @@
1
+ from .provider import OpenAIProvider
@@ -0,0 +1,137 @@
1
+ from janito.llm.model import LLMModelInfo
2
+
3
+ MODEL_SPECS = {
4
+ "gpt-3.5-turbo": LLMModelInfo(
5
+ name="gpt-3.5-turbo",
6
+ context=16385,
7
+ max_input=12289,
8
+ max_cot="N/A",
9
+ max_response=4096,
10
+ thinking_supported=False,
11
+ default_temp=0.2,
12
+ open="openai",
13
+ driver="OpenAIModelDriver",
14
+ ),
15
+ "gpt-4.1": LLMModelInfo(
16
+ name="gpt-4.1",
17
+ context=1047576,
18
+ max_input=1014808,
19
+ max_cot="N/A",
20
+ max_response=32768,
21
+ thinking_supported=False,
22
+ default_temp=0.2,
23
+ open="openai",
24
+ driver="OpenAIModelDriver",
25
+ ),
26
+ "gpt-4.1-mini": LLMModelInfo(
27
+ name="gpt-4.1-mini",
28
+ context=1047576,
29
+ max_input=1014808,
30
+ max_cot="N/A",
31
+ max_response=32768,
32
+ thinking_supported=False,
33
+ default_temp=0.2,
34
+ open="openai",
35
+ driver="OpenAIModelDriver",
36
+ ),
37
+ "gpt-4.1-nano": LLMModelInfo(
38
+ name="gpt-4.1-nano",
39
+ context=1047576,
40
+ max_input=1014808,
41
+ max_cot="N/A",
42
+ max_response=32768,
43
+ thinking_supported=False,
44
+ default_temp=0.2,
45
+ open="openai",
46
+ driver="OpenAIModelDriver",
47
+ ),
48
+ "gpt-4-turbo": LLMModelInfo(
49
+ name="gpt-4-turbo",
50
+ context=128000,
51
+ max_input="N/A",
52
+ max_cot="N/A",
53
+ max_response="N/A",
54
+ thinking_supported=False,
55
+ default_temp=0.2,
56
+ open="openai",
57
+ driver="OpenAIModelDriver",
58
+ ),
59
+ "gpt-4o": LLMModelInfo(
60
+ name="gpt-4o",
61
+ context=128000,
62
+ max_input=123904,
63
+ max_cot="N/A",
64
+ max_response=4096,
65
+ thinking_supported=False,
66
+ default_temp=0.2,
67
+ open="openai",
68
+ driver="OpenAIModelDriver",
69
+ ),
70
+ "gpt-4o-mini": LLMModelInfo(
71
+ name="gpt-4o-mini",
72
+ context=128000,
73
+ max_input=111616,
74
+ max_cot="N/A",
75
+ max_response=16384,
76
+ thinking_supported=False,
77
+ default_temp=0.2,
78
+ open="openai",
79
+ driver="OpenAIModelDriver",
80
+ ),
81
+ "o3-mini": LLMModelInfo(
82
+ name="o3-mini",
83
+ context=200000,
84
+ max_input=100000,
85
+ max_cot="N/A",
86
+ max_response=100000,
87
+ thinking_supported=True,
88
+ default_temp=1.0,
89
+ open="openai",
90
+ driver="OpenAIModelDriver",
91
+ ),
92
+ "o3": LLMModelInfo(
93
+ name="o3",
94
+ context=200000,
95
+ max_input=100000,
96
+ max_cot="N/A",
97
+ max_response=100000,
98
+ thinking_supported=True,
99
+ default_temp=1.0,
100
+ open="openai",
101
+ driver="OpenAIModelDriver",
102
+ ),
103
+ "o4-mini": LLMModelInfo(
104
+ name="o4-mini",
105
+ context=200000,
106
+ max_input=100000,
107
+ max_cot="N/A",
108
+ max_response=100000,
109
+ thinking_supported=True,
110
+ default_temp=1.0,
111
+ open="openai",
112
+ driver="OpenAIModelDriver",
113
+ ),
114
+ "o4-mini-high": LLMModelInfo(
115
+ name="o4-mini-high",
116
+ context=200000,
117
+ max_input=100000,
118
+ max_cot="N/A",
119
+ max_response=100000,
120
+ thinking_supported=True,
121
+ default_temp=0.2,
122
+ open="openai",
123
+ driver="OpenAIModelDriver",
124
+ ),
125
+ # duplicated gpt-4-turbo with minimal properties for distinction
126
+ "gpt-4-turbo-alt": LLMModelInfo(
127
+ name="gpt-4-turbo",
128
+ context=128000,
129
+ max_input="N/A",
130
+ max_cot="N/A",
131
+ max_response="N/A",
132
+ thinking_supported=False,
133
+ default_temp=0.2,
134
+ open="openai",
135
+ driver="OpenAIModelDriver",
136
+ ),
137
+ }
@@ -0,0 +1,107 @@
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 OpenAIProvider(LLMProvider):
16
+ name = "openai"
17
+ maintainer = "João Pinto <lamego.pinto@gmail.com>"
18
+ MODEL_SPECS = MODEL_SPECS
19
+ DEFAULT_MODEL = (
20
+ "gpt-4.1" # Options: gpt-4.1, gpt-4o, o3-mini, o4-mini, o4-mini-high
21
+ )
22
+
23
+ def __init__(
24
+ self, auth_manager: LLMAuthManager = None, config: LLMDriverConfig = None
25
+ ):
26
+ if not self.available:
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=None)
33
+ if not self._driver_config.model:
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 only the correct token parameter for the model
38
+ model_name = self._driver_config.model
39
+ model_spec = self.MODEL_SPECS.get(model_name)
40
+ # Remove both to avoid stale values
41
+ if hasattr(self._driver_config, "max_tokens"):
42
+ self._driver_config.max_tokens = None
43
+ if hasattr(self._driver_config, "max_completion_tokens"):
44
+ self._driver_config.max_completion_tokens = None
45
+ if model_spec:
46
+ if getattr(model_spec, "thinking_supported", False):
47
+ max_cot = getattr(model_spec, "max_cot", None)
48
+ if max_cot and max_cot != "N/A":
49
+ self._driver_config.max_completion_tokens = int(max_cot)
50
+ else:
51
+ max_response = getattr(model_spec, "max_response", None)
52
+ if max_response and max_response != "N/A":
53
+ self._driver_config.max_tokens = int(max_response)
54
+ self.fill_missing_device_info(self._driver_config)
55
+ self._driver = None # to be provided by factory/agent
56
+
57
+ @property
58
+ def driver(self) -> OpenAIModelDriver:
59
+ if not self.available:
60
+ raise ImportError(f"OpenAIProvider unavailable: {self.unavailable_reason}")
61
+ return self._driver
62
+
63
+ @property
64
+ def available(self):
65
+ return available
66
+
67
+ @property
68
+ def unavailable_reason(self):
69
+ return unavailable_reason
70
+
71
+ def create_driver(self):
72
+ """
73
+ Creates and returns a new OpenAIModelDriver instance with input/output queues.
74
+ """
75
+ driver = OpenAIModelDriver(
76
+ tools_adapter=self._tools_adapter, provider_name=self.name
77
+ )
78
+ driver.config = self._driver_config
79
+ # NOTE: The caller is responsible for calling driver.start() if background processing is needed.
80
+ return driver
81
+
82
+ def create_agent(self, tools_adapter=None, agent_name: str = None, **kwargs):
83
+ from janito.llm.agent import LLMAgent
84
+
85
+ # Always create a new driver with the passed-in tools_adapter
86
+ if tools_adapter is None:
87
+ tools_adapter = get_local_tools_adapter()
88
+ # Should use new-style driver construction via queues/factory (handled elsewhere)
89
+ raise NotImplementedError(
90
+ "create_agent must be constructed via new factory using input/output queues and config."
91
+ )
92
+
93
+ @property
94
+ def model_name(self):
95
+ return self._driver_config.model
96
+
97
+ @property
98
+ def driver_config(self):
99
+ """Public, read-only access to the provider's LLMDriverConfig object."""
100
+ return self._driver_config
101
+
102
+ def execute_tool(self, tool_name: str, event_bus, *args, **kwargs):
103
+ self._tools_adapter.event_bus = event_bus
104
+ return self._tools_adapter.execute_by_name(tool_name, *args, **kwargs)
105
+
106
+
107
+ LLMProviderRegistry.register(OpenAIProvider.name, OpenAIProvider)
@@ -0,0 +1,63 @@
1
+ import inspect
2
+ import typing
3
+ from collections import OrderedDict
4
+ from typing import List
5
+ from janito.tools.tools_schema import ToolSchemaBase
6
+
7
+
8
+ class OpenAISchemaGenerator(ToolSchemaBase):
9
+ PYTHON_TYPE_TO_JSON = {
10
+ str: "string",
11
+ int: "integer",
12
+ float: "number",
13
+ bool: "boolean",
14
+ list: "array",
15
+ dict: "object",
16
+ }
17
+
18
+ def type_to_json_schema(self, annotation):
19
+ if hasattr(annotation, "__origin__"):
20
+ if annotation.__origin__ is list or annotation.__origin__ is typing.List:
21
+ return {
22
+ "type": "array",
23
+ "items": self.type_to_json_schema(annotation.__args__[0]),
24
+ }
25
+ if annotation.__origin__ is dict or annotation.__origin__ is typing.Dict:
26
+ return {"type": "object"}
27
+ return {"type": self.PYTHON_TYPE_TO_JSON.get(annotation, "string")}
28
+
29
+ def generate_schema(self, tool_class):
30
+ # DEBUG: Print class and .name for trace
31
+ func, tool_name, sig, summary, param_descs, return_desc, description = (
32
+ self.validate_tool_class(tool_class)
33
+ )
34
+ properties = OrderedDict()
35
+ required = []
36
+ # Removed tool_call_reason from properties and required
37
+ for name, param in sig.parameters.items():
38
+ if name == "self":
39
+ continue
40
+ annotation = param.annotation
41
+ pdesc = param_descs.get(name, "")
42
+ schema = self.type_to_json_schema(annotation)
43
+ schema["description"] = pdesc
44
+ properties[name] = schema
45
+ if param.default == inspect._empty:
46
+ required.append(name)
47
+ return {
48
+ "name": tool_name,
49
+ "description": description,
50
+ "parameters": {
51
+ "type": "object",
52
+ "properties": properties,
53
+ "required": required,
54
+ },
55
+ }
56
+
57
+
58
+ def generate_tool_schemas(tool_classes: List[type]):
59
+ generator = OpenAISchemaGenerator()
60
+ return [
61
+ {"type": "function", "function": generator.generate_schema(tool_class)}
62
+ for tool_class in tool_classes
63
+ ]
@@ -0,0 +1,21 @@
1
+ # Provider static metadata registry for listing purposes (name, maintainer, and future fields)
2
+ STATIC_PROVIDER_METADATA = {
3
+ "openai": {
4
+ "maintainer": "João Pinto <lamego.pinto@gmail.com>",
5
+ },
6
+ "azure_openai": {
7
+ "maintainer": "João Pinto <lamego.pinto@gmail.com>",
8
+ },
9
+ "google": {
10
+ "maintainer": "Needs maintainer",
11
+ },
12
+ "mistralai": {
13
+ "maintainer": "Needs maintainer",
14
+ },
15
+ "anthropic": {
16
+ "maintainer": "Needs maintainer",
17
+ },
18
+ "deepseek": {
19
+ "maintainer": "João Pinto <lamego.pinto@gmail.com>",
20
+ },
21
+ }
@@ -0,0 +1,26 @@
1
+ from typing import Type, Dict
2
+ from janito.llm.provider import LLMProvider
3
+
4
+
5
+ class LLMProviderRegistry:
6
+ """
7
+ Registry for LLM provider classes.
8
+ """
9
+
10
+ _providers: Dict[str, Type[LLMProvider]] = {}
11
+
12
+ @classmethod
13
+ def register(cls, name: str, provider_cls: Type[LLMProvider]):
14
+ if name in cls._providers:
15
+ raise ValueError(f"Provider '{name}' is already registered.")
16
+ cls._providers[name] = provider_cls
17
+
18
+ @classmethod
19
+ def get(cls, name: str) -> Type[LLMProvider]:
20
+ if name not in cls._providers:
21
+ raise KeyError(f"Provider '{name}' is not registered.")
22
+ return cls._providers[name]
23
+
24
+ @classmethod
25
+ def list_providers(cls):
26
+ return list(cls._providers.keys())