glaip-sdk 0.0.19__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.
- glaip_sdk/_version.py +2 -2
- glaip_sdk/branding.py +27 -2
- glaip_sdk/cli/auth.py +93 -28
- glaip_sdk/cli/commands/__init__.py +2 -2
- glaip_sdk/cli/commands/agents.py +108 -21
- glaip_sdk/cli/commands/configure.py +141 -90
- glaip_sdk/cli/commands/mcps.py +81 -29
- glaip_sdk/cli/commands/models.py +4 -3
- glaip_sdk/cli/commands/tools.py +27 -14
- glaip_sdk/cli/commands/update.py +66 -0
- glaip_sdk/cli/config.py +13 -2
- glaip_sdk/cli/display.py +35 -26
- glaip_sdk/cli/io.py +14 -5
- glaip_sdk/cli/main.py +185 -73
- glaip_sdk/cli/pager.py +2 -1
- glaip_sdk/cli/resolution.py +4 -1
- glaip_sdk/cli/slash/__init__.py +3 -4
- glaip_sdk/cli/slash/agent_session.py +88 -36
- glaip_sdk/cli/slash/prompt.py +20 -48
- glaip_sdk/cli/slash/session.py +440 -189
- glaip_sdk/cli/transcript/__init__.py +71 -0
- glaip_sdk/cli/transcript/cache.py +338 -0
- glaip_sdk/cli/transcript/capture.py +278 -0
- glaip_sdk/cli/transcript/export.py +38 -0
- glaip_sdk/cli/transcript/launcher.py +79 -0
- glaip_sdk/cli/transcript/viewer.py +624 -0
- glaip_sdk/cli/update_notifier.py +29 -5
- glaip_sdk/cli/utils.py +256 -74
- glaip_sdk/client/agents.py +3 -1
- glaip_sdk/client/run_rendering.py +2 -2
- glaip_sdk/icons.py +19 -0
- glaip_sdk/models.py +6 -0
- glaip_sdk/rich_components.py +29 -1
- glaip_sdk/utils/__init__.py +1 -1
- glaip_sdk/utils/client_utils.py +6 -4
- glaip_sdk/utils/display.py +61 -32
- glaip_sdk/utils/rendering/formatting.py +6 -5
- glaip_sdk/utils/rendering/renderer/base.py +213 -66
- glaip_sdk/utils/rendering/renderer/debug.py +73 -16
- glaip_sdk/utils/rendering/renderer/panels.py +27 -15
- glaip_sdk/utils/rendering/renderer/progress.py +61 -38
- glaip_sdk/utils/serialization.py +5 -2
- glaip_sdk/utils/validation.py +1 -2
- {glaip_sdk-0.0.19.dist-info → glaip_sdk-0.0.20.dist-info}/METADATA +1 -1
- glaip_sdk-0.0.20.dist-info/RECORD +80 -0
- glaip_sdk/utils/rich_utils.py +0 -29
- glaip_sdk-0.0.19.dist-info/RECORD +0 -73
- {glaip_sdk-0.0.19.dist-info → glaip_sdk-0.0.20.dist-info}/WHEEL +0 -0
- {glaip_sdk-0.0.19.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(
|
|
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
|
|
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
|
-
|
|
96
|
-
|
|
97
|
-
"Please provide the token.
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
"
|
|
101
|
-
|
|
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
|
-
"[
|
|
109
|
-
"using placeholder for bearer token[/
|
|
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
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
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"[
|
|
221
|
-
f"using placeholder for API key '{key_name}'[/
|
|
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
|
-
|
|
366
|
-
|
|
367
|
-
f"
|
|
368
|
-
|
|
369
|
-
|
|
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"[
|
|
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"]
|
glaip_sdk/cli/commands/agents.py
CHANGED
|
@@ -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
|
-
|
|
174
|
-
if
|
|
175
|
-
|
|
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
|
-
|
|
179
|
-
|
|
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
|
|
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("[
|
|
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"
|
|
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("[
|
|
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",
|
|
405
|
-
("type", "Type",
|
|
406
|
-
("framework", "Framework",
|
|
407
|
-
("version", "Version",
|
|
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
|
-
"
|
|
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"[
|
|
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(
|
|
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"[
|
|
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(
|
|
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"[
|
|
1407
|
+
f"[{SUCCESS_STYLE}]✅ Successfully synced {success_count} LangFlow agents ({total_count} total processed)[/]"
|
|
1321
1408
|
),
|
|
1322
1409
|
)
|
|
1323
1410
|
|