glaip-sdk 0.0.10__py3-none-any.whl → 0.0.11__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/cli/utils.py CHANGED
@@ -828,7 +828,7 @@ def _build_table_group(
828
828
  table = _create_table(columns, title)
829
829
  for row in rows:
830
830
  table.add_row(*[str(row.get(key, "N/A")) for key, _, _, _ in columns])
831
- footer = Text(f"\n[dim]Total {len(rows)} items[/dim]")
831
+ footer = Text.from_markup(f"\n[dim]Total {len(rows)} items[/dim]")
832
832
  return Group(table, footer)
833
833
 
834
834
 
@@ -872,7 +872,7 @@ def _handle_markdown_output(
872
872
 
873
873
  def _handle_empty_items(title: str) -> None:
874
874
  """Handle case when no items are found."""
875
- console.print(Text(f"[yellow]No {title.lower()} found.[/yellow]"))
875
+ console.print(Text.from_markup(f"[yellow]No {title.lower()} found.[/yellow]"))
876
876
 
877
877
 
878
878
  def _should_use_fuzzy_picker() -> bool:
@@ -916,7 +916,9 @@ def _print_selection_tip(title: str) -> None:
916
916
  """Print the contextual follow-up tip after a fuzzy selection."""
917
917
 
918
918
  tip_cmd = _resource_tip_command(title)
919
- console.print(Text(f"\n[dim]Tip: use `{tip_cmd} <ID>` for details[/dim]"))
919
+ console.print(
920
+ Text.from_markup(f"\n[dim]Tip: use `{tip_cmd} <ID>` for details[/dim]")
921
+ )
920
922
 
921
923
 
922
924
  def _handle_fuzzy_pick_selection(
@@ -936,11 +938,21 @@ def _handle_fuzzy_pick_selection(
936
938
 
937
939
 
938
940
  def _handle_table_output(
939
- rows: list[dict[str, Any]], columns: list[tuple], title: str
941
+ rows: list[dict[str, Any]],
942
+ columns: list[tuple],
943
+ title: str,
944
+ *,
945
+ use_pager: bool | None = None,
940
946
  ) -> None:
941
947
  """Handle table output with paging."""
942
948
  content = _build_table_group(rows, columns, title)
943
- if _should_page_output(len(rows), console.is_terminal and os.isatty(1)):
949
+ should_page = (
950
+ _should_page_output(len(rows), console.is_terminal and os.isatty(1))
951
+ if use_pager is None
952
+ else use_pager
953
+ )
954
+
955
+ if should_page:
944
956
  ansi = _render_ansi(content)
945
957
  if not _page_with_system_pager(ansi):
946
958
  with console.pager(styles=True):
@@ -955,8 +967,11 @@ def output_list(
955
967
  title: str,
956
968
  columns: list[tuple[str, str, str, int | None]],
957
969
  transform_func: Callable | None = None,
970
+ *,
971
+ skip_picker: bool = False,
972
+ use_pager: bool | None = None,
958
973
  ) -> None:
959
- """Display a list with fuzzy palette by default on TTY, Rich table as fallback."""
974
+ """Display a list with optional fuzzy palette for quick selection."""
960
975
  fmt = _get_view(ctx)
961
976
  rows = _normalise_rows(items, transform_func)
962
977
  rows = _mask_rows_if_configured(rows)
@@ -983,10 +998,10 @@ def output_list(
983
998
  except Exception:
984
999
  pass
985
1000
 
986
- if _handle_fuzzy_pick_selection(rows, columns, title):
1001
+ if not skip_picker and _handle_fuzzy_pick_selection(rows, columns, title):
987
1002
  return
988
1003
 
989
- _handle_table_output(rows, columns, title)
1004
+ _handle_table_output(rows, columns, title, use_pager=use_pager)
990
1005
 
991
1006
 
992
1007
  # ------------------------- Output flags decorator ------------------------ #
glaip_sdk/models.py CHANGED
@@ -179,8 +179,6 @@ class MCP(BaseModel):
179
179
  name: str
180
180
  description: str | None = None
181
181
  config: dict[str, Any] | None = None
182
- framework: str | None = None
183
- version: str | None = None
184
182
  transport: str | None = None # "sse" or "http"
185
183
  authentication: dict[str, Any] | None = None
186
184
  metadata: dict[str, Any] | None = None
@@ -57,13 +57,9 @@ def convert_export_to_import_format(
57
57
  """
58
58
  import_data = data.copy()
59
59
 
60
- # Convert tools from dicts to IDs
61
- if "tools" in import_data and isinstance(import_data["tools"], list):
62
- import_data["tools"] = extract_ids_from_export(import_data["tools"])
63
-
64
- # Convert agents from dicts to IDs
65
- if "agents" in import_data and isinstance(import_data["agents"], list):
66
- import_data["agents"] = extract_ids_from_export(import_data["agents"])
60
+ for key in ["tools", "agents", "mcps"]:
61
+ if key in import_data and isinstance(import_data[key], list):
62
+ import_data[key] = extract_ids_from_export(import_data[key])
67
63
 
68
64
  return import_data
69
65
 
@@ -10,10 +10,15 @@ Authors:
10
10
  import json
11
11
  from collections.abc import Callable, Iterable
12
12
  from pathlib import Path
13
- from typing import Any
13
+ from typing import TYPE_CHECKING, Any
14
14
 
15
15
  import yaml
16
16
 
17
+ if TYPE_CHECKING: # pragma: no cover - type-only imports
18
+ from rich.console import Console
19
+
20
+ from glaip_sdk.models import MCP
21
+
17
22
 
18
23
  def read_json(file_path: Path) -> dict[str, Any]:
19
24
  """Read data from JSON file.
@@ -132,7 +137,8 @@ def load_resource_from_file(file_path: Path) -> dict[str, Any]:
132
137
  return read_json(file_path)
133
138
  else:
134
139
  raise ValueError(
135
- f"Unsupported file format: {file_path.suffix}. Only JSON and YAML files are supported."
140
+ f"Unsupported file format: {file_path.suffix}. "
141
+ f"Only JSON and YAML files are supported."
136
142
  )
137
143
 
138
144
 
@@ -305,6 +311,91 @@ def _should_include_attribute(key: str, value: Any) -> bool:
305
311
  return True
306
312
 
307
313
 
314
+ def strip_empty_fields(data: dict[str, Any]) -> dict[str, Any]:
315
+ """Recursively remove None values and empty dictionaries from a dictionary.
316
+
317
+ Args:
318
+ data: Dictionary to clean
319
+
320
+ Returns:
321
+ Cleaned dictionary with None values and empty dicts removed
322
+ """
323
+ if not isinstance(data, dict):
324
+ return data
325
+
326
+ cleaned = {}
327
+ for key, value in data.items():
328
+ if value is None:
329
+ continue
330
+ if isinstance(value, dict):
331
+ nested = strip_empty_fields(value)
332
+ if nested: # Only include non-empty dicts
333
+ cleaned[key] = nested
334
+ else:
335
+ cleaned[key] = value
336
+
337
+ return cleaned
338
+
339
+
340
+ def build_mcp_export_payload(
341
+ mcp: "MCP",
342
+ *,
343
+ prompt_for_secrets: bool,
344
+ placeholder: str,
345
+ console: "Console",
346
+ ) -> dict[str, Any]:
347
+ """Build MCP export payload with authentication secret handling.
348
+
349
+ This function prepares an MCP resource for export by:
350
+ 1. Starting from model_dump(exclude_none=True) for API alignment
351
+ 2. Cleaning internal fields (_client, empty metadata)
352
+ 3. Processing authentication with secret capture/placeholder logic
353
+ 4. Removing empty fields recursively
354
+
355
+ Args:
356
+ mcp: MCP model instance to export
357
+ prompt_for_secrets: Whether to interactively prompt for missing secrets
358
+ placeholder: Placeholder text for missing secrets
359
+ console: Rich Console instance for user interaction
360
+
361
+ Returns:
362
+ Dictionary ready for export (JSON/YAML serialization)
363
+
364
+ Raises:
365
+ ImportError: If required modules (auth helpers) are not available
366
+ """
367
+ # Import here to avoid circular dependency
368
+ from glaip_sdk.cli.auth import prepare_authentication_export
369
+
370
+ # Start with model dump (excludes None values automatically)
371
+ payload = mcp.model_dump(exclude_none=True)
372
+
373
+ # Remove internal/CLI fields
374
+ payload.pop("_client", None)
375
+
376
+ # Remove empty metadata dict
377
+ if "metadata" in payload and not payload["metadata"]:
378
+ payload.pop("metadata")
379
+
380
+ # Process authentication section
381
+ if "authentication" in payload:
382
+ processed_auth = prepare_authentication_export(
383
+ payload["authentication"],
384
+ prompt_for_secrets=prompt_for_secrets,
385
+ placeholder=placeholder,
386
+ console=console,
387
+ )
388
+ if processed_auth:
389
+ payload["authentication"] = processed_auth
390
+ else:
391
+ payload.pop("authentication")
392
+
393
+ # Apply final cleanup to remove any remaining empty fields
394
+ payload = strip_empty_fields(payload)
395
+
396
+ return payload
397
+
398
+
308
399
  def validate_json_string(json_str: str) -> dict[str, Any]:
309
400
  """Validate JSON string and return parsed data.
310
401
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: glaip-sdk
3
- Version: 0.0.10
3
+ Version: 0.0.11
4
4
  Summary: Python SDK for GL AIP (GDP Labs AI Agent Package) - Simplified CLI Design
5
5
  License: MIT
6
6
  Author: Raymond Christopher
@@ -13,6 +13,7 @@ Classifier: Programming Language :: Python :: 3.11
13
13
  Classifier: Programming Language :: Python :: 3.12
14
14
  Requires-Dist: click (>=8.2.0,<8.3.0)
15
15
  Requires-Dist: httpx (>=0.28.1)
16
+ Requires-Dist: packaging (>=23.2)
16
17
  Requires-Dist: pydantic (>=2.0.0)
17
18
  Requires-Dist: python-dotenv (>=1.1.1,<2.0.0)
18
19
  Requires-Dist: pyyaml (>=6.0.0)
@@ -3,21 +3,23 @@ glaip_sdk/_version.py,sha256=tGkFWAVu2ry4Hy7j-u7ophGbPRX8y-ngBbXDhN1VBIQ,2007
3
3
  glaip_sdk/branding.py,sha256=xsHL7nRAWuwJrAvCi2fZhaPD-AWvdcLNoTVmlw4gZKc,5604
4
4
  glaip_sdk/cli/__init__.py,sha256=xCCfuF1Yc7mpCDcfhHZTX0vizvtrDSLeT8MJ3V7m5A0,156
5
5
  glaip_sdk/cli/agent_config.py,sha256=VHjebw68wAdhGUzYdPH8qz10oADZPRgUQcPW6F7iHIU,2421
6
+ glaip_sdk/cli/auth.py,sha256=eYdtGmJ3XgiO96hq_69GF6b3W-aRWZrDQ-6bHuaRX4M,13517
6
7
  glaip_sdk/cli/commands/__init__.py,sha256=x0CZlZbZHoHvuzfoTWIyEch6WmNnbPzxajrox6riYp0,173
7
- glaip_sdk/cli/commands/agents.py,sha256=1xGSoH6C9hSaGglXf4pnloqX5gJQIPsgHhkliiWQQcY,39988
8
+ glaip_sdk/cli/commands/agents.py,sha256=97dzowjHgk5knyHuI-0z2ojvqNlkebNN1-ikGEoS5sc,40623
8
9
  glaip_sdk/cli/commands/configure.py,sha256=eRDzsaKV4fl2lJt8ieS4g2-xRnaa02eAAPW8xBf-tqA,7507
9
- glaip_sdk/cli/commands/mcps.py,sha256=fRCRQMAnogT76lHUn_nuqkge_x75Fj023CDRgdoj0kQ,14343
10
+ glaip_sdk/cli/commands/mcps.py,sha256=a2p8KfPYv4YaC9qiC7LEyh8oPsbLAwXv4dsnwxZ_juI,19752
10
11
  glaip_sdk/cli/commands/models.py,sha256=Ra3-50BPScNs0Q-j4b7U4iK0hNooucEyVgHpQ11-pt8,1700
11
12
  glaip_sdk/cli/commands/tools.py,sha256=MOM9Db3HGL1stF-WvL5cZXjw-iZo2qc-oyKQHy6VwIM,18690
12
13
  glaip_sdk/cli/display.py,sha256=jE20swoRKzpYUmc0jgbeonaXKeE9x95hfjWAEdnBYRc,8727
13
14
  glaip_sdk/cli/io.py,sha256=GPkw3pQMLBGoD5GH-KlbKpNRlVWFZOXHE17F7V3kQsI,3343
14
- glaip_sdk/cli/main.py,sha256=uWuntvFl0hQSLfNa1rXb-J2zUK_msf3vrSbbrqBcEc4,12692
15
+ glaip_sdk/cli/main.py,sha256=3Bl8u9t1MekzaNrAZqsx4TukbzzFdi6Wss6jvTDos00,12930
15
16
  glaip_sdk/cli/resolution.py,sha256=BOw2NchReLKewAwBAZLWw_3_bI7u3tfzQEO7kQbIiGE,2067
16
17
  glaip_sdk/cli/slash/__init__.py,sha256=Vdv6Y8bu-pA8dxDlyP4XrhudBPivztUozhLAz9vaLig,682
17
18
  glaip_sdk/cli/slash/agent_session.py,sha256=pDOwGXNHuyJIulrGYu1pacyF3oxHWeDQY-Uv92h2qVg,6859
18
19
  glaip_sdk/cli/slash/prompt.py,sha256=Pr5SSTOKFssRsi-AujOm5_BCW_f5MxgLwJ3CCji1ogM,7356
19
- glaip_sdk/cli/slash/session.py,sha256=W8Fk1t9qqr1B9clhIwsAuv3i_6yYk_vEAuM00zGHxHM,30482
20
- glaip_sdk/cli/utils.py,sha256=7UNg4qDIR0BDgiWJgtEDaVmRa9fhfUsBLiygcuTDxmE,42236
20
+ glaip_sdk/cli/slash/session.py,sha256=U5UEL6eIvNkIJcSz04Uf8Ql0EptmLJukqHxDCAJ-nOQ,31097
21
+ glaip_sdk/cli/update_notifier.py,sha256=uVbjZJnW4znTzx4AkqsDO4NfXiF-mtQiypTkJByAVuM,3236
22
+ glaip_sdk/cli/utils.py,sha256=98n1tovTUSqS5BIUl4cz6zGoRSSJiXFGJW8oD0xIm2g,42537
21
23
  glaip_sdk/cli/validators.py,sha256=USbBgY86AwuDHO-Q_g8g7hu-ot4NgITBsWjTWIl62ms,5569
22
24
  glaip_sdk/client/__init__.py,sha256=nYLXfBVTTWwKjP0e63iumPYO4k5FifwWaELQPaPIKIg,188
23
25
  glaip_sdk/client/agents.py,sha256=FSKubF40wptMNIheC3_iawiX2CRbhTcNLFiz4qkPC6k,34659
@@ -28,14 +30,14 @@ glaip_sdk/client/tools.py,sha256=n8DIiOOf1YU_j9JK3Bx2-rDnkpckPi0MI9Ok2s1kwa4,166
28
30
  glaip_sdk/client/validators.py,sha256=NtPsWjQLjj25LiUnmR-WuS8lL5p4MVRaYT9UVRmj9bo,8809
29
31
  glaip_sdk/config/constants.py,sha256=ysEobMiXlLZGIOEaqTdHpPF8kmg5nbLn7BIcBvTCuHM,819
30
32
  glaip_sdk/exceptions.py,sha256=DJgaIcvGA09qIX10-ypYgQQ5_k5N3qknmiIFP3p4Z7E,1872
31
- glaip_sdk/models.py,sha256=Ry_Ihd6FuC0JGb0Obd5T3A22AOp2r9xStQisfE8uo8c,8822
33
+ glaip_sdk/models.py,sha256=0Y65LXpLqUY3IYVPIzP7jm8gdZUMw-EKRKGC1ZOLOcA,8758
32
34
  glaip_sdk/rich_components.py,sha256=pmJd-81OQE8bC9UOXtga5rsax4zphKlzCZ1JoWbbQzQ,803
33
35
  glaip_sdk/utils/__init__.py,sha256=fmVGcUFa7G0CCfSMSqfNU2BqFl36G1gOFyDfTvtJfVw,926
34
36
  glaip_sdk/utils/agent_config.py,sha256=b7_J5DELyk0b_XEoi7tsxbS3wqzAKbMa-3_C-65pPIY,6791
35
37
  glaip_sdk/utils/client_utils.py,sha256=M6rZloMKyONaZfI0RtU5tnkibwrIJL5Udw4wPMKkJcw,13588
36
38
  glaip_sdk/utils/display.py,sha256=94s9lYF_8ra8jpeqOkbVrUm8oidtCE6OtucyxLQPKmU,3105
37
39
  glaip_sdk/utils/general.py,sha256=V5hJrIpYDvDsldU_nChHpuvV2AwhFLUI7Qvcaihq_8A,2270
38
- glaip_sdk/utils/import_export.py,sha256=Wxt2QuWI7JexSkkcBOdTgeYs1nly35yppaTNeF28XJo,5400
40
+ glaip_sdk/utils/import_export.py,sha256=az_0jCpMB7I6N5HygS2uc62-W6ddm4buEwm6gTsalhY,5203
39
41
  glaip_sdk/utils/rendering/__init__.py,sha256=vXjwk5rPhhfPyD8S0DnV4GFFEtPJp4HCCg1Um9SXfs0,70
40
42
  glaip_sdk/utils/rendering/formatting.py,sha256=_k8tkcobctmHvdygMljZF7-ALGXpD9-hHF1CNtM2KMU,7201
41
43
  glaip_sdk/utils/rendering/models.py,sha256=SS34_00FaoGuSYn-viBkAtIbq7cJNwwPjpxnvyeUmxI,1567
@@ -51,9 +53,9 @@ glaip_sdk/utils/rendering/steps.py,sha256=4zdeyKxMbUzCal4-yv8yf18144cs5wwXaxhe6m
51
53
  glaip_sdk/utils/resource_refs.py,sha256=0YzblJNfRhz9xhpaKE9aE68XEV-6_ssr0fIkiMVOka0,5489
52
54
  glaip_sdk/utils/rich_utils.py,sha256=-Ij-1bIJvnVAi6DrfftchIlMcvOTjVmSE0Qqax0EY_s,763
53
55
  glaip_sdk/utils/run_renderer.py,sha256=d_VMI6LbvHPUUeRmGqh5wK_lHqDEIAcym2iqpbtDad0,1365
54
- glaip_sdk/utils/serialization.py,sha256=cUE6PxqTsfJuEEmsk_Li3QmaDavTIPotEA-BQ-v5exY,9043
56
+ glaip_sdk/utils/serialization.py,sha256=T1yt_8G2DCFpcxx7XnqFl5slksRXfBCUuLQJTreGYEQ,11806
55
57
  glaip_sdk/utils/validation.py,sha256=QNORcdyvuliEs4EH2_mkDgmoyT9utgl7YNhaf45SEf8,6992
56
- glaip_sdk-0.0.10.dist-info/METADATA,sha256=ryaYhShJ7h43sX_oXbkLdKqpy5-eRgAP0lDczHVkCog,4950
57
- glaip_sdk-0.0.10.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
58
- glaip_sdk-0.0.10.dist-info/entry_points.txt,sha256=EGs8NO8J1fdFMWA3CsF7sKBEvtHb_fujdCoNPhfMouE,47
59
- glaip_sdk-0.0.10.dist-info/RECORD,,
58
+ glaip_sdk-0.0.11.dist-info/METADATA,sha256=Z8hxLQAn8fWQtisQyZAi6QgOCSxDpEWw4gLbTBMDrxU,4984
59
+ glaip_sdk-0.0.11.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
60
+ glaip_sdk-0.0.11.dist-info/entry_points.txt,sha256=EGs8NO8J1fdFMWA3CsF7sKBEvtHb_fujdCoNPhfMouE,47
61
+ glaip_sdk-0.0.11.dist-info/RECORD,,