janito 2.19.1__py3-none-any.whl → 2.20.1__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.
@@ -2,8 +2,8 @@
2
2
  CLI Command: List models for the specified/current provider
3
3
  """
4
4
 
5
- from janito.cli.cli_commands.model_utils import _print_models_table
6
5
  import sys
6
+ from janito.cli.cli_commands.model_utils import _print_models_table
7
7
 
8
8
  _provider_instance = None
9
9
 
@@ -36,8 +36,6 @@ def handle_list_models(args, provider_instance):
36
36
 
37
37
  for m in models:
38
38
  table.add_row(str(m))
39
-
40
- import sys
41
39
  if sys.stdout.isatty():
42
40
  shared_console.print(table)
43
41
  else:
@@ -64,14 +64,20 @@ class OpenAIModelDriver(LLMDriver):
64
64
  if config.model:
65
65
  api_kwargs["model"] = config.model
66
66
  # Prefer max_completion_tokens if present, else fallback to max_tokens (for backward compatibility)
67
- if (
68
- hasattr(config, "max_completion_tokens")
69
- and config.max_completion_tokens is not None
70
- ):
71
- api_kwargs["max_completion_tokens"] = int(config.max_completion_tokens)
67
+ # Skip max_completion_tokens for Mistral as their API doesn't support it
68
+ is_mistral = config.base_url and "mistral.ai" in str(config.base_url)
69
+ if not is_mistral:
70
+ if (
71
+ hasattr(config, "max_completion_tokens")
72
+ and config.max_completion_tokens is not None
73
+ ):
74
+ api_kwargs["max_completion_tokens"] = int(config.max_completion_tokens)
75
+ elif hasattr(config, "max_tokens") and config.max_tokens is not None:
76
+ # For models that do not support 'max_tokens', map to 'max_completion_tokens'
77
+ api_kwargs["max_completion_tokens"] = int(config.max_tokens)
72
78
  elif hasattr(config, "max_tokens") and config.max_tokens is not None:
73
- # For models that do not support 'max_tokens', map to 'max_completion_tokens'
74
- api_kwargs["max_completion_tokens"] = int(config.max_tokens)
79
+ # For Mistral, use max_tokens directly
80
+ api_kwargs["max_tokens"] = int(config.max_tokens)
75
81
  for p in (
76
82
  "temperature",
77
83
  "top_p",
janito/llm/agent.py CHANGED
@@ -229,6 +229,12 @@ class LLMAgent:
229
229
  print("[agent] [INFO] Handling ResponseReceived event.")
230
230
  from janito.llm.message_parts import FunctionCallMessagePart
231
231
 
232
+ # Skip tool processing if no tools adapter is available
233
+ if self.tools_adapter is None:
234
+ if getattr(self, "verbose_agent", False):
235
+ print("[agent] [DEBUG] No tools adapter available, skipping tool calls")
236
+ return False
237
+
232
238
  tool_calls = []
233
239
  tool_results = []
234
240
  for part in event.parts:
@@ -8,3 +8,4 @@ import janito.providers.moonshotai.provider
8
8
  import janito.providers.alibaba.provider
9
9
  import janito.providers.zai.provider
10
10
  import janito.providers.cerebras.provider
11
+ import janito.providers.mistral.provider
@@ -0,0 +1 @@
1
+ # Codestral provider module
@@ -0,0 +1,81 @@
1
+ from janito.llm.model import LLMModelInfo
2
+
3
+ MODEL_SPECS = {
4
+ "codestral-latest": LLMModelInfo(
5
+ name="codestral-latest",
6
+ context=256000,
7
+ max_input=250000,
8
+ max_cot="N/A",
9
+ max_response=4096,
10
+ thinking_supported=False,
11
+ default_temp=0.2,
12
+ open="mistral",
13
+ driver="OpenAIModelDriver",
14
+ ),
15
+ "codestral-2405": LLMModelInfo(
16
+ name="codestral-2405",
17
+ context=256000,
18
+ max_input=250000,
19
+ max_cot="N/A",
20
+ max_response=4096,
21
+ thinking_supported=False,
22
+ default_temp=0.2,
23
+ open="mistral",
24
+ driver="OpenAIModelDriver",
25
+ ),
26
+ "mistral-small-latest": LLMModelInfo(
27
+ name="mistral-small-latest",
28
+ context=32000,
29
+ max_input=28000,
30
+ max_cot="N/A",
31
+ max_response=4096,
32
+ thinking_supported=False,
33
+ default_temp=0.7,
34
+ open="mistral",
35
+ driver="OpenAIModelDriver",
36
+ ),
37
+ "mistral-medium-latest": LLMModelInfo(
38
+ name="mistral-medium-latest",
39
+ context=32000,
40
+ max_input=28000,
41
+ max_cot="N/A",
42
+ max_response=4096,
43
+ thinking_supported=False,
44
+ default_temp=0.7,
45
+ open="mistral",
46
+ driver="OpenAIModelDriver",
47
+ ),
48
+ "mistral-large-latest": LLMModelInfo(
49
+ name="mistral-large-latest",
50
+ context=128000,
51
+ max_input=120000,
52
+ max_cot="N/A",
53
+ max_response=4096,
54
+ thinking_supported=False,
55
+ default_temp=0.7,
56
+ open="mistral",
57
+ driver="OpenAIModelDriver",
58
+ ),
59
+ "devstral-small-latest": LLMModelInfo(
60
+ name="devstral-small-latest",
61
+ context=128000,
62
+ max_input=120000,
63
+ max_cot="N/A",
64
+ max_response=4096,
65
+ thinking_supported=False,
66
+ default_temp=0.7,
67
+ open="mistral",
68
+ driver="OpenAIModelDriver",
69
+ ),
70
+ "devstral-medium-latest": LLMModelInfo(
71
+ name="devstral-medium-latest",
72
+ context=128000,
73
+ max_input=120000,
74
+ max_cot="N/A",
75
+ max_response=4096,
76
+ thinking_supported=False,
77
+ default_temp=0.7,
78
+ open="mistral",
79
+ driver="OpenAIModelDriver",
80
+ ),
81
+ }
@@ -0,0 +1,124 @@
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
+
10
+ available = OpenAIModelDriver.available
11
+ unavailable_reason = OpenAIModelDriver.unavailable_reason
12
+
13
+
14
+ class MistralProvider(LLMProvider):
15
+ name = "mistral"
16
+ NAME = "mistral"
17
+ MAINTAINER = "João Pinto <janito@ikignosis.org>"
18
+ MODEL_SPECS = MODEL_SPECS
19
+ DEFAULT_MODEL = "mistral-large-latest"
20
+
21
+ def __init__(
22
+ self, auth_manager: LLMAuthManager = None, config: LLMDriverConfig = None
23
+ ):
24
+ self._tools_adapter = get_local_tools_adapter()
25
+ self._driver = None
26
+
27
+ if not self.available:
28
+ return
29
+
30
+ self._initialize_config(auth_manager, config)
31
+ self._setup_model_config()
32
+
33
+ def _initialize_config(self, auth_manager, config):
34
+ """Initialize configuration and API key."""
35
+ self.auth_manager = auth_manager or LLMAuthManager()
36
+ self._api_key = self.auth_manager.get_credentials(type(self).NAME)
37
+ if not self._api_key:
38
+ from janito.llm.auth_utils import handle_missing_api_key
39
+
40
+ handle_missing_api_key(self.name, "MISTRAL_API_KEY")
41
+
42
+ self._driver_config = config or LLMDriverConfig(model=None)
43
+ if not self._driver_config.model:
44
+ self._driver_config.model = self.DEFAULT_MODEL
45
+ if not self._driver_config.api_key:
46
+ self._driver_config.api_key = self._api_key
47
+
48
+ # Set Mistral-specific base URL
49
+ self._driver_config.base_url = "https://api.mistral.ai/v1"
50
+
51
+ def _setup_model_config(self):
52
+ """Configure token limits based on model specifications."""
53
+ model_name = self._driver_config.model
54
+ model_spec = self.MODEL_SPECS.get(model_name)
55
+
56
+ # Reset token parameters
57
+ if hasattr(self._driver_config, "max_tokens"):
58
+ self._driver_config.max_tokens = None
59
+ if hasattr(self._driver_config, "max_completion_tokens"):
60
+ self._driver_config.max_completion_tokens = None
61
+
62
+ if model_spec:
63
+ if getattr(model_spec, "thinking_supported", False):
64
+ max_cot = getattr(model_spec, "max_cot", None)
65
+ if max_cot and max_cot != "N/A":
66
+ self._driver_config.max_tokens = int(max_cot)
67
+ else:
68
+ max_response = getattr(model_spec, "max_response", None)
69
+ if max_response and max_response != "N/A":
70
+ self._driver_config.max_tokens = int(max_response)
71
+
72
+ self.fill_missing_device_info(self._driver_config)
73
+
74
+ @property
75
+ def driver(self) -> OpenAIModelDriver:
76
+ if not self.available:
77
+ raise ImportError(f"MistralProvider unavailable: {self.unavailable_reason}")
78
+ return self._driver
79
+
80
+ @property
81
+ def available(self):
82
+ return available
83
+
84
+ @property
85
+ def unavailable_reason(self):
86
+ return unavailable_reason
87
+
88
+ def create_driver(self):
89
+ """
90
+ Creates and returns a new OpenAIModelDriver instance with input/output queues.
91
+ """
92
+ driver = OpenAIModelDriver(
93
+ tools_adapter=self._tools_adapter, provider_name=self.NAME
94
+ )
95
+ driver.config = self._driver_config
96
+ # NOTE: The caller is responsible for calling driver.start() if background processing is needed.
97
+ return driver
98
+
99
+ def create_agent(self, tools_adapter=None, agent_name: str = None, **kwargs):
100
+ from janito.llm.agent import LLMAgent
101
+
102
+ # Always create a new driver with the passed-in tools_adapter
103
+ if tools_adapter is None:
104
+ tools_adapter = get_local_tools_adapter()
105
+ # Should use new-style driver construction via queues/factory (handled elsewhere)
106
+ raise NotImplementedError(
107
+ "create_agent must be constructed via new factory using input/output queues and config."
108
+ )
109
+
110
+ @property
111
+ def model_name(self):
112
+ return self._driver_config.model
113
+
114
+ @property
115
+ def driver_config(self):
116
+ """Public, read-only access to the provider's LLMDriverConfig object."""
117
+ return self._driver_config
118
+
119
+ def execute_tool(self, tool_name: str, event_bus, *args, **kwargs):
120
+ self._tools_adapter.event_bus = event_bus
121
+ return self._tools_adapter.execute_by_name(tool_name, *args, **kwargs)
122
+
123
+
124
+ LLMProviderRegistry.register(MistralProvider.NAME, MistralProvider)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: janito
3
- Version: 2.19.1
3
+ Version: 2.20.1
4
4
  Summary: A new Python package called janito.
5
5
  Author-email: João Pinto <janito@ikignosis.org>
6
6
  Project-URL: Homepage, https://github.com/ikignosis/janito
@@ -74,7 +74,7 @@ janito/cli/chat_mode/shell/session/history.py,sha256=tYav6GgjAZkvWhlI_rfG6OArNqW
74
74
  janito/cli/chat_mode/shell/session/manager.py,sha256=MwD9reHsRaly0CyRB-S1JJ0wPKz2g8Xdj2VvlU35Hgc,1001
75
75
  janito/cli/cli_commands/list_config.py,sha256=oiQEGaGPjwjG-PrOcakpNMbbqISTsBEs7rkGH3ceQsI,1179
76
76
  janito/cli/cli_commands/list_drivers.py,sha256=r2ENykUcvf_9XYp6LHd3RvLXGXyVUA6oe_Pr0dyv92I,5124
77
- janito/cli/cli_commands/list_models.py,sha256=DAXH9CT3Q4krJ_NlrXseCGsc4WECYeJSGX6z0ks8_uA,1661
77
+ janito/cli/cli_commands/list_models.py,sha256=7Cyjfwht77nm6_h1DRY2A-Nkkm1Kiy0e339EYglVqEI,1619
78
78
  janito/cli/cli_commands/list_profiles.py,sha256=9-HV2EbtP2AdubbMoakjbu7Oq4Ss9UDyO7Eb6CC52wI,2681
79
79
  janito/cli/cli_commands/list_providers.py,sha256=3ywm1Ohv7yVqV1E9hB-3Jz8BwzhyCScKxffq6iDI4nA,391
80
80
  janito/cli/cli_commands/list_providers_region.py,sha256=qrMj_gtgEMty8UH0P_O5SgWCVJ9ZKxGUp_GdsE4_EH4,2548
@@ -100,7 +100,7 @@ janito/drivers/openai_responses.bak.zip,sha256=E43eDCHGa2tCtdjzj_pMnWDdnsOZzj8BJ
100
100
  janito/drivers/azure_openai/driver.py,sha256=L2rQOl1d0BHaDChHLtZszAeuWNoyYIgwuYuahE1qJps,4152
101
101
  janito/drivers/cerebras/__init__.py,sha256=yGkKANI4xKT_2j6x1-RBJhmaRzEGyt1DFaBSLt7EtYU,25
102
102
  janito/drivers/openai/README.md,sha256=bgPdaYX0pyotCoJ9t3cJbYM-teQ_YM1DAFEKLCMP32Q,666
103
- janito/drivers/openai/driver.py,sha256=ITwonFiux8pVIlCuD9jy1og3sGc-rHH2_LQFRHZvBRc,19152
103
+ janito/drivers/openai/driver.py,sha256=NbR_1Btr7QpJjNzJ3CxJa1-Kfw17lImZFU9fyKDLSRo,19567
104
104
  janito/drivers/zai/__init__.py,sha256=rleES3ZJEslJ8M02TdTPyxHKXxA4-e2fDJa6yjuzY8s,22
105
105
  janito/drivers/zai/driver.py,sha256=uOR7VFEMjd7Dw_zSFO1SN5SgBCIG8b4CEzRMIUXBgUQ,18859
106
106
  janito/event_bus/__init__.py,sha256=VG6GOhKMBh0O_92D-zW8a3YitJPKDajGgPiFezTXlNE,77
@@ -114,7 +114,7 @@ janito/i18n/messages.py,sha256=fBuwOTFoygyHPkYphm6Y0r1iE8497Z4iryVAmPhMEkg,1851
114
114
  janito/i18n/pt.py,sha256=NlTgpDSftUfFG7FGbs7TK54vQlJVMyaZDHGcWjelwMc,4168
115
115
  janito/llm/README.md,sha256=6GRqCu_a9va5HCB1YqNqbshyWKFyAGlnXugrjom-xj8,1213
116
116
  janito/llm/__init__.py,sha256=dpyVH51qVRCw-PDyAFLAxq0zd4jl5MDcuV6Cri0D-dQ,134
117
- janito/llm/agent.py,sha256=JE59p1YSnB-KnCI8kHIcqcxTY30MlMVZ_RzzDM4KiD4,20735
117
+ janito/llm/agent.py,sha256=RYX1LAQKDkdE4H76bAT7ZeFst5ZP_npefuwhevJpbDg,21013
118
118
  janito/llm/auth.py,sha256=8Dl_orUEPhn2X6XjkO2Nr-j1HFT2YDxk1qJl9hSFI88,2286
119
119
  janito/llm/auth_utils.py,sha256=7GH7bIScKhVWJW6ugcDrJLcYRamj5dl_l8N1rrvR4Ws,663
120
120
  janito/llm/driver.py,sha256=stiicPe_MXTuWW4q6MSwK7PCj8UZcA_30pGACu6xYUQ,10039
@@ -124,7 +124,7 @@ janito/llm/driver_input.py,sha256=Zq7IO4KdQPUraeIo6XoOaRy1IdQAyYY15RQw4JU30uA,38
124
124
  janito/llm/message_parts.py,sha256=QY_0kDjaxdoErDgKPRPv1dNkkYJuXIBmHWNLiOEKAH4,1365
125
125
  janito/llm/model.py,sha256=EioBkdgn8hJ0iQaKN-0KbXlsrk3YKmwR9IbvoEbdVTE,1159
126
126
  janito/llm/provider.py,sha256=3FbhQPrWBSEoIdIi-5DWIh0DD_CM570EFf1NcuGyGko,7961
127
- janito/providers/__init__.py,sha256=wlb8-dfnWRsZclFTT5cbwYqSWFpppChrAxZEgpdBgng,450
127
+ janito/providers/__init__.py,sha256=HWgChDOEWKjXavZXwMlKKtdghiy7pxs4KUx3HfhyyUM,492
128
128
  janito/providers/dashscope.bak.zip,sha256=BwXxRmZreEivvRtmqbr5BR62IFVlNjAf4y6DrF2BVJo,5998
129
129
  janito/providers/registry.py,sha256=Ygwv9eVrTXOKhv0EKxSWQXO5WMHvajWE2Q_Lc3p7dKo,730
130
130
  janito/providers/alibaba/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -143,6 +143,9 @@ janito/providers/deepseek/provider.py,sha256=eU-wwVqJog_oJ8VyQyohm6OMHlvrddSszqT
143
143
  janito/providers/google/__init__.py,sha256=hE3OGJvLEhvNLhIK_XmCGIdrIj8MKlyGgdOLJ4mdess,38
144
144
  janito/providers/google/model_info.py,sha256=AakTmzvWm1GPvFzGAq6-PeE_Dpq7BmAAqmh3L8N5KKo,1126
145
145
  janito/providers/google/provider.py,sha256=NQVG5kovHOc2SDgWjVIwYGMqshvMUAqRAk9iMntQ52k,3606
146
+ janito/providers/mistral/__init__.py,sha256=L8X53_KdP8xjmwdxwPmcDHY5iiVZm2xKE4xixsjibHk,27
147
+ janito/providers/mistral/model_info.py,sha256=1Zlac_Bss3wuMELROXTVDfeSeWaI1quhhi0ISEE9NQU,2266
148
+ janito/providers/mistral/provider.py,sha256=v7zIl2EZajLF8zVyLhqhmaCzeXhyanK1X9wuX-bcCgc,4773
146
149
  janito/providers/moonshotai/__init__.py,sha256=nThTAtynq4O2Iidm95daKOCKXi5APRJYtRK2Wr3SDpM,31
147
150
  janito/providers/moonshotai/model_info.py,sha256=MpPAB3tZVvZ8V7tZsiJpk5SReHjVcnwwbp63aUebx9Y,718
148
151
  janito/providers/moonshotai/provider.py,sha256=Lynw2cAF0IA9QPIRN4oY6Yr0cEwyVggpaQQrmkcgHuE,3874
@@ -219,9 +222,9 @@ janito/tools/adapters/local/validate_file_syntax/ps1_validator.py,sha256=TeIkPt0
219
222
  janito/tools/adapters/local/validate_file_syntax/python_validator.py,sha256=BfCO_K18qy92m-2ZVvHsbEU5e11OPo1pO9Vz4G4616E,130
220
223
  janito/tools/adapters/local/validate_file_syntax/xml_validator.py,sha256=AijlsP_PgNuC8ZbGsC5vOTt3Jur76otQzkd_7qR0QFY,284
221
224
  janito/tools/adapters/local/validate_file_syntax/yaml_validator.py,sha256=TgyI0HRL6ug_gBcWEm5TGJJuA4E34ZXcIzMpAbv3oJs,155
222
- janito-2.19.1.dist-info/licenses/LICENSE,sha256=GSAKapQH5ZIGWlpQTA7v5YrfECyaxaohUb1vJX-qepw,1090
223
- janito-2.19.1.dist-info/METADATA,sha256=2pmHGTyGGxQ_SEekpmK-xu6oL-_ZRSBjlKdNTEZuW3U,16365
224
- janito-2.19.1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
225
- janito-2.19.1.dist-info/entry_points.txt,sha256=wIo5zZxbmu4fC-ZMrsKD0T0vq7IqkOOLYhrqRGypkx4,48
226
- janito-2.19.1.dist-info/top_level.txt,sha256=m0NaVCq0-ivxbazE2-ND0EA9Hmuijj_OGkmCbnBcCig,7
227
- janito-2.19.1.dist-info/RECORD,,
225
+ janito-2.20.1.dist-info/licenses/LICENSE,sha256=GSAKapQH5ZIGWlpQTA7v5YrfECyaxaohUb1vJX-qepw,1090
226
+ janito-2.20.1.dist-info/METADATA,sha256=6HXr9gjIG_oQEDhfe6FPY56FIHhccnuWriVp9BmymBQ,16365
227
+ janito-2.20.1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
228
+ janito-2.20.1.dist-info/entry_points.txt,sha256=wIo5zZxbmu4fC-ZMrsKD0T0vq7IqkOOLYhrqRGypkx4,48
229
+ janito-2.20.1.dist-info/top_level.txt,sha256=m0NaVCq0-ivxbazE2-ND0EA9Hmuijj_OGkmCbnBcCig,7
230
+ janito-2.20.1.dist-info/RECORD,,