janito 2.27.0__py3-none-any.whl → 2.28.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 +50 -24
- janito/cli/chat_mode/session_profile_select.py +8 -2
- janito/cli/chat_mode/shell/commands/__init__.py +2 -0
- janito/cli/chat_mode/shell/commands/execute.py +4 -2
- janito/cli/chat_mode/shell/commands/help.py +8 -1
- janito/cli/chat_mode/shell/commands/privileges.py +6 -2
- janito/cli/chat_mode/shell/commands/provider.py +28 -0
- 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 +15 -1
- janito/cli/cli_commands/enable_disable_plugin.py +87 -0
- janito/cli/cli_commands/list_models.py +2 -2
- janito/cli/cli_commands/list_plugins.py +35 -19
- 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 +7 -0
- janito/cli/core/model_guesser.py +18 -15
- janito/cli/core/runner.py +28 -6
- janito/cli/core/setters.py +21 -6
- janito/cli/main_cli.py +14 -12
- janito/cli/prompt_core.py +2 -0
- janito/cli/prompt_setup.py +4 -4
- janito/cli/single_shot_mode/handler.py +2 -0
- 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 +88 -0
- janito/plugins/config.py +16 -19
- janito/plugins/discovery.py +129 -40
- janito/plugins/manager.py +63 -59
- 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/ask_user.py +7 -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/search_text/core.py +1 -1
- janito/tools/adapters/local/validate_file_syntax/jinja2_validator.py +14 -11
- janito/tools/base.py +12 -0
- 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.0.dist-info → janito-2.28.0.dist-info}/METADATA +3 -1
- {janito-2.27.0.dist-info → janito-2.28.0.dist-info}/RECORD +81 -82
- janito-2.28.0.dist-info/top_level.txt +1 -0
- janito/providers/moonshotai/__init__.py +0 -1
- janito-2.27.0.dist-info/top_level.txt +0 -2
- janito-coder/janito_coder/__init__.py +0 -9
- janito-coder/janito_coder/plugins/__init__.py +0 -27
- janito-coder/janito_coder/plugins/code_navigator.py +0 -618
- janito-coder/janito_coder/plugins/git_analyzer.py +0 -273
- janito-coder/pyproject.toml +0 -347
- {janito-2.27.0.dist-info → janito-2.28.0.dist-info}/WHEEL +0 -0
- {janito-2.27.0.dist-info → janito-2.28.0.dist-info}/entry_points.txt +0 -0
- {janito-2.27.0.dist-info → janito-2.28.0.dist-info}/licenses/LICENSE +0 -0
janito/cli/core/runner.py
CHANGED
@@ -2,7 +2,9 @@
|
|
2
2
|
|
3
3
|
from janito.llm.driver_config import LLMDriverConfig
|
4
4
|
from janito.provider_config import get_config_provider
|
5
|
-
from janito.cli.core.model_guesser import
|
5
|
+
from janito.cli.core.model_guesser import (
|
6
|
+
guess_provider_from_model as _guess_provider_from_model,
|
7
|
+
)
|
6
8
|
from janito.cli.verbose_output import print_verbose_info
|
7
9
|
|
8
10
|
|
@@ -22,10 +24,13 @@ def _choose_provider(args):
|
|
22
24
|
if guessed_provider:
|
23
25
|
if getattr(args, "verbose", False):
|
24
26
|
print_verbose_info(
|
25
|
-
"Guessed provider",
|
27
|
+
"Guessed provider",
|
28
|
+
guessed_provider,
|
29
|
+
style="magenta",
|
30
|
+
align_content=True,
|
26
31
|
)
|
27
32
|
return guessed_provider
|
28
|
-
|
33
|
+
|
29
34
|
print(
|
30
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."
|
31
36
|
)
|
@@ -151,9 +156,10 @@ def handle_runner(
|
|
151
156
|
if unrestricted:
|
152
157
|
# Patch: disable path security enforcement for this adapter instance
|
153
158
|
setattr(adapter, "unrestricted_paths", True)
|
154
|
-
|
159
|
+
|
155
160
|
# Also disable URL whitelist restrictions in unrestricted mode
|
156
161
|
from janito.tools.url_whitelist import get_url_whitelist_manager
|
162
|
+
|
157
163
|
whitelist_manager = get_url_whitelist_manager()
|
158
164
|
whitelist_manager.set_unrestricted_mode(True)
|
159
165
|
|
@@ -174,7 +180,23 @@ def handle_runner(
|
|
174
180
|
"Active LLMDriverConfig (after provider)", llm_driver_config, style="green"
|
175
181
|
)
|
176
182
|
print_verbose_info("Agent role", agent_role, style="green")
|
177
|
-
|
183
|
+
|
184
|
+
# Skip chat mode for list commands - handle them directly
|
185
|
+
from janito.cli.core.getters import GETTER_KEYS
|
186
|
+
|
187
|
+
skip_chat_mode = False
|
188
|
+
if args is not None:
|
189
|
+
for key in GETTER_KEYS:
|
190
|
+
if getattr(args, key, False):
|
191
|
+
skip_chat_mode = True
|
192
|
+
break
|
193
|
+
|
194
|
+
if skip_chat_mode:
|
195
|
+
# Handle list commands directly without prompt
|
196
|
+
from janito.cli.core.getters import handle_getter
|
197
|
+
|
198
|
+
handle_getter(args)
|
199
|
+
elif mode == "single_shot":
|
178
200
|
from janito.cli.single_shot_mode.handler import (
|
179
201
|
PromptHandler as SingleShotPromptHandler,
|
180
202
|
)
|
@@ -208,4 +230,4 @@ def handle_runner(
|
|
208
230
|
|
209
231
|
|
210
232
|
def get_prompt_mode(args):
|
211
|
-
return "single_shot" if getattr(args, "user_prompt", None) else "chat_mode"
|
233
|
+
return "single_shot" if getattr(args, "user_prompt", None) else "chat_mode"
|
janito/cli/core/setters.py
CHANGED
@@ -71,8 +71,8 @@ def _dispatch_set_key(key, value):
|
|
71
71
|
return True
|
72
72
|
if key == "allowed_sites":
|
73
73
|
from janito.tools.url_whitelist import get_url_whitelist_manager
|
74
|
-
|
75
|
-
sites = [site.strip() for site in value.split(
|
74
|
+
|
75
|
+
sites = [site.strip() for site in value.split(",") if site.strip()]
|
76
76
|
whitelist_manager = get_url_whitelist_manager()
|
77
77
|
whitelist_manager.set_allowed_sites(sites)
|
78
78
|
global_config.file_set("allowed_sites", value)
|
@@ -101,17 +101,32 @@ def _handle_set_base_url(value):
|
|
101
101
|
return True
|
102
102
|
|
103
103
|
|
104
|
-
def
|
104
|
+
def set_provider(value):
|
105
|
+
"""Set the current provider.
|
106
|
+
|
107
|
+
Args:
|
108
|
+
value (str): The provider name to set
|
109
|
+
|
110
|
+
Raises:
|
111
|
+
ValueError: If the provider is not supported
|
112
|
+
"""
|
105
113
|
try:
|
106
114
|
supported = ProviderRegistry().get_provider(value)
|
107
115
|
except Exception:
|
108
|
-
|
109
|
-
f"
|
116
|
+
raise ValueError(
|
117
|
+
f"Provider '{value}' is not supported. Run '--list-providers' to see the supported list."
|
110
118
|
)
|
111
|
-
return True
|
112
119
|
from janito.provider_config import set_config_provider
|
113
120
|
|
114
121
|
set_config_provider(value)
|
122
|
+
|
123
|
+
|
124
|
+
def _handle_set_config_provider(value):
|
125
|
+
try:
|
126
|
+
set_provider(value)
|
127
|
+
except ValueError as e:
|
128
|
+
print(f"Error: {str(e)}")
|
129
|
+
return True
|
115
130
|
print(f"Provider set to '{value}'.")
|
116
131
|
return True
|
117
132
|
|
janito/cli/main_cli.py
CHANGED
@@ -134,7 +134,10 @@ definition = [
|
|
134
134
|
),
|
135
135
|
(
|
136
136
|
["--ping"],
|
137
|
-
{
|
137
|
+
{
|
138
|
+
"action": "store_true",
|
139
|
+
"help": "Ping/test connectivity for all providers (use with --list-providers)",
|
140
|
+
},
|
138
141
|
),
|
139
142
|
(
|
140
143
|
["--list-drivers"],
|
@@ -157,7 +160,6 @@ definition = [
|
|
157
160
|
"help": "List all providers with their regional API information",
|
158
161
|
},
|
159
162
|
),
|
160
|
-
|
161
163
|
(
|
162
164
|
["-l", "--list-models"],
|
163
165
|
{"action": "store_true", "help": "List all supported models"},
|
@@ -232,7 +234,10 @@ definition = [
|
|
232
234
|
),
|
233
235
|
(
|
234
236
|
["--list-resources"],
|
235
|
-
{
|
237
|
+
{
|
238
|
+
"action": "store_true",
|
239
|
+
"help": "List all resources (tools, commands, config) from loaded plugins",
|
240
|
+
},
|
236
241
|
),
|
237
242
|
]
|
238
243
|
|
@@ -292,9 +297,8 @@ class JanitoCLI:
|
|
292
297
|
|
293
298
|
self.parser = argparse.ArgumentParser(
|
294
299
|
description="Janito CLI - A tool for running LLM-powered workflows from the command line."
|
295
|
-
"\n\nExample usage: janito -p
|
300
|
+
"\n\nExample usage: janito -p moonshot -m kimi-k1-8k 'Your prompt here'\n\n"
|
296
301
|
"Use -m or --model to set the model for the session.",
|
297
|
-
|
298
302
|
)
|
299
303
|
self._define_args()
|
300
304
|
self.args = self.parser.parse_args()
|
@@ -346,8 +350,6 @@ class JanitoCLI:
|
|
346
350
|
|
347
351
|
argkwargs["version"] = f"Janito {janito_version}"
|
348
352
|
self.parser.add_argument(*argnames, **argkwargs)
|
349
|
-
|
350
|
-
|
351
353
|
|
352
354
|
def _set_all_arg_defaults(self):
|
353
355
|
# Gather all possible keys from definition, MODIFIER_KEYS, SETTER_KEYS, GETTER_KEYS
|
@@ -405,23 +407,25 @@ class JanitoCLI:
|
|
405
407
|
or self.args.list_drivers
|
406
408
|
or self.args.list_plugins
|
407
409
|
or self.args.list_plugins_available
|
410
|
+
or self.args.list_resources
|
408
411
|
or self.args.ping
|
409
412
|
):
|
410
413
|
self._maybe_print_verbose_provider_model()
|
411
414
|
handle_getter(self.args)
|
412
415
|
return
|
413
416
|
# Handle /rwx prefix for enabling all permissions
|
414
|
-
if self.args.user_prompt and self.args.user_prompt[0] ==
|
417
|
+
if self.args.user_prompt and self.args.user_prompt[0] == "/rwx":
|
415
418
|
self.args.read = True
|
416
419
|
self.args.write = True
|
417
420
|
self.args.exec = True
|
418
421
|
# Remove the /rwx prefix from the prompt
|
419
422
|
self.args.user_prompt = self.args.user_prompt[1:]
|
420
|
-
elif self.args.user_prompt and self.args.user_prompt[0].startswith(
|
423
|
+
elif self.args.user_prompt and self.args.user_prompt[0].startswith("/"):
|
421
424
|
# Skip LLM processing for other commands that start with /
|
422
425
|
return
|
423
|
-
|
426
|
+
|
424
427
|
# If running in single shot mode and --profile is not provided, default to 'developer' profile
|
428
|
+
# Skip profile selection for list commands that don't need it
|
425
429
|
if get_prompt_mode(self.args) == "single_shot" and not getattr(
|
426
430
|
self.args, "profile", None
|
427
431
|
):
|
@@ -453,8 +457,6 @@ class JanitoCLI:
|
|
453
457
|
agent_role,
|
454
458
|
verbose_tools=self.args.verbose_tools,
|
455
459
|
)
|
456
|
-
elif run_mode == RunMode.GET:
|
457
|
-
handle_getter(self.args)
|
458
460
|
|
459
461
|
def _run_set_mode(self):
|
460
462
|
if handle_api_key_set(self.args):
|
janito/cli/prompt_core.py
CHANGED
@@ -216,6 +216,8 @@ class PromptHandler:
|
|
216
216
|
if on_event and final_event is not None:
|
217
217
|
on_event(final_event)
|
218
218
|
global_event_bus.publish(final_event)
|
219
|
+
# Terminal bell moved to token summary printing in session.py and handler.py
|
220
|
+
pass # print('\a', end='', flush=True)
|
219
221
|
except KeyboardInterrupt:
|
220
222
|
# Capture user interrupt / cancellation
|
221
223
|
self.console.print("[red]Interrupted by the user.[/red]")
|
janito/cli/prompt_setup.py
CHANGED
@@ -35,10 +35,10 @@ def setup_agent_and_prompt_handler(
|
|
35
35
|
prompt handler that points to that agent.
|
36
36
|
"""
|
37
37
|
no_tools_mode = False
|
38
|
-
if hasattr(args,
|
39
|
-
no_tools_mode = getattr(args,
|
40
|
-
|
41
|
-
zero_mode = getattr(args,
|
38
|
+
if hasattr(args, "no_tools_mode"):
|
39
|
+
no_tools_mode = getattr(args, "no_tools_mode", False)
|
40
|
+
|
41
|
+
zero_mode = getattr(args, "zero", False)
|
42
42
|
agent = create_configured_agent(
|
43
43
|
provider_instance=provider_instance,
|
44
44
|
llm_driver_config=llm_driver_config,
|
@@ -125,6 +125,8 @@ class PromptHandler:
|
|
125
125
|
print_token_message_summary(
|
126
126
|
shared_console, msg_count=1, usage=usage, elapsed=elapsed
|
127
127
|
)
|
128
|
+
# Send terminal bell character to trigger TUI bell after printing token summary
|
129
|
+
print("\a", end="", flush=True)
|
128
130
|
self._cleanup_driver_and_console()
|
129
131
|
|
130
132
|
def _cleanup_driver_and_console(self):
|
janito/config_manager.py
CHANGED
@@ -60,6 +60,7 @@ class ConfigManager:
|
|
60
60
|
if plugins_config:
|
61
61
|
try:
|
62
62
|
from janito.plugins.manager import PluginManager
|
63
|
+
|
63
64
|
plugin_manager = PluginManager()
|
64
65
|
plugin_manager.load_plugins_from_config({"plugins": plugins_config})
|
65
66
|
except Exception as e:
|
@@ -68,6 +69,7 @@ class ConfigManager:
|
|
68
69
|
# Try loading from user config directory
|
69
70
|
try:
|
70
71
|
from janito.plugins.manager import PluginManager
|
72
|
+
|
71
73
|
plugin_manager = PluginManager()
|
72
74
|
plugin_manager.load_plugins_from_user_config()
|
73
75
|
except Exception as e:
|
janito/docs/GETTING_STARTED.md
CHANGED
@@ -13,7 +13,7 @@ pip install janito
|
|
13
13
|
|
14
14
|
Janito supports multiple AI providers. Choose one to get started:
|
15
15
|
|
16
|
-
**
|
16
|
+
**Moonshot (Recommended for Chinese users)**
|
17
17
|
1. Go to [Moonshot AI Platform](https://platform.moonshot.cn/)
|
18
18
|
2. Sign up for an account
|
19
19
|
3. Navigate to API Keys section
|
@@ -31,10 +31,10 @@ Janito supports multiple AI providers. Choose one to get started:
|
|
31
31
|
|
32
32
|
### 3. Configure Janito
|
33
33
|
|
34
|
-
**
|
34
|
+
**Moonshot Setup:**
|
35
35
|
```bash
|
36
|
-
# Set
|
37
|
-
janito --set-api-key YOUR_API_KEY -p
|
36
|
+
# Set Moonshot as your default provider
|
37
|
+
janito --set-api-key YOUR_API_KEY -p moonshot
|
38
38
|
|
39
39
|
# Verify it's working
|
40
40
|
janito "Hello, can you introduce yourself?"
|
@@ -87,17 +87,17 @@ janito -W ./my_project "Create a REST API with FastAPI"
|
|
87
87
|
### Set as Default Provider
|
88
88
|
```bash
|
89
89
|
# Make your chosen provider the permanent default
|
90
|
-
janito --set provider=
|
90
|
+
janito --set provider=moonshot # or openai, ibm, etc.
|
91
91
|
janito --set model=kimi-k1-8k # or gpt-5, ibm/granite-3-8b-instruct, etc.
|
92
92
|
```
|
93
93
|
|
94
94
|
### Environment Variables
|
95
95
|
You can also use environment variables:
|
96
96
|
|
97
|
-
**
|
97
|
+
**Moonshot:**
|
98
98
|
```bash
|
99
|
-
export
|
100
|
-
export JANITO_PROVIDER=
|
99
|
+
export MOONSHOT_API_KEY=your_key_here
|
100
|
+
export JANITO_PROVIDER=moonshot
|
101
101
|
export JANITO_MODEL=kimi-k1-8k
|
102
102
|
```
|
103
103
|
|
@@ -119,7 +119,7 @@ export JANITO_MODEL=ibm/granite-3-3-8b-instruct
|
|
119
119
|
|
120
120
|
## Available Models by Provider
|
121
121
|
|
122
|
-
###
|
122
|
+
### Moonshot Models
|
123
123
|
- **kimi-k1-8k**: Fast responses, good for general tasks
|
124
124
|
- **kimi-k1-32k**: Better for longer contexts
|
125
125
|
- **kimi-k1-128k**: Best for very long documents
|
@@ -1 +1 @@
|
|
1
|
-
# Cerebras driver package
|
1
|
+
# Cerebras driver package
|
janito/exceptions.py
CHANGED
@@ -9,11 +9,11 @@ class ToolCallException(Exception):
|
|
9
9
|
self.error = error
|
10
10
|
self.arguments = arguments
|
11
11
|
self.original_exception = exception
|
12
|
-
|
12
|
+
|
13
13
|
# Build detailed error message
|
14
14
|
details = []
|
15
15
|
details.append(f"ToolCallException: {tool_name}: {error}")
|
16
|
-
|
16
|
+
|
17
17
|
if arguments is not None:
|
18
18
|
details.append(f"Arguments received: {arguments}")
|
19
19
|
if isinstance(arguments, dict):
|
@@ -25,8 +25,10 @@ class ToolCallException(Exception):
|
|
25
25
|
for i, value in enumerate(arguments):
|
26
26
|
details.append(f" [{i}]: {repr(value)} ({type(value).__name__})")
|
27
27
|
else:
|
28
|
-
details.append(
|
29
|
-
|
28
|
+
details.append(
|
29
|
+
f"Single argument: {repr(arguments)} ({type(arguments).__name__})"
|
30
|
+
)
|
31
|
+
|
30
32
|
super().__init__("\n".join(details))
|
31
33
|
|
32
34
|
|
janito/plugins/__init__.py
CHANGED
janito/plugins/base.py
CHANGED
@@ -11,6 +11,7 @@ from janito.tools.tool_base import ToolBase
|
|
11
11
|
@dataclass
|
12
12
|
class PluginMetadata:
|
13
13
|
"""Metadata describing a plugin."""
|
14
|
+
|
14
15
|
name: str
|
15
16
|
version: str
|
16
17
|
description: str
|
@@ -18,7 +19,7 @@ class PluginMetadata:
|
|
18
19
|
license: str = "MIT"
|
19
20
|
homepage: Optional[str] = None
|
20
21
|
dependencies: List[str] = None
|
21
|
-
|
22
|
+
|
22
23
|
def __post_init__(self):
|
23
24
|
if self.dependencies is None:
|
24
25
|
self.dependencies = []
|
@@ -27,6 +28,7 @@ class PluginMetadata:
|
|
27
28
|
@dataclass
|
28
29
|
class PluginResource:
|
29
30
|
"""Represents a resource provided by a plugin."""
|
31
|
+
|
30
32
|
name: str
|
31
33
|
type: str # "tool", "command", "config"
|
32
34
|
description: str
|
@@ -36,66 +38,66 @@ class PluginResource:
|
|
36
38
|
class Plugin(ABC):
|
37
39
|
"""
|
38
40
|
Base class for all janito plugins.
|
39
|
-
|
41
|
+
|
40
42
|
Plugins can provide tools, commands, or other functionality.
|
41
43
|
"""
|
42
|
-
|
44
|
+
|
43
45
|
def __init__(self):
|
44
46
|
self.metadata: PluginMetadata = self.get_metadata()
|
45
|
-
|
47
|
+
|
46
48
|
@abstractmethod
|
47
49
|
def get_metadata(self) -> PluginMetadata:
|
48
50
|
"""Return metadata describing this plugin."""
|
49
51
|
pass
|
50
|
-
|
52
|
+
|
51
53
|
def get_tools(self) -> List[Type[ToolBase]]:
|
52
54
|
"""
|
53
55
|
Return a list of tool classes provided by this plugin.
|
54
|
-
|
56
|
+
|
55
57
|
Returns:
|
56
58
|
List of ToolBase subclasses that should be registered
|
57
59
|
"""
|
58
60
|
return []
|
59
|
-
|
61
|
+
|
60
62
|
def get_commands(self) -> Dict[str, Any]:
|
61
63
|
"""
|
62
64
|
Return a dictionary of CLI commands provided by this plugin.
|
63
|
-
|
65
|
+
|
64
66
|
Returns:
|
65
67
|
Dict mapping command names to command handlers
|
66
68
|
"""
|
67
69
|
return {}
|
68
|
-
|
70
|
+
|
69
71
|
def initialize(self) -> None:
|
70
72
|
"""
|
71
73
|
Called when the plugin is loaded.
|
72
74
|
Override to perform any initialization needed.
|
73
75
|
"""
|
74
76
|
pass
|
75
|
-
|
77
|
+
|
76
78
|
def cleanup(self) -> None:
|
77
79
|
"""
|
78
80
|
Called when the plugin is unloaded.
|
79
81
|
Override to perform any cleanup needed.
|
80
82
|
"""
|
81
83
|
pass
|
82
|
-
|
84
|
+
|
83
85
|
def get_config_schema(self) -> Dict[str, Any]:
|
84
86
|
"""
|
85
87
|
Return JSON schema for plugin configuration.
|
86
|
-
|
88
|
+
|
87
89
|
Returns:
|
88
90
|
JSON schema dict describing configuration options
|
89
91
|
"""
|
90
92
|
return {}
|
91
|
-
|
93
|
+
|
92
94
|
def validate_config(self, config: Dict[str, Any]) -> bool:
|
93
95
|
"""
|
94
96
|
Validate plugin configuration.
|
95
|
-
|
97
|
+
|
96
98
|
Args:
|
97
99
|
config: Configuration dict to validate
|
98
|
-
|
100
|
+
|
99
101
|
Returns:
|
100
102
|
True if configuration is valid
|
101
103
|
"""
|
@@ -104,41 +106,47 @@ class Plugin(ABC):
|
|
104
106
|
def get_resources(self) -> List[PluginResource]:
|
105
107
|
"""
|
106
108
|
Return a list of resources provided by this plugin.
|
107
|
-
|
109
|
+
|
108
110
|
Returns:
|
109
111
|
List of PluginResource objects describing the resources
|
110
112
|
"""
|
111
113
|
resources = []
|
112
|
-
|
114
|
+
|
113
115
|
# Add tools as resources
|
114
116
|
for tool_class in self.get_tools():
|
115
117
|
tool_instance = tool_class()
|
116
|
-
tool_name = getattr(tool_instance,
|
117
|
-
tool_desc = getattr(tool_class,
|
118
|
-
resources.append(
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
118
|
+
tool_name = getattr(tool_instance, "tool_name", tool_class.__name__)
|
119
|
+
tool_desc = getattr(tool_class, "__doc__", f"Tool: {tool_name}")
|
120
|
+
resources.append(
|
121
|
+
PluginResource(
|
122
|
+
name=tool_name,
|
123
|
+
type="tool",
|
124
|
+
description=tool_desc or f"Tool provided by {self.metadata.name}",
|
125
|
+
)
|
126
|
+
)
|
127
|
+
|
124
128
|
# Add commands as resources
|
125
129
|
commands = self.get_commands()
|
126
130
|
for cmd_name, cmd_handler in commands.items():
|
127
|
-
cmd_desc = getattr(cmd_handler,
|
128
|
-
resources.append(
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
131
|
+
cmd_desc = getattr(cmd_handler, "__doc__", f"Command: {cmd_name}")
|
132
|
+
resources.append(
|
133
|
+
PluginResource(
|
134
|
+
name=cmd_name,
|
135
|
+
type="command",
|
136
|
+
description=cmd_desc or f"Command provided by {self.metadata.name}",
|
137
|
+
)
|
138
|
+
)
|
139
|
+
|
134
140
|
# Add config schema as resource
|
135
141
|
config_schema = self.get_config_schema()
|
136
142
|
if config_schema:
|
137
|
-
resources.append(
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
143
|
+
resources.append(
|
144
|
+
PluginResource(
|
145
|
+
name=f"{self.metadata.name}_config",
|
146
|
+
type="config",
|
147
|
+
description=f"Configuration schema for {self.metadata.name} plugin",
|
148
|
+
schema=config_schema,
|
149
|
+
)
|
150
|
+
)
|
151
|
+
|
152
|
+
return resources
|
@@ -0,0 +1,88 @@
|
|
1
|
+
"""
|
2
|
+
Builtin plugin system for janito-packaged plugins.
|
3
|
+
|
4
|
+
This module provides the infrastructure for plugins that are bundled
|
5
|
+
with janito and available by default without requiring external installation.
|
6
|
+
"""
|
7
|
+
|
8
|
+
import importlib
|
9
|
+
from typing import Dict, List, Optional, Type
|
10
|
+
from janito.plugins.base import Plugin
|
11
|
+
|
12
|
+
|
13
|
+
class BuiltinPluginRegistry:
|
14
|
+
"""Registry for builtin plugins that come packaged with janito."""
|
15
|
+
|
16
|
+
_plugins: Dict[str, Type[Plugin]] = {}
|
17
|
+
|
18
|
+
@classmethod
|
19
|
+
def register(cls, name: str, plugin_class: Type[Plugin]) -> None:
|
20
|
+
"""Register a builtin plugin."""
|
21
|
+
cls._plugins[name] = plugin_class
|
22
|
+
|
23
|
+
@classmethod
|
24
|
+
def get_plugin_class(cls, name: str) -> Optional[Type[Plugin]]:
|
25
|
+
"""Get the plugin class for a builtin plugin."""
|
26
|
+
return cls._plugins.get(name)
|
27
|
+
|
28
|
+
@classmethod
|
29
|
+
def list_builtin_plugins(cls) -> List[str]:
|
30
|
+
"""List all registered builtin plugins."""
|
31
|
+
return list(cls._plugins.keys())
|
32
|
+
|
33
|
+
@classmethod
|
34
|
+
def is_builtin(cls, name: str) -> bool:
|
35
|
+
"""Check if a plugin is builtin."""
|
36
|
+
return name in cls._plugins
|
37
|
+
|
38
|
+
|
39
|
+
def register_builtin_plugin(name: str):
|
40
|
+
"""Decorator to register a plugin as builtin."""
|
41
|
+
|
42
|
+
def decorator(plugin_class: Type[Plugin]) -> Type[Plugin]:
|
43
|
+
BuiltinPluginRegistry.register(name, plugin_class)
|
44
|
+
return plugin_class
|
45
|
+
|
46
|
+
return decorator
|
47
|
+
|
48
|
+
|
49
|
+
def load_builtin_plugin(name: str) -> Optional[Plugin]:
|
50
|
+
"""Load a builtin plugin by name."""
|
51
|
+
plugin_class = BuiltinPluginRegistry.get_plugin_class(name)
|
52
|
+
if plugin_class:
|
53
|
+
return plugin_class()
|
54
|
+
return None
|
55
|
+
|
56
|
+
|
57
|
+
# Auto-register janito-coder plugins as builtin
|
58
|
+
try:
|
59
|
+
from janito_coder.plugins import (
|
60
|
+
GitAnalyzerPlugin,
|
61
|
+
CodeNavigatorPlugin,
|
62
|
+
DependencyAnalyzerPlugin,
|
63
|
+
CodeFormatterPlugin,
|
64
|
+
TestRunnerPlugin,
|
65
|
+
LinterPlugin,
|
66
|
+
DebuggerPlugin,
|
67
|
+
PerformanceProfilerPlugin,
|
68
|
+
SecurityScannerPlugin,
|
69
|
+
DocumentationGeneratorPlugin,
|
70
|
+
)
|
71
|
+
|
72
|
+
# Register all janito-coder plugins as builtin
|
73
|
+
BuiltinPluginRegistry.register("git_analyzer", GitAnalyzerPlugin)
|
74
|
+
BuiltinPluginRegistry.register("code_navigator", CodeNavigatorPlugin)
|
75
|
+
BuiltinPluginRegistry.register("dependency_analyzer", DependencyAnalyzerPlugin)
|
76
|
+
BuiltinPluginRegistry.register("code_formatter", CodeFormatterPlugin)
|
77
|
+
BuiltinPluginRegistry.register("test_runner", TestRunnerPlugin)
|
78
|
+
BuiltinPluginRegistry.register("linter", LinterPlugin)
|
79
|
+
BuiltinPluginRegistry.register("debugger", DebuggerPlugin)
|
80
|
+
BuiltinPluginRegistry.register("performance_profiler", PerformanceProfilerPlugin)
|
81
|
+
BuiltinPluginRegistry.register("security_scanner", SecurityScannerPlugin)
|
82
|
+
BuiltinPluginRegistry.register(
|
83
|
+
"documentation_generator", DocumentationGeneratorPlugin
|
84
|
+
)
|
85
|
+
|
86
|
+
except ImportError:
|
87
|
+
# janito-coder not available, skip registration
|
88
|
+
pass
|