glaip-sdk 0.0.18__py3-none-any.whl → 0.0.20__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 (50) 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 +108 -21
  6. glaip_sdk/cli/commands/configure.py +141 -90
  7. glaip_sdk/cli/commands/mcps.py +371 -48
  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/parsers/json_input.py +62 -14
  17. glaip_sdk/cli/resolution.py +4 -1
  18. glaip_sdk/cli/slash/__init__.py +3 -4
  19. glaip_sdk/cli/slash/agent_session.py +88 -36
  20. glaip_sdk/cli/slash/prompt.py +20 -48
  21. glaip_sdk/cli/slash/session.py +440 -189
  22. glaip_sdk/cli/transcript/__init__.py +71 -0
  23. glaip_sdk/cli/transcript/cache.py +338 -0
  24. glaip_sdk/cli/transcript/capture.py +278 -0
  25. glaip_sdk/cli/transcript/export.py +38 -0
  26. glaip_sdk/cli/transcript/launcher.py +79 -0
  27. glaip_sdk/cli/transcript/viewer.py +624 -0
  28. glaip_sdk/cli/update_notifier.py +29 -5
  29. glaip_sdk/cli/utils.py +256 -74
  30. glaip_sdk/client/agents.py +3 -1
  31. glaip_sdk/client/run_rendering.py +2 -2
  32. glaip_sdk/icons.py +19 -0
  33. glaip_sdk/models.py +6 -0
  34. glaip_sdk/rich_components.py +29 -1
  35. glaip_sdk/utils/__init__.py +1 -1
  36. glaip_sdk/utils/client_utils.py +6 -4
  37. glaip_sdk/utils/display.py +61 -32
  38. glaip_sdk/utils/rendering/formatting.py +6 -5
  39. glaip_sdk/utils/rendering/renderer/base.py +213 -66
  40. glaip_sdk/utils/rendering/renderer/debug.py +73 -16
  41. glaip_sdk/utils/rendering/renderer/panels.py +27 -15
  42. glaip_sdk/utils/rendering/renderer/progress.py +61 -38
  43. glaip_sdk/utils/serialization.py +5 -2
  44. glaip_sdk/utils/validation.py +1 -2
  45. {glaip_sdk-0.0.18.dist-info → glaip_sdk-0.0.20.dist-info}/METADATA +1 -1
  46. glaip_sdk-0.0.20.dist-info/RECORD +80 -0
  47. glaip_sdk/utils/rich_utils.py +0 -29
  48. glaip_sdk-0.0.18.dist-info/RECORD +0 -73
  49. {glaip_sdk-0.0.18.dist-info → glaip_sdk-0.0.20.dist-info}/WHEEL +0 -0
  50. {glaip_sdk-0.0.18.dist-info → glaip_sdk-0.0.20.dist-info}/entry_points.txt +0 -0
glaip_sdk/_version.py CHANGED
@@ -6,6 +6,8 @@ Falls back to a dev marker when running from source without installation.
6
6
 
7
7
  from __future__ import annotations
8
8
 
9
+ from pathlib import Path
10
+
9
11
  try:
10
12
  from importlib.metadata import PackageNotFoundError, version # Python 3.8+
11
13
  except Exception: # pragma: no cover - extremely unlikely
@@ -38,8 +40,6 @@ def _try_get_dev_version() -> str | None:
38
40
  return None
39
41
 
40
42
  try:
41
- from pathlib import Path
42
-
43
43
  here = Path(__file__).resolve()
44
44
  root = here.parent.parent # project root (contains pyproject.toml)
45
45
  pyproject = root / "pyproject.toml"
glaip_sdk/branding.py CHANGED
@@ -36,9 +36,27 @@ SECONDARY_DARK = "#003A5C" # Darkest variant for emphasis
36
36
  SECONDARY_MEDIUM = "#005CB8" # Medium variant for UI elements
37
37
  SECONDARY_LIGHT = "#40B4E5" # Light variant for highlights
38
38
 
39
+ # Neutral companion palette (optimized for dark terminals)
40
+ SUCCESS = "#7FA089" # Muted teal-green for success messaging
41
+ WARNING = "#C3A46F" # Soft amber for warnings
42
+ ERROR = "#C97B6C" # Tempered coral-red for errors
43
+ INFO = "#9CA3AF" # Cool grey for informational accents
44
+ NEUTRAL = "#D1D5DB" # Light grey for muted text and dividers
45
+
39
46
  BORDER = PRIMARY # Keep borders aligned with primary brand tone
40
47
  TITLE_STYLE = f"bold {PRIMARY}"
41
48
  LABEL = "bold"
49
+ SUCCESS_STYLE = f"bold {SUCCESS}"
50
+ WARNING_STYLE = f"bold {WARNING}"
51
+ ERROR_STYLE = f"bold {ERROR}"
52
+ INFO_STYLE = f"bold {INFO}"
53
+ ACCENT_STYLE = INFO # For subdued inline highlights
54
+
55
+ # Hint styling (slash command helpers, tips, quick actions)
56
+ HINT_TITLE_STYLE = f"bold {SECONDARY_LIGHT}"
57
+ HINT_COMMAND_STYLE = f"bold {SECONDARY_LIGHT}"
58
+ HINT_DESCRIPTION_COLOR = NEUTRAL
59
+ HINT_PREFIX_STYLE = INFO_STYLE
42
60
 
43
61
 
44
62
  class AIPBranding:
@@ -118,11 +136,17 @@ GDP Labs AI Agents Package
118
136
  "architecture": platform.architecture()[0],
119
137
  }
120
138
 
121
- def display_welcome_panel(self, title: str = "Welcome to AIP") -> None:
139
+ def display_welcome_panel(
140
+ self,
141
+ title: str = "Welcome to AIP",
142
+ *,
143
+ console: Console | None = None,
144
+ ) -> None:
122
145
  """Display a welcome panel with branding.
123
146
 
124
147
  Args:
125
148
  title: Custom title for the welcome panel
149
+ console: Optional console instance to print to. If None, uses self.console
126
150
  """
127
151
  banner = self.get_welcome_banner()
128
152
  panel = AIPPanel(
@@ -131,7 +155,8 @@ GDP Labs AI Agents Package
131
155
  border_style=BORDER,
132
156
  padding=(1, 2),
133
157
  )
134
- self.console.print(panel)
158
+ target_console = console or self.console
159
+ target_console.print(panel)
135
160
 
136
161
  def display_version_panel(self) -> None:
137
162
  """Display a panel with comprehensive version information."""
glaip_sdk/cli/auth.py CHANGED
@@ -3,6 +3,10 @@
3
3
  This module provides utilities for preparing authentication data for export,
4
4
  including interactive secret capture and placeholder generation.
5
5
 
6
+ These helpers are distinct from the AIP CLI's own authentication, which always
7
+ relies on the API URL and API key managed via ``aip configure`` / `AIP_API_*`
8
+ environment variables.
9
+
6
10
  Authors:
7
11
  Raymond Christopher (raymond.christopher@gdplabs.id)
8
12
  """
@@ -13,6 +17,9 @@ from typing import Any
13
17
  import click
14
18
  from rich.console import Console
15
19
 
20
+ from glaip_sdk.branding import HINT_PREFIX_STYLE, WARNING_STYLE
21
+ from glaip_sdk.cli.utils import command_hint, format_command_hint
22
+
16
23
 
17
24
  def prepare_authentication_export(
18
25
  auth: dict[str, Any] | None,
@@ -92,21 +99,19 @@ def _get_token_value(
92
99
  The token string, either provided by the user or the placeholder.
93
100
  """
94
101
  if prompt_for_secrets:
95
- console.print(
96
- "[yellow]Bearer token is missing or redacted. "
97
- "Please provide the token.[/yellow]"
98
- )
99
- token_value = click.prompt(
100
- "Bearer token (leave blank for placeholder)",
101
- default="",
102
- show_default=False,
102
+ return _prompt_secret_with_placeholder(
103
+ console,
104
+ warning_message="Bearer token is missing or redacted. Please provide the token.",
105
+ prompt_message="Bearer token (leave blank for placeholder)",
106
+ placeholder=placeholder,
107
+ tip_cli_command="configure",
108
+ tip_slash_command="configure",
103
109
  )
104
- return token_value.strip() or placeholder
105
110
 
106
111
  if not click.get_text_stream("stdin").isatty():
107
112
  console.print(
108
- "[yellow]⚠️ Non-interactive mode: "
109
- "using placeholder for bearer token[/yellow]"
113
+ f"[{WARNING_STYLE}]⚠️ Non-interactive mode: "
114
+ "using placeholder for bearer token[/]"
110
115
  )
111
116
  return placeholder
112
117
 
@@ -205,20 +210,19 @@ def _get_api_key_value(
205
210
  The API key value, either provided by the user or the placeholder.
206
211
  """
207
212
  if prompt_for_secrets:
208
- console.print(
209
- f"[yellow]API key value for '{key_name}' is missing or redacted.[/yellow]"
210
- )
211
- key_value = click.prompt(
212
- f"API key value for '{key_name}' (leave blank for placeholder)",
213
- default="",
214
- show_default=False,
213
+ return _prompt_secret_with_placeholder(
214
+ console,
215
+ warning_message=f"API key value for '{key_name}' is missing or redacted.",
216
+ prompt_message=f"API key value for '{key_name}' (leave blank for placeholder)",
217
+ placeholder=placeholder,
218
+ tip_cli_command="configure api-key",
219
+ tip_slash_command="configure",
215
220
  )
216
- return key_value.strip() or placeholder
217
221
 
218
222
  if not click.get_text_stream("stdin").isatty():
219
223
  console.print(
220
- f"[yellow]⚠️ Non-interactive mode: "
221
- f"using placeholder for API key '{key_name}'[/yellow]"
224
+ f"[{WARNING_STYLE}]⚠️ Non-interactive mode: "
225
+ f"using placeholder for API key '{key_name}'[/]"
222
226
  )
223
227
  return placeholder
224
228
 
@@ -362,17 +366,18 @@ def _prompt_or_placeholder(
362
366
  The provided value or the placeholder.
363
367
  """
364
368
  if prompt_for_secrets:
365
- console.print(f"[yellow]Header '{name}' is missing or redacted.[/yellow]")
366
- value = click.prompt(
367
- f"Value for header '{name}' (leave blank for placeholder)",
368
- default="",
369
- show_default=False,
369
+ return _prompt_secret_with_placeholder(
370
+ console,
371
+ warning_message=f"Header '{name}' is missing or redacted.",
372
+ prompt_message=f"Value for header '{name}' (leave blank for placeholder)",
373
+ placeholder=placeholder,
374
+ tip_cli_command="configure",
375
+ tip_slash_command="configure",
370
376
  )
371
- return value.strip() or placeholder
372
377
 
373
378
  if not click.get_text_stream("stdin").isatty():
374
379
  console.print(
375
- f"[yellow]⚠️ Non-interactive mode: using placeholder for header '{name}'[/yellow]"
380
+ f"[{WARNING_STYLE}]⚠️ Non-interactive mode: using placeholder for header '{name}'[/]"
376
381
  )
377
382
  return placeholder
378
383
 
@@ -412,3 +417,63 @@ def _build_custom_headers(
412
417
  )
413
418
 
414
419
  return headers
420
+
421
+
422
+ def _prompt_secret_with_placeholder(
423
+ console: Console,
424
+ *,
425
+ warning_message: str,
426
+ prompt_message: str,
427
+ placeholder: str,
428
+ tip_cli_command: str | None = "configure",
429
+ tip_slash_command: str | None = "configure",
430
+ mask_input: bool = True,
431
+ retry_limit: int = 1,
432
+ ) -> str:
433
+ """Prompt for a secret value with masking, retries, and placeholder fallback.
434
+
435
+ Args:
436
+ console: Rich console used to render messaging.
437
+ warning_message: Message shown before prompting (rendered with warning style).
438
+ prompt_message: The message passed to :func:`click.prompt`.
439
+ placeholder: Placeholder value inserted when the user skips input.
440
+ tip_cli_command: CLI command (without ``aip`` prefix) used to build hints.
441
+ tip_slash_command: Slash command counterpart used in hints.
442
+ mask_input: Whether to hide user input while typing.
443
+ retry_limit: Number of additional attempts when the user submits empty input.
444
+
445
+ Returns:
446
+ The value entered by the user or the provided placeholder.
447
+ """
448
+ console.print(f"[{WARNING_STYLE}]{warning_message}[/]")
449
+
450
+ tip = command_hint(tip_cli_command, tip_slash_command)
451
+ if tip:
452
+ console.print(
453
+ f"[{HINT_PREFIX_STYLE}]Tip:[/] use {format_command_hint(tip) or tip} later if you want to update these credentials."
454
+ )
455
+
456
+ attempts = 0
457
+ while attempts <= retry_limit:
458
+ response = click.prompt(
459
+ prompt_message,
460
+ default="",
461
+ show_default=False,
462
+ hide_input=mask_input,
463
+ )
464
+ value = response.strip()
465
+ if value:
466
+ return value
467
+
468
+ if attempts < retry_limit:
469
+ console.print(
470
+ f"[{WARNING_STYLE}]No value entered. Enter a value or press Enter again to use the placeholder.[/]"
471
+ )
472
+ attempts += 1
473
+ continue
474
+
475
+ console.print("[dim]Using placeholder value.[/dim]")
476
+ return placeholder
477
+
478
+ # This line is unreachable as the loop always returns
479
+ # return placeholder
@@ -1,5 +1,5 @@
1
1
  """CLI commands package exports."""
2
2
 
3
- from glaip_sdk.cli.commands import agents, configure, mcps, models, tools
3
+ from glaip_sdk.cli.commands import agents, configure, mcps, models, tools, update
4
4
 
5
- __all__ = ["agents", "configure", "mcps", "models", "tools"]
5
+ __all__ = ["agents", "configure", "mcps", "models", "tools", "update"]
@@ -4,6 +4,8 @@ Authors:
4
4
  Raymond Christopher (raymond.christopher@gdplabs.id)
5
5
  """
6
6
 
7
+ from __future__ import annotations
8
+
7
9
  import json
8
10
  import os
9
11
  from collections.abc import Mapping
@@ -13,6 +15,14 @@ from typing import Any
13
15
  import click
14
16
  from rich.console import Console
15
17
 
18
+ from glaip_sdk.branding import (
19
+ ACCENT_STYLE,
20
+ ERROR_STYLE,
21
+ INFO,
22
+ SUCCESS,
23
+ SUCCESS_STYLE,
24
+ WARNING_STYLE,
25
+ )
16
26
  from glaip_sdk.cli.agent_config import (
17
27
  merge_agent_config_with_cli_args as merge_import_with_cli_args,
18
28
  )
@@ -45,6 +55,10 @@ from glaip_sdk.cli.io import (
45
55
  )
46
56
  from glaip_sdk.cli.resolution import resolve_resource_reference
47
57
  from glaip_sdk.cli.rich_helpers import markup_text, print_markup
58
+ from glaip_sdk.cli.transcript import (
59
+ maybe_launch_post_run_viewer,
60
+ store_transcript_for_session,
61
+ )
48
62
  from glaip_sdk.cli.utils import (
49
63
  _fuzzy_pick_for_resources,
50
64
  build_renderer,
@@ -65,6 +79,7 @@ from glaip_sdk.cli.validators import (
65
79
  )
66
80
  from glaip_sdk.config.constants import DEFAULT_AGENT_RUN_TIMEOUT, DEFAULT_MODEL
67
81
  from glaip_sdk.exceptions import AgentTimeoutError
82
+ from glaip_sdk.icons import ICON_AGENT
68
83
  from glaip_sdk.utils import format_datetime, is_uuid
69
84
  from glaip_sdk.utils.agent_config import normalize_agent_config_for_import
70
85
  from glaip_sdk.utils.import_export import convert_export_to_import_format
@@ -168,17 +183,41 @@ def _fetch_full_agent_details(client: Any, agent: Any) -> Any | None:
168
183
  return agent
169
184
 
170
185
 
186
+ def _normalise_model_name(value: Any) -> str | None:
187
+ """Return a cleaned model name or None when not usable."""
188
+ if value is None:
189
+ return None
190
+ if isinstance(value, str):
191
+ cleaned = value.strip()
192
+ return cleaned or None
193
+ if isinstance(value, bool):
194
+ return None
195
+ return str(value)
196
+
197
+
198
+ def _model_from_config(agent: Any) -> str | None:
199
+ """Extract a usable model name from an agent's configuration mapping."""
200
+ config = getattr(agent, "agent_config", None)
201
+ if not config or not isinstance(config, dict):
202
+ return None
203
+
204
+ for key in ("lm_name", "model"):
205
+ normalised = _normalise_model_name(config.get(key))
206
+ if normalised:
207
+ return normalised
208
+ return None
209
+
210
+
171
211
  def _get_agent_model_name(agent: Any) -> str | None:
172
212
  """Extract model name from agent configuration."""
173
- # Try different possible locations for model name
174
- if hasattr(agent, "agent_config") and agent.agent_config:
175
- if isinstance(agent.agent_config, dict):
176
- return agent.agent_config.get("lm_name") or agent.agent_config.get("model")
213
+ config_model = _model_from_config(agent)
214
+ if config_model:
215
+ return config_model
177
216
 
178
- if hasattr(agent, "model") and agent.model:
179
- return agent.model
217
+ normalised_attr = _normalise_model_name(getattr(agent, "model", None))
218
+ if normalised_attr:
219
+ return normalised_attr
180
220
 
181
- # Default fallback
182
221
  return DEFAULT_MODEL
183
222
 
184
223
 
@@ -198,7 +237,7 @@ def _resolve_resources_by_name(
198
237
  List of resolved resource IDs
199
238
  """
200
239
  out = []
201
- for ref in list(items or ()):
240
+ for ref in items or ():
202
241
  if is_uuid(ref):
203
242
  out.append(ref)
204
243
  continue
@@ -275,7 +314,7 @@ def _format_fallback_agent_data(client: Any, agent: Any) -> dict:
275
314
  def _display_agent_details(ctx: Any, client: Any, agent: Any) -> None:
276
315
  """Display full agent details using raw API data to preserve ALL fields."""
277
316
  if agent is None:
278
- handle_rich_output(ctx, markup_text("[red]❌ No agent provided[/red]"))
317
+ handle_rich_output(ctx, markup_text(f"[{ERROR_STYLE}]❌ No agent provided[/]"))
279
318
  return
280
319
 
281
320
  # Try to fetch and format raw agent data first
@@ -288,7 +327,7 @@ def _display_agent_details(ctx: Any, client: Any, agent: Any) -> None:
288
327
 
289
328
  if formatted_data:
290
329
  # Use raw API data - this preserves ALL fields including account_id
291
- panel_title = f"🤖 {formatted_data.get('name', 'Unknown')}"
330
+ panel_title = f"{ICON_AGENT} {formatted_data.get('name', 'Unknown')}"
292
331
  output_result(
293
332
  ctx,
294
333
  formatted_data,
@@ -298,7 +337,7 @@ def _display_agent_details(ctx: Any, client: Any, agent: Any) -> None:
298
337
  # Fall back to Pydantic model data if raw fetch fails
299
338
  handle_rich_output(
300
339
  ctx,
301
- markup_text("[yellow]Falling back to Pydantic model data[/yellow]"),
340
+ markup_text(f"[{WARNING_STYLE}]Falling back to Pydantic model data[/]"),
302
341
  )
303
342
 
304
343
  with spinner_context(
@@ -401,10 +440,10 @@ def list_agents(
401
440
  # Define table columns: (data_key, header, style, width)
402
441
  columns = [
403
442
  ("id", "ID", "dim", 36),
404
- ("name", "Name", "cyan", None),
405
- ("type", "Type", "yellow", None),
406
- ("framework", "Framework", "blue", None),
407
- ("version", "Version", "green", None),
443
+ ("name", "Name", ACCENT_STYLE, None),
444
+ ("type", "Type", WARNING_STYLE, None),
445
+ ("framework", "Framework", INFO, None),
446
+ ("version", "Version", SUCCESS, None),
408
447
  ]
409
448
 
410
449
  # Transform function for safe attribute access
@@ -439,7 +478,7 @@ def list_agents(
439
478
  output_list(
440
479
  ctx,
441
480
  agents,
442
- "🤖 Available Agents",
481
+ f"{ICON_AGENT} Available Agents",
443
482
  columns,
444
483
  transform_agent,
445
484
  skip_picker=simple
@@ -497,19 +536,21 @@ def get(ctx: Any, agent_ref: str, select: int | None, export: str | None) -> Non
497
536
  handle_rich_output(
498
537
  ctx,
499
538
  markup_text(
500
- f"[yellow]⚠️ Could not fetch full agent details: {e}[/yellow]"
539
+ f"[{WARNING_STYLE}]⚠️ Could not fetch full agent details: {e}[/]"
501
540
  ),
502
541
  )
503
542
  handle_rich_output(
504
543
  ctx,
505
- markup_text("[yellow]⚠️ Proceeding with available data[/yellow]"),
544
+ markup_text(
545
+ f"[{WARNING_STYLE}]⚠️ Proceeding with available data[/]"
546
+ ),
506
547
  )
507
548
 
508
549
  export_resource_to_file(agent, export_path, detected_format)
509
550
  handle_rich_output(
510
551
  ctx,
511
552
  markup_text(
512
- f"[green]✅ Complete agent configuration exported to: {export_path} (format: {detected_format})[/green]"
553
+ f"[{SUCCESS_STYLE}]✅ Complete agent configuration exported to: {export_path} (format: {detected_format})[/]"
513
554
  ),
514
555
  )
515
556
 
@@ -621,7 +662,9 @@ def _save_run_transcript(save: str | None, result: Any, working_console: Any) ->
621
662
 
622
663
  with open(save, "w", encoding="utf-8") as f:
623
664
  f.write(content)
624
- print_markup(f"[green]Full debug output saved to: {save}[/green]", console=console)
665
+ print_markup(
666
+ f"[{SUCCESS_STYLE}]Full debug output saved to: {save}[/]", console=console
667
+ )
625
668
 
626
669
 
627
670
  @agents_group.command()
@@ -678,6 +721,10 @@ def run(
678
721
  """
679
722
  final_input_text = _validate_run_input(input_option, input_text)
680
723
 
724
+ if verbose:
725
+ _emit_verbose_guidance(ctx)
726
+ return
727
+
681
728
  try:
682
729
  client = get_client(ctx)
683
730
  agent = _resolve_agent(
@@ -703,8 +750,29 @@ def run(
703
750
 
704
751
  result = client.agents.run_agent(**run_kwargs, timeout=timeout)
705
752
 
753
+ slash_mode = _running_in_slash_mode(ctx)
754
+ agent_id = str(_safe_agent_attribute(agent, "id") or "") or None
755
+ agent_name = _safe_agent_attribute(agent, "name")
756
+ model_hint = _get_agent_model_name(agent)
757
+
758
+ transcript_context = store_transcript_for_session(
759
+ ctx,
760
+ renderer,
761
+ final_result=result,
762
+ agent_id=agent_id,
763
+ agent_name=agent_name,
764
+ model=model_hint,
765
+ source="slash" if slash_mode else "cli",
766
+ )
767
+
706
768
  _handle_run_output(ctx, result, renderer)
707
769
  _save_run_transcript(save, result, working_console)
770
+ maybe_launch_post_run_viewer(
771
+ ctx,
772
+ transcript_context,
773
+ console=console,
774
+ slash_mode=slash_mode,
775
+ )
708
776
 
709
777
  except AgentTimeoutError as e:
710
778
  error_msg = str(e)
@@ -714,6 +782,25 @@ def run(
714
782
  _handle_command_exception(ctx, e)
715
783
 
716
784
 
785
+ def _running_in_slash_mode(ctx: Any) -> bool:
786
+ ctx_obj = getattr(ctx, "obj", None)
787
+ return isinstance(ctx_obj, dict) and bool(ctx_obj.get("_slash_session"))
788
+
789
+
790
+ def _emit_verbose_guidance(ctx: Any) -> None:
791
+ if _running_in_slash_mode(ctx):
792
+ message = (
793
+ "[dim]Tip:[/] Verbose streaming has been retired in the command palette. Run the agent normally and open "
794
+ "the post-run viewer (Ctrl+T) to inspect the transcript."
795
+ )
796
+ else:
797
+ message = (
798
+ "[dim]Tip:[/] `--verbose` is no longer supported. Re-run without the flag and toggle the post-run viewer "
799
+ "(Ctrl+T) for detailed output."
800
+ )
801
+ handle_rich_output(ctx, markup_text(message))
802
+
803
+
717
804
  def _handle_import_file_logic(
718
805
  import_file: str,
719
806
  model: str | None,
@@ -1317,7 +1404,7 @@ def sync_langflow(ctx: Any, base_url: str | None, api_key: str | None) -> None:
1317
1404
  handle_rich_output(
1318
1405
  ctx,
1319
1406
  markup_text(
1320
- f"[green]✅ Successfully synced {success_count} LangFlow agents ({total_count} total processed)[/green]"
1407
+ f"[{SUCCESS_STYLE}]✅ Successfully synced {success_count} LangFlow agents ({total_count} total processed)[/]"
1321
1408
  ),
1322
1409
  )
1323
1410