glaip-sdk 0.0.18__py3-none-any.whl → 0.0.20__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/_version.py +2 -2
- glaip_sdk/branding.py +27 -2
- glaip_sdk/cli/auth.py +93 -28
- glaip_sdk/cli/commands/__init__.py +2 -2
- glaip_sdk/cli/commands/agents.py +108 -21
- glaip_sdk/cli/commands/configure.py +141 -90
- glaip_sdk/cli/commands/mcps.py +371 -48
- glaip_sdk/cli/commands/models.py +4 -3
- glaip_sdk/cli/commands/tools.py +27 -14
- glaip_sdk/cli/commands/update.py +66 -0
- glaip_sdk/cli/config.py +13 -2
- glaip_sdk/cli/display.py +35 -26
- glaip_sdk/cli/io.py +14 -5
- glaip_sdk/cli/main.py +185 -73
- glaip_sdk/cli/pager.py +2 -1
- glaip_sdk/cli/parsers/json_input.py +62 -14
- glaip_sdk/cli/resolution.py +4 -1
- glaip_sdk/cli/slash/__init__.py +3 -4
- glaip_sdk/cli/slash/agent_session.py +88 -36
- glaip_sdk/cli/slash/prompt.py +20 -48
- glaip_sdk/cli/slash/session.py +440 -189
- glaip_sdk/cli/transcript/__init__.py +71 -0
- glaip_sdk/cli/transcript/cache.py +338 -0
- glaip_sdk/cli/transcript/capture.py +278 -0
- glaip_sdk/cli/transcript/export.py +38 -0
- glaip_sdk/cli/transcript/launcher.py +79 -0
- glaip_sdk/cli/transcript/viewer.py +624 -0
- glaip_sdk/cli/update_notifier.py +29 -5
- glaip_sdk/cli/utils.py +256 -74
- glaip_sdk/client/agents.py +3 -1
- glaip_sdk/client/run_rendering.py +2 -2
- glaip_sdk/icons.py +19 -0
- glaip_sdk/models.py +6 -0
- glaip_sdk/rich_components.py +29 -1
- glaip_sdk/utils/__init__.py +1 -1
- glaip_sdk/utils/client_utils.py +6 -4
- glaip_sdk/utils/display.py +61 -32
- glaip_sdk/utils/rendering/formatting.py +6 -5
- glaip_sdk/utils/rendering/renderer/base.py +213 -66
- glaip_sdk/utils/rendering/renderer/debug.py +73 -16
- glaip_sdk/utils/rendering/renderer/panels.py +27 -15
- glaip_sdk/utils/rendering/renderer/progress.py +61 -38
- glaip_sdk/utils/serialization.py +5 -2
- glaip_sdk/utils/validation.py +1 -2
- {glaip_sdk-0.0.18.dist-info → glaip_sdk-0.0.20.dist-info}/METADATA +1 -1
- glaip_sdk-0.0.20.dist-info/RECORD +80 -0
- glaip_sdk/utils/rich_utils.py +0 -29
- glaip_sdk-0.0.18.dist-info/RECORD +0 -73
- {glaip_sdk-0.0.18.dist-info → glaip_sdk-0.0.20.dist-info}/WHEEL +0 -0
- {glaip_sdk-0.0.18.dist-info → glaip_sdk-0.0.20.dist-info}/entry_points.txt +0 -0
|
@@ -12,10 +12,20 @@ from rich.text import Text
|
|
|
12
12
|
|
|
13
13
|
from glaip_sdk import Client
|
|
14
14
|
from glaip_sdk._version import __version__ as _SDK_VERSION
|
|
15
|
-
from glaip_sdk.branding import
|
|
15
|
+
from glaip_sdk.branding import (
|
|
16
|
+
ACCENT_STYLE,
|
|
17
|
+
ERROR_STYLE,
|
|
18
|
+
INFO,
|
|
19
|
+
PRIMARY,
|
|
20
|
+
SUCCESS,
|
|
21
|
+
SUCCESS_STYLE,
|
|
22
|
+
WARNING_STYLE,
|
|
23
|
+
AIPBranding,
|
|
24
|
+
)
|
|
16
25
|
from glaip_sdk.cli.config import CONFIG_FILE, load_config, save_config
|
|
17
26
|
from glaip_sdk.cli.rich_helpers import markup_text
|
|
18
|
-
from glaip_sdk.cli.utils import command_hint
|
|
27
|
+
from glaip_sdk.cli.utils import command_hint, format_command_hint
|
|
28
|
+
from glaip_sdk.icons import ICON_TOOL
|
|
19
29
|
from glaip_sdk.rich_components import AIPTable
|
|
20
30
|
|
|
21
31
|
console = Console()
|
|
@@ -33,29 +43,10 @@ def list_config() -> None:
|
|
|
33
43
|
config = load_config()
|
|
34
44
|
|
|
35
45
|
if not config:
|
|
36
|
-
|
|
37
|
-
if hint:
|
|
38
|
-
console.print(
|
|
39
|
-
f"[yellow]No configuration found. Run '{hint}' to set up.[/yellow]"
|
|
40
|
-
)
|
|
41
|
-
else:
|
|
42
|
-
console.print("[yellow]No configuration found.[/yellow]")
|
|
46
|
+
_print_missing_config_hint()
|
|
43
47
|
return
|
|
44
48
|
|
|
45
|
-
|
|
46
|
-
table.add_column("Setting", style="cyan", width=20)
|
|
47
|
-
table.add_column("Value", style="green")
|
|
48
|
-
|
|
49
|
-
for key, value in config.items():
|
|
50
|
-
if key == "api_key" and value:
|
|
51
|
-
# Mask the API key
|
|
52
|
-
masked_value = "***" + value[-4:] if len(value) > 4 else "***"
|
|
53
|
-
table.add_row(key, masked_value)
|
|
54
|
-
else:
|
|
55
|
-
table.add_row(key, str(value))
|
|
56
|
-
|
|
57
|
-
console.print(table)
|
|
58
|
-
console.print(Text(f"\n📁 Config file: {CONFIG_FILE}"))
|
|
49
|
+
_render_config_table(config)
|
|
59
50
|
|
|
60
51
|
|
|
61
52
|
@config_group.command("set")
|
|
@@ -67,7 +58,7 @@ def set_config(key: str, value: str) -> None:
|
|
|
67
58
|
|
|
68
59
|
if key not in valid_keys:
|
|
69
60
|
console.print(
|
|
70
|
-
f"[
|
|
61
|
+
f"[{ERROR_STYLE}]Error: Invalid key '{key}'. Valid keys are: {', '.join(valid_keys)}[/]"
|
|
71
62
|
)
|
|
72
63
|
raise click.ClickException(f"Invalid configuration key: {key}")
|
|
73
64
|
|
|
@@ -76,10 +67,11 @@ def set_config(key: str, value: str) -> None:
|
|
|
76
67
|
save_config(config)
|
|
77
68
|
|
|
78
69
|
if key == "api_key":
|
|
79
|
-
|
|
80
|
-
|
|
70
|
+
console.print(
|
|
71
|
+
Text(f"✅ Set {key} = {_mask_api_key(value)}", style=SUCCESS_STYLE)
|
|
72
|
+
)
|
|
81
73
|
else:
|
|
82
|
-
console.print(Text(f"✅ Set {key} = {value}"))
|
|
74
|
+
console.print(Text(f"✅ Set {key} = {value}", style=SUCCESS_STYLE))
|
|
83
75
|
|
|
84
76
|
|
|
85
77
|
@config_group.command("get")
|
|
@@ -90,16 +82,14 @@ def get_config(key: str) -> None:
|
|
|
90
82
|
|
|
91
83
|
if key not in config:
|
|
92
84
|
console.print(
|
|
93
|
-
markup_text(f"[
|
|
85
|
+
markup_text(f"[{WARNING_STYLE}]Configuration key '{key}' not found.[/]")
|
|
94
86
|
)
|
|
95
87
|
raise click.ClickException(f"Configuration key not found: {key}")
|
|
96
88
|
|
|
97
89
|
value = config[key]
|
|
98
90
|
|
|
99
91
|
if key == "api_key":
|
|
100
|
-
|
|
101
|
-
masked_value = "***" + value[-4:] if len(value) > 4 else "***"
|
|
102
|
-
console.print(masked_value)
|
|
92
|
+
console.print(_mask_api_key(value))
|
|
103
93
|
else:
|
|
104
94
|
console.print(value)
|
|
105
95
|
|
|
@@ -112,14 +102,14 @@ def unset_config(key: str) -> None:
|
|
|
112
102
|
|
|
113
103
|
if key not in config:
|
|
114
104
|
console.print(
|
|
115
|
-
markup_text(f"[
|
|
105
|
+
markup_text(f"[{WARNING_STYLE}]Configuration key '{key}' not found.[/]")
|
|
116
106
|
)
|
|
117
107
|
return
|
|
118
108
|
|
|
119
109
|
del config[key]
|
|
120
110
|
save_config(config)
|
|
121
111
|
|
|
122
|
-
console.print(Text(f"✅ Removed {key} from configuration"))
|
|
112
|
+
console.print(Text(f"✅ Removed {key} from configuration", style=SUCCESS_STYLE))
|
|
123
113
|
|
|
124
114
|
|
|
125
115
|
@config_group.command("reset")
|
|
@@ -127,7 +117,7 @@ def unset_config(key: str) -> None:
|
|
|
127
117
|
def reset_config(force: bool) -> None:
|
|
128
118
|
"""Reset all configuration to defaults."""
|
|
129
119
|
if not force:
|
|
130
|
-
console.print("[
|
|
120
|
+
console.print(f"[{WARNING_STYLE}]This will remove all AIP configuration.[/]")
|
|
131
121
|
confirm = input("Are you sure? (y/N): ").strip().lower()
|
|
132
122
|
if confirm not in ["y", "yes"]:
|
|
133
123
|
console.print("Cancelled.")
|
|
@@ -137,8 +127,10 @@ def reset_config(force: bool) -> None:
|
|
|
137
127
|
file_exists = CONFIG_FILE.exists()
|
|
138
128
|
|
|
139
129
|
if not file_exists and not config_data:
|
|
140
|
-
console.print("[
|
|
141
|
-
console.print(
|
|
130
|
+
console.print(f"[{WARNING_STYLE}]No configuration found to reset.[/]")
|
|
131
|
+
console.print(
|
|
132
|
+
Text("✅ Configuration reset (nothing to remove).", style=SUCCESS_STYLE)
|
|
133
|
+
)
|
|
142
134
|
return
|
|
143
135
|
|
|
144
136
|
if file_exists:
|
|
@@ -151,103 +143,162 @@ def reset_config(force: bool) -> None:
|
|
|
151
143
|
save_config({})
|
|
152
144
|
|
|
153
145
|
hint = command_hint("config configure", slash_command="login")
|
|
154
|
-
message = "✅ Configuration reset."
|
|
146
|
+
message = Text("✅ Configuration reset.", style=SUCCESS_STYLE)
|
|
155
147
|
if hint:
|
|
156
|
-
message
|
|
148
|
+
message.append(f" Run '{hint}' to set up again.")
|
|
157
149
|
console.print(message)
|
|
158
150
|
|
|
159
151
|
|
|
160
152
|
def _configure_interactive() -> None:
|
|
161
153
|
"""Shared configuration logic for both configure commands."""
|
|
162
|
-
|
|
154
|
+
_render_configuration_header()
|
|
155
|
+
config = load_config()
|
|
156
|
+
_prompt_configuration_inputs(config)
|
|
157
|
+
_save_configuration(config)
|
|
158
|
+
_test_and_report_connection(config)
|
|
159
|
+
_print_post_configuration_hints()
|
|
160
|
+
|
|
161
|
+
|
|
162
|
+
@config_group.command()
|
|
163
|
+
def configure() -> None:
|
|
164
|
+
"""Configure AIP CLI credentials and settings interactively."""
|
|
165
|
+
_configure_interactive()
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+
# Alias command for backward compatibility
|
|
169
|
+
@click.command()
|
|
170
|
+
def configure_command() -> None:
|
|
171
|
+
"""Configure AIP CLI credentials and settings interactively.
|
|
172
|
+
|
|
173
|
+
This is an alias for 'aip config configure' for backward compatibility.
|
|
174
|
+
"""
|
|
175
|
+
# Delegate to the shared function
|
|
176
|
+
_configure_interactive()
|
|
177
|
+
|
|
178
|
+
|
|
179
|
+
# Note: The config command group should be registered in main.py
|
|
180
|
+
|
|
181
|
+
|
|
182
|
+
def _mask_api_key(value: str | None) -> str:
|
|
183
|
+
if not value:
|
|
184
|
+
return ""
|
|
185
|
+
return "***" + value[-4:] if len(value) > 4 else "***"
|
|
186
|
+
|
|
187
|
+
|
|
188
|
+
def _print_missing_config_hint() -> None:
|
|
189
|
+
hint = command_hint("config configure", slash_command="login")
|
|
190
|
+
if hint:
|
|
191
|
+
console.print(
|
|
192
|
+
f"[{WARNING_STYLE}]No configuration found.[/] Run {format_command_hint(hint) or hint} to set up."
|
|
193
|
+
)
|
|
194
|
+
else:
|
|
195
|
+
console.print(f"[{WARNING_STYLE}]No configuration found.[/]")
|
|
196
|
+
|
|
197
|
+
|
|
198
|
+
def _render_config_table(config: dict[str, str]) -> None:
|
|
199
|
+
table = AIPTable(title=f"{ICON_TOOL} AIP Configuration")
|
|
200
|
+
table.add_column("Setting", style=INFO, width=20)
|
|
201
|
+
table.add_column("Value", style=SUCCESS)
|
|
202
|
+
|
|
203
|
+
for key, value in config.items():
|
|
204
|
+
table.add_row(key, _mask_api_key(value) if key == "api_key" else str(value))
|
|
205
|
+
|
|
206
|
+
console.print(table)
|
|
207
|
+
console.print(Text(f"\n📁 Config file: {CONFIG_FILE}"))
|
|
208
|
+
|
|
209
|
+
|
|
210
|
+
def _render_configuration_header() -> None:
|
|
163
211
|
branding = AIPBranding.create_from_sdk(
|
|
164
212
|
sdk_version=_SDK_VERSION, package_name="glaip-sdk"
|
|
165
213
|
)
|
|
166
|
-
|
|
214
|
+
heading = "[bold]>_ GDP Labs AI Agents Package (AIP CLI)[/bold]"
|
|
215
|
+
console.print(heading)
|
|
216
|
+
console.print()
|
|
217
|
+
console.print(branding.get_welcome_banner())
|
|
218
|
+
console.rule("[bold]AIP Configuration[/bold]", style=PRIMARY)
|
|
167
219
|
|
|
168
|
-
# Load existing config
|
|
169
|
-
config = load_config()
|
|
170
220
|
|
|
221
|
+
def _prompt_configuration_inputs(config: dict[str, str]) -> None:
|
|
171
222
|
console.print("\n[bold]Enter your AIP configuration:[/bold]")
|
|
172
223
|
console.print("(Leave blank to keep current values)")
|
|
173
224
|
console.print("─" * 50)
|
|
174
225
|
|
|
175
|
-
|
|
226
|
+
_prompt_api_url(config)
|
|
227
|
+
_prompt_api_key(config)
|
|
228
|
+
|
|
229
|
+
|
|
230
|
+
def _prompt_api_url(config: dict[str, str]) -> None:
|
|
176
231
|
current_url = config.get("api_url", "")
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
)
|
|
232
|
+
suffix = f"(current: {current_url})" if current_url else ""
|
|
233
|
+
console.print(f"\n[{ACCENT_STYLE}]AIP API URL[/] {suffix}:")
|
|
180
234
|
new_url = input("> ").strip()
|
|
181
235
|
if new_url:
|
|
182
236
|
config["api_url"] = new_url
|
|
183
237
|
elif not current_url:
|
|
184
238
|
config["api_url"] = "https://your-aip-instance.com"
|
|
185
239
|
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
)
|
|
190
|
-
console.print(
|
|
191
|
-
f"\n[cyan]AIP API Key[/cyan] {f'(current: {current_key_masked})' if current_key_masked else ''}:"
|
|
192
|
-
)
|
|
240
|
+
|
|
241
|
+
def _prompt_api_key(config: dict[str, str]) -> None:
|
|
242
|
+
current_key_masked = _mask_api_key(config.get("api_key"))
|
|
243
|
+
suffix = f"(current: {current_key_masked})" if current_key_masked else ""
|
|
244
|
+
console.print(f"\n[{ACCENT_STYLE}]AIP API Key[/] {suffix}:")
|
|
193
245
|
new_key = getpass.getpass("> ")
|
|
194
246
|
if new_key:
|
|
195
247
|
config["api_key"] = new_key
|
|
196
248
|
|
|
197
|
-
|
|
249
|
+
|
|
250
|
+
def _save_configuration(config: dict[str, str]) -> None:
|
|
198
251
|
save_config(config)
|
|
252
|
+
console.print(
|
|
253
|
+
Text(f"\n✅ Configuration saved to: {CONFIG_FILE}", style=SUCCESS_STYLE)
|
|
254
|
+
)
|
|
199
255
|
|
|
200
|
-
console.print(Text(f"\n✅ Configuration saved to: {CONFIG_FILE}"))
|
|
201
256
|
|
|
202
|
-
|
|
257
|
+
def _test_and_report_connection(config: dict[str, str]) -> None:
|
|
203
258
|
console.print("\n🔌 Testing connection...")
|
|
259
|
+
client: Client | None = None
|
|
204
260
|
try:
|
|
205
|
-
# Create client with new config
|
|
206
261
|
client = Client(api_url=config["api_url"], api_key=config["api_key"])
|
|
207
|
-
|
|
208
|
-
# Try to list resources to test connection
|
|
209
262
|
try:
|
|
210
263
|
agents = client.list_agents()
|
|
211
|
-
console.print(
|
|
212
|
-
|
|
213
|
-
|
|
264
|
+
console.print(
|
|
265
|
+
Text(
|
|
266
|
+
f"✅ Connection successful! Found {len(agents)} agents",
|
|
267
|
+
style=SUCCESS_STYLE,
|
|
268
|
+
)
|
|
269
|
+
)
|
|
270
|
+
except Exception as exc: # pragma: no cover - API failures depend on network
|
|
271
|
+
console.print(
|
|
272
|
+
Text(
|
|
273
|
+
f"⚠️ Connection established but API call failed: {exc}",
|
|
274
|
+
style=WARNING_STYLE,
|
|
275
|
+
)
|
|
276
|
+
)
|
|
214
277
|
console.print(
|
|
215
278
|
" You may need to check your API permissions or network access"
|
|
216
279
|
)
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
except Exception as e:
|
|
221
|
-
console.print(Text(f"❌ Connection failed: {e}"))
|
|
280
|
+
except Exception as exc:
|
|
281
|
+
console.print(Text(f"❌ Connection failed: {exc}"))
|
|
222
282
|
console.print(" Please check your API URL and key")
|
|
223
283
|
hint_status = command_hint("status", slash_command="status")
|
|
224
284
|
if hint_status:
|
|
225
|
-
console.print(
|
|
285
|
+
console.print(
|
|
286
|
+
f" You can run {format_command_hint(hint_status) or hint_status} later to test again"
|
|
287
|
+
)
|
|
288
|
+
finally:
|
|
289
|
+
if client is not None:
|
|
290
|
+
client.close()
|
|
291
|
+
|
|
226
292
|
|
|
293
|
+
def _print_post_configuration_hints() -> None:
|
|
227
294
|
console.print("\n💡 You can now use AIP CLI commands!")
|
|
228
295
|
hint_status = command_hint("status", slash_command="status")
|
|
229
296
|
if hint_status:
|
|
230
|
-
console.print(
|
|
297
|
+
console.print(
|
|
298
|
+
f" • Run {format_command_hint(hint_status) or hint_status} to check connection"
|
|
299
|
+
)
|
|
231
300
|
hint_agents = command_hint("agents list", slash_command="agents")
|
|
232
301
|
if hint_agents:
|
|
233
|
-
console.print(
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
@config_group.command()
|
|
237
|
-
def configure() -> None:
|
|
238
|
-
"""Configure AIP CLI credentials and settings interactively."""
|
|
239
|
-
_configure_interactive()
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
# Alias command for backward compatibility
|
|
243
|
-
@click.command()
|
|
244
|
-
def configure_command() -> None:
|
|
245
|
-
"""Configure AIP CLI credentials and settings interactively.
|
|
246
|
-
|
|
247
|
-
This is an alias for 'aip config configure' for backward compatibility.
|
|
248
|
-
"""
|
|
249
|
-
# Delegate to the shared function
|
|
250
|
-
_configure_interactive()
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
# Note: The config command group should be registered in main.py
|
|
302
|
+
console.print(
|
|
303
|
+
f" • Run {format_command_hint(hint_agents) or hint_agents} to see your agents"
|
|
304
|
+
)
|