glaip-sdk 0.6.20__py3-none-any.whl → 0.6.22__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/cli/auth.py CHANGED
@@ -19,8 +19,7 @@ from rich.console import Console
19
19
 
20
20
  from glaip_sdk.branding import HINT_PREFIX_STYLE, WARNING_STYLE
21
21
  from glaip_sdk.cli.account_store import AccountNotFoundError, AccountStoreError, get_account_store
22
- from glaip_sdk.cli.hints import format_command_hint
23
- from glaip_sdk.cli.utils import command_hint
22
+ from glaip_sdk.cli.hints import command_hint, format_command_hint
24
23
 
25
24
 
26
25
  def prepare_authentication_export(
@@ -526,12 +525,19 @@ def resolve_api_url_from_context(
526
525
  elif hasattr(ctx, "obj") and isinstance(ctx.obj, dict):
527
526
  account_name = ctx.obj.get("account_name")
528
527
 
529
- resolved_url, _, _ = resolve_credentials(
530
- account_name=account_name,
531
- api_url=api_url,
532
- api_key=None,
533
- ignore_env_creds=True,
534
- )
528
+ if isinstance(api_url, str) and api_url.strip():
529
+ return api_url.strip()
530
+
531
+ try:
532
+ resolved_url, _, _ = resolve_credentials(
533
+ account_name=account_name,
534
+ api_url=None,
535
+ api_key=None,
536
+ ignore_env_creds=True,
537
+ )
538
+ except Exception:
539
+ return None
540
+
535
541
  return resolved_url
536
542
 
537
543
 
@@ -33,7 +33,7 @@ from glaip_sdk.cli.commands.common_config import check_connection, render_brandi
33
33
  from glaip_sdk.cli.hints import format_command_hint
34
34
  from glaip_sdk.cli.masking import mask_api_key_display
35
35
  from glaip_sdk.cli.slash.accounts_shared import env_credentials_present
36
- from glaip_sdk.cli.utils import command_hint
36
+ from glaip_sdk.cli.hints import command_hint
37
37
  from glaip_sdk.icons import ICON_TOOL
38
38
  from glaip_sdk.rich_components import AIPPanel, AIPTable
39
39
 
@@ -60,17 +60,10 @@ from glaip_sdk.cli.transcript import (
60
60
  maybe_launch_post_run_viewer,
61
61
  store_transcript_for_session,
62
62
  )
63
- from glaip_sdk.cli.utils import (
64
- _fuzzy_pick_for_resources,
65
- build_renderer,
66
- coerce_to_row,
67
- get_client,
68
- handle_resource_export,
69
- output_list,
70
- output_result,
71
- spinner_context,
72
- with_client_and_spinner,
73
- )
63
+ from glaip_sdk.cli.core.context import get_client
64
+ from glaip_sdk.cli.core.output import coerce_to_row, handle_resource_export, output_list, output_result
65
+ from glaip_sdk.cli.core.prompting import _fuzzy_pick_for_resources
66
+ from glaip_sdk.cli.core.rendering import build_renderer, spinner_context, with_client_and_spinner
74
67
  from glaip_sdk.cli.validators import (
75
68
  validate_agent_instruction_cli as validate_agent_instruction,
76
69
  )
@@ -9,7 +9,7 @@ import click
9
9
  from rich.console import Console
10
10
  from rich.text import Text
11
11
  from glaip_sdk.branding import PRIMARY, SUCCESS_STYLE, WARNING_STYLE, AIPBranding
12
- from glaip_sdk.cli.utils import sdk_version
12
+ from glaip_sdk.cli.core.output import sdk_version
13
13
 
14
14
  if TYPE_CHECKING: # pragma: no cover - type checking only
15
15
  from glaip_sdk import Client
@@ -27,10 +27,9 @@ except ImportError: # pragma: no cover - optional dependency
27
27
  from glaip_sdk.cli.account_store import get_account_store
28
28
  from glaip_sdk.cli.commands.common_config import check_connection, render_branding_header
29
29
  from glaip_sdk.cli.config import CONFIG_FILE, load_config, save_config
30
- from glaip_sdk.cli.hints import format_command_hint
30
+ from glaip_sdk.cli.hints import command_hint, format_command_hint
31
31
  from glaip_sdk.cli.masking import mask_api_key_display
32
32
  from glaip_sdk.cli.rich_helpers import markup_text
33
- from glaip_sdk.cli.utils import command_hint
34
33
  from glaip_sdk.rich_components import AIPTable
35
34
 
36
35
  console = Console()
@@ -41,16 +41,15 @@ from glaip_sdk.cli.mcp_validators import (
41
41
  from glaip_sdk.cli.parsers.json_input import parse_json_input
42
42
  from glaip_sdk.cli.resolution import resolve_resource_reference
43
43
  from glaip_sdk.cli.rich_helpers import print_markup
44
- from glaip_sdk.cli.utils import (
44
+ from glaip_sdk.cli.core.context import get_client
45
+ from glaip_sdk.cli.core.output import (
45
46
  coerce_to_row,
46
47
  fetch_resource_for_export,
47
48
  format_datetime_fields,
48
- get_client,
49
49
  output_list,
50
50
  output_result,
51
- spinner_context,
52
- with_client_and_spinner,
53
51
  )
52
+ from glaip_sdk.cli.core.rendering import spinner_context, with_client_and_spinner
54
53
  from glaip_sdk.config.constants import (
55
54
  DEFAULT_MCP_TYPE,
56
55
  )
@@ -11,10 +11,8 @@ from rich.console import Console
11
11
 
12
12
  from glaip_sdk.branding import ACCENT_STYLE, INFO, SUCCESS
13
13
  from glaip_sdk.cli.context import output_flags
14
- from glaip_sdk.cli.utils import (
15
- output_list,
16
- with_client_and_spinner,
17
- )
14
+ from glaip_sdk.cli.core.output import output_list
15
+ from glaip_sdk.cli.core.rendering import with_client_and_spinner
18
16
 
19
17
  console = Console()
20
18
 
@@ -33,16 +33,15 @@ from glaip_sdk.cli.io import (
33
33
  )
34
34
  from glaip_sdk.cli.resolution import resolve_resource_reference
35
35
  from glaip_sdk.cli.rich_helpers import markup_text, print_markup
36
- from glaip_sdk.cli.utils import (
36
+ from glaip_sdk.cli.core.context import get_client, handle_best_effort_check
37
+ from glaip_sdk.cli.core.output import (
37
38
  coerce_to_row,
38
39
  format_datetime_fields,
39
- get_client,
40
- handle_best_effort_check,
41
40
  handle_resource_export,
42
41
  output_list,
43
42
  output_result,
44
- spinner_context,
45
43
  )
44
+ from glaip_sdk.cli.core.rendering import spinner_context
46
45
  from glaip_sdk.icons import ICON_TOOL
47
46
  from glaip_sdk.utils.import_export import merge_import_with_cli_args
48
47
  from rich.console import Console
@@ -34,7 +34,8 @@ from glaip_sdk.cli.transcript.history import (
34
34
  load_history_snapshot,
35
35
  )
36
36
  from glaip_sdk.cli.transcript.viewer import ViewerContext, run_viewer_session
37
- from glaip_sdk.cli.utils import format_size, get_ctx_value, parse_json_line
37
+ from glaip_sdk.cli.context import get_ctx_value
38
+ from glaip_sdk.cli.core.output import format_size, parse_json_line
38
39
  from glaip_sdk.rich_components import AIPTable
39
40
  from glaip_sdk.utils.rendering.layout.panels import create_final_panel
40
41
  from glaip_sdk.utils.rendering.renderer.debug import render_debug_event
@@ -6,9 +6,12 @@ Author:
6
6
 
7
7
  from __future__ import annotations
8
8
 
9
+ import importlib.util
10
+ import os
9
11
  import subprocess
10
12
  import sys
11
13
  from collections.abc import Sequence
14
+ from pathlib import Path
12
15
 
13
16
  import click
14
17
  from rich.console import Console
@@ -21,11 +24,54 @@ PACKAGE_NAME = "glaip-sdk"
21
24
  def _is_uv_managed_environment() -> bool:
22
25
  """Check if running in a uv-managed tool environment.
23
26
 
24
- Uses a path-based heuristic that may need updates if uv changes its layout.
27
+ Uses a path-based heuristic against sys.executable, sys.prefix, and UV_TOOL_DIR
28
+ or UV_TOOL_BIN to detect a case-insensitive "uv/tools" segment. Update if uv
29
+ changes its layout.
25
30
  """
26
- executable = str(sys.executable)
27
- # Check for uv tool install paths: ~/.local/share/uv/tools/*/bin/python*
28
- return ".local/share/uv/tools" in executable or "/uv/tools/" in executable
31
+ if _has_uv_tool_path(sys.executable):
32
+ return True
33
+ if _has_uv_tool_path(sys.prefix):
34
+ return True
35
+ uv_tool_dir = os.environ.get("UV_TOOL_DIR") or os.environ.get("UV_TOOL_BIN")
36
+ if uv_tool_dir and _has_uv_tool_path(uv_tool_dir):
37
+ return True
38
+ return False
39
+
40
+
41
+ def _has_uv_tool_path(path: str) -> bool:
42
+ """Return True when a path contains a case-insensitive uv/tools segment."""
43
+ parts = [part.lower() for part in Path(path).parts]
44
+ for idx, part in enumerate(parts[:-1]):
45
+ if part == "uv" and parts[idx + 1] == "tools":
46
+ return True
47
+ return False
48
+
49
+
50
+ def _is_pip_available() -> bool:
51
+ """Return True when pip can be imported in the current interpreter."""
52
+ return importlib.util.find_spec("pip") is not None
53
+
54
+
55
+ def _build_missing_pip_guidance(
56
+ *,
57
+ include_prerelease: bool,
58
+ package_name: str = PACKAGE_NAME,
59
+ force_reinstall: bool = False,
60
+ ) -> tuple[str, str]:
61
+ """Return error and troubleshooting guidance when pip is unavailable."""
62
+ manual_cmd = _build_manual_upgrade_command(
63
+ include_prerelease,
64
+ package_name=package_name,
65
+ is_uv=True,
66
+ force_reinstall=force_reinstall,
67
+ )
68
+ error_detail = "pip is not available in this environment."
69
+ troubleshooting = (
70
+ "💡 Troubleshooting:\n"
71
+ f" • If you installed via uv tool, run: {manual_cmd}\n"
72
+ " • Otherwise install pip: python -m ensurepip"
73
+ )
74
+ return error_detail, troubleshooting
29
75
 
30
76
 
31
77
  def _build_command_parts(
@@ -115,6 +161,11 @@ def update_command(include_prerelease: bool) -> None:
115
161
  console = Console()
116
162
  # Call _is_uv_managed_environment() once and pass explicitly to avoid redundant calls
117
163
  is_uv = _is_uv_managed_environment()
164
+ if not is_uv and not _is_pip_available():
165
+ error_detail, troubleshooting = _build_missing_pip_guidance(
166
+ include_prerelease=include_prerelease,
167
+ )
168
+ raise click.ClickException(f"{error_detail}\n{troubleshooting}")
118
169
  upgrade_cmd = _build_upgrade_command(include_prerelease, is_uv=is_uv)
119
170
 
120
171
  # Determine the appropriate manual command for error messages
glaip_sdk/cli/main.py CHANGED
@@ -36,22 +36,28 @@ from glaip_sdk.cli.commands.models import models_group
36
36
  from glaip_sdk.cli.commands.tools import tools_group
37
37
  from glaip_sdk.cli.commands.transcripts import transcripts_group
38
38
  from glaip_sdk.cli.commands.update import (
39
+ _build_missing_pip_guidance,
39
40
  _build_manual_upgrade_command,
40
41
  _build_upgrade_command,
42
+ _is_pip_available,
41
43
  _is_uv_managed_environment,
42
44
  update_command,
43
45
  )
44
46
  from glaip_sdk.cli.config import load_config
45
47
  from glaip_sdk.cli.hints import in_slash_mode
48
+ from glaip_sdk.cli.core.output import format_size, sdk_version
49
+ from glaip_sdk.cli.core.rendering import spinner_context, update_spinner
46
50
  from glaip_sdk.cli.transcript import get_transcript_cache_stats
47
51
  from glaip_sdk.cli.update_notifier import maybe_notify_update
48
- from glaip_sdk.cli.utils import format_size, sdk_version, spinner_context, update_spinner
49
52
  from glaip_sdk.config.constants import (
50
53
  DEFAULT_AGENT_RUN_TIMEOUT,
51
54
  )
52
55
  from glaip_sdk.icons import ICON_AGENT
53
56
  from glaip_sdk.rich_components import AIPPanel, AIPTable
54
57
 
58
+ # Constants
59
+ UPDATE_ERROR_TITLE = "❌ Update Error"
60
+
55
61
  Client: type[Any] | None = None
56
62
 
57
63
 
@@ -242,26 +248,40 @@ def _load_and_merge_config(ctx: click.Context) -> dict:
242
248
 
243
249
  def _validate_config_and_show_error(config: dict, console: Console) -> None:
244
250
  """Validate configuration and show error if incomplete."""
245
- store = get_account_store()
246
- has_accounts = bool(store.list_accounts())
247
- if not config.get("api_url") or not config.get("api_key"):
248
- no_accounts_hint = "" if has_accounts else "\n • No accounts found; create one now to continue"
249
- console.print(
250
- AIPPanel(
251
- f"[{ERROR_STYLE}]❌ Configuration incomplete[/]\n\n"
252
- f"🔍 Current config:\n"
253
- f" • API URL: {config.get('api_url', 'Not set')}\n"
254
- f" • API Key: {'***' + config.get('api_key', '')[-4:] if config.get('api_key') else 'Not set'}\n\n"
255
- f"💡 To fix this:\n"
256
- f" Run 'aip accounts add default' to set up credentials\n"
257
- f" • Or run 'aip configure' for interactive setup\n"
258
- f" • Or run 'aip accounts list' to see current accounts{no_accounts_hint}",
259
- title=" Configuration Error",
260
- border_style=ERROR,
261
- ),
262
- )
263
- console.print(f"\n[{SUCCESS_STYLE}]✅ AIP - Ready[/] (SDK v{sdk_version()}) - Configure to connect")
264
- sys.exit(1)
251
+ if config.get("api_url") and config.get("api_key"):
252
+ return
253
+
254
+ # Best effort: avoid failing validation due to config I/O issues.
255
+ has_accounts = True
256
+ logger = logging.getLogger(__name__)
257
+ try:
258
+ store = get_account_store()
259
+ try:
260
+ has_accounts = bool(store.list_accounts())
261
+ except Exception:
262
+ logger.warning("Failed to list accounts from account store.", exc_info=True)
263
+ has_accounts = True
264
+ except Exception:
265
+ logger.warning("Failed to initialize account store.", exc_info=True)
266
+ has_accounts = True
267
+
268
+ no_accounts_hint = "" if has_accounts else "\n • No accounts found; create one now to continue"
269
+ console.print(
270
+ AIPPanel(
271
+ f"[{ERROR_STYLE}]❌ Configuration incomplete[/]\n\n"
272
+ f"🔍 Current config:\n"
273
+ f" • API URL: {config.get('api_url', 'Not set')}\n"
274
+ f" • API Key: {'***' + config.get('api_key', '')[-4:] if config.get('api_key') else 'Not set'}\n\n"
275
+ f"💡 To fix this:\n"
276
+ f" • Run 'aip accounts add default' to set up credentials\n"
277
+ f" • Or run 'aip configure' for interactive setup\n"
278
+ f" • Or run 'aip accounts list' to see current accounts{no_accounts_hint}",
279
+ title="❌ Configuration Error",
280
+ border_style=ERROR,
281
+ ),
282
+ )
283
+ console.print(f"\n[{SUCCESS_STYLE}]✅ AIP - Ready[/] (SDK v{sdk_version()}) - Configure to connect")
284
+ sys.exit(1)
265
285
 
266
286
 
267
287
  def _resolve_status_console(ctx: Any) -> tuple[Console, bool]:
@@ -557,6 +577,21 @@ def update(check_only: bool, force: bool) -> None:
557
577
  # Update using pip or uv tool install
558
578
  try:
559
579
  is_uv = _is_uv_managed_environment()
580
+ if not is_uv and not _is_pip_available():
581
+ error_detail, troubleshooting = _build_missing_pip_guidance(
582
+ include_prerelease=False,
583
+ package_name="glaip-sdk",
584
+ force_reinstall=force,
585
+ )
586
+ console.print(
587
+ AIPPanel(
588
+ f"[{ERROR_STYLE}]❌ Update failed[/]\n\n🔍 Error: {error_detail}\n\n{troubleshooting}",
589
+ title=UPDATE_ERROR_TITLE,
590
+ border_style=ERROR,
591
+ padding=(0, 1),
592
+ ),
593
+ )
594
+ sys.exit(1)
560
595
  cmd = list(
561
596
  _build_upgrade_command(
562
597
  include_prerelease=False,
@@ -609,7 +644,7 @@ def update(check_only: bool, force: bool) -> None:
609
644
  console.print(
610
645
  AIPPanel(
611
646
  f"[{ERROR_STYLE}]❌ Update failed[/]\n\n🔍 Error: {error_detail}\n\n{troubleshooting}",
612
- title="❌ Update Error",
647
+ title=UPDATE_ERROR_TITLE,
613
648
  border_style=ERROR,
614
649
  padding=(0, 1),
615
650
  ),
@@ -627,7 +662,7 @@ def update(check_only: bool, force: bool) -> None:
627
662
  console.print(
628
663
  AIPPanel(
629
664
  f"[{ERROR_STYLE}]❌ Update failed[/]\n\n🔍 Error: {e.stderr}\n\n{troubleshooting}",
630
- title="❌ Update Error",
665
+ title=UPDATE_ERROR_TITLE,
631
666
  border_style=ERROR,
632
667
  padding=(0, 1),
633
668
  ),
glaip_sdk/cli/pager.py CHANGED
@@ -46,11 +46,11 @@ def _get_console() -> Console:
46
46
  """
47
47
  global console
48
48
  try:
49
- cli_utils = importlib.import_module("glaip_sdk.cli.utils")
49
+ cli_output = importlib.import_module("glaip_sdk.cli.core.output")
50
50
  except Exception: # pragma: no cover - fallback during import cycles
51
- cli_utils = None
51
+ cli_output = None
52
52
 
53
- current_console = getattr(cli_utils, "console", None) if cli_utils else None
53
+ current_console = getattr(cli_output, "console", None) if cli_output else None
54
54
  if current_console is not None and current_console is not console:
55
55
  console = current_console
56
56
 
@@ -13,7 +13,8 @@ from typing import Any
13
13
  import click
14
14
 
15
15
  from glaip_sdk.branding import ACCENT_STYLE
16
- from glaip_sdk.cli.utils import resolve_resource, spinner_context
16
+ from glaip_sdk.cli.core.output import resolve_resource
17
+ from glaip_sdk.cli.core.rendering import spinner_context
17
18
 
18
19
 
19
20
  def resolve_resource_reference(
@@ -17,7 +17,7 @@ from glaip_sdk.cli.commands.agents import run as agents_run_command
17
17
  from glaip_sdk.cli.constants import DEFAULT_AGENT_INSTRUCTION_PREVIEW_LIMIT
18
18
  from glaip_sdk.cli.hints import format_command_hint
19
19
  from glaip_sdk.cli.slash.prompt import _HAS_PROMPT_TOOLKIT, FormattedText
20
- from glaip_sdk.cli.utils import bind_slash_session_context
20
+ from glaip_sdk.cli.core.context import bind_slash_session_context
21
21
 
22
22
  if TYPE_CHECKING: # pragma: no cover - type checking only
23
23
  from glaip_sdk.cli.slash.session import SlashSession
@@ -30,7 +30,7 @@ from glaip_sdk.branding import (
30
30
  )
31
31
  from glaip_sdk.cli.constants import DEFAULT_REMOTE_RUNS_PAGE_LIMIT
32
32
  from glaip_sdk.cli.slash.tui.remote_runs_app import RemoteRunsTUICallbacks, run_remote_runs_textual
33
- from glaip_sdk.cli.utils import prompt_export_choice_questionary, questionary_safe_ask
33
+ from glaip_sdk.cli.core.prompting import prompt_export_choice_questionary, questionary_safe_ask
34
34
  from glaip_sdk.exceptions import (
35
35
  AuthenticationError,
36
36
  ForbiddenError,
@@ -57,13 +57,10 @@ from glaip_sdk.cli.transcript import (
57
57
  )
58
58
  from glaip_sdk.cli.transcript.viewer import ViewerContext, run_viewer_session
59
59
  from glaip_sdk.cli.update_notifier import maybe_notify_update
60
- from glaip_sdk.cli.utils import (
61
- _fuzzy_pick_for_resources,
62
- command_hint,
63
- format_size,
64
- get_client,
65
- restore_slash_session_context,
66
- )
60
+ from glaip_sdk.cli.core.context import get_client, restore_slash_session_context
61
+ from glaip_sdk.cli.core.output import format_size
62
+ from glaip_sdk.cli.core.prompting import _fuzzy_pick_for_resources
63
+ from glaip_sdk.cli.hints import command_hint
67
64
  from glaip_sdk.rich_components import AIPGrid, AIPPanel, AIPTable
68
65
 
69
66
  SlashHandler = Callable[["SlashSession", list[str], bool], bool]
@@ -23,7 +23,7 @@ from glaip_sdk.cli.transcript.cache import ( # Reuse helpers even if marked pri
23
23
  transcript_path_candidates,
24
24
  write_manifest,
25
25
  )
26
- from glaip_sdk.cli.utils import parse_json_line
26
+ from glaip_sdk.cli.core.output import parse_json_line
27
27
  from glaip_sdk.utils.datetime_helpers import coerce_datetime
28
28
 
29
29
  DEFAULT_HISTORY_LIMIT = 10
@@ -21,7 +21,7 @@ except Exception: # pragma: no cover - optional dependency
21
21
  Choice = None # type: ignore[assignment]
22
22
 
23
23
  from glaip_sdk.cli.transcript.cache import suggest_filename
24
- from glaip_sdk.cli.utils import prompt_export_choice_questionary, questionary_safe_ask
24
+ from glaip_sdk.cli.core.prompting import prompt_export_choice_questionary, questionary_safe_ask
25
25
  from glaip_sdk.utils.rendering.layout.progress import is_delegation_tool
26
26
  from glaip_sdk.utils.rendering.layout.transcript import DEFAULT_TRANSCRIPT_THEME
27
27
  from glaip_sdk.utils.rendering.viewer import (
@@ -27,13 +27,14 @@ from glaip_sdk.branding import (
27
27
  WARNING_STYLE,
28
28
  )
29
29
  from glaip_sdk.cli.commands.update import (
30
+ PACKAGE_NAME,
31
+ _build_command_parts,
30
32
  _build_manual_upgrade_command,
31
33
  _is_uv_managed_environment,
32
34
  update_command,
33
35
  )
34
36
  from glaip_sdk.cli.constants import UPDATE_CHECK_ENABLED
35
- from glaip_sdk.cli.hints import format_command_hint
36
- from glaip_sdk.cli.utils import command_hint
37
+ from glaip_sdk.cli.hints import command_hint, format_command_hint
37
38
  from glaip_sdk.rich_components import AIPPanel
38
39
 
39
40
  FetchLatestVersion = Callable[[], str | None]
@@ -219,27 +220,90 @@ def _prompt_update_decision(console: Console) -> Literal["update", "skip"]:
219
220
  console.print(f"[{ERROR_STYLE}]Please enter 1 to update now or 2 to skip.[/]")
220
221
 
221
222
 
223
+ def _get_manual_upgrade_command(is_uv: bool) -> str:
224
+ """Get the manual upgrade command for the given environment type.
225
+
226
+ Args:
227
+ is_uv: True if running in uv tool environment, False for pip environment.
228
+
229
+ Returns:
230
+ Manual upgrade command string.
231
+ """
232
+ try:
233
+ return _build_manual_upgrade_command(include_prerelease=False, is_uv=is_uv)
234
+ except Exception:
235
+ # Fallback: rebuild from shared command parts to avoid hardcoded strings.
236
+ try:
237
+ command_parts, _ = _build_command_parts(
238
+ package_name=PACKAGE_NAME,
239
+ is_uv=is_uv,
240
+ force_reinstall=False,
241
+ include_prerelease=False,
242
+ )
243
+ except Exception:
244
+ command_parts = (
245
+ ["uv", "tool", "install", "--upgrade", PACKAGE_NAME]
246
+ if is_uv
247
+ else ["pip", "install", "--upgrade", PACKAGE_NAME]
248
+ )
249
+ return " ".join(command_parts)
250
+
251
+
252
+ def _show_proactive_uv_guidance(console: Console, is_uv: bool) -> None:
253
+ """Show proactive guidance for uv environments before update attempt.
254
+
255
+ Args:
256
+ console: Rich console for output.
257
+ is_uv: True if running in uv tool environment.
258
+ """
259
+ if not is_uv:
260
+ return
261
+
262
+ manual_cmd = _get_manual_upgrade_command(is_uv=True)
263
+ console.print(
264
+ f"[{INFO_STYLE}]💡 Detected uv tool environment.[/] "
265
+ f"If automatic update fails, run: [{ACCENT_STYLE}]{manual_cmd}[/]"
266
+ )
267
+
268
+
269
+ def _show_error_guidance(console: Console, is_uv: bool) -> None:
270
+ """Show error guidance with correct manual command based on environment.
271
+
272
+ Args:
273
+ console: Rich console for output.
274
+ is_uv: True if running in uv tool environment.
275
+ """
276
+ try:
277
+ manual_cmd = _get_manual_upgrade_command(is_uv=is_uv)
278
+ console.print(f"[{INFO_STYLE}]💡 Tip:[/] Run this command manually:\n [{ACCENT_STYLE}]{manual_cmd}[/]")
279
+ except Exception as exc: # pragma: no cover - defensive guard
280
+ _LOGGER.debug("Failed to render update tip: %s", exc, exc_info=True)
281
+
282
+
222
283
  def _run_update_command(console: Console, ctx: Any) -> None:
223
284
  """Invoke the built-in update command and surface any errors."""
285
+ # Detect uv environment proactively before attempting update
286
+ is_uv = _is_uv_managed_environment()
287
+
288
+ # Provide proactive guidance for uv environments
289
+ # This helps users on older versions (e.g., 0.6.19) that don't have uv detection
290
+ # in their update command
291
+ _show_proactive_uv_guidance(console, is_uv)
292
+
224
293
  try:
225
294
  ctx.invoke(update_command)
226
295
  except click.ClickException as exc:
227
296
  exc.show()
228
297
  console.print(f"[{ERROR_STYLE}]Update command exited with an error.[/]")
229
- # Provide additional context for uv environments
230
- try:
231
- if _is_uv_managed_environment():
232
- manual_cmd = _build_manual_upgrade_command(include_prerelease=False, is_uv=True)
233
- console.print(
234
- f"[{INFO_STYLE}]💡 Tip:[/] If automatic update failed, try running manually:\n"
235
- f" [{ACCENT_STYLE}]{manual_cmd}[/]"
236
- )
237
- except Exception as exc: # pragma: no cover - defensive guard
238
- _LOGGER.debug("Failed to render uv update tip: %s", exc, exc_info=True)
298
+ _show_error_guidance(console, is_uv)
239
299
  except click.Abort:
240
300
  console.print(f"[{WARNING_STYLE}]Update aborted by user.[/]")
241
301
  except Exception as exc: # pragma: no cover - defensive guard
242
302
  console.print(f"[{ERROR_STYLE}]Unexpected error while running update: {exc}[/]")
303
+ # Also provide guidance for unexpected errors in uv environments
304
+ if is_uv:
305
+ manual_cmd = _get_manual_upgrade_command(is_uv=True)
306
+ console.print(f"[{INFO_STYLE}]💡 Tip:[/] Try running manually:\n [{ACCENT_STYLE}]{manual_cmd}[/]")
243
307
  else:
244
308
  _refresh_installed_version(console, ctx)
245
309
 
@@ -13,7 +13,7 @@ from typing import Any
13
13
 
14
14
  import click
15
15
 
16
- from glaip_sdk.cli.utils import handle_best_effort_check
16
+ from glaip_sdk.cli.core.context import handle_best_effort_check
17
17
  from glaip_sdk.utils.validation import (
18
18
  coerce_timeout,
19
19
  validate_agent_instruction,
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: glaip-sdk
3
- Version: 0.6.20
3
+ Version: 0.6.22
4
4
  Summary: Python SDK and CLI for GL AIP (GDP Labs AI Agent Package) - Build, run, and manage AI agents
5
5
  Author-email: Raymond Christopher <raymond.christopher@gdplabs.id>
6
6
  License: MIT
@@ -20,13 +20,12 @@ Requires-Dist: gllm-core-binary>=0.1.0
20
20
  Requires-Dist: langchain-core>=0.3.0
21
21
  Requires-Dist: gllm-tools-binary>=0.1.3
22
22
  Provides-Extra: local
23
- Requires-Dist: aip-agents-binary[local]>=0.5.14; (python_version >= "3.11" and python_version < "3.13") and extra == "local"
24
- Requires-Dist: wrapt>=1.17.0; (python_version >= "3.11" and python_version < "3.13") and extra == "local"
23
+ Requires-Dist: aip-agents-binary[local]>=0.5.17; (python_version >= "3.11" and python_version < "3.13") and extra == "local"
24
+ Requires-Dist: gllm-docproc[docx,pdf,xlsx]<0.8.0,>=0.7.20; extra == "local"
25
25
  Provides-Extra: memory
26
- Requires-Dist: aip-agents-binary[memory]>=0.5.14; (python_version >= "3.11" and python_version < "3.13") and extra == "memory"
26
+ Requires-Dist: aip-agents-binary[memory]>=0.5.17; (python_version >= "3.11" and python_version < "3.13") and extra == "memory"
27
27
  Provides-Extra: privacy
28
- Requires-Dist: aip-agents-binary[privacy]>=0.5.14; (python_version >= "3.11" and python_version < "3.13") and extra == "privacy"
29
- Requires-Dist: en-core-web-sm; extra == "privacy"
28
+ Requires-Dist: aip-agents-binary[privacy]>=0.5.17; (python_version >= "3.11" and python_version < "3.13") and extra == "privacy"
30
29
  Provides-Extra: dev
31
30
  Requires-Dist: pytest>=7.0.0; extra == "dev"
32
31
  Requires-Dist: pytest-cov>=4.0.0; extra == "dev"
@@ -9,32 +9,31 @@ glaip_sdk/agents/base.py,sha256=_KfxI11vM3GaABN5o7hxD2f1Wv7nalCivC11J3wh0VM,4250
9
9
  glaip_sdk/cli/__init__.py,sha256=xCCfuF1Yc7mpCDcfhHZTX0vizvtrDSLeT8MJ3V7m5A0,156
10
10
  glaip_sdk/cli/account_store.py,sha256=TK4iTV93Q1uD9mCY_2ZMT6EazHKU2jX0qhgWfEM4V-4,18459
11
11
  glaip_sdk/cli/agent_config.py,sha256=YAbFKrTNTRqNA6b0i0Q3pH-01rhHDRi5v8dxSFwGSwM,2401
12
- glaip_sdk/cli/auth.py,sha256=e3Ctkjz3HBFk2mJE5xYpg78flot_luByLhqJ_bVtIsM,24149
12
+ glaip_sdk/cli/auth.py,sha256=bqOHMGIOCg3KXssme3uJBBjEbK0rCEppQ6oq-gJ-hzA,24276
13
13
  glaip_sdk/cli/config.py,sha256=s0_xBB1e5YE4I_Wc4q-ayY3dwsBU1JrHAF-8ySlim7Y,3040
14
14
  glaip_sdk/cli/constants.py,sha256=zqcVtzfj6huW97gbCmhkFqntge1H-c1vnkGqTazADgU,895
15
15
  glaip_sdk/cli/context.py,sha256=--Y5vc6lgoAV7cRoUAr9UxSQaLmkMg29FolA7EwoRqM,3803
16
16
  glaip_sdk/cli/display.py,sha256=ojgWdGeD5KUnGOmWNqqK4JP-1EaWHWX--DWze3BmIz0,12137
17
17
  glaip_sdk/cli/hints.py,sha256=ca4krG103IS43s5BSLr0-N7uRMpte1_LY4nAXVvgDxo,1596
18
18
  glaip_sdk/cli/io.py,sha256=ChP6CRKbtuENsNomNEaMDfPDU0iqO-WuVvl4_y7F2io,3871
19
- glaip_sdk/cli/main.py,sha256=vQ8YcsFT4tG0xXCsJdS1WEWHK6ojiQS6pWIRWiW9PnA,23275
19
+ glaip_sdk/cli/main.py,sha256=mSaiIRl9UDcJ5LvahHo3gHioZxd1owaKVrFFSFiOfqs,24478
20
20
  glaip_sdk/cli/masking.py,sha256=2lrXQ-pfL7N-vNEQRT1s4Xq3JPDPDT8RC61OdaTtkkc,4060
21
21
  glaip_sdk/cli/mcp_validators.py,sha256=cwbz7p_p7_9xVuuF96OBQOdmEgo5UObU6iWWQ2X03PI,10047
22
- glaip_sdk/cli/pager.py,sha256=XygkAB6UW3bte7I4KmK7-PUGCJiq2Pv-4-MfyXAmXCw,7925
23
- glaip_sdk/cli/resolution.py,sha256=K-VaEHm9SYY_qfb9538VNHykL4_2N6F8iQqI1zMx_64,2402
22
+ glaip_sdk/cli/pager.py,sha256=TmiMDNpUMuZju7QJ6A_ITqIoEf8Dhv8U6mTXx2Fga1k,7935
23
+ glaip_sdk/cli/resolution.py,sha256=AGvv7kllLcuvk_jdaArJqH3lId4IDEXpHceRZwy14xY,2448
24
24
  glaip_sdk/cli/rich_helpers.py,sha256=kO47N8e506rxrN6Oc9mbAWN3Qb536oQPWZy1s9A616g,819
25
- glaip_sdk/cli/update_notifier.py,sha256=Wbe_6WD_iQKq1GvoFS_vdcD_PIfj1LGCXMf0on2jKMY,10732
26
- glaip_sdk/cli/utils.py,sha256=iemmKkpPndoZFBasoVqV7QArplchtr08yYWLA2efMzg,11996
27
- glaip_sdk/cli/validators.py,sha256=d-kq4y7HWMo6Gc7wLXWUsCt8JwFvJX_roZqRm1Nko1I,5622
25
+ glaip_sdk/cli/update_notifier.py,sha256=fO1xbSBF8cHukEN_FZDJuhDRqOYubB1CoPYOgvy9J7U,12898
26
+ glaip_sdk/cli/validators.py,sha256=k4J2ACYJPF6UmWJfENt9OHWdp4RNArVxR3hoeqauO88,5629
28
27
  glaip_sdk/cli/commands/__init__.py,sha256=6Z3ASXDut0lAbUX_umBFtxPzzFyqoiZfVeTahThFu1A,219
29
- glaip_sdk/cli/commands/accounts.py,sha256=J89chwJWWpEv6TBXaGPUJH-aLrM9Ymxp4jywp5YUUEo,24685
30
- glaip_sdk/cli/commands/agents.py,sha256=WCOzllyh_Znwlju5camT4vE6OeRJbsAmjWwcyiAqWs4,48429
31
- glaip_sdk/cli/commands/common_config.py,sha256=ZdWxv050MIZyHOG_UR5AoZvSxvVMx0mdwSeQffHYw4E,3724
32
- glaip_sdk/cli/commands/configure.py,sha256=Y3ST1I33rXqlLvUyhKFOl9JUjDe01QCrL1dzOjO1E-c,30304
33
- glaip_sdk/cli/commands/mcps.py,sha256=tttqQnfM89iI9Pm94u8YRhiHMQNYNouecFX0brsT4cQ,42551
34
- glaip_sdk/cli/commands/models.py,sha256=vfcGprK5CHprQ0CNpNzQlNNTELvdgKC7JxTG_ijOwmE,2009
35
- glaip_sdk/cli/commands/tools.py,sha256=_VBqG-vIjnn-gqvDlSTvcU7_F4N3ANGGKEECcQVR-BM,18430
36
- glaip_sdk/cli/commands/transcripts.py,sha256=ofxZLus1xLB061NxrLo1J6LPEb2VIxJTjmz7hLKgPmc,26377
37
- glaip_sdk/cli/commands/update.py,sha256=BZJ_E0iF0K9n6EupQAqjTSzUP4GPmq5ybqhx5i-_xQ0,4611
28
+ glaip_sdk/cli/commands/accounts.py,sha256=vUZYt5Ii-nWKJ1nXRU684NHILpPXj40Xfh4qN1tZsNc,24685
29
+ glaip_sdk/cli/commands/agents.py,sha256=8F4WZbfXPfvB5Vvy2YuOoUxG_3uC3hCrLJbv3X_q7to,48512
30
+ glaip_sdk/cli/commands/common_config.py,sha256=seZUw_3kV7GlDH31uYHnT_Khq6B3oEuO-fIerXasgEI,3730
31
+ glaip_sdk/cli/commands/configure.py,sha256=ZToy6LSQ3ulEBrB9YpuWiIAiOQ2XQ11MxPNtN3V1V_A,30273
32
+ glaip_sdk/cli/commands/mcps.py,sha256=e2d4ZbvTQ-lrlC-VB2XaOqksJXvwwJfD1Hxz9vPQEbA,42623
33
+ glaip_sdk/cli/commands/models.py,sha256=kZKqwv2uzfyz8n_7b0hYTT8waaVZMDzVoSXtRvWa9jk,2042
34
+ glaip_sdk/cli/commands/tools.py,sha256=T1ATubfboWj3dZp4UnjFIX1dotWoaRfEIJus6Vz_G70,18502
35
+ glaip_sdk/cli/commands/transcripts.py,sha256=6KEAP_mMdoNgydpunxLjYl6QJIY-CJorwLTBSF3Cfuo,26416
36
+ glaip_sdk/cli/commands/update.py,sha256=SMO_Hr9WEolqvpFhEXY3TboBLHBfXIvBvwovbONEs7Y,6329
38
37
  glaip_sdk/cli/core/__init__.py,sha256=HTQqpijKNts6bYnwY97rpP3J324phoQmGFi6OXqi0E4,2116
39
38
  glaip_sdk/cli/core/context.py,sha256=I22z5IhZ09g5FPtMycDGU9Aj20Qv3TOQLhA5enaU2qk,3970
40
39
  glaip_sdk/cli/core/output.py,sha256=hj5F1M_rEqr4CChmdyW1QzGiWL0Mwzf-BFw-d6pjhjY,28304
@@ -45,10 +44,10 @@ glaip_sdk/cli/parsers/json_input.py,sha256=kxoxeIlgfsaH2jhe6apZAgSxAtwlpSINLTMRs
45
44
  glaip_sdk/cli/slash/__init__.py,sha256=J9TPL2UcNTkW8eifG6nRmAEGHhyEgdYMYk4cHaaObC0,386
46
45
  glaip_sdk/cli/slash/accounts_controller.py,sha256=-7v_4nTAVCqXySbOLtTfMpUpsqCzDTWmZYkBU880AzI,24803
47
46
  glaip_sdk/cli/slash/accounts_shared.py,sha256=Mq5HxlI0YsVEQ0KKISWvyBZhzOFFWCzwRbhF5xwvUbM,2626
48
- glaip_sdk/cli/slash/agent_session.py,sha256=ZK51zrwhFtun26Lu3a70Kcp3VFh0jwu37crWDKx7Ivk,11377
47
+ glaip_sdk/cli/slash/agent_session.py,sha256=tuVOme-NbEyr6rwJvsBEKZYWQmsaRf4piJeRvIGu0ns,11384
49
48
  glaip_sdk/cli/slash/prompt.py,sha256=q4f1c2zr7ZMUeO6AgOBF2Nz4qgMOXrVPt6WzPRQMbAM,8501
50
- glaip_sdk/cli/slash/remote_runs_controller.py,sha256=Ok6CezIeF1CPGQ8-QN3TRx5kGGEACOrgyPwH_BRRCyI,21354
51
- glaip_sdk/cli/slash/session.py,sha256=JieIjUCTMW350LDqdSOdfPP8U0OJSmRYvqPBbddO2bw,64333
49
+ glaip_sdk/cli/slash/remote_runs_controller.py,sha256=a5X5rYgb9l6dHhvTewRUCj-hAo7mKRnuM_MwGvxs8jI,21363
50
+ glaip_sdk/cli/slash/session.py,sha256=f6yetP4ih_x7MZCbv4sVQfqHH7JJYgxLY0Q6VHHWTes,64423
52
51
  glaip_sdk/cli/slash/tui/__init__.py,sha256=ljBAeAFY2qNDkbJrZh5NgXxjwUlsv9-UxgKNIv0AF1Q,274
53
52
  glaip_sdk/cli/slash/tui/accounts.tcss,sha256=xuQjQ0tBM08K1DUv6lI5Sfu1zgZzQxg60c9-RlEWB4s,1160
54
53
  glaip_sdk/cli/slash/tui/accounts_app.py,sha256=QDaOpVStS6Z51tfXcS8GRRjTrVfMO26-guHepqysU9k,33715
@@ -59,9 +58,9 @@ glaip_sdk/cli/transcript/__init__.py,sha256=yiYHyNtebMCu3BXu56Xm5RBC2tDc865q8UGP
59
58
  glaip_sdk/cli/transcript/cache.py,sha256=Wi1uln6HP1U6F-MRTrfnxi9bn6XJTxwWXhREIRPoMqQ,17439
60
59
  glaip_sdk/cli/transcript/capture.py,sha256=t8j_62cC6rhb51oCluZd17N04vcXqyjkhPRcRd3ZcmM,10291
61
60
  glaip_sdk/cli/transcript/export.py,sha256=reCvrZVzli8_LzYe5ZNdaa-MwZ1ov2RjnDzKZWr_6-E,1117
62
- glaip_sdk/cli/transcript/history.py,sha256=2FBjawxP8CX9gRPMUMP8bDjG50BGM2j2zk6IfHvAMH4,26211
61
+ glaip_sdk/cli/transcript/history.py,sha256=IAUaY41QCr9jKgQ1t8spDJiO3Me5r1vAoTX47QQu5z0,26217
63
62
  glaip_sdk/cli/transcript/launcher.py,sha256=z5ivkPXDQJpATIqtRLUK8jH3p3WIZ72PvOPqYRDMJvw,2327
64
- glaip_sdk/cli/transcript/viewer.py,sha256=HKL3U-FrhluKSmxLdE_kTbdTalG-LCE0wu1MXsf22Ao,13189
63
+ glaip_sdk/cli/transcript/viewer.py,sha256=Y4G40WR6v1g4TfxRbGSZqdrqhLcqBxoWkQgToQoGGxM,13198
65
64
  glaip_sdk/client/__init__.py,sha256=F-eE_dRSzA0cc1it06oi0tZetZBHmSUjWSHGhJMLCls,263
66
65
  glaip_sdk/client/_agent_payloads.py,sha256=cH7CvNRn0JvudwKLr072E7W2QGWO9r-4xDxWMvXoPKE,17865
67
66
  glaip_sdk/client/agent_runs.py,sha256=tZSFEZZ3Yx0uYRgnwkLe-X0TlmgKJQ-ivzb6SrVnxY8,4862
@@ -156,8 +155,8 @@ glaip_sdk/utils/rendering/steps/format.py,sha256=Chnq7OBaj8XMeBntSBxrX5zSmrYeGcO
156
155
  glaip_sdk/utils/rendering/steps/manager.py,sha256=BiBmTeQMQhjRMykgICXsXNYh1hGsss-fH9BIGVMWFi0,13194
157
156
  glaip_sdk/utils/rendering/viewer/__init__.py,sha256=XrxmE2cMAozqrzo1jtDFm8HqNtvDcYi2mAhXLXn5CjI,457
158
157
  glaip_sdk/utils/rendering/viewer/presenter.py,sha256=mlLMTjnyeyPVtsyrAbz1BJu9lFGQSlS-voZ-_Cuugv0,5725
159
- glaip_sdk-0.6.20.dist-info/METADATA,sha256=m7NqyPGjDfUjM7TCsH_KcD_NSlQKW3-BesUIpYdEq5g,8455
160
- glaip_sdk-0.6.20.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
161
- glaip_sdk-0.6.20.dist-info/entry_points.txt,sha256=65vNPUggyYnVGhuw7RhNJ8Fp2jygTcX0yxJBcBY3iLU,48
162
- glaip_sdk-0.6.20.dist-info/top_level.txt,sha256=td7yXttiYX2s94-4wFhv-5KdT0rSZ-pnJRSire341hw,10
163
- glaip_sdk-0.6.20.dist-info/RECORD,,
158
+ glaip_sdk-0.6.22.dist-info/METADATA,sha256=f0VCtMfGVoaWe3bA4KVUN3AmPZk0AFZtyw3GsOLA4ug,8375
159
+ glaip_sdk-0.6.22.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
160
+ glaip_sdk-0.6.22.dist-info/entry_points.txt,sha256=65vNPUggyYnVGhuw7RhNJ8Fp2jygTcX0yxJBcBY3iLU,48
161
+ glaip_sdk-0.6.22.dist-info/top_level.txt,sha256=td7yXttiYX2s94-4wFhv-5KdT0rSZ-pnJRSire341hw,10
162
+ glaip_sdk-0.6.22.dist-info/RECORD,,
glaip_sdk/cli/utils.py DELETED
@@ -1,263 +0,0 @@
1
- """CLI utilities for glaip-sdk (facade for backward compatibility).
2
-
3
- This module is a backward-compatible facade that re-exports functions from
4
- glaip_sdk.cli.core.* modules. New code should import directly from the core modules.
5
- The facade is deprecated and will be removed after consumers migrate to core modules;
6
- see docs/specs/refactor/cli-core-modularization.md for the migration plan.
7
-
8
- Authors:
9
- Raymond Christopher (raymond.christopher@gdplabs.id)
10
- Putu Ravindra Wiguna (putu.r.wiguna@gdplabs.id)
11
- """ # pylint: disable=duplicate-code
12
-
13
- from __future__ import annotations
14
-
15
- import threading
16
- import warnings
17
-
18
- # Re-export from core modules
19
- from glaip_sdk.cli.core.context import (
20
- bind_slash_session_context,
21
- get_client,
22
- handle_best_effort_check,
23
- restore_slash_session_context,
24
- )
25
- from glaip_sdk.cli.core.output import (
26
- coerce_to_row,
27
- detect_export_format,
28
- fetch_resource_for_export,
29
- format_datetime_fields,
30
- format_size,
31
- handle_ambiguous_resource,
32
- handle_resource_export,
33
- output_list,
34
- output_result,
35
- parse_json_line,
36
- resolve_resource,
37
- sdk_version,
38
- # Private functions for backward compatibility (used in tests)
39
- _build_table_group,
40
- _build_yaml_renderable,
41
- _coerce_result_payload,
42
- _create_table,
43
- _ensure_displayable,
44
- _format_yaml_text,
45
- _get_interface_order,
46
- _handle_empty_items,
47
- _handle_fallback_numeric_ambiguity,
48
- _handle_fuzzy_pick_selection,
49
- _handle_json_output,
50
- _handle_json_view_ambiguity,
51
- _handle_markdown_output,
52
- _handle_plain_output,
53
- _handle_questionary_ambiguity,
54
- _handle_table_output,
55
- _literal_str_representer,
56
- _normalise_rows,
57
- _normalize_interface_preference,
58
- _print_selection_tip,
59
- _render_markdown_list,
60
- _render_markdown_output,
61
- _render_plain_list,
62
- _resolve_by_id,
63
- _resolve_by_name_multiple_fuzzy,
64
- _resolve_by_name_multiple_questionary,
65
- _resolve_by_name_multiple_with_select,
66
- _resource_tip_command,
67
- _should_fallback_to_numeric_prompt,
68
- _should_sort_rows,
69
- _should_use_fuzzy_picker,
70
- _try_fuzzy_pick,
71
- _try_fuzzy_selection,
72
- _try_interface_selection,
73
- _try_questionary_selection,
74
- _LiteralYamlDumper,
75
- )
76
- from glaip_sdk.cli.core.prompting import (
77
- _FuzzyCompleter, # Private class for backward compatibility (used in tests)
78
- _fuzzy_pick_for_resources,
79
- prompt_export_choice_questionary,
80
- questionary_safe_ask,
81
- # Private functions for backward compatibility (used in tests)
82
- _asyncio_loop_running,
83
- _basic_prompt,
84
- _build_resource_labels,
85
- _build_display_parts,
86
- _build_primary_parts,
87
- _build_unique_labels,
88
- _calculate_consecutive_bonus,
89
- _calculate_exact_match_bonus,
90
- _calculate_length_bonus,
91
- _check_fuzzy_pick_requirements,
92
- _extract_display_fields,
93
- _extract_fallback_values,
94
- _extract_id_suffix,
95
- _get_fallback_columns,
96
- _fuzzy_pick,
97
- _fuzzy_score,
98
- _is_fuzzy_match,
99
- _is_standard_field,
100
- _load_questionary_module,
101
- _make_questionary_choice,
102
- _perform_fuzzy_search,
103
- _prompt_with_auto_select,
104
- _rank_labels,
105
- _row_display,
106
- _run_questionary_in_thread,
107
- _strip_spaces_for_matching,
108
- )
109
- from glaip_sdk.cli.core.rendering import (
110
- build_renderer,
111
- spinner_context,
112
- stop_spinner,
113
- update_spinner,
114
- with_client_and_spinner,
115
- # Private functions for backward compatibility (used in tests)
116
- _can_use_spinner,
117
- _register_renderer_with_session,
118
- _spinner_stop,
119
- _spinner_update,
120
- _stream_supports_tty,
121
- )
122
-
123
- # Re-export from other modules for backward compatibility
124
- from glaip_sdk.cli.context import get_ctx_value
125
- from glaip_sdk.cli.hints import command_hint
126
- from glaip_sdk.utils import is_uuid
127
-
128
- # Re-export module-level variables for backward compatibility
129
- # Note: console is re-exported from output.py since that's where _handle_table_output uses it
130
- from glaip_sdk.cli.core.output import console
131
- import logging
132
-
133
- logger = logging.getLogger("glaip_sdk.cli.utils")
134
- questionary = None # type: ignore[assignment]
135
-
136
- _warn_lock = threading.Lock()
137
- _warned = False
138
-
139
-
140
- def _warn_once() -> None:
141
- """Emit the deprecation warning once in a thread-safe way."""
142
- global _warned
143
- if _warned:
144
- return
145
- with _warn_lock:
146
- if _warned:
147
- return
148
- warnings.warn(
149
- "Importing from glaip_sdk.cli.utils is deprecated. Use glaip_sdk.cli.core.* modules instead.",
150
- DeprecationWarning,
151
- stacklevel=3,
152
- )
153
- _warned = True
154
-
155
-
156
- _warn_once()
157
-
158
- # Re-export everything for backward compatibility
159
- __all__ = [
160
- # Context
161
- "bind_slash_session_context",
162
- "get_client",
163
- "get_ctx_value", # Re-exported from context module
164
- "handle_best_effort_check",
165
- "restore_slash_session_context",
166
- # Prompting
167
- "_FuzzyCompleter", # Private class for backward compatibility (used in tests)
168
- "_asyncio_loop_running", # Private function for backward compatibility (used in tests)
169
- "_basic_prompt", # Private function for backward compatibility (used in tests)
170
- "_build_display_parts", # Private function for backward compatibility (used in tests)
171
- "_build_primary_parts", # Private function for backward compatibility (used in tests)
172
- "_build_resource_labels", # Private function for backward compatibility (used in tests)
173
- "_build_unique_labels", # Private function for backward compatibility (used in tests)
174
- "_calculate_consecutive_bonus", # Private function for backward compatibility (used in tests)
175
- "_calculate_exact_match_bonus", # Private function for backward compatibility (used in tests)
176
- "_calculate_length_bonus", # Private function for backward compatibility (used in tests)
177
- "_check_fuzzy_pick_requirements", # Private function for backward compatibility (used in tests)
178
- "_extract_display_fields", # Private function for backward compatibility (used in tests)
179
- "_extract_fallback_values", # Private function for backward compatibility (used in tests)
180
- "_extract_id_suffix", # Private function for backward compatibility (used in tests)
181
- "_fuzzy_pick", # Private function for backward compatibility (used in tests)
182
- "_fuzzy_pick_for_resources",
183
- "_fuzzy_score", # Private function for backward compatibility (used in tests)
184
- "_get_fallback_columns", # Private function for backward compatibility (used in tests)
185
- "_is_fuzzy_match", # Private function for backward compatibility (used in tests)
186
- "_is_standard_field", # Private function for backward compatibility (used in tests)
187
- "_load_questionary_module", # Private function for backward compatibility (used in tests)
188
- "_make_questionary_choice", # Private function for backward compatibility (used in tests)
189
- "_perform_fuzzy_search", # Private function for backward compatibility (used in tests)
190
- "_prompt_with_auto_select", # Private function for backward compatibility (used in tests)
191
- "_rank_labels", # Private function for backward compatibility (used in tests)
192
- "_row_display", # Private function for backward compatibility (used in tests)
193
- "_run_questionary_in_thread", # Private function for backward compatibility (used in tests)
194
- "_strip_spaces_for_matching", # Private function for backward compatibility (used in tests)
195
- "prompt_export_choice_questionary",
196
- "questionary_safe_ask",
197
- # Rendering
198
- "_can_use_spinner", # Private function for backward compatibility (used in tests)
199
- "_register_renderer_with_session", # Private function for backward compatibility (used in tests)
200
- "_spinner_stop", # Private function for backward compatibility (used in tests)
201
- "_spinner_update", # Private function for backward compatibility (used in tests)
202
- "_stream_supports_tty", # Private function for backward compatibility (used in tests)
203
- "build_renderer",
204
- "console", # Module-level variable for backward compatibility
205
- "logger", # Module-level variable for backward compatibility
206
- "questionary", # Module-level variable for backward compatibility
207
- "spinner_context",
208
- "stop_spinner",
209
- "update_spinner",
210
- "with_client_and_spinner",
211
- # Output
212
- "_LiteralYamlDumper", # Private class for backward compatibility (used in tests)
213
- "_build_table_group", # Private function for backward compatibility (used in tests)
214
- "_build_yaml_renderable", # Private function for backward compatibility (used in tests)
215
- "_coerce_result_payload", # Private function for backward compatibility (used in tests)
216
- "_create_table", # Private function for backward compatibility (used in tests)
217
- "_ensure_displayable", # Private function for backward compatibility (used in tests)
218
- "_format_yaml_text", # Private function for backward compatibility (used in tests)
219
- "_get_interface_order", # Private function for backward compatibility (used in tests)
220
- "_handle_empty_items", # Private function for backward compatibility (used in tests)
221
- "_handle_fallback_numeric_ambiguity", # Private function for backward compatibility (used in tests)
222
- "_handle_fuzzy_pick_selection", # Private function for backward compatibility (used in tests)
223
- "_handle_json_output", # Private function for backward compatibility (used in tests)
224
- "_handle_json_view_ambiguity", # Private function for backward compatibility (used in tests)
225
- "_handle_markdown_output", # Private function for backward compatibility (used in tests)
226
- "_handle_plain_output", # Private function for backward compatibility (used in tests)
227
- "_handle_questionary_ambiguity", # Private function for backward compatibility (used in tests)
228
- "_handle_table_output", # Private function for backward compatibility (used in tests)
229
- "_literal_str_representer", # Private function for backward compatibility (used in tests)
230
- "_normalise_rows", # Private function for backward compatibility (used in tests)
231
- "_normalize_interface_preference", # Private function for backward compatibility (used in tests)
232
- "_print_selection_tip", # Private function for backward compatibility (used in tests)
233
- "_render_markdown_list", # Private function for backward compatibility (used in tests)
234
- "_render_markdown_output", # Private function for backward compatibility (used in tests)
235
- "_render_plain_list", # Private function for backward compatibility (used in tests)
236
- "_resolve_by_id", # Private function for backward compatibility (used in tests)
237
- "_resolve_by_name_multiple_fuzzy", # Private function for backward compatibility (used in tests)
238
- "_resolve_by_name_multiple_questionary", # Private function for backward compatibility (used in tests)
239
- "_resolve_by_name_multiple_with_select", # Private function for backward compatibility (used in tests)
240
- "_resource_tip_command", # Private function for backward compatibility (used in tests)
241
- "_should_fallback_to_numeric_prompt", # Private function for backward compatibility (used in tests)
242
- "_should_sort_rows", # Private function for backward compatibility (used in tests)
243
- "_should_use_fuzzy_picker", # Private function for backward compatibility (used in tests)
244
- "_try_fuzzy_pick", # Private function for backward compatibility (used in tests)
245
- "_try_fuzzy_selection", # Private function for backward compatibility (used in tests)
246
- "_try_interface_selection", # Private function for backward compatibility (used in tests)
247
- "_try_questionary_selection", # Private function for backward compatibility (used in tests)
248
- "coerce_to_row",
249
- "command_hint", # Re-exported from hints module
250
- "detect_export_format",
251
- "fetch_resource_for_export",
252
- "format_datetime_fields",
253
- "format_size",
254
- "handle_ambiguous_resource",
255
- "handle_resource_export",
256
- "output_list",
257
- "output_result",
258
- "parse_json_line",
259
- "resolve_resource",
260
- "sdk_version",
261
- # Utils
262
- "is_uuid", # Re-exported from glaip_sdk.utils for backward compatibility
263
- ]