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.
Files changed (88) hide show
  1. janito/README.md +9 -9
  2. janito/agent/setup_agent.py +29 -16
  3. janito/cli/chat_mode/script_runner.py +1 -1
  4. janito/cli/chat_mode/session.py +50 -24
  5. janito/cli/chat_mode/session_profile_select.py +8 -2
  6. janito/cli/chat_mode/shell/commands/__init__.py +2 -0
  7. janito/cli/chat_mode/shell/commands/execute.py +4 -2
  8. janito/cli/chat_mode/shell/commands/help.py +8 -1
  9. janito/cli/chat_mode/shell/commands/privileges.py +6 -2
  10. janito/cli/chat_mode/shell/commands/provider.py +28 -0
  11. janito/cli/chat_mode/shell/commands/read.py +4 -2
  12. janito/cli/chat_mode/shell/commands/security/__init__.py +1 -1
  13. janito/cli/chat_mode/shell/commands/security/allowed_sites.py +16 -13
  14. janito/cli/chat_mode/shell/commands/security_command.py +14 -10
  15. janito/cli/chat_mode/shell/commands/tools.py +4 -2
  16. janito/cli/chat_mode/shell/commands/unrestricted.py +17 -12
  17. janito/cli/chat_mode/shell/commands/write.py +4 -2
  18. janito/cli/chat_mode/toolbar.py +15 -1
  19. janito/cli/cli_commands/enable_disable_plugin.py +87 -0
  20. janito/cli/cli_commands/list_models.py +2 -2
  21. janito/cli/cli_commands/list_plugins.py +35 -19
  22. janito/cli/cli_commands/list_profiles.py +6 -6
  23. janito/cli/cli_commands/list_providers.py +1 -1
  24. janito/cli/cli_commands/model_utils.py +45 -20
  25. janito/cli/cli_commands/ping_providers.py +10 -10
  26. janito/cli/cli_commands/set_api_key.py +5 -3
  27. janito/cli/cli_commands/show_config.py +13 -7
  28. janito/cli/cli_commands/show_system_prompt.py +13 -6
  29. janito/cli/core/getters.py +7 -0
  30. janito/cli/core/model_guesser.py +18 -15
  31. janito/cli/core/runner.py +28 -6
  32. janito/cli/core/setters.py +21 -6
  33. janito/cli/main_cli.py +14 -12
  34. janito/cli/prompt_core.py +2 -0
  35. janito/cli/prompt_setup.py +4 -4
  36. janito/cli/single_shot_mode/handler.py +2 -0
  37. janito/config_manager.py +2 -0
  38. janito/docs/GETTING_STARTED.md +9 -9
  39. janito/drivers/cerebras/__init__.py +1 -1
  40. janito/exceptions.py +6 -4
  41. janito/plugins/__init__.py +2 -2
  42. janito/plugins/base.py +48 -40
  43. janito/plugins/builtin.py +88 -0
  44. janito/plugins/config.py +16 -19
  45. janito/plugins/discovery.py +129 -40
  46. janito/plugins/manager.py +63 -59
  47. janito/provider_registry.py +10 -10
  48. janito/providers/__init__.py +1 -1
  49. janito/providers/alibaba/model_info.py +3 -5
  50. janito/providers/alibaba/provider.py +3 -1
  51. janito/providers/cerebras/__init__.py +1 -1
  52. janito/providers/cerebras/model_info.py +12 -27
  53. janito/providers/cerebras/provider.py +11 -9
  54. janito/providers/mistral/__init__.py +1 -1
  55. janito/providers/mistral/model_info.py +1 -1
  56. janito/providers/mistral/provider.py +1 -1
  57. janito/providers/moonshot/__init__.py +1 -0
  58. janito/providers/{moonshotai → moonshot}/model_info.py +3 -3
  59. janito/providers/{moonshotai → moonshot}/provider.py +8 -8
  60. janito/providers/openai/provider.py +3 -1
  61. janito/report_events.py +0 -1
  62. janito/tools/adapters/local/ask_user.py +7 -1
  63. janito/tools/adapters/local/create_file.py +1 -1
  64. janito/tools/adapters/local/fetch_url.py +45 -29
  65. janito/tools/adapters/local/python_command_run.py +2 -1
  66. janito/tools/adapters/local/python_file_run.py +1 -0
  67. janito/tools/adapters/local/run_powershell_command.py +1 -1
  68. janito/tools/adapters/local/search_text/core.py +1 -1
  69. janito/tools/adapters/local/validate_file_syntax/jinja2_validator.py +14 -11
  70. janito/tools/base.py +12 -0
  71. janito/tools/loop_protection.py +24 -22
  72. janito/tools/path_utils.py +7 -7
  73. janito/tools/tool_base.py +0 -2
  74. janito/tools/tools_adapter.py +15 -5
  75. janito/tools/url_whitelist.py +27 -26
  76. {janito-2.27.0.dist-info → janito-2.28.0.dist-info}/METADATA +3 -1
  77. {janito-2.27.0.dist-info → janito-2.28.0.dist-info}/RECORD +81 -82
  78. janito-2.28.0.dist-info/top_level.txt +1 -0
  79. janito/providers/moonshotai/__init__.py +0 -1
  80. janito-2.27.0.dist-info/top_level.txt +0 -2
  81. janito-coder/janito_coder/__init__.py +0 -9
  82. janito-coder/janito_coder/plugins/__init__.py +0 -27
  83. janito-coder/janito_coder/plugins/code_navigator.py +0 -618
  84. janito-coder/janito_coder/plugins/git_analyzer.py +0 -273
  85. janito-coder/pyproject.toml +0 -347
  86. {janito-2.27.0.dist-info → janito-2.28.0.dist-info}/WHEEL +0 -0
  87. {janito-2.27.0.dist-info → janito-2.28.0.dist-info}/entry_points.txt +0 -0
  88. {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 guess_provider_from_model as _guess_provider_from_model
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", guessed_provider, style="magenta", align_content=True
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
- if mode == "single_shot":
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"
@@ -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(',') if site.strip()]
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 _handle_set_config_provider(value):
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
- print(
109
- f"Error: Provider '{value}' is not supported. Run '--list-providers' to see the supported list."
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
- {"action": "store_true", "help": "Ping/test connectivity for all providers (use with --list-providers)"},
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
- {"action": "store_true", "help": "List all resources (tools, commands, config) from loaded plugins"},
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 moonshotai -m kimi-k1-8k 'Your prompt here'\n\n"
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] == '/rwx':
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]")
@@ -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, 'no_tools_mode'):
39
- no_tools_mode = getattr(args, 'no_tools_mode', False)
40
-
41
- zero_mode = getattr(args, 'zero', False)
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:
@@ -13,7 +13,7 @@ pip install janito
13
13
 
14
14
  Janito supports multiple AI providers. Choose one to get started:
15
15
 
16
- **MoonshotAI (Recommended for Chinese users)**
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
- **MoonshotAI Setup:**
34
+ **Moonshot Setup:**
35
35
  ```bash
36
- # Set MoonshotAI as your default provider
37
- janito --set-api-key YOUR_API_KEY -p moonshotai
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=moonshotai # or openai, ibm, etc.
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
- **MoonshotAI:**
97
+ **Moonshot:**
98
98
  ```bash
99
- export MOONSHOTAI_API_KEY=your_key_here
100
- export JANITO_PROVIDER=moonshotai
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
- ### MoonshotAI Models
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(f"Single argument: {repr(arguments)} ({type(arguments).__name__})")
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
 
@@ -12,6 +12,6 @@ from .discovery import discover_plugins
12
12
  __all__ = [
13
13
  "PluginManager",
14
14
  "Plugin",
15
- "PluginMetadata",
15
+ "PluginMetadata",
16
16
  "discover_plugins",
17
- ]
17
+ ]
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, 'tool_name', tool_class.__name__)
117
- tool_desc = getattr(tool_class, '__doc__', f"Tool: {tool_name}")
118
- resources.append(PluginResource(
119
- name=tool_name,
120
- type="tool",
121
- description=tool_desc or f"Tool provided by {self.metadata.name}"
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, '__doc__', f"Command: {cmd_name}")
128
- resources.append(PluginResource(
129
- name=cmd_name,
130
- type="command",
131
- description=cmd_desc or f"Command provided by {self.metadata.name}"
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(PluginResource(
138
- name=f"{self.metadata.name}_config",
139
- type="config",
140
- description=f"Configuration schema for {self.metadata.name} plugin",
141
- schema=config_schema
142
- ))
143
-
144
- return resources
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