glaip-sdk 0.6.19__py3-none-any.whl → 0.7.27__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 (135) hide show
  1. glaip_sdk/agents/base.py +283 -30
  2. glaip_sdk/agents/component.py +233 -0
  3. glaip_sdk/branding.py +113 -2
  4. glaip_sdk/cli/account_store.py +15 -0
  5. glaip_sdk/cli/auth.py +14 -8
  6. glaip_sdk/cli/commands/accounts.py +1 -1
  7. glaip_sdk/cli/commands/agents/__init__.py +116 -0
  8. glaip_sdk/cli/commands/agents/_common.py +562 -0
  9. glaip_sdk/cli/commands/agents/create.py +155 -0
  10. glaip_sdk/cli/commands/agents/delete.py +64 -0
  11. glaip_sdk/cli/commands/agents/get.py +89 -0
  12. glaip_sdk/cli/commands/agents/list.py +129 -0
  13. glaip_sdk/cli/commands/agents/run.py +264 -0
  14. glaip_sdk/cli/commands/agents/sync_langflow.py +72 -0
  15. glaip_sdk/cli/commands/agents/update.py +112 -0
  16. glaip_sdk/cli/commands/common_config.py +1 -1
  17. glaip_sdk/cli/commands/configure.py +1 -2
  18. glaip_sdk/cli/commands/mcps/__init__.py +94 -0
  19. glaip_sdk/cli/commands/mcps/_common.py +459 -0
  20. glaip_sdk/cli/commands/mcps/connect.py +82 -0
  21. glaip_sdk/cli/commands/mcps/create.py +152 -0
  22. glaip_sdk/cli/commands/mcps/delete.py +73 -0
  23. glaip_sdk/cli/commands/mcps/get.py +212 -0
  24. glaip_sdk/cli/commands/mcps/list.py +69 -0
  25. glaip_sdk/cli/commands/mcps/tools.py +235 -0
  26. glaip_sdk/cli/commands/mcps/update.py +190 -0
  27. glaip_sdk/cli/commands/models.py +2 -4
  28. glaip_sdk/cli/commands/shared/__init__.py +21 -0
  29. glaip_sdk/cli/commands/shared/formatters.py +91 -0
  30. glaip_sdk/cli/commands/tools/__init__.py +69 -0
  31. glaip_sdk/cli/commands/tools/_common.py +80 -0
  32. glaip_sdk/cli/commands/tools/create.py +228 -0
  33. glaip_sdk/cli/commands/tools/delete.py +61 -0
  34. glaip_sdk/cli/commands/tools/get.py +103 -0
  35. glaip_sdk/cli/commands/tools/list.py +69 -0
  36. glaip_sdk/cli/commands/tools/script.py +49 -0
  37. glaip_sdk/cli/commands/tools/update.py +102 -0
  38. glaip_sdk/cli/commands/transcripts/__init__.py +90 -0
  39. glaip_sdk/cli/commands/transcripts/_common.py +9 -0
  40. glaip_sdk/cli/commands/transcripts/clear.py +5 -0
  41. glaip_sdk/cli/commands/transcripts/detail.py +5 -0
  42. glaip_sdk/cli/commands/{transcripts.py → transcripts_original.py} +2 -1
  43. glaip_sdk/cli/commands/update.py +163 -17
  44. glaip_sdk/cli/config.py +1 -0
  45. glaip_sdk/cli/entrypoint.py +20 -0
  46. glaip_sdk/cli/main.py +112 -35
  47. glaip_sdk/cli/pager.py +3 -3
  48. glaip_sdk/cli/resolution.py +2 -1
  49. glaip_sdk/cli/slash/accounts_controller.py +3 -1
  50. glaip_sdk/cli/slash/agent_session.py +1 -1
  51. glaip_sdk/cli/slash/remote_runs_controller.py +3 -1
  52. glaip_sdk/cli/slash/session.py +343 -20
  53. glaip_sdk/cli/slash/tui/__init__.py +29 -1
  54. glaip_sdk/cli/slash/tui/accounts.tcss +97 -6
  55. glaip_sdk/cli/slash/tui/accounts_app.py +1117 -126
  56. glaip_sdk/cli/slash/tui/clipboard.py +316 -0
  57. glaip_sdk/cli/slash/tui/context.py +92 -0
  58. glaip_sdk/cli/slash/tui/indicators.py +341 -0
  59. glaip_sdk/cli/slash/tui/keybind_registry.py +235 -0
  60. glaip_sdk/cli/slash/tui/layouts/__init__.py +14 -0
  61. glaip_sdk/cli/slash/tui/layouts/harlequin.py +184 -0
  62. glaip_sdk/cli/slash/tui/loading.py +43 -21
  63. glaip_sdk/cli/slash/tui/remote_runs_app.py +178 -20
  64. glaip_sdk/cli/slash/tui/terminal.py +407 -0
  65. glaip_sdk/cli/slash/tui/theme/__init__.py +15 -0
  66. glaip_sdk/cli/slash/tui/theme/catalog.py +79 -0
  67. glaip_sdk/cli/slash/tui/theme/manager.py +112 -0
  68. glaip_sdk/cli/slash/tui/theme/tokens.py +55 -0
  69. glaip_sdk/cli/slash/tui/toast.py +388 -0
  70. glaip_sdk/cli/transcript/history.py +1 -1
  71. glaip_sdk/cli/transcript/viewer.py +1 -1
  72. glaip_sdk/cli/tui_settings.py +125 -0
  73. glaip_sdk/cli/update_notifier.py +215 -7
  74. glaip_sdk/cli/validators.py +1 -1
  75. glaip_sdk/client/__init__.py +2 -1
  76. glaip_sdk/client/_schedule_payloads.py +89 -0
  77. glaip_sdk/client/agents.py +293 -17
  78. glaip_sdk/client/base.py +25 -0
  79. glaip_sdk/client/hitl.py +136 -0
  80. glaip_sdk/client/main.py +7 -5
  81. glaip_sdk/client/mcps.py +44 -13
  82. glaip_sdk/client/payloads/agent/__init__.py +23 -0
  83. glaip_sdk/client/{_agent_payloads.py → payloads/agent/requests.py} +28 -48
  84. glaip_sdk/client/payloads/agent/responses.py +43 -0
  85. glaip_sdk/client/run_rendering.py +109 -30
  86. glaip_sdk/client/schedules.py +439 -0
  87. glaip_sdk/client/tools.py +52 -23
  88. glaip_sdk/config/constants.py +22 -2
  89. glaip_sdk/guardrails/__init__.py +80 -0
  90. glaip_sdk/guardrails/serializer.py +91 -0
  91. glaip_sdk/hitl/__init__.py +35 -2
  92. glaip_sdk/hitl/base.py +64 -0
  93. glaip_sdk/hitl/callback.py +43 -0
  94. glaip_sdk/hitl/local.py +1 -31
  95. glaip_sdk/hitl/remote.py +523 -0
  96. glaip_sdk/models/__init__.py +47 -1
  97. glaip_sdk/models/_provider_mappings.py +101 -0
  98. glaip_sdk/models/_validation.py +97 -0
  99. glaip_sdk/models/agent.py +2 -1
  100. glaip_sdk/models/agent_runs.py +2 -1
  101. glaip_sdk/models/constants.py +141 -0
  102. glaip_sdk/models/model.py +170 -0
  103. glaip_sdk/models/schedule.py +224 -0
  104. glaip_sdk/payload_schemas/agent.py +1 -0
  105. glaip_sdk/payload_schemas/guardrails.py +34 -0
  106. glaip_sdk/ptc.py +145 -0
  107. glaip_sdk/registry/tool.py +270 -57
  108. glaip_sdk/runner/__init__.py +20 -3
  109. glaip_sdk/runner/deps.py +4 -1
  110. glaip_sdk/runner/langgraph.py +251 -27
  111. glaip_sdk/runner/logging_config.py +77 -0
  112. glaip_sdk/runner/mcp_adapter/mcp_config_builder.py +30 -9
  113. glaip_sdk/runner/ptc_adapter.py +98 -0
  114. glaip_sdk/runner/tool_adapter/langchain_tool_adapter.py +25 -2
  115. glaip_sdk/schedules/__init__.py +22 -0
  116. glaip_sdk/schedules/base.py +291 -0
  117. glaip_sdk/tools/base.py +67 -14
  118. glaip_sdk/utils/__init__.py +1 -0
  119. glaip_sdk/utils/agent_config.py +8 -2
  120. glaip_sdk/utils/bundler.py +138 -2
  121. glaip_sdk/utils/import_resolver.py +427 -49
  122. glaip_sdk/utils/runtime_config.py +3 -2
  123. glaip_sdk/utils/sync.py +31 -11
  124. glaip_sdk/utils/tool_detection.py +274 -6
  125. {glaip_sdk-0.6.19.dist-info → glaip_sdk-0.7.27.dist-info}/METADATA +22 -8
  126. glaip_sdk-0.7.27.dist-info/RECORD +227 -0
  127. {glaip_sdk-0.6.19.dist-info → glaip_sdk-0.7.27.dist-info}/WHEEL +1 -1
  128. glaip_sdk-0.7.27.dist-info/entry_points.txt +2 -0
  129. glaip_sdk/cli/commands/agents.py +0 -1509
  130. glaip_sdk/cli/commands/mcps.py +0 -1356
  131. glaip_sdk/cli/commands/tools.py +0 -576
  132. glaip_sdk/cli/utils.py +0 -263
  133. glaip_sdk-0.6.19.dist-info/RECORD +0 -163
  134. glaip_sdk-0.6.19.dist-info/entry_points.txt +0 -2
  135. {glaip_sdk-0.6.19.dist-info → glaip_sdk-0.7.27.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,233 @@
1
+ """Agent Component for Glaip SDK.
2
+
3
+ This module provides the AgentComponent class, which wraps an Agent
4
+ to be used as a reusable component in pipelines.
5
+
6
+ Authors:
7
+ Christian Trisno Sen Long Chen (christian.t.s.l.chen@gdplabs.id)
8
+ """
9
+
10
+ from __future__ import annotations
11
+
12
+ from typing import TYPE_CHECKING, Any
13
+
14
+ from gllm_core.schema import Chunk, Component
15
+ from gllm_core.utils import LoggerManager
16
+
17
+ if TYPE_CHECKING:
18
+ from glaip_sdk.agents import Agent
19
+
20
+ logger = LoggerManager().get_logger(__name__)
21
+
22
+
23
+ class AgentComponent(Component):
24
+ """A Component that wraps a GL Agent for pipeline integration.
25
+
26
+ This component acts as a bridge between structured pipeline state
27
+ and the natural language interface of an Agent. It compiles inputs
28
+ (query, context, history) into a prompt and executes the agent.
29
+ """
30
+
31
+ def __init__(self, agent: Agent) -> None:
32
+ """Initialize the AgentComponent.
33
+
34
+ Args:
35
+ agent: The Agent instance to wrap.
36
+ """
37
+ super().__init__()
38
+ self.agent = agent
39
+
40
+ def _format_context(self, context: list[Chunk | str | dict[str, Any] | Any] | None) -> str:
41
+ """Format the context list into a string.
42
+
43
+ Supports Chunk objects (extracting content), strings, and dicts.
44
+
45
+ Args:
46
+ context: List of context items.
47
+
48
+ Returns:
49
+ Formatted context string.
50
+ """
51
+ if not context:
52
+ return ""
53
+
54
+ formatted_items = []
55
+ for item in context:
56
+ if isinstance(item, Chunk):
57
+ content = item.content
58
+ elif isinstance(item, dict):
59
+ content = str(item)
60
+ else:
61
+ content = str(item)
62
+ formatted_items.append(f"- {content}")
63
+
64
+ return "\n".join(formatted_items)
65
+
66
+ def _format_history(self, history: list[Any] | None) -> str:
67
+ """Format the chat history into a string.
68
+
69
+ Supports gllm_inference Message objects and dicts.
70
+
71
+ Args:
72
+ history: List of history items.
73
+
74
+ Returns:
75
+ Formatted history string.
76
+ """
77
+ if not history:
78
+ return "No previous history."
79
+
80
+ # Try to use gllm_inference schema if available for robust handling
81
+ try:
82
+ from gllm_inference.schema import Message # noqa: PLC0415
83
+ except ImportError:
84
+ Message = None
85
+
86
+ formatted_items = []
87
+ for item in history:
88
+ if Message and isinstance(item, Message):
89
+ # Message object has role and contents (list)
90
+ role = item.role.capitalize()
91
+ # Use standard content property if available, or join contents
92
+ content = getattr(item, "content", None)
93
+ if content is None and hasattr(item, "contents"):
94
+ content = "\n".join([str(c) for c in item.contents])
95
+ formatted_items.append(f"{role}: {content}")
96
+ elif isinstance(item, dict):
97
+ role = str(item.get("role", "User")).capitalize()
98
+ content = str(item.get("content", ""))
99
+ formatted_items.append(f"{role}: {content}")
100
+ else:
101
+ formatted_items.append(str(item))
102
+ return "\n".join(formatted_items)
103
+
104
+ def _compile_prompt(
105
+ self,
106
+ query: str,
107
+ context: list[Any] | None,
108
+ chat_history: list[Any] | None,
109
+ ) -> str:
110
+ """Compile the raw inputs into a single text prompt.
111
+
112
+ Args:
113
+ query: The user query.
114
+ context: List of context items.
115
+ chat_history: List of conversation history items.
116
+
117
+ Returns:
118
+ The compiled prompt string.
119
+ """
120
+ parts = []
121
+
122
+ if chat_history:
123
+ history_str = self._format_history(chat_history)
124
+ parts.append(f"Conversation History:\n{history_str}\n")
125
+
126
+ if context:
127
+ context_str = self._format_context(context)
128
+ parts.append(f"Context:\n{context_str}\n")
129
+
130
+ parts.append(f"{query}\n")
131
+
132
+ return "\n".join(parts)
133
+
134
+ async def run_agent(
135
+ self,
136
+ query: str,
137
+ context: list[Chunk | Any] | None = None,
138
+ chat_history: list[Any] | None = None,
139
+ runtime_config: dict[str, Any] | None = None,
140
+ run_kwargs: dict[str, Any] | None = None,
141
+ ) -> dict[str, Any]:
142
+ """Run the agent with the provided context and history.
143
+
144
+ This method is the main entry point for the component logic.
145
+
146
+ Args:
147
+ query: The user's input string.
148
+ context: List of retrieved documents/chunks or data.
149
+ chat_history: List of previous conversation turns.
150
+ runtime_config: Optional configuration.
151
+ run_kwargs: Optional payload for advanced agent execution parameters.
152
+
153
+ Returns:
154
+ The raw response dictionary from the agent.
155
+ """
156
+ if not query:
157
+ raise ValueError("Query is required")
158
+
159
+ logger.info("Compiling prompt for agent: %s", self.agent.name)
160
+
161
+ prompt = self._compile_prompt(
162
+ query=query,
163
+ context=context,
164
+ chat_history=chat_history,
165
+ )
166
+
167
+ params = (run_kwargs or {}).copy()
168
+ if runtime_config:
169
+ params["runtime_config"] = runtime_config
170
+
171
+ last_chunk = {}
172
+
173
+ try:
174
+ async for chunk in self.agent.arun(message=prompt, **params):
175
+ if isinstance(chunk, dict):
176
+ last_chunk = chunk
177
+ if chunk.get("event_type") == "final_response":
178
+ return chunk
179
+ except Exception as e:
180
+ raise RuntimeError(f"AgentComponent '{self.agent.name}' failed during execution: {e}") from e
181
+
182
+ return last_chunk
183
+
184
+ def _extract_content_string(self, result: Any) -> str:
185
+ """Extract the content string from the agent response.
186
+
187
+ Assumes the result is always a string or a dictionary containing a content field.
188
+
189
+ Args:
190
+ result: The agent response (dict or string).
191
+
192
+ Returns:
193
+ The content string extracted from the response.
194
+ """
195
+ if isinstance(result, dict):
196
+ content = result.get("content")
197
+ if content is not None:
198
+ return str(content)
199
+ return str(result)
200
+
201
+ return str(result) if result is not None else ""
202
+
203
+ async def _run(self, **kwargs: Any) -> str:
204
+ """Execute the component logic.
205
+
206
+ Args:
207
+ **kwargs: Keyword arguments including query, context, chat_history,
208
+ runtime_config, and run_kwargs. All execution control parameters
209
+ (e.g., local, verbose, temperature, etc.) must be provided via
210
+ run_kwargs dict.
211
+
212
+ Returns:
213
+ The content string extracted from the response.
214
+ """
215
+ # Extract standard component inputs
216
+ query = kwargs.pop("query", None)
217
+ context = kwargs.pop("context", None)
218
+ chat_history = kwargs.pop("chat_history", None)
219
+ runtime_config = kwargs.pop("runtime_config", None)
220
+ run_kwargs = kwargs.pop("run_kwargs", None)
221
+
222
+ # Ignore any remaining unrecognized kwargs for API consistency
223
+ # All execution parameters must be provided via run_kwargs
224
+
225
+ result = await self.run_agent(
226
+ query=query, # type: ignore[arg-type]
227
+ context=context,
228
+ chat_history=chat_history,
229
+ runtime_config=runtime_config,
230
+ run_kwargs=run_kwargs,
231
+ )
232
+
233
+ return self._extract_content_string(result)
glaip_sdk/branding.py CHANGED
@@ -17,6 +17,7 @@ import platform
17
17
  import sys
18
18
 
19
19
  from rich.console import Console
20
+ from rich.text import Text
20
21
 
21
22
  from glaip_sdk._version import __version__ as SDK_VERSION
22
23
  from glaip_sdk.rich_components import AIPPanel
@@ -110,9 +111,13 @@ GDP Labs AI Agents Package
110
111
  return SDK_VERSION
111
112
 
112
113
  @staticmethod
113
- def _make_console() -> Console:
114
+ def _make_console(force_terminal: bool | None = None, *, soft_wrap: bool = True) -> Console:
114
115
  """Create a Rich Console instance respecting NO_COLOR environment variables.
115
116
 
117
+ Args:
118
+ force_terminal: Override terminal detection when True/False.
119
+ soft_wrap: Whether to enable soft wrapping in the console.
120
+
116
121
  Returns:
117
122
  Console instance with color system configured based on environment.
118
123
  """
@@ -124,7 +129,12 @@ GDP Labs AI Agents Package
124
129
  else:
125
130
  color_system = "auto"
126
131
  no_color = False
127
- return Console(color_system=color_system, no_color=no_color, soft_wrap=True)
132
+ return Console(
133
+ color_system=color_system,
134
+ no_color=no_color,
135
+ soft_wrap=soft_wrap,
136
+ force_terminal=force_terminal,
137
+ )
128
138
 
129
139
  # ---- public API -----------------------------------------------------------
130
140
  def get_welcome_banner(self) -> str:
@@ -209,3 +219,104 @@ GDP Labs AI Agents Package
209
219
  AIPBranding instance
210
220
  """
211
221
  return cls(version=sdk_version, package_name=package_name)
222
+
223
+
224
+ class LogoAnimator:
225
+ """Animated logo with pulse effect for CLI startup.
226
+
227
+ Provides a "Knight Rider" style light pulse animation that sweeps across
228
+ the GL AIP logo during initialization tasks. Respects NO_COLOR and non-TTY
229
+ environments with graceful degradation.
230
+ """
231
+
232
+ # Animation colors from GDP Labs brand palette
233
+ BASE_BLUE = SECONDARY_MEDIUM # "#005CB8" - Medium Blue
234
+ HIGHLIGHT = SECONDARY_LIGHT # "#40B4E5" - Light Blue
235
+ WHITE = "#FFFFFF" # Bright white center
236
+
237
+ def __init__(self, console: Console | None = None) -> None:
238
+ """Initialize LogoAnimator.
239
+
240
+ Args:
241
+ console: Optional console instance. If None, creates a default console.
242
+ """
243
+ self.console = console or AIPBranding._make_console()
244
+ self.logo = AIPBranding.AIP_LOGO
245
+ self.lines = self.logo.split("\n")
246
+ self.max_width = max(len(line) for line in self.lines) if self.lines else 0
247
+
248
+ def generate_frame(self, step: int, status_text: str = "") -> Text:
249
+ """Generate a single animation frame with logo pulse and status.
250
+
251
+ Args:
252
+ step: Current animation step (position of the pulse).
253
+ status_text: Optional status text to display below the logo.
254
+
255
+ Returns:
256
+ Text object with styled logo and status.
257
+ """
258
+ text = Text()
259
+
260
+ for line in self.lines:
261
+ for x, char in enumerate(line):
262
+ distance = abs(x - step)
263
+
264
+ if distance == 0:
265
+ style = f"bold {self.WHITE}" # Bright white center
266
+ elif distance <= 3:
267
+ style = f"bold {self.HIGHLIGHT}" # Light blue glow
268
+ else:
269
+ style = self.BASE_BLUE # Base blue
270
+
271
+ text.append(char, style=style)
272
+ text.append("\n")
273
+
274
+ # Add status area below the logo
275
+ if status_text:
276
+ text.append(f"\n{status_text}\n")
277
+
278
+ return text
279
+
280
+ def should_animate(self) -> bool:
281
+ """Check if animation should be used.
282
+
283
+ Returns:
284
+ True if animation should be used (interactive TTY with colors),
285
+ False otherwise (NO_COLOR set or non-TTY).
286
+ """
287
+ # Check for NO_COLOR environment variables
288
+ no_color = os.getenv("NO_COLOR") is not None or os.getenv("AIP_NO_COLOR") is not None
289
+ if no_color:
290
+ return False
291
+
292
+ # Check if console is a TTY
293
+ if not self.console.is_terminal:
294
+ return False
295
+
296
+ # Check if console explicitly disables colors
297
+ if self.console.no_color:
298
+ return False
299
+
300
+ # If we get here, we have a TTY without NO_COLOR set
301
+ # Rich will handle color detection, so we can animate
302
+ return True
303
+
304
+ def display_static_logo(self, status_text: str = "") -> None:
305
+ """Display static logo without animation (for non-TTY or NO_COLOR).
306
+
307
+ Args:
308
+ status_text: Optional status text to display below the logo.
309
+ """
310
+ self.console.print(self.static_frame(status_text))
311
+
312
+ def static_frame(self, status_text: str = "") -> Text:
313
+ """Return a static logo frame for use in non-animated renders.
314
+
315
+ Args:
316
+ status_text: Optional status text to display below the logo.
317
+ """
318
+ logo_text = Text(self.logo, style=self.BASE_BLUE)
319
+ if status_text:
320
+ logo_text.append("\n")
321
+ logo_text.append(status_text)
322
+ return logo_text
@@ -523,6 +523,21 @@ class AccountStore:
523
523
 
524
524
  self._save_config(config)
525
525
 
526
+ def save_config_updates(self, config: dict[str, Any]) -> None:
527
+ """Save config updates, preserving all existing keys.
528
+
529
+ This method allows external code to update arbitrary config keys
530
+ (e.g., TUI preferences) while preserving the full config structure.
531
+
532
+ Args:
533
+ config: Complete configuration dictionary to save. This should
534
+ include all keys that should be preserved, not just updates.
535
+
536
+ Raises:
537
+ AccountStoreError: If config file cannot be written.
538
+ """
539
+ self._save_config(config)
540
+
526
541
 
527
542
  # Global instance for convenience
528
543
  _account_store = AccountStore()
glaip_sdk/cli/auth.py CHANGED
@@ -19,8 +19,7 @@ from rich.console import Console
19
19
 
20
20
  from glaip_sdk.branding import HINT_PREFIX_STYLE, WARNING_STYLE
21
21
  from glaip_sdk.cli.account_store import AccountNotFoundError, AccountStoreError, get_account_store
22
- from glaip_sdk.cli.hints import format_command_hint
23
- from glaip_sdk.cli.utils import command_hint
22
+ from glaip_sdk.cli.hints import command_hint, format_command_hint
24
23
 
25
24
 
26
25
  def prepare_authentication_export(
@@ -526,12 +525,19 @@ def resolve_api_url_from_context(
526
525
  elif hasattr(ctx, "obj") and isinstance(ctx.obj, dict):
527
526
  account_name = ctx.obj.get("account_name")
528
527
 
529
- resolved_url, _, _ = resolve_credentials(
530
- account_name=account_name,
531
- api_url=api_url,
532
- api_key=None,
533
- ignore_env_creds=True,
534
- )
528
+ if isinstance(api_url, str) and api_url.strip():
529
+ return api_url.strip()
530
+
531
+ try:
532
+ resolved_url, _, _ = resolve_credentials(
533
+ account_name=account_name,
534
+ api_url=None,
535
+ api_key=None,
536
+ ignore_env_creds=True,
537
+ )
538
+ except Exception:
539
+ return None
540
+
535
541
  return resolved_url
536
542
 
537
543
 
@@ -33,7 +33,7 @@ from glaip_sdk.cli.commands.common_config import check_connection, render_brandi
33
33
  from glaip_sdk.cli.hints import format_command_hint
34
34
  from glaip_sdk.cli.masking import mask_api_key_display
35
35
  from glaip_sdk.cli.slash.accounts_shared import env_credentials_present
36
- from glaip_sdk.cli.utils import command_hint
36
+ from glaip_sdk.cli.hints import command_hint
37
37
  from glaip_sdk.icons import ICON_TOOL
38
38
  from glaip_sdk.rich_components import AIPPanel, AIPTable
39
39
 
@@ -0,0 +1,116 @@
1
+ """Agent CLI commands package.
2
+
3
+ This package contains agent management commands split by operation.
4
+ The package is the canonical import surface.
5
+
6
+ Authors:
7
+ Raymond Christopher (raymond.christopher@gdplabs.id)
8
+ """
9
+
10
+ # pylint: disable=duplicate-code
11
+ # Import from submodules
12
+ from glaip_sdk.cli.commands.agents._common import ( # noqa: E402
13
+ AGENT_NOT_FOUND_ERROR,
14
+ _coerce_mapping_candidate,
15
+ _display_agent_details,
16
+ _emit_verbose_guidance,
17
+ _fetch_full_agent_details,
18
+ _get_agent_for_update,
19
+ _get_agent_model_name,
20
+ _get_language_model_display_name,
21
+ _model_from_config,
22
+ _prepare_agent_output,
23
+ _resolve_agent,
24
+ _resolve_resources_by_name,
25
+ agents_group,
26
+ console,
27
+ )
28
+ from glaip_sdk.cli.commands.agents.create import create # noqa: E402
29
+ from glaip_sdk.cli.commands.agents.delete import delete # noqa: E402
30
+ from glaip_sdk.cli.commands.agents.get import get # noqa: E402
31
+ from glaip_sdk.cli.commands.agents.list import list_agents # noqa: E402
32
+ from glaip_sdk.cli.commands.agents.run import _maybe_attach_transcript_toggle, run # noqa: E402
33
+ from glaip_sdk.cli.commands.agents.sync_langflow import sync_langflow # noqa: E402
34
+ from glaip_sdk.cli.commands.agents.update import update # noqa: E402
35
+
36
+ # Import core functions for test compatibility
37
+ from glaip_sdk.cli.core.context import get_client # noqa: E402
38
+
39
+ # Import core output functions for test compatibility
40
+ from glaip_sdk.cli.core.output import ( # noqa: E402
41
+ handle_resource_export,
42
+ output_list,
43
+ )
44
+
45
+ # Import rendering functions for test compatibility
46
+ from glaip_sdk.cli.core.rendering import ( # noqa: E402
47
+ build_renderer,
48
+ with_client_and_spinner, # noqa: E402
49
+ )
50
+
51
+ # Import display functions for test compatibility
52
+ # Import display functions for test compatibility
53
+ from glaip_sdk.cli.display import ( # noqa: E402 # noqa: E402
54
+ display_agent_run_suggestions,
55
+ handle_json_output,
56
+ handle_rich_output,
57
+ )
58
+
59
+ # Import IO functions for test compatibility
60
+ from glaip_sdk.cli.io import ( # noqa: E402
61
+ fetch_raw_resource_details,
62
+ )
63
+
64
+ # Import rich helpers for test compatibility
65
+ from glaip_sdk.cli.rich_helpers import ( # noqa: E402
66
+ markup_text,
67
+ )
68
+
69
+ # Import transcript functions for test compatibility
70
+ from glaip_sdk.cli.transcript import ( # noqa: E402
71
+ maybe_launch_post_run_viewer,
72
+ store_transcript_for_session,
73
+ )
74
+
75
+ # Import utils for test compatibility
76
+ from glaip_sdk.utils import ( # noqa: E402
77
+ is_uuid,
78
+ )
79
+
80
+ __all__ = [
81
+ "AGENT_NOT_FOUND_ERROR",
82
+ "agents_group",
83
+ "create",
84
+ "delete",
85
+ "get",
86
+ "list_agents",
87
+ "run",
88
+ "sync_langflow",
89
+ "update",
90
+ "_get_agent_for_update",
91
+ "_resolve_agent",
92
+ "_coerce_mapping_candidate",
93
+ "_display_agent_details",
94
+ "_emit_verbose_guidance",
95
+ "_fetch_full_agent_details",
96
+ "_get_agent_model_name",
97
+ "_get_language_model_display_name",
98
+ "_model_from_config",
99
+ "_prepare_agent_output",
100
+ "_resolve_resources_by_name",
101
+ "_maybe_attach_transcript_toggle",
102
+ "get_client",
103
+ "with_client_and_spinner",
104
+ "console",
105
+ "handle_json_output",
106
+ "handle_rich_output",
107
+ "output_list",
108
+ "handle_resource_export",
109
+ "build_renderer",
110
+ "display_agent_run_suggestions",
111
+ "markup_text",
112
+ "maybe_launch_post_run_viewer",
113
+ "store_transcript_for_session",
114
+ "fetch_raw_resource_details",
115
+ "is_uuid",
116
+ ]