glaip-sdk 0.1.0__py3-none-any.whl ā 0.6.10__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- glaip_sdk/__init__.py +5 -2
- glaip_sdk/_version.py +10 -3
- glaip_sdk/agents/__init__.py +27 -0
- glaip_sdk/agents/base.py +1191 -0
- glaip_sdk/branding.py +15 -6
- glaip_sdk/cli/account_store.py +540 -0
- glaip_sdk/cli/agent_config.py +2 -6
- glaip_sdk/cli/auth.py +265 -45
- glaip_sdk/cli/commands/__init__.py +2 -2
- glaip_sdk/cli/commands/accounts.py +746 -0
- glaip_sdk/cli/commands/agents.py +251 -173
- glaip_sdk/cli/commands/common_config.py +101 -0
- glaip_sdk/cli/commands/configure.py +735 -143
- glaip_sdk/cli/commands/mcps.py +266 -134
- glaip_sdk/cli/commands/models.py +13 -9
- glaip_sdk/cli/commands/tools.py +67 -88
- glaip_sdk/cli/commands/transcripts.py +755 -0
- glaip_sdk/cli/commands/update.py +3 -8
- glaip_sdk/cli/config.py +49 -7
- glaip_sdk/cli/constants.py +38 -0
- glaip_sdk/cli/context.py +8 -0
- glaip_sdk/cli/core/__init__.py +79 -0
- glaip_sdk/cli/core/context.py +124 -0
- glaip_sdk/cli/core/output.py +846 -0
- glaip_sdk/cli/core/prompting.py +649 -0
- glaip_sdk/cli/core/rendering.py +187 -0
- glaip_sdk/cli/display.py +45 -32
- glaip_sdk/cli/hints.py +57 -0
- glaip_sdk/cli/io.py +14 -17
- glaip_sdk/cli/main.py +232 -143
- glaip_sdk/cli/masking.py +21 -33
- glaip_sdk/cli/mcp_validators.py +5 -15
- glaip_sdk/cli/pager.py +12 -19
- glaip_sdk/cli/parsers/__init__.py +1 -3
- glaip_sdk/cli/parsers/json_input.py +11 -22
- glaip_sdk/cli/resolution.py +3 -9
- glaip_sdk/cli/rich_helpers.py +1 -3
- glaip_sdk/cli/slash/__init__.py +0 -9
- glaip_sdk/cli/slash/accounts_controller.py +578 -0
- glaip_sdk/cli/slash/accounts_shared.py +75 -0
- glaip_sdk/cli/slash/agent_session.py +65 -29
- glaip_sdk/cli/slash/prompt.py +24 -10
- glaip_sdk/cli/slash/remote_runs_controller.py +566 -0
- glaip_sdk/cli/slash/session.py +807 -225
- glaip_sdk/cli/slash/tui/__init__.py +9 -0
- glaip_sdk/cli/slash/tui/accounts.tcss +86 -0
- glaip_sdk/cli/slash/tui/accounts_app.py +876 -0
- glaip_sdk/cli/slash/tui/background_tasks.py +72 -0
- glaip_sdk/cli/slash/tui/loading.py +58 -0
- glaip_sdk/cli/slash/tui/remote_runs_app.py +628 -0
- glaip_sdk/cli/transcript/__init__.py +12 -52
- glaip_sdk/cli/transcript/cache.py +258 -60
- glaip_sdk/cli/transcript/capture.py +72 -21
- glaip_sdk/cli/transcript/history.py +815 -0
- glaip_sdk/cli/transcript/launcher.py +1 -3
- glaip_sdk/cli/transcript/viewer.py +79 -499
- glaip_sdk/cli/update_notifier.py +177 -24
- glaip_sdk/cli/utils.py +242 -1308
- glaip_sdk/cli/validators.py +16 -18
- glaip_sdk/client/__init__.py +2 -1
- glaip_sdk/client/_agent_payloads.py +53 -37
- glaip_sdk/client/agent_runs.py +147 -0
- glaip_sdk/client/agents.py +320 -92
- glaip_sdk/client/base.py +78 -35
- glaip_sdk/client/main.py +19 -10
- glaip_sdk/client/mcps.py +123 -15
- glaip_sdk/client/run_rendering.py +136 -101
- glaip_sdk/client/shared.py +21 -0
- glaip_sdk/client/tools.py +163 -34
- glaip_sdk/client/validators.py +20 -48
- glaip_sdk/config/constants.py +11 -0
- glaip_sdk/exceptions.py +1 -3
- glaip_sdk/mcps/__init__.py +21 -0
- glaip_sdk/mcps/base.py +345 -0
- glaip_sdk/models/__init__.py +90 -0
- glaip_sdk/models/agent.py +47 -0
- glaip_sdk/models/agent_runs.py +116 -0
- glaip_sdk/models/common.py +42 -0
- glaip_sdk/models/mcp.py +33 -0
- glaip_sdk/models/tool.py +33 -0
- glaip_sdk/payload_schemas/__init__.py +1 -13
- glaip_sdk/payload_schemas/agent.py +1 -3
- glaip_sdk/registry/__init__.py +55 -0
- glaip_sdk/registry/agent.py +164 -0
- glaip_sdk/registry/base.py +139 -0
- glaip_sdk/registry/mcp.py +253 -0
- glaip_sdk/registry/tool.py +232 -0
- glaip_sdk/rich_components.py +58 -2
- glaip_sdk/runner/__init__.py +59 -0
- glaip_sdk/runner/base.py +84 -0
- glaip_sdk/runner/deps.py +115 -0
- glaip_sdk/runner/langgraph.py +706 -0
- glaip_sdk/runner/mcp_adapter/__init__.py +13 -0
- glaip_sdk/runner/mcp_adapter/base_mcp_adapter.py +43 -0
- glaip_sdk/runner/mcp_adapter/langchain_mcp_adapter.py +257 -0
- glaip_sdk/runner/mcp_adapter/mcp_config_builder.py +95 -0
- glaip_sdk/runner/tool_adapter/__init__.py +18 -0
- glaip_sdk/runner/tool_adapter/base_tool_adapter.py +44 -0
- glaip_sdk/runner/tool_adapter/langchain_tool_adapter.py +219 -0
- glaip_sdk/tools/__init__.py +22 -0
- glaip_sdk/tools/base.py +435 -0
- glaip_sdk/utils/__init__.py +58 -12
- glaip_sdk/utils/a2a/__init__.py +34 -0
- glaip_sdk/utils/a2a/event_processor.py +188 -0
- glaip_sdk/utils/agent_config.py +4 -14
- glaip_sdk/utils/bundler.py +267 -0
- glaip_sdk/utils/client.py +111 -0
- glaip_sdk/utils/client_utils.py +46 -28
- glaip_sdk/utils/datetime_helpers.py +58 -0
- glaip_sdk/utils/discovery.py +78 -0
- glaip_sdk/utils/display.py +25 -21
- glaip_sdk/utils/export.py +143 -0
- glaip_sdk/utils/general.py +1 -36
- glaip_sdk/utils/import_export.py +15 -16
- glaip_sdk/utils/import_resolver.py +492 -0
- glaip_sdk/utils/instructions.py +101 -0
- glaip_sdk/utils/rendering/__init__.py +115 -1
- glaip_sdk/utils/rendering/formatting.py +7 -35
- glaip_sdk/utils/rendering/layout/__init__.py +64 -0
- glaip_sdk/utils/rendering/{renderer ā layout}/panels.py +10 -3
- glaip_sdk/utils/rendering/{renderer ā layout}/progress.py +73 -12
- glaip_sdk/utils/rendering/layout/summary.py +74 -0
- glaip_sdk/utils/rendering/layout/transcript.py +606 -0
- glaip_sdk/utils/rendering/models.py +3 -6
- glaip_sdk/utils/rendering/renderer/__init__.py +9 -49
- glaip_sdk/utils/rendering/renderer/base.py +258 -1577
- glaip_sdk/utils/rendering/renderer/config.py +1 -5
- glaip_sdk/utils/rendering/renderer/debug.py +30 -34
- glaip_sdk/utils/rendering/renderer/factory.py +138 -0
- glaip_sdk/utils/rendering/renderer/stream.py +10 -51
- glaip_sdk/utils/rendering/renderer/summary_window.py +79 -0
- glaip_sdk/utils/rendering/renderer/thinking.py +273 -0
- glaip_sdk/utils/rendering/renderer/toggle.py +1 -3
- glaip_sdk/utils/rendering/renderer/tool_panels.py +442 -0
- glaip_sdk/utils/rendering/renderer/transcript_mode.py +162 -0
- glaip_sdk/utils/rendering/state.py +204 -0
- glaip_sdk/utils/rendering/step_tree_state.py +1 -3
- glaip_sdk/utils/rendering/steps/__init__.py +34 -0
- glaip_sdk/utils/rendering/{steps.py ā steps/event_processor.py} +76 -517
- glaip_sdk/utils/rendering/steps/format.py +176 -0
- glaip_sdk/utils/rendering/steps/manager.py +387 -0
- glaip_sdk/utils/rendering/timing.py +36 -0
- glaip_sdk/utils/rendering/viewer/__init__.py +21 -0
- glaip_sdk/utils/rendering/viewer/presenter.py +184 -0
- glaip_sdk/utils/resource_refs.py +29 -26
- glaip_sdk/utils/runtime_config.py +425 -0
- glaip_sdk/utils/serialization.py +32 -46
- glaip_sdk/utils/sync.py +142 -0
- glaip_sdk/utils/tool_detection.py +33 -0
- glaip_sdk/utils/validation.py +20 -28
- {glaip_sdk-0.1.0.dist-info ā glaip_sdk-0.6.10.dist-info}/METADATA +42 -4
- glaip_sdk-0.6.10.dist-info/RECORD +159 -0
- {glaip_sdk-0.1.0.dist-info ā glaip_sdk-0.6.10.dist-info}/WHEEL +1 -1
- glaip_sdk/models.py +0 -259
- glaip_sdk-0.1.0.dist-info/RECORD +0 -82
- {glaip_sdk-0.1.0.dist-info ā glaip_sdk-0.6.10.dist-info}/entry_points.txt +0 -0
glaip_sdk/cli/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
|
-
"""
|
|
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
|
|
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
|
|
140
|
-
|
|
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:]
|
glaip_sdk/cli/mcp_validators.py
CHANGED
|
@@ -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
|
|
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
|
-
|
|
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"] =
|
|
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
|
-
|
|
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
|
-
|
|
264
|
-
if
|
|
256
|
+
pager_mode = (PAGER_MODE or "auto").lower()
|
|
257
|
+
if pager_mode in ("0", "off", "false"):
|
|
265
258
|
return False
|
|
266
|
-
if
|
|
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
|
|
@@ -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
|
-
|
|
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\
|
|
187
|
-
|
|
188
|
-
)
|
|
176
|
+
f"Invalid JSON in inline value\nError: {e.msg} at line {e.lineno}, column {e.colno}"
|
|
177
|
+
) from e
|
glaip_sdk/cli/resolution.py
CHANGED
|
@@ -51,14 +51,8 @@ def resolve_resource_reference(
|
|
|
51
51
|
click.ClickException: If resolution fails.
|
|
52
52
|
"""
|
|
53
53
|
try:
|
|
54
|
-
message =
|
|
55
|
-
|
|
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
|
glaip_sdk/cli/rich_helpers.py
CHANGED
|
@@ -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))
|
glaip_sdk/cli/slash/__init__.py
CHANGED
|
@@ -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
|
]
|