glaip-sdk 0.6.10__py3-none-any.whl → 0.6.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/client/agents.py +4 -6
- glaip_sdk/client/run_rendering.py +286 -1
- glaip_sdk/runner/langgraph.py +91 -15
- {glaip_sdk-0.6.10.dist-info → glaip_sdk-0.6.11.dist-info}/METADATA +5 -4
- {glaip_sdk-0.6.10.dist-info → glaip_sdk-0.6.11.dist-info}/RECORD +7 -7
- {glaip_sdk-0.6.10.dist-info → glaip_sdk-0.6.11.dist-info}/WHEEL +0 -0
- {glaip_sdk-0.6.10.dist-info → glaip_sdk-0.6.11.dist-info}/entry_points.txt +0 -0
glaip_sdk/client/agents.py
CHANGED
|
@@ -453,13 +453,11 @@ class AgentClient(BaseClient):
|
|
|
453
453
|
Returns:
|
|
454
454
|
Final text string.
|
|
455
455
|
"""
|
|
456
|
+
from glaip_sdk.client.run_rendering import finalize_render_manager # noqa: PLC0415
|
|
457
|
+
|
|
456
458
|
manager = self._get_renderer_manager()
|
|
457
|
-
return
|
|
458
|
-
renderer,
|
|
459
|
-
final_text,
|
|
460
|
-
stats_usage,
|
|
461
|
-
started_monotonic,
|
|
462
|
-
finished_monotonic,
|
|
459
|
+
return finalize_render_manager(
|
|
460
|
+
manager, renderer, final_text, stats_usage, started_monotonic, finished_monotonic
|
|
463
461
|
)
|
|
464
462
|
|
|
465
463
|
def _get_tool_client(self) -> ToolClient:
|
|
@@ -9,7 +9,7 @@ from __future__ import annotations
|
|
|
9
9
|
|
|
10
10
|
import json
|
|
11
11
|
import logging
|
|
12
|
-
from collections.abc import Callable
|
|
12
|
+
from collections.abc import AsyncIterable, Callable
|
|
13
13
|
from time import monotonic
|
|
14
14
|
from typing import Any
|
|
15
15
|
|
|
@@ -163,6 +163,261 @@ class AgentRunRenderingManager:
|
|
|
163
163
|
finished_monotonic = monotonic()
|
|
164
164
|
return final_text, stats_usage, started_monotonic, finished_monotonic
|
|
165
165
|
|
|
166
|
+
async def async_process_stream_events(
|
|
167
|
+
self,
|
|
168
|
+
event_stream: AsyncIterable[dict[str, Any]],
|
|
169
|
+
renderer: RichStreamRenderer,
|
|
170
|
+
meta: dict[str, Any],
|
|
171
|
+
*,
|
|
172
|
+
skip_final_render: bool = True,
|
|
173
|
+
) -> tuple[str, dict[str, Any], float | None, float | None]:
|
|
174
|
+
"""Process streaming events from an async event source.
|
|
175
|
+
|
|
176
|
+
This method provides unified stream processing for both remote (HTTP)
|
|
177
|
+
and local (LangGraph) agent execution, ensuring consistent behavior.
|
|
178
|
+
|
|
179
|
+
Args:
|
|
180
|
+
event_stream: Async iterable yielding SSE-like event dicts.
|
|
181
|
+
Each event should have a "data" key with JSON string, or be
|
|
182
|
+
a pre-parsed dict with "content", "metadata", etc.
|
|
183
|
+
renderer: Renderer to use for displaying events.
|
|
184
|
+
meta: Metadata dictionary for renderer context.
|
|
185
|
+
skip_final_render: If True, skip rendering final_response events
|
|
186
|
+
(they are rendered separately via finalize_renderer).
|
|
187
|
+
|
|
188
|
+
Returns:
|
|
189
|
+
Tuple of (final_text, stats_usage, started_monotonic, finished_monotonic).
|
|
190
|
+
"""
|
|
191
|
+
final_text = ""
|
|
192
|
+
stats_usage: dict[str, Any] = {}
|
|
193
|
+
started_monotonic: float | None = None
|
|
194
|
+
last_rendered_content: str | None = None
|
|
195
|
+
|
|
196
|
+
controller = getattr(renderer, "transcript_controller", None)
|
|
197
|
+
if controller and getattr(controller, "enabled", False):
|
|
198
|
+
controller.on_stream_start(renderer)
|
|
199
|
+
|
|
200
|
+
try:
|
|
201
|
+
async for event in event_stream:
|
|
202
|
+
if started_monotonic is None:
|
|
203
|
+
started_monotonic = monotonic()
|
|
204
|
+
|
|
205
|
+
# Parse event if needed (handles both raw SSE and pre-parsed dicts)
|
|
206
|
+
parsed_event = self._parse_event(event)
|
|
207
|
+
if parsed_event is None:
|
|
208
|
+
continue
|
|
209
|
+
|
|
210
|
+
# Process the event and update accumulators
|
|
211
|
+
final_text, stats_usage = self._handle_parsed_event(
|
|
212
|
+
parsed_event,
|
|
213
|
+
renderer,
|
|
214
|
+
final_text,
|
|
215
|
+
stats_usage,
|
|
216
|
+
meta,
|
|
217
|
+
skip_final_render=skip_final_render,
|
|
218
|
+
last_rendered_content=last_rendered_content,
|
|
219
|
+
)
|
|
220
|
+
|
|
221
|
+
# Track last rendered content to avoid duplicates
|
|
222
|
+
content_str = self._extract_content_string(parsed_event)
|
|
223
|
+
if content_str:
|
|
224
|
+
last_rendered_content = content_str
|
|
225
|
+
|
|
226
|
+
if controller and getattr(controller, "enabled", False):
|
|
227
|
+
controller.poll(renderer)
|
|
228
|
+
finally:
|
|
229
|
+
if controller and getattr(controller, "enabled", False):
|
|
230
|
+
controller.on_stream_complete()
|
|
231
|
+
|
|
232
|
+
finished_monotonic = monotonic()
|
|
233
|
+
return final_text, stats_usage, started_monotonic, finished_monotonic
|
|
234
|
+
|
|
235
|
+
def _parse_event(self, event: dict[str, Any]) -> dict[str, Any] | None:
|
|
236
|
+
"""Parse an SSE event dict into a usable format.
|
|
237
|
+
|
|
238
|
+
Args:
|
|
239
|
+
event: Raw event dict, either with "data" key (SSE format) or
|
|
240
|
+
pre-parsed with "content", "metadata", etc.
|
|
241
|
+
|
|
242
|
+
Returns:
|
|
243
|
+
Parsed event dict, or None if parsing fails.
|
|
244
|
+
"""
|
|
245
|
+
if "data" in event:
|
|
246
|
+
try:
|
|
247
|
+
return json.loads(event["data"])
|
|
248
|
+
except json.JSONDecodeError:
|
|
249
|
+
self._logger.debug("Non-JSON SSE fragment skipped")
|
|
250
|
+
return None
|
|
251
|
+
# Already parsed (e.g., from local runner)
|
|
252
|
+
return event if event else None
|
|
253
|
+
|
|
254
|
+
def _handle_parsed_event(
|
|
255
|
+
self,
|
|
256
|
+
ev: dict[str, Any],
|
|
257
|
+
renderer: RichStreamRenderer,
|
|
258
|
+
final_text: str,
|
|
259
|
+
stats_usage: dict[str, Any],
|
|
260
|
+
meta: dict[str, Any],
|
|
261
|
+
*,
|
|
262
|
+
skip_final_render: bool = True,
|
|
263
|
+
last_rendered_content: str | None = None,
|
|
264
|
+
) -> tuple[str, dict[str, Any]]:
|
|
265
|
+
"""Handle a parsed event and update accumulators.
|
|
266
|
+
|
|
267
|
+
Args:
|
|
268
|
+
ev: Parsed event dictionary.
|
|
269
|
+
renderer: Renderer instance.
|
|
270
|
+
final_text: Current accumulated final text.
|
|
271
|
+
stats_usage: Usage statistics dictionary.
|
|
272
|
+
meta: Metadata dictionary.
|
|
273
|
+
skip_final_render: If True, skip rendering final_response events.
|
|
274
|
+
last_rendered_content: Last rendered content to avoid duplicates.
|
|
275
|
+
|
|
276
|
+
Returns:
|
|
277
|
+
Tuple of (updated_final_text, updated_stats_usage).
|
|
278
|
+
"""
|
|
279
|
+
kind = self._get_event_kind(ev)
|
|
280
|
+
|
|
281
|
+
# Dispatch to specialized handlers based on event kind
|
|
282
|
+
handler = self._get_event_handler(kind, ev)
|
|
283
|
+
if handler:
|
|
284
|
+
return handler(ev, renderer, final_text, stats_usage, meta, skip_final_render)
|
|
285
|
+
|
|
286
|
+
# Default: handle content events
|
|
287
|
+
return self._handle_content_event_async(ev, renderer, final_text, stats_usage, last_rendered_content)
|
|
288
|
+
|
|
289
|
+
def _get_event_handler(
|
|
290
|
+
self,
|
|
291
|
+
kind: str | None,
|
|
292
|
+
ev: dict[str, Any],
|
|
293
|
+
) -> Callable[..., tuple[str, dict[str, Any]]] | None:
|
|
294
|
+
"""Get the appropriate handler for an event kind.
|
|
295
|
+
|
|
296
|
+
Args:
|
|
297
|
+
kind: Event kind string.
|
|
298
|
+
ev: Event dictionary (for checking is_final flag).
|
|
299
|
+
|
|
300
|
+
Returns:
|
|
301
|
+
Handler function or None for default content handling.
|
|
302
|
+
"""
|
|
303
|
+
if kind == "usage":
|
|
304
|
+
return self._handle_usage_event
|
|
305
|
+
if kind == "final_response" or ev.get("is_final"):
|
|
306
|
+
return self._handle_final_response_event
|
|
307
|
+
if kind == "run_info":
|
|
308
|
+
return self._handle_run_info_event_wrapper
|
|
309
|
+
if kind in ("artifact", "status_update"):
|
|
310
|
+
return self._handle_render_only_event
|
|
311
|
+
return None
|
|
312
|
+
|
|
313
|
+
def _handle_usage_event(
|
|
314
|
+
self,
|
|
315
|
+
ev: dict[str, Any],
|
|
316
|
+
_renderer: RichStreamRenderer,
|
|
317
|
+
final_text: str,
|
|
318
|
+
stats_usage: dict[str, Any],
|
|
319
|
+
_meta: dict[str, Any],
|
|
320
|
+
_skip_final_render: bool,
|
|
321
|
+
) -> tuple[str, dict[str, Any]]:
|
|
322
|
+
"""Handle usage events."""
|
|
323
|
+
stats_usage.update(ev.get("usage") or {})
|
|
324
|
+
return final_text, stats_usage
|
|
325
|
+
|
|
326
|
+
def _handle_final_response_event(
|
|
327
|
+
self,
|
|
328
|
+
ev: dict[str, Any],
|
|
329
|
+
renderer: RichStreamRenderer,
|
|
330
|
+
final_text: str,
|
|
331
|
+
stats_usage: dict[str, Any],
|
|
332
|
+
_meta: dict[str, Any],
|
|
333
|
+
skip_final_render: bool,
|
|
334
|
+
) -> tuple[str, dict[str, Any]]:
|
|
335
|
+
"""Handle final_response events."""
|
|
336
|
+
content = ev.get("content")
|
|
337
|
+
if content:
|
|
338
|
+
final_text = str(content)
|
|
339
|
+
if not skip_final_render:
|
|
340
|
+
renderer.on_event(ev)
|
|
341
|
+
return final_text, stats_usage
|
|
342
|
+
|
|
343
|
+
def _handle_run_info_event_wrapper(
|
|
344
|
+
self,
|
|
345
|
+
ev: dict[str, Any],
|
|
346
|
+
renderer: RichStreamRenderer,
|
|
347
|
+
final_text: str,
|
|
348
|
+
stats_usage: dict[str, Any],
|
|
349
|
+
meta: dict[str, Any],
|
|
350
|
+
_skip_final_render: bool,
|
|
351
|
+
) -> tuple[str, dict[str, Any]]:
|
|
352
|
+
"""Handle run_info events."""
|
|
353
|
+
self._handle_run_info_event(ev, meta, renderer)
|
|
354
|
+
return final_text, stats_usage
|
|
355
|
+
|
|
356
|
+
def _handle_render_only_event(
|
|
357
|
+
self,
|
|
358
|
+
ev: dict[str, Any],
|
|
359
|
+
renderer: RichStreamRenderer,
|
|
360
|
+
final_text: str,
|
|
361
|
+
stats_usage: dict[str, Any],
|
|
362
|
+
_meta: dict[str, Any],
|
|
363
|
+
_skip_final_render: bool,
|
|
364
|
+
) -> tuple[str, dict[str, Any]]:
|
|
365
|
+
"""Handle events that only need rendering (artifact, status_update)."""
|
|
366
|
+
renderer.on_event(ev)
|
|
367
|
+
return final_text, stats_usage
|
|
368
|
+
|
|
369
|
+
def _handle_content_event_async(
|
|
370
|
+
self,
|
|
371
|
+
ev: dict[str, Any],
|
|
372
|
+
renderer: RichStreamRenderer,
|
|
373
|
+
final_text: str,
|
|
374
|
+
stats_usage: dict[str, Any],
|
|
375
|
+
last_rendered_content: str | None,
|
|
376
|
+
) -> tuple[str, dict[str, Any]]:
|
|
377
|
+
"""Handle content events with deduplication."""
|
|
378
|
+
content = ev.get("content")
|
|
379
|
+
if content:
|
|
380
|
+
content_str = str(content)
|
|
381
|
+
if not content_str.startswith("Artifact received:"):
|
|
382
|
+
if content_str != last_rendered_content:
|
|
383
|
+
renderer.on_event(ev)
|
|
384
|
+
final_text = content_str
|
|
385
|
+
else:
|
|
386
|
+
renderer.on_event(ev)
|
|
387
|
+
return final_text, stats_usage
|
|
388
|
+
|
|
389
|
+
def _get_event_kind(self, ev: dict[str, Any]) -> str | None:
|
|
390
|
+
"""Extract normalized event kind from parsed event.
|
|
391
|
+
|
|
392
|
+
Args:
|
|
393
|
+
ev: Parsed event dictionary.
|
|
394
|
+
|
|
395
|
+
Returns:
|
|
396
|
+
Event kind string or None.
|
|
397
|
+
"""
|
|
398
|
+
metadata = ev.get("metadata") or {}
|
|
399
|
+
kind = metadata.get("kind")
|
|
400
|
+
if kind:
|
|
401
|
+
return str(kind)
|
|
402
|
+
event_type = ev.get("event_type")
|
|
403
|
+
return str(event_type) if event_type else None
|
|
404
|
+
|
|
405
|
+
def _extract_content_string(self, event: dict[str, Any]) -> str | None:
|
|
406
|
+
"""Extract textual content from a parsed event.
|
|
407
|
+
|
|
408
|
+
Args:
|
|
409
|
+
event: Parsed event dictionary.
|
|
410
|
+
|
|
411
|
+
Returns:
|
|
412
|
+
Content string or None.
|
|
413
|
+
"""
|
|
414
|
+
if not event:
|
|
415
|
+
return None
|
|
416
|
+
content = event.get("content")
|
|
417
|
+
if content:
|
|
418
|
+
return str(content)
|
|
419
|
+
return None
|
|
420
|
+
|
|
166
421
|
def _capture_request_id(
|
|
167
422
|
self,
|
|
168
423
|
stream_response: httpx.Response,
|
|
@@ -413,3 +668,33 @@ def compute_timeout_seconds(kwargs: dict[str, Any]) -> float:
|
|
|
413
668
|
if not specified in kwargs.
|
|
414
669
|
"""
|
|
415
670
|
return kwargs.get("timeout", DEFAULT_AGENT_RUN_TIMEOUT)
|
|
671
|
+
|
|
672
|
+
|
|
673
|
+
def finalize_render_manager(
|
|
674
|
+
manager: AgentRunRenderingManager,
|
|
675
|
+
renderer: RichStreamRenderer,
|
|
676
|
+
final_text: str,
|
|
677
|
+
stats_usage: dict[str, Any],
|
|
678
|
+
started_monotonic: float | None,
|
|
679
|
+
finished_monotonic: float | None,
|
|
680
|
+
) -> str:
|
|
681
|
+
"""Helper to finalize renderer via manager and return final text.
|
|
682
|
+
|
|
683
|
+
Args:
|
|
684
|
+
manager: The rendering manager instance.
|
|
685
|
+
renderer: Renderer to finalize.
|
|
686
|
+
final_text: Final text content.
|
|
687
|
+
stats_usage: Usage statistics dictionary.
|
|
688
|
+
started_monotonic: Start time (monotonic).
|
|
689
|
+
finished_monotonic: Finish time (monotonic).
|
|
690
|
+
|
|
691
|
+
Returns:
|
|
692
|
+
Final text string.
|
|
693
|
+
"""
|
|
694
|
+
return manager.finalize_renderer(
|
|
695
|
+
renderer,
|
|
696
|
+
final_text,
|
|
697
|
+
stats_usage,
|
|
698
|
+
started_monotonic,
|
|
699
|
+
finished_monotonic,
|
|
700
|
+
)
|
glaip_sdk/runner/langgraph.py
CHANGED
|
@@ -20,25 +20,52 @@ from __future__ import annotations
|
|
|
20
20
|
import asyncio
|
|
21
21
|
import inspect
|
|
22
22
|
from dataclasses import dataclass
|
|
23
|
+
import logging
|
|
23
24
|
from typing import TYPE_CHECKING, Any
|
|
24
25
|
|
|
26
|
+
from gllm_core.utils import LoggerManager
|
|
27
|
+
|
|
25
28
|
from glaip_sdk.runner.base import BaseRunner
|
|
26
29
|
from glaip_sdk.runner.deps import (
|
|
27
30
|
check_local_runtime_available,
|
|
28
31
|
get_local_runtime_missing_message,
|
|
29
32
|
)
|
|
30
|
-
from glaip_sdk.
|
|
31
|
-
from gllm_core.utils import LoggerManager
|
|
33
|
+
from glaip_sdk.client.run_rendering import AgentRunRenderingManager
|
|
32
34
|
|
|
33
35
|
if TYPE_CHECKING:
|
|
34
36
|
from langchain_core.messages import BaseMessage
|
|
35
37
|
|
|
36
38
|
from glaip_sdk.agents.base import Agent
|
|
37
39
|
|
|
38
|
-
logger = LoggerManager().get_logger(__name__)
|
|
39
40
|
|
|
40
|
-
|
|
41
|
-
|
|
41
|
+
_AIP_LOGS_SWALLOWED = False
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def _swallow_aip_logs(level: int = logging.ERROR) -> None:
|
|
45
|
+
"""Consume noisy AIPAgents logs once (opt-in via runner flag)."""
|
|
46
|
+
global _AIP_LOGS_SWALLOWED
|
|
47
|
+
if _AIP_LOGS_SWALLOWED:
|
|
48
|
+
return
|
|
49
|
+
prefixes = ("aip_agents.",)
|
|
50
|
+
|
|
51
|
+
def _silence(name: str) -> None:
|
|
52
|
+
lg = logging.getLogger(name)
|
|
53
|
+
lg.handlers = [logging.NullHandler()]
|
|
54
|
+
lg.propagate = False
|
|
55
|
+
lg.setLevel(level)
|
|
56
|
+
|
|
57
|
+
# Silence any already-registered loggers under the given prefixes
|
|
58
|
+
for logger_name in logging.root.manager.loggerDict:
|
|
59
|
+
if any(logger_name.startswith(prefix) for prefix in prefixes):
|
|
60
|
+
_silence(logger_name)
|
|
61
|
+
|
|
62
|
+
# Also set the base prefix loggers so future children inherit silence
|
|
63
|
+
for prefix in prefixes:
|
|
64
|
+
_silence(prefix.rstrip("."))
|
|
65
|
+
_AIP_LOGS_SWALLOWED = True
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
logger = LoggerManager().get_logger(__name__)
|
|
42
69
|
|
|
43
70
|
|
|
44
71
|
def _convert_chat_history_to_messages(
|
|
@@ -81,9 +108,10 @@ def _convert_chat_history_to_messages(
|
|
|
81
108
|
class LangGraphRunner(BaseRunner):
|
|
82
109
|
"""Runner implementation using aip-agents LangGraphReactAgent.
|
|
83
110
|
|
|
84
|
-
|
|
85
|
-
- Execute via `LangGraphReactAgent.
|
|
86
|
-
-
|
|
111
|
+
Current behavior:
|
|
112
|
+
- Execute via `LangGraphReactAgent.arun_sse_stream()` (normalized SSE-compatible stream)
|
|
113
|
+
- Route all events through `AgentRunRenderingManager.async_process_stream_events`
|
|
114
|
+
for unified rendering between local and remote agents
|
|
87
115
|
|
|
88
116
|
Attributes:
|
|
89
117
|
default_model: Model name to use when agent.model is not set.
|
|
@@ -99,6 +127,8 @@ class LangGraphRunner(BaseRunner):
|
|
|
99
127
|
verbose: bool = False,
|
|
100
128
|
runtime_config: dict[str, Any] | None = None,
|
|
101
129
|
chat_history: list[dict[str, str]] | None = None,
|
|
130
|
+
*,
|
|
131
|
+
swallow_aip_logs: bool = True,
|
|
102
132
|
**kwargs: Any,
|
|
103
133
|
) -> str:
|
|
104
134
|
"""Execute agent synchronously and return final response text.
|
|
@@ -113,6 +143,9 @@ class LangGraphRunner(BaseRunner):
|
|
|
113
143
|
chat_history: Optional list of prior conversation messages.
|
|
114
144
|
Each message is a dict with "role" and "content" keys.
|
|
115
145
|
Defaults to None.
|
|
146
|
+
swallow_aip_logs: When True (default), silence noisy logs from aip-agents,
|
|
147
|
+
gllm_inference, OpenAILMInvoker, and httpx. Set to False to honor user
|
|
148
|
+
logging configuration.
|
|
116
149
|
**kwargs: Additional keyword arguments passed to the backend.
|
|
117
150
|
|
|
118
151
|
Returns:
|
|
@@ -141,6 +174,7 @@ class LangGraphRunner(BaseRunner):
|
|
|
141
174
|
verbose=verbose,
|
|
142
175
|
runtime_config=runtime_config,
|
|
143
176
|
chat_history=chat_history,
|
|
177
|
+
swallow_aip_logs=swallow_aip_logs,
|
|
144
178
|
**kwargs,
|
|
145
179
|
)
|
|
146
180
|
|
|
@@ -153,6 +187,8 @@ class LangGraphRunner(BaseRunner):
|
|
|
153
187
|
verbose: bool = False,
|
|
154
188
|
runtime_config: dict[str, Any] | None = None,
|
|
155
189
|
chat_history: list[dict[str, str]] | None = None,
|
|
190
|
+
*,
|
|
191
|
+
swallow_aip_logs: bool = True,
|
|
156
192
|
**kwargs: Any,
|
|
157
193
|
) -> str:
|
|
158
194
|
"""Execute agent asynchronously and return final response text.
|
|
@@ -167,6 +203,7 @@ class LangGraphRunner(BaseRunner):
|
|
|
167
203
|
chat_history: Optional list of prior conversation messages.
|
|
168
204
|
Each message is a dict with "role" and "content" keys.
|
|
169
205
|
Defaults to None.
|
|
206
|
+
swallow_aip_logs: When True (default), silence noisy AIPAgents logs.
|
|
170
207
|
**kwargs: Additional keyword arguments passed to the backend.
|
|
171
208
|
|
|
172
209
|
Returns:
|
|
@@ -181,6 +218,7 @@ class LangGraphRunner(BaseRunner):
|
|
|
181
218
|
verbose=verbose,
|
|
182
219
|
runtime_config=runtime_config,
|
|
183
220
|
chat_history=chat_history,
|
|
221
|
+
swallow_aip_logs=swallow_aip_logs,
|
|
184
222
|
**kwargs,
|
|
185
223
|
)
|
|
186
224
|
|
|
@@ -191,6 +229,8 @@ class LangGraphRunner(BaseRunner):
|
|
|
191
229
|
verbose: bool = False,
|
|
192
230
|
runtime_config: dict[str, Any] | None = None,
|
|
193
231
|
chat_history: list[dict[str, str]] | None = None,
|
|
232
|
+
*,
|
|
233
|
+
swallow_aip_logs: bool = True,
|
|
194
234
|
**kwargs: Any,
|
|
195
235
|
) -> str:
|
|
196
236
|
"""Internal async implementation of agent execution.
|
|
@@ -201,11 +241,16 @@ class LangGraphRunner(BaseRunner):
|
|
|
201
241
|
verbose: If True, emit debug trace output during execution.
|
|
202
242
|
runtime_config: Optional runtime configuration for tools, MCPs, etc.
|
|
203
243
|
chat_history: Optional list of prior conversation messages.
|
|
244
|
+
swallow_aip_logs: When True (default), silence noisy AIPAgents logs.
|
|
204
245
|
**kwargs: Additional keyword arguments passed to the backend.
|
|
205
246
|
|
|
206
247
|
Returns:
|
|
207
248
|
The final response text from the agent.
|
|
208
249
|
"""
|
|
250
|
+
# Optionally swallow noisy AIPAgents logs
|
|
251
|
+
if swallow_aip_logs:
|
|
252
|
+
_swallow_aip_logs()
|
|
253
|
+
|
|
209
254
|
# Build the local LangGraphReactAgent from the glaip_sdk Agent
|
|
210
255
|
local_agent = self.build_langgraph_agent(agent, runtime_config=runtime_config)
|
|
211
256
|
|
|
@@ -219,15 +264,42 @@ class LangGraphRunner(BaseRunner):
|
|
|
219
264
|
agent.name,
|
|
220
265
|
)
|
|
221
266
|
|
|
222
|
-
#
|
|
223
|
-
|
|
267
|
+
# Use shared render manager for unified processing
|
|
268
|
+
render_manager = AgentRunRenderingManager(logger)
|
|
269
|
+
renderer = render_manager.create_renderer(kwargs.get("renderer"), verbose=verbose)
|
|
270
|
+
meta = render_manager.build_initial_metadata(agent.name, message, kwargs)
|
|
271
|
+
render_manager.start_renderer(renderer, meta)
|
|
272
|
+
|
|
273
|
+
try:
|
|
274
|
+
# Use shared async stream processor for unified event handling
|
|
275
|
+
(
|
|
276
|
+
final_text,
|
|
277
|
+
stats_usage,
|
|
278
|
+
started_monotonic,
|
|
279
|
+
finished_monotonic,
|
|
280
|
+
) = await render_manager.async_process_stream_events(
|
|
281
|
+
local_agent.arun_sse_stream(message, **kwargs),
|
|
282
|
+
renderer,
|
|
283
|
+
meta,
|
|
284
|
+
skip_final_render=True,
|
|
285
|
+
)
|
|
286
|
+
except KeyboardInterrupt:
|
|
287
|
+
try:
|
|
288
|
+
renderer.close()
|
|
289
|
+
finally:
|
|
290
|
+
raise
|
|
291
|
+
except Exception:
|
|
292
|
+
try:
|
|
293
|
+
renderer.close()
|
|
294
|
+
finally:
|
|
295
|
+
raise
|
|
224
296
|
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
self._log_event(event)
|
|
228
|
-
events.append(event)
|
|
297
|
+
# Use shared finalizer to avoid code duplication
|
|
298
|
+
from glaip_sdk.client.run_rendering import finalize_render_manager # noqa: PLC0415
|
|
229
299
|
|
|
230
|
-
return
|
|
300
|
+
return finalize_render_manager(
|
|
301
|
+
render_manager, renderer, final_text, stats_usage, started_monotonic, finished_monotonic
|
|
302
|
+
)
|
|
231
303
|
|
|
232
304
|
def build_langgraph_agent(
|
|
233
305
|
self,
|
|
@@ -249,6 +321,7 @@ class LangGraphRunner(BaseRunner):
|
|
|
249
321
|
ValueError: If agent has unsupported tools, MCPs, or sub-agents for local mode.
|
|
250
322
|
"""
|
|
251
323
|
from aip_agents.agent import LangGraphReactAgent # noqa: PLC0415
|
|
324
|
+
|
|
252
325
|
from glaip_sdk.runner.tool_adapter import LangChainToolAdapter # noqa: PLC0415
|
|
253
326
|
|
|
254
327
|
# Adapt tools for local execution
|
|
@@ -572,6 +645,9 @@ class LangGraphRunner(BaseRunner):
|
|
|
572
645
|
direct_params["planning"] = agent_config["planning"]
|
|
573
646
|
|
|
574
647
|
# Kwargs parameters (passed through **kwargs to BaseAgent)
|
|
648
|
+
if "enable_pii" in agent_config:
|
|
649
|
+
kwargs_params["enable_pii"] = agent_config["enable_pii"]
|
|
650
|
+
|
|
575
651
|
if "memory" in agent_config:
|
|
576
652
|
# Map "memory" to "memory_backend" for aip-agents compatibility
|
|
577
653
|
kwargs_params["memory_backend"] = agent_config["memory"]
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: glaip-sdk
|
|
3
|
-
Version: 0.6.
|
|
3
|
+
Version: 0.6.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,10 +13,11 @@ Classifier: Programming Language :: Python :: 3.12
|
|
|
13
13
|
Provides-Extra: dev
|
|
14
14
|
Provides-Extra: memory
|
|
15
15
|
Provides-Extra: privacy
|
|
16
|
-
Requires-Dist: aip-agents-binary (>=0.5.
|
|
17
|
-
Requires-Dist: aip-agents[memory] (>=0.5.
|
|
18
|
-
Requires-Dist: aip-agents[privacy] (>=0.5.
|
|
16
|
+
Requires-Dist: aip-agents-binary (>=0.5.4)
|
|
17
|
+
Requires-Dist: aip-agents[memory] (>=0.5.4) ; (python_version >= "3.11" and python_version < "3.13") and (extra == "memory")
|
|
18
|
+
Requires-Dist: aip-agents[privacy] (>=0.5.4) ; (python_version >= "3.11" and python_version < "3.13") and (extra == "privacy")
|
|
19
19
|
Requires-Dist: click (>=8.2.0,<8.3.0)
|
|
20
|
+
Requires-Dist: en-core-web-sm ; extra == "privacy"
|
|
20
21
|
Requires-Dist: gllm-core-binary (>=0.1.0)
|
|
21
22
|
Requires-Dist: gllm-tools-binary (>=0.1.3)
|
|
22
23
|
Requires-Dist: httpx (>=0.28.1)
|
|
@@ -62,11 +62,11 @@ glaip_sdk/cli/validators.py,sha256=d-kq4y7HWMo6Gc7wLXWUsCt8JwFvJX_roZqRm1Nko1I,5
|
|
|
62
62
|
glaip_sdk/client/__init__.py,sha256=F-eE_dRSzA0cc1it06oi0tZetZBHmSUjWSHGhJMLCls,263
|
|
63
63
|
glaip_sdk/client/_agent_payloads.py,sha256=cH7CvNRn0JvudwKLr072E7W2QGWO9r-4xDxWMvXoPKE,17865
|
|
64
64
|
glaip_sdk/client/agent_runs.py,sha256=tZSFEZZ3Yx0uYRgnwkLe-X0TlmgKJQ-ivzb6SrVnxY8,4862
|
|
65
|
-
glaip_sdk/client/agents.py,sha256=
|
|
65
|
+
glaip_sdk/client/agents.py,sha256=75uDLN85Smf67rw-jFhlVKyiToicAfcFyJHSvWJkAww,47631
|
|
66
66
|
glaip_sdk/client/base.py,sha256=BhNaC2TJJ2jVWRTYmfxD3WjYgAyIuWNz9YURdNXXjJo,18245
|
|
67
67
|
glaip_sdk/client/main.py,sha256=RTREAOgGouYm4lFKkpNBQ9dmxalnBsIpSSaQLWVFSmU,9054
|
|
68
68
|
glaip_sdk/client/mcps.py,sha256=gFRuLOGeh6ieIhR4PeD6yNVT6NhvUMTqPq9iuu1vkAY,13019
|
|
69
|
-
glaip_sdk/client/run_rendering.py,sha256=
|
|
69
|
+
glaip_sdk/client/run_rendering.py,sha256=j0BTDfy13lFX-B4T-Own-NtmqefoRGQ4M5DM6QRkiTs,24109
|
|
70
70
|
glaip_sdk/client/shared.py,sha256=esHlsR0LEfL-pFDaWebQjKKOLl09jsRY-2pllBUn4nU,522
|
|
71
71
|
glaip_sdk/client/tools.py,sha256=kK0rBwX1e_5AlGQRjlO6rNz6gDlohhXWdlxN9AwotdE,22585
|
|
72
72
|
glaip_sdk/client/validators.py,sha256=ioF9VCs-LG2yLkaRDd7Hff74lojDZZ0_Q3CiLbdm1RY,8381
|
|
@@ -92,7 +92,7 @@ glaip_sdk/rich_components.py,sha256=44Z0V1ZQleVh9gUDGwRR5mriiYFnVGOhm7fFxZYbP8c,
|
|
|
92
92
|
glaip_sdk/runner/__init__.py,sha256=8RrngoGfpF8x9X27RPdX4gJjch75ZvhtVt_6UV0ULLQ,1615
|
|
93
93
|
glaip_sdk/runner/base.py,sha256=KIjcSAyDCP9_mn2H4rXR5gu1FZlwD9pe0gkTBmr6Yi4,2663
|
|
94
94
|
glaip_sdk/runner/deps.py,sha256=3ZDWyvWu4LFJOGHd18tv3VzVo8NY5gb1VeZIelMknyI,3934
|
|
95
|
-
glaip_sdk/runner/langgraph.py,sha256=
|
|
95
|
+
glaip_sdk/runner/langgraph.py,sha256=97fCY4BwBj-APID3e4qQUUwXLEDbrxTyTqHhN2Z7RcA,28811
|
|
96
96
|
glaip_sdk/runner/mcp_adapter/__init__.py,sha256=Rdttfg3N6kg3-DaTCKqaGXKByZyBt0Mwf6FV8s_5kI8,462
|
|
97
97
|
glaip_sdk/runner/mcp_adapter/base_mcp_adapter.py,sha256=ic56fKgb3zgVZZQm3ClWUZi7pE1t4EVq8mOg6AM6hdA,1374
|
|
98
98
|
glaip_sdk/runner/mcp_adapter/langchain_mcp_adapter.py,sha256=b58GuadPz7q7aXoJyTYs0eeJ_oqp-wLR1tcr_5cbV1s,9723
|
|
@@ -153,7 +153,7 @@ glaip_sdk/utils/serialization.py,sha256=z-qpvWLSBrGK3wbUclcA1UIKLXJedTnMSwPdq-FF
|
|
|
153
153
|
glaip_sdk/utils/sync.py,sha256=3VKqs1UfNGWSobgRXohBKP7mMMzdUW3SU0bJQ1uxOgw,4872
|
|
154
154
|
glaip_sdk/utils/tool_detection.py,sha256=g410GNug_PhLye8rd9UU-LVFIKq3jHPbmSItEkLxPTc,807
|
|
155
155
|
glaip_sdk/utils/validation.py,sha256=hB_k3lvHdIFUiSwHStrC0Eqnhx0OG2UvwqASeem0HuQ,6859
|
|
156
|
-
glaip_sdk-0.6.
|
|
157
|
-
glaip_sdk-0.6.
|
|
158
|
-
glaip_sdk-0.6.
|
|
159
|
-
glaip_sdk-0.6.
|
|
156
|
+
glaip_sdk-0.6.11.dist-info/METADATA,sha256=QVzKd6VTTlmr4-YA5D_ECf2w5XM14RAPpcT9RZq5Lms,7971
|
|
157
|
+
glaip_sdk-0.6.11.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
|
|
158
|
+
glaip_sdk-0.6.11.dist-info/entry_points.txt,sha256=EGs8NO8J1fdFMWA3CsF7sKBEvtHb_fujdCoNPhfMouE,47
|
|
159
|
+
glaip_sdk-0.6.11.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|