janito 0.14.0__py3-none-any.whl → 0.15.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/__init__.py CHANGED
@@ -2,4 +2,4 @@
2
2
  Janito package.
3
3
  """
4
4
 
5
- __version__ = "0.14.0"
5
+ __version__ = "0.15.0"
@@ -20,21 +20,17 @@ console = Console()
20
20
 
21
21
  def get_api_key() -> str:
22
22
  """
23
- Get the API key from global config, environment variable, or user input.
23
+ Get the API key from global config or user input.
24
24
 
25
25
  Returns:
26
26
  str: The API key
27
27
  """
28
- # Get API key from global config, environment variable, or ask the user
28
+ # Get API key from global config or ask the user
29
29
  api_key = Config.get_api_key()
30
-
31
- # If not found in global config, try environment variable
32
- if not api_key:
33
- api_key = os.environ.get("ANTHROPIC_API_KEY")
34
30
 
35
- # If still not found, prompt the user
31
+ # If not found, prompt the user
36
32
  if not api_key:
37
- console.print("[bold yellow]⚠️ Warning:[/bold yellow] API key not found in global config or ANTHROPIC_API_KEY environment variable.")
33
+ console.print("[bold yellow]⚠️ Warning:[/bold yellow] API key not found in global config.")
38
34
  console.print("🔑 Please set it using --set-api-key or provide your API key now:")
39
35
  api_key = typer.prompt("Anthropic API Key", hide_input=True)
40
36
 
janito/cli/agent/query.py CHANGED
@@ -11,6 +11,7 @@ from janito.token_report import generate_token_report
11
11
  from janito.tools import print_usage_stats
12
12
  from janito.cli.agent.initialization import initialize_agent
13
13
  from janito.cli.agent.conversation import load_messages, save_messages
14
+ from janito.config import Config
14
15
 
15
16
  console = Console()
16
17
 
@@ -60,15 +61,17 @@ def handle_query(query: str, temperature: float, verbose: bool, show_tokens: boo
60
61
  # Save messages after successful query and get the message ID
61
62
  message_id = save_messages(agent)
62
63
 
63
- # Print token usage report
64
- if show_tokens:
65
- generate_token_report(agent, verbose=True, interrupted=False)
66
- else:
67
- # Show basic token usage
68
- generate_token_report(agent, verbose=False, interrupted=False)
69
-
70
- # Print tool usage statistics
71
- print_usage_stats()
64
+ # Check if usage reports should be shown
65
+ if Config().show_usage_report:
66
+ # Print token usage report
67
+ if show_tokens:
68
+ generate_token_report(agent, verbose=True, interrupted=False)
69
+ else:
70
+ # Show basic token usage
71
+ generate_token_report(agent, verbose=False, interrupted=False)
72
+
73
+ # Print tool usage statistics
74
+ print_usage_stats()
72
75
 
73
76
 
74
77
 
@@ -79,22 +82,23 @@ def handle_query(query: str, temperature: float, verbose: bool, show_tokens: boo
79
82
  # Save messages even if interrupted
80
83
  message_id = save_messages(agent)
81
84
 
82
- # Print token usage report (even if interrupted)
83
- try:
84
- if show_tokens:
85
- generate_token_report(agent, verbose=True, interrupted=True)
86
- else:
87
- # Show basic token usage
88
- generate_token_report(agent, verbose=False, interrupted=True)
89
-
90
- # Print tool usage statistics
91
- print_usage_stats()
92
-
93
-
94
- except Exception as e:
95
- console.print(f"[bold red]❌ Error generating usage report:[/bold red] {str(e)}")
96
- if verbose:
97
- console.print(traceback.format_exc())
85
+ # Check if usage reports should be shown
86
+ if Config().show_usage_report:
87
+ # Print token usage report (even if interrupted)
88
+ try:
89
+ if show_tokens:
90
+ generate_token_report(agent, verbose=True, interrupted=True)
91
+ else:
92
+ # Show basic token usage
93
+ generate_token_report(agent, verbose=False, interrupted=True)
94
+
95
+ # Print tool usage statistics
96
+ print_usage_stats()
97
+
98
+ except Exception as e:
99
+ console.print(f"[bold red]❌ Error generating usage report:[/bold red] {str(e)}")
100
+ if verbose:
101
+ console.print(traceback.format_exc())
98
102
 
99
103
  # Exit with non-zero status to indicate interruption
100
104
  sys.exit(130) # 130 is the standard exit code for SIGINT
janito/cli/app.py CHANGED
@@ -8,7 +8,7 @@ from rich.console import Console
8
8
  import importlib.metadata
9
9
 
10
10
  from janito import __version__
11
- from janito.config import get_config
11
+ from janito.config import Config
12
12
  from janito.cli.commands import handle_config_commands, validate_parameters
13
13
  from janito.cli.agent import handle_query
14
14
  from janito.cli.utils import get_stdin_termination_hint
@@ -22,9 +22,11 @@ def main(ctx: typer.Context,
22
22
  verbose: bool = typer.Option(False, "--verbose", "-v", help="Enable verbose mode with detailed output"),
23
23
  show_tokens: bool = typer.Option(False, "--show-tokens", "--tokens", help="Show detailed token usage and pricing information"),
24
24
  workspace: Optional[str] = typer.Option(None, "--workspace", "-w", help="Set the workspace directory"),
25
- config_str: Optional[str] = typer.Option(None, "--set-config", help="Configuration string in format 'key=value', e.g., 'temperature=0.7' or 'profile=technical'"),
25
+ set_local_config: Optional[str] = typer.Option(None, "--set-local-config", help="Set a local configuration value in format 'key=value' (overrides global config)"),
26
+ set_global_config: Optional[str] = typer.Option(None, "--set-global-config", help="Set a global configuration value in format 'key=value' (used as default)"),
26
27
  show_config: bool = typer.Option(False, "--show-config", help="Show current configuration"),
27
- reset_config: bool = typer.Option(False, "--reset-config", help="Reset configuration by removing the config file"),
28
+ reset_local_config: bool = typer.Option(False, "--reset-local-config", help="Reset local configuration by removing the local config file"),
29
+ reset_global_config: bool = typer.Option(False, "--reset-global-config", help="Reset global configuration by removing the global config file"),
28
30
  set_api_key: Optional[str] = typer.Option(None, "--set-api-key", help="Set the Anthropic API key globally in the user's home directory"),
29
31
  ask: bool = typer.Option(False, "--ask", help="Enable ask mode which disables tools that perform changes"),
30
32
  trust: bool = typer.Option(False, "--trust", "-t", help="Enable trust mode which suppresses tool outputs for a more concise execution"),
@@ -34,23 +36,22 @@ def main(ctx: typer.Context,
34
36
  role: Optional[str] = typer.Option(None, "--role", help="Set the assistant's role (default: 'software engineer')"),
35
37
  system: Optional[str] = typer.Option(None, "--system", "-s", help="Provide custom system instructions, bypassing the default file load method"),
36
38
  version: bool = typer.Option(False, "--version", help="Show the version and exit"),
37
- continue_id: Optional[str] = typer.Option(None, "--continue-id", help="Continue a specific conversation with the given ID"),
38
39
  continue_flag: Optional[str] = typer.Option(None, "--continue", "-c", help="Continue a conversation. Can be used as: 1) --continue (to continue most recent), 2) --continue 123 (to continue conversation with ID 123), or 3) --continue \"query\" (to continue most recent with new query)"),
39
40
  history_flag: bool = typer.Option(False, "--history", help="Show a summary of conversations. Use --history for default (20) or --history n to specify count")):
40
41
  """
41
42
  Janito CLI tool. If a query is provided without a command, it will be sent to the claudine agent.
42
43
  """
43
44
  # Set verbose mode in config
44
- get_config().verbose = verbose
45
+ Config().verbose = verbose
45
46
 
46
47
  # Set ask mode in config
47
- get_config().ask_mode = ask
48
+ Config().ask_mode = ask
48
49
 
49
50
  # Set trust mode in config
50
- get_config().trust_mode = trust
51
+ Config().trust_mode = trust
51
52
 
52
53
  # Set no-tools mode in config
53
- get_config().no_tools = no_tools
54
+ Config().no_tools = no_tools
54
55
 
55
56
  # Show a message if ask mode is enabled
56
57
  if ask:
@@ -124,22 +125,15 @@ def main(ctx: typer.Context,
124
125
  # --continue with no args means continue most recent conversation
125
126
  continue_conversation = ""
126
127
 
127
- # Handle explicit --continue-id if specified (this takes precedence)
128
- if "--continue-id" in args:
129
- continue_id_idx = args.index("--continue-id")
130
- if continue_id_idx + 1 < len(args) and not args[continue_id_idx + 1].startswith("-"):
131
- continue_conversation = args[continue_id_idx + 1]
128
+ # --continue-id has been removed in favor of --continue
132
129
  except Exception as e:
133
130
  if verbose:
134
131
  console.print(f"[bold yellow]⚠️ Error parsing continue arguments: {str(e)}[/bold yellow]")
135
132
 
136
133
  # Fall back to typer-processed args if our parsing failed
137
134
  if continue_conversation is None:
138
- # Handle the --continue-id option
139
- if continue_id is not None:
140
- continue_conversation = continue_id
141
135
  # Handle the --continue flag option (processed by typer)
142
- elif continue_flag is not None:
136
+ if continue_flag is not None:
143
137
  if continue_flag == "":
144
138
  continue_conversation = "" # Empty string means continue most recent
145
139
  elif continue_flag.isdigit():
@@ -151,15 +145,17 @@ def main(ctx: typer.Context,
151
145
  # Handle configuration-related commands
152
146
  exit_after_config = handle_config_commands(
153
147
  ctx,
154
- reset_config,
148
+ False, # reset_config is removed, passing False for backward compatibility
149
+ reset_local_config,
150
+ reset_global_config,
155
151
  workspace,
156
152
  show_config,
157
153
  profile,
158
154
  role,
159
- set_api_key,
160
- config_str,
155
+ set_api_key,
156
+ set_local_config,
157
+ set_global_config,
161
158
  query,
162
- continue_id,
163
159
  continue_flag,
164
160
  history_flag,
165
161
  history_count_override
@@ -1,242 +1,30 @@
1
1
  """
2
2
  Configuration management functions for Janito CLI.
3
+ This file is a thin wrapper around the actual implementation in janito.config.cli.commands
4
+ to maintain backward compatibility.
3
5
  """
4
- import sys
5
- import os
6
- from pathlib import Path
7
- from typing import Optional
8
6
  import typer
9
- from rich.console import Console
10
-
11
- from janito.config import get_config, Config
12
- from janito.cli.commands.workspace import handle_workspace
13
- from janito.cli.commands.profile import handle_profile, handle_role
14
- from janito.cli.commands.history import handle_history
15
-
16
- console = Console()
17
-
18
- def handle_reset_config(reset_config: bool, ctx: typer.Context, query: Optional[str]) -> bool:
19
- """
20
- Handle the --reset-config parameter.
21
-
22
- Args:
23
- reset_config: Whether to reset the configuration
24
- ctx: Typer context
25
- query: Query string
26
-
27
- Returns:
28
- bool: True if the program should exit after this operation
29
- """
30
- if reset_config:
31
- try:
32
- config_path = Path(get_config().workspace_dir) / ".janito" / "config.json"
33
- if get_config().reset_config():
34
- console.print(f"[bold green]✅ Configuration file removed: {config_path}[/bold green]")
35
- else:
36
- console.print(f"[bold yellow]⚠️ Configuration file does not exist: {config_path}[/bold yellow]")
37
- except Exception as e:
38
- console.print(f"[bold red]Error removing configuration file:[/bold red] {str(e)}")
39
-
40
- # Exit after resetting config if no other operation is requested
41
- return ctx.invoked_subcommand is None and not query
42
-
43
- return False
44
-
45
- def handle_show_config(show_config: bool, ctx: typer.Context, query: Optional[str]) -> bool:
46
- """
47
- Handle the --show-config parameter.
48
-
49
- Args:
50
- show_config: Whether to show the configuration
51
- ctx: Typer context
52
- query: Query string
53
-
54
- Returns:
55
- bool: True if the program should exit after this operation
56
- """
57
- if show_config:
58
- config = get_config()
59
- console.print("[bold blue]⚙️ Current Configuration:[/bold blue]")
60
- console.print(f"[bold]📁 Local Configuration File:[/bold] .janito/config.json")
61
- console.print(f"[bold]🏠 Global Configuration File:[/bold] {Path.home() / '.janito' / 'config.json'}")
62
-
63
- # Show API key status
64
- api_key_global = Config.get_api_key()
65
- api_key_env = os.environ.get("ANTHROPIC_API_KEY")
66
- if api_key_global:
67
- console.print(f"[bold]🔑 API Key:[/bold] [green]Set in global config[/green]")
68
- elif api_key_env:
69
- console.print(f"[bold]🔑 API Key:[/bold] [yellow]Set in environment variable[/yellow]")
70
- else:
71
- console.print(f"[bold]🔑 API Key:[/bold] [red]Not set[/red]")
72
-
73
- console.print(f"[bold]🔊 Verbose Mode:[/bold] {'Enabled' if config.verbose else 'Disabled'}")
74
- console.print(f"[bold]❓ Ask Mode:[/bold] {'Enabled' if config.ask_mode else 'Disabled'}")
75
-
76
- console.print(f"[bold]👤 Role:[/bold] {config.role}")
77
-
78
- # Show profile information if one is set
79
- if config.profile:
80
- profile_data = config.get_available_profiles()[config.profile]
81
- console.print(f"[bold]📋 Active Profile:[/bold] {config.profile} - {profile_data['description']}")
82
-
83
- # Show available profiles
84
- profiles = config.get_available_profiles()
85
- if profiles:
86
- console.print("\n[bold blue]📋 Available Parameter Profiles:[/bold blue]")
87
- for name, data in profiles.items():
88
- console.print(f"[bold]🔹 {name}[/bold] - {data['description']}")
89
-
90
- # Exit if this was the only operation requested
91
- return ctx.invoked_subcommand is None and not query
92
-
93
- return False
94
-
95
- def handle_set_api_key(set_api_key: Optional[str], ctx: typer.Context, query: Optional[str]) -> bool:
96
- """
97
- Handle the --set-api-key parameter.
98
-
99
- Args:
100
- set_api_key: API key
101
- ctx: Typer context
102
- query: Query string
103
-
104
- Returns:
105
- bool: True if the program should exit after this operation
106
- """
107
- if set_api_key is not None:
108
- try:
109
- Config.set_api_key(set_api_key)
110
- console.print(f"[bold green]✅ API key saved to global configuration[/bold green]")
111
- console.print(f"[dim]📁 Location: {Path.home() / '.janito' / 'config.json'}[/dim]")
112
-
113
- # Exit after setting API key if no other operation is requested
114
- return ctx.invoked_subcommand is None and not query
115
- except Exception as e:
116
- console.print(f"[bold red]Error:[/bold red] {str(e)}")
117
- sys.exit(1)
118
-
119
- return False
120
-
121
- def handle_set_config(config_str: Optional[str], ctx: typer.Context, query: Optional[str]) -> bool:
122
- """
123
- Handle the --set-config parameter.
124
-
125
- Args:
126
- config_str: Configuration string in format 'key=value'
127
- ctx: Typer context
128
- query: Query string
129
-
130
- Returns:
131
- bool: True if the program should exit after this operation
132
- """
133
- if config_str is not None:
134
- try:
135
- # Parse the config string
136
- config_parts = config_str.split("=", 1)
137
- if len(config_parts) != 2:
138
- console.print(f"[bold red]Error:[/bold red] Invalid configuration format. Use 'key=value' format.")
139
- return ctx.invoked_subcommand is None and not query
140
-
141
- key = config_parts[0].strip()
142
- value = config_parts[1].strip()
143
-
144
- # Remove quotes if present
145
- if (value.startswith("'") and value.endswith("'")) or \
146
- (value.startswith('"') and value.endswith('"')):
147
- value = value[1:-1]
148
-
149
- if key == "profile":
150
- try:
151
- get_config().set_profile(value)
152
- profile_data = get_config().get_available_profiles()[value.lower()]
153
- console.print(f"[bold green]✅ Profile set to '{value.lower()}'[/bold green]")
154
- console.print(f"[dim]📝 Description: {profile_data['description']}[/dim]")
155
- except ValueError as e:
156
- console.print(f"[bold red]Error:[/bold red] {str(e)}")
157
- elif key == "temperature":
158
- try:
159
- temp_value = float(value)
160
- if temp_value < 0.0 or temp_value > 1.0:
161
- console.print("[bold red]Error:[/bold red] Temperature must be between 0.0 and 1.0")
162
- return ctx.invoked_subcommand is None and not query
163
-
164
- get_config().temperature = temp_value
165
- console.print(f"[bold green]✅ Temperature set to {temp_value} and saved to configuration[/bold green]")
166
- except ValueError:
167
- console.print(f"[bold red]Error:[/bold red] Invalid temperature value: {value}. Must be a float between 0.0 and 1.0.")
168
- # top_k and top_p are now only accessible through profiles
169
- elif key == "role":
170
- get_config().role = value
171
- console.print(f"[bold green]✅ Role set to '{value}' and saved to configuration[/bold green]")
172
- else:
173
- console.print(f"[bold yellow]Warning:[/bold yellow] Unsupported configuration key: {key}")
174
-
175
- # Exit after applying config changes if no other operation is requested
176
- return ctx.invoked_subcommand is None and not query
177
- except Exception as e:
178
- console.print(f"[bold red]Error:[/bold red] {str(e)}")
179
-
180
- return False
7
+ from typing import Optional
181
8
 
182
- def handle_config_commands(
183
- ctx: typer.Context,
184
- reset_config: bool,
185
- workspace: Optional[str],
186
- show_config: bool,
187
- profile: Optional[str],
188
- role: Optional[str],
189
- set_api_key: Optional[str],
190
- config_str: Optional[str],
191
- query: Optional[str],
192
- continue_id: Optional[str] = None,
193
- continue_flag: Optional[str] = None,
194
- history_flag: bool = False,
195
- history_count: Optional[int] = None
196
- ) -> bool:
197
- """
198
- Handle all configuration-related commands.
199
-
200
- Args:
201
- ctx: Typer context
202
- reset_config: Whether to reset the configuration
203
- workspace: Workspace directory path
204
- show_config: Whether to show the configuration
205
- profile: Profile name
206
- role: Role name
207
- set_api_key: API key
208
- config_str: Configuration string in format 'key=value'
209
- query: Query string
210
- continue_id: Optional message ID to continue a specific conversation
211
- continue_flag: Optional string that can be empty (flag only) or contain a chat ID
212
- history_flag: Whether to show conversation history (--history flag)
213
- history_count: Number of history entries to display (value after --history)
214
-
215
- Returns:
216
- bool: True if the program should exit after these operations
217
- """
218
- # Handle each command and check if we should exit after it
219
- if handle_reset_config(reset_config, ctx, query):
220
- return True
221
-
222
- handle_workspace(workspace)
223
-
224
- if handle_show_config(show_config, ctx, query):
225
- return True
226
-
227
- if handle_profile(profile, ctx, query):
228
- return True
229
-
230
- if handle_role(role, ctx, query):
231
- return True
232
-
233
- if handle_set_api_key(set_api_key, ctx, query):
234
- return True
235
-
236
- if handle_set_config(config_str, ctx, query):
237
- return True
238
-
239
- if handle_history(history_flag, history_count, ctx, query):
240
- return True
241
-
242
- return False
9
+ from janito.config.cli.commands import (
10
+ handle_reset_config,
11
+ handle_reset_local_config,
12
+ handle_reset_global_config,
13
+ handle_show_config,
14
+ handle_set_api_key,
15
+ handle_set_local_config,
16
+ handle_set_global_config,
17
+ handle_config_commands
18
+ )
19
+
20
+ # Re-export all functions for backward compatibility
21
+ __all__ = [
22
+ "handle_reset_config",
23
+ "handle_reset_local_config",
24
+ "handle_reset_global_config",
25
+ "handle_show_config",
26
+ "handle_set_api_key",
27
+ "handle_set_local_config",
28
+ "handle_set_global_config",
29
+ "handle_config_commands"
30
+ ]
@@ -1,72 +1,93 @@
1
- """
2
- Profile and role management functions for Janito CLI.
3
- """
4
- import sys
5
- from typing import Optional
6
- import typer
7
- from rich.console import Console
8
-
9
- from janito.config import get_config
10
-
11
- console = Console()
12
-
13
- def handle_profile(profile: Optional[str], ctx: typer.Context, query: Optional[str]) -> bool:
14
- """
15
- Handle the --profile parameter.
16
-
17
- Args:
18
- profile: Profile name
19
- ctx: Typer context
20
- query: Query string
21
-
22
- Returns:
23
- bool: True if the program should exit after this operation
24
- """
25
- if profile is not None:
26
- try:
27
- # Apply profile without saving to config
28
- config = get_config()
29
- profile_data = config.get_available_profiles()[profile.lower()]
30
-
31
- # Set values directly without saving
32
- config._temperature = profile_data["temperature"]
33
- config._profile = profile.lower()
34
-
35
- console.print(f"[bold green]✅ Profile '{profile.lower()}' applied for this session only[/bold green]")
36
- console.print(f"[dim]📝 Description: {profile_data['description']}[/dim]")
37
-
38
- # Exit after applying profile if no other operation is requested
39
- return ctx.invoked_subcommand is None and not query
40
- except ValueError as e:
41
- console.print(f"[bold red]Error:[/bold red] {str(e)}")
42
- sys.exit(1)
43
-
44
- return False
45
-
46
- def handle_role(role: Optional[str], ctx: typer.Context, query: Optional[str]) -> bool:
47
- """
48
- Handle the --role parameter.
49
-
50
- Args:
51
- role: Role name
52
- ctx: Typer context
53
- query: Query string
54
-
55
- Returns:
56
- bool: True if the program should exit after this operation
57
- """
58
- if role is not None:
59
- try:
60
- # Set role directly without saving to config
61
- config = get_config()
62
- config._role = role
63
-
64
- console.print(f"[bold green]✅ Role '{role}' applied for this session only[/bold green]")
65
-
66
- # Exit after applying role if no other operation is requested
67
- return ctx.invoked_subcommand is None and not query
68
- except Exception as e:
69
- console.print(f"[bold red]Error:[/bold red] {str(e)}")
70
- sys.exit(1)
71
-
1
+ """
2
+ Profile and role management functions for Janito CLI.
3
+ """
4
+ import sys
5
+ from typing import Optional
6
+ import typer
7
+ from rich.console import Console
8
+
9
+ from janito.config import Config
10
+
11
+ console = Console()
12
+
13
+ def handle_profile(profile: Optional[str], ctx: typer.Context, query: Optional[str], config_type: str = "session") -> bool:
14
+ """
15
+ Handle the --profile parameter.
16
+
17
+ Args:
18
+ profile: Profile name
19
+ ctx: Typer context
20
+ query: Query string
21
+ config_type: Type of configuration to update ("session", "local", or "global")
22
+
23
+ Returns:
24
+ bool: True if the program should exit after this operation
25
+ """
26
+ if profile is not None:
27
+ try:
28
+ # Apply profile
29
+ config = Config()
30
+ profile_data = config.get_available_profiles()[profile.lower()]
31
+
32
+ if config_type == "session":
33
+ # Set values directly without saving
34
+ config._temperature = profile_data["temperature"]
35
+ config._profile = profile.lower()
36
+ console.print(f"[bold green] Profile '{profile.lower()}' applied for this session only[/bold green]")
37
+ elif config_type in ["local", "global"]:
38
+ # Set profile in the specified configuration
39
+ config.set_profile(profile.lower(), config_type)
40
+ console.print(f"[bold green]✅ Profile '{profile.lower()}' set in {config_type} configuration[/bold green]")
41
+ else:
42
+ console.print(f"[bold red]Error:[/bold red] Invalid config_type: {config_type}")
43
+ return ctx.invoked_subcommand is None and not query
44
+
45
+ console.print(f"[dim]📝 Description: {profile_data['description']}[/dim]")
46
+
47
+ # Exit after applying profile if no other operation is requested
48
+ return ctx.invoked_subcommand is None and not query
49
+ except ValueError as e:
50
+ console.print(f"[bold red]Error:[/bold red] {str(e)}")
51
+ sys.exit(1)
52
+
53
+ return False
54
+
55
+ def handle_role(role: Optional[str], ctx: typer.Context, query: Optional[str], config_type: str = "session") -> bool:
56
+ """
57
+ Handle the --role parameter.
58
+
59
+ Args:
60
+ role: Role name
61
+ ctx: Typer context
62
+ query: Query string
63
+ config_type: Type of configuration to update ("session", "local", or "global")
64
+
65
+ Returns:
66
+ bool: True if the program should exit after this operation
67
+ """
68
+ if role is not None:
69
+ try:
70
+ config = Config()
71
+
72
+ if config_type == "session":
73
+ # Set role directly without saving
74
+ config._role = role
75
+ console.print(f"[bold green]✅ Role '{role}' applied for this session only[/bold green]")
76
+ elif config_type in ["local", "global"]:
77
+ # Set role in the specified configuration
78
+ if config_type == "local":
79
+ config.role = role, "local"
80
+ else:
81
+ config.role = role, "global"
82
+ console.print(f"[bold green]✅ Role '{role}' set in {config_type} configuration[/bold green]")
83
+ else:
84
+ console.print(f"[bold red]Error:[/bold red] Invalid config_type: {config_type}")
85
+ return ctx.invoked_subcommand is None and not query
86
+
87
+ # Exit after applying role if no other operation is requested
88
+ return ctx.invoked_subcommand is None and not query
89
+ except Exception as e:
90
+ console.print(f"[bold red]Error:[/bold red] {str(e)}")
91
+ sys.exit(1)
92
+
72
93
  return False