glaip-sdk 0.1.0__py3-none-any.whl → 0.6.10__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 +5 -2
- glaip_sdk/_version.py +10 -3
- glaip_sdk/agents/__init__.py +27 -0
- glaip_sdk/agents/base.py +1191 -0
- glaip_sdk/branding.py +15 -6
- glaip_sdk/cli/account_store.py +540 -0
- glaip_sdk/cli/agent_config.py +2 -6
- glaip_sdk/cli/auth.py +265 -45
- glaip_sdk/cli/commands/__init__.py +2 -2
- glaip_sdk/cli/commands/accounts.py +746 -0
- glaip_sdk/cli/commands/agents.py +251 -173
- glaip_sdk/cli/commands/common_config.py +101 -0
- glaip_sdk/cli/commands/configure.py +735 -143
- glaip_sdk/cli/commands/mcps.py +266 -134
- glaip_sdk/cli/commands/models.py +13 -9
- glaip_sdk/cli/commands/tools.py +67 -88
- glaip_sdk/cli/commands/transcripts.py +755 -0
- glaip_sdk/cli/commands/update.py +3 -8
- glaip_sdk/cli/config.py +49 -7
- glaip_sdk/cli/constants.py +38 -0
- glaip_sdk/cli/context.py +8 -0
- 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/display.py +45 -32
- glaip_sdk/cli/hints.py +57 -0
- glaip_sdk/cli/io.py +14 -17
- glaip_sdk/cli/main.py +232 -143
- glaip_sdk/cli/masking.py +21 -33
- glaip_sdk/cli/mcp_validators.py +5 -15
- glaip_sdk/cli/pager.py +12 -19
- glaip_sdk/cli/parsers/__init__.py +1 -3
- glaip_sdk/cli/parsers/json_input.py +11 -22
- glaip_sdk/cli/resolution.py +3 -9
- glaip_sdk/cli/rich_helpers.py +1 -3
- glaip_sdk/cli/slash/__init__.py +0 -9
- glaip_sdk/cli/slash/accounts_controller.py +578 -0
- glaip_sdk/cli/slash/accounts_shared.py +75 -0
- glaip_sdk/cli/slash/agent_session.py +65 -29
- glaip_sdk/cli/slash/prompt.py +24 -10
- glaip_sdk/cli/slash/remote_runs_controller.py +566 -0
- glaip_sdk/cli/slash/session.py +807 -225
- glaip_sdk/cli/slash/tui/__init__.py +9 -0
- glaip_sdk/cli/slash/tui/accounts.tcss +86 -0
- glaip_sdk/cli/slash/tui/accounts_app.py +876 -0
- glaip_sdk/cli/slash/tui/background_tasks.py +72 -0
- glaip_sdk/cli/slash/tui/loading.py +58 -0
- glaip_sdk/cli/slash/tui/remote_runs_app.py +628 -0
- glaip_sdk/cli/transcript/__init__.py +12 -52
- glaip_sdk/cli/transcript/cache.py +258 -60
- glaip_sdk/cli/transcript/capture.py +72 -21
- glaip_sdk/cli/transcript/history.py +815 -0
- glaip_sdk/cli/transcript/launcher.py +1 -3
- glaip_sdk/cli/transcript/viewer.py +79 -499
- glaip_sdk/cli/update_notifier.py +177 -24
- glaip_sdk/cli/utils.py +242 -1308
- glaip_sdk/cli/validators.py +16 -18
- glaip_sdk/client/__init__.py +2 -1
- glaip_sdk/client/_agent_payloads.py +53 -37
- glaip_sdk/client/agent_runs.py +147 -0
- glaip_sdk/client/agents.py +320 -92
- glaip_sdk/client/base.py +78 -35
- glaip_sdk/client/main.py +19 -10
- glaip_sdk/client/mcps.py +123 -15
- glaip_sdk/client/run_rendering.py +136 -101
- glaip_sdk/client/shared.py +21 -0
- glaip_sdk/client/tools.py +163 -34
- glaip_sdk/client/validators.py +20 -48
- glaip_sdk/config/constants.py +11 -0
- glaip_sdk/exceptions.py +1 -3
- glaip_sdk/mcps/__init__.py +21 -0
- glaip_sdk/mcps/base.py +345 -0
- glaip_sdk/models/__init__.py +90 -0
- glaip_sdk/models/agent.py +47 -0
- glaip_sdk/models/agent_runs.py +116 -0
- glaip_sdk/models/common.py +42 -0
- glaip_sdk/models/mcp.py +33 -0
- glaip_sdk/models/tool.py +33 -0
- glaip_sdk/payload_schemas/__init__.py +1 -13
- glaip_sdk/payload_schemas/agent.py +1 -3
- glaip_sdk/registry/__init__.py +55 -0
- glaip_sdk/registry/agent.py +164 -0
- glaip_sdk/registry/base.py +139 -0
- glaip_sdk/registry/mcp.py +253 -0
- glaip_sdk/registry/tool.py +232 -0
- glaip_sdk/rich_components.py +58 -2
- glaip_sdk/runner/__init__.py +59 -0
- glaip_sdk/runner/base.py +84 -0
- glaip_sdk/runner/deps.py +115 -0
- glaip_sdk/runner/langgraph.py +706 -0
- glaip_sdk/runner/mcp_adapter/__init__.py +13 -0
- glaip_sdk/runner/mcp_adapter/base_mcp_adapter.py +43 -0
- glaip_sdk/runner/mcp_adapter/langchain_mcp_adapter.py +257 -0
- glaip_sdk/runner/mcp_adapter/mcp_config_builder.py +95 -0
- glaip_sdk/runner/tool_adapter/__init__.py +18 -0
- glaip_sdk/runner/tool_adapter/base_tool_adapter.py +44 -0
- glaip_sdk/runner/tool_adapter/langchain_tool_adapter.py +219 -0
- glaip_sdk/tools/__init__.py +22 -0
- glaip_sdk/tools/base.py +435 -0
- glaip_sdk/utils/__init__.py +58 -12
- glaip_sdk/utils/a2a/__init__.py +34 -0
- glaip_sdk/utils/a2a/event_processor.py +188 -0
- glaip_sdk/utils/agent_config.py +4 -14
- glaip_sdk/utils/bundler.py +267 -0
- glaip_sdk/utils/client.py +111 -0
- glaip_sdk/utils/client_utils.py +46 -28
- glaip_sdk/utils/datetime_helpers.py +58 -0
- glaip_sdk/utils/discovery.py +78 -0
- glaip_sdk/utils/display.py +25 -21
- glaip_sdk/utils/export.py +143 -0
- glaip_sdk/utils/general.py +1 -36
- glaip_sdk/utils/import_export.py +15 -16
- glaip_sdk/utils/import_resolver.py +492 -0
- glaip_sdk/utils/instructions.py +101 -0
- glaip_sdk/utils/rendering/__init__.py +115 -1
- glaip_sdk/utils/rendering/formatting.py +7 -35
- glaip_sdk/utils/rendering/layout/__init__.py +64 -0
- glaip_sdk/utils/rendering/{renderer → layout}/panels.py +10 -3
- glaip_sdk/utils/rendering/{renderer → layout}/progress.py +73 -12
- glaip_sdk/utils/rendering/layout/summary.py +74 -0
- glaip_sdk/utils/rendering/layout/transcript.py +606 -0
- glaip_sdk/utils/rendering/models.py +3 -6
- glaip_sdk/utils/rendering/renderer/__init__.py +9 -49
- glaip_sdk/utils/rendering/renderer/base.py +258 -1577
- glaip_sdk/utils/rendering/renderer/config.py +1 -5
- glaip_sdk/utils/rendering/renderer/debug.py +30 -34
- glaip_sdk/utils/rendering/renderer/factory.py +138 -0
- glaip_sdk/utils/rendering/renderer/stream.py +10 -51
- glaip_sdk/utils/rendering/renderer/summary_window.py +79 -0
- glaip_sdk/utils/rendering/renderer/thinking.py +273 -0
- glaip_sdk/utils/rendering/renderer/toggle.py +1 -3
- glaip_sdk/utils/rendering/renderer/tool_panels.py +442 -0
- glaip_sdk/utils/rendering/renderer/transcript_mode.py +162 -0
- glaip_sdk/utils/rendering/state.py +204 -0
- glaip_sdk/utils/rendering/step_tree_state.py +1 -3
- glaip_sdk/utils/rendering/steps/__init__.py +34 -0
- glaip_sdk/utils/rendering/{steps.py → steps/event_processor.py} +76 -517
- glaip_sdk/utils/rendering/steps/format.py +176 -0
- glaip_sdk/utils/rendering/steps/manager.py +387 -0
- glaip_sdk/utils/rendering/timing.py +36 -0
- glaip_sdk/utils/rendering/viewer/__init__.py +21 -0
- glaip_sdk/utils/rendering/viewer/presenter.py +184 -0
- glaip_sdk/utils/resource_refs.py +29 -26
- glaip_sdk/utils/runtime_config.py +425 -0
- glaip_sdk/utils/serialization.py +32 -46
- glaip_sdk/utils/sync.py +142 -0
- glaip_sdk/utils/tool_detection.py +33 -0
- glaip_sdk/utils/validation.py +20 -28
- {glaip_sdk-0.1.0.dist-info → glaip_sdk-0.6.10.dist-info}/METADATA +42 -4
- glaip_sdk-0.6.10.dist-info/RECORD +159 -0
- {glaip_sdk-0.1.0.dist-info → glaip_sdk-0.6.10.dist-info}/WHEEL +1 -1
- glaip_sdk/models.py +0 -259
- glaip_sdk-0.1.0.dist-info/RECORD +0 -82
- {glaip_sdk-0.1.0.dist-info → glaip_sdk-0.6.10.dist-info}/entry_points.txt +0 -0
glaip_sdk/cli/update_notifier.py
CHANGED
|
@@ -6,10 +6,14 @@ Author:
|
|
|
6
6
|
|
|
7
7
|
from __future__ import annotations
|
|
8
8
|
|
|
9
|
-
import
|
|
10
|
-
|
|
9
|
+
import importlib
|
|
10
|
+
import logging
|
|
11
|
+
import sys
|
|
12
|
+
from collections.abc import Callable, Iterable, Iterator
|
|
13
|
+
from contextlib import contextmanager
|
|
11
14
|
from typing import Any, Literal
|
|
12
15
|
|
|
16
|
+
import click
|
|
13
17
|
import httpx
|
|
14
18
|
from packaging.version import InvalidVersion, Version
|
|
15
19
|
from rich import box
|
|
@@ -17,10 +21,14 @@ from rich.console import Console
|
|
|
17
21
|
|
|
18
22
|
from glaip_sdk.branding import (
|
|
19
23
|
ACCENT_STYLE,
|
|
24
|
+
ERROR_STYLE,
|
|
20
25
|
SUCCESS_STYLE,
|
|
21
26
|
WARNING_STYLE,
|
|
22
27
|
)
|
|
23
|
-
from glaip_sdk.cli.
|
|
28
|
+
from glaip_sdk.cli.commands.update import update_command
|
|
29
|
+
from glaip_sdk.cli.constants import UPDATE_CHECK_ENABLED
|
|
30
|
+
from glaip_sdk.cli.hints import format_command_hint
|
|
31
|
+
from glaip_sdk.cli.utils import command_hint
|
|
24
32
|
from glaip_sdk.rich_components import AIPPanel
|
|
25
33
|
|
|
26
34
|
FetchLatestVersion = Callable[[], str | None]
|
|
@@ -28,6 +36,8 @@ FetchLatestVersion = Callable[[], str | None]
|
|
|
28
36
|
PYPI_JSON_URL = "https://pypi.org/pypi/{package}/json"
|
|
29
37
|
DEFAULT_TIMEOUT = 1.5 # seconds
|
|
30
38
|
|
|
39
|
+
_LOGGER = logging.getLogger(__name__)
|
|
40
|
+
|
|
31
41
|
|
|
32
42
|
def _parse_version(value: str) -> Version | None:
|
|
33
43
|
"""Parse a version string into a `Version`, returning None on failure."""
|
|
@@ -43,13 +53,16 @@ def _fetch_latest_version(package_name: str) -> str | None:
|
|
|
43
53
|
timeout = httpx.Timeout(DEFAULT_TIMEOUT)
|
|
44
54
|
|
|
45
55
|
try:
|
|
46
|
-
with
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
56
|
+
with _suppress_library_logging():
|
|
57
|
+
with httpx.Client(timeout=timeout) as client:
|
|
58
|
+
response = client.get(url, headers={"Accept": "application/json"})
|
|
59
|
+
response.raise_for_status()
|
|
60
|
+
payload = response.json()
|
|
61
|
+
except httpx.HTTPError as exc:
|
|
62
|
+
_LOGGER.debug("Update check failed: %s", exc, exc_info=True)
|
|
51
63
|
return None
|
|
52
|
-
except ValueError:
|
|
64
|
+
except ValueError as exc:
|
|
65
|
+
_LOGGER.debug("Invalid JSON while checking for updates: %s", exc, exc_info=True)
|
|
53
66
|
return None
|
|
54
67
|
|
|
55
68
|
info = payload.get("info") if isinstance(payload, dict) else None
|
|
@@ -61,13 +74,19 @@ def _fetch_latest_version(package_name: str) -> str | None:
|
|
|
61
74
|
|
|
62
75
|
def _should_check_for_updates() -> bool:
|
|
63
76
|
"""Return False when update checks are explicitly disabled."""
|
|
64
|
-
|
|
77
|
+
# Check module attribute first (for test overrides), then fall back to imported constant
|
|
78
|
+
module = sys.modules.get(__name__)
|
|
79
|
+
if module and hasattr(module, "UPDATE_CHECK_ENABLED"):
|
|
80
|
+
return getattr(module, "UPDATE_CHECK_ENABLED")
|
|
81
|
+
return UPDATE_CHECK_ENABLED
|
|
65
82
|
|
|
66
83
|
|
|
67
84
|
def _build_update_panel(
|
|
68
85
|
current_version: str,
|
|
69
86
|
latest_version: str,
|
|
70
87
|
command_text: str,
|
|
88
|
+
*,
|
|
89
|
+
show_command_hint: bool,
|
|
71
90
|
) -> AIPPanel:
|
|
72
91
|
"""Create a Rich panel that prompts the user to update."""
|
|
73
92
|
command_markup = format_command_hint(command_text) or command_text
|
|
@@ -75,9 +94,10 @@ def _build_update_panel(
|
|
|
75
94
|
f"[{WARNING_STYLE}]✨ Update available![/] "
|
|
76
95
|
f"{current_version} → {latest_version}\n\n"
|
|
77
96
|
"See the latest release notes:\n"
|
|
78
|
-
f"https://pypi.org/project/glaip-sdk/{latest_version}
|
|
79
|
-
f"[{ACCENT_STYLE}]Run[/] {command_markup} to install."
|
|
97
|
+
f"https://pypi.org/project/glaip-sdk/{latest_version}/"
|
|
80
98
|
)
|
|
99
|
+
if show_command_hint:
|
|
100
|
+
message += f"\n\n[{ACCENT_STYLE}]Run[/] {command_markup} to install."
|
|
81
101
|
return AIPPanel(
|
|
82
102
|
message,
|
|
83
103
|
title=f"[{SUCCESS_STYLE}]AIP SDK Update[/]",
|
|
@@ -97,11 +117,7 @@ def maybe_notify_update(
|
|
|
97
117
|
slash_command: str | None = None,
|
|
98
118
|
style: Literal["panel", "inline"] = "panel",
|
|
99
119
|
) -> None:
|
|
100
|
-
"""Check PyPI for a newer version and display a prompt if one exists.
|
|
101
|
-
|
|
102
|
-
This function deliberately swallows network errors to avoid impacting CLI
|
|
103
|
-
startup time when offline or when PyPI is unavailable.
|
|
104
|
-
"""
|
|
120
|
+
"""Check PyPI for a newer version and display a prompt if one exists."""
|
|
105
121
|
if not _should_check_for_updates():
|
|
106
122
|
return
|
|
107
123
|
|
|
@@ -120,18 +136,155 @@ def maybe_notify_update(
|
|
|
120
136
|
return
|
|
121
137
|
|
|
122
138
|
active_console = console or Console()
|
|
139
|
+
should_prompt = _should_prompt_for_action(active_console, ctx)
|
|
140
|
+
|
|
123
141
|
if style == "inline":
|
|
142
|
+
if should_prompt:
|
|
143
|
+
message = (
|
|
144
|
+
f"[{WARNING_STYLE}]✨ Update[/] "
|
|
145
|
+
f"{current_version} → {latest_version} "
|
|
146
|
+
"- choose Update now or Skip to continue."
|
|
147
|
+
)
|
|
148
|
+
active_console.print(message)
|
|
149
|
+
_handle_update_decision(active_console, ctx)
|
|
150
|
+
return
|
|
151
|
+
|
|
124
152
|
command_markup = format_command_hint(command_text) or command_text
|
|
125
|
-
|
|
126
|
-
f"[{WARNING_STYLE}]✨ Update[/] "
|
|
127
|
-
f"{current_version} → {latest_version} "
|
|
128
|
-
f"- {command_markup}"
|
|
129
|
-
)
|
|
130
|
-
active_console.print(message)
|
|
153
|
+
active_console.print(f"[{WARNING_STYLE}]✨ Update[/] {current_version} → {latest_version} - {command_markup}")
|
|
131
154
|
return
|
|
132
155
|
|
|
133
|
-
panel = _build_update_panel(
|
|
156
|
+
panel = _build_update_panel(
|
|
157
|
+
current_version,
|
|
158
|
+
latest_version,
|
|
159
|
+
command_text,
|
|
160
|
+
show_command_hint=not should_prompt,
|
|
161
|
+
)
|
|
134
162
|
active_console.print(panel)
|
|
163
|
+
if should_prompt:
|
|
164
|
+
_handle_update_decision(active_console, ctx)
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+
def _handle_update_decision(console: Console, ctx: Any) -> None:
|
|
168
|
+
"""Prompt the user to take action on the available update."""
|
|
169
|
+
choice = _prompt_update_decision(console)
|
|
170
|
+
if choice == "skip":
|
|
171
|
+
return
|
|
172
|
+
|
|
173
|
+
_run_update_command(console, ctx)
|
|
174
|
+
|
|
175
|
+
|
|
176
|
+
def _should_prompt_for_action(console: Console, ctx: Any | None) -> bool:
|
|
177
|
+
"""Return True when we can safely block for interactive input."""
|
|
178
|
+
if ctx is None or not hasattr(ctx, "invoke"):
|
|
179
|
+
return False
|
|
180
|
+
|
|
181
|
+
is_interactive = getattr(console, "is_interactive", False)
|
|
182
|
+
if not isinstance(is_interactive, bool) or not is_interactive:
|
|
183
|
+
return False
|
|
184
|
+
|
|
185
|
+
is_terminal = getattr(console, "is_terminal", False)
|
|
186
|
+
if not isinstance(is_terminal, bool) or not is_terminal:
|
|
187
|
+
return False
|
|
188
|
+
|
|
189
|
+
input_method = getattr(console, "input", None)
|
|
190
|
+
return callable(input_method)
|
|
191
|
+
|
|
192
|
+
|
|
193
|
+
def _prompt_update_decision(console: Console) -> Literal["update", "skip"]:
|
|
194
|
+
"""Ask the user to choose between updating now or skipping."""
|
|
195
|
+
console.print(
|
|
196
|
+
f"[{ACCENT_STYLE}]Select an option to continue:[/]\n"
|
|
197
|
+
f" [{SUCCESS_STYLE}]1.[/] Update now\n"
|
|
198
|
+
f" [{WARNING_STYLE}]2.[/] Skip\n"
|
|
199
|
+
)
|
|
200
|
+
console.print("[dim]Press Enter after typing your choice.[/]")
|
|
201
|
+
|
|
202
|
+
while True:
|
|
203
|
+
try:
|
|
204
|
+
response = console.input("Choice [1/2]: ").strip().lower()
|
|
205
|
+
except (KeyboardInterrupt, EOFError):
|
|
206
|
+
console.print(f"\n[{WARNING_STYLE}]Update skipped.[/]")
|
|
207
|
+
return "skip"
|
|
208
|
+
|
|
209
|
+
if response in {"1", "update", "u"}:
|
|
210
|
+
return "update"
|
|
211
|
+
if response in {"2", "skip", "s"}:
|
|
212
|
+
return "skip"
|
|
213
|
+
|
|
214
|
+
console.print(f"[{ERROR_STYLE}]Please enter 1 to update now or 2 to skip.[/]")
|
|
215
|
+
|
|
216
|
+
|
|
217
|
+
def _run_update_command(console: Console, ctx: Any) -> None:
|
|
218
|
+
"""Invoke the built-in update command and surface any errors."""
|
|
219
|
+
try:
|
|
220
|
+
ctx.invoke(update_command)
|
|
221
|
+
except click.ClickException as exc:
|
|
222
|
+
exc.show()
|
|
223
|
+
console.print(f"[{ERROR_STYLE}]Update command exited with an error.[/]")
|
|
224
|
+
except click.Abort:
|
|
225
|
+
console.print(f"[{WARNING_STYLE}]Update aborted by user.[/]")
|
|
226
|
+
except Exception as exc: # pragma: no cover - defensive guard
|
|
227
|
+
console.print(f"[{ERROR_STYLE}]Unexpected error while running update: {exc}[/]")
|
|
228
|
+
else:
|
|
229
|
+
_refresh_installed_version(console, ctx)
|
|
230
|
+
|
|
231
|
+
|
|
232
|
+
@contextmanager
|
|
233
|
+
def _suppress_library_logging(
|
|
234
|
+
logger_names: Iterable[str] | None = None, *, level: int = logging.WARNING
|
|
235
|
+
) -> Iterator[None]:
|
|
236
|
+
"""Temporarily raise log level for selected libraries during update checks."""
|
|
237
|
+
names = tuple(logger_names) if logger_names is not None else ("httpx",)
|
|
238
|
+
captured: list[tuple[logging.Logger, int]] = []
|
|
239
|
+
try:
|
|
240
|
+
for name in names:
|
|
241
|
+
logger = logging.getLogger(name)
|
|
242
|
+
captured.append((logger, logger.level))
|
|
243
|
+
logger.setLevel(level)
|
|
244
|
+
yield
|
|
245
|
+
finally:
|
|
246
|
+
for logger, previous_level in captured:
|
|
247
|
+
logger.setLevel(previous_level)
|
|
248
|
+
|
|
249
|
+
|
|
250
|
+
def _refresh_installed_version(console: Console, ctx: Any) -> None:
|
|
251
|
+
"""Reload runtime metadata after an in-process upgrade."""
|
|
252
|
+
new_version: str | None = None
|
|
253
|
+
branding_module: Any | None = None
|
|
254
|
+
|
|
255
|
+
try:
|
|
256
|
+
version_module = importlib.reload(importlib.import_module("glaip_sdk._version"))
|
|
257
|
+
new_version = getattr(version_module, "__version__", None)
|
|
258
|
+
except Exception as exc: # pragma: no cover - defensive guard
|
|
259
|
+
_LOGGER.debug("Failed to reload glaip_sdk._version: %s", exc, exc_info=True)
|
|
260
|
+
|
|
261
|
+
try:
|
|
262
|
+
branding_module = importlib.reload(importlib.import_module("glaip_sdk.branding"))
|
|
263
|
+
if new_version:
|
|
264
|
+
branding_module.SDK_VERSION = new_version
|
|
265
|
+
except Exception as exc: # pragma: no cover - defensive guard
|
|
266
|
+
_LOGGER.debug("Failed to update branding metadata: %s", exc, exc_info=True)
|
|
267
|
+
branding_module = None
|
|
268
|
+
|
|
269
|
+
session = _get_slash_session(ctx)
|
|
270
|
+
if session and hasattr(session, "refresh_branding"):
|
|
271
|
+
try:
|
|
272
|
+
branding_cls = getattr(branding_module, "AIPBranding", None) if branding_module else None
|
|
273
|
+
session.refresh_branding(new_version, branding_cls=branding_cls)
|
|
274
|
+
return
|
|
275
|
+
except Exception as exc: # pragma: no cover - defensive guard
|
|
276
|
+
_LOGGER.debug("Failed to refresh active slash session: %s", exc, exc_info=True)
|
|
277
|
+
|
|
278
|
+
if new_version:
|
|
279
|
+
console.print(f"[{SUCCESS_STYLE}]CLI now running glaip-sdk {new_version}.[/]")
|
|
280
|
+
|
|
281
|
+
|
|
282
|
+
def _get_slash_session(ctx: Any) -> Any | None:
|
|
283
|
+
"""Return active slash session from the Click context if present."""
|
|
284
|
+
ctx_obj = getattr(ctx, "obj", None)
|
|
285
|
+
if isinstance(ctx_obj, dict):
|
|
286
|
+
return ctx_obj.get("_slash_session")
|
|
287
|
+
return None
|
|
135
288
|
|
|
136
289
|
|
|
137
290
|
__all__ = ["maybe_notify_update"]
|