ngpt 3.8.3__py3-none-any.whl → 3.9.1__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.
ngpt/cli/args.py CHANGED
@@ -58,6 +58,10 @@ def setup_argument_parser():
58
58
  help='Show available markdown renderers for use with --prettify')
59
59
  config_group.add_argument('--cli-config', nargs='*', metavar='COMMAND',
60
60
  help='Manage CLI configuration (set, get, unset, list, help)')
61
+
62
+ # Role configuration options
63
+ config_group.add_argument('--role-config', nargs='*', metavar='ACTION',
64
+ help='Manage custom roles (help, create, show, edit, list, remove) [role_name]')
61
65
 
62
66
  # Global options
63
67
  global_group = parser.add_argument_group('Global Options')
@@ -79,8 +83,13 @@ def setup_argument_parser():
79
83
  help='Set max response length in tokens')
80
84
  global_group.add_argument('--log', metavar='FILE', nargs='?', const=True,
81
85
  help='Set filepath to log conversation to, or create a temporary log file if no path provided')
82
- global_group.add_argument('--preprompt',
86
+
87
+ # System prompt options (mutually exclusive)
88
+ prompt_exclusive_group = global_group.add_mutually_exclusive_group()
89
+ prompt_exclusive_group.add_argument('--preprompt',
83
90
  help='Set custom system prompt to control AI behavior')
91
+ prompt_exclusive_group.add_argument('--role',
92
+ help='Use a predefined role to set system prompt (mutually exclusive with --preprompt)')
84
93
 
85
94
  # Output display options (mutually exclusive group)
86
95
  output_group = parser.add_argument_group('Output Display Options (mutually exclusive)')
@@ -226,4 +235,36 @@ def handle_cli_config_args(args):
226
235
  return (True, action, option, value)
227
236
  else:
228
237
  # Unknown action, show help
229
- return (True, "help", None, None)
238
+ return (True, "help", None, None)
239
+
240
+ def handle_role_config_args(args):
241
+ """Process role configuration arguments and determine command parameters.
242
+
243
+ Args:
244
+ args: The parsed command line arguments.
245
+
246
+ Returns:
247
+ tuple: (should_handle, action, role_name)
248
+ - should_handle: True if --role-config was specified and should be handled
249
+ - action: The action to perform (help, create, show, edit, list, remove)
250
+ - role_name: The name of the role (or None for actions like list and help)
251
+ """
252
+ if args.role_config is None:
253
+ return (False, None, None)
254
+
255
+ # Show help if no arguments or "help" argument
256
+ if len(args.role_config) == 0 or (len(args.role_config) > 0 and args.role_config[0].lower() == "help"):
257
+ return (True, "help", None)
258
+
259
+ action = args.role_config[0].lower()
260
+ role_name = args.role_config[1] if len(args.role_config) > 1 else None
261
+
262
+ # If action requires a role name but none is provided
263
+ if action in ("create", "show", "edit", "remove") and role_name is None:
264
+ raise ValueError(f"--role-config {action} requires a role name")
265
+
266
+ if action in ("help", "create", "show", "edit", "list", "remove"):
267
+ return (True, action, role_name)
268
+ else:
269
+ # Unknown action, show help
270
+ return (True, "help", None)
ngpt/cli/main.py CHANGED
@@ -25,7 +25,8 @@ from .modes.shell import shell_mode
25
25
  from .modes.text import text_mode
26
26
  from .modes.rewrite import rewrite_mode
27
27
  from .modes.gitcommsg import gitcommsg_mode
28
- from .args import parse_args, validate_args, handle_cli_config_args, setup_argument_parser, validate_markdown_renderer
28
+ from .args import parse_args, validate_args, handle_cli_config_args, setup_argument_parser, validate_markdown_renderer, handle_role_config_args
29
+ from .roles import handle_role_config, get_role_prompt
29
30
 
30
31
  def show_cli_config_help():
31
32
  """Display help information about CLI configuration."""
@@ -194,6 +195,12 @@ def main():
194
195
  handle_cli_config(action, option, value)
195
196
  return
196
197
 
198
+ # Handle role configuration command
199
+ should_handle_role_config, action, role_name = handle_role_config_args(args)
200
+ if should_handle_role_config:
201
+ handle_role_config(action, role_name)
202
+ return
203
+
197
204
  # Handle --renderers flag to show available markdown renderers
198
205
  if args.list_renderers:
199
206
  show_available_renderers()
@@ -484,6 +491,15 @@ def main():
484
491
  if not has_renderer:
485
492
  show_available_renderers()
486
493
 
494
+ # Get system prompt from role if specified
495
+ if args.role:
496
+ role_prompt = get_role_prompt(args.role)
497
+ if role_prompt:
498
+ args.preprompt = role_prompt
499
+ else:
500
+ # If role doesn't exist, exit
501
+ return
502
+
487
503
  # Initialize client using the potentially overridden active_config
488
504
  client = NGPTClient(
489
505
  api_key=active_config.get("api_key", args.api_key),
ngpt/cli/roles.py ADDED
@@ -0,0 +1,274 @@
1
+ import os
2
+ import json
3
+ import sys
4
+ from pathlib import Path
5
+ from .formatters import COLORS
6
+ from .ui import get_multiline_input
7
+
8
+ # Role directory within config
9
+ ROLE_DIR_NAME = "ngpt_roles"
10
+
11
+ def get_role_directory():
12
+ """Get the path to the role directory, creating it if it doesn't exist."""
13
+ # Use OS-specific paths
14
+ if sys.platform == "win32":
15
+ # Windows
16
+ config_dir = Path(os.environ.get("APPDATA", "")) / "ngpt"
17
+ elif sys.platform == "darwin":
18
+ # macOS
19
+ config_dir = Path.home() / "Library" / "Application Support" / "ngpt"
20
+ else:
21
+ # Linux and other Unix-like systems
22
+ xdg_config_home = os.environ.get("XDG_CONFIG_HOME")
23
+ if xdg_config_home:
24
+ config_dir = Path(xdg_config_home) / "ngpt"
25
+ else:
26
+ config_dir = Path.home() / ".config" / "ngpt"
27
+
28
+ # Create role directory if it doesn't exist
29
+ role_dir = config_dir / ROLE_DIR_NAME
30
+ role_dir.mkdir(parents=True, exist_ok=True)
31
+
32
+ return role_dir
33
+
34
+ def create_role(role_name):
35
+ """Create a new role with the given name.
36
+
37
+ Args:
38
+ role_name: The name of the role to create.
39
+
40
+ Returns:
41
+ bool: True if the role was created successfully, False otherwise.
42
+ """
43
+ role_dir = get_role_directory()
44
+ role_file = role_dir / f"{role_name}.json"
45
+
46
+ # Check if role already exists
47
+ if role_file.exists():
48
+ print(f"{COLORS['yellow']}Role '{role_name}' already exists. Use --role-config edit {role_name} to modify it.{COLORS['reset']}")
49
+ return False
50
+
51
+ print(f"Creating new role '{role_name}'. Enter system prompt below (Ctrl+D to finish):")
52
+
53
+ # Get multiline input for the system prompt
54
+ system_prompt = get_multiline_input()
55
+ if not system_prompt:
56
+ print(f"{COLORS['yellow']}Role creation cancelled.{COLORS['reset']}")
57
+ return False
58
+
59
+ # Create role data
60
+ role_data = {
61
+ "name": role_name,
62
+ "system_prompt": system_prompt
63
+ }
64
+
65
+ # Save role to file
66
+ try:
67
+ with open(role_file, 'w') as f:
68
+ json.dump(role_data, f, indent=2)
69
+ print(f"{COLORS['green']}Role '{role_name}' created successfully.{COLORS['reset']}")
70
+ return True
71
+ except Exception as e:
72
+ print(f"{COLORS['red']}Error creating role: {str(e)}{COLORS['reset']}")
73
+ return False
74
+
75
+ def edit_role(role_name):
76
+ """Edit an existing role with the given name.
77
+
78
+ Args:
79
+ role_name: The name of the role to edit.
80
+
81
+ Returns:
82
+ bool: True if the role was edited successfully, False otherwise.
83
+ """
84
+ role_dir = get_role_directory()
85
+ role_file = role_dir / f"{role_name}.json"
86
+
87
+ # Check if role exists
88
+ if not role_file.exists():
89
+ print(f"{COLORS['yellow']}Role '{role_name}' does not exist.{COLORS['reset']}")
90
+ return False
91
+
92
+ # Load existing role data
93
+ try:
94
+ with open(role_file, 'r') as f:
95
+ role_data = json.load(f)
96
+
97
+ print(f"Editing role '{role_name}'. Current system prompt will be loaded in the editor.")
98
+
99
+ # Get multiline input for the new system prompt with the current one pre-loaded
100
+ system_prompt = get_multiline_input(initial_text=role_data['system_prompt'])
101
+ if not system_prompt:
102
+ print(f"{COLORS['yellow']}Role edit cancelled.{COLORS['reset']}")
103
+ return False
104
+
105
+ # Update role data
106
+ role_data['system_prompt'] = system_prompt
107
+
108
+ # Save updated role to file
109
+ with open(role_file, 'w') as f:
110
+ json.dump(role_data, f, indent=2)
111
+
112
+ print(f"{COLORS['green']}Role '{role_name}' updated successfully.{COLORS['reset']}")
113
+ return True
114
+ except Exception as e:
115
+ print(f"{COLORS['red']}Error editing role: {str(e)}{COLORS['reset']}")
116
+ return False
117
+
118
+ def show_role(role_name):
119
+ """Show details of a role with the given name.
120
+
121
+ Args:
122
+ role_name: The name of the role to show.
123
+
124
+ Returns:
125
+ bool: True if the role was found and displayed, False otherwise.
126
+ """
127
+ role_dir = get_role_directory()
128
+ role_file = role_dir / f"{role_name}.json"
129
+
130
+ # Check if role exists
131
+ if not role_file.exists():
132
+ print(f"{COLORS['yellow']}Role '{role_name}' does not exist.{COLORS['reset']}")
133
+ return False
134
+
135
+ # Load role data
136
+ try:
137
+ with open(role_file, 'r') as f:
138
+ role_data = json.load(f)
139
+
140
+ print(f"\n{COLORS['bold']}Role: {COLORS['cyan']}{role_name}{COLORS['reset']}")
141
+ print(f"\n{COLORS['bold']}System Prompt:{COLORS['reset']}")
142
+ print(f"{COLORS['cyan']}{role_data['system_prompt']}{COLORS['reset']}")
143
+
144
+ return True
145
+ except Exception as e:
146
+ print(f"{COLORS['red']}Error showing role: {str(e)}{COLORS['reset']}")
147
+ return False
148
+
149
+ def list_roles():
150
+ """List all available roles.
151
+
152
+ Returns:
153
+ bool: True if roles were listed successfully, False otherwise.
154
+ """
155
+ role_dir = get_role_directory()
156
+
157
+ # Get all JSON files in the role directory
158
+ try:
159
+ role_files = list(role_dir.glob("*.json"))
160
+
161
+ if not role_files:
162
+ print(f"{COLORS['yellow']}No roles found. Use --role-config create <role_name> to create a new role.{COLORS['reset']}")
163
+ return True
164
+
165
+ print(f"\n{COLORS['bold']}Available Roles:{COLORS['reset']}")
166
+ for role_file in sorted(role_files):
167
+ role_name = role_file.stem
168
+ print(f" • {COLORS['cyan']}{role_name}{COLORS['reset']}")
169
+
170
+ return True
171
+ except Exception as e:
172
+ print(f"{COLORS['red']}Error listing roles: {str(e)}{COLORS['reset']}")
173
+ return False
174
+
175
+ def remove_role(role_name):
176
+ """Remove a role with the given name.
177
+
178
+ Args:
179
+ role_name: The name of the role to remove.
180
+
181
+ Returns:
182
+ bool: True if the role was removed successfully, False otherwise.
183
+ """
184
+ role_dir = get_role_directory()
185
+ role_file = role_dir / f"{role_name}.json"
186
+
187
+ # Check if role exists
188
+ if not role_file.exists():
189
+ print(f"{COLORS['yellow']}Role '{role_name}' does not exist.{COLORS['reset']}")
190
+ return False
191
+
192
+ # Confirm deletion
193
+ confirm = input(f"Are you sure you want to remove the role '{role_name}'? (y/N): ")
194
+ if confirm.lower() not in ["y", "yes"]:
195
+ print(f"{COLORS['yellow']}Role removal cancelled.{COLORS['reset']}")
196
+ return False
197
+
198
+ # Remove role file
199
+ try:
200
+ os.remove(role_file)
201
+ print(f"{COLORS['green']}Role '{role_name}' removed successfully.{COLORS['reset']}")
202
+ return True
203
+ except Exception as e:
204
+ print(f"{COLORS['red']}Error removing role: {str(e)}{COLORS['reset']}")
205
+ return False
206
+
207
+ def get_role_prompt(role_name):
208
+ """Get the system prompt for a role with the given name.
209
+
210
+ Args:
211
+ role_name: The name of the role.
212
+
213
+ Returns:
214
+ str or None: The system prompt for the role, or None if the role does not exist.
215
+ """
216
+ role_dir = get_role_directory()
217
+ role_file = role_dir / f"{role_name}.json"
218
+
219
+ # Check if role exists
220
+ if not role_file.exists():
221
+ print(f"{COLORS['yellow']}Role '{role_name}' does not exist.{COLORS['reset']}")
222
+ return None
223
+
224
+ # Load role data
225
+ try:
226
+ with open(role_file, 'r') as f:
227
+ role_data = json.load(f)
228
+
229
+ return role_data.get('system_prompt')
230
+ except Exception as e:
231
+ print(f"{COLORS['red']}Error loading role: {str(e)}{COLORS['reset']}")
232
+ return None
233
+
234
+ def show_help():
235
+ """Show help information for role configuration."""
236
+ print(f"\n{COLORS['bold']}Role Configuration Help:{COLORS['reset']}")
237
+ print(f" {COLORS['cyan']}--role-config help{COLORS['reset']} - Show this help information")
238
+ print(f" {COLORS['cyan']}--role-config create <role_name>{COLORS['reset']} - Create a new role")
239
+ print(f" {COLORS['cyan']}--role-config show <role_name>{COLORS['reset']} - Show details of a role")
240
+ print(f" {COLORS['cyan']}--role-config edit <role_name>{COLORS['reset']} - Edit an existing role")
241
+ print(f" {COLORS['cyan']}--role-config list{COLORS['reset']} - List all available roles")
242
+ print(f" {COLORS['cyan']}--role-config remove <role_name>{COLORS['reset']} - Remove a role")
243
+ print(f"\n{COLORS['bold']}Usage Examples:{COLORS['reset']}")
244
+ print(f" {COLORS['cyan']}ngpt --role-config create json_generator{COLORS['reset']} - Create a new role for generating JSON")
245
+ print(f" {COLORS['cyan']}ngpt --role json_generator \"generate random user data\"{COLORS['reset']} - Use the json_generator role")
246
+
247
+ def handle_role_config(action, role_name):
248
+ """Handle role configuration based on the action and role name.
249
+
250
+ Args:
251
+ action: The action to perform (help, create, show, edit, list, remove).
252
+ role_name: The name of the role (or None for actions like list and help).
253
+
254
+ Returns:
255
+ bool: True if the action was handled successfully, False otherwise.
256
+ """
257
+ if action == "help":
258
+ show_help()
259
+ return True
260
+ elif action == "create":
261
+ return create_role(role_name)
262
+ elif action == "show":
263
+ return show_role(role_name)
264
+ elif action == "edit":
265
+ return edit_role(role_name)
266
+ elif action == "list":
267
+ return list_roles()
268
+ elif action == "remove":
269
+ return remove_role(role_name)
270
+ else:
271
+ # This shouldn't happen due to prior validation
272
+ print(f"{COLORS['yellow']}Unknown action: {action}{COLORS['reset']}")
273
+ show_help()
274
+ return False
ngpt/cli/ui.py CHANGED
@@ -22,9 +22,12 @@ try:
22
22
  except ImportError:
23
23
  HAS_PROMPT_TOOLKIT = False
24
24
 
25
- def create_multiline_editor():
25
+ def create_multiline_editor(initial_text=None):
26
26
  """Create a multi-line editor with prompt_toolkit.
27
27
 
28
+ Args:
29
+ initial_text: Optional initial text to prepopulate the editor with
30
+
28
31
  Returns:
29
32
  tuple: (app, has_prompt_toolkit) - the editor application and a boolean
30
33
  indicating if prompt_toolkit is available
@@ -62,6 +65,7 @@ def create_multiline_editor():
62
65
  scrollbar=True,
63
66
  focus_on_click=True,
64
67
  lexer=None,
68
+ text=initial_text or "", # Set initial text if provided
65
69
  )
66
70
  text_area.window.right_margins = [ScrollbarMargin(display_arrows=True)]
67
71
 
@@ -108,13 +112,16 @@ def create_multiline_editor():
108
112
  print(f"Error creating editor: {e}")
109
113
  return None, False
110
114
 
111
- def get_multiline_input():
115
+ def get_multiline_input(initial_text=None):
112
116
  """Get multi-line input from the user using either prompt_toolkit or standard input.
113
117
 
118
+ Args:
119
+ initial_text: Optional initial text to prepopulate the editor with
120
+
114
121
  Returns:
115
122
  str: The user's input text, or None if cancelled
116
123
  """
117
- editor_app, has_editor = create_multiline_editor()
124
+ editor_app, has_editor = create_multiline_editor(initial_text)
118
125
 
119
126
  if has_editor and editor_app:
120
127
  try:
@@ -132,8 +139,14 @@ def get_multiline_input():
132
139
  if not HAS_PROMPT_TOOLKIT:
133
140
  print("Note: Install 'prompt_toolkit' package for an enhanced input experience")
134
141
 
142
+ # Show initial text if provided
143
+ if initial_text:
144
+ print(initial_text)
145
+ lines = initial_text.splitlines()
146
+ else:
147
+ lines = []
148
+
135
149
  # Use a more robust approach for multiline input without prompt_toolkit
136
- lines = []
137
150
  try:
138
151
  while True:
139
152
  try:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ngpt
3
- Version: 3.8.3
3
+ Version: 3.9.1
4
4
  Summary: Swiss army knife for LLMs: powerful CLI and interactive chatbot in one package. Seamlessly work with OpenAI, Ollama, Groq, Claude, Gemini, or any OpenAI-compatible API to generate code, craft git commits, rewrite text, and execute shell commands.
5
5
  Project-URL: Homepage, https://github.com/nazdridoy/ngpt
6
6
  Project-URL: Repository, https://github.com/nazdridoy/ngpt
@@ -75,6 +75,7 @@ Description-Content-Type: text/markdown
75
75
  - 📝 **Rich Multiline Editor**: Interactive multiline text input with syntax highlighting and intuitive controls
76
76
  - 📑 **Git Commit Messages**: AI-powered generation of conventional, detailed commit messages from git diffs
77
77
  - 🎭 **System Prompts**: Customize model behavior with custom system prompts
78
+ - 🤖 **Custom Roles**: Create and use reusable AI roles for specialized tasks
78
79
  - 📃 **Conversation Logging**: Save your conversations to text files for later reference
79
80
  - 🔌 **Modular Architecture**: Well-structured codebase with clean separation of concerns
80
81
  - 🔄 **Provider Switching**: Easily switch between different LLM providers with a single parameter
@@ -164,6 +165,17 @@ What is the best way to learn Golang?
164
165
  Provide simple hello world example.
165
166
  EOF
166
167
 
168
+ # Create a custom role for specialized tasks
169
+ ngpt --role-config create json_generator
170
+
171
+ # Use a custom role for specific tasks
172
+ ngpt --role json_generator "Generate user data with name, email, and address"
173
+
174
+ # Use a role from the Role Gallery (first create it, then use it)
175
+ ngpt --role-config create sql_expert
176
+ # Paste the SQL Expert role from https://nazdridoy.github.io/ngpt/examples/role-gallery/
177
+ ngpt --role sql_expert "Write a query to find all users who made a purchase in the last 30 days"
178
+
167
179
  # Rewrite text to improve quality while preserving tone and meaning
168
180
  echo "your text" | ngpt -r
169
181
 
@@ -267,10 +279,11 @@ For more examples and detailed usage, visit the [CLI Usage Guide](https://nazdri
267
279
 
268
280
  usage: ngpt [-h] [-v] [--language LANGUAGE] [--config [CONFIG]] [--config-index CONFIG_INDEX] [--provider PROVIDER]
269
281
  [--remove] [--show-config] [--all] [--list-models] [--list-renderers] [--cli-config [COMMAND ...]]
270
- [--api-key API_KEY] [--base-url BASE_URL] [--model MODEL] [--web-search] [--pipe]
271
- [--temperature TEMPERATURE] [--top_p TOP_P] [--max_tokens MAX_TOKENS] [--log [FILE]] [--preprompt PREPROMPT]
272
- [--no-stream | --prettify | --stream-prettify] [--renderer {auto,rich,glow}] [--rec-chunk] [--diff [FILE]]
273
- [--chunk-size CHUNK_SIZE] [--analyses-chunk-size ANALYSES_CHUNK_SIZE] [--max-msg-lines MAX_MSG_LINES]
282
+ [--role-config [ACTION ...]] [--api-key API_KEY] [--base-url BASE_URL] [--model MODEL] [--web-search]
283
+ [--pipe] [--temperature TEMPERATURE] [--top_p TOP_P] [--max_tokens MAX_TOKENS] [--log [FILE]]
284
+ [--preprompt PREPROMPT | --role ROLE] [--no-stream | --prettify | --stream-prettify]
285
+ [--renderer {auto,rich,glow}] [--rec-chunk] [--diff [FILE]] [--chunk-size CHUNK_SIZE]
286
+ [--analyses-chunk-size ANALYSES_CHUNK_SIZE] [--max-msg-lines MAX_MSG_LINES]
274
287
  [--max-recursion-depth MAX_RECURSION_DEPTH] [-i | -s | -c | -t | -r | -g]
275
288
  [prompt]
276
289
 
@@ -297,6 +310,7 @@ Configuration Options::
297
310
  --list-models List all available models for the current configuration and exit
298
311
  --list-renderers Show available markdown renderers for use with --prettify
299
312
  --cli-config [COMMAND ...] Manage CLI configuration (set, get, unset, list, help)
313
+ --role-config [ACTION ...] Manage custom roles (help, create, show, edit, list, remove) [role_name]
300
314
 
301
315
  Global Options::
302
316
 
@@ -310,6 +324,7 @@ Global Options::
310
324
  --max_tokens MAX_TOKENS Set max response length in tokens
311
325
  --log [FILE] Set filepath to log conversation to, or create a temporary log file if no path provided
312
326
  --preprompt PREPROMPT Set custom system prompt to control AI behavior
327
+ --role ROLE Use a predefined role to set system prompt (mutually exclusive with --preprompt)
313
328
  --renderer {auto,rich,glow} Select which markdown renderer to use with --prettify or --stream-prettify (auto, rich, or glow)
314
329
 
315
330
  Output Display Options (mutually exclusive)::
@@ -325,7 +340,7 @@ Git Commit Message Options::
325
340
  --chunk-size CHUNK_SIZE Number of lines per chunk when chunking is enabled (default: 200)
326
341
  --analyses-chunk-size ANALYSES_CHUNK_SIZE Number of lines per chunk when recursively chunking analyses (default: 200)
327
342
  --max-msg-lines MAX_MSG_LINES Maximum number of lines in commit message before condensing (default: 20)
328
- --max-recursion-depth MAX_RECURSION_DEPTH Maximum recursion depth for commit message condensing (default: 3)
343
+ --max-recursion-depth MAX_RECURSION_DEPTH Maximum recursion depth for commit message condensing (default: 3)
329
344
 
330
345
  Modes (mutually exclusive)::
331
346
 
@@ -353,6 +368,8 @@ Key documentation sections:
353
368
  - [Installation Guide](https://nazdridoy.github.io/ngpt/installation/)
354
369
  - [CLI Usage Guide](https://nazdridoy.github.io/ngpt/usage/cli_usage/)
355
370
  - [Configuration Guide](https://nazdridoy.github.io/ngpt/configuration/)
371
+ - [Custom Roles Guide](https://nazdridoy.github.io/ngpt/usage/roles/)
372
+ - [Role Gallery](https://nazdridoy.github.io/ngpt/examples/role-gallery/)
356
373
  - [Examples & Tutorials](https://nazdridoy.github.io/ngpt/examples/basic/)
357
374
  - [Git Commit Message Guide](https://nazdridoy.github.io/ngpt/usage/gitcommsg/)
358
375
 
@@ -601,6 +618,40 @@ This is a huge time-saver. nGPT analyzes your git diff and generates a properly
601
618
 
602
619
  ![ngpt-g](https://raw.githubusercontent.com/nazdridoy/ngpt/main/previews/ngpt-g.png)
603
620
 
621
+ #### Custom AI Roles
622
+
623
+ ```bash
624
+ # Create a specialized role for JSON generation
625
+ ngpt --role-config create json_generator
626
+
627
+ # Use the custom role to generate structured data
628
+ ngpt --role json_generator "Generate random user profile data"
629
+ ```
630
+ ```json
631
+ {
632
+ "id": "a1b2c3d4-e5f6-7890-1234-567890abcdef",
633
+ "firstName": "Aurora",
634
+ "lastName": "Reynolds",
635
+ "email": "aurora.reynolds@example.com",
636
+ "phone": "+1-555-0101",
637
+ "address": {
638
+ "street": "123 Main St",
639
+ "city": "Anytown",
640
+ "state": "CA",
641
+ "zipCode": "90210"
642
+ },
643
+ "birthDate": "1990-07-15",
644
+ "registrationDate": "2022-01-20",
645
+ "isActive": true,
646
+ "roles": [
647
+ "user",
648
+ "premium"
649
+ ]
650
+ }
651
+ ```
652
+
653
+ Custom roles allow you to create reusable AI personas for consistent responses across various prompts. For more details, see the [Custom Roles Guide](https://nazdridoy.github.io/ngpt/usage/roles/) and check out the [Role Gallery](https://nazdridoy.github.io/ngpt/examples/role-gallery/) for ready-to-use roles.
654
+
604
655
  #### Web Search Integration
605
656
 
606
657
  ```bash
@@ -2,12 +2,13 @@ ngpt/__init__.py,sha256=kpKhViLakwMdHZkuLht2vWcjt0uD_5gR33gvMhfXr6w,664
2
2
  ngpt/__main__.py,sha256=j3eFYPOtCCFBOGh7NK5IWEnADnTMMSEB9GLyIDoW724,66
3
3
  ngpt/client.py,sha256=XjpA2UnvrRvzk6_DzVEddUTzoPlF8koQ-cZURpHoT7c,9041
4
4
  ngpt/cli/__init__.py,sha256=hebbDSMGiOd43YNnQP67uzr67Ue6rZPwm2czynr5iZY,43
5
- ngpt/cli/args.py,sha256=HYCDHhqP-BI_tibL1qGQ9we4483h_kCa2ksh-QxOeiU,12694
5
+ ngpt/cli/args.py,sha256=TbaID-NgRTCa1NQAct74XqWTADvSMbf-sSXKNI1NkXU,14537
6
6
  ngpt/cli/config_manager.py,sha256=NQQcWnjUppAAd0s0p9YAf8EyKS1ex5-0EB4DvKdB4dk,3662
7
7
  ngpt/cli/formatters.py,sha256=HBYGlx_7eoAKyzfy0Vq5L0yn8yVKjngqYBukMmXCcz0,9401
8
- ngpt/cli/main.py,sha256=PVulo8Pm53-oQ2Pgc4G90YhwyPImt8j7HKmY38SJ7CM,28696
8
+ ngpt/cli/main.py,sha256=36mi8uYDcl56IhTkt-TJTRRhwHeF157xMAYgufLRAMo,29256
9
9
  ngpt/cli/renderers.py,sha256=vAoDkpvgG2Fl81zkJDk_-zM1Fsw8E4Uv6m1AI81Fawo,17049
10
- ngpt/cli/ui.py,sha256=4RFxIf51di5EsytVr7OoyCWF_d40KJ0Mbom0VWgPlCc,10870
10
+ ngpt/cli/roles.py,sha256=jtARS_XgZ1_UW8eAdLLMe7trpYhDnzEyCH9PYAiH-Og,9675
11
+ ngpt/cli/ui.py,sha256=8-WyPMwgQiqLXWO0mGfBhKTRnIDDtPUtm_XCvOnqBJA,11334
11
12
  ngpt/cli/modes/__init__.py,sha256=KP7VR6Xw9k1p5Jcu0F38RDxSFvFIzH3j1ThDLNwznUI,363
12
13
  ngpt/cli/modes/chat.py,sha256=x1leClKq7UupA_CdW4tym0AivY2o_II123-I5IcAkxQ,7091
13
14
  ngpt/cli/modes/code.py,sha256=Qj59xq6fZqgUDw7SbvmPKX_gdpc7DHJhNkn1sB5qgUU,12932
@@ -22,8 +23,8 @@ ngpt/utils/config.py,sha256=wsArA4osnh8fKqOvtsPqqBxAz3DpdjtaWUFaRtnUdyc,10452
22
23
  ngpt/utils/log.py,sha256=f1jg2iFo35PAmsarH8FVL_62plq4VXH0Mu2QiP6RJGw,15934
23
24
  ngpt/utils/pipe.py,sha256=qRHF-Ma7bbU0cOcb1Yhe4S-kBavivtnnvLA3EYS4FY4,2162
24
25
  ngpt/utils/web_search.py,sha256=w5ke4KJMRxq7r5jtbUXvspja6XhjoPZloVkZ0IvBXIE,30731
25
- ngpt-3.8.3.dist-info/METADATA,sha256=GjMEbP2fAxk4J6LdsM7vN0N3vT6ikicEbTRoWRGlNQI,28919
26
- ngpt-3.8.3.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
27
- ngpt-3.8.3.dist-info/entry_points.txt,sha256=SqAAvLhMrsEpkIr4YFRdUeyuXQ9o0IBCeYgE6AVojoI,44
28
- ngpt-3.8.3.dist-info/licenses/LICENSE,sha256=mQkpWoADxbHqE0HRefYLJdm7OpdrXBr3vNv5bZ8w72M,1065
29
- ngpt-3.8.3.dist-info/RECORD,,
26
+ ngpt-3.9.1.dist-info/METADATA,sha256=g5ESNkkas9Iz9Yr3uylXhUMPcl9pLATkYaC2_qZJ8Sg,30894
27
+ ngpt-3.9.1.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
28
+ ngpt-3.9.1.dist-info/entry_points.txt,sha256=SqAAvLhMrsEpkIr4YFRdUeyuXQ9o0IBCeYgE6AVojoI,44
29
+ ngpt-3.9.1.dist-info/licenses/LICENSE,sha256=mQkpWoADxbHqE0HRefYLJdm7OpdrXBr3vNv5bZ8w72M,1065
30
+ ngpt-3.9.1.dist-info/RECORD,,
File without changes