janito 3.12.1__py3-none-any.whl → 3.12.3__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/read_files.py +1 -1
- janito/plugins/tools/local/replace_text_in_file.py +1 -1
- janito/plugins/tools/local/search_text/core.py +2 -2
- janito/plugins/tools/local/show_image.py +119 -74
- janito/plugins/tools/local/show_image_grid.py +134 -76
- janito/plugins/tools/local/view_file.py +3 -3
- janito/providers/alibaba/model_info.py +136 -105
- janito/providers/alibaba/provider.py +104 -104
- {janito-3.12.1.dist-info → janito-3.12.3.dist-info}/METADATA +1 -1
- {janito-3.12.1.dist-info → janito-3.12.3.dist-info}/RECORD +27 -25
- {janito-3.12.1.dist-info → janito-3.12.3.dist-info}/WHEEL +0 -0
- {janito-3.12.1.dist-info → janito-3.12.3.dist-info}/entry_points.txt +0 -0
- {janito-3.12.1.dist-info → janito-3.12.3.dist-info}/licenses/LICENSE +0 -0
- {janito-3.12.1.dist-info → janito-3.12.3.dist-info}/top_level.txt +0 -0
janito/cli/main_cli.py
CHANGED
@@ -1,519 +1,520 @@
|
|
1
|
-
import argparse
|
2
|
-
import sys
|
3
|
-
import enum
|
4
|
-
from janito.cli.core.setters import handle_api_key_set, handle_set
|
5
|
-
from janito.cli.core.getters import handle_getter
|
6
|
-
from janito.cli.core.runner import (
|
7
|
-
prepare_llm_driver_config,
|
8
|
-
handle_runner,
|
9
|
-
get_prompt_mode,
|
10
|
-
)
|
11
|
-
from janito.cli.core.event_logger import (
|
12
|
-
setup_event_logger_if_needed,
|
13
|
-
inject_debug_event_bus_if_needed,
|
14
|
-
)
|
15
|
-
|
16
|
-
|
17
|
-
definition = [
|
18
|
-
(
|
19
|
-
["-u", "--unrestricted"],
|
20
|
-
{
|
21
|
-
"action": "store_true",
|
22
|
-
"help": "Unrestricted mode: disable path security and URL whitelist restrictions (DANGEROUS)",
|
23
|
-
},
|
24
|
-
),
|
25
|
-
(
|
26
|
-
["--multi"],
|
27
|
-
{
|
28
|
-
"action": "store_true",
|
29
|
-
"help": "Start chat mode with multi-line input as default (no need for /multi command)",
|
30
|
-
},
|
31
|
-
),
|
32
|
-
(
|
33
|
-
["--profile"],
|
34
|
-
{
|
35
|
-
"metavar": "PROFILE",
|
36
|
-
"help": "Select the profile name for the system prompt (e.g. 'developer').",
|
37
|
-
"default": None,
|
38
|
-
},
|
39
|
-
),
|
40
|
-
(
|
41
|
-
["--developer"],
|
42
|
-
{
|
43
|
-
"action": "store_true",
|
44
|
-
"help": "Start with the Python developer profile (equivalent to --profile 'Developer
|
45
|
-
},
|
46
|
-
),
|
47
|
-
(
|
48
|
-
["--market"],
|
49
|
-
{
|
50
|
-
"action": "store_true",
|
51
|
-
"help": "Start with the Market Analyst profile (equivalent to --profile 'Market Analyst')",
|
52
|
-
},
|
53
|
-
),
|
54
|
-
(
|
55
|
-
["-W", "--workdir"],
|
56
|
-
{
|
57
|
-
"metavar": "WORKDIR",
|
58
|
-
"help": "Working directory to chdir to before tool execution",
|
59
|
-
"default": None,
|
60
|
-
},
|
61
|
-
),
|
62
|
-
(
|
63
|
-
["--verbose-api"],
|
64
|
-
{
|
65
|
-
"action": "store_true",
|
66
|
-
"help": "Print API calls and responses of LLM driver APIs for debugging/tracing.",
|
67
|
-
},
|
68
|
-
),
|
69
|
-
(
|
70
|
-
["--verbose-tools"],
|
71
|
-
{
|
72
|
-
"action": "store_true",
|
73
|
-
"help": "Print info messages for tool execution in tools adapter.",
|
74
|
-
},
|
75
|
-
),
|
76
|
-
(
|
77
|
-
["--verbose-agent"],
|
78
|
-
{
|
79
|
-
"action": "store_true",
|
80
|
-
"help": "Print info messages for agent event and message part handling.",
|
81
|
-
},
|
82
|
-
),
|
83
|
-
(
|
84
|
-
["-z", "--zero"],
|
85
|
-
{
|
86
|
-
"action": "store_true",
|
87
|
-
"help": "IDE zero mode: disables system prompt & all tools for raw LLM interaction",
|
88
|
-
},
|
89
|
-
),
|
90
|
-
(
|
91
|
-
["-x", "--exec"],
|
92
|
-
{
|
93
|
-
"action": "store_true",
|
94
|
-
"help": "Enable execution/run tools (allows running code or shell tools from the CLI)",
|
95
|
-
},
|
96
|
-
),
|
97
|
-
(
|
98
|
-
["-r", "--read"],
|
99
|
-
{
|
100
|
-
"action": "store_true",
|
101
|
-
"help": "Enable tools that require read permissions",
|
102
|
-
},
|
103
|
-
),
|
104
|
-
(
|
105
|
-
["-w", "--write"],
|
106
|
-
{
|
107
|
-
"action": "store_true",
|
108
|
-
"help": "Enable tools that require write permissions",
|
109
|
-
},
|
110
|
-
),
|
111
|
-
(["--unset"], {"metavar": "KEY", "help": "Unset (remove) a config key"}),
|
112
|
-
(["--version"], {"action": "version", "version": None}),
|
113
|
-
(["--list-tools"], {"action": "store_true", "help": "List all registered tools"}),
|
114
|
-
(["--show-config"], {"action": "store_true", "help": "Show the current config"}),
|
115
|
-
(
|
116
|
-
["--list-config"],
|
117
|
-
{"action": "store_true", "help": "List all configuration files"},
|
118
|
-
),
|
119
|
-
(
|
120
|
-
["--list-profiles"],
|
121
|
-
{"action": "store_true", "help": "List available system prompt profiles"},
|
122
|
-
),
|
123
|
-
(
|
124
|
-
["--list-providers"],
|
125
|
-
{"action": "store_true", "help": "List supported LLM providers"},
|
126
|
-
),
|
127
|
-
(
|
128
|
-
["--ping"],
|
129
|
-
{
|
130
|
-
"action": "store_true",
|
131
|
-
"help": "Ping/test connectivity for all providers (use with --list-providers)",
|
132
|
-
},
|
133
|
-
),
|
134
|
-
(
|
135
|
-
["--list-drivers"],
|
136
|
-
{
|
137
|
-
"action": "store_true",
|
138
|
-
"help": "List available LLM drivers and their dependencies",
|
139
|
-
},
|
140
|
-
),
|
141
|
-
(
|
142
|
-
["--region-info"],
|
143
|
-
{
|
144
|
-
"action": "store_true",
|
145
|
-
"help": "Show current region information and location",
|
146
|
-
},
|
147
|
-
),
|
148
|
-
(
|
149
|
-
["--list-providers-region"],
|
150
|
-
{
|
151
|
-
"action": "store_true",
|
152
|
-
"help": "List all providers with their regional API information",
|
153
|
-
},
|
154
|
-
),
|
155
|
-
(
|
156
|
-
["-l", "--list-models"],
|
157
|
-
{"action": "store_true", "help": "List all supported models"},
|
158
|
-
),
|
159
|
-
(
|
160
|
-
["--set-api-key"],
|
161
|
-
{
|
162
|
-
"metavar": "API_KEY",
|
163
|
-
"help": "Set API key for the provider (requires -p PROVIDER)",
|
164
|
-
},
|
165
|
-
),
|
166
|
-
(["--set"], {"metavar": "KEY=VALUE", "help": "Set a config key"}),
|
167
|
-
(["-s", "--system"], {"metavar": "SYSTEM_PROMPT", "help": "Set a system prompt"}),
|
168
|
-
(
|
169
|
-
["-S", "--show-system"],
|
170
|
-
{
|
171
|
-
"action": "store_true",
|
172
|
-
"help": "Show the resolved system prompt for the main agent",
|
173
|
-
},
|
174
|
-
),
|
175
|
-
(["-p", "--provider"], {"metavar": "PROVIDER", "help": "Select the provider"}),
|
176
|
-
(["-m", "--model"], {"metavar": "MODEL", "help": "Select the model"}),
|
177
|
-
(
|
178
|
-
["-t", "--temperature"],
|
179
|
-
{"type": float, "default": None, "help": "Set the temperature"},
|
180
|
-
),
|
181
|
-
(
|
182
|
-
["-v", "--verbose"],
|
183
|
-
{"action": "store_true", "help": "Print extra information before answering"},
|
184
|
-
),
|
185
|
-
(
|
186
|
-
["-R", "--raw"],
|
187
|
-
{
|
188
|
-
"action": "store_true",
|
189
|
-
"help": "Print the raw JSON response from the OpenAI API (if applicable)",
|
190
|
-
},
|
191
|
-
),
|
192
|
-
(
|
193
|
-
["--effort"],
|
194
|
-
{
|
195
|
-
"choices": ["low", "medium", "high", "none"],
|
196
|
-
"default": None,
|
197
|
-
"help": "Set the reasoning effort for models that support it (low, medium, high, none)",
|
198
|
-
},
|
199
|
-
),
|
200
|
-
(
|
201
|
-
["--emoji"],
|
202
|
-
{
|
203
|
-
"action": "store_true",
|
204
|
-
"help": "Enable emoji usage in responses to make output more engaging and expressive",
|
205
|
-
},
|
206
|
-
),
|
207
|
-
(
|
208
|
-
["-i", "--interactive"],
|
209
|
-
{
|
210
|
-
"action": "store_true",
|
211
|
-
"help": "Signal that this is an interactive chat session",
|
212
|
-
},
|
213
|
-
),
|
214
|
-
(["user_prompt"], {"nargs": argparse.REMAINDER, "help": "Prompt to submit"}),
|
215
|
-
(
|
216
|
-
["-e", "--event-log"],
|
217
|
-
{"action": "store_true", "help": "Enable event logging to the system bus"},
|
218
|
-
),
|
219
|
-
(
|
220
|
-
["--event-debug"],
|
221
|
-
{
|
222
|
-
"action": "store_true",
|
223
|
-
"help": "Print debug info on event subscribe/submit methods",
|
224
|
-
},
|
225
|
-
),
|
226
|
-
(
|
227
|
-
["-c", "--config"],
|
228
|
-
{
|
229
|
-
"metavar": "NAME",
|
230
|
-
"help": "Use custom configuration file ~/.janito/configs/NAME.json instead of default config.json",
|
231
|
-
},
|
232
|
-
),
|
233
|
-
(
|
234
|
-
["--list-plugins"],
|
235
|
-
{"action": "store_true", "help": "List all loaded plugins"},
|
236
|
-
),
|
237
|
-
(
|
238
|
-
["--list-plugins-available"],
|
239
|
-
{"action": "store_true", "help": "List all available plugins"},
|
240
|
-
),
|
241
|
-
(
|
242
|
-
["--list-resources"],
|
243
|
-
{
|
244
|
-
"action": "store_true",
|
245
|
-
"help": "List all resources (tools, commands, config) from loaded plugins",
|
246
|
-
},
|
247
|
-
),
|
248
|
-
]
|
249
|
-
|
250
|
-
MODIFIER_KEYS = [
|
251
|
-
"provider",
|
252
|
-
"model",
|
253
|
-
"profile",
|
254
|
-
"developer",
|
255
|
-
"market",
|
256
|
-
"system",
|
257
|
-
"temperature",
|
258
|
-
"verbose",
|
259
|
-
"raw",
|
260
|
-
"verbose_api",
|
261
|
-
"verbose_tools",
|
262
|
-
"exec",
|
263
|
-
"read",
|
264
|
-
"write",
|
265
|
-
"emoji",
|
266
|
-
"interactive",
|
267
|
-
]
|
268
|
-
SETTER_KEYS = ["set", "set_provider", "set_api_key", "unset"]
|
269
|
-
GETTER_KEYS = [
|
270
|
-
"show_config",
|
271
|
-
"list_providers",
|
272
|
-
"list_profiles",
|
273
|
-
"list_models",
|
274
|
-
"list_tools",
|
275
|
-
"list_config",
|
276
|
-
"list_drivers",
|
277
|
-
"region_info",
|
278
|
-
"list_providers_region",
|
279
|
-
"ping",
|
280
|
-
]
|
281
|
-
GETTER_KEYS = [
|
282
|
-
"show_config",
|
283
|
-
"list_providers",
|
284
|
-
"list_profiles",
|
285
|
-
"list_models",
|
286
|
-
"list_tools",
|
287
|
-
"list_config",
|
288
|
-
"list_drivers",
|
289
|
-
"region_info",
|
290
|
-
"list_providers_region",
|
291
|
-
"ping",
|
292
|
-
]
|
293
|
-
|
294
|
-
|
295
|
-
class RunMode(enum.Enum):
|
296
|
-
GET = "get"
|
297
|
-
SET = "set"
|
298
|
-
RUN = "run"
|
299
|
-
|
300
|
-
|
301
|
-
class JanitoCLI:
|
302
|
-
def __init__(self):
|
303
|
-
import janito.tools
|
304
|
-
|
305
|
-
self.parser = argparse.ArgumentParser(
|
306
|
-
description="Janito CLI - A tool for running LLM-powered workflows from the command line."
|
307
|
-
"\n\nExample usage: janito -p moonshot -m kimi-k1-8k 'Your prompt here'\n\n"
|
308
|
-
"Use -m or --model to set the model for the session.",
|
309
|
-
)
|
310
|
-
self._define_args()
|
311
|
-
self.args = self.parser.parse_args()
|
312
|
-
self._set_all_arg_defaults()
|
313
|
-
# Support custom config file via -c/--config
|
314
|
-
if getattr(self.args, "config", None):
|
315
|
-
from janito import config as global_config
|
316
|
-
from janito.config_manager import ConfigManager
|
317
|
-
import sys
|
318
|
-
import importlib
|
319
|
-
|
320
|
-
config_name = self.args.config
|
321
|
-
# Re-initialize the global config singleton
|
322
|
-
new_config = ConfigManager(config_name=config_name)
|
323
|
-
# Ensure the config path is updated when the singleton already existed
|
324
|
-
from pathlib import Path
|
325
|
-
|
326
|
-
new_config.config_path = (
|
327
|
-
Path.home() / ".janito" / "configs" / f"{config_name}.json"
|
328
|
-
)
|
329
|
-
# Reload config from the selected file
|
330
|
-
new_config._load_file_config()
|
331
|
-
# Patch the global singleton reference
|
332
|
-
import janito.config as config_module
|
333
|
-
|
334
|
-
config_module.config = new_config
|
335
|
-
sys.modules["janito.config"].config = new_config
|
336
|
-
# Support reading prompt from stdin if no user_prompt is given
|
337
|
-
import sys
|
338
|
-
|
339
|
-
if not sys.stdin.isatty():
|
340
|
-
stdin_input = sys.stdin.read().strip()
|
341
|
-
if stdin_input:
|
342
|
-
if self.args.user_prompt and len(self.args.user_prompt) > 0:
|
343
|
-
# Prefix the prompt argument to the stdin input
|
344
|
-
combined = " ".join(self.args.user_prompt) + " " + stdin_input
|
345
|
-
self.args.user_prompt = [combined]
|
346
|
-
else:
|
347
|
-
self.args.user_prompt = [stdin_input]
|
348
|
-
from janito.cli.rich_terminal_reporter import RichTerminalReporter
|
349
|
-
|
350
|
-
self.rich_reporter = RichTerminalReporter(raw_mode=self.args.raw)
|
351
|
-
|
352
|
-
def _define_args(self):
|
353
|
-
for argnames, argkwargs in definition:
|
354
|
-
# Patch version argument dynamically with real version
|
355
|
-
if "--version" in argnames:
|
356
|
-
from janito import __version__ as janito_version
|
357
|
-
|
358
|
-
argkwargs["version"] = f"Janito {janito_version}"
|
359
|
-
self.parser.add_argument(*argnames, **argkwargs)
|
360
|
-
|
361
|
-
def _set_all_arg_defaults(self):
|
362
|
-
# Gather all possible keys from definition, MODIFIER_KEYS, SETTER_KEYS, GETTER_KEYS
|
363
|
-
all_keys = set()
|
364
|
-
for argnames, argkwargs in definition:
|
365
|
-
for name in argnames:
|
366
|
-
key = name.lstrip("-").replace("-", "_")
|
367
|
-
all_keys.add(key)
|
368
|
-
all_keys.update(MODIFIER_KEYS)
|
369
|
-
all_keys.update(SETTER_KEYS)
|
370
|
-
all_keys.update(GETTER_KEYS)
|
371
|
-
# Set defaults for all keys if not present
|
372
|
-
for key in all_keys:
|
373
|
-
if not hasattr(self.args, key):
|
374
|
-
setattr(self.args, key, None)
|
375
|
-
|
376
|
-
def collect_modifiers(self):
|
377
|
-
modifiers = {
|
378
|
-
k: getattr(self.args, k)
|
379
|
-
for k in MODIFIER_KEYS
|
380
|
-
if getattr(self.args, k, None) is not None
|
381
|
-
}
|
382
|
-
|
383
|
-
return modifiers
|
384
|
-
|
385
|
-
def classify(self):
|
386
|
-
if any(getattr(self.args, k, None) for k in SETTER_KEYS):
|
387
|
-
return RunMode.SET
|
388
|
-
if any(getattr(self.args, k, None) for k in GETTER_KEYS):
|
389
|
-
return RunMode.GET
|
390
|
-
return RunMode.RUN
|
391
|
-
|
392
|
-
def run(self):
|
393
|
-
# Handle --show-system/-S before anything else
|
394
|
-
if getattr(self.args, "show_system", False):
|
395
|
-
from janito.cli.cli_commands.show_system_prompt import (
|
396
|
-
handle_show_system_prompt,
|
397
|
-
)
|
398
|
-
|
399
|
-
handle_show_system_prompt(self.args)
|
400
|
-
return
|
401
|
-
run_mode = self.classify()
|
402
|
-
if run_mode == RunMode.SET:
|
403
|
-
if self._run_set_mode():
|
404
|
-
return
|
405
|
-
# Special handling: provider is not required for list commands
|
406
|
-
if run_mode == RunMode.GET and (
|
407
|
-
self.args.list_providers
|
408
|
-
or self.args.
|
409
|
-
or self.args.
|
410
|
-
or self.args.
|
411
|
-
or self.args.
|
412
|
-
or self.args.
|
413
|
-
or self.args.
|
414
|
-
or self.args.
|
415
|
-
or self.args.
|
416
|
-
or self.args.
|
417
|
-
|
418
|
-
|
419
|
-
|
420
|
-
|
421
|
-
|
422
|
-
|
423
|
-
|
424
|
-
self.args.
|
425
|
-
self.args.
|
426
|
-
|
427
|
-
|
428
|
-
|
429
|
-
|
430
|
-
#
|
431
|
-
#
|
432
|
-
if
|
433
|
-
|
434
|
-
|
435
|
-
|
436
|
-
|
437
|
-
|
438
|
-
|
439
|
-
|
440
|
-
|
441
|
-
|
442
|
-
|
443
|
-
self.
|
444
|
-
|
445
|
-
|
446
|
-
|
447
|
-
|
448
|
-
|
449
|
-
|
450
|
-
|
451
|
-
|
452
|
-
|
453
|
-
|
454
|
-
|
455
|
-
|
456
|
-
|
457
|
-
|
458
|
-
|
459
|
-
|
460
|
-
|
461
|
-
|
462
|
-
|
463
|
-
|
464
|
-
|
465
|
-
|
466
|
-
|
467
|
-
|
468
|
-
|
469
|
-
|
470
|
-
|
471
|
-
|
472
|
-
|
473
|
-
|
474
|
-
|
475
|
-
|
476
|
-
|
477
|
-
|
478
|
-
|
479
|
-
|
480
|
-
|
481
|
-
|
482
|
-
|
483
|
-
|
484
|
-
|
485
|
-
|
486
|
-
|
487
|
-
|
488
|
-
|
489
|
-
|
490
|
-
|
491
|
-
|
492
|
-
|
493
|
-
|
494
|
-
|
495
|
-
|
496
|
-
|
497
|
-
|
498
|
-
|
499
|
-
|
500
|
-
|
501
|
-
|
502
|
-
|
503
|
-
|
504
|
-
print_verbose_info(
|
505
|
-
|
506
|
-
|
507
|
-
|
508
|
-
|
509
|
-
|
510
|
-
|
511
|
-
|
512
|
-
|
513
|
-
|
514
|
-
|
515
|
-
|
516
|
-
|
517
|
-
|
518
|
-
|
519
|
-
cli
|
1
|
+
import argparse
|
2
|
+
import sys
|
3
|
+
import enum
|
4
|
+
from janito.cli.core.setters import handle_api_key_set, handle_set
|
5
|
+
from janito.cli.core.getters import handle_getter
|
6
|
+
from janito.cli.core.runner import (
|
7
|
+
prepare_llm_driver_config,
|
8
|
+
handle_runner,
|
9
|
+
get_prompt_mode,
|
10
|
+
)
|
11
|
+
from janito.cli.core.event_logger import (
|
12
|
+
setup_event_logger_if_needed,
|
13
|
+
inject_debug_event_bus_if_needed,
|
14
|
+
)
|
15
|
+
|
16
|
+
|
17
|
+
definition = [
|
18
|
+
(
|
19
|
+
["-u", "--unrestricted"],
|
20
|
+
{
|
21
|
+
"action": "store_true",
|
22
|
+
"help": "Unrestricted mode: disable path security and URL whitelist restrictions (DANGEROUS)",
|
23
|
+
},
|
24
|
+
),
|
25
|
+
(
|
26
|
+
["--multi"],
|
27
|
+
{
|
28
|
+
"action": "store_true",
|
29
|
+
"help": "Start chat mode with multi-line input as default (no need for /multi command)",
|
30
|
+
},
|
31
|
+
),
|
32
|
+
(
|
33
|
+
["--profile"],
|
34
|
+
{
|
35
|
+
"metavar": "PROFILE",
|
36
|
+
"help": "Select the profile name for the system prompt (e.g. 'developer').",
|
37
|
+
"default": None,
|
38
|
+
},
|
39
|
+
),
|
40
|
+
(
|
41
|
+
["--developer"],
|
42
|
+
{
|
43
|
+
"action": "store_true",
|
44
|
+
"help": "Start with the Python developer profile (equivalent to --profile 'Developer')",
|
45
|
+
},
|
46
|
+
),
|
47
|
+
(
|
48
|
+
["--market"],
|
49
|
+
{
|
50
|
+
"action": "store_true",
|
51
|
+
"help": "Start with the Market Analyst profile (equivalent to --profile 'Market Analyst')",
|
52
|
+
},
|
53
|
+
),
|
54
|
+
(
|
55
|
+
["-W", "--workdir"],
|
56
|
+
{
|
57
|
+
"metavar": "WORKDIR",
|
58
|
+
"help": "Working directory to chdir to before tool execution",
|
59
|
+
"default": None,
|
60
|
+
},
|
61
|
+
),
|
62
|
+
(
|
63
|
+
["--verbose-api"],
|
64
|
+
{
|
65
|
+
"action": "store_true",
|
66
|
+
"help": "Print API calls and responses of LLM driver APIs for debugging/tracing.",
|
67
|
+
},
|
68
|
+
),
|
69
|
+
(
|
70
|
+
["--verbose-tools"],
|
71
|
+
{
|
72
|
+
"action": "store_true",
|
73
|
+
"help": "Print info messages for tool execution in tools adapter.",
|
74
|
+
},
|
75
|
+
),
|
76
|
+
(
|
77
|
+
["--verbose-agent"],
|
78
|
+
{
|
79
|
+
"action": "store_true",
|
80
|
+
"help": "Print info messages for agent event and message part handling.",
|
81
|
+
},
|
82
|
+
),
|
83
|
+
(
|
84
|
+
["-z", "--zero"],
|
85
|
+
{
|
86
|
+
"action": "store_true",
|
87
|
+
"help": "IDE zero mode: disables system prompt & all tools for raw LLM interaction",
|
88
|
+
},
|
89
|
+
),
|
90
|
+
(
|
91
|
+
["-x", "--exec"],
|
92
|
+
{
|
93
|
+
"action": "store_true",
|
94
|
+
"help": "Enable execution/run tools (allows running code or shell tools from the CLI)",
|
95
|
+
},
|
96
|
+
),
|
97
|
+
(
|
98
|
+
["-r", "--read"],
|
99
|
+
{
|
100
|
+
"action": "store_true",
|
101
|
+
"help": "Enable tools that require read permissions",
|
102
|
+
},
|
103
|
+
),
|
104
|
+
(
|
105
|
+
["-w", "--write"],
|
106
|
+
{
|
107
|
+
"action": "store_true",
|
108
|
+
"help": "Enable tools that require write permissions",
|
109
|
+
},
|
110
|
+
),
|
111
|
+
(["--unset"], {"metavar": "KEY", "help": "Unset (remove) a config key"}),
|
112
|
+
(["--version"], {"action": "version", "version": None}),
|
113
|
+
(["--list-tools"], {"action": "store_true", "help": "List all registered tools"}),
|
114
|
+
(["--show-config"], {"action": "store_true", "help": "Show the current config"}),
|
115
|
+
(
|
116
|
+
["--list-config"],
|
117
|
+
{"action": "store_true", "help": "List all configuration files"},
|
118
|
+
),
|
119
|
+
(
|
120
|
+
["--list-profiles"],
|
121
|
+
{"action": "store_true", "help": "List available system prompt profiles"},
|
122
|
+
),
|
123
|
+
(
|
124
|
+
["--list-providers"],
|
125
|
+
{"action": "store_true", "help": "List supported LLM providers"},
|
126
|
+
),
|
127
|
+
(
|
128
|
+
["--ping"],
|
129
|
+
{
|
130
|
+
"action": "store_true",
|
131
|
+
"help": "Ping/test connectivity for all providers (use with --list-providers)",
|
132
|
+
},
|
133
|
+
),
|
134
|
+
(
|
135
|
+
["--list-drivers"],
|
136
|
+
{
|
137
|
+
"action": "store_true",
|
138
|
+
"help": "List available LLM drivers and their dependencies",
|
139
|
+
},
|
140
|
+
),
|
141
|
+
(
|
142
|
+
["--region-info"],
|
143
|
+
{
|
144
|
+
"action": "store_true",
|
145
|
+
"help": "Show current region information and location",
|
146
|
+
},
|
147
|
+
),
|
148
|
+
(
|
149
|
+
["--list-providers-region"],
|
150
|
+
{
|
151
|
+
"action": "store_true",
|
152
|
+
"help": "List all providers with their regional API information",
|
153
|
+
},
|
154
|
+
),
|
155
|
+
(
|
156
|
+
["-l", "--list-models"],
|
157
|
+
{"action": "store_true", "help": "List all supported models"},
|
158
|
+
),
|
159
|
+
(
|
160
|
+
["--set-api-key"],
|
161
|
+
{
|
162
|
+
"metavar": "API_KEY",
|
163
|
+
"help": "Set API key for the provider (requires -p PROVIDER)",
|
164
|
+
},
|
165
|
+
),
|
166
|
+
(["--set"], {"metavar": "KEY=VALUE", "help": "Set a config key"}),
|
167
|
+
(["-s", "--system"], {"metavar": "SYSTEM_PROMPT", "help": "Set a system prompt"}),
|
168
|
+
(
|
169
|
+
["-S", "--show-system"],
|
170
|
+
{
|
171
|
+
"action": "store_true",
|
172
|
+
"help": "Show the resolved system prompt for the main agent",
|
173
|
+
},
|
174
|
+
),
|
175
|
+
(["-p", "--provider"], {"metavar": "PROVIDER", "help": "Select the provider"}),
|
176
|
+
(["-m", "--model"], {"metavar": "MODEL", "help": "Select the model"}),
|
177
|
+
(
|
178
|
+
["-t", "--temperature"],
|
179
|
+
{"type": float, "default": None, "help": "Set the temperature"},
|
180
|
+
),
|
181
|
+
(
|
182
|
+
["-v", "--verbose"],
|
183
|
+
{"action": "store_true", "help": "Print extra information before answering"},
|
184
|
+
),
|
185
|
+
(
|
186
|
+
["-R", "--raw"],
|
187
|
+
{
|
188
|
+
"action": "store_true",
|
189
|
+
"help": "Print the raw JSON response from the OpenAI API (if applicable)",
|
190
|
+
},
|
191
|
+
),
|
192
|
+
(
|
193
|
+
["--effort"],
|
194
|
+
{
|
195
|
+
"choices": ["low", "medium", "high", "none"],
|
196
|
+
"default": None,
|
197
|
+
"help": "Set the reasoning effort for models that support it (low, medium, high, none)",
|
198
|
+
},
|
199
|
+
),
|
200
|
+
(
|
201
|
+
["--emoji"],
|
202
|
+
{
|
203
|
+
"action": "store_true",
|
204
|
+
"help": "Enable emoji usage in responses to make output more engaging and expressive",
|
205
|
+
},
|
206
|
+
),
|
207
|
+
(
|
208
|
+
["-i", "--interactive"],
|
209
|
+
{
|
210
|
+
"action": "store_true",
|
211
|
+
"help": "Signal that this is an interactive chat session",
|
212
|
+
},
|
213
|
+
),
|
214
|
+
(["user_prompt"], {"nargs": argparse.REMAINDER, "help": "Prompt to submit"}),
|
215
|
+
(
|
216
|
+
["-e", "--event-log"],
|
217
|
+
{"action": "store_true", "help": "Enable event logging to the system bus"},
|
218
|
+
),
|
219
|
+
(
|
220
|
+
["--event-debug"],
|
221
|
+
{
|
222
|
+
"action": "store_true",
|
223
|
+
"help": "Print debug info on event subscribe/submit methods",
|
224
|
+
},
|
225
|
+
),
|
226
|
+
(
|
227
|
+
["-c", "--config"],
|
228
|
+
{
|
229
|
+
"metavar": "NAME",
|
230
|
+
"help": "Use custom configuration file ~/.janito/configs/NAME.json instead of default config.json",
|
231
|
+
},
|
232
|
+
),
|
233
|
+
(
|
234
|
+
["--list-plugins"],
|
235
|
+
{"action": "store_true", "help": "List all loaded plugins"},
|
236
|
+
),
|
237
|
+
(
|
238
|
+
["--list-plugins-available"],
|
239
|
+
{"action": "store_true", "help": "List all available plugins"},
|
240
|
+
),
|
241
|
+
(
|
242
|
+
["--list-resources"],
|
243
|
+
{
|
244
|
+
"action": "store_true",
|
245
|
+
"help": "List all resources (tools, commands, config) from loaded plugins",
|
246
|
+
},
|
247
|
+
),
|
248
|
+
]
|
249
|
+
|
250
|
+
MODIFIER_KEYS = [
|
251
|
+
"provider",
|
252
|
+
"model",
|
253
|
+
"profile",
|
254
|
+
"developer",
|
255
|
+
"market",
|
256
|
+
"system",
|
257
|
+
"temperature",
|
258
|
+
"verbose",
|
259
|
+
"raw",
|
260
|
+
"verbose_api",
|
261
|
+
"verbose_tools",
|
262
|
+
"exec",
|
263
|
+
"read",
|
264
|
+
"write",
|
265
|
+
"emoji",
|
266
|
+
"interactive",
|
267
|
+
]
|
268
|
+
SETTER_KEYS = ["set", "set_provider", "set_api_key", "unset"]
|
269
|
+
GETTER_KEYS = [
|
270
|
+
"show_config",
|
271
|
+
"list_providers",
|
272
|
+
"list_profiles",
|
273
|
+
"list_models",
|
274
|
+
"list_tools",
|
275
|
+
"list_config",
|
276
|
+
"list_drivers",
|
277
|
+
"region_info",
|
278
|
+
"list_providers_region",
|
279
|
+
"ping",
|
280
|
+
]
|
281
|
+
GETTER_KEYS = [
|
282
|
+
"show_config",
|
283
|
+
"list_providers",
|
284
|
+
"list_profiles",
|
285
|
+
"list_models",
|
286
|
+
"list_tools",
|
287
|
+
"list_config",
|
288
|
+
"list_drivers",
|
289
|
+
"region_info",
|
290
|
+
"list_providers_region",
|
291
|
+
"ping",
|
292
|
+
]
|
293
|
+
|
294
|
+
|
295
|
+
class RunMode(enum.Enum):
|
296
|
+
GET = "get"
|
297
|
+
SET = "set"
|
298
|
+
RUN = "run"
|
299
|
+
|
300
|
+
|
301
|
+
class JanitoCLI:
|
302
|
+
def __init__(self):
|
303
|
+
import janito.tools
|
304
|
+
|
305
|
+
self.parser = argparse.ArgumentParser(
|
306
|
+
description="Janito CLI - A tool for running LLM-powered workflows from the command line."
|
307
|
+
"\n\nExample usage: janito -p moonshot -m kimi-k1-8k 'Your prompt here'\n\n"
|
308
|
+
"Use -m or --model to set the model for the session.",
|
309
|
+
)
|
310
|
+
self._define_args()
|
311
|
+
self.args = self.parser.parse_args()
|
312
|
+
self._set_all_arg_defaults()
|
313
|
+
# Support custom config file via -c/--config
|
314
|
+
if getattr(self.args, "config", None):
|
315
|
+
from janito import config as global_config
|
316
|
+
from janito.config_manager import ConfigManager
|
317
|
+
import sys
|
318
|
+
import importlib
|
319
|
+
|
320
|
+
config_name = self.args.config
|
321
|
+
# Re-initialize the global config singleton
|
322
|
+
new_config = ConfigManager(config_name=config_name)
|
323
|
+
# Ensure the config path is updated when the singleton already existed
|
324
|
+
from pathlib import Path
|
325
|
+
|
326
|
+
new_config.config_path = (
|
327
|
+
Path.home() / ".janito" / "configs" / f"{config_name}.json"
|
328
|
+
)
|
329
|
+
# Reload config from the selected file
|
330
|
+
new_config._load_file_config()
|
331
|
+
# Patch the global singleton reference
|
332
|
+
import janito.config as config_module
|
333
|
+
|
334
|
+
config_module.config = new_config
|
335
|
+
sys.modules["janito.config"].config = new_config
|
336
|
+
# Support reading prompt from stdin if no user_prompt is given
|
337
|
+
import sys
|
338
|
+
|
339
|
+
if not sys.stdin.isatty():
|
340
|
+
stdin_input = sys.stdin.read().strip()
|
341
|
+
if stdin_input:
|
342
|
+
if self.args.user_prompt and len(self.args.user_prompt) > 0:
|
343
|
+
# Prefix the prompt argument to the stdin input
|
344
|
+
combined = " ".join(self.args.user_prompt) + " " + stdin_input
|
345
|
+
self.args.user_prompt = [combined]
|
346
|
+
else:
|
347
|
+
self.args.user_prompt = [stdin_input]
|
348
|
+
from janito.cli.rich_terminal_reporter import RichTerminalReporter
|
349
|
+
|
350
|
+
self.rich_reporter = RichTerminalReporter(raw_mode=self.args.raw)
|
351
|
+
|
352
|
+
def _define_args(self):
|
353
|
+
for argnames, argkwargs in definition:
|
354
|
+
# Patch version argument dynamically with real version
|
355
|
+
if "--version" in argnames:
|
356
|
+
from janito import __version__ as janito_version
|
357
|
+
|
358
|
+
argkwargs["version"] = f"Janito {janito_version}"
|
359
|
+
self.parser.add_argument(*argnames, **argkwargs)
|
360
|
+
|
361
|
+
def _set_all_arg_defaults(self):
|
362
|
+
# Gather all possible keys from definition, MODIFIER_KEYS, SETTER_KEYS, GETTER_KEYS
|
363
|
+
all_keys = set()
|
364
|
+
for argnames, argkwargs in definition:
|
365
|
+
for name in argnames:
|
366
|
+
key = name.lstrip("-").replace("-", "_")
|
367
|
+
all_keys.add(key)
|
368
|
+
all_keys.update(MODIFIER_KEYS)
|
369
|
+
all_keys.update(SETTER_KEYS)
|
370
|
+
all_keys.update(GETTER_KEYS)
|
371
|
+
# Set defaults for all keys if not present
|
372
|
+
for key in all_keys:
|
373
|
+
if not hasattr(self.args, key):
|
374
|
+
setattr(self.args, key, None)
|
375
|
+
|
376
|
+
def collect_modifiers(self):
|
377
|
+
modifiers = {
|
378
|
+
k: getattr(self.args, k)
|
379
|
+
for k in MODIFIER_KEYS
|
380
|
+
if getattr(self.args, k, None) is not None
|
381
|
+
}
|
382
|
+
|
383
|
+
return modifiers
|
384
|
+
|
385
|
+
def classify(self):
|
386
|
+
if any(getattr(self.args, k, None) for k in SETTER_KEYS):
|
387
|
+
return RunMode.SET
|
388
|
+
if any(getattr(self.args, k, None) for k in GETTER_KEYS):
|
389
|
+
return RunMode.GET
|
390
|
+
return RunMode.RUN
|
391
|
+
|
392
|
+
def run(self):
|
393
|
+
# Handle --show-system/-S before anything else
|
394
|
+
if getattr(self.args, "show_system", False):
|
395
|
+
from janito.cli.cli_commands.show_system_prompt import (
|
396
|
+
handle_show_system_prompt,
|
397
|
+
)
|
398
|
+
|
399
|
+
handle_show_system_prompt(self.args)
|
400
|
+
return
|
401
|
+
run_mode = self.classify()
|
402
|
+
if run_mode == RunMode.SET:
|
403
|
+
if self._run_set_mode():
|
404
|
+
return
|
405
|
+
# Special handling: provider is not required for list commands
|
406
|
+
if run_mode == RunMode.GET and (
|
407
|
+
self.args.list_providers
|
408
|
+
or self.args.list_models
|
409
|
+
or self.args.list_tools
|
410
|
+
or self.args.list_profiles
|
411
|
+
or self.args.show_config
|
412
|
+
or self.args.list_config
|
413
|
+
or self.args.list_drivers
|
414
|
+
or self.args.list_plugins
|
415
|
+
or self.args.list_plugins_available
|
416
|
+
or self.args.list_resources
|
417
|
+
or self.args.ping
|
418
|
+
):
|
419
|
+
self._maybe_print_verbose_provider_model()
|
420
|
+
handle_getter(self.args)
|
421
|
+
return
|
422
|
+
# Handle /rwx prefix for enabling all permissions
|
423
|
+
if self.args.user_prompt and self.args.user_prompt[0] == "/rwx":
|
424
|
+
self.args.read = True
|
425
|
+
self.args.write = True
|
426
|
+
self.args.exec = True
|
427
|
+
# Remove the /rwx prefix from the prompt
|
428
|
+
self.args.user_prompt = self.args.user_prompt[1:]
|
429
|
+
|
430
|
+
# If running in single shot mode and --profile is not provided, default to 'developer' profile
|
431
|
+
# Skip profile selection for list commands that don't need it
|
432
|
+
# Also skip if interactive mode is enabled (forces chat mode)
|
433
|
+
if get_prompt_mode(self.args) == "single_shot" and not getattr(
|
434
|
+
self.args, "profile", None
|
435
|
+
):
|
436
|
+
self.args.profile = "developer"
|
437
|
+
provider = self._get_provider_or_default()
|
438
|
+
if provider is None:
|
439
|
+
print(
|
440
|
+
"Error: No provider selected and no provider found in config. Please set a provider using '-p PROVIDER', '--set provider=name', or configure a provider."
|
441
|
+
)
|
442
|
+
sys.exit(1)
|
443
|
+
modifiers = self.collect_modifiers()
|
444
|
+
self._maybe_print_verbose_modifiers(modifiers)
|
445
|
+
setup_event_logger_if_needed(self.args)
|
446
|
+
inject_debug_event_bus_if_needed(self.args)
|
447
|
+
provider, llm_driver_config, agent_role = prepare_llm_driver_config(
|
448
|
+
self.args, modifiers
|
449
|
+
)
|
450
|
+
if provider is None or llm_driver_config is None:
|
451
|
+
return
|
452
|
+
self._maybe_print_verbose_llm_config(llm_driver_config, run_mode)
|
453
|
+
if run_mode == RunMode.RUN:
|
454
|
+
self._maybe_print_verbose_run_mode()
|
455
|
+
# DEBUG: Print exec_enabled propagation at main_cli
|
456
|
+
|
457
|
+
handle_runner(
|
458
|
+
self.args,
|
459
|
+
provider,
|
460
|
+
llm_driver_config,
|
461
|
+
agent_role,
|
462
|
+
verbose_tools=self.args.verbose_tools,
|
463
|
+
)
|
464
|
+
|
465
|
+
def _run_set_mode(self):
|
466
|
+
if handle_api_key_set(self.args):
|
467
|
+
return True
|
468
|
+
if handle_set(self.args):
|
469
|
+
return True
|
470
|
+
from janito.cli.core.unsetters import handle_unset
|
471
|
+
|
472
|
+
if handle_unset(self.args):
|
473
|
+
return True
|
474
|
+
return False
|
475
|
+
|
476
|
+
def _get_provider_or_default(self):
|
477
|
+
provider = self.args.provider
|
478
|
+
if provider is None:
|
479
|
+
from janito.provider_config import get_config_provider
|
480
|
+
|
481
|
+
provider = get_config_provider()
|
482
|
+
return provider
|
483
|
+
|
484
|
+
def _maybe_print_verbose_modifiers(self, modifiers):
|
485
|
+
if self.args.verbose:
|
486
|
+
from janito.cli.verbose_output import print_verbose_info
|
487
|
+
|
488
|
+
print_verbose_info("Modifiers collected", modifiers, style="blue")
|
489
|
+
|
490
|
+
def _maybe_print_verbose_provider_model(self):
|
491
|
+
if self.args.verbose:
|
492
|
+
from janito.cli.verbose_output import print_verbose_info
|
493
|
+
|
494
|
+
print_verbose_info(
|
495
|
+
"Validated provider/model",
|
496
|
+
f"Provider: {self.args.provider} | Model: {self.args.model}",
|
497
|
+
style="blue",
|
498
|
+
)
|
499
|
+
|
500
|
+
def _maybe_print_verbose_llm_config(self, llm_driver_config, run_mode):
|
501
|
+
if self.args.verbose:
|
502
|
+
from janito.cli.verbose_output import print_verbose_info
|
503
|
+
|
504
|
+
print_verbose_info("LLMDriverConfig", llm_driver_config, style="cyan")
|
505
|
+
print_verbose_info(
|
506
|
+
"Dispatch branch", run_mode, style="cyan", align_content=True
|
507
|
+
)
|
508
|
+
|
509
|
+
def _maybe_print_verbose_run_mode(self):
|
510
|
+
if self.args.verbose:
|
511
|
+
from janito.cli.verbose_output import print_verbose_info
|
512
|
+
|
513
|
+
print_verbose_info(
|
514
|
+
"Run mode", get_prompt_mode(self.args), style="cyan", align_content=True
|
515
|
+
)
|
516
|
+
|
517
|
+
|
518
|
+
if __name__ == "__main__":
|
519
|
+
cli = JanitoCLI()
|
520
|
+
cli.run()
|