glaip-sdk 0.1.3__py3-none-any.whl → 0.6.19__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.
Files changed (146) hide show
  1. glaip_sdk/__init__.py +44 -4
  2. glaip_sdk/_version.py +9 -0
  3. glaip_sdk/agents/__init__.py +27 -0
  4. glaip_sdk/agents/base.py +1196 -0
  5. glaip_sdk/branding.py +13 -0
  6. glaip_sdk/cli/account_store.py +540 -0
  7. glaip_sdk/cli/auth.py +254 -15
  8. glaip_sdk/cli/commands/__init__.py +2 -2
  9. glaip_sdk/cli/commands/accounts.py +746 -0
  10. glaip_sdk/cli/commands/agents.py +213 -73
  11. glaip_sdk/cli/commands/common_config.py +104 -0
  12. glaip_sdk/cli/commands/configure.py +729 -113
  13. glaip_sdk/cli/commands/mcps.py +241 -72
  14. glaip_sdk/cli/commands/models.py +11 -5
  15. glaip_sdk/cli/commands/tools.py +49 -57
  16. glaip_sdk/cli/commands/transcripts.py +755 -0
  17. glaip_sdk/cli/config.py +48 -4
  18. glaip_sdk/cli/constants.py +38 -0
  19. glaip_sdk/cli/context.py +8 -0
  20. glaip_sdk/cli/core/__init__.py +79 -0
  21. glaip_sdk/cli/core/context.py +124 -0
  22. glaip_sdk/cli/core/output.py +851 -0
  23. glaip_sdk/cli/core/prompting.py +649 -0
  24. glaip_sdk/cli/core/rendering.py +187 -0
  25. glaip_sdk/cli/display.py +35 -19
  26. glaip_sdk/cli/hints.py +57 -0
  27. glaip_sdk/cli/io.py +6 -3
  28. glaip_sdk/cli/main.py +241 -121
  29. glaip_sdk/cli/masking.py +21 -33
  30. glaip_sdk/cli/pager.py +9 -10
  31. glaip_sdk/cli/parsers/__init__.py +1 -3
  32. glaip_sdk/cli/slash/__init__.py +0 -9
  33. glaip_sdk/cli/slash/accounts_controller.py +578 -0
  34. glaip_sdk/cli/slash/accounts_shared.py +75 -0
  35. glaip_sdk/cli/slash/agent_session.py +62 -21
  36. glaip_sdk/cli/slash/prompt.py +21 -0
  37. glaip_sdk/cli/slash/remote_runs_controller.py +566 -0
  38. glaip_sdk/cli/slash/session.py +771 -140
  39. glaip_sdk/cli/slash/tui/__init__.py +9 -0
  40. glaip_sdk/cli/slash/tui/accounts.tcss +86 -0
  41. glaip_sdk/cli/slash/tui/accounts_app.py +876 -0
  42. glaip_sdk/cli/slash/tui/background_tasks.py +72 -0
  43. glaip_sdk/cli/slash/tui/loading.py +58 -0
  44. glaip_sdk/cli/slash/tui/remote_runs_app.py +628 -0
  45. glaip_sdk/cli/transcript/__init__.py +12 -52
  46. glaip_sdk/cli/transcript/cache.py +255 -44
  47. glaip_sdk/cli/transcript/capture.py +27 -1
  48. glaip_sdk/cli/transcript/history.py +815 -0
  49. glaip_sdk/cli/transcript/viewer.py +72 -499
  50. glaip_sdk/cli/update_notifier.py +14 -5
  51. glaip_sdk/cli/utils.py +243 -1252
  52. glaip_sdk/cli/validators.py +5 -6
  53. glaip_sdk/client/__init__.py +2 -1
  54. glaip_sdk/client/_agent_payloads.py +45 -9
  55. glaip_sdk/client/agent_runs.py +147 -0
  56. glaip_sdk/client/agents.py +291 -35
  57. glaip_sdk/client/base.py +1 -0
  58. glaip_sdk/client/main.py +19 -10
  59. glaip_sdk/client/mcps.py +122 -12
  60. glaip_sdk/client/run_rendering.py +466 -89
  61. glaip_sdk/client/shared.py +21 -0
  62. glaip_sdk/client/tools.py +155 -10
  63. glaip_sdk/config/constants.py +11 -0
  64. glaip_sdk/hitl/__init__.py +15 -0
  65. glaip_sdk/hitl/local.py +151 -0
  66. glaip_sdk/mcps/__init__.py +21 -0
  67. glaip_sdk/mcps/base.py +345 -0
  68. glaip_sdk/models/__init__.py +90 -0
  69. glaip_sdk/models/agent.py +47 -0
  70. glaip_sdk/models/agent_runs.py +116 -0
  71. glaip_sdk/models/common.py +42 -0
  72. glaip_sdk/models/mcp.py +33 -0
  73. glaip_sdk/models/tool.py +33 -0
  74. glaip_sdk/payload_schemas/__init__.py +1 -13
  75. glaip_sdk/registry/__init__.py +55 -0
  76. glaip_sdk/registry/agent.py +164 -0
  77. glaip_sdk/registry/base.py +139 -0
  78. glaip_sdk/registry/mcp.py +253 -0
  79. glaip_sdk/registry/tool.py +232 -0
  80. glaip_sdk/rich_components.py +58 -2
  81. glaip_sdk/runner/__init__.py +59 -0
  82. glaip_sdk/runner/base.py +84 -0
  83. glaip_sdk/runner/deps.py +112 -0
  84. glaip_sdk/runner/langgraph.py +870 -0
  85. glaip_sdk/runner/mcp_adapter/__init__.py +13 -0
  86. glaip_sdk/runner/mcp_adapter/base_mcp_adapter.py +43 -0
  87. glaip_sdk/runner/mcp_adapter/langchain_mcp_adapter.py +257 -0
  88. glaip_sdk/runner/mcp_adapter/mcp_config_builder.py +95 -0
  89. glaip_sdk/runner/tool_adapter/__init__.py +18 -0
  90. glaip_sdk/runner/tool_adapter/base_tool_adapter.py +44 -0
  91. glaip_sdk/runner/tool_adapter/langchain_tool_adapter.py +219 -0
  92. glaip_sdk/tools/__init__.py +22 -0
  93. glaip_sdk/tools/base.py +435 -0
  94. glaip_sdk/utils/__init__.py +58 -12
  95. glaip_sdk/utils/a2a/__init__.py +34 -0
  96. glaip_sdk/utils/a2a/event_processor.py +188 -0
  97. glaip_sdk/utils/bundler.py +267 -0
  98. glaip_sdk/utils/client.py +111 -0
  99. glaip_sdk/utils/client_utils.py +39 -7
  100. glaip_sdk/utils/datetime_helpers.py +58 -0
  101. glaip_sdk/utils/discovery.py +78 -0
  102. glaip_sdk/utils/display.py +23 -15
  103. glaip_sdk/utils/export.py +143 -0
  104. glaip_sdk/utils/general.py +0 -33
  105. glaip_sdk/utils/import_export.py +12 -7
  106. glaip_sdk/utils/import_resolver.py +492 -0
  107. glaip_sdk/utils/instructions.py +101 -0
  108. glaip_sdk/utils/rendering/__init__.py +115 -1
  109. glaip_sdk/utils/rendering/formatting.py +5 -30
  110. glaip_sdk/utils/rendering/layout/__init__.py +64 -0
  111. glaip_sdk/utils/rendering/{renderer → layout}/panels.py +9 -0
  112. glaip_sdk/utils/rendering/{renderer → layout}/progress.py +70 -1
  113. glaip_sdk/utils/rendering/layout/summary.py +74 -0
  114. glaip_sdk/utils/rendering/layout/transcript.py +606 -0
  115. glaip_sdk/utils/rendering/models.py +1 -0
  116. glaip_sdk/utils/rendering/renderer/__init__.py +9 -47
  117. glaip_sdk/utils/rendering/renderer/base.py +275 -1476
  118. glaip_sdk/utils/rendering/renderer/debug.py +26 -20
  119. glaip_sdk/utils/rendering/renderer/factory.py +138 -0
  120. glaip_sdk/utils/rendering/renderer/stream.py +4 -12
  121. glaip_sdk/utils/rendering/renderer/thinking.py +273 -0
  122. glaip_sdk/utils/rendering/renderer/tool_panels.py +442 -0
  123. glaip_sdk/utils/rendering/renderer/transcript_mode.py +162 -0
  124. glaip_sdk/utils/rendering/state.py +204 -0
  125. glaip_sdk/utils/rendering/steps/__init__.py +34 -0
  126. glaip_sdk/utils/rendering/{steps.py → steps/event_processor.py} +53 -440
  127. glaip_sdk/utils/rendering/steps/format.py +176 -0
  128. glaip_sdk/utils/rendering/steps/manager.py +387 -0
  129. glaip_sdk/utils/rendering/timing.py +36 -0
  130. glaip_sdk/utils/rendering/viewer/__init__.py +21 -0
  131. glaip_sdk/utils/rendering/viewer/presenter.py +184 -0
  132. glaip_sdk/utils/resource_refs.py +25 -13
  133. glaip_sdk/utils/runtime_config.py +425 -0
  134. glaip_sdk/utils/serialization.py +18 -0
  135. glaip_sdk/utils/sync.py +142 -0
  136. glaip_sdk/utils/tool_detection.py +33 -0
  137. glaip_sdk/utils/tool_storage_provider.py +140 -0
  138. glaip_sdk/utils/validation.py +16 -24
  139. {glaip_sdk-0.1.3.dist-info → glaip_sdk-0.6.19.dist-info}/METADATA +56 -21
  140. glaip_sdk-0.6.19.dist-info/RECORD +163 -0
  141. {glaip_sdk-0.1.3.dist-info → glaip_sdk-0.6.19.dist-info}/WHEEL +2 -1
  142. glaip_sdk-0.6.19.dist-info/entry_points.txt +2 -0
  143. glaip_sdk-0.6.19.dist-info/top_level.txt +1 -0
  144. glaip_sdk/models.py +0 -240
  145. glaip_sdk-0.1.3.dist-info/RECORD +0 -83
  146. glaip_sdk-0.1.3.dist-info/entry_points.txt +0 -3
@@ -10,8 +10,6 @@ from pathlib import Path
10
10
  from typing import Any
11
11
 
12
12
  import click
13
- from rich.console import Console
14
-
15
13
  from glaip_sdk.branding import (
16
14
  ACCENT_STYLE,
17
15
  ERROR_STYLE,
@@ -19,7 +17,7 @@ from glaip_sdk.branding import (
19
17
  SUCCESS_STYLE,
20
18
  WARNING_STYLE,
21
19
  )
22
- from glaip_sdk.cli.context import detect_export_format, get_ctx_value, output_flags
20
+ from glaip_sdk.cli.context import get_ctx_value, output_flags
23
21
  from glaip_sdk.cli.display import (
24
22
  display_api_error,
25
23
  display_confirmation_prompt,
@@ -29,12 +27,7 @@ from glaip_sdk.cli.display import (
29
27
  handle_json_output,
30
28
  handle_rich_output,
31
29
  )
32
- from glaip_sdk.cli.io import (
33
- export_resource_to_file_with_validation as export_resource_to_file,
34
- )
35
- from glaip_sdk.cli.io import (
36
- fetch_raw_resource_details,
37
- )
30
+ from glaip_sdk.cli.io import fetch_raw_resource_details
38
31
  from glaip_sdk.cli.io import (
39
32
  load_resource_from_file_with_validation as load_resource_from_file,
40
33
  )
@@ -42,14 +35,17 @@ from glaip_sdk.cli.resolution import resolve_resource_reference
42
35
  from glaip_sdk.cli.rich_helpers import markup_text, print_markup
43
36
  from glaip_sdk.cli.utils import (
44
37
  coerce_to_row,
38
+ format_datetime_fields,
45
39
  get_client,
40
+ handle_best_effort_check,
41
+ handle_resource_export,
46
42
  output_list,
47
43
  output_result,
48
44
  spinner_context,
49
45
  )
50
46
  from glaip_sdk.icons import ICON_TOOL
51
- from glaip_sdk.utils import format_datetime
52
47
  from glaip_sdk.utils.import_export import merge_import_with_cli_args
48
+ from rich.console import Console
53
49
 
54
50
  console = Console()
55
51
 
@@ -61,14 +57,31 @@ def tools_group() -> None:
61
57
 
62
58
 
63
59
  def _resolve_tool(ctx: Any, client: Any, ref: str, select: int | None = None) -> Any | None:
64
- """Resolve tool reference (ID or name) with ambiguity handling."""
60
+ """Resolve a tool by ID or name, handling ambiguous matches interactively.
61
+
62
+ This function provides tool-specific resolution logic. It uses
63
+ resolve_resource_reference to find tools by UUID or name, with interactive
64
+ selection when multiple matches are found.
65
+
66
+ Args:
67
+ ctx: Click context for CLI operations.
68
+ client: API client instance.
69
+ ref: Tool reference (UUID string or name).
70
+ select: Pre-selected index for non-interactive mode (1-based).
71
+
72
+ Returns:
73
+ Tool object if found, None otherwise.
74
+ """
75
+ # Configure tool-specific resolution with standard fuzzy matching
76
+ get_by_id = client.get_tool
77
+ find_by_name = client.find_tools
65
78
  return resolve_resource_reference(
66
79
  ctx,
67
80
  client,
68
81
  ref,
69
82
  "tool",
70
- client.get_tool,
71
- client.find_tools,
83
+ get_by_id,
84
+ find_by_name,
72
85
  "Tool",
73
86
  select=select,
74
87
  )
@@ -102,22 +115,20 @@ def _validate_name_match(provided: str | None, internal: str) -> str:
102
115
 
103
116
  def _check_duplicate_name(client: Any, tool_name: str) -> None:
104
117
  """Raise if a tool with the same name already exists."""
105
- try:
118
+
119
+ def _check_duplicate() -> None:
106
120
  existing = client.find_tools(name=tool_name)
107
121
  if existing:
108
122
  raise click.ClickException(
109
123
  f"A tool named '{tool_name}' already exists. "
110
124
  "Please change your plugin's 'name' to a unique value, then re-run."
111
125
  )
112
- except click.ClickException:
113
- # Re-raise ClickException (intended error)
114
- raise
115
- except Exception:
116
- # Non-fatal: best-effort duplicate check for other errors
117
- pass
126
+
127
+ handle_best_effort_check(_check_duplicate)
118
128
 
119
129
 
120
130
  def _parse_tags(tags: str | None) -> list[str]:
131
+ """Return a cleaned list of tag strings from a comma-separated input."""
121
132
  return [t.strip() for t in (tags.split(",") if tags else []) if t.strip()]
122
133
 
123
134
 
@@ -212,6 +223,14 @@ def list_tools(ctx: Any, tool_type: str | None) -> None:
212
223
 
213
224
  # Transform function for safe dictionary access
214
225
  def transform_tool(tool: Any) -> dict[str, Any]:
226
+ """Transform a tool object to a display row dictionary.
227
+
228
+ Args:
229
+ tool: Tool object to transform.
230
+
231
+ Returns:
232
+ Dictionary with id, name, and framework fields.
233
+ """
215
234
  row = coerce_to_row(tool, ["id", "name", "framework"])
216
235
  # Ensure id is always a string
217
236
  row["id"] = str(row["id"])
@@ -259,8 +278,9 @@ def create(
259
278
  tags: tuple[str, ...] | None,
260
279
  import_file: str | None,
261
280
  ) -> None:
262
- """Create a new tool.
281
+ r"""Create a new tool.
263
282
 
283
+ \b
264
284
  Examples:
265
285
  aip tools create tool.py # Create from file
266
286
  aip tools create --import tool.json # Create from exported configuration
@@ -325,8 +345,9 @@ def create(
325
345
  @output_flags()
326
346
  @click.pass_context
327
347
  def get(ctx: Any, tool_ref: str, select: int | None, export: str | None) -> None:
328
- """Get tool details.
348
+ r"""Get tool details.
329
349
 
350
+ \b
330
351
  Examples:
331
352
  aip tools get my-tool
332
353
  aip tools get my-tool --export tool.json # Exports complete configuration as JSON
@@ -340,38 +361,13 @@ def get(ctx: Any, tool_ref: str, select: int | None, export: str | None) -> None
340
361
 
341
362
  # Handle export option
342
363
  if export:
343
- export_path = Path(export)
344
- # Auto-detect format from file extension
345
- detected_format = detect_export_format(export_path)
346
-
347
- # Always export comprehensive data - re-fetch tool with full details if needed
348
- try:
349
- with spinner_context(
350
- ctx,
351
- "[bold blue]Fetching complete tool details…[/bold blue]",
352
- console_override=console,
353
- ):
354
- tool = client.get_tool_by_id(tool.id)
355
- except Exception as e:
356
- print_markup(
357
- f"[{WARNING_STYLE}]⚠️ Could not fetch full tool details: {e}[/]",
358
- console=console,
359
- )
360
- print_markup(
361
- f"[{WARNING_STYLE}]⚠️ Proceeding with available data[/]",
362
- console=console,
363
- )
364
-
365
- with spinner_context(
364
+ handle_resource_export(
366
365
  ctx,
367
- "[bold blue]Exporting tool configuration…[/bold blue]",
366
+ tool,
367
+ Path(export),
368
+ resource_type="tool",
369
+ get_by_id_func=client.get_tool_by_id,
368
370
  console_override=console,
369
- ):
370
- export_resource_to_file(tool, export_path, detected_format)
371
- print_markup(
372
- f"[{SUCCESS_STYLE}]✅ Complete tool configuration exported to: {export_path} "
373
- f"(format: {detected_format})[/]",
374
- console=console,
375
371
  )
376
372
 
377
373
  # Try to fetch raw API data first to preserve ALL fields
@@ -385,11 +381,7 @@ def get(ctx: Any, tool_ref: str, select: int | None, export: str | None) -> None
385
381
  if raw_tool_data:
386
382
  # Use raw API data - this preserves ALL fields
387
383
  # Format dates for better display (minimal postprocessing)
388
- formatted_data = raw_tool_data.copy()
389
- if "created_at" in formatted_data:
390
- formatted_data["created_at"] = format_datetime(formatted_data["created_at"])
391
- if "updated_at" in formatted_data:
392
- formatted_data["updated_at"] = format_datetime(formatted_data["updated_at"])
384
+ formatted_data = format_datetime_fields(raw_tool_data)
393
385
 
394
386
  # Display using output_result with raw data
395
387
  output_result(