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.
- janito/README.md +9 -9
- janito/agent/setup_agent.py +29 -16
- janito/cli/chat_mode/script_runner.py +1 -1
- janito/cli/chat_mode/session.py +160 -56
- janito/cli/chat_mode/session_profile_select.py +8 -2
- janito/cli/chat_mode/shell/commands/execute.py +4 -2
- janito/cli/chat_mode/shell/commands/help.py +2 -0
- janito/cli/chat_mode/shell/commands/privileges.py +6 -2
- janito/cli/chat_mode/shell/commands/provider.py +7 -4
- janito/cli/chat_mode/shell/commands/read.py +4 -2
- janito/cli/chat_mode/shell/commands/security/__init__.py +1 -1
- janito/cli/chat_mode/shell/commands/security/allowed_sites.py +16 -13
- janito/cli/chat_mode/shell/commands/security_command.py +14 -10
- janito/cli/chat_mode/shell/commands/tools.py +4 -2
- janito/cli/chat_mode/shell/commands/unrestricted.py +17 -12
- janito/cli/chat_mode/shell/commands/write.py +4 -2
- janito/cli/chat_mode/toolbar.py +4 -4
- janito/cli/cli_commands/enable_disable_plugin.py +48 -25
- janito/cli/cli_commands/list_models.py +2 -2
- janito/cli/cli_commands/list_plugins.py +18 -18
- janito/cli/cli_commands/list_profiles.py +6 -6
- janito/cli/cli_commands/list_providers.py +1 -1
- janito/cli/cli_commands/model_utils.py +45 -20
- janito/cli/cli_commands/ping_providers.py +10 -10
- janito/cli/cli_commands/set_api_key.py +5 -3
- janito/cli/cli_commands/show_config.py +13 -7
- janito/cli/cli_commands/show_system_prompt.py +13 -6
- janito/cli/core/getters.py +1 -0
- janito/cli/core/model_guesser.py +18 -15
- janito/cli/core/runner.py +15 -7
- janito/cli/core/setters.py +9 -6
- janito/cli/main_cli.py +15 -12
- janito/cli/prompt_setup.py +4 -4
- janito/cli/rich_terminal_reporter.py +2 -1
- janito/config_manager.py +2 -0
- janito/docs/GETTING_STARTED.md +9 -9
- janito/drivers/cerebras/__init__.py +1 -1
- janito/exceptions.py +6 -4
- janito/plugins/__init__.py +2 -2
- janito/plugins/base.py +48 -40
- janito/plugins/builtin.py +13 -9
- janito/plugins/config.py +16 -19
- janito/plugins/discovery.py +73 -66
- janito/plugins/manager.py +62 -60
- janito/provider_registry.py +10 -10
- janito/providers/__init__.py +1 -1
- janito/providers/alibaba/model_info.py +3 -5
- janito/providers/alibaba/provider.py +3 -1
- janito/providers/cerebras/__init__.py +1 -1
- janito/providers/cerebras/model_info.py +12 -27
- janito/providers/cerebras/provider.py +11 -9
- janito/providers/mistral/__init__.py +1 -1
- janito/providers/mistral/model_info.py +1 -1
- janito/providers/mistral/provider.py +1 -1
- janito/providers/moonshot/__init__.py +1 -0
- janito/providers/{moonshotai → moonshot}/model_info.py +3 -3
- janito/providers/{moonshotai → moonshot}/provider.py +8 -8
- janito/providers/openai/provider.py +3 -1
- janito/report_events.py +0 -1
- janito/tools/adapters/local/create_file.py +1 -1
- janito/tools/adapters/local/fetch_url.py +45 -29
- janito/tools/adapters/local/python_command_run.py +2 -1
- janito/tools/adapters/local/python_file_run.py +1 -0
- janito/tools/adapters/local/run_powershell_command.py +1 -1
- janito/tools/adapters/local/validate_file_syntax/jinja2_validator.py +14 -11
- janito/tools/base.py +4 -3
- janito/tools/loop_protection.py +24 -22
- janito/tools/path_utils.py +7 -7
- janito/tools/tool_base.py +0 -2
- janito/tools/tools_adapter.py +15 -5
- janito/tools/url_whitelist.py +27 -26
- {janito-2.27.1.dist-info → janito-2.29.0.dist-info}/METADATA +1 -1
- {janito-2.27.1.dist-info → janito-2.29.0.dist-info}/RECORD +77 -77
- janito/providers/moonshotai/__init__.py +0 -1
- {janito-2.27.1.dist-info → janito-2.29.0.dist-info}/WHEEL +0 -0
- {janito-2.27.1.dist-info → janito-2.29.0.dist-info}/entry_points.txt +0 -0
- {janito-2.27.1.dist-info → janito-2.29.0.dist-info}/licenses/LICENSE +0 -0
- {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(
|
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,
|
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(),
|
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(
|
150
|
-
|
151
|
+
plugins_config = config.get("plugins", {})
|
152
|
+
|
151
153
|
# Add plugin paths
|
152
|
-
for path in plugins_config.get(
|
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(
|
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
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
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
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
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
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
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
|
janito/provider_registry.py
CHANGED
@@ -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 = {
|
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, "
|
105
|
-
model_specs = model_info_mod.
|
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 == "
|
117
|
+
|
118
|
+
if provider_name == "moonshot":
|
119
119
|
return ", ".join(model_names)
|
120
120
|
return ", ".join(model_names)
|
121
121
|
return "-"
|
janito/providers/__init__.py
CHANGED
@@ -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.
|
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 =
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
72
|
-
|
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__(
|
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
|
@@ -0,0 +1 @@
|
|
1
|
+
# Moonshot provider package
|
@@ -1,6 +1,6 @@
|
|
1
1
|
from janito.llm.model import LLMModelInfo
|
2
2
|
|
3
|
-
|
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="
|
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="
|
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
|
7
|
+
from .model_info import MOONSHOT_MODEL_SPECS
|
8
8
|
|
9
9
|
|
10
|
-
class
|
11
|
-
name = "
|
12
|
-
NAME = "
|
10
|
+
class MoonshotProvider(LLMProvider):
|
11
|
+
name = "moonshot"
|
12
|
+
NAME = "moonshot"
|
13
13
|
MAINTAINER = "João Pinto <janito@ikignosis.org>"
|
14
|
-
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, "
|
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"
|
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(
|
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 =
|
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
@@ -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
|
"""
|