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.
- 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 +371 -48
- 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/parsers/json_input.py +62 -14
- 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.18.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.18.dist-info/RECORD +0 -73
- {glaip_sdk-0.0.18.dist-info → glaip_sdk-0.0.20.dist-info}/WHEEL +0 -0
- {glaip_sdk-0.0.18.dist-info → glaip_sdk-0.0.20.dist-info}/entry_points.txt +0 -0
glaip_sdk/cli/commands/tools.py
CHANGED
|
@@ -12,6 +12,13 @@ from typing import Any
|
|
|
12
12
|
import click
|
|
13
13
|
from rich.console import Console
|
|
14
14
|
|
|
15
|
+
from glaip_sdk.branding import (
|
|
16
|
+
ACCENT_STYLE,
|
|
17
|
+
ERROR_STYLE,
|
|
18
|
+
INFO,
|
|
19
|
+
SUCCESS_STYLE,
|
|
20
|
+
WARNING_STYLE,
|
|
21
|
+
)
|
|
15
22
|
from glaip_sdk.cli.context import detect_export_format, get_ctx_value, output_flags
|
|
16
23
|
from glaip_sdk.cli.display import (
|
|
17
24
|
display_api_error,
|
|
@@ -40,6 +47,7 @@ from glaip_sdk.cli.utils import (
|
|
|
40
47
|
output_result,
|
|
41
48
|
spinner_context,
|
|
42
49
|
)
|
|
50
|
+
from glaip_sdk.icons import ICON_TOOL
|
|
43
51
|
from glaip_sdk.utils import format_datetime
|
|
44
52
|
from glaip_sdk.utils.import_export import merge_import_with_cli_args
|
|
45
53
|
|
|
@@ -202,8 +210,8 @@ def list_tools(ctx: Any, tool_type: str | None) -> None:
|
|
|
202
210
|
# Define table columns: (data_key, header, style, width)
|
|
203
211
|
columns = [
|
|
204
212
|
("id", "ID", "dim", 36),
|
|
205
|
-
("name", "Name",
|
|
206
|
-
("framework", "Framework",
|
|
213
|
+
("name", "Name", ACCENT_STYLE, None),
|
|
214
|
+
("framework", "Framework", INFO, None),
|
|
207
215
|
]
|
|
208
216
|
|
|
209
217
|
# Transform function for safe dictionary access
|
|
@@ -213,7 +221,7 @@ def list_tools(ctx: Any, tool_type: str | None) -> None:
|
|
|
213
221
|
row["id"] = str(row["id"])
|
|
214
222
|
return row
|
|
215
223
|
|
|
216
|
-
output_list(ctx, tools, "
|
|
224
|
+
output_list(ctx, tools, f"{ICON_TOOL} Available Tools", columns, transform_tool)
|
|
217
225
|
|
|
218
226
|
except Exception as e:
|
|
219
227
|
raise click.ClickException(str(e))
|
|
@@ -350,11 +358,11 @@ def get(ctx: Any, tool_ref: str, select: int | None, export: str | None) -> None
|
|
|
350
358
|
tool = client.get_tool_by_id(tool.id)
|
|
351
359
|
except Exception as e:
|
|
352
360
|
print_markup(
|
|
353
|
-
f"[
|
|
361
|
+
f"[{WARNING_STYLE}]⚠️ Could not fetch full tool details: {e}[/]",
|
|
354
362
|
console=console,
|
|
355
363
|
)
|
|
356
364
|
print_markup(
|
|
357
|
-
"[
|
|
365
|
+
f"[{WARNING_STYLE}]⚠️ Proceeding with available data[/]",
|
|
358
366
|
console=console,
|
|
359
367
|
)
|
|
360
368
|
|
|
@@ -365,7 +373,7 @@ def get(ctx: Any, tool_ref: str, select: int | None, export: str | None) -> None
|
|
|
365
373
|
):
|
|
366
374
|
export_resource_to_file(tool, export_path, detected_format)
|
|
367
375
|
print_markup(
|
|
368
|
-
f"[
|
|
376
|
+
f"[{SUCCESS_STYLE}]✅ Complete tool configuration exported to: {export_path} (format: {detected_format})[/]",
|
|
369
377
|
console=console,
|
|
370
378
|
)
|
|
371
379
|
|
|
@@ -395,11 +403,11 @@ def get(ctx: Any, tool_ref: str, select: int | None, export: str | None) -> None
|
|
|
395
403
|
ctx,
|
|
396
404
|
formatted_data,
|
|
397
405
|
title="Tool Details",
|
|
398
|
-
panel_title=f"
|
|
406
|
+
panel_title=f"{ICON_TOOL} {raw_tool_data.get('name', 'Unknown')}",
|
|
399
407
|
)
|
|
400
408
|
else:
|
|
401
409
|
# Fall back to original method if raw fetch fails
|
|
402
|
-
console.print("[
|
|
410
|
+
console.print(f"[{WARNING_STYLE}]Falling back to Pydantic model data[/]")
|
|
403
411
|
|
|
404
412
|
# Create result data with all available fields from backend
|
|
405
413
|
result_data = {
|
|
@@ -412,7 +420,10 @@ def get(ctx: Any, tool_ref: str, select: int | None, export: str | None) -> None
|
|
|
412
420
|
}
|
|
413
421
|
|
|
414
422
|
output_result(
|
|
415
|
-
ctx,
|
|
423
|
+
ctx,
|
|
424
|
+
result_data,
|
|
425
|
+
title="Tool Details",
|
|
426
|
+
panel_title=f"{ICON_TOOL} {tool.name}",
|
|
416
427
|
)
|
|
417
428
|
|
|
418
429
|
except Exception as e:
|
|
@@ -475,7 +486,7 @@ def update(
|
|
|
475
486
|
)
|
|
476
487
|
handle_rich_output(
|
|
477
488
|
ctx,
|
|
478
|
-
markup_text(f"[
|
|
489
|
+
markup_text(f"[{SUCCESS_STYLE}]✓[/] Tool code updated from {file}"),
|
|
479
490
|
)
|
|
480
491
|
elif update_data:
|
|
481
492
|
# Update metadata only (native tools only)
|
|
@@ -490,11 +501,11 @@ def update(
|
|
|
490
501
|
):
|
|
491
502
|
updated_tool = tool.update(**update_data)
|
|
492
503
|
handle_rich_output(
|
|
493
|
-
ctx, markup_text("[
|
|
504
|
+
ctx, markup_text(f"[{SUCCESS_STYLE}]✓[/] Tool metadata updated")
|
|
494
505
|
)
|
|
495
506
|
else:
|
|
496
507
|
handle_rich_output(
|
|
497
|
-
ctx, markup_text("[
|
|
508
|
+
ctx, markup_text(f"[{WARNING_STYLE}]No updates specified[/]")
|
|
498
509
|
)
|
|
499
510
|
return
|
|
500
511
|
|
|
@@ -574,11 +585,13 @@ def script(ctx: Any, tool_id: str) -> None:
|
|
|
574
585
|
if get_ctx_value(ctx, "view") == "json":
|
|
575
586
|
click.echo(json.dumps({"script": script_content}, indent=2))
|
|
576
587
|
else:
|
|
577
|
-
console.print(f"[
|
|
588
|
+
console.print(f"[{SUCCESS_STYLE}]📜 Tool Script for '{tool_id}':[/]")
|
|
578
589
|
console.print(script_content)
|
|
579
590
|
|
|
580
591
|
except Exception as e:
|
|
581
592
|
handle_json_output(ctx, error=e)
|
|
582
593
|
if get_ctx_value(ctx, "view") != "json":
|
|
583
|
-
print_markup(
|
|
594
|
+
print_markup(
|
|
595
|
+
f"[{ERROR_STYLE}]Error getting tool script: {e}[/]", console=console
|
|
596
|
+
)
|
|
584
597
|
raise click.ClickException(str(e))
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
"""Update command for upgrading the glaip-sdk package.
|
|
2
|
+
|
|
3
|
+
Author:
|
|
4
|
+
Raymond Christopher (raymond.christopher@gdplabs.id)
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
import subprocess
|
|
10
|
+
import sys
|
|
11
|
+
from collections.abc import Sequence
|
|
12
|
+
|
|
13
|
+
import click
|
|
14
|
+
from rich.console import Console
|
|
15
|
+
|
|
16
|
+
from glaip_sdk.branding import ACCENT_STYLE, ERROR_STYLE, INFO_STYLE, SUCCESS_STYLE
|
|
17
|
+
|
|
18
|
+
PACKAGE_NAME = "glaip-sdk"
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def _build_upgrade_command(include_prerelease: bool) -> Sequence[str]:
|
|
22
|
+
"""Return the pip command used to upgrade the SDK."""
|
|
23
|
+
command = [
|
|
24
|
+
sys.executable,
|
|
25
|
+
"-m",
|
|
26
|
+
"pip",
|
|
27
|
+
"install",
|
|
28
|
+
"--upgrade",
|
|
29
|
+
PACKAGE_NAME,
|
|
30
|
+
]
|
|
31
|
+
if include_prerelease:
|
|
32
|
+
command.append("--pre")
|
|
33
|
+
return command
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
@click.command(name="update")
|
|
37
|
+
@click.option(
|
|
38
|
+
"--pre",
|
|
39
|
+
"include_prerelease",
|
|
40
|
+
is_flag=True,
|
|
41
|
+
help="Include pre-release versions when upgrading.",
|
|
42
|
+
)
|
|
43
|
+
def update_command(include_prerelease: bool) -> None:
|
|
44
|
+
"""Upgrade the glaip-sdk package using pip."""
|
|
45
|
+
console = Console()
|
|
46
|
+
upgrade_cmd = _build_upgrade_command(include_prerelease)
|
|
47
|
+
console.print(
|
|
48
|
+
f"[{ACCENT_STYLE}]Upgrading {PACKAGE_NAME} using[/] "
|
|
49
|
+
f"[{INFO_STYLE}]{' '.join(upgrade_cmd)}[/]"
|
|
50
|
+
)
|
|
51
|
+
|
|
52
|
+
try:
|
|
53
|
+
subprocess.run(upgrade_cmd, check=True)
|
|
54
|
+
except FileNotFoundError as exc:
|
|
55
|
+
raise click.ClickException(
|
|
56
|
+
"Unable to locate Python executable to run pip. "
|
|
57
|
+
"Please ensure Python is installed and try again."
|
|
58
|
+
) from exc
|
|
59
|
+
except subprocess.CalledProcessError as exc:
|
|
60
|
+
console.print(
|
|
61
|
+
f"[{ERROR_STYLE}]Automatic upgrade failed.[/] "
|
|
62
|
+
f"Please run `pip install -U {PACKAGE_NAME}` manually."
|
|
63
|
+
)
|
|
64
|
+
raise click.ClickException("Automatic upgrade failed.") from exc
|
|
65
|
+
|
|
66
|
+
console.print(f"[{SUCCESS_STYLE}]✅ {PACKAGE_NAME} upgraded successfully.[/]")
|
glaip_sdk/cli/config.py
CHANGED
|
@@ -12,6 +12,14 @@ import yaml
|
|
|
12
12
|
|
|
13
13
|
CONFIG_DIR = Path.home() / ".aip"
|
|
14
14
|
CONFIG_FILE = CONFIG_DIR / "config.yaml"
|
|
15
|
+
_ALLOWED_KEYS = {"api_url", "api_key", "timeout"}
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def _sanitize_config(data: dict[str, Any] | None) -> dict[str, Any]:
|
|
19
|
+
"""Return config filtered to allowed keys only."""
|
|
20
|
+
if not data:
|
|
21
|
+
return {}
|
|
22
|
+
return {k: v for k, v in data.items() if k in _ALLOWED_KEYS}
|
|
15
23
|
|
|
16
24
|
|
|
17
25
|
def load_config() -> dict[str, Any]:
|
|
@@ -21,7 +29,8 @@ def load_config() -> dict[str, Any]:
|
|
|
21
29
|
|
|
22
30
|
try:
|
|
23
31
|
with open(CONFIG_FILE) as f:
|
|
24
|
-
|
|
32
|
+
loaded = yaml.safe_load(f) or {}
|
|
33
|
+
return _sanitize_config(loaded)
|
|
25
34
|
except yaml.YAMLError:
|
|
26
35
|
return {}
|
|
27
36
|
|
|
@@ -30,8 +39,10 @@ def save_config(config: dict[str, Any]) -> None:
|
|
|
30
39
|
"""Save configuration to file."""
|
|
31
40
|
CONFIG_DIR.mkdir(exist_ok=True)
|
|
32
41
|
|
|
42
|
+
sanitized = _sanitize_config(config)
|
|
43
|
+
|
|
33
44
|
with open(CONFIG_FILE, "w") as f:
|
|
34
|
-
yaml.dump(
|
|
45
|
+
yaml.dump(sanitized, f, default_flow_style=False)
|
|
35
46
|
|
|
36
47
|
# Set secure file permissions
|
|
37
48
|
try:
|
glaip_sdk/cli/display.py
CHANGED
|
@@ -15,8 +15,10 @@ from rich.console import Console
|
|
|
15
15
|
from rich.panel import Panel
|
|
16
16
|
from rich.text import Text
|
|
17
17
|
|
|
18
|
-
from glaip_sdk.
|
|
19
|
-
from glaip_sdk.cli.
|
|
18
|
+
from glaip_sdk.branding import ERROR_STYLE, SUCCESS, SUCCESS_STYLE, WARNING_STYLE
|
|
19
|
+
from glaip_sdk.cli.rich_helpers import markup_text
|
|
20
|
+
from glaip_sdk.cli.utils import command_hint, format_command_hint
|
|
21
|
+
from glaip_sdk.icons import ICON_AGENT, ICON_TOOL
|
|
20
22
|
from glaip_sdk.rich_components import AIPPanel
|
|
21
23
|
|
|
22
24
|
console = Console()
|
|
@@ -44,10 +46,10 @@ def display_creation_success(
|
|
|
44
46
|
)
|
|
45
47
|
|
|
46
48
|
return AIPPanel(
|
|
47
|
-
f"[
|
|
49
|
+
f"[{SUCCESS_STYLE}]✅ {resource_type} '{resource_name}' created successfully![/]\n\n"
|
|
48
50
|
f"ID: {resource_id}{fields_display}",
|
|
49
|
-
title=f"
|
|
50
|
-
border_style=
|
|
51
|
+
title=f"{ICON_AGENT} {resource_type} Created",
|
|
52
|
+
border_style=SUCCESS,
|
|
51
53
|
padding=(0, 1),
|
|
52
54
|
)
|
|
53
55
|
|
|
@@ -63,7 +65,7 @@ def display_update_success(resource_type: str, resource_name: str) -> Text:
|
|
|
63
65
|
Rich Text object for display
|
|
64
66
|
"""
|
|
65
67
|
return markup_text(
|
|
66
|
-
f"[
|
|
68
|
+
f"[{SUCCESS_STYLE}]✅ {resource_type} '{resource_name}' updated successfully[/]"
|
|
67
69
|
)
|
|
68
70
|
|
|
69
71
|
|
|
@@ -78,7 +80,7 @@ def display_deletion_success(resource_type: str, resource_name: str) -> Text:
|
|
|
78
80
|
Rich Text object for display
|
|
79
81
|
"""
|
|
80
82
|
return markup_text(
|
|
81
|
-
f"[
|
|
83
|
+
f"[{SUCCESS_STYLE}]✅ {resource_type} '{resource_name}' deleted successfully[/]"
|
|
82
84
|
)
|
|
83
85
|
|
|
84
86
|
|
|
@@ -90,8 +92,15 @@ def display_api_error(error: Exception, operation: str = "operation") -> None:
|
|
|
90
92
|
operation: Description of the operation that failed
|
|
91
93
|
"""
|
|
92
94
|
error_type = type(error).__name__
|
|
93
|
-
|
|
94
|
-
|
|
95
|
+
error_message = markup_text(f"[{ERROR_STYLE}]Error during {operation}: {error}[/]")
|
|
96
|
+
error_message.no_wrap = True
|
|
97
|
+
error_message.overflow = "ignore"
|
|
98
|
+
console.print(error_message)
|
|
99
|
+
|
|
100
|
+
error_type_message = markup_text(f"[dim]Error type: {error_type}[/dim]")
|
|
101
|
+
error_type_message.no_wrap = True
|
|
102
|
+
error_type_message.overflow = "ignore"
|
|
103
|
+
console.print(error_type_message)
|
|
95
104
|
|
|
96
105
|
|
|
97
106
|
def print_api_error(e: Exception) -> None:
|
|
@@ -107,17 +116,17 @@ def print_api_error(e: Exception) -> None:
|
|
|
107
116
|
- Special handling for validation errors with detailed field-level errors
|
|
108
117
|
"""
|
|
109
118
|
if not hasattr(e, "__dict__"):
|
|
110
|
-
console.print(f"[
|
|
119
|
+
console.print(f"[{ERROR_STYLE}]Error: {e}[/]")
|
|
111
120
|
return
|
|
112
121
|
|
|
113
122
|
if not hasattr(e, "status_code"):
|
|
114
|
-
console.print(f"[
|
|
123
|
+
console.print(f"[{ERROR_STYLE}]Error: {e}[/]")
|
|
115
124
|
return
|
|
116
125
|
|
|
117
|
-
console.print(f"[
|
|
126
|
+
console.print(f"[{ERROR_STYLE}]API Error: {e}[/]")
|
|
118
127
|
status_code = getattr(e, "status_code", None)
|
|
119
128
|
if status_code is not None:
|
|
120
|
-
console.print(f"[
|
|
129
|
+
console.print(f"[{WARNING_STYLE}]Status: {status_code}[/]")
|
|
121
130
|
|
|
122
131
|
payload = getattr(e, "payload", _MISSING)
|
|
123
132
|
if payload is _MISSING:
|
|
@@ -125,9 +134,9 @@ def print_api_error(e: Exception) -> None:
|
|
|
125
134
|
|
|
126
135
|
if payload:
|
|
127
136
|
if not _print_structured_payload(payload):
|
|
128
|
-
console.print(f"[
|
|
137
|
+
console.print(f"[{WARNING_STYLE}]Details: {payload}[/]")
|
|
129
138
|
else:
|
|
130
|
-
console.print(f"[
|
|
139
|
+
console.print(f"[{WARNING_STYLE}]Details: {payload}[/]")
|
|
131
140
|
|
|
132
141
|
|
|
133
142
|
def _print_structured_payload(payload: Any) -> bool:
|
|
@@ -149,18 +158,18 @@ def _print_validation_details(detail: Any) -> bool:
|
|
|
149
158
|
if not isinstance(detail, list) or not detail:
|
|
150
159
|
return False
|
|
151
160
|
|
|
152
|
-
console.print("[
|
|
161
|
+
console.print(f"[{ERROR_STYLE}]Validation Errors:[/]")
|
|
153
162
|
for error in detail:
|
|
154
163
|
if isinstance(error, dict):
|
|
155
164
|
loc = " -> ".join(str(x) for x in error.get("loc", []))
|
|
156
165
|
msg = error.get("msg", "Unknown error")
|
|
157
166
|
error_type = error.get("type", "unknown")
|
|
158
167
|
location = loc if loc else "field"
|
|
159
|
-
console.print(f" [
|
|
168
|
+
console.print(f" [{WARNING_STYLE}]• {location}:[/] {msg}")
|
|
160
169
|
if error_type != "unknown":
|
|
161
170
|
console.print(f" [dim]({error_type})[/dim]")
|
|
162
171
|
else:
|
|
163
|
-
console.print(f" [
|
|
172
|
+
console.print(f" [{WARNING_STYLE}]•[/] {error}")
|
|
164
173
|
return True
|
|
165
174
|
|
|
166
175
|
|
|
@@ -169,14 +178,14 @@ def _print_details_field(details: Any) -> bool:
|
|
|
169
178
|
if not details:
|
|
170
179
|
return False
|
|
171
180
|
|
|
172
|
-
console.print("[
|
|
181
|
+
console.print(f"[{ERROR_STYLE}]Error Details:[/]")
|
|
173
182
|
if isinstance(details, str):
|
|
174
|
-
console.print(f" [
|
|
183
|
+
console.print(f" [{WARNING_STYLE}]•[/] {details}")
|
|
175
184
|
elif isinstance(details, list):
|
|
176
185
|
for detail in details:
|
|
177
|
-
console.print(f" [
|
|
186
|
+
console.print(f" [{WARNING_STYLE}]•[/] {detail}")
|
|
178
187
|
else:
|
|
179
|
-
console.print(f" [
|
|
188
|
+
console.print(f" [{WARNING_STYLE}]•[/] {details}")
|
|
180
189
|
return True
|
|
181
190
|
|
|
182
191
|
|
|
@@ -310,8 +319,8 @@ def display_agent_run_suggestions(agent: Any) -> Panel:
|
|
|
310
319
|
if run_hint_id and run_hint_name:
|
|
311
320
|
cli_section = (
|
|
312
321
|
"📋 Prefer the CLI instead?\n"
|
|
313
|
-
f"
|
|
314
|
-
f"
|
|
322
|
+
f" {format_command_hint(run_hint_id) or run_hint_id}\n"
|
|
323
|
+
f" {format_command_hint(run_hint_name) or run_hint_name}\n\n"
|
|
315
324
|
)
|
|
316
325
|
|
|
317
326
|
return AIPPanel(
|
|
@@ -319,7 +328,7 @@ def display_agent_run_suggestions(agent: Any) -> Panel:
|
|
|
319
328
|
f"🚀 Start chatting with [bold]{agent_name}[/bold] right here:\n"
|
|
320
329
|
f" Type your message below and press Enter to run it immediately.\n\n"
|
|
321
330
|
f"{cli_section}"
|
|
322
|
-
f"
|
|
331
|
+
f"{ICON_TOOL} Available options:\n"
|
|
323
332
|
f" [dim]--chat-history[/dim] Include previous conversation\n"
|
|
324
333
|
f" [dim]--file[/dim] Attach files\n"
|
|
325
334
|
f" [dim]--input[/dim] Alternative input method\n"
|
|
@@ -327,7 +336,7 @@ def display_agent_run_suggestions(agent: Any) -> Panel:
|
|
|
327
336
|
f" [dim]--save[/dim] Save transcript to file\n"
|
|
328
337
|
f" [dim]--verbose[/dim] Show detailed execution\n\n"
|
|
329
338
|
f"💡 [dim]Input text can be positional OR use --input flag (both work!)[/dim]",
|
|
330
|
-
title="
|
|
339
|
+
title=f"{ICON_AGENT} Ready to Run Agent",
|
|
331
340
|
border_style="blue",
|
|
332
341
|
padding=(0, 1),
|
|
333
342
|
)
|
glaip_sdk/cli/io.py
CHANGED
|
@@ -8,16 +8,27 @@ Authors:
|
|
|
8
8
|
"""
|
|
9
9
|
|
|
10
10
|
from pathlib import Path
|
|
11
|
-
from typing import Any
|
|
11
|
+
from typing import TYPE_CHECKING, Any
|
|
12
12
|
|
|
13
13
|
import click
|
|
14
14
|
|
|
15
|
+
from glaip_sdk.branding import WARNING_STYLE
|
|
15
16
|
from glaip_sdk.utils.serialization import (
|
|
16
17
|
collect_attributes_for_export,
|
|
17
18
|
load_resource_from_file,
|
|
18
19
|
write_resource_export,
|
|
19
20
|
)
|
|
20
21
|
|
|
22
|
+
if TYPE_CHECKING: # pragma: no cover - typing-only imports
|
|
23
|
+
from rich.console import Console
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def _create_console() -> "Console":
|
|
27
|
+
"""Return a Console instance (lazy import for easier testing)."""
|
|
28
|
+
from rich.console import Console # Local import for test patching
|
|
29
|
+
|
|
30
|
+
return Console()
|
|
31
|
+
|
|
21
32
|
|
|
22
33
|
def load_resource_from_file_with_validation(
|
|
23
34
|
file_path: Path, resource_type: str
|
|
@@ -79,9 +90,7 @@ def fetch_raw_resource_details(client: Any, resource: Any, resource_type: str) -
|
|
|
79
90
|
Notes:
|
|
80
91
|
This is CLI-specific functionality for displaying comprehensive resource details.
|
|
81
92
|
"""
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
console = Console()
|
|
93
|
+
console = _create_console()
|
|
85
94
|
|
|
86
95
|
try:
|
|
87
96
|
resource_id = str(getattr(resource, "id", "")).strip()
|
|
@@ -99,7 +108,7 @@ def fetch_raw_resource_details(client: Any, resource: Any, resource_type: str) -
|
|
|
99
108
|
return raw_response
|
|
100
109
|
except Exception as e:
|
|
101
110
|
console.print(
|
|
102
|
-
f"[
|
|
111
|
+
f"[{WARNING_STYLE}]Failed to fetch raw {resource_type} details: {e}[/]"
|
|
103
112
|
)
|
|
104
113
|
# Fall back to regular method
|
|
105
114
|
return None
|