janito 2.27.1__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 (80) 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 +17 -5
  5. janito/cli/chat_mode/session_profile_select.py +8 -2
  6. janito/cli/chat_mode/shell/commands/execute.py +4 -2
  7. janito/cli/chat_mode/shell/commands/help.py +2 -0
  8. janito/cli/chat_mode/shell/commands/privileges.py +6 -2
  9. janito/cli/chat_mode/shell/commands/provider.py +7 -4
  10. janito/cli/chat_mode/shell/commands/read.py +4 -2
  11. janito/cli/chat_mode/shell/commands/security/__init__.py +1 -1
  12. janito/cli/chat_mode/shell/commands/security/allowed_sites.py +16 -13
  13. janito/cli/chat_mode/shell/commands/security_command.py +14 -10
  14. janito/cli/chat_mode/shell/commands/tools.py +4 -2
  15. janito/cli/chat_mode/shell/commands/unrestricted.py +17 -12
  16. janito/cli/chat_mode/shell/commands/write.py +4 -2
  17. janito/cli/chat_mode/toolbar.py +4 -4
  18. janito/cli/cli_commands/enable_disable_plugin.py +48 -25
  19. janito/cli/cli_commands/list_models.py +2 -2
  20. janito/cli/cli_commands/list_plugins.py +18 -18
  21. janito/cli/cli_commands/list_profiles.py +6 -6
  22. janito/cli/cli_commands/list_providers.py +1 -1
  23. janito/cli/cli_commands/model_utils.py +45 -20
  24. janito/cli/cli_commands/ping_providers.py +10 -10
  25. janito/cli/cli_commands/set_api_key.py +5 -3
  26. janito/cli/cli_commands/show_config.py +13 -7
  27. janito/cli/cli_commands/show_system_prompt.py +13 -6
  28. janito/cli/core/getters.py +1 -0
  29. janito/cli/core/model_guesser.py +18 -15
  30. janito/cli/core/runner.py +15 -7
  31. janito/cli/core/setters.py +9 -6
  32. janito/cli/main_cli.py +15 -12
  33. janito/cli/prompt_core.py +2 -0
  34. janito/cli/prompt_setup.py +4 -4
  35. janito/cli/single_shot_mode/handler.py +2 -0
  36. janito/config_manager.py +2 -0
  37. janito/docs/GETTING_STARTED.md +9 -9
  38. janito/drivers/cerebras/__init__.py +1 -1
  39. janito/exceptions.py +6 -4
  40. janito/plugins/__init__.py +2 -2
  41. janito/plugins/base.py +48 -40
  42. janito/plugins/builtin.py +13 -9
  43. janito/plugins/config.py +16 -19
  44. janito/plugins/discovery.py +73 -66
  45. janito/plugins/manager.py +62 -60
  46. janito/provider_registry.py +10 -10
  47. janito/providers/__init__.py +1 -1
  48. janito/providers/alibaba/model_info.py +3 -5
  49. janito/providers/alibaba/provider.py +3 -1
  50. janito/providers/cerebras/__init__.py +1 -1
  51. janito/providers/cerebras/model_info.py +12 -27
  52. janito/providers/cerebras/provider.py +11 -9
  53. janito/providers/mistral/__init__.py +1 -1
  54. janito/providers/mistral/model_info.py +1 -1
  55. janito/providers/mistral/provider.py +1 -1
  56. janito/providers/moonshot/__init__.py +1 -0
  57. janito/providers/{moonshotai → moonshot}/model_info.py +3 -3
  58. janito/providers/{moonshotai → moonshot}/provider.py +8 -8
  59. janito/providers/openai/provider.py +3 -1
  60. janito/report_events.py +0 -1
  61. janito/tools/adapters/local/create_file.py +1 -1
  62. janito/tools/adapters/local/fetch_url.py +45 -29
  63. janito/tools/adapters/local/python_command_run.py +2 -1
  64. janito/tools/adapters/local/python_file_run.py +1 -0
  65. janito/tools/adapters/local/run_powershell_command.py +1 -1
  66. janito/tools/adapters/local/search_text/core.py +1 -1
  67. janito/tools/adapters/local/validate_file_syntax/jinja2_validator.py +14 -11
  68. janito/tools/base.py +4 -3
  69. janito/tools/loop_protection.py +24 -22
  70. janito/tools/path_utils.py +7 -7
  71. janito/tools/tool_base.py +0 -2
  72. janito/tools/tools_adapter.py +15 -5
  73. janito/tools/url_whitelist.py +27 -26
  74. {janito-2.27.1.dist-info → janito-2.28.0.dist-info}/METADATA +1 -1
  75. {janito-2.27.1.dist-info → janito-2.28.0.dist-info}/RECORD +79 -79
  76. janito/providers/moonshotai/__init__.py +0 -1
  77. {janito-2.27.1.dist-info → janito-2.28.0.dist-info}/WHEEL +0 -0
  78. {janito-2.27.1.dist-info → janito-2.28.0.dist-info}/entry_points.txt +0 -0
  79. {janito-2.27.1.dist-info → janito-2.28.0.dist-info}/licenses/LICENSE +0 -0
  80. {janito-2.27.1.dist-info → janito-2.28.0.dist-info}/top_level.txt +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,19 +180,21 @@ 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
+
178
184
  # Skip chat mode for list commands - handle them directly
179
185
  from janito.cli.core.getters import GETTER_KEYS
186
+
180
187
  skip_chat_mode = False
181
188
  if args is not None:
182
189
  for key in GETTER_KEYS:
183
190
  if getattr(args, key, False):
184
191
  skip_chat_mode = True
185
192
  break
186
-
193
+
187
194
  if skip_chat_mode:
188
195
  # Handle list commands directly without prompt
189
196
  from janito.cli.core.getters import handle_getter
197
+
190
198
  handle_getter(args)
191
199
  elif mode == "single_shot":
192
200
  from janito.cli.single_shot_mode.handler import (
@@ -222,4 +230,4 @@ def handle_runner(
222
230
 
223
231
 
224
232
  def get_prompt_mode(args):
225
- 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)
@@ -103,20 +103,23 @@ def _handle_set_base_url(value):
103
103
 
104
104
  def set_provider(value):
105
105
  """Set the current provider.
106
-
106
+
107
107
  Args:
108
108
  value (str): The provider name to set
109
-
109
+
110
110
  Raises:
111
111
  ValueError: If the provider is not supported
112
112
  """
113
113
  try:
114
114
  supported = ProviderRegistry().get_provider(value)
115
115
  except Exception:
116
- raise ValueError(f"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."
118
+ )
117
119
  from janito.provider_config import set_config_provider
120
+
118
121
  set_config_provider(value)
119
-
122
+
120
123
 
121
124
  def _handle_set_config_provider(value):
122
125
  try:
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
@@ -412,20 +414,21 @@ class JanitoCLI:
412
414
  handle_getter(self.args)
413
415
  return
414
416
  # Handle /rwx prefix for enabling all permissions
415
- 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":
416
418
  self.args.read = True
417
419
  self.args.write = True
418
420
  self.args.exec = True
419
421
  # Remove the /rwx prefix from the prompt
420
422
  self.args.user_prompt = self.args.user_prompt[1:]
421
- 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("/"):
422
424
  # Skip LLM processing for other commands that start with /
423
425
  return
424
-
426
+
425
427
  # If running in single shot mode and --profile is not provided, default to 'developer' profile
426
428
  # Skip profile selection for list commands that don't need it
427
- if (get_prompt_mode(self.args) == "single_shot" and
428
- not getattr(self.args, "profile", None)):
429
+ if get_prompt_mode(self.args) == "single_shot" and not getattr(
430
+ self.args, "profile", None
431
+ ):
429
432
  self.args.profile = "developer"
430
433
  provider = self._get_provider_or_default()
431
434
  if provider is None:
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
janito/plugins/builtin.py CHANGED
@@ -12,24 +12,24 @@ from janito.plugins.base import Plugin
12
12
 
13
13
  class BuiltinPluginRegistry:
14
14
  """Registry for builtin plugins that come packaged with janito."""
15
-
15
+
16
16
  _plugins: Dict[str, Type[Plugin]] = {}
17
-
17
+
18
18
  @classmethod
19
19
  def register(cls, name: str, plugin_class: Type[Plugin]) -> None:
20
20
  """Register a builtin plugin."""
21
21
  cls._plugins[name] = plugin_class
22
-
22
+
23
23
  @classmethod
24
24
  def get_plugin_class(cls, name: str) -> Optional[Type[Plugin]]:
25
25
  """Get the plugin class for a builtin plugin."""
26
26
  return cls._plugins.get(name)
27
-
27
+
28
28
  @classmethod
29
29
  def list_builtin_plugins(cls) -> List[str]:
30
30
  """List all registered builtin plugins."""
31
31
  return list(cls._plugins.keys())
32
-
32
+
33
33
  @classmethod
34
34
  def is_builtin(cls, name: str) -> bool:
35
35
  """Check if a plugin is builtin."""
@@ -38,9 +38,11 @@ class BuiltinPluginRegistry:
38
38
 
39
39
  def register_builtin_plugin(name: str):
40
40
  """Decorator to register a plugin as builtin."""
41
+
41
42
  def decorator(plugin_class: Type[Plugin]) -> Type[Plugin]:
42
43
  BuiltinPluginRegistry.register(name, plugin_class)
43
44
  return plugin_class
45
+
44
46
  return decorator
45
47
 
46
48
 
@@ -66,7 +68,7 @@ try:
66
68
  SecurityScannerPlugin,
67
69
  DocumentationGeneratorPlugin,
68
70
  )
69
-
71
+
70
72
  # Register all janito-coder plugins as builtin
71
73
  BuiltinPluginRegistry.register("git_analyzer", GitAnalyzerPlugin)
72
74
  BuiltinPluginRegistry.register("code_navigator", CodeNavigatorPlugin)
@@ -77,8 +79,10 @@ try:
77
79
  BuiltinPluginRegistry.register("debugger", DebuggerPlugin)
78
80
  BuiltinPluginRegistry.register("performance_profiler", PerformanceProfilerPlugin)
79
81
  BuiltinPluginRegistry.register("security_scanner", SecurityScannerPlugin)
80
- BuiltinPluginRegistry.register("documentation_generator", DocumentationGeneratorPlugin)
81
-
82
+ BuiltinPluginRegistry.register(
83
+ "documentation_generator", DocumentationGeneratorPlugin
84
+ )
85
+
82
86
  except ImportError:
83
87
  # janito-coder not available, skip registration
84
- pass
88
+ pass
janito/plugins/config.py CHANGED
@@ -21,35 +21,32 @@ def get_plugins_config_path() -> Path:
21
21
  def load_plugins_config() -> Dict[str, Any]:
22
22
  """
23
23
  Load plugins configuration from user directory.
24
-
24
+
25
25
  Returns:
26
26
  Dict containing plugins configuration
27
27
  """
28
28
  config_path = get_plugins_config_path()
29
-
29
+
30
30
  if not config_path.exists():
31
31
  # Create default config if it doesn't exist
32
32
  default_config = {
33
33
  "plugins": {
34
- "paths": [
35
- str(Path.home() / ".janito" / "plugins"),
36
- "./plugins"
37
- ],
38
- "load": {}
34
+ "paths": [str(Path.home() / ".janito" / "plugins"), "./plugins"],
35
+ "load": {},
39
36
  }
40
37
  }
41
-
38
+
42
39
  # Ensure directory exists
43
40
  config_path.parent.mkdir(parents=True, exist_ok=True)
44
-
41
+
45
42
  # Save default config
46
- with open(config_path, 'w') as f:
43
+ with open(config_path, "w") as f:
47
44
  json.dump(default_config, f, indent=2)
48
-
45
+
49
46
  return default_config
50
-
47
+
51
48
  try:
52
- with open(config_path, 'r') as f:
49
+ with open(config_path, "r") as f:
53
50
  return json.load(f)
54
51
  except (json.JSONDecodeError, IOError) as e:
55
52
  print(f"Warning: Failed to load plugins config from {config_path}: {e}")
@@ -59,20 +56,20 @@ def load_plugins_config() -> Dict[str, Any]:
59
56
  def save_plugins_config(config: Dict[str, Any]) -> bool:
60
57
  """
61
58
  Save plugins configuration to user directory.
62
-
59
+
63
60
  Args:
64
61
  config: Configuration dict to save
65
-
62
+
66
63
  Returns:
67
64
  True if saved successfully
68
65
  """
69
66
  config_path = get_plugins_config_path()
70
-
67
+
71
68
  try:
72
69
  # Ensure directory exists
73
70
  config_path.parent.mkdir(parents=True, exist_ok=True)
74
-
75
- with open(config_path, 'w') as f:
71
+
72
+ with open(config_path, "w") as f:
76
73
  json.dump(config, f, indent=2)
77
74
  return True
78
75
  except IOError as e:
@@ -84,4 +81,4 @@ def get_user_plugins_dir() -> Path:
84
81
  """Get the user plugins directory."""
85
82
  plugins_dir = get_user_config_dir() / "plugins"
86
83
  plugins_dir.mkdir(parents=True, exist_ok=True)
87
- return plugins_dir
84
+ return plugins_dir