glaip-sdk 0.6.12__py3-none-any.whl → 0.6.14__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/__init__.py +42 -5
- {glaip_sdk-0.6.12.dist-info → glaip_sdk-0.6.14.dist-info}/METADATA +31 -37
- glaip_sdk-0.6.14.dist-info/RECORD +12 -0
- {glaip_sdk-0.6.12.dist-info → glaip_sdk-0.6.14.dist-info}/WHEEL +2 -1
- glaip_sdk-0.6.14.dist-info/entry_points.txt +2 -0
- glaip_sdk-0.6.14.dist-info/top_level.txt +1 -0
- glaip_sdk/agents/__init__.py +0 -27
- glaip_sdk/agents/base.py +0 -1191
- glaip_sdk/cli/__init__.py +0 -9
- glaip_sdk/cli/account_store.py +0 -540
- glaip_sdk/cli/agent_config.py +0 -78
- glaip_sdk/cli/auth.py +0 -699
- glaip_sdk/cli/commands/__init__.py +0 -5
- glaip_sdk/cli/commands/accounts.py +0 -746
- glaip_sdk/cli/commands/agents.py +0 -1509
- glaip_sdk/cli/commands/common_config.py +0 -101
- glaip_sdk/cli/commands/configure.py +0 -896
- glaip_sdk/cli/commands/mcps.py +0 -1356
- glaip_sdk/cli/commands/models.py +0 -69
- glaip_sdk/cli/commands/tools.py +0 -576
- glaip_sdk/cli/commands/transcripts.py +0 -755
- glaip_sdk/cli/commands/update.py +0 -61
- glaip_sdk/cli/config.py +0 -95
- glaip_sdk/cli/constants.py +0 -38
- glaip_sdk/cli/context.py +0 -150
- glaip_sdk/cli/core/__init__.py +0 -79
- glaip_sdk/cli/core/context.py +0 -124
- glaip_sdk/cli/core/output.py +0 -846
- glaip_sdk/cli/core/prompting.py +0 -649
- glaip_sdk/cli/core/rendering.py +0 -187
- glaip_sdk/cli/display.py +0 -355
- glaip_sdk/cli/hints.py +0 -57
- glaip_sdk/cli/io.py +0 -112
- glaip_sdk/cli/main.py +0 -604
- glaip_sdk/cli/masking.py +0 -136
- glaip_sdk/cli/mcp_validators.py +0 -287
- glaip_sdk/cli/pager.py +0 -266
- glaip_sdk/cli/parsers/__init__.py +0 -7
- glaip_sdk/cli/parsers/json_input.py +0 -177
- glaip_sdk/cli/resolution.py +0 -67
- glaip_sdk/cli/rich_helpers.py +0 -27
- glaip_sdk/cli/slash/__init__.py +0 -15
- glaip_sdk/cli/slash/accounts_controller.py +0 -578
- glaip_sdk/cli/slash/accounts_shared.py +0 -75
- glaip_sdk/cli/slash/agent_session.py +0 -285
- glaip_sdk/cli/slash/prompt.py +0 -256
- glaip_sdk/cli/slash/remote_runs_controller.py +0 -566
- glaip_sdk/cli/slash/session.py +0 -1708
- glaip_sdk/cli/slash/tui/__init__.py +0 -9
- glaip_sdk/cli/slash/tui/accounts_app.py +0 -876
- glaip_sdk/cli/slash/tui/background_tasks.py +0 -72
- glaip_sdk/cli/slash/tui/loading.py +0 -58
- glaip_sdk/cli/slash/tui/remote_runs_app.py +0 -628
- glaip_sdk/cli/transcript/__init__.py +0 -31
- glaip_sdk/cli/transcript/cache.py +0 -536
- glaip_sdk/cli/transcript/capture.py +0 -329
- glaip_sdk/cli/transcript/export.py +0 -38
- glaip_sdk/cli/transcript/history.py +0 -815
- glaip_sdk/cli/transcript/launcher.py +0 -77
- glaip_sdk/cli/transcript/viewer.py +0 -374
- glaip_sdk/cli/update_notifier.py +0 -290
- glaip_sdk/cli/utils.py +0 -263
- glaip_sdk/cli/validators.py +0 -238
- glaip_sdk/client/__init__.py +0 -11
- glaip_sdk/client/_agent_payloads.py +0 -520
- glaip_sdk/client/agent_runs.py +0 -147
- glaip_sdk/client/agents.py +0 -1335
- glaip_sdk/client/base.py +0 -502
- glaip_sdk/client/main.py +0 -249
- glaip_sdk/client/mcps.py +0 -370
- glaip_sdk/client/run_rendering.py +0 -700
- glaip_sdk/client/shared.py +0 -21
- glaip_sdk/client/tools.py +0 -661
- glaip_sdk/client/validators.py +0 -198
- glaip_sdk/config/constants.py +0 -52
- glaip_sdk/mcps/__init__.py +0 -21
- glaip_sdk/mcps/base.py +0 -345
- glaip_sdk/models/__init__.py +0 -90
- glaip_sdk/models/agent.py +0 -47
- glaip_sdk/models/agent_runs.py +0 -116
- glaip_sdk/models/common.py +0 -42
- glaip_sdk/models/mcp.py +0 -33
- glaip_sdk/models/tool.py +0 -33
- glaip_sdk/payload_schemas/__init__.py +0 -7
- glaip_sdk/payload_schemas/agent.py +0 -85
- glaip_sdk/registry/__init__.py +0 -55
- glaip_sdk/registry/agent.py +0 -164
- glaip_sdk/registry/base.py +0 -139
- glaip_sdk/registry/mcp.py +0 -253
- glaip_sdk/registry/tool.py +0 -232
- glaip_sdk/runner/__init__.py +0 -59
- glaip_sdk/runner/base.py +0 -84
- glaip_sdk/runner/deps.py +0 -115
- glaip_sdk/runner/langgraph.py +0 -782
- glaip_sdk/runner/mcp_adapter/__init__.py +0 -13
- glaip_sdk/runner/mcp_adapter/base_mcp_adapter.py +0 -43
- glaip_sdk/runner/mcp_adapter/langchain_mcp_adapter.py +0 -257
- glaip_sdk/runner/mcp_adapter/mcp_config_builder.py +0 -95
- glaip_sdk/runner/tool_adapter/__init__.py +0 -18
- glaip_sdk/runner/tool_adapter/base_tool_adapter.py +0 -44
- glaip_sdk/runner/tool_adapter/langchain_tool_adapter.py +0 -219
- glaip_sdk/tools/__init__.py +0 -22
- glaip_sdk/tools/base.py +0 -435
- glaip_sdk/utils/__init__.py +0 -86
- glaip_sdk/utils/a2a/__init__.py +0 -34
- glaip_sdk/utils/a2a/event_processor.py +0 -188
- glaip_sdk/utils/agent_config.py +0 -194
- glaip_sdk/utils/bundler.py +0 -267
- glaip_sdk/utils/client.py +0 -111
- glaip_sdk/utils/client_utils.py +0 -486
- glaip_sdk/utils/datetime_helpers.py +0 -58
- glaip_sdk/utils/discovery.py +0 -78
- glaip_sdk/utils/display.py +0 -135
- glaip_sdk/utils/export.py +0 -143
- glaip_sdk/utils/general.py +0 -61
- glaip_sdk/utils/import_export.py +0 -168
- glaip_sdk/utils/import_resolver.py +0 -492
- glaip_sdk/utils/instructions.py +0 -101
- glaip_sdk/utils/rendering/__init__.py +0 -115
- glaip_sdk/utils/rendering/formatting.py +0 -264
- glaip_sdk/utils/rendering/layout/__init__.py +0 -64
- glaip_sdk/utils/rendering/layout/panels.py +0 -156
- glaip_sdk/utils/rendering/layout/progress.py +0 -202
- glaip_sdk/utils/rendering/layout/summary.py +0 -74
- glaip_sdk/utils/rendering/layout/transcript.py +0 -606
- glaip_sdk/utils/rendering/models.py +0 -85
- glaip_sdk/utils/rendering/renderer/__init__.py +0 -55
- glaip_sdk/utils/rendering/renderer/base.py +0 -1024
- glaip_sdk/utils/rendering/renderer/config.py +0 -27
- glaip_sdk/utils/rendering/renderer/console.py +0 -55
- glaip_sdk/utils/rendering/renderer/debug.py +0 -178
- glaip_sdk/utils/rendering/renderer/factory.py +0 -138
- glaip_sdk/utils/rendering/renderer/stream.py +0 -202
- glaip_sdk/utils/rendering/renderer/summary_window.py +0 -79
- glaip_sdk/utils/rendering/renderer/thinking.py +0 -273
- glaip_sdk/utils/rendering/renderer/toggle.py +0 -182
- glaip_sdk/utils/rendering/renderer/tool_panels.py +0 -442
- glaip_sdk/utils/rendering/renderer/transcript_mode.py +0 -162
- glaip_sdk/utils/rendering/state.py +0 -204
- glaip_sdk/utils/rendering/step_tree_state.py +0 -100
- glaip_sdk/utils/rendering/steps/__init__.py +0 -34
- glaip_sdk/utils/rendering/steps/event_processor.py +0 -778
- glaip_sdk/utils/rendering/steps/format.py +0 -176
- glaip_sdk/utils/rendering/steps/manager.py +0 -387
- glaip_sdk/utils/rendering/timing.py +0 -36
- glaip_sdk/utils/rendering/viewer/__init__.py +0 -21
- glaip_sdk/utils/rendering/viewer/presenter.py +0 -184
- glaip_sdk/utils/resource_refs.py +0 -195
- glaip_sdk/utils/run_renderer.py +0 -41
- glaip_sdk/utils/runtime_config.py +0 -425
- glaip_sdk/utils/serialization.py +0 -424
- glaip_sdk/utils/sync.py +0 -142
- glaip_sdk/utils/tool_detection.py +0 -33
- glaip_sdk/utils/validation.py +0 -264
- glaip_sdk-0.6.12.dist-info/RECORD +0 -159
- glaip_sdk-0.6.12.dist-info/entry_points.txt +0 -3
glaip_sdk/cli/core/rendering.py
DELETED
|
@@ -1,187 +0,0 @@
|
|
|
1
|
-
"""CLI rendering utilities: Rich console helpers, viewer launchers, renderer builders.
|
|
2
|
-
|
|
3
|
-
Authors:
|
|
4
|
-
Raymond Christopher (raymond.christopher@gdplabs.id)
|
|
5
|
-
Putu Ravindra Wiguna (putu.r.wiguna@gdplabs.id)
|
|
6
|
-
"""
|
|
7
|
-
|
|
8
|
-
from __future__ import annotations
|
|
9
|
-
|
|
10
|
-
import os
|
|
11
|
-
import sys
|
|
12
|
-
from contextlib import AbstractContextManager, contextmanager, nullcontext
|
|
13
|
-
from typing import Any
|
|
14
|
-
|
|
15
|
-
from rich.console import Console
|
|
16
|
-
|
|
17
|
-
from glaip_sdk.branding import ACCENT_STYLE
|
|
18
|
-
from glaip_sdk.cli.context import _get_view, get_ctx_value
|
|
19
|
-
from glaip_sdk.utils.rendering.renderer import (
|
|
20
|
-
CapturingConsole,
|
|
21
|
-
RendererFactoryOptions,
|
|
22
|
-
RichStreamRenderer,
|
|
23
|
-
make_default_renderer,
|
|
24
|
-
make_verbose_renderer,
|
|
25
|
-
)
|
|
26
|
-
|
|
27
|
-
# Export console for backward compatibility
|
|
28
|
-
console = Console()
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
def _can_use_spinner(ctx: Any | None, active_console: Console) -> bool:
|
|
32
|
-
"""Check if spinner output is allowed in the current environment."""
|
|
33
|
-
if ctx is not None:
|
|
34
|
-
tty_enabled = bool(get_ctx_value(ctx, "tty", True))
|
|
35
|
-
view = (_get_view(ctx) or "rich").lower()
|
|
36
|
-
if not tty_enabled or view not in {"", "rich"}:
|
|
37
|
-
return False
|
|
38
|
-
|
|
39
|
-
if not active_console.is_terminal:
|
|
40
|
-
return False
|
|
41
|
-
|
|
42
|
-
return _stream_supports_tty(getattr(active_console, "file", None))
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
def _stream_supports_tty(stream: Any) -> bool:
|
|
46
|
-
"""Return True if the provided stream can safely render a spinner."""
|
|
47
|
-
target = stream if hasattr(stream, "isatty") else sys.stdout
|
|
48
|
-
try:
|
|
49
|
-
return bool(target.isatty())
|
|
50
|
-
except Exception:
|
|
51
|
-
return False
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
def update_spinner(status_indicator: Any | None, message: str) -> None:
|
|
55
|
-
"""Update spinner text when a status indicator is active."""
|
|
56
|
-
if status_indicator is None:
|
|
57
|
-
return
|
|
58
|
-
|
|
59
|
-
try:
|
|
60
|
-
status_indicator.update(message)
|
|
61
|
-
except Exception: # pragma: no cover - defensive update
|
|
62
|
-
pass
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
def stop_spinner(status_indicator: Any | None) -> None:
|
|
66
|
-
"""Stop an active spinner safely."""
|
|
67
|
-
if status_indicator is None:
|
|
68
|
-
return
|
|
69
|
-
|
|
70
|
-
try:
|
|
71
|
-
status_indicator.stop()
|
|
72
|
-
except Exception: # pragma: no cover - defensive stop
|
|
73
|
-
pass
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
# Backwards compatibility aliases for legacy callers
|
|
77
|
-
_spinner_update = update_spinner
|
|
78
|
-
_spinner_stop = stop_spinner
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
def spinner_context(
|
|
82
|
-
ctx: Any | None,
|
|
83
|
-
message: str,
|
|
84
|
-
*,
|
|
85
|
-
console_override: Console | None = None,
|
|
86
|
-
spinner: str = "dots",
|
|
87
|
-
spinner_style: str = ACCENT_STYLE,
|
|
88
|
-
) -> AbstractContextManager[Any]:
|
|
89
|
-
"""Return a context manager that renders a spinner when appropriate."""
|
|
90
|
-
active_console = console_override or console
|
|
91
|
-
if not _can_use_spinner(ctx, active_console):
|
|
92
|
-
return nullcontext()
|
|
93
|
-
|
|
94
|
-
status = active_console.status(
|
|
95
|
-
message,
|
|
96
|
-
spinner=spinner,
|
|
97
|
-
spinner_style=spinner_style,
|
|
98
|
-
)
|
|
99
|
-
|
|
100
|
-
if not hasattr(status, "__enter__") or not hasattr(status, "__exit__"):
|
|
101
|
-
return nullcontext()
|
|
102
|
-
|
|
103
|
-
return status
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
def _register_renderer_with_session(ctx: Any, renderer: RichStreamRenderer) -> None:
|
|
107
|
-
"""Attach renderer to an active slash session when present."""
|
|
108
|
-
try:
|
|
109
|
-
ctx_obj = getattr(ctx, "obj", None)
|
|
110
|
-
session = ctx_obj.get("_slash_session") if isinstance(ctx_obj, dict) else None
|
|
111
|
-
if session and hasattr(session, "register_active_renderer"):
|
|
112
|
-
session.register_active_renderer(renderer)
|
|
113
|
-
except Exception:
|
|
114
|
-
# Never let session bookkeeping break renderer creation
|
|
115
|
-
pass
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
def build_renderer(
|
|
119
|
-
_ctx: Any,
|
|
120
|
-
*,
|
|
121
|
-
save_path: str | os.PathLike[str] | None,
|
|
122
|
-
verbose: bool = False,
|
|
123
|
-
_tty_enabled: bool = True,
|
|
124
|
-
live: bool | None = None,
|
|
125
|
-
snapshots: bool | None = None,
|
|
126
|
-
) -> tuple[RichStreamRenderer, Console | CapturingConsole]:
|
|
127
|
-
"""Build renderer and capturing console for CLI commands.
|
|
128
|
-
|
|
129
|
-
Args:
|
|
130
|
-
_ctx: Click context object for CLI operations.
|
|
131
|
-
save_path: Path to save output to (enables capturing console).
|
|
132
|
-
verbose: Whether to enable verbose mode.
|
|
133
|
-
_tty_enabled: Whether TTY is available for interactive features.
|
|
134
|
-
live: Whether to enable live rendering mode (overrides verbose default).
|
|
135
|
-
snapshots: Whether to capture and store snapshots.
|
|
136
|
-
|
|
137
|
-
Returns:
|
|
138
|
-
Tuple of (renderer, capturing_console) for streaming output.
|
|
139
|
-
"""
|
|
140
|
-
# Use capturing console if saving output
|
|
141
|
-
working_console = CapturingConsole(console, capture=True) if save_path else console
|
|
142
|
-
|
|
143
|
-
# Configure renderer based on verbose mode and explicit overrides
|
|
144
|
-
live_enabled = bool(live) if live is not None else not verbose
|
|
145
|
-
cfg_overrides = {
|
|
146
|
-
"live": live_enabled,
|
|
147
|
-
"append_finished_snapshots": bool(snapshots) if snapshots is not None else False,
|
|
148
|
-
}
|
|
149
|
-
renderer_console = (
|
|
150
|
-
working_console.original_console if isinstance(working_console, CapturingConsole) else working_console
|
|
151
|
-
)
|
|
152
|
-
factory = make_verbose_renderer if verbose else make_default_renderer
|
|
153
|
-
factory_options = RendererFactoryOptions(
|
|
154
|
-
console=renderer_console,
|
|
155
|
-
cfg_overrides=cfg_overrides,
|
|
156
|
-
verbose=verbose if factory is make_default_renderer else None,
|
|
157
|
-
)
|
|
158
|
-
renderer = factory_options.build(factory)
|
|
159
|
-
|
|
160
|
-
# Link the renderer back to the slash session when running from the palette.
|
|
161
|
-
_register_renderer_with_session(_ctx, renderer)
|
|
162
|
-
|
|
163
|
-
return renderer, working_console
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
@contextmanager
|
|
167
|
-
def with_client_and_spinner(
|
|
168
|
-
ctx: Any,
|
|
169
|
-
spinner_message: str,
|
|
170
|
-
*,
|
|
171
|
-
console_override: Console | None = None,
|
|
172
|
-
) -> Any:
|
|
173
|
-
"""Context manager for commands that need client and spinner.
|
|
174
|
-
|
|
175
|
-
Args:
|
|
176
|
-
ctx: Click context.
|
|
177
|
-
spinner_message: Message to display in spinner.
|
|
178
|
-
console_override: Optional console override.
|
|
179
|
-
|
|
180
|
-
Yields:
|
|
181
|
-
Client instance.
|
|
182
|
-
"""
|
|
183
|
-
from glaip_sdk.cli.core.context import get_client # noqa: PLC0415
|
|
184
|
-
|
|
185
|
-
client = get_client(ctx)
|
|
186
|
-
with spinner_context(ctx, spinner_message, console_override=console_override):
|
|
187
|
-
yield client
|
glaip_sdk/cli/display.py
DELETED
|
@@ -1,355 +0,0 @@
|
|
|
1
|
-
"""CLI display utilities for success/failure panels and Rich renderers.
|
|
2
|
-
|
|
3
|
-
This module handles all display-related functionality for CLI commands,
|
|
4
|
-
including success messages, error handling, and output formatting.
|
|
5
|
-
|
|
6
|
-
Authors:
|
|
7
|
-
Raymond Christopher (raymond.christopher@gdplabs.id)
|
|
8
|
-
"""
|
|
9
|
-
|
|
10
|
-
import json
|
|
11
|
-
from typing import Any
|
|
12
|
-
|
|
13
|
-
import click
|
|
14
|
-
from rich.console import Console
|
|
15
|
-
from rich.panel import Panel
|
|
16
|
-
from rich.text import Text
|
|
17
|
-
|
|
18
|
-
from glaip_sdk.branding import ERROR_STYLE, SUCCESS, SUCCESS_STYLE, WARNING_STYLE
|
|
19
|
-
from glaip_sdk.cli.hints import command_hint, format_command_hint, in_slash_mode
|
|
20
|
-
from glaip_sdk.cli.rich_helpers import markup_text
|
|
21
|
-
from glaip_sdk.icons import ICON_AGENT, ICON_TOOL
|
|
22
|
-
from glaip_sdk.rich_components import AIPPanel
|
|
23
|
-
|
|
24
|
-
console = Console()
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
def display_creation_success(
|
|
28
|
-
resource_type: str, resource_name: str, resource_id: str, **additional_fields: Any
|
|
29
|
-
) -> Panel:
|
|
30
|
-
"""Create standardized success message for resource creation.
|
|
31
|
-
|
|
32
|
-
Args:
|
|
33
|
-
resource_type: Type of resource (e.g., "Agent", "Tool", "MCP")
|
|
34
|
-
resource_name: Name of the created resource
|
|
35
|
-
resource_id: ID of the created resource
|
|
36
|
-
**additional_fields: Additional fields to display
|
|
37
|
-
|
|
38
|
-
Returns:
|
|
39
|
-
Rich Panel object for display
|
|
40
|
-
"""
|
|
41
|
-
# Build additional fields display
|
|
42
|
-
fields_display = ""
|
|
43
|
-
if additional_fields:
|
|
44
|
-
fields_display = "\n" + "\n".join(f"{key}: {value}" for key, value in additional_fields.items())
|
|
45
|
-
|
|
46
|
-
return AIPPanel(
|
|
47
|
-
f"[{SUCCESS_STYLE}]✅ {resource_type} '{resource_name}' created successfully![/]\n\n"
|
|
48
|
-
f"ID: {resource_id}{fields_display}",
|
|
49
|
-
title=f"{ICON_AGENT} {resource_type} Created",
|
|
50
|
-
border_style=SUCCESS,
|
|
51
|
-
padding=(0, 1),
|
|
52
|
-
)
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
def display_update_success(resource_type: str, resource_name: str) -> Text:
|
|
56
|
-
"""Create standardized success message for resource update.
|
|
57
|
-
|
|
58
|
-
Args:
|
|
59
|
-
resource_type: Type of resource (e.g., "Agent", "Tool", "MCP")
|
|
60
|
-
resource_name: Name of the updated resource
|
|
61
|
-
|
|
62
|
-
Returns:
|
|
63
|
-
Rich Text object for display
|
|
64
|
-
"""
|
|
65
|
-
return markup_text(f"[{SUCCESS_STYLE}]✅ {resource_type} '{resource_name}' updated successfully[/]")
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
def display_deletion_success(resource_type: str, resource_name: str) -> Text:
|
|
69
|
-
"""Create standardized success message for resource deletion.
|
|
70
|
-
|
|
71
|
-
Args:
|
|
72
|
-
resource_type: Type of resource (e.g., "Agent", "Tool", "MCP")
|
|
73
|
-
resource_name: Name of the deleted resource
|
|
74
|
-
|
|
75
|
-
Returns:
|
|
76
|
-
Rich Text object for display
|
|
77
|
-
"""
|
|
78
|
-
return markup_text(f"[{SUCCESS_STYLE}]✅ {resource_type} '{resource_name}' deleted successfully[/]")
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
def display_api_error(error: Exception, operation: str = "operation") -> None:
|
|
82
|
-
"""Display standardized API error message.
|
|
83
|
-
|
|
84
|
-
Args:
|
|
85
|
-
error: The exception that occurred
|
|
86
|
-
operation: Description of the operation that failed
|
|
87
|
-
"""
|
|
88
|
-
error_type = type(error).__name__
|
|
89
|
-
error_message = markup_text(f"[{ERROR_STYLE}]Error during {operation}: {error}[/]")
|
|
90
|
-
error_message.no_wrap = True
|
|
91
|
-
error_message.overflow = "ignore"
|
|
92
|
-
console.print(error_message)
|
|
93
|
-
|
|
94
|
-
error_type_message = markup_text(f"[dim]Error type: {error_type}[/dim]")
|
|
95
|
-
error_type_message.no_wrap = True
|
|
96
|
-
error_type_message.overflow = "ignore"
|
|
97
|
-
console.print(error_type_message)
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
def print_api_error(e: Exception) -> None:
|
|
101
|
-
"""Print API error with consistent formatting for both JSON and Rich views.
|
|
102
|
-
|
|
103
|
-
Args:
|
|
104
|
-
e: The exception to format and display
|
|
105
|
-
|
|
106
|
-
Notes:
|
|
107
|
-
- Extracts status_code, error_type, and payload from APIError exceptions
|
|
108
|
-
- Provides consistent error reporting across CLI commands
|
|
109
|
-
- Handles both JSON and Rich output formats
|
|
110
|
-
- Special handling for validation errors with detailed field-level errors
|
|
111
|
-
"""
|
|
112
|
-
if not hasattr(e, "__dict__"):
|
|
113
|
-
console.print(f"[{ERROR_STYLE}]Error: {e}[/]")
|
|
114
|
-
return
|
|
115
|
-
|
|
116
|
-
if not hasattr(e, "status_code"):
|
|
117
|
-
console.print(f"[{ERROR_STYLE}]Error: {e}[/]")
|
|
118
|
-
return
|
|
119
|
-
|
|
120
|
-
error_text = str(e).strip()
|
|
121
|
-
if not error_text:
|
|
122
|
-
error_text = "Unknown error"
|
|
123
|
-
if "\n" in error_text:
|
|
124
|
-
error_text = error_text.splitlines()[0]
|
|
125
|
-
console.print(f"[{ERROR_STYLE}]API Error: {error_text}[/]")
|
|
126
|
-
status_code = getattr(e, "status_code", None)
|
|
127
|
-
if status_code is not None:
|
|
128
|
-
console.print(f"[{WARNING_STYLE}]Status: {status_code}[/]")
|
|
129
|
-
|
|
130
|
-
payload = getattr(e, "payload", _MISSING)
|
|
131
|
-
if payload is _MISSING:
|
|
132
|
-
return
|
|
133
|
-
|
|
134
|
-
if payload:
|
|
135
|
-
if not _print_structured_payload(payload):
|
|
136
|
-
console.print(f"[{WARNING_STYLE}]Details: {payload}[/]")
|
|
137
|
-
else:
|
|
138
|
-
console.print(f"[{WARNING_STYLE}]Details: {payload}[/]")
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
def _print_structured_payload(payload: Any) -> bool:
|
|
142
|
-
"""Print structured payloads with enhanced formatting. Returns True if handled."""
|
|
143
|
-
if not isinstance(payload, dict):
|
|
144
|
-
return False
|
|
145
|
-
|
|
146
|
-
if "detail" in payload and _print_validation_details(payload["detail"]):
|
|
147
|
-
return True
|
|
148
|
-
|
|
149
|
-
if "details" in payload and _print_details_field(payload["details"]):
|
|
150
|
-
return True
|
|
151
|
-
|
|
152
|
-
return False
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
def _print_validation_details(detail: Any) -> bool:
|
|
156
|
-
"""Render FastAPI-style validation errors."""
|
|
157
|
-
if not isinstance(detail, list) or not detail:
|
|
158
|
-
return False
|
|
159
|
-
|
|
160
|
-
console.print(f"[{ERROR_STYLE}]Validation Errors:[/]")
|
|
161
|
-
for error in detail:
|
|
162
|
-
if isinstance(error, dict):
|
|
163
|
-
loc = " -> ".join(str(x) for x in error.get("loc", []))
|
|
164
|
-
msg = error.get("msg", "Unknown error")
|
|
165
|
-
error_type = error.get("type", "unknown")
|
|
166
|
-
location = loc if loc else "field"
|
|
167
|
-
console.print(f" [{WARNING_STYLE}]• {location}:[/] {msg}")
|
|
168
|
-
if error_type != "unknown":
|
|
169
|
-
console.print(f" [dim]({error_type})[/dim]")
|
|
170
|
-
else:
|
|
171
|
-
console.print(f" [{WARNING_STYLE}]•[/] {error}")
|
|
172
|
-
return True
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
def _print_details_field(details: Any) -> bool:
|
|
176
|
-
"""Render custom error details from API payloads."""
|
|
177
|
-
if not details:
|
|
178
|
-
return False
|
|
179
|
-
|
|
180
|
-
console.print(f"[{ERROR_STYLE}]Error Details:[/]")
|
|
181
|
-
if isinstance(details, str):
|
|
182
|
-
console.print(f" [{WARNING_STYLE}]•[/] {details}")
|
|
183
|
-
elif isinstance(details, list):
|
|
184
|
-
for detail in details:
|
|
185
|
-
console.print(f" [{WARNING_STYLE}]•[/] {detail}")
|
|
186
|
-
else:
|
|
187
|
-
console.print(f" [{WARNING_STYLE}]•[/] {details}")
|
|
188
|
-
return True
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
_MISSING = object()
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
def build_resource_result_data(resource: Any, fields: list[str]) -> dict[str, Any]:
|
|
195
|
-
"""Return a normalized mapping of ``fields`` extracted from ``resource``."""
|
|
196
|
-
result: dict[str, Any] = {}
|
|
197
|
-
for field in fields:
|
|
198
|
-
try:
|
|
199
|
-
value = getattr(resource, field)
|
|
200
|
-
except AttributeError:
|
|
201
|
-
value = _MISSING
|
|
202
|
-
except Exception:
|
|
203
|
-
value = _MISSING
|
|
204
|
-
|
|
205
|
-
result[field] = _normalise_field_value(field, value)
|
|
206
|
-
|
|
207
|
-
return result
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
def _normalise_field_value(field: str, value: Any) -> Any:
|
|
211
|
-
"""Convert special sentinel values into display-friendly text."""
|
|
212
|
-
if value is _MISSING:
|
|
213
|
-
return "N/A"
|
|
214
|
-
if hasattr(value, "_mock_name"):
|
|
215
|
-
return "N/A"
|
|
216
|
-
if field == "id":
|
|
217
|
-
return str(value)
|
|
218
|
-
return value
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
def _get_context_object(ctx: Any) -> dict[str, Any]:
|
|
222
|
-
"""Get context object safely."""
|
|
223
|
-
ctx_obj = getattr(ctx, "obj", {}) if ctx is not None else {}
|
|
224
|
-
return ctx_obj if isinstance(ctx_obj, dict) else {}
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
def _should_output_json(ctx_obj: dict[str, Any]) -> bool:
|
|
228
|
-
"""Check if output should be in JSON format."""
|
|
229
|
-
return ctx_obj.get("view") == "json"
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
def _build_error_output_data(error: Exception) -> dict[str, Any]:
|
|
233
|
-
"""Build error output data with additional error details."""
|
|
234
|
-
output_data = {"error": str(error)}
|
|
235
|
-
|
|
236
|
-
# Add additional error details if available
|
|
237
|
-
if hasattr(error, "status_code"):
|
|
238
|
-
output_data["status_code"] = error.status_code
|
|
239
|
-
if hasattr(error, "error_type"):
|
|
240
|
-
output_data["error_type"] = error.error_type
|
|
241
|
-
if hasattr(error, "payload"):
|
|
242
|
-
output_data["details"] = error.payload
|
|
243
|
-
|
|
244
|
-
return output_data
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
def _build_success_output_data(data: Any) -> dict[str, Any]:
|
|
248
|
-
"""Build success output data."""
|
|
249
|
-
return data if data is not None else {"success": True}
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
def handle_json_output(ctx: Any, data: Any = None, error: Exception = None) -> None:
|
|
253
|
-
"""Handle JSON output format for CLI commands.
|
|
254
|
-
|
|
255
|
-
Args:
|
|
256
|
-
ctx: Click context
|
|
257
|
-
data: Data to output (for successful operations)
|
|
258
|
-
error: Error to output (for failed operations)
|
|
259
|
-
"""
|
|
260
|
-
ctx_obj = _get_context_object(ctx)
|
|
261
|
-
|
|
262
|
-
if _should_output_json(ctx_obj):
|
|
263
|
-
if error:
|
|
264
|
-
output_data = _build_error_output_data(error)
|
|
265
|
-
else:
|
|
266
|
-
output_data = _build_success_output_data(data)
|
|
267
|
-
|
|
268
|
-
click.echo(json.dumps(output_data, indent=2, default=str))
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
def handle_rich_output(ctx: Any, rich_content: Any = None) -> None:
|
|
272
|
-
"""Handle Rich output format for CLI commands.
|
|
273
|
-
|
|
274
|
-
Args:
|
|
275
|
-
ctx: Click context
|
|
276
|
-
rich_content: Rich content to display
|
|
277
|
-
"""
|
|
278
|
-
ctx_obj = getattr(ctx, "obj", {}) if ctx is not None else {}
|
|
279
|
-
if not isinstance(ctx_obj, dict):
|
|
280
|
-
ctx_obj = {}
|
|
281
|
-
|
|
282
|
-
if ctx_obj.get("view") != "json" and rich_content:
|
|
283
|
-
console.print(rich_content)
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
def display_confirmation_prompt(resource_type: str, resource_name: str) -> bool:
|
|
287
|
-
"""Display standardized confirmation prompt for destructive operations.
|
|
288
|
-
|
|
289
|
-
Args:
|
|
290
|
-
resource_type: Type of resource (e.g., "Agent", "Tool", "MCP")
|
|
291
|
-
resource_name: Name of the resource
|
|
292
|
-
|
|
293
|
-
Returns:
|
|
294
|
-
True if user confirms, False otherwise
|
|
295
|
-
"""
|
|
296
|
-
if not click.confirm(f"Are you sure you want to delete {resource_type.lower()} '{resource_name}'?"):
|
|
297
|
-
if console.is_terminal:
|
|
298
|
-
console.print(Text("Deletion cancelled."))
|
|
299
|
-
return False
|
|
300
|
-
return True
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
def display_agent_run_suggestions(agent: Any) -> Panel:
|
|
304
|
-
"""Return a panel with post-creation suggestions for an agent."""
|
|
305
|
-
agent_id = getattr(agent, "id", "")
|
|
306
|
-
agent_name = getattr(agent, "name", "")
|
|
307
|
-
slash_mode = in_slash_mode()
|
|
308
|
-
run_hint_id = command_hint(
|
|
309
|
-
f'agents run {agent_id} "Your message here"',
|
|
310
|
-
slash_command=None,
|
|
311
|
-
)
|
|
312
|
-
run_hint_name = command_hint(
|
|
313
|
-
f'agents run "{agent_name}" "Your message here"',
|
|
314
|
-
slash_command=None,
|
|
315
|
-
)
|
|
316
|
-
|
|
317
|
-
content_parts: list[str] = ["[bold blue]💡 Next Steps:[/bold blue]\n\n"]
|
|
318
|
-
|
|
319
|
-
if slash_mode:
|
|
320
|
-
slash_shortcuts = "\n".join(
|
|
321
|
-
f" {format_command_hint(command, description) or command}"
|
|
322
|
-
for command, description in (
|
|
323
|
-
("/details", "Show configuration (toggle preview)"),
|
|
324
|
-
("/help", "Show command palette menu"),
|
|
325
|
-
("/exit", "Return to the palette"),
|
|
326
|
-
)
|
|
327
|
-
)
|
|
328
|
-
content_parts.append(
|
|
329
|
-
f"🚀 Start chatting with [bold]{agent_name}[/bold] right here:\n"
|
|
330
|
-
f" Type your message below and press Enter to run it immediately.\n\n"
|
|
331
|
-
f"{ICON_TOOL} Slash shortcuts:\n"
|
|
332
|
-
f"{slash_shortcuts}"
|
|
333
|
-
)
|
|
334
|
-
else:
|
|
335
|
-
cli_hint_lines = [format_command_hint(hint) or hint for hint in (run_hint_id, run_hint_name) if hint]
|
|
336
|
-
if cli_hint_lines:
|
|
337
|
-
joined_hints = "\n".join(f" {hint}" for hint in cli_hint_lines)
|
|
338
|
-
content_parts.append(f"🚀 Run this agent from the CLI:\n{joined_hints}\n\n")
|
|
339
|
-
content_parts.append(
|
|
340
|
-
f"{ICON_TOOL} Available options:\n"
|
|
341
|
-
f" [dim]--chat-history[/dim] Include previous conversation\n"
|
|
342
|
-
f" [dim]--file[/dim] Attach files\n"
|
|
343
|
-
f" [dim]--input[/dim] Alternative input method\n"
|
|
344
|
-
f" [dim]--timeout[/dim] Set execution timeout\n"
|
|
345
|
-
f" [dim]--save[/dim] Save transcript to file\n"
|
|
346
|
-
f" [dim]--verbose[/dim] Show detailed execution\n\n"
|
|
347
|
-
f"💡 [dim]Input text can be positional OR use --input flag (both work!)[/dim]"
|
|
348
|
-
)
|
|
349
|
-
|
|
350
|
-
return AIPPanel(
|
|
351
|
-
"".join(content_parts),
|
|
352
|
-
title=f"{ICON_AGENT} Ready to Run Agent",
|
|
353
|
-
border_style="blue",
|
|
354
|
-
padding=(0, 1),
|
|
355
|
-
)
|
glaip_sdk/cli/hints.py
DELETED
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
"""Helpers for formatting CLI/slash command hints.
|
|
2
|
-
|
|
3
|
-
Authors:
|
|
4
|
-
Raymond Christopher (raymond.christopher@gdplabs.id)
|
|
5
|
-
"""
|
|
6
|
-
|
|
7
|
-
from __future__ import annotations
|
|
8
|
-
|
|
9
|
-
import click
|
|
10
|
-
|
|
11
|
-
from glaip_sdk.branding import HINT_COMMAND_STYLE, HINT_DESCRIPTION_COLOR
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
def in_slash_mode(ctx: click.Context | None = None) -> bool:
|
|
15
|
-
"""Return True when running inside the slash command palette."""
|
|
16
|
-
if ctx is None:
|
|
17
|
-
try:
|
|
18
|
-
ctx = click.get_current_context(silent=True)
|
|
19
|
-
except RuntimeError:
|
|
20
|
-
ctx = None
|
|
21
|
-
|
|
22
|
-
if ctx is None:
|
|
23
|
-
return False
|
|
24
|
-
|
|
25
|
-
obj = getattr(ctx, "obj", None)
|
|
26
|
-
if isinstance(obj, dict):
|
|
27
|
-
return bool(obj.get("_slash_session"))
|
|
28
|
-
|
|
29
|
-
return bool(getattr(obj, "_slash_session", False))
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
def command_hint(
|
|
33
|
-
cli_command: str | None,
|
|
34
|
-
slash_command: str | None = None,
|
|
35
|
-
*,
|
|
36
|
-
ctx: click.Context | None = None,
|
|
37
|
-
) -> str | None:
|
|
38
|
-
"""Return the appropriate command string for the current mode."""
|
|
39
|
-
if in_slash_mode(ctx):
|
|
40
|
-
if not slash_command:
|
|
41
|
-
return None
|
|
42
|
-
return slash_command if slash_command.startswith("/") else f"/{slash_command}"
|
|
43
|
-
|
|
44
|
-
if not cli_command:
|
|
45
|
-
return None
|
|
46
|
-
return f"aip {cli_command}"
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
def format_command_hint(command: str | None, description: str | None = None) -> str | None:
|
|
50
|
-
"""Return a Rich markup string that highlights a command hint."""
|
|
51
|
-
if not command:
|
|
52
|
-
return None
|
|
53
|
-
|
|
54
|
-
highlighted = f"[{HINT_COMMAND_STYLE}]{command}[/]"
|
|
55
|
-
if description:
|
|
56
|
-
highlighted += f" [{HINT_DESCRIPTION_COLOR}]{description}[/{HINT_DESCRIPTION_COLOR}]"
|
|
57
|
-
return highlighted
|