glaip-sdk 0.0.20__py3-none-any.whl → 0.1.3__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 +1 -3
- glaip_sdk/branding.py +2 -6
- glaip_sdk/cli/agent_config.py +2 -6
- glaip_sdk/cli/auth.py +11 -30
- glaip_sdk/cli/commands/agents.py +64 -107
- glaip_sdk/cli/commands/configure.py +12 -36
- glaip_sdk/cli/commands/mcps.py +25 -63
- glaip_sdk/cli/commands/models.py +2 -4
- glaip_sdk/cli/commands/tools.py +22 -35
- glaip_sdk/cli/commands/update.py +3 -8
- glaip_sdk/cli/config.py +1 -3
- glaip_sdk/cli/display.py +10 -13
- glaip_sdk/cli/io.py +8 -14
- glaip_sdk/cli/main.py +10 -30
- glaip_sdk/cli/mcp_validators.py +5 -15
- glaip_sdk/cli/pager.py +3 -9
- 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/agent_session.py +5 -10
- glaip_sdk/cli/slash/prompt.py +3 -10
- glaip_sdk/cli/slash/session.py +46 -98
- glaip_sdk/cli/transcript/cache.py +6 -19
- glaip_sdk/cli/transcript/capture.py +45 -20
- glaip_sdk/cli/transcript/launcher.py +1 -3
- glaip_sdk/cli/transcript/viewer.py +224 -47
- glaip_sdk/cli/update_notifier.py +165 -21
- glaip_sdk/cli/utils.py +33 -91
- glaip_sdk/cli/validators.py +11 -12
- glaip_sdk/client/_agent_payloads.py +10 -30
- glaip_sdk/client/agents.py +33 -63
- glaip_sdk/client/base.py +77 -35
- glaip_sdk/client/mcps.py +1 -3
- glaip_sdk/client/run_rendering.py +121 -26
- glaip_sdk/client/tools.py +8 -24
- glaip_sdk/client/validators.py +20 -48
- glaip_sdk/exceptions.py +1 -3
- glaip_sdk/icons.py +9 -3
- glaip_sdk/models.py +14 -33
- glaip_sdk/payload_schemas/agent.py +1 -3
- glaip_sdk/utils/agent_config.py +4 -14
- glaip_sdk/utils/client_utils.py +7 -21
- glaip_sdk/utils/display.py +2 -6
- glaip_sdk/utils/general.py +1 -3
- glaip_sdk/utils/import_export.py +3 -9
- glaip_sdk/utils/rendering/formatting.py +52 -12
- glaip_sdk/utils/rendering/models.py +17 -8
- glaip_sdk/utils/rendering/renderer/__init__.py +1 -5
- glaip_sdk/utils/rendering/renderer/base.py +1181 -328
- glaip_sdk/utils/rendering/renderer/config.py +4 -10
- glaip_sdk/utils/rendering/renderer/debug.py +4 -14
- glaip_sdk/utils/rendering/renderer/panels.py +1 -3
- glaip_sdk/utils/rendering/renderer/progress.py +3 -11
- glaip_sdk/utils/rendering/renderer/stream.py +9 -42
- glaip_sdk/utils/rendering/renderer/summary_window.py +79 -0
- glaip_sdk/utils/rendering/renderer/toggle.py +182 -0
- glaip_sdk/utils/rendering/step_tree_state.py +100 -0
- glaip_sdk/utils/rendering/steps.py +899 -25
- glaip_sdk/utils/resource_refs.py +4 -13
- glaip_sdk/utils/serialization.py +14 -46
- glaip_sdk/utils/validation.py +4 -4
- {glaip_sdk-0.0.20.dist-info → glaip_sdk-0.1.3.dist-info}/METADATA +12 -1
- glaip_sdk-0.1.3.dist-info/RECORD +83 -0
- glaip_sdk-0.0.20.dist-info/RECORD +0 -80
- {glaip_sdk-0.0.20.dist-info → glaip_sdk-0.1.3.dist-info}/WHEEL +0 -0
- {glaip_sdk-0.0.20.dist-info → glaip_sdk-0.1.3.dist-info}/entry_points.txt +0 -0
glaip_sdk/_version.py
CHANGED
|
@@ -47,9 +47,7 @@ def _try_get_dev_version() -> str | None:
|
|
|
47
47
|
return None
|
|
48
48
|
|
|
49
49
|
data = _toml.loads(pyproject.read_text(encoding="utf-8"))
|
|
50
|
-
ver = data.get("project", {}).get("version") or data.get("tool", {}).get(
|
|
51
|
-
"poetry", {}
|
|
52
|
-
).get("version")
|
|
50
|
+
ver = data.get("project", {}).get("version") or data.get("tool", {}).get("poetry", {}).get("version")
|
|
53
51
|
if isinstance(ver, str) and ver:
|
|
54
52
|
return ver
|
|
55
53
|
except Exception:
|
glaip_sdk/branding.py
CHANGED
|
@@ -104,9 +104,7 @@ GDP Labs AI Agents Package
|
|
|
104
104
|
@staticmethod
|
|
105
105
|
def _make_console() -> Console:
|
|
106
106
|
# Respect NO_COLOR/AIP_NO_COLOR environment variables
|
|
107
|
-
no_color_env = (
|
|
108
|
-
os.getenv("NO_COLOR") is not None or os.getenv("AIP_NO_COLOR") is not None
|
|
109
|
-
)
|
|
107
|
+
no_color_env = os.getenv("NO_COLOR") is not None or os.getenv("AIP_NO_COLOR") is not None
|
|
110
108
|
if no_color_env:
|
|
111
109
|
color_system = None
|
|
112
110
|
no_color = True
|
|
@@ -187,9 +185,7 @@ GDP Labs AI Agents Package
|
|
|
187
185
|
self.console.print(banner)
|
|
188
186
|
|
|
189
187
|
@classmethod
|
|
190
|
-
def create_from_sdk(
|
|
191
|
-
cls, sdk_version: str | None = None, package_name: str | None = None
|
|
192
|
-
) -> AIPBranding:
|
|
188
|
+
def create_from_sdk(cls, sdk_version: str | None = None, package_name: str | None = None) -> AIPBranding:
|
|
193
189
|
"""Create AIPBranding instance from SDK package information.
|
|
194
190
|
|
|
195
191
|
Args:
|
glaip_sdk/cli/agent_config.py
CHANGED
|
@@ -16,9 +16,7 @@ from glaip_sdk.utils.agent_config import (
|
|
|
16
16
|
from glaip_sdk.utils.import_export import merge_import_with_cli_args
|
|
17
17
|
|
|
18
18
|
|
|
19
|
-
def merge_agent_config_with_cli_args(
|
|
20
|
-
import_data: dict[str, Any], cli_args: dict[str, Any]
|
|
21
|
-
) -> dict[str, Any]:
|
|
19
|
+
def merge_agent_config_with_cli_args(import_data: dict[str, Any], cli_args: dict[str, Any]) -> dict[str, Any]:
|
|
22
20
|
"""Merge imported agent data with CLI arguments, preferring CLI args.
|
|
23
21
|
|
|
24
22
|
This is a CLI-specific wrapper that handles agent-specific merging logic.
|
|
@@ -35,9 +33,7 @@ def merge_agent_config_with_cli_args(
|
|
|
35
33
|
- Handles agent-specific fields like tools and agents arrays
|
|
36
34
|
- Preserves agent configuration structure
|
|
37
35
|
"""
|
|
38
|
-
return merge_import_with_cli_args(
|
|
39
|
-
import_data, cli_args, array_fields=["tools", "agents"]
|
|
40
|
-
)
|
|
36
|
+
return merge_import_with_cli_args(import_data, cli_args, array_fields=["tools", "agents"])
|
|
41
37
|
|
|
42
38
|
|
|
43
39
|
def resolve_agent_language_model_selection(
|
glaip_sdk/cli/auth.py
CHANGED
|
@@ -65,9 +65,7 @@ def prepare_authentication_export(
|
|
|
65
65
|
|
|
66
66
|
# Handle bearer-token authentication
|
|
67
67
|
if auth_type == "bearer-token":
|
|
68
|
-
return _prepare_bearer_token_auth(
|
|
69
|
-
auth, prompt_for_secrets, placeholder, console
|
|
70
|
-
)
|
|
68
|
+
return _prepare_bearer_token_auth(auth, prompt_for_secrets, placeholder, console)
|
|
71
69
|
|
|
72
70
|
# Handle api-key authentication
|
|
73
71
|
if auth_type == "api-key":
|
|
@@ -75,9 +73,7 @@ def prepare_authentication_export(
|
|
|
75
73
|
|
|
76
74
|
# Handle custom-header authentication
|
|
77
75
|
if auth_type == "custom-header":
|
|
78
|
-
return _prepare_custom_header_auth(
|
|
79
|
-
auth, prompt_for_secrets, placeholder, console
|
|
80
|
-
)
|
|
76
|
+
return _prepare_custom_header_auth(auth, prompt_for_secrets, placeholder, console)
|
|
81
77
|
|
|
82
78
|
# Unknown auth type - return as-is but strip helper metadata
|
|
83
79
|
result = auth.copy()
|
|
@@ -85,9 +81,7 @@ def prepare_authentication_export(
|
|
|
85
81
|
return result
|
|
86
82
|
|
|
87
83
|
|
|
88
|
-
def _get_token_value(
|
|
89
|
-
prompt_for_secrets: bool, placeholder: str, console: Console
|
|
90
|
-
) -> str:
|
|
84
|
+
def _get_token_value(prompt_for_secrets: bool, placeholder: str, console: Console) -> str:
|
|
91
85
|
"""Get bearer token value either by prompting or using a placeholder.
|
|
92
86
|
|
|
93
87
|
Args:
|
|
@@ -109,10 +103,7 @@ def _get_token_value(
|
|
|
109
103
|
)
|
|
110
104
|
|
|
111
105
|
if not click.get_text_stream("stdin").isatty():
|
|
112
|
-
console.print(
|
|
113
|
-
f"[{WARNING_STYLE}]⚠️ Non-interactive mode: "
|
|
114
|
-
"using placeholder for bearer token[/]"
|
|
115
|
-
)
|
|
106
|
+
console.print(f"[{WARNING_STYLE}]⚠️ Non-interactive mode: using placeholder for bearer token[/]")
|
|
116
107
|
return placeholder
|
|
117
108
|
|
|
118
109
|
|
|
@@ -220,16 +211,11 @@ def _get_api_key_value(
|
|
|
220
211
|
)
|
|
221
212
|
|
|
222
213
|
if not click.get_text_stream("stdin").isatty():
|
|
223
|
-
console.print(
|
|
224
|
-
f"[{WARNING_STYLE}]⚠️ Non-interactive mode: "
|
|
225
|
-
f"using placeholder for API key '{key_name}'[/]"
|
|
226
|
-
)
|
|
214
|
+
console.print(f"[{WARNING_STYLE}]⚠️ Non-interactive mode: using placeholder for API key '{key_name}'[/]")
|
|
227
215
|
return placeholder
|
|
228
216
|
|
|
229
217
|
|
|
230
|
-
def _build_api_key_headers(
|
|
231
|
-
auth: dict[str, Any], key_name: str | None, key_value: str
|
|
232
|
-
) -> dict[str, str]:
|
|
218
|
+
def _build_api_key_headers(auth: dict[str, Any], key_name: str | None, key_value: str) -> dict[str, str]:
|
|
233
219
|
"""Build headers for API key authentication.
|
|
234
220
|
|
|
235
221
|
Args:
|
|
@@ -270,9 +256,7 @@ def _prepare_api_key_auth(
|
|
|
270
256
|
|
|
271
257
|
# Capture or use placeholder for value
|
|
272
258
|
if not has_valid_value:
|
|
273
|
-
key_value = _get_api_key_value(
|
|
274
|
-
key_name, prompt_for_secrets, placeholder, console
|
|
275
|
-
)
|
|
259
|
+
key_value = _get_api_key_value(key_name, prompt_for_secrets, placeholder, console)
|
|
276
260
|
|
|
277
261
|
# Check if original had headers structure
|
|
278
262
|
if "headers" in auth or "header_keys" in auth:
|
|
@@ -317,9 +301,7 @@ def _prepare_custom_header_auth(
|
|
|
317
301
|
return {"type": "custom-header", "headers": headers}
|
|
318
302
|
|
|
319
303
|
|
|
320
|
-
def _extract_header_names(
|
|
321
|
-
existing_headers: Mapping[str, Any] | None, header_keys: Iterable[str] | None
|
|
322
|
-
) -> list[str]:
|
|
304
|
+
def _extract_header_names(existing_headers: Mapping[str, Any] | None, header_keys: Iterable[str] | None) -> list[str]:
|
|
323
305
|
"""Extract the list of header names to process.
|
|
324
306
|
|
|
325
307
|
Args:
|
|
@@ -376,9 +358,7 @@ def _prompt_or_placeholder(
|
|
|
376
358
|
)
|
|
377
359
|
|
|
378
360
|
if not click.get_text_stream("stdin").isatty():
|
|
379
|
-
console.print(
|
|
380
|
-
f"[{WARNING_STYLE}]⚠️ Non-interactive mode: using placeholder for header '{name}'[/]"
|
|
381
|
-
)
|
|
361
|
+
console.print(f"[{WARNING_STYLE}]⚠️ Non-interactive mode: using placeholder for header '{name}'[/]")
|
|
382
362
|
return placeholder
|
|
383
363
|
|
|
384
364
|
|
|
@@ -450,7 +430,8 @@ def _prompt_secret_with_placeholder(
|
|
|
450
430
|
tip = command_hint(tip_cli_command, tip_slash_command)
|
|
451
431
|
if tip:
|
|
452
432
|
console.print(
|
|
453
|
-
f"[{HINT_PREFIX_STYLE}]Tip:[/] use {format_command_hint(tip) or tip} later
|
|
433
|
+
f"[{HINT_PREFIX_STYLE}]Tip:[/] use {format_command_hint(tip) or tip} later "
|
|
434
|
+
"if you want to update these credentials."
|
|
454
435
|
)
|
|
455
436
|
|
|
456
437
|
attempts = 0
|
glaip_sdk/cli/commands/agents.py
CHANGED
|
@@ -83,6 +83,7 @@ from glaip_sdk.icons import ICON_AGENT
|
|
|
83
83
|
from glaip_sdk.utils import format_datetime, is_uuid
|
|
84
84
|
from glaip_sdk.utils.agent_config import normalize_agent_config_for_import
|
|
85
85
|
from glaip_sdk.utils.import_export import convert_export_to_import_format
|
|
86
|
+
from glaip_sdk.utils.rendering.renderer.toggle import TranscriptToggleController
|
|
86
87
|
from glaip_sdk.utils.validation import coerce_timeout
|
|
87
88
|
|
|
88
89
|
console = Console()
|
|
@@ -246,9 +247,7 @@ def _resolve_resources_by_name(
|
|
|
246
247
|
if not matches:
|
|
247
248
|
raise click.ClickException(f"{label} not found: {ref}")
|
|
248
249
|
if len(matches) > 1:
|
|
249
|
-
raise click.ClickException(
|
|
250
|
-
f"Multiple {resource_type}s named '{ref}'. Use ID instead."
|
|
251
|
-
)
|
|
250
|
+
raise click.ClickException(f"Multiple {resource_type}s named '{ref}'. Use ID instead.")
|
|
252
251
|
out.append(str(matches[0].id))
|
|
253
252
|
return out
|
|
254
253
|
|
|
@@ -394,15 +393,9 @@ def _resolve_agent(
|
|
|
394
393
|
|
|
395
394
|
|
|
396
395
|
@agents_group.command(name="list")
|
|
397
|
-
@click.option(
|
|
398
|
-
|
|
399
|
-
)
|
|
400
|
-
@click.option(
|
|
401
|
-
"--type", "agent_type", help="Filter by agent type (config, code, a2a, langflow)"
|
|
402
|
-
)
|
|
403
|
-
@click.option(
|
|
404
|
-
"--framework", help="Filter by framework (langchain, langgraph, google_adk)"
|
|
405
|
-
)
|
|
396
|
+
@click.option("--simple", is_flag=True, help="Show simple table without interactive picker")
|
|
397
|
+
@click.option("--type", "agent_type", help="Filter by agent type (config, code, a2a, langflow)")
|
|
398
|
+
@click.option("--framework", help="Filter by framework (langchain, langgraph, google_adk)")
|
|
406
399
|
@click.option("--name", help="Filter by partial name match (case-insensitive)")
|
|
407
400
|
@click.option("--version", help="Filter by exact version match")
|
|
408
401
|
@click.option(
|
|
@@ -481,15 +474,12 @@ def list_agents(
|
|
|
481
474
|
f"{ICON_AGENT} Available Agents",
|
|
482
475
|
columns,
|
|
483
476
|
transform_agent,
|
|
484
|
-
skip_picker=simple
|
|
485
|
-
or any(
|
|
486
|
-
param is not None for param in (agent_type, framework, name, version)
|
|
487
|
-
),
|
|
477
|
+
skip_picker=simple or any(param is not None for param in (agent_type, framework, name, version)),
|
|
488
478
|
use_pager=False,
|
|
489
479
|
)
|
|
490
480
|
|
|
491
481
|
except Exception as e:
|
|
492
|
-
raise click.ClickException(str(e))
|
|
482
|
+
raise click.ClickException(str(e)) from e
|
|
493
483
|
|
|
494
484
|
|
|
495
485
|
@agents_group.command()
|
|
@@ -514,9 +504,7 @@ def get(ctx: Any, agent_ref: str, select: int | None, export: str | None) -> Non
|
|
|
514
504
|
client = get_client(ctx)
|
|
515
505
|
|
|
516
506
|
# Resolve agent with ambiguity handling - use questionary interface for traditional UX
|
|
517
|
-
agent = _resolve_agent(
|
|
518
|
-
ctx, client, agent_ref, select, interface_preference="questionary"
|
|
519
|
-
)
|
|
507
|
+
agent = _resolve_agent(ctx, client, agent_ref, select, interface_preference="questionary")
|
|
520
508
|
|
|
521
509
|
# Handle export option
|
|
522
510
|
if export:
|
|
@@ -535,22 +523,19 @@ def get(ctx: Any, agent_ref: str, select: int | None, export: str | None) -> Non
|
|
|
535
523
|
except Exception as e:
|
|
536
524
|
handle_rich_output(
|
|
537
525
|
ctx,
|
|
538
|
-
markup_text(
|
|
539
|
-
f"[{WARNING_STYLE}]⚠️ Could not fetch full agent details: {e}[/]"
|
|
540
|
-
),
|
|
526
|
+
markup_text(f"[{WARNING_STYLE}]⚠️ Could not fetch full agent details: {e}[/]"),
|
|
541
527
|
)
|
|
542
528
|
handle_rich_output(
|
|
543
529
|
ctx,
|
|
544
|
-
markup_text(
|
|
545
|
-
f"[{WARNING_STYLE}]⚠️ Proceeding with available data[/]"
|
|
546
|
-
),
|
|
530
|
+
markup_text(f"[{WARNING_STYLE}]⚠️ Proceeding with available data[/]"),
|
|
547
531
|
)
|
|
548
532
|
|
|
549
533
|
export_resource_to_file(agent, export_path, detected_format)
|
|
550
534
|
handle_rich_output(
|
|
551
535
|
ctx,
|
|
552
536
|
markup_text(
|
|
553
|
-
f"[{SUCCESS_STYLE}]✅ Complete agent configuration exported to: {export_path}
|
|
537
|
+
f"[{SUCCESS_STYLE}]✅ Complete agent configuration exported to: {export_path} "
|
|
538
|
+
f"(format: {detected_format})[/]"
|
|
554
539
|
),
|
|
555
540
|
)
|
|
556
541
|
|
|
@@ -561,7 +546,7 @@ def get(ctx: Any, agent_ref: str, select: int | None, export: str | None) -> Non
|
|
|
561
546
|
handle_rich_output(ctx, display_agent_run_suggestions(agent))
|
|
562
547
|
|
|
563
548
|
except Exception as e:
|
|
564
|
-
raise click.ClickException(str(e))
|
|
549
|
+
raise click.ClickException(str(e)) from e
|
|
565
550
|
|
|
566
551
|
|
|
567
552
|
def _validate_run_input(input_option: str | None, input_text: str | None) -> str:
|
|
@@ -569,9 +554,7 @@ def _validate_run_input(input_option: str | None, input_text: str | None) -> str
|
|
|
569
554
|
final_input_text = input_option if input_option else input_text
|
|
570
555
|
|
|
571
556
|
if not final_input_text:
|
|
572
|
-
raise click.ClickException(
|
|
573
|
-
"Input text is required. Use either positional argument or --input option."
|
|
574
|
-
)
|
|
557
|
+
raise click.ClickException("Input text is required. Use either positional argument or --input option.")
|
|
575
558
|
|
|
576
559
|
return final_input_text
|
|
577
560
|
|
|
@@ -583,8 +566,8 @@ def _parse_chat_history(chat_history: str | None) -> list[dict[str, Any]] | None
|
|
|
583
566
|
|
|
584
567
|
try:
|
|
585
568
|
return json.loads(chat_history)
|
|
586
|
-
except json.JSONDecodeError:
|
|
587
|
-
raise click.ClickException("Invalid JSON in chat history")
|
|
569
|
+
except json.JSONDecodeError as err:
|
|
570
|
+
raise click.ClickException("Invalid JSON in chat history") from err
|
|
588
571
|
|
|
589
572
|
|
|
590
573
|
def _setup_run_renderer(ctx: Any, save: str | None, verbose: bool) -> Any:
|
|
@@ -598,6 +581,23 @@ def _setup_run_renderer(ctx: Any, save: str | None, verbose: bool) -> Any:
|
|
|
598
581
|
)
|
|
599
582
|
|
|
600
583
|
|
|
584
|
+
def _maybe_attach_transcript_toggle(ctx: Any, renderer: Any) -> None:
|
|
585
|
+
"""Attach transcript toggle controller when interactive TTY is available."""
|
|
586
|
+
if renderer is None:
|
|
587
|
+
return
|
|
588
|
+
|
|
589
|
+
console_obj = getattr(renderer, "console", None)
|
|
590
|
+
if console_obj is None or not getattr(console_obj, "is_terminal", False):
|
|
591
|
+
return
|
|
592
|
+
|
|
593
|
+
tty_enabled = bool(get_ctx_value(ctx, "tty", True))
|
|
594
|
+
if not tty_enabled:
|
|
595
|
+
return
|
|
596
|
+
|
|
597
|
+
controller = TranscriptToggleController(enabled=True)
|
|
598
|
+
renderer.transcript_controller = controller
|
|
599
|
+
|
|
600
|
+
|
|
601
601
|
def _prepare_run_kwargs(
|
|
602
602
|
agent: Any,
|
|
603
603
|
final_input_text: str,
|
|
@@ -647,9 +647,7 @@ def _save_run_transcript(save: str | None, result: Any, working_console: Any) ->
|
|
|
647
647
|
if ext == "json":
|
|
648
648
|
save_data = {
|
|
649
649
|
"output": result or "",
|
|
650
|
-
"full_debug_output": getattr(
|
|
651
|
-
working_console, "get_captured_output", lambda: ""
|
|
652
|
-
)(),
|
|
650
|
+
"full_debug_output": getattr(working_console, "get_captured_output", lambda: "")(),
|
|
653
651
|
"timestamp": "captured during agent execution",
|
|
654
652
|
}
|
|
655
653
|
content = json.dumps(save_data, indent=2)
|
|
@@ -662,9 +660,7 @@ def _save_run_transcript(save: str | None, result: Any, working_console: Any) ->
|
|
|
662
660
|
|
|
663
661
|
with open(save, "w", encoding="utf-8") as f:
|
|
664
662
|
f.write(content)
|
|
665
|
-
print_markup(
|
|
666
|
-
f"[{SUCCESS_STYLE}]Full debug output saved to: {save}[/]", console=console
|
|
667
|
-
)
|
|
663
|
+
print_markup(f"[{SUCCESS_STYLE}]Full debug output saved to: {save}[/]", console=console)
|
|
668
664
|
|
|
669
665
|
|
|
670
666
|
@agents_group.command()
|
|
@@ -727,12 +723,11 @@ def run(
|
|
|
727
723
|
|
|
728
724
|
try:
|
|
729
725
|
client = get_client(ctx)
|
|
730
|
-
agent = _resolve_agent(
|
|
731
|
-
ctx, client, agent_ref, select, interface_preference="fuzzy"
|
|
732
|
-
)
|
|
726
|
+
agent = _resolve_agent(ctx, client, agent_ref, select, interface_preference="fuzzy")
|
|
733
727
|
|
|
734
728
|
parsed_chat_history = _parse_chat_history(chat_history)
|
|
735
729
|
renderer, working_console = _setup_run_renderer(ctx, save, verbose)
|
|
730
|
+
_maybe_attach_transcript_toggle(ctx, renderer)
|
|
736
731
|
|
|
737
732
|
try:
|
|
738
733
|
client.timeout = float(timeout)
|
|
@@ -777,7 +772,7 @@ def run(
|
|
|
777
772
|
except AgentTimeoutError as e:
|
|
778
773
|
error_msg = str(e)
|
|
779
774
|
handle_json_output(ctx, error=Exception(error_msg))
|
|
780
|
-
raise click.ClickException(error_msg)
|
|
775
|
+
raise click.ClickException(error_msg) from e
|
|
781
776
|
except Exception as e:
|
|
782
777
|
_handle_command_exception(ctx, e)
|
|
783
778
|
|
|
@@ -866,16 +861,12 @@ def _extract_and_validate_fields(
|
|
|
866
861
|
if not name:
|
|
867
862
|
raise click.ClickException("Agent name is required (--name or --import)")
|
|
868
863
|
if not instruction:
|
|
869
|
-
raise click.ClickException(
|
|
870
|
-
"Agent instruction is required (--instruction or --import)"
|
|
871
|
-
)
|
|
864
|
+
raise click.ClickException("Agent instruction is required (--instruction or --import)")
|
|
872
865
|
|
|
873
866
|
return name, instruction, model, tools, agents, mcps, timeout
|
|
874
867
|
|
|
875
868
|
|
|
876
|
-
def _validate_and_coerce_fields(
|
|
877
|
-
name: str, instruction: str, timeout: Any
|
|
878
|
-
) -> tuple[str, str, Any]:
|
|
869
|
+
def _validate_and_coerce_fields(name: str, instruction: str, timeout: Any) -> tuple[str, str, Any]:
|
|
879
870
|
"""Validate and coerce field values."""
|
|
880
871
|
name = validate_agent_name(name)
|
|
881
872
|
instruction = validate_agent_instruction(instruction)
|
|
@@ -886,19 +877,11 @@ def _validate_and_coerce_fields(
|
|
|
886
877
|
return name, instruction, timeout
|
|
887
878
|
|
|
888
879
|
|
|
889
|
-
def _resolve_resources(
|
|
890
|
-
client: Any, tools: tuple, agents: tuple, mcps: tuple
|
|
891
|
-
) -> tuple[list, list, list]:
|
|
880
|
+
def _resolve_resources(client: Any, tools: tuple, agents: tuple, mcps: tuple) -> tuple[list, list, list]:
|
|
892
881
|
"""Resolve tool, agent, and MCP references."""
|
|
893
|
-
resolved_tools = _resolve_resources_by_name(
|
|
894
|
-
|
|
895
|
-
)
|
|
896
|
-
resolved_agents = _resolve_resources_by_name(
|
|
897
|
-
client, agents, "agent", client.find_agents, "Agent"
|
|
898
|
-
)
|
|
899
|
-
resolved_mcps = _resolve_resources_by_name(
|
|
900
|
-
client, mcps, "mcp", client.find_mcps, "MCP"
|
|
901
|
-
)
|
|
882
|
+
resolved_tools = _resolve_resources_by_name(client, tools, "tool", client.find_tools, "Tool")
|
|
883
|
+
resolved_agents = _resolve_resources_by_name(client, agents, "agent", client.find_agents, "Agent")
|
|
884
|
+
resolved_mcps = _resolve_resources_by_name(client, mcps, "mcp", client.find_mcps, "MCP")
|
|
902
885
|
|
|
903
886
|
return resolved_tools, resolved_agents, resolved_mcps
|
|
904
887
|
|
|
@@ -925,16 +908,12 @@ def _build_create_kwargs(
|
|
|
925
908
|
}
|
|
926
909
|
|
|
927
910
|
# Handle language model selection
|
|
928
|
-
lm_selection_dict, should_strip_lm_identity = resolve_language_model_selection(
|
|
929
|
-
merged_data, model
|
|
930
|
-
)
|
|
911
|
+
lm_selection_dict, should_strip_lm_identity = resolve_language_model_selection(merged_data, model)
|
|
931
912
|
create_kwargs.update(lm_selection_dict)
|
|
932
913
|
|
|
933
914
|
# Handle import file specific logic
|
|
934
915
|
if import_file:
|
|
935
|
-
_add_import_file_attributes(
|
|
936
|
-
create_kwargs, merged_data, should_strip_lm_identity
|
|
937
|
-
)
|
|
916
|
+
_add_import_file_attributes(create_kwargs, merged_data, should_strip_lm_identity)
|
|
938
917
|
|
|
939
918
|
return create_kwargs
|
|
940
919
|
|
|
@@ -980,12 +959,7 @@ def _get_language_model_display_name(agent: Any, model: str | None) -> str:
|
|
|
980
959
|
lm_display = getattr(agent, "model", None)
|
|
981
960
|
if not lm_display:
|
|
982
961
|
cfg = getattr(agent, "agent_config", {}) or {}
|
|
983
|
-
lm_display = (
|
|
984
|
-
cfg.get("lm_name")
|
|
985
|
-
or cfg.get("model")
|
|
986
|
-
or model
|
|
987
|
-
or f"{DEFAULT_MODEL} (backend default)"
|
|
988
|
-
)
|
|
962
|
+
lm_display = cfg.get("lm_name") or cfg.get("model") or model or f"{DEFAULT_MODEL} (backend default)"
|
|
989
963
|
return lm_display
|
|
990
964
|
|
|
991
965
|
|
|
@@ -1020,7 +994,7 @@ def _handle_command_exception(ctx: Any, e: Exception) -> None:
|
|
|
1020
994
|
handle_json_output(ctx, error=e)
|
|
1021
995
|
if get_ctx_value(ctx, "view") != "json":
|
|
1022
996
|
print_api_error(e)
|
|
1023
|
-
raise click.
|
|
997
|
+
raise click.exceptions.Exit(1) from e
|
|
1024
998
|
|
|
1025
999
|
|
|
1026
1000
|
def _handle_creation_exception(ctx: Any, e: Exception) -> None:
|
|
@@ -1074,13 +1048,9 @@ def create(
|
|
|
1074
1048
|
|
|
1075
1049
|
# Handle import file or CLI args
|
|
1076
1050
|
if import_file:
|
|
1077
|
-
merged_data = _handle_import_file_logic(
|
|
1078
|
-
import_file, model, name, instruction, tools, agents, mcps, timeout
|
|
1079
|
-
)
|
|
1051
|
+
merged_data = _handle_import_file_logic(import_file, model, name, instruction, tools, agents, mcps, timeout)
|
|
1080
1052
|
else:
|
|
1081
|
-
merged_data = _build_cli_args_data(
|
|
1082
|
-
name, instruction, model, tools, agents, mcps, timeout
|
|
1083
|
-
)
|
|
1053
|
+
merged_data = _build_cli_args_data(name, instruction, model, tools, agents, mcps, timeout)
|
|
1084
1054
|
|
|
1085
1055
|
# Extract and validate fields
|
|
1086
1056
|
(
|
|
@@ -1092,14 +1062,10 @@ def create(
|
|
|
1092
1062
|
mcps,
|
|
1093
1063
|
timeout,
|
|
1094
1064
|
) = _extract_and_validate_fields(merged_data)
|
|
1095
|
-
name, instruction, timeout = _validate_and_coerce_fields(
|
|
1096
|
-
name, instruction, timeout
|
|
1097
|
-
)
|
|
1065
|
+
name, instruction, timeout = _validate_and_coerce_fields(name, instruction, timeout)
|
|
1098
1066
|
|
|
1099
1067
|
# Resolve resources
|
|
1100
|
-
resolved_tools, resolved_agents, resolved_mcps = _resolve_resources(
|
|
1101
|
-
client, tools, agents, mcps
|
|
1102
|
-
)
|
|
1068
|
+
resolved_tools, resolved_agents, resolved_mcps = _resolve_resources(client, tools, agents, mcps)
|
|
1103
1069
|
|
|
1104
1070
|
# Build create kwargs
|
|
1105
1071
|
create_kwargs = _build_create_kwargs(
|
|
@@ -1129,7 +1095,7 @@ def _get_agent_for_update(client: Any, agent_id: str) -> Any:
|
|
|
1129
1095
|
try:
|
|
1130
1096
|
return client.agents.get_agent_by_id(agent_id)
|
|
1131
1097
|
except Exception as e:
|
|
1132
|
-
raise click.ClickException(f"Agent with ID '{agent_id}' not found: {e}")
|
|
1098
|
+
raise click.ClickException(f"Agent with ID '{agent_id}' not found: {e}") from e
|
|
1133
1099
|
|
|
1134
1100
|
|
|
1135
1101
|
def _handle_update_import_file(
|
|
@@ -1211,16 +1177,12 @@ def _handle_update_import_config(
|
|
|
1211
1177
|
if not import_file:
|
|
1212
1178
|
return
|
|
1213
1179
|
|
|
1214
|
-
lm_selection, should_strip_lm_identity = resolve_language_model_selection(
|
|
1215
|
-
merged_data, None
|
|
1216
|
-
)
|
|
1180
|
+
lm_selection, should_strip_lm_identity = resolve_language_model_selection(merged_data, None)
|
|
1217
1181
|
update_data.update(lm_selection)
|
|
1218
1182
|
|
|
1219
1183
|
raw_cfg = merged_data.get("agent_config") if isinstance(merged_data, dict) else None
|
|
1220
1184
|
if isinstance(raw_cfg, dict):
|
|
1221
|
-
update_data["agent_config"] = sanitize_agent_config(
|
|
1222
|
-
raw_cfg, strip_lm_identity=should_strip_lm_identity
|
|
1223
|
-
)
|
|
1185
|
+
update_data["agent_config"] = sanitize_agent_config(raw_cfg, strip_lm_identity=should_strip_lm_identity)
|
|
1224
1186
|
|
|
1225
1187
|
excluded_fields = {
|
|
1226
1188
|
"name",
|
|
@@ -1289,13 +1251,9 @@ def update(
|
|
|
1289
1251
|
agents,
|
|
1290
1252
|
mcps,
|
|
1291
1253
|
timeout,
|
|
1292
|
-
) = _handle_update_import_file(
|
|
1293
|
-
import_file, name, instruction, tools, agents, mcps, timeout
|
|
1294
|
-
)
|
|
1254
|
+
) = _handle_update_import_file(import_file, name, instruction, tools, agents, mcps, timeout)
|
|
1295
1255
|
|
|
1296
|
-
update_data = _build_update_data(
|
|
1297
|
-
name, instruction, tools, agents, mcps, timeout
|
|
1298
|
-
)
|
|
1256
|
+
update_data = _build_update_data(name, instruction, tools, agents, mcps, timeout)
|
|
1299
1257
|
|
|
1300
1258
|
if merged_data:
|
|
1301
1259
|
_handle_update_import_config(import_file, merged_data, update_data)
|
|
@@ -1333,7 +1291,7 @@ def delete(ctx: Any, agent_id: str, yes: bool) -> None:
|
|
|
1333
1291
|
try:
|
|
1334
1292
|
agent = client.agents.get_agent_by_id(agent_id)
|
|
1335
1293
|
except Exception as e:
|
|
1336
|
-
raise click.ClickException(f"Agent with ID '{agent_id}' not found: {e}")
|
|
1294
|
+
raise click.ClickException(f"Agent with ID '{agent_id}' not found: {e}") from e
|
|
1337
1295
|
|
|
1338
1296
|
# Confirm deletion when not forced
|
|
1339
1297
|
if not yes and not display_confirmation_prompt("Agent", agent.name):
|
|
@@ -1365,9 +1323,7 @@ def delete(ctx: Any, agent_id: str, yes: bool) -> None:
|
|
|
1365
1323
|
"--base-url",
|
|
1366
1324
|
help="Custom LangFlow server base URL (overrides LANGFLOW_BASE_URL env var)",
|
|
1367
1325
|
)
|
|
1368
|
-
@click.option(
|
|
1369
|
-
"--api-key", help="Custom LangFlow API key (overrides LANGFLOW_API_KEY env var)"
|
|
1370
|
-
)
|
|
1326
|
+
@click.option("--api-key", help="Custom LangFlow API key (overrides LANGFLOW_API_KEY env var)")
|
|
1371
1327
|
@output_flags()
|
|
1372
1328
|
@click.pass_context
|
|
1373
1329
|
def sync_langflow(ctx: Any, base_url: str | None, api_key: str | None) -> None:
|
|
@@ -1396,15 +1352,16 @@ def sync_langflow(ctx: Any, base_url: str | None, api_key: str | None) -> None:
|
|
|
1396
1352
|
# Show success message for non-JSON output
|
|
1397
1353
|
if get_ctx_value(ctx, "view") != "json":
|
|
1398
1354
|
# Extract some useful info from the result
|
|
1399
|
-
success_count = result.get("data", {}).get("created_count", 0) + result.get(
|
|
1400
|
-
"
|
|
1401
|
-
)
|
|
1355
|
+
success_count = result.get("data", {}).get("created_count", 0) + result.get("data", {}).get(
|
|
1356
|
+
"updated_count", 0
|
|
1357
|
+
)
|
|
1402
1358
|
total_count = result.get("data", {}).get("total_processed", 0)
|
|
1403
1359
|
|
|
1404
1360
|
handle_rich_output(
|
|
1405
1361
|
ctx,
|
|
1406
1362
|
markup_text(
|
|
1407
|
-
f"[{SUCCESS_STYLE}]✅ Successfully synced {success_count} LangFlow agents
|
|
1363
|
+
f"[{SUCCESS_STYLE}]✅ Successfully synced {success_count} LangFlow agents "
|
|
1364
|
+
f"({total_count} total processed)[/]"
|
|
1408
1365
|
),
|
|
1409
1366
|
)
|
|
1410
1367
|
|
|
@@ -57,9 +57,7 @@ def set_config(key: str, value: str) -> None:
|
|
|
57
57
|
valid_keys = ["api_url", "api_key"]
|
|
58
58
|
|
|
59
59
|
if key not in valid_keys:
|
|
60
|
-
console.print(
|
|
61
|
-
f"[{ERROR_STYLE}]Error: Invalid key '{key}'. Valid keys are: {', '.join(valid_keys)}[/]"
|
|
62
|
-
)
|
|
60
|
+
console.print(f"[{ERROR_STYLE}]Error: Invalid key '{key}'. Valid keys are: {', '.join(valid_keys)}[/]")
|
|
63
61
|
raise click.ClickException(f"Invalid configuration key: {key}")
|
|
64
62
|
|
|
65
63
|
config = load_config()
|
|
@@ -67,9 +65,7 @@ def set_config(key: str, value: str) -> None:
|
|
|
67
65
|
save_config(config)
|
|
68
66
|
|
|
69
67
|
if key == "api_key":
|
|
70
|
-
console.print(
|
|
71
|
-
Text(f"✅ Set {key} = {_mask_api_key(value)}", style=SUCCESS_STYLE)
|
|
72
|
-
)
|
|
68
|
+
console.print(Text(f"✅ Set {key} = {_mask_api_key(value)}", style=SUCCESS_STYLE))
|
|
73
69
|
else:
|
|
74
70
|
console.print(Text(f"✅ Set {key} = {value}", style=SUCCESS_STYLE))
|
|
75
71
|
|
|
@@ -81,9 +77,7 @@ def get_config(key: str) -> None:
|
|
|
81
77
|
config = load_config()
|
|
82
78
|
|
|
83
79
|
if key not in config:
|
|
84
|
-
console.print(
|
|
85
|
-
markup_text(f"[{WARNING_STYLE}]Configuration key '{key}' not found.[/]")
|
|
86
|
-
)
|
|
80
|
+
console.print(markup_text(f"[{WARNING_STYLE}]Configuration key '{key}' not found.[/]"))
|
|
87
81
|
raise click.ClickException(f"Configuration key not found: {key}")
|
|
88
82
|
|
|
89
83
|
value = config[key]
|
|
@@ -101,9 +95,7 @@ def unset_config(key: str) -> None:
|
|
|
101
95
|
config = load_config()
|
|
102
96
|
|
|
103
97
|
if key not in config:
|
|
104
|
-
console.print(
|
|
105
|
-
markup_text(f"[{WARNING_STYLE}]Configuration key '{key}' not found.[/]")
|
|
106
|
-
)
|
|
98
|
+
console.print(markup_text(f"[{WARNING_STYLE}]Configuration key '{key}' not found.[/]"))
|
|
107
99
|
return
|
|
108
100
|
|
|
109
101
|
del config[key]
|
|
@@ -128,9 +120,7 @@ def reset_config(force: bool) -> None:
|
|
|
128
120
|
|
|
129
121
|
if not file_exists and not config_data:
|
|
130
122
|
console.print(f"[{WARNING_STYLE}]No configuration found to reset.[/]")
|
|
131
|
-
console.print(
|
|
132
|
-
Text("✅ Configuration reset (nothing to remove).", style=SUCCESS_STYLE)
|
|
133
|
-
)
|
|
123
|
+
console.print(Text("✅ Configuration reset (nothing to remove).", style=SUCCESS_STYLE))
|
|
134
124
|
return
|
|
135
125
|
|
|
136
126
|
if file_exists:
|
|
@@ -188,9 +178,7 @@ def _mask_api_key(value: str | None) -> str:
|
|
|
188
178
|
def _print_missing_config_hint() -> None:
|
|
189
179
|
hint = command_hint("config configure", slash_command="login")
|
|
190
180
|
if hint:
|
|
191
|
-
console.print(
|
|
192
|
-
f"[{WARNING_STYLE}]No configuration found.[/] Run {format_command_hint(hint) or hint} to set up."
|
|
193
|
-
)
|
|
181
|
+
console.print(f"[{WARNING_STYLE}]No configuration found.[/] Run {format_command_hint(hint) or hint} to set up.")
|
|
194
182
|
else:
|
|
195
183
|
console.print(f"[{WARNING_STYLE}]No configuration found.[/]")
|
|
196
184
|
|
|
@@ -208,9 +196,7 @@ def _render_config_table(config: dict[str, str]) -> None:
|
|
|
208
196
|
|
|
209
197
|
|
|
210
198
|
def _render_configuration_header() -> None:
|
|
211
|
-
branding = AIPBranding.create_from_sdk(
|
|
212
|
-
sdk_version=_SDK_VERSION, package_name="glaip-sdk"
|
|
213
|
-
)
|
|
199
|
+
branding = AIPBranding.create_from_sdk(sdk_version=_SDK_VERSION, package_name="glaip-sdk")
|
|
214
200
|
heading = "[bold]>_ GDP Labs AI Agents Package (AIP CLI)[/bold]"
|
|
215
201
|
console.print(heading)
|
|
216
202
|
console.print()
|
|
@@ -249,9 +235,7 @@ def _prompt_api_key(config: dict[str, str]) -> None:
|
|
|
249
235
|
|
|
250
236
|
def _save_configuration(config: dict[str, str]) -> None:
|
|
251
237
|
save_config(config)
|
|
252
|
-
console.print(
|
|
253
|
-
Text(f"\n✅ Configuration saved to: {CONFIG_FILE}", style=SUCCESS_STYLE)
|
|
254
|
-
)
|
|
238
|
+
console.print(Text(f"\n✅ Configuration saved to: {CONFIG_FILE}", style=SUCCESS_STYLE))
|
|
255
239
|
|
|
256
240
|
|
|
257
241
|
def _test_and_report_connection(config: dict[str, str]) -> None:
|
|
@@ -274,17 +258,13 @@ def _test_and_report_connection(config: dict[str, str]) -> None:
|
|
|
274
258
|
style=WARNING_STYLE,
|
|
275
259
|
)
|
|
276
260
|
)
|
|
277
|
-
console.print(
|
|
278
|
-
" You may need to check your API permissions or network access"
|
|
279
|
-
)
|
|
261
|
+
console.print(" You may need to check your API permissions or network access")
|
|
280
262
|
except Exception as exc:
|
|
281
263
|
console.print(Text(f"❌ Connection failed: {exc}"))
|
|
282
264
|
console.print(" Please check your API URL and key")
|
|
283
265
|
hint_status = command_hint("status", slash_command="status")
|
|
284
266
|
if hint_status:
|
|
285
|
-
console.print(
|
|
286
|
-
f" You can run {format_command_hint(hint_status) or hint_status} later to test again"
|
|
287
|
-
)
|
|
267
|
+
console.print(f" You can run {format_command_hint(hint_status) or hint_status} later to test again")
|
|
288
268
|
finally:
|
|
289
269
|
if client is not None:
|
|
290
270
|
client.close()
|
|
@@ -294,11 +274,7 @@ def _print_post_configuration_hints() -> None:
|
|
|
294
274
|
console.print("\n💡 You can now use AIP CLI commands!")
|
|
295
275
|
hint_status = command_hint("status", slash_command="status")
|
|
296
276
|
if hint_status:
|
|
297
|
-
console.print(
|
|
298
|
-
f" • Run {format_command_hint(hint_status) or hint_status} to check connection"
|
|
299
|
-
)
|
|
277
|
+
console.print(f" • Run {format_command_hint(hint_status) or hint_status} to check connection")
|
|
300
278
|
hint_agents = command_hint("agents list", slash_command="agents")
|
|
301
279
|
if hint_agents:
|
|
302
|
-
console.print(
|
|
303
|
-
f" • Run {format_command_hint(hint_agents) or hint_agents} to see your agents"
|
|
304
|
-
)
|
|
280
|
+
console.print(f" • Run {format_command_hint(hint_agents) or hint_agents} to see your agents")
|