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.
Files changed (156) hide show
  1. glaip_sdk/__init__.py +5 -2
  2. glaip_sdk/_version.py +10 -3
  3. glaip_sdk/agents/__init__.py +27 -0
  4. glaip_sdk/agents/base.py +1191 -0
  5. glaip_sdk/branding.py +15 -6
  6. glaip_sdk/cli/account_store.py +540 -0
  7. glaip_sdk/cli/agent_config.py +2 -6
  8. glaip_sdk/cli/auth.py +265 -45
  9. glaip_sdk/cli/commands/__init__.py +2 -2
  10. glaip_sdk/cli/commands/accounts.py +746 -0
  11. glaip_sdk/cli/commands/agents.py +251 -173
  12. glaip_sdk/cli/commands/common_config.py +101 -0
  13. glaip_sdk/cli/commands/configure.py +735 -143
  14. glaip_sdk/cli/commands/mcps.py +266 -134
  15. glaip_sdk/cli/commands/models.py +13 -9
  16. glaip_sdk/cli/commands/tools.py +67 -88
  17. glaip_sdk/cli/commands/transcripts.py +755 -0
  18. glaip_sdk/cli/commands/update.py +3 -8
  19. glaip_sdk/cli/config.py +49 -7
  20. glaip_sdk/cli/constants.py +38 -0
  21. glaip_sdk/cli/context.py +8 -0
  22. glaip_sdk/cli/core/__init__.py +79 -0
  23. glaip_sdk/cli/core/context.py +124 -0
  24. glaip_sdk/cli/core/output.py +846 -0
  25. glaip_sdk/cli/core/prompting.py +649 -0
  26. glaip_sdk/cli/core/rendering.py +187 -0
  27. glaip_sdk/cli/display.py +45 -32
  28. glaip_sdk/cli/hints.py +57 -0
  29. glaip_sdk/cli/io.py +14 -17
  30. glaip_sdk/cli/main.py +232 -143
  31. glaip_sdk/cli/masking.py +21 -33
  32. glaip_sdk/cli/mcp_validators.py +5 -15
  33. glaip_sdk/cli/pager.py +12 -19
  34. glaip_sdk/cli/parsers/__init__.py +1 -3
  35. glaip_sdk/cli/parsers/json_input.py +11 -22
  36. glaip_sdk/cli/resolution.py +3 -9
  37. glaip_sdk/cli/rich_helpers.py +1 -3
  38. glaip_sdk/cli/slash/__init__.py +0 -9
  39. glaip_sdk/cli/slash/accounts_controller.py +578 -0
  40. glaip_sdk/cli/slash/accounts_shared.py +75 -0
  41. glaip_sdk/cli/slash/agent_session.py +65 -29
  42. glaip_sdk/cli/slash/prompt.py +24 -10
  43. glaip_sdk/cli/slash/remote_runs_controller.py +566 -0
  44. glaip_sdk/cli/slash/session.py +807 -225
  45. glaip_sdk/cli/slash/tui/__init__.py +9 -0
  46. glaip_sdk/cli/slash/tui/accounts.tcss +86 -0
  47. glaip_sdk/cli/slash/tui/accounts_app.py +876 -0
  48. glaip_sdk/cli/slash/tui/background_tasks.py +72 -0
  49. glaip_sdk/cli/slash/tui/loading.py +58 -0
  50. glaip_sdk/cli/slash/tui/remote_runs_app.py +628 -0
  51. glaip_sdk/cli/transcript/__init__.py +12 -52
  52. glaip_sdk/cli/transcript/cache.py +258 -60
  53. glaip_sdk/cli/transcript/capture.py +72 -21
  54. glaip_sdk/cli/transcript/history.py +815 -0
  55. glaip_sdk/cli/transcript/launcher.py +1 -3
  56. glaip_sdk/cli/transcript/viewer.py +79 -499
  57. glaip_sdk/cli/update_notifier.py +177 -24
  58. glaip_sdk/cli/utils.py +242 -1308
  59. glaip_sdk/cli/validators.py +16 -18
  60. glaip_sdk/client/__init__.py +2 -1
  61. glaip_sdk/client/_agent_payloads.py +53 -37
  62. glaip_sdk/client/agent_runs.py +147 -0
  63. glaip_sdk/client/agents.py +320 -92
  64. glaip_sdk/client/base.py +78 -35
  65. glaip_sdk/client/main.py +19 -10
  66. glaip_sdk/client/mcps.py +123 -15
  67. glaip_sdk/client/run_rendering.py +136 -101
  68. glaip_sdk/client/shared.py +21 -0
  69. glaip_sdk/client/tools.py +163 -34
  70. glaip_sdk/client/validators.py +20 -48
  71. glaip_sdk/config/constants.py +11 -0
  72. glaip_sdk/exceptions.py +1 -3
  73. glaip_sdk/mcps/__init__.py +21 -0
  74. glaip_sdk/mcps/base.py +345 -0
  75. glaip_sdk/models/__init__.py +90 -0
  76. glaip_sdk/models/agent.py +47 -0
  77. glaip_sdk/models/agent_runs.py +116 -0
  78. glaip_sdk/models/common.py +42 -0
  79. glaip_sdk/models/mcp.py +33 -0
  80. glaip_sdk/models/tool.py +33 -0
  81. glaip_sdk/payload_schemas/__init__.py +1 -13
  82. glaip_sdk/payload_schemas/agent.py +1 -3
  83. glaip_sdk/registry/__init__.py +55 -0
  84. glaip_sdk/registry/agent.py +164 -0
  85. glaip_sdk/registry/base.py +139 -0
  86. glaip_sdk/registry/mcp.py +253 -0
  87. glaip_sdk/registry/tool.py +232 -0
  88. glaip_sdk/rich_components.py +58 -2
  89. glaip_sdk/runner/__init__.py +59 -0
  90. glaip_sdk/runner/base.py +84 -0
  91. glaip_sdk/runner/deps.py +115 -0
  92. glaip_sdk/runner/langgraph.py +706 -0
  93. glaip_sdk/runner/mcp_adapter/__init__.py +13 -0
  94. glaip_sdk/runner/mcp_adapter/base_mcp_adapter.py +43 -0
  95. glaip_sdk/runner/mcp_adapter/langchain_mcp_adapter.py +257 -0
  96. glaip_sdk/runner/mcp_adapter/mcp_config_builder.py +95 -0
  97. glaip_sdk/runner/tool_adapter/__init__.py +18 -0
  98. glaip_sdk/runner/tool_adapter/base_tool_adapter.py +44 -0
  99. glaip_sdk/runner/tool_adapter/langchain_tool_adapter.py +219 -0
  100. glaip_sdk/tools/__init__.py +22 -0
  101. glaip_sdk/tools/base.py +435 -0
  102. glaip_sdk/utils/__init__.py +58 -12
  103. glaip_sdk/utils/a2a/__init__.py +34 -0
  104. glaip_sdk/utils/a2a/event_processor.py +188 -0
  105. glaip_sdk/utils/agent_config.py +4 -14
  106. glaip_sdk/utils/bundler.py +267 -0
  107. glaip_sdk/utils/client.py +111 -0
  108. glaip_sdk/utils/client_utils.py +46 -28
  109. glaip_sdk/utils/datetime_helpers.py +58 -0
  110. glaip_sdk/utils/discovery.py +78 -0
  111. glaip_sdk/utils/display.py +25 -21
  112. glaip_sdk/utils/export.py +143 -0
  113. glaip_sdk/utils/general.py +1 -36
  114. glaip_sdk/utils/import_export.py +15 -16
  115. glaip_sdk/utils/import_resolver.py +492 -0
  116. glaip_sdk/utils/instructions.py +101 -0
  117. glaip_sdk/utils/rendering/__init__.py +115 -1
  118. glaip_sdk/utils/rendering/formatting.py +7 -35
  119. glaip_sdk/utils/rendering/layout/__init__.py +64 -0
  120. glaip_sdk/utils/rendering/{renderer → layout}/panels.py +10 -3
  121. glaip_sdk/utils/rendering/{renderer → layout}/progress.py +73 -12
  122. glaip_sdk/utils/rendering/layout/summary.py +74 -0
  123. glaip_sdk/utils/rendering/layout/transcript.py +606 -0
  124. glaip_sdk/utils/rendering/models.py +3 -6
  125. glaip_sdk/utils/rendering/renderer/__init__.py +9 -49
  126. glaip_sdk/utils/rendering/renderer/base.py +258 -1577
  127. glaip_sdk/utils/rendering/renderer/config.py +1 -5
  128. glaip_sdk/utils/rendering/renderer/debug.py +30 -34
  129. glaip_sdk/utils/rendering/renderer/factory.py +138 -0
  130. glaip_sdk/utils/rendering/renderer/stream.py +10 -51
  131. glaip_sdk/utils/rendering/renderer/summary_window.py +79 -0
  132. glaip_sdk/utils/rendering/renderer/thinking.py +273 -0
  133. glaip_sdk/utils/rendering/renderer/toggle.py +1 -3
  134. glaip_sdk/utils/rendering/renderer/tool_panels.py +442 -0
  135. glaip_sdk/utils/rendering/renderer/transcript_mode.py +162 -0
  136. glaip_sdk/utils/rendering/state.py +204 -0
  137. glaip_sdk/utils/rendering/step_tree_state.py +1 -3
  138. glaip_sdk/utils/rendering/steps/__init__.py +34 -0
  139. glaip_sdk/utils/rendering/{steps.py → steps/event_processor.py} +76 -517
  140. glaip_sdk/utils/rendering/steps/format.py +176 -0
  141. glaip_sdk/utils/rendering/steps/manager.py +387 -0
  142. glaip_sdk/utils/rendering/timing.py +36 -0
  143. glaip_sdk/utils/rendering/viewer/__init__.py +21 -0
  144. glaip_sdk/utils/rendering/viewer/presenter.py +184 -0
  145. glaip_sdk/utils/resource_refs.py +29 -26
  146. glaip_sdk/utils/runtime_config.py +425 -0
  147. glaip_sdk/utils/serialization.py +32 -46
  148. glaip_sdk/utils/sync.py +142 -0
  149. glaip_sdk/utils/tool_detection.py +33 -0
  150. glaip_sdk/utils/validation.py +20 -28
  151. {glaip_sdk-0.1.0.dist-info → glaip_sdk-0.6.10.dist-info}/METADATA +42 -4
  152. glaip_sdk-0.6.10.dist-info/RECORD +159 -0
  153. {glaip_sdk-0.1.0.dist-info → glaip_sdk-0.6.10.dist-info}/WHEEL +1 -1
  154. glaip_sdk/models.py +0 -259
  155. glaip_sdk-0.1.0.dist-info/RECORD +0 -82
  156. {glaip_sdk-0.1.0.dist-info → glaip_sdk-0.6.10.dist-info}/entry_points.txt +0 -0
glaip_sdk/cli/masking.py CHANGED
@@ -6,9 +6,10 @@ Authors:
6
6
 
7
7
  from __future__ import annotations
8
8
 
9
- import os
10
9
  from typing import Any
11
10
 
11
+ from glaip_sdk.cli.constants import MASK_SENSITIVE_FIELDS, MASKING_ENABLED
12
+
12
13
  __all__ = [
13
14
  "mask_payload",
14
15
  "mask_rows",
@@ -16,20 +17,9 @@ __all__ = [
16
17
  "_mask_any",
17
18
  "_maybe_mask_row",
18
19
  "_resolve_mask_fields",
20
+ "mask_api_key_display",
19
21
  ]
20
22
 
21
- _DEFAULT_MASK_FIELDS = {
22
- "api_key",
23
- "apikey",
24
- "token",
25
- "access_token",
26
- "secret",
27
- "client_secret",
28
- "password",
29
- "private_key",
30
- "bearer",
31
- }
32
-
33
23
 
34
24
  def _mask_value(raw: Any) -> str:
35
25
  """Return a masked representation of the provided value.
@@ -90,22 +80,10 @@ def _maybe_mask_row(row: dict[str, Any], mask_fields: set[str]) -> dict[str, Any
90
80
 
91
81
 
92
82
  def _resolve_mask_fields() -> set[str]:
93
- """Resolve the set of sensitive fields to mask based on environment.
94
-
95
- Returns:
96
- set[str]: Set of field names to mask. Empty set if masking is disabled
97
- via AIP_MASK_OFF environment variable, custom fields from
98
- AIP_MASK_FIELDS, or default fields if neither is set.
99
- """
100
- if os.getenv("AIP_MASK_OFF", "0") in {"1", "true", "on", "yes"}:
83
+ """Return the configured set of fields that should be masked."""
84
+ if not MASKING_ENABLED:
101
85
  return set()
102
-
103
- env_fields = (os.getenv("AIP_MASK_FIELDS") or "").strip()
104
- if env_fields:
105
- parts = [part.strip().lower() for part in env_fields.split(",") if part.strip()]
106
- return set(parts)
107
-
108
- return set(_DEFAULT_MASK_FIELDS)
86
+ return set(MASK_SENSITIVE_FIELDS)
109
87
 
110
88
 
111
89
  def mask_payload(payload: Any) -> Any:
@@ -115,9 +93,7 @@ def mask_payload(payload: Any) -> Any:
115
93
  payload: Any data structure (dict, list, or primitive) to mask.
116
94
 
117
95
  Returns:
118
- Any: The payload with sensitive fields masked based on environment
119
- configuration. Returns original payload if masking is disabled
120
- or if an error occurs during masking.
96
+ Any: The payload with sensitive fields masked based on configuration.
121
97
  """
122
98
  mask_fields = _resolve_mask_fields()
123
99
  if not mask_fields:
@@ -136,8 +112,8 @@ def mask_rows(rows: list[dict[str, Any]]) -> list[dict[str, Any]]:
136
112
 
137
113
  Returns:
138
114
  list[dict[str, Any]]: List of rows with sensitive fields masked based
139
- on environment configuration. Returns original
140
- rows if masking is disabled or if an error occurs.
115
+ on configuration. Returns original rows if
116
+ masking is disabled or if an error occurs.
141
117
  """
142
118
  mask_fields = _resolve_mask_fields()
143
119
  if not mask_fields:
@@ -146,3 +122,15 @@ def mask_rows(rows: list[dict[str, Any]]) -> list[dict[str, Any]]:
146
122
  return [_maybe_mask_row(row, mask_fields) for row in rows]
147
123
  except Exception:
148
124
  return rows
125
+
126
+
127
+ def mask_api_key_display(value: str | None) -> str:
128
+ """Mask API keys for CLI display while preserving readability for short keys."""
129
+ if not value:
130
+ return ""
131
+ length = len(value)
132
+ if length <= 4:
133
+ return "***"
134
+ if length <= 8:
135
+ return value[:1] + "••••" + value[-1:]
136
+ return value[:4] + "••••" + value[-4:]
@@ -79,9 +79,7 @@ def validate_mcp_config_structure(
79
79
  requirement = "Missing required 'url' field with a non-empty string value."
80
80
  if transport:
81
81
  requirement += f" Required for transport '{transport}'."
82
- raise click.ClickException(
83
- format_validation_error(f"Invalid {source} value", requirement)
84
- )
82
+ raise click.ClickException(format_validation_error(f"Invalid {source} value", requirement))
85
83
 
86
84
  parsed_url = urlparse(url_value)
87
85
  if parsed_url.scheme not in {"http", "https"} or not parsed_url.netloc:
@@ -95,9 +93,7 @@ def validate_mcp_config_structure(
95
93
  return config
96
94
 
97
95
 
98
- def _validate_headers_mapping(
99
- headers: Any, *, source: str, context: str
100
- ) -> dict[str, str]:
96
+ def _validate_headers_mapping(headers: Any, *, source: str, context: str) -> dict[str, str]:
101
97
  """Validate headers mapping for authentication.
102
98
 
103
99
  Args:
@@ -156,9 +152,7 @@ def _validate_bearer_token_auth(auth: dict[str, Any], source: str) -> dict[str,
156
152
  if isinstance(token, str) and token.strip():
157
153
  return {"type": "bearer-token", "token": token}
158
154
  headers = auth.get("headers")
159
- normalized_headers = _validate_headers_mapping(
160
- headers, source=source, context="bearer-token authentication"
161
- )
155
+ normalized_headers = _validate_headers_mapping(headers, source=source, context="bearer-token authentication")
162
156
  return {"type": "bearer-token", "headers": normalized_headers}
163
157
 
164
158
 
@@ -177,9 +171,7 @@ def _validate_api_key_auth(auth: dict[str, Any], source: str) -> dict[str, Any]:
177
171
  """
178
172
  headers = auth.get("headers")
179
173
  if headers is not None:
180
- normalized_headers = _validate_headers_mapping(
181
- headers, source=source, context="api-key authentication"
182
- )
174
+ normalized_headers = _validate_headers_mapping(headers, source=source, context="api-key authentication")
183
175
  return {"type": "api-key", "headers": normalized_headers}
184
176
 
185
177
  key = auth.get("key")
@@ -215,9 +207,7 @@ def _validate_custom_header_auth(auth: dict[str, Any], source: str) -> dict[str,
215
207
  click.ClickException: If custom-header structure is invalid
216
208
  """
217
209
  headers = auth.get("headers")
218
- normalized_headers = _validate_headers_mapping(
219
- headers, source=source, context="custom-header authentication"
220
- )
210
+ normalized_headers = _validate_headers_mapping(headers, source=source, context="custom-header authentication")
221
211
  return {"type": "custom-header", "headers": normalized_headers}
222
212
 
223
213
 
glaip_sdk/cli/pager.py CHANGED
@@ -19,6 +19,8 @@ from typing import Any
19
19
 
20
20
  from rich.console import Console
21
21
 
22
+ from glaip_sdk.cli.constants import PAGER_HEADER_ENABLED, PAGER_MODE, PAGER_WRAP_LINES
23
+
22
24
  __all__ = [
23
25
  "console",
24
26
  "_prepare_pager_env",
@@ -64,8 +66,7 @@ def _prepare_pager_env(clear_on_exit: bool = True) -> None:
64
66
  -R : pass ANSI color escapes
65
67
  -S : chop long lines (horizontal scroll with ←/→)
66
68
  (No -F, no -X) so we open a full-screen pager and clear on exit.
67
- Toggle wrapping with AIP_PAGER_WRAP=1 to drop -S.
68
- Power users can override via AIP_LESS_FLAGS.
69
+ Toggle wrapping via `PAGER_WRAP_LINES` (True drops -S).
69
70
 
70
71
  Args:
71
72
  clear_on_exit: Whether to clear the pager on exit (default: True)
@@ -75,10 +76,9 @@ def _prepare_pager_env(clear_on_exit: bool = True) -> None:
75
76
  """
76
77
  os.environ.pop("LESSSECURE", None)
77
78
  if os.getenv("LESS") is None:
78
- want_wrap = os.getenv("AIP_PAGER_WRAP", "0") == "1"
79
- base = "-R" if want_wrap else "-RS"
79
+ base = "-R" if PAGER_WRAP_LINES else "-RS"
80
80
  default_flags = base if clear_on_exit else (base + "FX")
81
- os.environ["LESS"] = os.getenv("AIP_LESS_FLAGS", default_flags)
81
+ os.environ["LESS"] = default_flags
82
82
 
83
83
 
84
84
  def _render_ansi(renderable: Any) -> str:
@@ -111,8 +111,7 @@ def _pager_header() -> str:
111
111
  Returns:
112
112
  str: Header text containing navigation help, or empty string if disabled
113
113
  """
114
- v = (os.getenv("AIP_PAGER_HEADER", "1") or "1").strip().lower()
115
- if v in {"0", "false", "off"}:
114
+ if not PAGER_HEADER_ENABLED:
116
115
  return ""
117
116
  return "\n".join(
118
117
  [
@@ -156,9 +155,7 @@ def _resolve_pager_command() -> tuple[list[str] | None, str | None]:
156
155
  return pager_cmd, less_path
157
156
 
158
157
 
159
- def _run_less_pager(
160
- pager_cmd: list[str] | None, less_path: str | None, tmp_path: str
161
- ) -> None:
158
+ def _run_less_pager(pager_cmd: list[str] | None, less_path: str | None, tmp_path: str) -> None:
162
159
  """Run less pager with appropriate command and flags.
163
160
 
164
161
  Args:
@@ -195,9 +192,7 @@ def _run_more_pager(tmp_path: str) -> None:
195
192
  raise FileNotFoundError("more command not found")
196
193
 
197
194
 
198
- def _run_pager_with_temp_file(
199
- pager_runner: Callable[[str], None], ansi_text: str
200
- ) -> bool:
195
+ def _run_pager_with_temp_file(pager_runner: Callable[[str], None], ansi_text: str) -> bool:
201
196
  """Run a pager using a temporary file containing the content.
202
197
 
203
198
  Args:
@@ -239,9 +234,7 @@ def _page_with_system_pager(ansi_text: str) -> bool:
239
234
  pager_cmd, less_path = _resolve_pager_command()
240
235
 
241
236
  if pager_cmd or less_path:
242
- return _run_pager_with_temp_file(
243
- lambda tmp_path: _run_less_pager(pager_cmd, less_path, tmp_path), ansi_text
244
- )
237
+ return _run_pager_with_temp_file(lambda tmp_path: _run_less_pager(pager_cmd, less_path, tmp_path), ansi_text)
245
238
 
246
239
  if platform.system().lower().startswith("win"):
247
240
  return False
@@ -260,10 +253,10 @@ def _should_page_output(row_count: int, is_tty: bool) -> bool:
260
253
  bool: True if output should be paginated, False otherwise
261
254
  """
262
255
  active_console = _get_console()
263
- pager_env = (os.getenv("AIP_PAGER", "auto") or "auto").lower()
264
- if pager_env in ("0", "off", "false"):
256
+ pager_mode = (PAGER_MODE or "auto").lower()
257
+ if pager_mode in ("0", "off", "false"):
265
258
  return False
266
- if pager_env in ("1", "on", "true"):
259
+ if pager_mode in ("1", "on", "true"):
267
260
  return is_tty
268
261
  try:
269
262
  term_h = active_console.size.height or 24
@@ -4,6 +4,4 @@ Authors:
4
4
  Putu Ravindra Wiguna (putu.r.wiguna@gdplabs.id)
5
5
  """
6
6
 
7
- from glaip_sdk.cli.parsers.json_input import parse_json_input
8
-
9
- __all__ = ["parse_json_input"]
7
+ __all__: list[str] = []
@@ -33,9 +33,7 @@ def _looks_like_file_path(value: str) -> bool:
33
33
  )
34
34
 
35
35
 
36
- def _format_file_error(
37
- prefix: str, file_path_str: str, resolved_path: Path, *, detail: str | None = None
38
- ) -> str:
36
+ def _format_file_error(prefix: str, file_path_str: str, resolved_path: Path, *, detail: str | None = None) -> str:
39
37
  r"""Format a file-related error message with path context.
40
38
 
41
39
  Args:
@@ -77,16 +75,12 @@ def _parse_json_from_file(file_path_str: str) -> Any:
77
75
 
78
76
  # Check if file exists and is a regular file
79
77
  if not file_path.is_file():
80
- raise click.ClickException(
81
- _format_file_error("File not found or not a file", file_path_str, file_path)
82
- )
78
+ raise click.ClickException(_format_file_error("File not found or not a file", file_path_str, file_path))
83
79
 
84
80
  # Check if file is readable
85
81
  if not os.access(file_path, os.R_OK):
86
82
  raise click.ClickException(
87
- _format_file_error(
88
- "File not readable (permission denied)", file_path_str, file_path
89
- )
83
+ _format_file_error("File not readable (permission denied)", file_path_str, file_path)
90
84
  )
91
85
 
92
86
  # Read file content
@@ -94,16 +88,12 @@ def _parse_json_from_file(file_path_str: str) -> Any:
94
88
  content = file_path.read_text(encoding="utf-8")
95
89
  except Exception as e:
96
90
  raise click.ClickException(
97
- _format_file_error(
98
- "Error reading file", file_path_str, file_path, detail=f"Error: {e}"
99
- )
100
- )
91
+ _format_file_error("Error reading file", file_path_str, file_path, detail=f"Error: {e}")
92
+ ) from e
101
93
 
102
94
  # Check for empty content
103
95
  if not content.strip():
104
- raise click.ClickException(
105
- _format_file_error("File is empty", file_path_str, file_path)
106
- )
96
+ raise click.ClickException(_format_file_error("File is empty", file_path_str, file_path))
107
97
 
108
98
  # Determine file format and parse accordingly
109
99
  file_ext = file_path.suffix.lower()
@@ -120,7 +110,7 @@ def _parse_json_from_file(file_path_str: str) -> Any:
120
110
  file_path,
121
111
  detail=f"Error: {e}",
122
112
  )
123
- )
113
+ ) from e
124
114
  else:
125
115
  # Default to JSON parsing
126
116
  try:
@@ -133,7 +123,7 @@ def _parse_json_from_file(file_path_str: str) -> Any:
133
123
  file_path,
134
124
  detail=f"Error: {e.msg} at line {e.lineno}, column {e.colno}",
135
125
  )
136
- )
126
+ ) from e
137
127
 
138
128
 
139
129
  def parse_json_input(value: str | None) -> Any:
@@ -180,9 +170,8 @@ def parse_json_input(value: str | None) -> Any:
180
170
  f"Error: {e.msg} at line {e.lineno}, column {e.colno}\n"
181
171
  f"\nšŸ’” Did you mean to load this from a file? "
182
172
  f"File-based config values should start with @ (e.g., @{trimmed})"
183
- )
173
+ ) from e
184
174
 
185
175
  raise click.ClickException(
186
- f"Invalid JSON in inline value\n"
187
- f"Error: {e.msg} at line {e.lineno}, column {e.colno}"
188
- )
176
+ f"Invalid JSON in inline value\nError: {e.msg} at line {e.lineno}, column {e.colno}"
177
+ ) from e
@@ -51,14 +51,8 @@ def resolve_resource_reference(
51
51
  click.ClickException: If resolution fails.
52
52
  """
53
53
  try:
54
- message = (
55
- spinner_message
56
- if spinner_message is not None
57
- else f"[bold blue]Fetching {label}…[/bold blue]"
58
- )
59
- with spinner_context(
60
- ctx, message, spinner_style=ACCENT_STYLE
61
- ) as status_indicator:
54
+ message = spinner_message if spinner_message is not None else f"[bold blue]Fetching {label}…[/bold blue]"
55
+ with spinner_context(ctx, message, spinner_style=ACCENT_STYLE) as status_indicator:
62
56
  return resolve_resource(
63
57
  ctx,
64
58
  reference,
@@ -70,4 +64,4 @@ def resolve_resource_reference(
70
64
  status_indicator=status_indicator,
71
65
  )
72
66
  except Exception as e:
73
- raise click.ClickException(f"Failed to resolve {resource_type.lower()}: {e}")
67
+ raise click.ClickException(f"Failed to resolve {resource_type.lower()}: {e}") from e
@@ -21,9 +21,7 @@ def markup_text(message: str, **kwargs: Any) -> Text:
21
21
  return Text(message, **kwargs)
22
22
 
23
23
 
24
- def print_markup(
25
- message: str, *, console: Console | None = None, **kwargs: Any
26
- ) -> None:
24
+ def print_markup(message: str, *, console: Console | None = None, **kwargs: Any) -> None:
27
25
  """Print markup-aware text to the provided console (default: new Console)."""
28
26
  target_console = console or Console()
29
27
  target_console.print(markup_text(message, **kwargs))
@@ -6,19 +6,10 @@ Authors:
6
6
 
7
7
  from glaip_sdk.cli.commands.agents import get as agents_get_command
8
8
  from glaip_sdk.cli.commands.agents import run as agents_run_command
9
- from glaip_sdk.cli.commands.configure import configure_command, load_config
10
- from glaip_sdk.cli.slash.agent_session import AgentRunSession
11
- from glaip_sdk.cli.slash.prompt import _HAS_PROMPT_TOOLKIT
12
9
  from glaip_sdk.cli.slash.session import SlashSession
13
- from glaip_sdk.cli.utils import get_client
14
10
 
15
11
  __all__ = [
16
- "AgentRunSession",
17
12
  "SlashSession",
18
- "_HAS_PROMPT_TOOLKIT",
19
13
  "agents_get_command",
20
14
  "agents_run_command",
21
- "configure_command",
22
- "get_client",
23
- "load_config",
24
15
  ]