glaip-sdk 0.6.11__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.
Files changed (156) hide show
  1. glaip_sdk/__init__.py +42 -5
  2. {glaip_sdk-0.6.11.dist-info → glaip_sdk-0.6.14.dist-info}/METADATA +31 -37
  3. glaip_sdk-0.6.14.dist-info/RECORD +12 -0
  4. {glaip_sdk-0.6.11.dist-info → glaip_sdk-0.6.14.dist-info}/WHEEL +2 -1
  5. glaip_sdk-0.6.14.dist-info/entry_points.txt +2 -0
  6. glaip_sdk-0.6.14.dist-info/top_level.txt +1 -0
  7. glaip_sdk/agents/__init__.py +0 -27
  8. glaip_sdk/agents/base.py +0 -1191
  9. glaip_sdk/cli/__init__.py +0 -9
  10. glaip_sdk/cli/account_store.py +0 -540
  11. glaip_sdk/cli/agent_config.py +0 -78
  12. glaip_sdk/cli/auth.py +0 -699
  13. glaip_sdk/cli/commands/__init__.py +0 -5
  14. glaip_sdk/cli/commands/accounts.py +0 -746
  15. glaip_sdk/cli/commands/agents.py +0 -1509
  16. glaip_sdk/cli/commands/common_config.py +0 -101
  17. glaip_sdk/cli/commands/configure.py +0 -896
  18. glaip_sdk/cli/commands/mcps.py +0 -1356
  19. glaip_sdk/cli/commands/models.py +0 -69
  20. glaip_sdk/cli/commands/tools.py +0 -576
  21. glaip_sdk/cli/commands/transcripts.py +0 -755
  22. glaip_sdk/cli/commands/update.py +0 -61
  23. glaip_sdk/cli/config.py +0 -95
  24. glaip_sdk/cli/constants.py +0 -38
  25. glaip_sdk/cli/context.py +0 -150
  26. glaip_sdk/cli/core/__init__.py +0 -79
  27. glaip_sdk/cli/core/context.py +0 -124
  28. glaip_sdk/cli/core/output.py +0 -846
  29. glaip_sdk/cli/core/prompting.py +0 -649
  30. glaip_sdk/cli/core/rendering.py +0 -187
  31. glaip_sdk/cli/display.py +0 -355
  32. glaip_sdk/cli/hints.py +0 -57
  33. glaip_sdk/cli/io.py +0 -112
  34. glaip_sdk/cli/main.py +0 -604
  35. glaip_sdk/cli/masking.py +0 -136
  36. glaip_sdk/cli/mcp_validators.py +0 -287
  37. glaip_sdk/cli/pager.py +0 -266
  38. glaip_sdk/cli/parsers/__init__.py +0 -7
  39. glaip_sdk/cli/parsers/json_input.py +0 -177
  40. glaip_sdk/cli/resolution.py +0 -67
  41. glaip_sdk/cli/rich_helpers.py +0 -27
  42. glaip_sdk/cli/slash/__init__.py +0 -15
  43. glaip_sdk/cli/slash/accounts_controller.py +0 -578
  44. glaip_sdk/cli/slash/accounts_shared.py +0 -75
  45. glaip_sdk/cli/slash/agent_session.py +0 -285
  46. glaip_sdk/cli/slash/prompt.py +0 -256
  47. glaip_sdk/cli/slash/remote_runs_controller.py +0 -566
  48. glaip_sdk/cli/slash/session.py +0 -1708
  49. glaip_sdk/cli/slash/tui/__init__.py +0 -9
  50. glaip_sdk/cli/slash/tui/accounts_app.py +0 -876
  51. glaip_sdk/cli/slash/tui/background_tasks.py +0 -72
  52. glaip_sdk/cli/slash/tui/loading.py +0 -58
  53. glaip_sdk/cli/slash/tui/remote_runs_app.py +0 -628
  54. glaip_sdk/cli/transcript/__init__.py +0 -31
  55. glaip_sdk/cli/transcript/cache.py +0 -536
  56. glaip_sdk/cli/transcript/capture.py +0 -329
  57. glaip_sdk/cli/transcript/export.py +0 -38
  58. glaip_sdk/cli/transcript/history.py +0 -815
  59. glaip_sdk/cli/transcript/launcher.py +0 -77
  60. glaip_sdk/cli/transcript/viewer.py +0 -374
  61. glaip_sdk/cli/update_notifier.py +0 -290
  62. glaip_sdk/cli/utils.py +0 -263
  63. glaip_sdk/cli/validators.py +0 -238
  64. glaip_sdk/client/__init__.py +0 -11
  65. glaip_sdk/client/_agent_payloads.py +0 -520
  66. glaip_sdk/client/agent_runs.py +0 -147
  67. glaip_sdk/client/agents.py +0 -1335
  68. glaip_sdk/client/base.py +0 -502
  69. glaip_sdk/client/main.py +0 -249
  70. glaip_sdk/client/mcps.py +0 -370
  71. glaip_sdk/client/run_rendering.py +0 -700
  72. glaip_sdk/client/shared.py +0 -21
  73. glaip_sdk/client/tools.py +0 -661
  74. glaip_sdk/client/validators.py +0 -198
  75. glaip_sdk/config/constants.py +0 -52
  76. glaip_sdk/mcps/__init__.py +0 -21
  77. glaip_sdk/mcps/base.py +0 -345
  78. glaip_sdk/models/__init__.py +0 -90
  79. glaip_sdk/models/agent.py +0 -47
  80. glaip_sdk/models/agent_runs.py +0 -116
  81. glaip_sdk/models/common.py +0 -42
  82. glaip_sdk/models/mcp.py +0 -33
  83. glaip_sdk/models/tool.py +0 -33
  84. glaip_sdk/payload_schemas/__init__.py +0 -7
  85. glaip_sdk/payload_schemas/agent.py +0 -85
  86. glaip_sdk/registry/__init__.py +0 -55
  87. glaip_sdk/registry/agent.py +0 -164
  88. glaip_sdk/registry/base.py +0 -139
  89. glaip_sdk/registry/mcp.py +0 -253
  90. glaip_sdk/registry/tool.py +0 -232
  91. glaip_sdk/runner/__init__.py +0 -59
  92. glaip_sdk/runner/base.py +0 -84
  93. glaip_sdk/runner/deps.py +0 -115
  94. glaip_sdk/runner/langgraph.py +0 -782
  95. glaip_sdk/runner/mcp_adapter/__init__.py +0 -13
  96. glaip_sdk/runner/mcp_adapter/base_mcp_adapter.py +0 -43
  97. glaip_sdk/runner/mcp_adapter/langchain_mcp_adapter.py +0 -257
  98. glaip_sdk/runner/mcp_adapter/mcp_config_builder.py +0 -95
  99. glaip_sdk/runner/tool_adapter/__init__.py +0 -18
  100. glaip_sdk/runner/tool_adapter/base_tool_adapter.py +0 -44
  101. glaip_sdk/runner/tool_adapter/langchain_tool_adapter.py +0 -219
  102. glaip_sdk/tools/__init__.py +0 -22
  103. glaip_sdk/tools/base.py +0 -435
  104. glaip_sdk/utils/__init__.py +0 -86
  105. glaip_sdk/utils/a2a/__init__.py +0 -34
  106. glaip_sdk/utils/a2a/event_processor.py +0 -188
  107. glaip_sdk/utils/agent_config.py +0 -194
  108. glaip_sdk/utils/bundler.py +0 -267
  109. glaip_sdk/utils/client.py +0 -111
  110. glaip_sdk/utils/client_utils.py +0 -486
  111. glaip_sdk/utils/datetime_helpers.py +0 -58
  112. glaip_sdk/utils/discovery.py +0 -78
  113. glaip_sdk/utils/display.py +0 -135
  114. glaip_sdk/utils/export.py +0 -143
  115. glaip_sdk/utils/general.py +0 -61
  116. glaip_sdk/utils/import_export.py +0 -168
  117. glaip_sdk/utils/import_resolver.py +0 -492
  118. glaip_sdk/utils/instructions.py +0 -101
  119. glaip_sdk/utils/rendering/__init__.py +0 -115
  120. glaip_sdk/utils/rendering/formatting.py +0 -264
  121. glaip_sdk/utils/rendering/layout/__init__.py +0 -64
  122. glaip_sdk/utils/rendering/layout/panels.py +0 -156
  123. glaip_sdk/utils/rendering/layout/progress.py +0 -202
  124. glaip_sdk/utils/rendering/layout/summary.py +0 -74
  125. glaip_sdk/utils/rendering/layout/transcript.py +0 -606
  126. glaip_sdk/utils/rendering/models.py +0 -85
  127. glaip_sdk/utils/rendering/renderer/__init__.py +0 -55
  128. glaip_sdk/utils/rendering/renderer/base.py +0 -1024
  129. glaip_sdk/utils/rendering/renderer/config.py +0 -27
  130. glaip_sdk/utils/rendering/renderer/console.py +0 -55
  131. glaip_sdk/utils/rendering/renderer/debug.py +0 -178
  132. glaip_sdk/utils/rendering/renderer/factory.py +0 -138
  133. glaip_sdk/utils/rendering/renderer/stream.py +0 -202
  134. glaip_sdk/utils/rendering/renderer/summary_window.py +0 -79
  135. glaip_sdk/utils/rendering/renderer/thinking.py +0 -273
  136. glaip_sdk/utils/rendering/renderer/toggle.py +0 -182
  137. glaip_sdk/utils/rendering/renderer/tool_panels.py +0 -442
  138. glaip_sdk/utils/rendering/renderer/transcript_mode.py +0 -162
  139. glaip_sdk/utils/rendering/state.py +0 -204
  140. glaip_sdk/utils/rendering/step_tree_state.py +0 -100
  141. glaip_sdk/utils/rendering/steps/__init__.py +0 -34
  142. glaip_sdk/utils/rendering/steps/event_processor.py +0 -778
  143. glaip_sdk/utils/rendering/steps/format.py +0 -176
  144. glaip_sdk/utils/rendering/steps/manager.py +0 -387
  145. glaip_sdk/utils/rendering/timing.py +0 -36
  146. glaip_sdk/utils/rendering/viewer/__init__.py +0 -21
  147. glaip_sdk/utils/rendering/viewer/presenter.py +0 -184
  148. glaip_sdk/utils/resource_refs.py +0 -195
  149. glaip_sdk/utils/run_renderer.py +0 -41
  150. glaip_sdk/utils/runtime_config.py +0 -425
  151. glaip_sdk/utils/serialization.py +0 -424
  152. glaip_sdk/utils/sync.py +0 -142
  153. glaip_sdk/utils/tool_detection.py +0 -33
  154. glaip_sdk/utils/validation.py +0 -264
  155. glaip_sdk-0.6.11.dist-info/RECORD +0 -159
  156. glaip_sdk-0.6.11.dist-info/entry_points.txt +0 -3
@@ -1,61 +0,0 @@
1
- """Update command for upgrading the glaip-sdk package.
2
-
3
- Author:
4
- Raymond Christopher (raymond.christopher@gdplabs.id)
5
- """
6
-
7
- from __future__ import annotations
8
-
9
- import subprocess
10
- import sys
11
- from collections.abc import Sequence
12
-
13
- import click
14
- from rich.console import Console
15
-
16
- from glaip_sdk.branding import ACCENT_STYLE, ERROR_STYLE, INFO_STYLE, SUCCESS_STYLE
17
-
18
- PACKAGE_NAME = "glaip-sdk"
19
-
20
-
21
- def _build_upgrade_command(include_prerelease: bool) -> Sequence[str]:
22
- """Return the pip command used to upgrade the SDK."""
23
- command = [
24
- sys.executable,
25
- "-m",
26
- "pip",
27
- "install",
28
- "--upgrade",
29
- PACKAGE_NAME,
30
- ]
31
- if include_prerelease:
32
- command.append("--pre")
33
- return command
34
-
35
-
36
- @click.command(name="update")
37
- @click.option(
38
- "--pre",
39
- "include_prerelease",
40
- is_flag=True,
41
- help="Include pre-release versions when upgrading.",
42
- )
43
- def update_command(include_prerelease: bool) -> None:
44
- """Upgrade the glaip-sdk package using pip."""
45
- console = Console()
46
- upgrade_cmd = _build_upgrade_command(include_prerelease)
47
- console.print(f"[{ACCENT_STYLE}]Upgrading {PACKAGE_NAME} using[/] [{INFO_STYLE}]{' '.join(upgrade_cmd)}[/]")
48
-
49
- try:
50
- subprocess.run(upgrade_cmd, check=True)
51
- except FileNotFoundError as exc:
52
- raise click.ClickException(
53
- "Unable to locate Python executable to run pip. Please ensure Python is installed and try again."
54
- ) from exc
55
- except subprocess.CalledProcessError as exc:
56
- console.print(
57
- f"[{ERROR_STYLE}]Automatic upgrade failed.[/] Please run `pip install -U {PACKAGE_NAME}` manually."
58
- )
59
- raise click.ClickException("Automatic upgrade failed.") from exc
60
-
61
- console.print(f"[{SUCCESS_STYLE}]✅ {PACKAGE_NAME} upgraded successfully.[/]")
glaip_sdk/cli/config.py DELETED
@@ -1,95 +0,0 @@
1
- """Configuration management utilities.
2
-
3
- Authors:
4
- Raymond Christopher (raymond.christopher@gdplabs.id)
5
- """
6
-
7
- import os
8
- from copy import deepcopy
9
- from pathlib import Path
10
- from typing import Any
11
-
12
- import yaml
13
-
14
- _ENV_CONFIG_DIR = os.getenv("AIP_CONFIG_DIR")
15
- # Detect pytest environment: check for pytest markers or test session
16
- # This provides automatic test isolation even if conftest.py doesn't set AIP_CONFIG_DIR
17
- # Note: conftest.py sets AIP_CONFIG_DIR before imports, which takes precedence
18
- _TEST_ENV = os.getenv("PYTEST_CURRENT_TEST") or os.getenv("PYTEST_XDIST_WORKER") or os.getenv("_PYTEST_RAISE")
19
-
20
- if _ENV_CONFIG_DIR:
21
- # Explicit override via environment variable (highest priority)
22
- # This is set by conftest.py before imports, ensuring test isolation
23
- CONFIG_DIR = Path(_ENV_CONFIG_DIR)
24
- elif _TEST_ENV:
25
- # Isolate test runs (including xdist workers) from the real user config directory
26
- # Use a per-process unique temp directory to avoid conflicts in parallel test runs
27
- import tempfile
28
- import uuid
29
-
30
- # Create a unique temp dir per test process to avoid conflicts
31
- temp_base = Path(tempfile.gettempdir())
32
- test_config_dir = temp_base / f"aip-test-config-{os.getpid()}-{uuid.uuid4().hex[:8]}"
33
- CONFIG_DIR = test_config_dir
34
- CONFIG_DIR.mkdir(parents=True, exist_ok=True)
35
- else: # pragma: no cover - default path used outside test runs
36
- CONFIG_DIR = Path.home() / ".aip"
37
-
38
- CONFIG_FILE = CONFIG_DIR / "config.yaml"
39
- _ALLOWED_KEYS = {
40
- "api_url",
41
- "api_key",
42
- "timeout",
43
- "history_default_limit",
44
- }
45
- # Keys that must be preserved for multi-account support
46
- _PRESERVE_KEYS = {
47
- "version",
48
- "active_account",
49
- "accounts",
50
- }
51
-
52
-
53
- def _sanitize_config(data: dict[str, Any] | None) -> dict[str, Any]:
54
- """Return config filtered to allowed keys only, preserving multi-account keys."""
55
- if not data:
56
- return {}
57
- result: dict[str, Any] = {}
58
- # Preserve multi-account structure (defensively copy to avoid callers mutating source)
59
- for key in _PRESERVE_KEYS:
60
- if key in data:
61
- result[key] = deepcopy(data[key])
62
- # Add allowed legacy keys (copied to avoid side effects)
63
- for key in _ALLOWED_KEYS:
64
- if key in data:
65
- result[key] = deepcopy(data[key])
66
- return result
67
-
68
-
69
- def load_config() -> dict[str, Any]:
70
- """Load configuration from file."""
71
- if not CONFIG_FILE.exists():
72
- return {}
73
-
74
- try:
75
- with open(CONFIG_FILE) as f:
76
- loaded = yaml.safe_load(f) or {}
77
- return _sanitize_config(loaded)
78
- except yaml.YAMLError:
79
- return {}
80
-
81
-
82
- def save_config(config: dict[str, Any]) -> None:
83
- """Save configuration to file."""
84
- CONFIG_DIR.mkdir(exist_ok=True)
85
-
86
- sanitized = _sanitize_config(config)
87
-
88
- with open(CONFIG_FILE, "w") as f:
89
- yaml.dump(sanitized, f, default_flow_style=False)
90
-
91
- # Set secure file permissions
92
- try:
93
- os.chmod(CONFIG_FILE, 0o600)
94
- except OSError: # pragma: no cover - permission errors are expected in some environments
95
- pass
@@ -1,38 +0,0 @@
1
- """CLI-specific constants for glaip-sdk.
2
-
3
- Authors:
4
- Raymond Christopher (raymond.christopher@gdplabs.id)
5
- """
6
-
7
- # Minimum length that forces multiline YAML strings to be rendered using the literal
8
- # block style. This prevents long prompts and instructions from being inlined.
9
- LITERAL_STRING_THRESHOLD = 200
10
-
11
- # Masking configuration
12
- MASKING_ENABLED = True
13
- MASK_SENSITIVE_FIELDS = {
14
- "api_key",
15
- "apikey",
16
- "token",
17
- "access_token",
18
- "secret",
19
- "client_secret",
20
- "password",
21
- "private_key",
22
- "bearer",
23
- }
24
-
25
- # Table + pager behaviour
26
- TABLE_SORT_ENABLED = True
27
- PAGER_MODE = "auto" # valid values: "auto", "on", "off"
28
- PAGER_WRAP_LINES = False
29
- PAGER_HEADER_ENABLED = True
30
-
31
- # Update notification toggle
32
- UPDATE_CHECK_ENABLED = True
33
-
34
- # Agent instruction preview defaults
35
- DEFAULT_AGENT_INSTRUCTION_PREVIEW_LIMIT = 800
36
-
37
- # Remote runs defaults
38
- DEFAULT_REMOTE_RUNS_PAGE_LIMIT = 20
glaip_sdk/cli/context.py DELETED
@@ -1,150 +0,0 @@
1
- """Context-related helpers for the glaip CLI.
2
-
3
- Authors:
4
- Putu Ravindra Wiguna (putu.r.wiguna@gdplabs.id)
5
- """
6
-
7
- from __future__ import annotations
8
-
9
- from collections.abc import Callable
10
- from pathlib import Path
11
- from typing import Any
12
-
13
- import click
14
-
15
- __all__ = [
16
- "get_ctx_value",
17
- "_get_view",
18
- "_set_view",
19
- "_set_json",
20
- "output_flags",
21
- "detect_export_format",
22
- ]
23
-
24
-
25
- def get_ctx_value(ctx: Any, key: str, default: Any = None) -> Any:
26
- """Safely resolve a value from a click context object.
27
-
28
- Args:
29
- ctx: Click context object to extract value from
30
- key: Key to retrieve from the context
31
- default: Default value if key is not found
32
-
33
- Returns:
34
- The value associated with the key, or the default if not found
35
- """
36
- if ctx is None:
37
- return default
38
-
39
- obj = getattr(ctx, "obj", None)
40
- if obj is None:
41
- return default
42
-
43
- if isinstance(obj, dict):
44
- return obj.get(key, default)
45
-
46
- getter = getattr(obj, "get", None)
47
- if callable(getter):
48
- try:
49
- return getter(key, default)
50
- except TypeError:
51
- return default
52
-
53
- return getattr(obj, key, default) if hasattr(obj, key) else default
54
-
55
-
56
- def _get_view(ctx: Any) -> str:
57
- """Resolve the active view preference from context.
58
-
59
- Args:
60
- ctx: Click context object containing view preferences
61
-
62
- Returns:
63
- The view format string (rich, plain, json, md), defaults to 'rich'
64
- """
65
- view = get_ctx_value(ctx, "view")
66
- if view:
67
- return view
68
-
69
- fallback = get_ctx_value(ctx, "format")
70
- return fallback or "rich"
71
-
72
-
73
- def _set_view(ctx: Any, _param: Any, value: str) -> None:
74
- """Click callback to persist the `--view/--output` option.
75
-
76
- Args:
77
- ctx: Click context object to store the view preference
78
- _param: Click parameter object (unused)
79
- value: The view format string to store
80
- """
81
- if not value:
82
- return
83
- ctx.ensure_object(dict)
84
- ctx.obj["view"] = value
85
-
86
-
87
- def _set_json(ctx: Any, _param: Any, value: bool) -> None:
88
- """Click callback for the `--json` shorthand flag.
89
-
90
- Args:
91
- ctx: Click context object to store the view preference
92
- _param: Click parameter object (unused)
93
- value: Boolean flag indicating json mode
94
- """
95
- if not value:
96
- return
97
- ctx.ensure_object(dict)
98
- ctx.obj["view"] = "json"
99
-
100
-
101
- def output_flags() -> Callable[[Callable[..., Any]], Callable[..., Any]]:
102
- """Decorator to add shared output flags (`--view`, `--json`) to commands.
103
-
104
- Returns:
105
- A decorator function that adds output format options to click commands
106
- """
107
-
108
- def decorator(f: Callable[..., Any]) -> Callable[..., Any]:
109
- """Apply output flags to a click command.
110
-
111
- Args:
112
- f: Click command function to decorate.
113
-
114
- Returns:
115
- Decorated command function.
116
- """
117
- f = click.option(
118
- "--json",
119
- "json_mode",
120
- is_flag=True,
121
- expose_value=False,
122
- help="Shortcut for --view json",
123
- callback=_set_json,
124
- )(f)
125
- f = click.option(
126
- "-o",
127
- "--output",
128
- "--view",
129
- "view_opt",
130
- type=click.Choice(["rich", "plain", "json", "md"]),
131
- expose_value=False,
132
- help="Output format",
133
- callback=_set_view,
134
- )(f)
135
- return f
136
-
137
- return decorator
138
-
139
-
140
- def detect_export_format(file_path: str | Path) -> str:
141
- """Detect the export format from the file extension.
142
-
143
- Args:
144
- file_path: Path to the file to analyze
145
-
146
- Returns:
147
- The format string ('yaml' or 'json') based on file extension
148
- """
149
- path = Path(file_path)
150
- return "yaml" if path.suffix.lower() in {".yaml", ".yml"} else "json"
@@ -1,79 +0,0 @@
1
- """CLI core modules for glaip-sdk.
2
-
3
- This package contains focused modules extracted from the monolithic cli/utils.py:
4
- - context: Click context helpers, config loading, credential resolution
5
- - prompting: prompt_toolkit + questionary wrappers, validators
6
- - rendering: Rich console helpers, viewer launchers, renderer builders
7
- - output: Table/console output utilities, list rendering
8
-
9
- Authors:
10
- Raymond Christopher (raymond.christopher@gdplabs.id)
11
- Putu Ravindra Wiguna (putu.r.wiguna@gdplabs.id)
12
- """ # pylint: disable=duplicate-code
13
-
14
- from __future__ import annotations
15
-
16
- # Re-export all public APIs from submodules for convenience
17
- from glaip_sdk.cli.core.context import (
18
- bind_slash_session_context,
19
- get_client,
20
- handle_best_effort_check,
21
- restore_slash_session_context,
22
- )
23
- from glaip_sdk.cli.core.output import (
24
- coerce_to_row,
25
- detect_export_format,
26
- fetch_resource_for_export,
27
- format_datetime_fields,
28
- format_size,
29
- handle_resource_export,
30
- output_list,
31
- output_result,
32
- parse_json_line,
33
- resolve_resource,
34
- handle_ambiguous_resource,
35
- sdk_version,
36
- )
37
- from glaip_sdk.cli.core.prompting import (
38
- _fuzzy_pick_for_resources,
39
- prompt_export_choice_questionary,
40
- questionary_safe_ask,
41
- )
42
- from glaip_sdk.cli.core.rendering import (
43
- build_renderer,
44
- spinner_context,
45
- stop_spinner,
46
- update_spinner,
47
- with_client_and_spinner,
48
- )
49
-
50
- __all__ = [
51
- # Context
52
- "bind_slash_session_context",
53
- "get_client",
54
- "handle_best_effort_check",
55
- "restore_slash_session_context",
56
- # Prompting
57
- "_fuzzy_pick_for_resources",
58
- "prompt_export_choice_questionary",
59
- "questionary_safe_ask",
60
- # Rendering
61
- "build_renderer",
62
- "spinner_context",
63
- "stop_spinner",
64
- "update_spinner",
65
- "with_client_and_spinner",
66
- # Output
67
- "coerce_to_row",
68
- "detect_export_format",
69
- "fetch_resource_for_export",
70
- "format_datetime_fields",
71
- "format_size",
72
- "handle_resource_export",
73
- "output_list",
74
- "output_result",
75
- "parse_json_line",
76
- "resolve_resource",
77
- "handle_ambiguous_resource",
78
- "sdk_version",
79
- ]
@@ -1,124 +0,0 @@
1
- """CLI context helpers, config loading, and credential resolution.
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 importlib
11
- import os
12
- from collections.abc import Mapping
13
- from contextlib import contextmanager
14
- from typing import TYPE_CHECKING, Any, cast
15
-
16
- import click
17
-
18
- from glaip_sdk.cli.config import load_config
19
- from glaip_sdk.cli.hints import command_hint
20
-
21
- if TYPE_CHECKING: # pragma: no cover - import-only during type checking
22
- from glaip_sdk import Client
23
-
24
-
25
- @contextmanager
26
- def bind_slash_session_context(ctx: Any, session: Any) -> Any:
27
- """Temporarily attach a slash session to the Click context.
28
-
29
- Args:
30
- ctx: Click context object.
31
- session: SlashSession instance to bind.
32
-
33
- Yields:
34
- None - context manager for use in with statement.
35
- """
36
- ctx_obj = getattr(ctx, "obj", None)
37
- has_context = isinstance(ctx_obj, dict)
38
- previous_session = ctx_obj.get("_slash_session") if has_context else None
39
- if has_context:
40
- ctx_obj["_slash_session"] = session
41
- try:
42
- yield
43
- finally:
44
- if has_context:
45
- if previous_session is None:
46
- ctx_obj.pop("_slash_session", None)
47
- else:
48
- ctx_obj["_slash_session"] = previous_session
49
-
50
-
51
- def restore_slash_session_context(ctx_obj: dict[str, Any], previous_session: Any | None) -> None:
52
- """Restore slash session context after operation.
53
-
54
- Args:
55
- ctx_obj: Click context obj dictionary.
56
- previous_session: Previous session to restore, or None to remove.
57
- """
58
- if previous_session is None:
59
- ctx_obj.pop("_slash_session", None)
60
- else:
61
- ctx_obj["_slash_session"] = previous_session
62
-
63
-
64
- def handle_best_effort_check(
65
- check_func: Any,
66
- ) -> None:
67
- """Handle best-effort duplicate/existence checks with proper exception handling.
68
-
69
- Args:
70
- check_func: Function that performs the check and raises ClickException if duplicate found.
71
- """
72
- try:
73
- check_func()
74
- except click.ClickException:
75
- raise
76
- except Exception:
77
- # Non-fatal: best-effort duplicate check
78
- pass
79
-
80
-
81
- def get_client(ctx: Any) -> Client: # pragma: no cover
82
- """Get configured client from context and account store (ctx > account)."""
83
- # Import here to avoid circular import
84
- from glaip_sdk.cli.auth import resolve_credentials # noqa: PLC0415
85
-
86
- module = importlib.import_module("glaip_sdk")
87
- client_class = cast("type[Client]", module.Client)
88
- context_config_obj = getattr(ctx, "obj", None)
89
- context_config = context_config_obj if isinstance(context_config_obj, Mapping) else {}
90
-
91
- account_name = context_config.get("account_name")
92
- api_url, api_key, _ = resolve_credentials(
93
- account_name=account_name,
94
- api_url=context_config.get("api_url"),
95
- api_key=context_config.get("api_key"),
96
- )
97
-
98
- if not api_url or not api_key:
99
- configure_hint = command_hint("accounts add", slash_command="login", ctx=ctx)
100
- actions: list[str] = []
101
- if configure_hint:
102
- actions.append(f"Run `{configure_hint}` to add an account profile")
103
- else:
104
- actions.append("add an account with 'aip accounts add'")
105
- raise click.ClickException(f"Missing api_url/api_key. {' or '.join(actions)}.")
106
-
107
- # Get timeout from context or config
108
- timeout = context_config.get("timeout")
109
- if timeout is None:
110
- raw_timeout = os.getenv("AIP_TIMEOUT", "0") or "0"
111
- try:
112
- timeout = float(raw_timeout) if raw_timeout != "0" else None
113
- except ValueError:
114
- timeout = None
115
- if timeout is None:
116
- # Fallback to legacy config
117
- file_config = load_config() or {}
118
- timeout = file_config.get("timeout")
119
-
120
- return client_class(
121
- api_url=api_url,
122
- api_key=api_key,
123
- timeout=float(timeout or 30.0),
124
- )