janito 2.27.1__py3-none-any.whl → 2.29.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 (78) hide show
  1. janito/README.md +9 -9
  2. janito/agent/setup_agent.py +29 -16
  3. janito/cli/chat_mode/script_runner.py +1 -1
  4. janito/cli/chat_mode/session.py +160 -56
  5. janito/cli/chat_mode/session_profile_select.py +8 -2
  6. janito/cli/chat_mode/shell/commands/execute.py +4 -2
  7. janito/cli/chat_mode/shell/commands/help.py +2 -0
  8. janito/cli/chat_mode/shell/commands/privileges.py +6 -2
  9. janito/cli/chat_mode/shell/commands/provider.py +7 -4
  10. janito/cli/chat_mode/shell/commands/read.py +4 -2
  11. janito/cli/chat_mode/shell/commands/security/__init__.py +1 -1
  12. janito/cli/chat_mode/shell/commands/security/allowed_sites.py +16 -13
  13. janito/cli/chat_mode/shell/commands/security_command.py +14 -10
  14. janito/cli/chat_mode/shell/commands/tools.py +4 -2
  15. janito/cli/chat_mode/shell/commands/unrestricted.py +17 -12
  16. janito/cli/chat_mode/shell/commands/write.py +4 -2
  17. janito/cli/chat_mode/toolbar.py +4 -4
  18. janito/cli/cli_commands/enable_disable_plugin.py +48 -25
  19. janito/cli/cli_commands/list_models.py +2 -2
  20. janito/cli/cli_commands/list_plugins.py +18 -18
  21. janito/cli/cli_commands/list_profiles.py +6 -6
  22. janito/cli/cli_commands/list_providers.py +1 -1
  23. janito/cli/cli_commands/model_utils.py +45 -20
  24. janito/cli/cli_commands/ping_providers.py +10 -10
  25. janito/cli/cli_commands/set_api_key.py +5 -3
  26. janito/cli/cli_commands/show_config.py +13 -7
  27. janito/cli/cli_commands/show_system_prompt.py +13 -6
  28. janito/cli/core/getters.py +1 -0
  29. janito/cli/core/model_guesser.py +18 -15
  30. janito/cli/core/runner.py +15 -7
  31. janito/cli/core/setters.py +9 -6
  32. janito/cli/main_cli.py +15 -12
  33. janito/cli/prompt_setup.py +4 -4
  34. janito/cli/rich_terminal_reporter.py +2 -1
  35. janito/config_manager.py +2 -0
  36. janito/docs/GETTING_STARTED.md +9 -9
  37. janito/drivers/cerebras/__init__.py +1 -1
  38. janito/exceptions.py +6 -4
  39. janito/plugins/__init__.py +2 -2
  40. janito/plugins/base.py +48 -40
  41. janito/plugins/builtin.py +13 -9
  42. janito/plugins/config.py +16 -19
  43. janito/plugins/discovery.py +73 -66
  44. janito/plugins/manager.py +62 -60
  45. janito/provider_registry.py +10 -10
  46. janito/providers/__init__.py +1 -1
  47. janito/providers/alibaba/model_info.py +3 -5
  48. janito/providers/alibaba/provider.py +3 -1
  49. janito/providers/cerebras/__init__.py +1 -1
  50. janito/providers/cerebras/model_info.py +12 -27
  51. janito/providers/cerebras/provider.py +11 -9
  52. janito/providers/mistral/__init__.py +1 -1
  53. janito/providers/mistral/model_info.py +1 -1
  54. janito/providers/mistral/provider.py +1 -1
  55. janito/providers/moonshot/__init__.py +1 -0
  56. janito/providers/{moonshotai → moonshot}/model_info.py +3 -3
  57. janito/providers/{moonshotai → moonshot}/provider.py +8 -8
  58. janito/providers/openai/provider.py +3 -1
  59. janito/report_events.py +0 -1
  60. janito/tools/adapters/local/create_file.py +1 -1
  61. janito/tools/adapters/local/fetch_url.py +45 -29
  62. janito/tools/adapters/local/python_command_run.py +2 -1
  63. janito/tools/adapters/local/python_file_run.py +1 -0
  64. janito/tools/adapters/local/run_powershell_command.py +1 -1
  65. janito/tools/adapters/local/validate_file_syntax/jinja2_validator.py +14 -11
  66. janito/tools/base.py +4 -3
  67. janito/tools/loop_protection.py +24 -22
  68. janito/tools/path_utils.py +7 -7
  69. janito/tools/tool_base.py +0 -2
  70. janito/tools/tools_adapter.py +15 -5
  71. janito/tools/url_whitelist.py +27 -26
  72. {janito-2.27.1.dist-info → janito-2.29.0.dist-info}/METADATA +1 -1
  73. {janito-2.27.1.dist-info → janito-2.29.0.dist-info}/RECORD +77 -77
  74. janito/providers/moonshotai/__init__.py +0 -1
  75. {janito-2.27.1.dist-info → janito-2.29.0.dist-info}/WHEEL +0 -0
  76. {janito-2.27.1.dist-info → janito-2.29.0.dist-info}/entry_points.txt +0 -0
  77. {janito-2.27.1.dist-info → janito-2.29.0.dist-info}/licenses/LICENSE +0 -0
  78. {janito-2.27.1.dist-info → janito-2.29.0.dist-info}/top_level.txt +0 -0
janito/plugins/manager.py CHANGED
@@ -23,13 +23,13 @@ class PluginManager:
23
23
  """
24
24
  Manages plugin loading, registration, and lifecycle.
25
25
  """
26
-
26
+
27
27
  def __init__(self, tools_adapter: Optional[LocalToolsAdapter] = None):
28
28
  self.tools_adapter = tools_adapter or LocalToolsAdapter()
29
29
  self.plugins: Dict[str, Plugin] = {}
30
30
  self.plugin_configs: Dict[str, Dict[str, Any]] = {}
31
31
  self.plugin_paths: List[Path] = []
32
-
32
+
33
33
  def add_plugin_path(self, path: str) -> None:
34
34
  """Add a directory to search for plugins."""
35
35
  plugin_path = Path(path)
@@ -37,15 +37,17 @@ class PluginManager:
37
37
  self.plugin_paths.append(plugin_path)
38
38
  if str(plugin_path) not in sys.path:
39
39
  sys.path.insert(0, str(plugin_path))
40
-
41
- def load_plugin(self, plugin_name: str, config: Optional[Dict[str, Any]] = None) -> bool:
40
+
41
+ def load_plugin(
42
+ self, plugin_name: str, config: Optional[Dict[str, Any]] = None
43
+ ) -> bool:
42
44
  """
43
45
  Load a plugin by name.
44
-
46
+
45
47
  Args:
46
48
  plugin_name: Name of the plugin to load
47
49
  config: Optional configuration for the plugin
48
-
50
+
49
51
  Returns:
50
52
  True if plugin loaded successfully
51
53
  """
@@ -53,47 +55,47 @@ class PluginManager:
53
55
  if plugin_name in self.plugins:
54
56
  logger.warning(f"Plugin {plugin_name} already loaded")
55
57
  return True
56
-
58
+
57
59
  plugin = discover_plugins(plugin_name, self.plugin_paths)
58
60
  if not plugin:
59
61
  logger.error(f"Plugin {plugin_name} not found")
60
62
  return False
61
-
63
+
62
64
  # Store config
63
65
  if config:
64
66
  self.plugin_configs[plugin_name] = config
65
-
67
+
66
68
  # Validate config if provided
67
- if config and hasattr(plugin, 'validate_config'):
69
+ if config and hasattr(plugin, "validate_config"):
68
70
  if not plugin.validate_config(config):
69
71
  logger.error(f"Invalid configuration for plugin {plugin_name}")
70
72
  return False
71
-
73
+
72
74
  # Initialize plugin
73
75
  plugin.initialize()
74
-
76
+
75
77
  # Register tools
76
78
  tools = plugin.get_tools()
77
79
  for tool_class in tools:
78
80
  self.tools_adapter.register_tool(tool_class)
79
-
81
+
80
82
  # Store plugin
81
83
  self.plugins[plugin_name] = plugin
82
-
84
+
83
85
  logger.info(f"Successfully loaded plugin: {plugin_name}")
84
86
  return True
85
-
87
+
86
88
  except Exception as e:
87
89
  logger.error(f"Failed to load plugin {plugin_name}: {e}")
88
90
  return False
89
-
91
+
90
92
  def unload_plugin(self, plugin_name: str) -> bool:
91
93
  """
92
94
  Unload a plugin.
93
-
95
+
94
96
  Args:
95
97
  plugin_name: Name of the plugin to unload
96
-
98
+
97
99
  Returns:
98
100
  True if plugin unloaded successfully
99
101
  """
@@ -101,65 +103,65 @@ class PluginManager:
101
103
  if plugin_name not in self.plugins:
102
104
  logger.warning(f"Plugin {plugin_name} not loaded")
103
105
  return False
104
-
106
+
105
107
  plugin = self.plugins[plugin_name]
106
-
108
+
107
109
  # Unregister tools
108
110
  tools = plugin.get_tools()
109
111
  for tool_class in tools:
110
- tool_name = getattr(tool_class(), 'tool_name', None)
112
+ tool_name = getattr(tool_class(), "tool_name", None)
111
113
  if tool_name:
112
114
  self.tools_adapter.unregister_tool(tool_name)
113
-
115
+
114
116
  # Cleanup plugin
115
117
  plugin.cleanup()
116
-
118
+
117
119
  # Remove from registry
118
120
  del self.plugins[plugin_name]
119
121
  if plugin_name in self.plugin_configs:
120
122
  del self.plugin_configs[plugin_name]
121
-
123
+
122
124
  logger.info(f"Successfully unloaded plugin: {plugin_name}")
123
125
  return True
124
-
126
+
125
127
  except Exception as e:
126
128
  logger.error(f"Failed to unload plugin {plugin_name}: {e}")
127
129
  return False
128
-
130
+
129
131
  def list_plugins(self) -> List[str]:
130
132
  """Return list of loaded plugin names."""
131
133
  return list(self.plugins.keys())
132
-
134
+
133
135
  def get_plugin(self, plugin_name: str) -> Optional[Plugin]:
134
136
  """Get a loaded plugin by name."""
135
137
  return self.plugins.get(plugin_name)
136
-
138
+
137
139
  def get_plugin_metadata(self, plugin_name: str) -> Optional[PluginMetadata]:
138
140
  """Get metadata for a loaded plugin."""
139
141
  plugin = self.plugins.get(plugin_name)
140
142
  return plugin.metadata if plugin else None
141
-
143
+
142
144
  def load_plugins_from_config(self, config: Dict[str, Any]) -> None:
143
145
  """
144
146
  Load plugins from configuration.
145
-
147
+
146
148
  Args:
147
149
  config: Configuration dict with plugin settings
148
150
  """
149
- plugins_config = config.get('plugins', {})
150
-
151
+ plugins_config = config.get("plugins", {})
152
+
151
153
  # Add plugin paths
152
- for path in plugins_config.get('paths', []):
154
+ for path in plugins_config.get("paths", []):
153
155
  self.add_plugin_path(path)
154
-
156
+
155
157
  # Load plugins
156
- for plugin_name, plugin_config in plugins_config.get('load', {}).items():
158
+ for plugin_name, plugin_config in plugins_config.get("load", {}).items():
157
159
  if isinstance(plugin_config, bool):
158
160
  if plugin_config:
159
161
  self.load_plugin(plugin_name)
160
162
  else:
161
163
  self.load_plugin(plugin_name, plugin_config)
162
-
164
+
163
165
  def load_plugins_from_user_config(self) -> None:
164
166
  """
165
167
  Load plugins from user configuration directory.
@@ -167,63 +169,63 @@ class PluginManager:
167
169
  """
168
170
  config = load_plugins_config()
169
171
  self.load_plugins_from_config(config)
170
-
172
+
171
173
  def reload_plugin(self, plugin_name: str) -> bool:
172
174
  """
173
175
  Reload a plugin.
174
-
176
+
175
177
  Args:
176
178
  plugin_name: Name of the plugin to reload
177
-
179
+
178
180
  Returns:
179
181
  True if plugin reloaded successfully
180
182
  """
181
183
  config = self.plugin_configs.get(plugin_name)
182
184
  self.unload_plugin(plugin_name)
183
185
  return self.load_plugin(plugin_name, config)
184
-
186
+
185
187
  def get_loaded_plugins_info(self) -> Dict[str, Dict[str, Any]]:
186
188
  """Get information about all loaded plugins."""
187
189
  info = {}
188
190
  for name, plugin in self.plugins.items():
189
191
  info[name] = {
190
- 'metadata': plugin.metadata,
191
- 'tools': [tool.__name__ for tool in plugin.get_tools()],
192
- 'commands': list(plugin.get_commands().keys()),
193
- 'config': self.plugin_configs.get(name, {}),
194
- 'builtin': BuiltinPluginRegistry.is_builtin(name),
195
- 'resources': [
192
+ "metadata": plugin.metadata,
193
+ "tools": [tool.__name__ for tool in plugin.get_tools()],
194
+ "commands": list(plugin.get_commands().keys()),
195
+ "config": self.plugin_configs.get(name, {}),
196
+ "builtin": BuiltinPluginRegistry.is_builtin(name),
197
+ "resources": [
196
198
  {
197
- 'name': resource.name,
198
- 'type': resource.type,
199
- 'description': resource.description,
200
- 'schema': resource.schema
199
+ "name": resource.name,
200
+ "type": resource.type,
201
+ "description": resource.description,
202
+ "schema": resource.schema,
201
203
  }
202
204
  for resource in plugin.get_resources()
203
- ]
205
+ ],
204
206
  }
205
207
  return info
206
208
 
207
209
  def get_plugin_resources(self, plugin_name: str) -> List[Dict[str, Any]]:
208
210
  """
209
211
  Get resources provided by a specific plugin.
210
-
212
+
211
213
  Args:
212
214
  plugin_name: Name of the plugin
213
-
215
+
214
216
  Returns:
215
217
  List of resource dictionaries
216
218
  """
217
219
  plugin = self.plugins.get(plugin_name)
218
220
  if not plugin:
219
221
  return []
220
-
222
+
221
223
  return [
222
224
  {
223
- 'name': resource.name,
224
- 'type': resource.type,
225
- 'description': resource.description,
226
- 'schema': resource.schema
225
+ "name": resource.name,
226
+ "type": resource.type,
227
+ "description": resource.description,
228
+ "schema": resource.schema,
227
229
  }
228
230
  for resource in plugin.get_resources()
229
231
  ]
@@ -231,11 +233,11 @@ class PluginManager:
231
233
  def list_all_resources(self) -> Dict[str, List[Dict[str, Any]]]:
232
234
  """
233
235
  List all resources from all loaded plugins.
234
-
236
+
235
237
  Returns:
236
238
  Dict mapping plugin names to their resources
237
239
  """
238
240
  all_resources = {}
239
241
  for plugin_name in self.plugins:
240
242
  all_resources[plugin_name] = self.get_plugin_resources(plugin_name)
241
- return all_resources
243
+ return all_resources
@@ -39,16 +39,16 @@ class ProviderRegistry:
39
39
  if len(info) == 4 and info[3]:
40
40
  continue # skip providers flagged as not implemented
41
41
  rows.append(info[:3])
42
-
42
+
43
43
  # Group providers by openness (open-source first, then proprietary)
44
- open_providers = {'cerebras', 'deepseek', 'alibaba', 'moonshotai', 'zai'}
45
-
44
+ open_providers = {"cerebras", "deepseek", "alibaba", "moonshot", "zai"}
45
+
46
46
  def sort_key(row):
47
47
  provider_name = row[0]
48
48
  is_open = provider_name in open_providers
49
49
  # Sort open providers alphabetically first, then proprietary alphabetically
50
50
  return (not is_open, provider_name)
51
-
51
+
52
52
  rows.sort(key=sort_key)
53
53
  return rows
54
54
 
@@ -101,21 +101,21 @@ class ProviderRegistry:
101
101
  model_specs = None
102
102
  if hasattr(model_info_mod, "MODEL_SPECS"):
103
103
  model_specs = model_info_mod.MODEL_SPECS
104
- elif hasattr(model_info_mod, "MOONSHOTAI_MODEL_SPECS"):
105
- model_specs = model_info_mod.MOONSHOTAI_MODEL_SPECS
106
-
104
+ elif hasattr(model_info_mod, "MOONSHOT_MODEL_SPECS"):
105
+ model_specs = model_info_mod.MOONSHOT_MODEL_SPECS
106
+
107
107
  if model_specs:
108
108
  default_model = getattr(provider_class, "DEFAULT_MODEL", None)
109
109
  model_names = []
110
-
110
+
111
111
  for model_key in model_specs.keys():
112
112
  if model_key == default_model:
113
113
  # Highlight the default model with color and star icon
114
114
  model_names.append(f"[bold green]⭐ {model_key}[/bold green]")
115
115
  else:
116
116
  model_names.append(model_key)
117
-
118
- if provider_name == "moonshotai":
117
+
118
+ if provider_name == "moonshot":
119
119
  return ", ".join(model_names)
120
120
  return ", ".join(model_names)
121
121
  return "-"
@@ -4,7 +4,7 @@ import janito.providers.google.provider
4
4
  import janito.providers.azure_openai.provider
5
5
  import janito.providers.anthropic.provider
6
6
  import janito.providers.deepseek.provider
7
- import janito.providers.moonshotai.provider
7
+ import janito.providers.moonshot.provider
8
8
  import janito.providers.alibaba.provider
9
9
  import janito.providers.zai.provider
10
10
  import janito.providers.cerebras.provider
@@ -12,7 +12,7 @@ MODEL_SPECS = {
12
12
  max_cot=8192,
13
13
  ),
14
14
  "qwen-plus": LLMModelInfo(
15
- name="qwen-plus",
15
+ name="qwen-plus",
16
16
  context=131072,
17
17
  max_response=8192,
18
18
  category="Alibaba Qwen Plus Model (OpenAI-compatible)",
@@ -23,7 +23,7 @@ MODEL_SPECS = {
23
23
  ),
24
24
  "qwen-max": LLMModelInfo(
25
25
  name="qwen-max",
26
- context=32768,
26
+ context=32768,
27
27
  max_response=8192,
28
28
  category="Alibaba Qwen Max Model (OpenAI-compatible)",
29
29
  driver="OpenAIModelDriver",
@@ -31,7 +31,6 @@ MODEL_SPECS = {
31
31
  thinking=False,
32
32
  max_cot=8192,
33
33
  ),
34
-
35
34
  "qwen3-coder-plus": LLMModelInfo(
36
35
  name="qwen3-coder-plus",
37
36
  context=1048576,
@@ -52,7 +51,6 @@ MODEL_SPECS = {
52
51
  thinking=False,
53
52
  max_cot=65536,
54
53
  ),
55
-
56
54
  # Qwen3 1M context models (July 2025 update)
57
55
  "qwen3-235b-a22b-thinking-2507": LLMModelInfo(
58
56
  name="qwen3-235b-a22b-thinking-2507",
@@ -94,4 +92,4 @@ MODEL_SPECS = {
94
92
  thinking=False,
95
93
  max_cot=32768,
96
94
  ),
97
- }
95
+ }
@@ -17,7 +17,9 @@ class AlibabaProvider(LLMProvider):
17
17
  NAME = "alibaba"
18
18
  MAINTAINER = "João Pinto <janito@ikignosis.org>"
19
19
  MODEL_SPECS = MODEL_SPECS
20
- DEFAULT_MODEL = "qwen3-235b-a22b-instruct-2507" # 129k context, general-purpose model
20
+ DEFAULT_MODEL = (
21
+ "qwen3-235b-a22b-instruct-2507" # 129k context, general-purpose model
22
+ )
21
23
 
22
24
  def __init__(
23
25
  self, auth_manager: LLMAuthManager = None, config: LLMDriverConfig = None
@@ -1 +1 @@
1
- # Cerebras provider package
1
+ # Cerebras provider package
@@ -11,11 +11,8 @@ MODEL_SPECS = {
11
11
  driver="CerebrasModelDriver",
12
12
  other={
13
13
  "description": "Qwen 3 32B model for general instruction following",
14
- "pricing": {
15
- "input_per_1k_tokens": 0.0002,
16
- "output_per_1k_tokens": 0.0006
17
- }
18
- }
14
+ "pricing": {"input_per_1k_tokens": 0.0002, "output_per_1k_tokens": 0.0006},
15
+ },
19
16
  ),
20
17
  "qwen-3-235b-a22b-instruct-2507": LLMModelInfo(
21
18
  name="qwen-3-235b-a22b-instruct-2507",
@@ -25,11 +22,8 @@ MODEL_SPECS = {
25
22
  driver="CerebrasModelDriver",
26
23
  other={
27
24
  "description": "Qwen 3 235B A22B instruction-tuned model (preview)",
28
- "pricing": {
29
- "input_per_1k_tokens": 0.001,
30
- "output_per_1k_tokens": 0.003
31
- }
32
- }
25
+ "pricing": {"input_per_1k_tokens": 0.001, "output_per_1k_tokens": 0.003},
26
+ },
33
27
  ),
34
28
  "qwen-3-235b-a22b-thinking-2507": LLMModelInfo(
35
29
  name="qwen-3-235b-a22b-thinking-2507",
@@ -39,11 +33,8 @@ MODEL_SPECS = {
39
33
  driver="CerebrasModelDriver",
40
34
  other={
41
35
  "description": "Qwen 3 235B A22B thinking model for reasoning tasks (preview)",
42
- "pricing": {
43
- "input_per_1k_tokens": 0.001,
44
- "output_per_1k_tokens": 0.003
45
- }
46
- }
36
+ "pricing": {"input_per_1k_tokens": 0.001, "output_per_1k_tokens": 0.003},
37
+ },
47
38
  ),
48
39
  "qwen-3-coder-480b": LLMModelInfo(
49
40
  name="qwen-3-coder-480b",
@@ -53,11 +44,8 @@ MODEL_SPECS = {
53
44
  driver="CerebrasModelDriver",
54
45
  other={
55
46
  "description": "Qwen 3 Coder 480B model for programming tasks (preview)",
56
- "pricing": {
57
- "input_per_1k_tokens": 0.002,
58
- "output_per_1k_tokens": 0.006
59
- }
60
- }
47
+ "pricing": {"input_per_1k_tokens": 0.002, "output_per_1k_tokens": 0.006},
48
+ },
61
49
  ),
62
50
  "gpt-oss-120b": LLMModelInfo(
63
51
  name="gpt-oss-120b",
@@ -67,10 +55,7 @@ MODEL_SPECS = {
67
55
  driver="CerebrasModelDriver",
68
56
  other={
69
57
  "description": "GPT-OSS 120B open-source model (preview)",
70
- "pricing": {
71
- "input_per_1k_tokens": 0.0008,
72
- "output_per_1k_tokens": 0.0024
73
- }
74
- }
75
- )
76
- }
58
+ "pricing": {"input_per_1k_tokens": 0.0008, "output_per_1k_tokens": 0.0024},
59
+ },
60
+ ),
61
+ }
@@ -12,14 +12,16 @@ from .model_info import MODEL_SPECS
12
12
 
13
13
  class CerebrasProvider(LLMProvider):
14
14
  """Cerebras Inference API provider."""
15
-
15
+
16
16
  name = "cerebras"
17
17
  NAME = "cerebras"
18
18
  DEFAULT_MODEL = "qwen-3-coder-480b"
19
19
  MAINTAINER = "João Pinto <janito@ikignosis.org>"
20
20
  MODEL_SPECS = MODEL_SPECS
21
21
 
22
- def __init__(self, auth_manager: LLMAuthManager = None, config: LLMDriverConfig = None):
22
+ def __init__(
23
+ self, auth_manager: LLMAuthManager = None, config: LLMDriverConfig = None
24
+ ):
23
25
  """Initialize Cerebras provider with optional configuration."""
24
26
  super().__init__()
25
27
  self._tools_adapter = get_local_tools_adapter()
@@ -32,10 +34,10 @@ class CerebrasProvider(LLMProvider):
32
34
  self._initialize_config(auth_manager, config)
33
35
  self._setup_model_config()
34
36
  self.fill_missing_device_info(self._driver_config)
35
-
37
+
36
38
  if not self.available:
37
39
  return
38
-
40
+
39
41
  self._initialize_config(None, None)
40
42
  self._driver_config.base_url = "https://api.cerebras.ai/v1"
41
43
 
@@ -72,11 +74,11 @@ class CerebrasProvider(LLMProvider):
72
74
  # Set context length
73
75
  if hasattr(model_spec, "context") and model_spec.context:
74
76
  self._driver_config.context_length = model_spec.context
75
-
77
+
76
78
  # Set max tokens based on model spec
77
79
  if hasattr(model_spec, "max_response") and model_spec.max_response:
78
80
  self._driver_config.max_tokens = model_spec.max_response
79
-
81
+
80
82
  # Set max completion tokens if thinking is supported
81
83
  if getattr(model_spec, "thinking_supported", False):
82
84
  max_cot = getattr(model_spec, "max_cot", None)
@@ -130,10 +132,10 @@ class CerebrasProvider(LLMProvider):
130
132
  name: model_info.to_dict()
131
133
  for name, model_info in self.MODEL_SPECS.items()
132
134
  }
133
-
135
+
134
136
  if model_name in self.MODEL_SPECS:
135
137
  return self.MODEL_SPECS[model_name].to_dict()
136
-
138
+
137
139
  return None
138
140
 
139
141
  def execute_tool(self, tool_name: str, event_bus, *args, **kwargs):
@@ -142,4 +144,4 @@ class CerebrasProvider(LLMProvider):
142
144
 
143
145
 
144
146
  # Register the provider
145
- LLMProviderRegistry.register(CerebrasProvider.name, CerebrasProvider)
147
+ LLMProviderRegistry.register(CerebrasProvider.name, CerebrasProvider)
@@ -1 +1 @@
1
- # Codestral provider module
1
+ # Codestral provider module
@@ -78,4 +78,4 @@ MODEL_SPECS = {
78
78
  open="mistral",
79
79
  driver="OpenAIModelDriver",
80
80
  ),
81
- }
81
+ }
@@ -121,4 +121,4 @@ class MistralProvider(LLMProvider):
121
121
  return self._tools_adapter.execute_by_name(tool_name, *args, **kwargs)
122
122
 
123
123
 
124
- LLMProviderRegistry.register(MistralProvider.NAME, MistralProvider)
124
+ LLMProviderRegistry.register(MistralProvider.NAME, MistralProvider)
@@ -0,0 +1 @@
1
+ # Moonshot provider package
@@ -1,6 +1,6 @@
1
1
  from janito.llm.model import LLMModelInfo
2
2
 
3
- MOONSHOTAI_MODEL_SPECS = {
3
+ MOONSHOT_MODEL_SPECS = {
4
4
  "kimi-k2-0711-preview": LLMModelInfo(
5
5
  name="kimi-k2-0711-preview",
6
6
  context=128000,
@@ -9,7 +9,7 @@ MOONSHOTAI_MODEL_SPECS = {
9
9
  max_response=4096,
10
10
  thinking_supported=False,
11
11
  default_temp=0.2,
12
- open="moonshotai",
12
+ open="moonshot",
13
13
  driver="OpenAIModelDriver",
14
14
  ),
15
15
  "kimi-k2-turbo-preview": LLMModelInfo(
@@ -20,7 +20,7 @@ MOONSHOTAI_MODEL_SPECS = {
20
20
  max_response=4096,
21
21
  thinking_supported=False,
22
22
  default_temp=0.2,
23
- open="moonshotai",
23
+ open="moonshot",
24
24
  driver="OpenAIModelDriver",
25
25
  ),
26
26
  }
@@ -4,14 +4,14 @@ from janito.llm.driver_config import LLMDriverConfig
4
4
  from janito.drivers.openai.driver import OpenAIModelDriver
5
5
  from janito.tools import get_local_tools_adapter
6
6
  from janito.providers.registry import LLMProviderRegistry
7
- from .model_info import MOONSHOTAI_MODEL_SPECS
7
+ from .model_info import MOONSHOT_MODEL_SPECS
8
8
 
9
9
 
10
- class MoonshotAIProvider(LLMProvider):
11
- name = "moonshotai"
12
- NAME = "moonshotai"
10
+ class MoonshotProvider(LLMProvider):
11
+ name = "moonshot"
12
+ NAME = "moonshot"
13
13
  MAINTAINER = "João Pinto <janito@ikignosis.org>"
14
- MODEL_SPECS = MOONSHOTAI_MODEL_SPECS
14
+ MODEL_SPECS = MOONSHOT_MODEL_SPECS
15
15
  DEFAULT_MODEL = "kimi-k2-turbo-preview"
16
16
 
17
17
  def __init__(
@@ -34,7 +34,7 @@ class MoonshotAIProvider(LLMProvider):
34
34
  if not self._api_key:
35
35
  from janito.llm.auth_utils import handle_missing_api_key
36
36
 
37
- handle_missing_api_key(self.name, "MOONSHOTAI_API_KEY")
37
+ handle_missing_api_key(self.name, "MOONSHOT_API_KEY")
38
38
 
39
39
  self._driver_config = config or LLMDriverConfig(model=None)
40
40
  if not self._driver_config.model:
@@ -69,7 +69,7 @@ class MoonshotAIProvider(LLMProvider):
69
69
  def driver(self) -> OpenAIModelDriver:
70
70
  if not self.available:
71
71
  raise ImportError(
72
- f"MoonshotAIProvider unavailable: {self.unavailable_reason}"
72
+ f"MoonshotProvider unavailable: {self.unavailable_reason}"
73
73
  )
74
74
  return self._driver
75
75
 
@@ -101,4 +101,4 @@ class MoonshotAIProvider(LLMProvider):
101
101
  return self._tools_adapter.execute_by_name(tool_name, *args, **kwargs)
102
102
 
103
103
 
104
- LLMProviderRegistry.register(MoonshotAIProvider.NAME, MoonshotAIProvider)
104
+ LLMProviderRegistry.register(MoonshotProvider.NAME, MoonshotProvider)
@@ -17,7 +17,9 @@ class OpenAIProvider(LLMProvider):
17
17
  NAME = "openai"
18
18
  MAINTAINER = "João Pinto <janito@ikignosis.org>"
19
19
  MODEL_SPECS = MODEL_SPECS
20
- DEFAULT_MODEL = "gpt-5" # Options: gpt-4.1, gpt-4o, o3-mini, o4-mini, gpt-5, gpt-5-nano
20
+ DEFAULT_MODEL = (
21
+ "gpt-5" # Options: gpt-4.1, gpt-4o, o3-mini, o4-mini, gpt-5, gpt-5-nano
22
+ )
21
23
 
22
24
  def __init__(
23
25
  self, auth_manager: LLMAuthManager = None, config: LLMDriverConfig = None
janito/report_events.py CHANGED
@@ -14,7 +14,6 @@ class ReportSubtype(Enum):
14
14
  PROGRESS = "progress"
15
15
 
16
16
 
17
-
18
17
  class ReportAction(Enum):
19
18
  READ = "READ"
20
19
  CREATE = "CREATE"
@@ -25,7 +25,7 @@ class CreateFileTool(ToolBase):
25
25
  - "✅ Successfully created the file at ..."
26
26
 
27
27
  Note: Syntax validation is automatically performed after this operation.
28
-
28
+
29
29
  Security: This tool includes loop protection to prevent excessive file creation operations.
30
30
  Maximum 5 calls per 10 seconds for the same file path.
31
31
  """