glaip-sdk 0.6.3__py3-none-any.whl → 0.6.5__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/agents/base.py +54 -8
- glaip_sdk/cli/auth.py +1 -1
- glaip_sdk/cli/core/__init__.py +79 -0
- glaip_sdk/cli/core/context.py +124 -0
- glaip_sdk/cli/core/output.py +846 -0
- glaip_sdk/cli/core/prompting.py +649 -0
- glaip_sdk/cli/core/rendering.py +187 -0
- glaip_sdk/cli/utils.py +241 -1732
- glaip_sdk/client/tools.py +5 -3
- glaip_sdk/registry/mcp.py +8 -6
- {glaip_sdk-0.6.3.dist-info → glaip_sdk-0.6.5.dist-info}/METADATA +1 -1
- {glaip_sdk-0.6.3.dist-info → glaip_sdk-0.6.5.dist-info}/RECORD +14 -9
- {glaip_sdk-0.6.3.dist-info → glaip_sdk-0.6.5.dist-info}/WHEEL +0 -0
- {glaip_sdk-0.6.3.dist-info → glaip_sdk-0.6.5.dist-info}/entry_points.txt +0 -0
|
@@ -0,0 +1,187 @@
|
|
|
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
|