janito 3.12.1__py3-none-any.whl → 3.12.2__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/agent/setup_agent.py +378 -377
- janito/cli/chat_mode/session.py +505 -505
- janito/cli/cli_commands/list_profiles.py +104 -107
- janito/cli/cli_commands/show_system_prompt.py +166 -166
- janito/cli/core/runner.py +250 -266
- janito/cli/main_cli.py +520 -519
- janito/cli/single_shot_mode/handler.py +167 -167
- janito/llm/__init__.py +6 -5
- janito/llm/driver.py +290 -254
- janito/llm/response_cache.py +57 -0
- janito/plugins/builtin.py +64 -88
- janito/plugins/tools/local/__init__.py +82 -80
- janito/plugins/tools/local/markdown_view.py +94 -0
- janito/plugins/tools/local/show_image.py +119 -74
- janito/plugins/tools/local/show_image_grid.py +134 -76
- janito/providers/alibaba/model_info.py +136 -105
- {janito-3.12.1.dist-info → janito-3.12.2.dist-info}/METADATA +1 -1
- {janito-3.12.1.dist-info → janito-3.12.2.dist-info}/RECORD +22 -20
- {janito-3.12.1.dist-info → janito-3.12.2.dist-info}/WHEEL +0 -0
- {janito-3.12.1.dist-info → janito-3.12.2.dist-info}/entry_points.txt +0 -0
- {janito-3.12.1.dist-info → janito-3.12.2.dist-info}/licenses/LICENSE +0 -0
- {janito-3.12.1.dist-info → janito-3.12.2.dist-info}/top_level.txt +0 -0
janito/cli/core/runner.py
CHANGED
@@ -1,266 +1,250 @@
|
|
1
|
-
"""Handles LLM driver config preparation and execution modes."""
|
2
|
-
|
3
|
-
from janito.llm.driver_config import LLMDriverConfig
|
4
|
-
from janito.provider_config import get_config_provider
|
5
|
-
from janito.cli.core.model_guesser import (
|
6
|
-
guess_provider_from_model as _guess_provider_from_model,
|
7
|
-
)
|
8
|
-
from janito.cli.verbose_output import print_verbose_info
|
9
|
-
|
10
|
-
|
11
|
-
def _choose_provider(args):
|
12
|
-
provider = getattr(args, "provider", None)
|
13
|
-
if provider is None:
|
14
|
-
provider = get_config_provider()
|
15
|
-
if provider and getattr(args, "verbose", False):
|
16
|
-
print_verbose_info(
|
17
|
-
"Default provider", provider, style="magenta", align_content=True
|
18
|
-
)
|
19
|
-
elif provider is None:
|
20
|
-
# Try to guess provider based on model name if -m is provided
|
21
|
-
model = getattr(args, "model", None)
|
22
|
-
if model:
|
23
|
-
guessed_provider = _guess_provider_from_model(model)
|
24
|
-
if guessed_provider:
|
25
|
-
if getattr(args, "verbose", False):
|
26
|
-
print_verbose_info(
|
27
|
-
"Guessed provider",
|
28
|
-
guessed_provider,
|
29
|
-
style="magenta",
|
30
|
-
align_content=True,
|
31
|
-
)
|
32
|
-
return guessed_provider
|
33
|
-
|
34
|
-
print(
|
35
|
-
"Error: No provider selected and no provider found in config. Please set a provider using '-p PROVIDER', '--set provider=name', or configure a provider."
|
36
|
-
)
|
37
|
-
return None
|
38
|
-
return provider
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
from
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
"""
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
args,
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
from janito.tools.
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
from janito.
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
if
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
from
|
231
|
-
|
232
|
-
)
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
allowed_permissions=allowed_permissions,
|
242
|
-
)
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
provider_instance,
|
252
|
-
llm_driver_config,
|
253
|
-
role=agent_role,
|
254
|
-
args=args,
|
255
|
-
verbose_tools=verbose_tools,
|
256
|
-
verbose_agent=getattr(args, "verbose_agent", False),
|
257
|
-
allowed_permissions=allowed_permissions,
|
258
|
-
)
|
259
|
-
session.run()
|
260
|
-
|
261
|
-
|
262
|
-
def get_prompt_mode(args):
|
263
|
-
# If interactive flag is set, force chat mode regardless of user_prompt
|
264
|
-
if getattr(args, "interactive", False):
|
265
|
-
return "chat_mode"
|
266
|
-
return "single_shot" if getattr(args, "user_prompt", None) else "chat_mode"
|
1
|
+
"""Handles LLM driver config preparation and execution modes."""
|
2
|
+
|
3
|
+
from janito.llm.driver_config import LLMDriverConfig
|
4
|
+
from janito.provider_config import get_config_provider
|
5
|
+
from janito.cli.core.model_guesser import (
|
6
|
+
guess_provider_from_model as _guess_provider_from_model,
|
7
|
+
)
|
8
|
+
from janito.cli.verbose_output import print_verbose_info
|
9
|
+
|
10
|
+
|
11
|
+
def _choose_provider(args):
|
12
|
+
provider = getattr(args, "provider", None)
|
13
|
+
if provider is None:
|
14
|
+
provider = get_config_provider()
|
15
|
+
if provider and getattr(args, "verbose", False):
|
16
|
+
print_verbose_info(
|
17
|
+
"Default provider", provider, style="magenta", align_content=True
|
18
|
+
)
|
19
|
+
elif provider is None:
|
20
|
+
# Try to guess provider based on model name if -m is provided
|
21
|
+
model = getattr(args, "model", None)
|
22
|
+
if model:
|
23
|
+
guessed_provider = _guess_provider_from_model(model)
|
24
|
+
if guessed_provider:
|
25
|
+
if getattr(args, "verbose", False):
|
26
|
+
print_verbose_info(
|
27
|
+
"Guessed provider",
|
28
|
+
guessed_provider,
|
29
|
+
style="magenta",
|
30
|
+
align_content=True,
|
31
|
+
)
|
32
|
+
return guessed_provider
|
33
|
+
|
34
|
+
print(
|
35
|
+
"Error: No provider selected and no provider found in config. Please set a provider using '-p PROVIDER', '--set provider=name', or configure a provider."
|
36
|
+
)
|
37
|
+
return None
|
38
|
+
return provider
|
39
|
+
|
40
|
+
|
41
|
+
|
42
|
+
|
43
|
+
|
44
|
+
def _populate_driver_config_data(args, modifiers, provider, model):
|
45
|
+
from janito.provider_config import get_effective_setting
|
46
|
+
|
47
|
+
CONFIG_LOOKUP_KEYS = ("max_tokens", "base_url")
|
48
|
+
driver_config_data = {"model": model}
|
49
|
+
if getattr(args, "verbose_api", None) is not None:
|
50
|
+
driver_config_data["verbose_api"] = args.verbose_api
|
51
|
+
|
52
|
+
# Add reasoning_effort from --effort CLI argument
|
53
|
+
if getattr(args, "effort", None) is not None:
|
54
|
+
driver_config_data["reasoning_effort"] = args.effort
|
55
|
+
for field in LLMDriverConfig.__dataclass_fields__:
|
56
|
+
if field in CONFIG_LOOKUP_KEYS:
|
57
|
+
if field in modifiers and modifiers[field] is not None:
|
58
|
+
driver_config_data[field] = modifiers[field]
|
59
|
+
else:
|
60
|
+
value = get_effective_setting(provider, model, field)
|
61
|
+
if value is not None:
|
62
|
+
driver_config_data[field] = value
|
63
|
+
elif field in modifiers and field != "model":
|
64
|
+
driver_config_data[field] = modifiers[field]
|
65
|
+
return driver_config_data
|
66
|
+
|
67
|
+
|
68
|
+
def prepare_llm_driver_config(args, modifiers):
|
69
|
+
"""Prepare the LLMDriverConfig instance based on CLI *args* and *modifiers*.
|
70
|
+
|
71
|
+
This helper additionally validates that the chosen ``--model`` (or the
|
72
|
+
resolved model coming from config precedence) is actually available for the
|
73
|
+
selected provider. If the combination is invalid an error is printed and
|
74
|
+
``None`` is returned for the config so that the caller can abort execution
|
75
|
+
gracefully.
|
76
|
+
"""
|
77
|
+
provider = _choose_provider(args)
|
78
|
+
if provider is None:
|
79
|
+
return None, None, None
|
80
|
+
from janito.provider_config import get_effective_model
|
81
|
+
|
82
|
+
model = getattr(args, "model", None)
|
83
|
+
if not model:
|
84
|
+
model = get_effective_model(provider)
|
85
|
+
|
86
|
+
|
87
|
+
|
88
|
+
# Validate that the chosen model is supported by the selected provider
|
89
|
+
if model:
|
90
|
+
from janito.provider_registry import ProviderRegistry
|
91
|
+
|
92
|
+
provider_instance = None
|
93
|
+
provider_instance = ProviderRegistry().get_instance(provider)
|
94
|
+
if provider_instance is None:
|
95
|
+
return provider, None, None
|
96
|
+
try:
|
97
|
+
if not provider_instance.is_model_available(model):
|
98
|
+
print(
|
99
|
+
f"Error: Model '{model}' is not available for provider '{provider}'."
|
100
|
+
)
|
101
|
+
# Optionally, print available models if possible
|
102
|
+
if hasattr(provider_instance, "get_model_info"):
|
103
|
+
available_models = [
|
104
|
+
m["name"]
|
105
|
+
for m in provider_instance.get_model_info().values()
|
106
|
+
if isinstance(m, dict) and "name" in m
|
107
|
+
]
|
108
|
+
print(f"Available models: {', '.join(available_models)}")
|
109
|
+
return provider, None, None
|
110
|
+
except Exception as e:
|
111
|
+
print(f"Error validating model for provider '{provider}': {e}")
|
112
|
+
return provider, None, None
|
113
|
+
driver_config_data = _populate_driver_config_data(args, modifiers, provider, model)
|
114
|
+
llm_driver_config = LLMDriverConfig(**driver_config_data)
|
115
|
+
if getattr(llm_driver_config, "verbose_api", None):
|
116
|
+
pass
|
117
|
+
|
118
|
+
agent_role = modifiers.get("profile") or "developer"
|
119
|
+
return provider, llm_driver_config, agent_role
|
120
|
+
|
121
|
+
|
122
|
+
def handle_runner(
|
123
|
+
args,
|
124
|
+
provider,
|
125
|
+
llm_driver_config,
|
126
|
+
agent_role,
|
127
|
+
verbose_tools=False,
|
128
|
+
):
|
129
|
+
"""
|
130
|
+
Main runner for CLI execution. If exec_enabled is False, disables execution/run tools.
|
131
|
+
"""
|
132
|
+
zero_mode = getattr(args, "zero", False)
|
133
|
+
from janito.provider_registry import ProviderRegistry
|
134
|
+
|
135
|
+
# Patch: disable execution/run tools if not enabled
|
136
|
+
import janito.tools
|
137
|
+
from janito.tools.tool_base import ToolPermissions
|
138
|
+
|
139
|
+
read = getattr(args, "read", False)
|
140
|
+
write = getattr(args, "write", False)
|
141
|
+
execute = getattr(args, "exec", False)
|
142
|
+
from janito.tools.permissions import set_global_allowed_permissions
|
143
|
+
from janito.tools.tool_base import ToolPermissions
|
144
|
+
|
145
|
+
allowed_permissions = ToolPermissions(read=read, write=write, execute=execute)
|
146
|
+
set_global_allowed_permissions(allowed_permissions)
|
147
|
+
# Store the default permissions for later restoration (e.g., on /restart)
|
148
|
+
from janito.tools.permissions import set_default_allowed_permissions
|
149
|
+
|
150
|
+
set_default_allowed_permissions(allowed_permissions)
|
151
|
+
|
152
|
+
# Load disabled tools from config
|
153
|
+
from janito.tools.disabled_tools import load_disabled_tools_from_config
|
154
|
+
|
155
|
+
load_disabled_tools_from_config()
|
156
|
+
|
157
|
+
# Disable bash tools when running in PowerShell
|
158
|
+
from janito.platform_discovery import PlatformDiscovery
|
159
|
+
|
160
|
+
pd = PlatformDiscovery()
|
161
|
+
if pd.detect_shell().startswith("PowerShell"):
|
162
|
+
from janito.tools.disabled_tools import DisabledToolsState
|
163
|
+
|
164
|
+
DisabledToolsState.disable_tool("run_bash_command")
|
165
|
+
|
166
|
+
unrestricted = getattr(args, "unrestricted", False)
|
167
|
+
adapter = janito.tools.get_local_tools_adapter(
|
168
|
+
workdir=getattr(args, "workdir", None)
|
169
|
+
)
|
170
|
+
if unrestricted:
|
171
|
+
# Patch: disable path security enforcement for this adapter instance
|
172
|
+
setattr(adapter, "unrestricted_paths", True)
|
173
|
+
|
174
|
+
# Also disable URL whitelist restrictions in unrestricted mode
|
175
|
+
from janito.tools.url_whitelist import get_url_whitelist_manager
|
176
|
+
|
177
|
+
whitelist_manager = get_url_whitelist_manager()
|
178
|
+
whitelist_manager.set_unrestricted_mode(True)
|
179
|
+
|
180
|
+
# Print allowed permissions in verbose mode
|
181
|
+
if getattr(args, "verbose", False):
|
182
|
+
print_verbose_info(
|
183
|
+
"Allowed Tool Permissions",
|
184
|
+
f"read={read}, write={write}, execute={execute}",
|
185
|
+
style="yellow",
|
186
|
+
)
|
187
|
+
|
188
|
+
provider_instance = ProviderRegistry().get_instance(provider, llm_driver_config)
|
189
|
+
if provider_instance is None:
|
190
|
+
return
|
191
|
+
mode = get_prompt_mode(args)
|
192
|
+
if getattr(args, "verbose", False):
|
193
|
+
print_verbose_info(
|
194
|
+
"Active LLMDriverConfig (after provider)", llm_driver_config, style="green"
|
195
|
+
)
|
196
|
+
print_verbose_info("Agent role", agent_role, style="green")
|
197
|
+
|
198
|
+
# Skip chat mode for list commands - handle them directly
|
199
|
+
from janito.cli.core.getters import GETTER_KEYS
|
200
|
+
|
201
|
+
skip_chat_mode = False
|
202
|
+
if args is not None:
|
203
|
+
for key in GETTER_KEYS:
|
204
|
+
if getattr(args, key, False):
|
205
|
+
skip_chat_mode = True
|
206
|
+
break
|
207
|
+
|
208
|
+
if skip_chat_mode:
|
209
|
+
# Handle list commands directly without prompt
|
210
|
+
from janito.cli.core.getters import handle_getter
|
211
|
+
|
212
|
+
handle_getter(args)
|
213
|
+
elif mode == "single_shot":
|
214
|
+
from janito.cli.single_shot_mode.handler import (
|
215
|
+
PromptHandler as SingleShotPromptHandler,
|
216
|
+
)
|
217
|
+
|
218
|
+
# DEBUG: Print exec_enabled propagation at runner
|
219
|
+
|
220
|
+
handler = SingleShotPromptHandler(
|
221
|
+
args,
|
222
|
+
provider_instance,
|
223
|
+
llm_driver_config,
|
224
|
+
role=agent_role,
|
225
|
+
allowed_permissions=allowed_permissions,
|
226
|
+
)
|
227
|
+
handler.handle()
|
228
|
+
else:
|
229
|
+
from janito.cli.chat_mode.session import ChatSession
|
230
|
+
from rich.console import Console
|
231
|
+
|
232
|
+
console = Console()
|
233
|
+
session = ChatSession(
|
234
|
+
console,
|
235
|
+
provider_instance,
|
236
|
+
llm_driver_config,
|
237
|
+
role=agent_role,
|
238
|
+
args=args,
|
239
|
+
verbose_tools=verbose_tools,
|
240
|
+
verbose_agent=getattr(args, "verbose_agent", False),
|
241
|
+
allowed_permissions=allowed_permissions,
|
242
|
+
)
|
243
|
+
session.run()
|
244
|
+
|
245
|
+
|
246
|
+
def get_prompt_mode(args):
|
247
|
+
# If interactive flag is set, force chat mode regardless of user_prompt
|
248
|
+
if getattr(args, "interactive", False):
|
249
|
+
return "chat_mode"
|
250
|
+
return "single_shot" if getattr(args, "user_prompt", None) else "chat_mode"
|