glaip-sdk 0.0.5__py3-none-any.whl → 0.0.6a0__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 +1 -1
- glaip_sdk/branding.py +3 -2
- glaip_sdk/cli/commands/__init__.py +1 -1
- glaip_sdk/cli/commands/agents.py +444 -268
- glaip_sdk/cli/commands/configure.py +12 -11
- glaip_sdk/cli/commands/mcps.py +28 -16
- glaip_sdk/cli/commands/models.py +5 -3
- glaip_sdk/cli/commands/tools.py +109 -102
- glaip_sdk/cli/display.py +38 -16
- glaip_sdk/cli/io.py +1 -1
- glaip_sdk/cli/main.py +26 -5
- glaip_sdk/cli/resolution.py +5 -4
- glaip_sdk/cli/utils.py +376 -157
- glaip_sdk/cli/validators.py +7 -2
- glaip_sdk/client/agents.py +184 -89
- glaip_sdk/client/base.py +24 -13
- glaip_sdk/client/validators.py +154 -94
- glaip_sdk/config/constants.py +0 -2
- glaip_sdk/models.py +4 -4
- glaip_sdk/utils/__init__.py +7 -7
- glaip_sdk/utils/client_utils.py +144 -78
- glaip_sdk/utils/display.py +4 -2
- glaip_sdk/utils/general.py +8 -6
- glaip_sdk/utils/import_export.py +55 -24
- glaip_sdk/utils/rendering/formatting.py +12 -6
- glaip_sdk/utils/rendering/models.py +1 -1
- glaip_sdk/utils/rendering/renderer/base.py +412 -248
- glaip_sdk/utils/rendering/renderer/console.py +6 -5
- glaip_sdk/utils/rendering/renderer/debug.py +94 -52
- glaip_sdk/utils/rendering/renderer/stream.py +93 -48
- glaip_sdk/utils/rendering/steps.py +103 -39
- glaip_sdk/utils/rich_utils.py +1 -1
- glaip_sdk/utils/run_renderer.py +1 -1
- glaip_sdk/utils/serialization.py +3 -1
- glaip_sdk/utils/validation.py +2 -2
- glaip_sdk-0.0.6a0.dist-info/METADATA +183 -0
- glaip_sdk-0.0.6a0.dist-info/RECORD +55 -0
- {glaip_sdk-0.0.5.dist-info → glaip_sdk-0.0.6a0.dist-info}/WHEEL +1 -1
- glaip_sdk-0.0.6a0.dist-info/entry_points.txt +3 -0
- glaip_sdk-0.0.5.dist-info/METADATA +0 -645
- glaip_sdk-0.0.5.dist-info/RECORD +0 -55
- glaip_sdk-0.0.5.dist-info/entry_points.txt +0 -2
glaip_sdk/utils/general.py
CHANGED
|
@@ -5,7 +5,9 @@ Authors:
|
|
|
5
5
|
"""
|
|
6
6
|
|
|
7
7
|
import re
|
|
8
|
+
from collections.abc import Iterable, Iterator
|
|
8
9
|
from datetime import datetime
|
|
10
|
+
from typing import Any
|
|
9
11
|
from uuid import UUID
|
|
10
12
|
|
|
11
13
|
import click
|
|
@@ -58,7 +60,7 @@ def format_file_size(size_bytes: int) -> str:
|
|
|
58
60
|
return f"{size_bytes:.1f} TB"
|
|
59
61
|
|
|
60
62
|
|
|
61
|
-
def format_datetime(dt):
|
|
63
|
+
def format_datetime(dt: datetime | str | None) -> str:
|
|
62
64
|
"""Format datetime object to readable string.
|
|
63
65
|
|
|
64
66
|
Args:
|
|
@@ -74,7 +76,9 @@ def format_datetime(dt):
|
|
|
74
76
|
return str(dt)
|
|
75
77
|
|
|
76
78
|
|
|
77
|
-
def progress_bar(
|
|
79
|
+
def progress_bar(
|
|
80
|
+
iterable: Iterable[Any], description: str = "Processing"
|
|
81
|
+
) -> Iterator[Any]:
|
|
78
82
|
"""Simple progress bar using click.
|
|
79
83
|
|
|
80
84
|
Args:
|
|
@@ -86,9 +90,7 @@ def progress_bar(iterable, description: str = "Processing"):
|
|
|
86
90
|
"""
|
|
87
91
|
try:
|
|
88
92
|
with click.progressbar(iterable, label=description) as bar:
|
|
89
|
-
|
|
90
|
-
yield item
|
|
93
|
+
yield from bar
|
|
91
94
|
except ImportError:
|
|
92
95
|
# Fallback if click not available
|
|
93
|
-
|
|
94
|
-
yield item
|
|
96
|
+
yield from iterable
|
glaip_sdk/utils/import_export.py
CHANGED
|
@@ -66,6 +66,58 @@ def convert_export_to_import_format(data: dict[str, Any]) -> dict[str, Any]:
|
|
|
66
66
|
return import_data
|
|
67
67
|
|
|
68
68
|
|
|
69
|
+
def _get_default_array_fields() -> list[str]:
|
|
70
|
+
"""Get default array fields that should be merged."""
|
|
71
|
+
return ["tools", "agents"]
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
def _should_use_cli_value(cli_value: Any) -> bool:
|
|
75
|
+
"""Check if CLI value should be used."""
|
|
76
|
+
return cli_value is not None and (
|
|
77
|
+
not isinstance(cli_value, list | tuple) or len(cli_value) > 0
|
|
78
|
+
)
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
def _handle_array_field_merge(
|
|
82
|
+
key: str, cli_value: Any, import_data: dict[str, Any]
|
|
83
|
+
) -> Any:
|
|
84
|
+
"""Handle merging of array fields."""
|
|
85
|
+
import_value = import_data[key]
|
|
86
|
+
if isinstance(import_value, list):
|
|
87
|
+
return list(cli_value) + import_value
|
|
88
|
+
else:
|
|
89
|
+
return cli_value
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
def _merge_cli_values_with_import(
|
|
93
|
+
merged: dict[str, Any],
|
|
94
|
+
cli_args: dict[str, Any],
|
|
95
|
+
import_data: dict[str, Any],
|
|
96
|
+
array_fields: list[str],
|
|
97
|
+
) -> None:
|
|
98
|
+
"""Merge CLI values into merged dict."""
|
|
99
|
+
for key, cli_value in cli_args.items():
|
|
100
|
+
if _should_use_cli_value(cli_value):
|
|
101
|
+
# CLI value takes precedence (for non-empty values)
|
|
102
|
+
if key in array_fields and key in import_data:
|
|
103
|
+
# For array fields, combine CLI and imported values
|
|
104
|
+
merged[key] = _handle_array_field_merge(key, cli_value, import_data)
|
|
105
|
+
else:
|
|
106
|
+
merged[key] = cli_value
|
|
107
|
+
elif key in import_data:
|
|
108
|
+
# Use imported value if no CLI value
|
|
109
|
+
merged[key] = import_data[key]
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
def _add_import_only_fields(
|
|
113
|
+
merged: dict[str, Any], import_data: dict[str, Any]
|
|
114
|
+
) -> None:
|
|
115
|
+
"""Add fields that exist only in import data."""
|
|
116
|
+
for key, import_value in import_data.items():
|
|
117
|
+
if key not in merged:
|
|
118
|
+
merged[key] = import_value
|
|
119
|
+
|
|
120
|
+
|
|
69
121
|
def merge_import_with_cli_args(
|
|
70
122
|
import_data: dict[str, Any],
|
|
71
123
|
cli_args: dict[str, Any],
|
|
@@ -87,32 +139,11 @@ def merge_import_with_cli_args(
|
|
|
87
139
|
- Empty arrays/lists are treated as None (no override)
|
|
88
140
|
"""
|
|
89
141
|
if array_fields is None:
|
|
90
|
-
array_fields =
|
|
142
|
+
array_fields = _get_default_array_fields()
|
|
91
143
|
|
|
92
144
|
merged = {}
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
if cli_value is not None and (
|
|
96
|
-
not isinstance(cli_value, list | tuple) or len(cli_value) > 0
|
|
97
|
-
):
|
|
98
|
-
# CLI value takes precedence (for non-empty values)
|
|
99
|
-
if key in array_fields and key in import_data:
|
|
100
|
-
# For array fields, combine CLI and imported values
|
|
101
|
-
import_value = import_data[key]
|
|
102
|
-
if isinstance(import_value, list):
|
|
103
|
-
merged[key] = list(cli_value) + import_value
|
|
104
|
-
else:
|
|
105
|
-
merged[key] = cli_value
|
|
106
|
-
else:
|
|
107
|
-
merged[key] = cli_value
|
|
108
|
-
elif key in import_data:
|
|
109
|
-
# Use imported value if no CLI value
|
|
110
|
-
merged[key] = import_data[key]
|
|
111
|
-
|
|
112
|
-
# Add any import-only fields
|
|
113
|
-
for key, import_value in import_data.items():
|
|
114
|
-
if key not in merged:
|
|
115
|
-
merged[key] = import_value
|
|
145
|
+
_merge_cli_values_with_import(merged, cli_args, import_data, array_fields)
|
|
146
|
+
_add_import_only_fields(merged, import_data)
|
|
116
147
|
|
|
117
148
|
return merged
|
|
118
149
|
|
|
@@ -8,6 +8,8 @@ from __future__ import annotations
|
|
|
8
8
|
|
|
9
9
|
import re
|
|
10
10
|
import time
|
|
11
|
+
from collections.abc import Callable
|
|
12
|
+
from typing import Any
|
|
11
13
|
|
|
12
14
|
# Constants for argument formatting
|
|
13
15
|
DEFAULT_ARGS_MAX_LEN = 100
|
|
@@ -65,9 +67,7 @@ def redact_sensitive(text: str | dict | list) -> str | dict | list:
|
|
|
65
67
|
for sensitive in ["password", "secret", "token", "key", "api_key"]
|
|
66
68
|
):
|
|
67
69
|
result[key] = "••••••"
|
|
68
|
-
elif isinstance(value, dict | list):
|
|
69
|
-
result[key] = redact_sensitive(value)
|
|
70
|
-
elif isinstance(value, str):
|
|
70
|
+
elif isinstance(value, dict | list) or isinstance(value, str):
|
|
71
71
|
result[key] = redact_sensitive(value)
|
|
72
72
|
else:
|
|
73
73
|
result[key] = value
|
|
@@ -156,7 +156,7 @@ def get_step_icon(step_kind: str) -> str:
|
|
|
156
156
|
return ""
|
|
157
157
|
|
|
158
158
|
|
|
159
|
-
def is_step_finished(step) -> bool:
|
|
159
|
+
def is_step_finished(step: Any) -> bool:
|
|
160
160
|
"""Check if a step is finished.
|
|
161
161
|
|
|
162
162
|
Args:
|
|
@@ -169,7 +169,9 @@ def is_step_finished(step) -> bool:
|
|
|
169
169
|
|
|
170
170
|
|
|
171
171
|
def format_main_title(
|
|
172
|
-
header_text: str,
|
|
172
|
+
header_text: str,
|
|
173
|
+
has_running_steps: bool,
|
|
174
|
+
get_spinner_char: Callable[[], str],
|
|
173
175
|
) -> str:
|
|
174
176
|
"""Generate the main panel title with dynamic status indicators.
|
|
175
177
|
|
|
@@ -191,7 +193,11 @@ def format_main_title(
|
|
|
191
193
|
|
|
192
194
|
|
|
193
195
|
def print_header_once(
|
|
194
|
-
console
|
|
196
|
+
console: Any,
|
|
197
|
+
text: str,
|
|
198
|
+
last_header: str,
|
|
199
|
+
rules_enabled: bool,
|
|
200
|
+
style: str | None = None,
|
|
195
201
|
) -> str:
|
|
196
202
|
"""Print header text only when it changes to avoid duplicate output.
|
|
197
203
|
|
|
@@ -25,7 +25,7 @@ class Step:
|
|
|
25
25
|
started_at: float = field(default_factory=monotonic)
|
|
26
26
|
duration_ms: int | None = None
|
|
27
27
|
|
|
28
|
-
def finish(self, duration_raw: float | None):
|
|
28
|
+
def finish(self, duration_raw: float | None) -> None:
|
|
29
29
|
if isinstance(duration_raw, int | float) and duration_raw > 0:
|
|
30
30
|
# Use provided duration if it's a positive number (even if very small)
|
|
31
31
|
self.duration_ms = round(float(duration_raw) * 1000)
|