glaip-sdk 0.0.19__py3-none-any.whl → 0.1.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 (56) hide show
  1. glaip_sdk/_version.py +2 -2
  2. glaip_sdk/branding.py +27 -2
  3. glaip_sdk/cli/auth.py +93 -28
  4. glaip_sdk/cli/commands/__init__.py +2 -2
  5. glaip_sdk/cli/commands/agents.py +127 -21
  6. glaip_sdk/cli/commands/configure.py +141 -90
  7. glaip_sdk/cli/commands/mcps.py +82 -31
  8. glaip_sdk/cli/commands/models.py +4 -3
  9. glaip_sdk/cli/commands/tools.py +27 -14
  10. glaip_sdk/cli/commands/update.py +66 -0
  11. glaip_sdk/cli/config.py +13 -2
  12. glaip_sdk/cli/display.py +35 -26
  13. glaip_sdk/cli/io.py +14 -5
  14. glaip_sdk/cli/main.py +185 -73
  15. glaip_sdk/cli/pager.py +2 -1
  16. glaip_sdk/cli/resolution.py +4 -1
  17. glaip_sdk/cli/slash/__init__.py +3 -4
  18. glaip_sdk/cli/slash/agent_session.py +88 -36
  19. glaip_sdk/cli/slash/prompt.py +20 -48
  20. glaip_sdk/cli/slash/session.py +437 -189
  21. glaip_sdk/cli/transcript/__init__.py +71 -0
  22. glaip_sdk/cli/transcript/cache.py +338 -0
  23. glaip_sdk/cli/transcript/capture.py +278 -0
  24. glaip_sdk/cli/transcript/export.py +38 -0
  25. glaip_sdk/cli/transcript/launcher.py +79 -0
  26. glaip_sdk/cli/transcript/viewer.py +794 -0
  27. glaip_sdk/cli/update_notifier.py +29 -5
  28. glaip_sdk/cli/utils.py +255 -74
  29. glaip_sdk/client/agents.py +3 -1
  30. glaip_sdk/client/run_rendering.py +126 -21
  31. glaip_sdk/icons.py +25 -0
  32. glaip_sdk/models.py +6 -0
  33. glaip_sdk/rich_components.py +29 -1
  34. glaip_sdk/utils/__init__.py +1 -1
  35. glaip_sdk/utils/client_utils.py +6 -4
  36. glaip_sdk/utils/display.py +61 -32
  37. glaip_sdk/utils/rendering/formatting.py +55 -11
  38. glaip_sdk/utils/rendering/models.py +15 -2
  39. glaip_sdk/utils/rendering/renderer/__init__.py +0 -2
  40. glaip_sdk/utils/rendering/renderer/base.py +1287 -227
  41. glaip_sdk/utils/rendering/renderer/config.py +3 -5
  42. glaip_sdk/utils/rendering/renderer/debug.py +73 -16
  43. glaip_sdk/utils/rendering/renderer/panels.py +27 -15
  44. glaip_sdk/utils/rendering/renderer/progress.py +61 -38
  45. glaip_sdk/utils/rendering/renderer/stream.py +3 -3
  46. glaip_sdk/utils/rendering/renderer/toggle.py +184 -0
  47. glaip_sdk/utils/rendering/step_tree_state.py +102 -0
  48. glaip_sdk/utils/rendering/steps.py +944 -16
  49. glaip_sdk/utils/serialization.py +5 -2
  50. glaip_sdk/utils/validation.py +1 -2
  51. {glaip_sdk-0.0.19.dist-info → glaip_sdk-0.1.0.dist-info}/METADATA +12 -1
  52. glaip_sdk-0.1.0.dist-info/RECORD +82 -0
  53. glaip_sdk/utils/rich_utils.py +0 -29
  54. glaip_sdk-0.0.19.dist-info/RECORD +0 -73
  55. {glaip_sdk-0.0.19.dist-info → glaip_sdk-0.1.0.dist-info}/WHEEL +0 -0
  56. {glaip_sdk-0.0.19.dist-info → glaip_sdk-0.1.0.dist-info}/entry_points.txt +0 -0
@@ -12,10 +12,20 @@ from rich.text import Text
12
12
 
13
13
  from glaip_sdk import Client
14
14
  from glaip_sdk._version import __version__ as _SDK_VERSION
15
- from glaip_sdk.branding import AIPBranding
15
+ from glaip_sdk.branding import (
16
+ ACCENT_STYLE,
17
+ ERROR_STYLE,
18
+ INFO,
19
+ PRIMARY,
20
+ SUCCESS,
21
+ SUCCESS_STYLE,
22
+ WARNING_STYLE,
23
+ AIPBranding,
24
+ )
16
25
  from glaip_sdk.cli.config import CONFIG_FILE, load_config, save_config
17
26
  from glaip_sdk.cli.rich_helpers import markup_text
18
- from glaip_sdk.cli.utils import command_hint
27
+ from glaip_sdk.cli.utils import command_hint, format_command_hint
28
+ from glaip_sdk.icons import ICON_TOOL
19
29
  from glaip_sdk.rich_components import AIPTable
20
30
 
21
31
  console = Console()
@@ -33,29 +43,10 @@ def list_config() -> None:
33
43
  config = load_config()
34
44
 
35
45
  if not config:
36
- hint = command_hint("config configure", slash_command="login")
37
- if hint:
38
- console.print(
39
- f"[yellow]No configuration found. Run '{hint}' to set up.[/yellow]"
40
- )
41
- else:
42
- console.print("[yellow]No configuration found.[/yellow]")
46
+ _print_missing_config_hint()
43
47
  return
44
48
 
45
- table = AIPTable(title="🔧 AIP Configuration")
46
- table.add_column("Setting", style="cyan", width=20)
47
- table.add_column("Value", style="green")
48
-
49
- for key, value in config.items():
50
- if key == "api_key" and value:
51
- # Mask the API key
52
- masked_value = "***" + value[-4:] if len(value) > 4 else "***"
53
- table.add_row(key, masked_value)
54
- else:
55
- table.add_row(key, str(value))
56
-
57
- console.print(table)
58
- console.print(Text(f"\n📁 Config file: {CONFIG_FILE}"))
49
+ _render_config_table(config)
59
50
 
60
51
 
61
52
  @config_group.command("set")
@@ -67,7 +58,7 @@ def set_config(key: str, value: str) -> None:
67
58
 
68
59
  if key not in valid_keys:
69
60
  console.print(
70
- f"[red]Error: Invalid key '{key}'. Valid keys are: {', '.join(valid_keys)}[/red]"
61
+ f"[{ERROR_STYLE}]Error: Invalid key '{key}'. Valid keys are: {', '.join(valid_keys)}[/]"
71
62
  )
72
63
  raise click.ClickException(f"Invalid configuration key: {key}")
73
64
 
@@ -76,10 +67,11 @@ def set_config(key: str, value: str) -> None:
76
67
  save_config(config)
77
68
 
78
69
  if key == "api_key":
79
- masked_value = "***" + value[-4:] if len(value) > 4 else "***"
80
- console.print(Text(f"✅ Set {key} = {masked_value}"))
70
+ console.print(
71
+ Text(f"✅ Set {key} = {_mask_api_key(value)}", style=SUCCESS_STYLE)
72
+ )
81
73
  else:
82
- console.print(Text(f"✅ Set {key} = {value}"))
74
+ console.print(Text(f"✅ Set {key} = {value}", style=SUCCESS_STYLE))
83
75
 
84
76
 
85
77
  @config_group.command("get")
@@ -90,16 +82,14 @@ def get_config(key: str) -> None:
90
82
 
91
83
  if key not in config:
92
84
  console.print(
93
- markup_text(f"[yellow]Configuration key '{key}' not found.[/yellow]")
85
+ markup_text(f"[{WARNING_STYLE}]Configuration key '{key}' not found.[/]")
94
86
  )
95
87
  raise click.ClickException(f"Configuration key not found: {key}")
96
88
 
97
89
  value = config[key]
98
90
 
99
91
  if key == "api_key":
100
- # Mask the API key for display
101
- masked_value = "***" + value[-4:] if len(value) > 4 else "***"
102
- console.print(masked_value)
92
+ console.print(_mask_api_key(value))
103
93
  else:
104
94
  console.print(value)
105
95
 
@@ -112,14 +102,14 @@ def unset_config(key: str) -> None:
112
102
 
113
103
  if key not in config:
114
104
  console.print(
115
- markup_text(f"[yellow]Configuration key '{key}' not found.[/yellow]")
105
+ markup_text(f"[{WARNING_STYLE}]Configuration key '{key}' not found.[/]")
116
106
  )
117
107
  return
118
108
 
119
109
  del config[key]
120
110
  save_config(config)
121
111
 
122
- console.print(Text(f"✅ Removed {key} from configuration"))
112
+ console.print(Text(f"✅ Removed {key} from configuration", style=SUCCESS_STYLE))
123
113
 
124
114
 
125
115
  @config_group.command("reset")
@@ -127,7 +117,7 @@ def unset_config(key: str) -> None:
127
117
  def reset_config(force: bool) -> None:
128
118
  """Reset all configuration to defaults."""
129
119
  if not force:
130
- console.print("[yellow]This will remove all AIP configuration.[/yellow]")
120
+ console.print(f"[{WARNING_STYLE}]This will remove all AIP configuration.[/]")
131
121
  confirm = input("Are you sure? (y/N): ").strip().lower()
132
122
  if confirm not in ["y", "yes"]:
133
123
  console.print("Cancelled.")
@@ -137,8 +127,10 @@ def reset_config(force: bool) -> None:
137
127
  file_exists = CONFIG_FILE.exists()
138
128
 
139
129
  if not file_exists and not config_data:
140
- console.print("[yellow]No configuration found to reset.[/yellow]")
141
- console.print("✅ Configuration reset (nothing to remove).")
130
+ console.print(f"[{WARNING_STYLE}]No configuration found to reset.[/]")
131
+ console.print(
132
+ Text("✅ Configuration reset (nothing to remove).", style=SUCCESS_STYLE)
133
+ )
142
134
  return
143
135
 
144
136
  if file_exists:
@@ -151,103 +143,162 @@ def reset_config(force: bool) -> None:
151
143
  save_config({})
152
144
 
153
145
  hint = command_hint("config configure", slash_command="login")
154
- message = "✅ Configuration reset."
146
+ message = Text("✅ Configuration reset.", style=SUCCESS_STYLE)
155
147
  if hint:
156
- message += f" Run '{hint}' to set up again."
148
+ message.append(f" Run '{hint}' to set up again.")
157
149
  console.print(message)
158
150
 
159
151
 
160
152
  def _configure_interactive() -> None:
161
153
  """Shared configuration logic for both configure commands."""
162
- # Display AIP welcome banner
154
+ _render_configuration_header()
155
+ config = load_config()
156
+ _prompt_configuration_inputs(config)
157
+ _save_configuration(config)
158
+ _test_and_report_connection(config)
159
+ _print_post_configuration_hints()
160
+
161
+
162
+ @config_group.command()
163
+ def configure() -> None:
164
+ """Configure AIP CLI credentials and settings interactively."""
165
+ _configure_interactive()
166
+
167
+
168
+ # Alias command for backward compatibility
169
+ @click.command()
170
+ def configure_command() -> None:
171
+ """Configure AIP CLI credentials and settings interactively.
172
+
173
+ This is an alias for 'aip config configure' for backward compatibility.
174
+ """
175
+ # Delegate to the shared function
176
+ _configure_interactive()
177
+
178
+
179
+ # Note: The config command group should be registered in main.py
180
+
181
+
182
+ def _mask_api_key(value: str | None) -> str:
183
+ if not value:
184
+ return ""
185
+ return "***" + value[-4:] if len(value) > 4 else "***"
186
+
187
+
188
+ def _print_missing_config_hint() -> None:
189
+ hint = command_hint("config configure", slash_command="login")
190
+ if hint:
191
+ console.print(
192
+ f"[{WARNING_STYLE}]No configuration found.[/] Run {format_command_hint(hint) or hint} to set up."
193
+ )
194
+ else:
195
+ console.print(f"[{WARNING_STYLE}]No configuration found.[/]")
196
+
197
+
198
+ def _render_config_table(config: dict[str, str]) -> None:
199
+ table = AIPTable(title=f"{ICON_TOOL} AIP Configuration")
200
+ table.add_column("Setting", style=INFO, width=20)
201
+ table.add_column("Value", style=SUCCESS)
202
+
203
+ for key, value in config.items():
204
+ table.add_row(key, _mask_api_key(value) if key == "api_key" else str(value))
205
+
206
+ console.print(table)
207
+ console.print(Text(f"\n📁 Config file: {CONFIG_FILE}"))
208
+
209
+
210
+ def _render_configuration_header() -> None:
163
211
  branding = AIPBranding.create_from_sdk(
164
212
  sdk_version=_SDK_VERSION, package_name="glaip-sdk"
165
213
  )
166
- branding.display_welcome_panel(title="🔧 AIP Configuration")
214
+ heading = "[bold]>_ GDP Labs AI Agents Package (AIP CLI)[/bold]"
215
+ console.print(heading)
216
+ console.print()
217
+ console.print(branding.get_welcome_banner())
218
+ console.rule("[bold]AIP Configuration[/bold]", style=PRIMARY)
167
219
 
168
- # Load existing config
169
- config = load_config()
170
220
 
221
+ def _prompt_configuration_inputs(config: dict[str, str]) -> None:
171
222
  console.print("\n[bold]Enter your AIP configuration:[/bold]")
172
223
  console.print("(Leave blank to keep current values)")
173
224
  console.print("─" * 50)
174
225
 
175
- # API URL
226
+ _prompt_api_url(config)
227
+ _prompt_api_key(config)
228
+
229
+
230
+ def _prompt_api_url(config: dict[str, str]) -> None:
176
231
  current_url = config.get("api_url", "")
177
- console.print(
178
- f"\n[cyan]AIP API URL[/cyan] {f'(current: {current_url})' if current_url else ''}:"
179
- )
232
+ suffix = f"(current: {current_url})" if current_url else ""
233
+ console.print(f"\n[{ACCENT_STYLE}]AIP API URL[/] {suffix}:")
180
234
  new_url = input("> ").strip()
181
235
  if new_url:
182
236
  config["api_url"] = new_url
183
237
  elif not current_url:
184
238
  config["api_url"] = "https://your-aip-instance.com"
185
239
 
186
- # API Key
187
- current_key_masked = (
188
- "***" + config.get("api_key", "")[-4:] if config.get("api_key") else ""
189
- )
190
- console.print(
191
- f"\n[cyan]AIP API Key[/cyan] {f'(current: {current_key_masked})' if current_key_masked else ''}:"
192
- )
240
+
241
+ def _prompt_api_key(config: dict[str, str]) -> None:
242
+ current_key_masked = _mask_api_key(config.get("api_key"))
243
+ suffix = f"(current: {current_key_masked})" if current_key_masked else ""
244
+ console.print(f"\n[{ACCENT_STYLE}]AIP API Key[/] {suffix}:")
193
245
  new_key = getpass.getpass("> ")
194
246
  if new_key:
195
247
  config["api_key"] = new_key
196
248
 
197
- # Save configuration
249
+
250
+ def _save_configuration(config: dict[str, str]) -> None:
198
251
  save_config(config)
252
+ console.print(
253
+ Text(f"\n✅ Configuration saved to: {CONFIG_FILE}", style=SUCCESS_STYLE)
254
+ )
199
255
 
200
- console.print(Text(f"\n✅ Configuration saved to: {CONFIG_FILE}"))
201
256
 
202
- # Test the new configuration
257
+ def _test_and_report_connection(config: dict[str, str]) -> None:
203
258
  console.print("\n🔌 Testing connection...")
259
+ client: Client | None = None
204
260
  try:
205
- # Create client with new config
206
261
  client = Client(api_url=config["api_url"], api_key=config["api_key"])
207
-
208
- # Try to list resources to test connection
209
262
  try:
210
263
  agents = client.list_agents()
211
- console.print(Text(f"✅ Connection successful! Found {len(agents)} agents"))
212
- except Exception as e:
213
- console.print(Text(f"⚠️ Connection established but API call failed: {e}"))
264
+ console.print(
265
+ Text(
266
+ f"Connection successful! Found {len(agents)} agents",
267
+ style=SUCCESS_STYLE,
268
+ )
269
+ )
270
+ except Exception as exc: # pragma: no cover - API failures depend on network
271
+ console.print(
272
+ Text(
273
+ f"⚠️ Connection established but API call failed: {exc}",
274
+ style=WARNING_STYLE,
275
+ )
276
+ )
214
277
  console.print(
215
278
  " You may need to check your API permissions or network access"
216
279
  )
217
-
218
- client.close()
219
-
220
- except Exception as e:
221
- console.print(Text(f"❌ Connection failed: {e}"))
280
+ except Exception as exc:
281
+ console.print(Text(f"❌ Connection failed: {exc}"))
222
282
  console.print(" Please check your API URL and key")
223
283
  hint_status = command_hint("status", slash_command="status")
224
284
  if hint_status:
225
- console.print(f" You can run '{hint_status}' later to test again")
285
+ console.print(
286
+ f" You can run {format_command_hint(hint_status) or hint_status} later to test again"
287
+ )
288
+ finally:
289
+ if client is not None:
290
+ client.close()
291
+
226
292
 
293
+ def _print_post_configuration_hints() -> None:
227
294
  console.print("\n💡 You can now use AIP CLI commands!")
228
295
  hint_status = command_hint("status", slash_command="status")
229
296
  if hint_status:
230
- console.print(f" • Run '{hint_status}' to check connection")
297
+ console.print(
298
+ f" • Run {format_command_hint(hint_status) or hint_status} to check connection"
299
+ )
231
300
  hint_agents = command_hint("agents list", slash_command="agents")
232
301
  if hint_agents:
233
- console.print(f" • Run '{hint_agents}' to see your agents")
234
-
235
-
236
- @config_group.command()
237
- def configure() -> None:
238
- """Configure AIP CLI credentials and settings interactively."""
239
- _configure_interactive()
240
-
241
-
242
- # Alias command for backward compatibility
243
- @click.command()
244
- def configure_command() -> None:
245
- """Configure AIP CLI credentials and settings interactively.
246
-
247
- This is an alias for 'aip config configure' for backward compatibility.
248
- """
249
- # Delegate to the shared function
250
- _configure_interactive()
251
-
252
-
253
- # Note: The config command group should be registered in main.py
302
+ console.print(
303
+ f" • Run {format_command_hint(hint_agents) or hint_agents} to see your agents"
304
+ )
@@ -13,6 +13,13 @@ from typing import Any
13
13
  import click
14
14
  from rich.console import Console
15
15
 
16
+ from glaip_sdk.branding import (
17
+ ACCENT_STYLE,
18
+ INFO,
19
+ SUCCESS,
20
+ SUCCESS_STYLE,
21
+ WARNING_STYLE,
22
+ )
16
23
  from glaip_sdk.cli.context import detect_export_format, get_ctx_value, output_flags
17
24
  from glaip_sdk.cli.display import (
18
25
  display_api_error,
@@ -44,6 +51,7 @@ from glaip_sdk.cli.utils import (
44
51
  from glaip_sdk.config.constants import (
45
52
  DEFAULT_MCP_TYPE,
46
53
  )
54
+ from glaip_sdk.icons import ICON_TOOL
47
55
  from glaip_sdk.rich_components import AIPPanel
48
56
  from glaip_sdk.utils import format_datetime
49
57
  from glaip_sdk.utils.import_export import convert_export_to_import_format
@@ -73,6 +81,38 @@ def _is_sensitive_data(val: Any) -> bool:
73
81
  )
74
82
 
75
83
 
84
+ def _redact_sensitive_dict(val: dict[str, Any]) -> dict[str, Any]:
85
+ """Redact sensitive fields from a dictionary.
86
+
87
+ Args:
88
+ val: Dictionary to redact
89
+
90
+ Returns:
91
+ Redacted dictionary
92
+ """
93
+ redacted = val.copy()
94
+ sensitive_patterns = {"token", "password", "secret", "key", "credential"}
95
+ for k in redacted.keys():
96
+ if any(pattern in k.lower() for pattern in sensitive_patterns):
97
+ redacted[k] = "<REDACTED>"
98
+ return redacted
99
+
100
+
101
+ def _format_dict_value(val: dict[str, Any]) -> str:
102
+ """Format a dictionary value for display.
103
+
104
+ Args:
105
+ val: Dictionary to format
106
+
107
+ Returns:
108
+ Formatted string representation
109
+ """
110
+ if _is_sensitive_data(val):
111
+ redacted = _redact_sensitive_dict(val)
112
+ return json.dumps(redacted, indent=2)
113
+ return json.dumps(val, indent=2)
114
+
115
+
76
116
  def _format_preview_value(val: Any) -> str:
77
117
  """Format a value for display in update preview with sensitive data redaction.
78
118
 
@@ -85,15 +125,7 @@ def _format_preview_value(val: Any) -> str:
85
125
  if val is None:
86
126
  return "[dim]None[/dim]"
87
127
  if isinstance(val, dict):
88
- # Redact sensitive fields in authentication
89
- if _is_sensitive_data(val):
90
- redacted = val.copy()
91
- sensitive_patterns = {"token", "password", "secret", "key", "credential"}
92
- for k in list(redacted.keys()):
93
- if any(pattern in k.lower() for pattern in sensitive_patterns):
94
- redacted[k] = "<REDACTED>"
95
- return json.dumps(redacted, indent=2)
96
- return json.dumps(val, indent=2)
128
+ return _format_dict_value(val)
97
129
  if isinstance(val, str):
98
130
  return f'"{val}"' if val else '""'
99
131
  return str(val)
@@ -143,6 +175,26 @@ def _validate_import_payload_fields(import_payload: dict[str, Any]) -> bool:
143
175
  return has_updatable
144
176
 
145
177
 
178
+ def _get_config_transport(
179
+ transport: str | None,
180
+ import_payload: dict[str, Any] | None,
181
+ mcp: Any,
182
+ ) -> str | None:
183
+ """Get the transport value for config validation.
184
+
185
+ Args:
186
+ transport: CLI transport flag
187
+ import_payload: Optional import payload
188
+ mcp: Current MCP object
189
+
190
+ Returns:
191
+ Transport value or None
192
+ """
193
+ if import_payload:
194
+ return transport or import_payload.get("transport")
195
+ return transport or getattr(mcp, "transport", None)
196
+
197
+
146
198
  def _build_update_data_from_sources(
147
199
  import_payload: dict[str, Any] | None,
148
200
  mcp: Any,
@@ -190,11 +242,7 @@ def _build_update_data_from_sources(
190
242
  update_data["description"] = description
191
243
  if config is not None:
192
244
  parsed_config = parse_json_input(config)
193
- config_transport = (
194
- (transport or import_payload.get("transport"))
195
- if import_payload
196
- else (transport or getattr(mcp, "transport", None))
197
- )
245
+ config_transport = _get_config_transport(transport, import_payload, mcp)
198
246
  update_data["config"] = validate_mcp_config_structure(
199
247
  parsed_config,
200
248
  transport=config_transport,
@@ -487,8 +535,8 @@ def list_mcps(ctx: Any) -> None:
487
535
  # Define table columns: (data_key, header, style, width)
488
536
  columns = [
489
537
  ("id", "ID", "dim", 36),
490
- ("name", "Name", "cyan", None),
491
- ("config", "Config", "blue", None),
538
+ ("name", "Name", ACCENT_STYLE, None),
539
+ ("config", "Config", INFO, None),
492
540
  ]
493
541
 
494
542
  # Transform function for safe dictionary access
@@ -675,11 +723,11 @@ def _handle_mcp_export(
675
723
  mcp = client.mcps.get_mcp_by_id(mcp.id)
676
724
  except Exception as e:
677
725
  print_markup(
678
- f"[yellow]⚠️ Could not fetch full MCP details: {e}[/yellow]",
726
+ f"[{WARNING_STYLE}]⚠️ Could not fetch full MCP details: {e}[/]",
679
727
  console=console,
680
728
  )
681
729
  print_markup(
682
- "[yellow]⚠️ Proceeding with available data[/yellow]", console=console
730
+ f"[{WARNING_STYLE}]⚠️ Proceeding with available data[/]", console=console
683
731
  )
684
732
 
685
733
  # Determine if we should prompt for secrets
@@ -688,8 +736,8 @@ def _handle_mcp_export(
688
736
  # Warn user if non-interactive mode forces placeholder usage
689
737
  if not no_auth_prompt and not sys.stdin.isatty():
690
738
  print_markup(
691
- "[yellow]⚠️ Non-interactive mode detected. "
692
- "Using placeholder values for secrets.[/yellow]",
739
+ f"[{WARNING_STYLE}]⚠️ Non-interactive mode detected. "
740
+ "Using placeholder values for secrets.[/]",
693
741
  console=console,
694
742
  )
695
743
 
@@ -724,8 +772,8 @@ def _handle_mcp_export(
724
772
  write_resource_export(export_path, export_payload, detected_format)
725
773
 
726
774
  print_markup(
727
- f"[green]✅ Complete MCP configuration exported to: "
728
- f"{export_path} (format: {detected_format})[/green]",
775
+ f"[{SUCCESS_STYLE}]✅ Complete MCP configuration exported to: "
776
+ f"{export_path} (format: {detected_format})[/]",
729
777
  console=console,
730
778
  )
731
779
 
@@ -767,7 +815,7 @@ def _display_mcp_details(ctx: Any, client: Any, mcp: Any) -> None:
767
815
  )
768
816
  else:
769
817
  # Fall back to Pydantic model data
770
- console.print("[yellow]Falling back to Pydantic model data[/yellow]")
818
+ console.print(f"[{WARNING_STYLE}]Falling back to Pydantic model data[/]")
771
819
  result_data = {
772
820
  "id": str(getattr(mcp, "id", "N/A")),
773
821
  "name": getattr(mcp, "name", "N/A"),
@@ -873,8 +921,8 @@ def list_tools(ctx: Any, mcp_ref: str) -> None:
873
921
 
874
922
  # Define table columns: (data_key, header, style, width)
875
923
  columns = [
876
- ("name", "Name", "cyan", None),
877
- ("description", "Description", "green", 50),
924
+ ("name", "Name", ACCENT_STYLE, None),
925
+ ("description", "Description", INFO, 50),
878
926
  ]
879
927
 
880
928
  # Transform function for safe dictionary access
@@ -887,7 +935,11 @@ def list_tools(ctx: Any, mcp_ref: str) -> None:
887
935
  }
888
936
 
889
937
  output_list(
890
- ctx, tools, f"🔧 Tools from MCP: {mcp.name}", columns, transform_tool
938
+ ctx,
939
+ tools,
940
+ f"{ICON_TOOL} Tools from MCP: {mcp.name}",
941
+ columns,
942
+ transform_tool,
891
943
  )
892
944
 
893
945
  except Exception as e:
@@ -927,7 +979,7 @@ def connect(ctx: Any, config_file: str) -> None:
927
979
  view = get_ctx_value(ctx, "view", "rich")
928
980
  if view != "json":
929
981
  print_markup(
930
- f"[yellow]Connecting to MCP with config from {config_file}...[/yellow]",
982
+ f"[{WARNING_STYLE}]Connecting to MCP with config from {config_file}...[/]",
931
983
  console=console,
932
984
  )
933
985
 
@@ -944,10 +996,10 @@ def connect(ctx: Any, config_file: str) -> None:
944
996
  handle_json_output(ctx, result)
945
997
  else:
946
998
  success_panel = AIPPanel(
947
- f"[green]✓[/green] MCP connection successful!\n\n"
999
+ f"[{SUCCESS_STYLE}]✓[/] MCP connection successful!\n\n"
948
1000
  f"[bold]Result:[/bold] {result}",
949
1001
  title="🔌 Connection",
950
- border_style="green",
1002
+ border_style=SUCCESS,
951
1003
  )
952
1004
  console.print(success_panel)
953
1005
 
@@ -1074,8 +1126,7 @@ def update(
1074
1126
  )
1075
1127
  if not import_file and not cli_flags_provided:
1076
1128
  raise click.ClickException(
1077
- "No update fields specified. Use --import file or at least one of: "
1078
- "--name, --transport, --description, --config, --auth"
1129
+ "No update fields specified. Use --import or one of: --name, --transport, --description, --config, --auth"
1079
1130
  )
1080
1131
 
1081
1132
  # Resolve MCP using helper function
@@ -9,6 +9,7 @@ from typing import Any
9
9
  import click
10
10
  from rich.console import Console
11
11
 
12
+ from glaip_sdk.branding import ACCENT_STYLE, INFO, SUCCESS
12
13
  from glaip_sdk.cli.context import output_flags
13
14
  from glaip_sdk.cli.utils import (
14
15
  get_client,
@@ -42,9 +43,9 @@ def list_models(ctx: Any) -> None:
42
43
  # Define table columns: (data_key, header, style, width)
43
44
  columns = [
44
45
  ("id", "ID", "dim", 36),
45
- ("provider", "Provider", "cyan", None),
46
- ("name", "Model", "green", None),
47
- ("base_url", "Base URL", "yellow", None),
46
+ ("provider", "Provider", ACCENT_STYLE, None),
47
+ ("name", "Model", SUCCESS, None),
48
+ ("base_url", "Base URL", INFO, None),
48
49
  ]
49
50
 
50
51
  # Transform function for safe dictionary access