glaip-sdk 0.7.2__py3-none-any.whl → 0.7.4__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/agents/base.py +32 -9
- glaip_sdk/cli/entrypoint.py +20 -0
- glaip_sdk/cli/main.py +6 -0
- glaip_sdk/hitl/__init__.py +21 -1
- glaip_sdk/hitl/callback.py +43 -0
- glaip_sdk/hitl/local.py +1 -31
- glaip_sdk/runner/__init__.py +20 -3
- glaip_sdk/runner/langgraph.py +4 -2
- glaip_sdk/runner/logging_config.py +77 -0
- glaip_sdk/utils/bundler.py +138 -2
- glaip_sdk/utils/import_resolver.py +3 -9
- glaip_sdk/utils/sync.py +31 -11
- glaip_sdk/utils/tool_detection.py +21 -0
- {glaip_sdk-0.7.2.dist-info → glaip_sdk-0.7.4.dist-info}/METADATA +1 -1
- {glaip_sdk-0.7.2.dist-info → glaip_sdk-0.7.4.dist-info}/RECORD +18 -15
- glaip_sdk-0.7.4.dist-info/entry_points.txt +2 -0
- glaip_sdk-0.7.2.dist-info/entry_points.txt +0 -2
- {glaip_sdk-0.7.2.dist-info → glaip_sdk-0.7.4.dist-info}/WHEEL +0 -0
- {glaip_sdk-0.7.2.dist-info → glaip_sdk-0.7.4.dist-info}/top_level.txt +0 -0
glaip_sdk/agents/base.py
CHANGED
|
@@ -46,8 +46,6 @@ import inspect
|
|
|
46
46
|
import logging
|
|
47
47
|
import warnings
|
|
48
48
|
from collections.abc import AsyncGenerator
|
|
49
|
-
|
|
50
|
-
|
|
51
49
|
from pathlib import Path
|
|
52
50
|
from typing import TYPE_CHECKING, Any
|
|
53
51
|
|
|
@@ -942,7 +940,16 @@ class Agent:
|
|
|
942
940
|
|
|
943
941
|
if check_local_runtime_available():
|
|
944
942
|
return get_default_runner()
|
|
945
|
-
|
|
943
|
+
|
|
944
|
+
# If agent is not deployed, it *must* use local runtime
|
|
945
|
+
if not self.id:
|
|
946
|
+
raise ValueError(f"{_AGENT_NOT_DEPLOYED_MSG}\n\n{get_local_runtime_missing_message()}")
|
|
947
|
+
|
|
948
|
+
# If agent IS deployed but local execution was forced (local=True)
|
|
949
|
+
raise ValueError(
|
|
950
|
+
f"Local execution override was requested, but local runtime is missing.\n\n"
|
|
951
|
+
f"{get_local_runtime_missing_message()}"
|
|
952
|
+
)
|
|
946
953
|
|
|
947
954
|
def _prepare_local_runner_kwargs(
|
|
948
955
|
self,
|
|
@@ -977,6 +984,7 @@ class Agent:
|
|
|
977
984
|
self,
|
|
978
985
|
message: str,
|
|
979
986
|
verbose: bool = False,
|
|
987
|
+
local: bool = False,
|
|
980
988
|
runtime_config: dict[str, Any] | None = None,
|
|
981
989
|
chat_history: list[dict[str, str]] | None = None,
|
|
982
990
|
**kwargs: Any,
|
|
@@ -989,9 +997,13 @@ class Agent:
|
|
|
989
997
|
- **Local**: When the agent is not deployed and glaip-sdk[local] is installed,
|
|
990
998
|
execution happens locally via aip-agents (no server required).
|
|
991
999
|
|
|
1000
|
+
You can force local execution for a deployed agent by passing `local=True`.
|
|
1001
|
+
|
|
992
1002
|
Args:
|
|
993
1003
|
message: The message to send to the agent.
|
|
994
1004
|
verbose: If True, print streaming output to console. Defaults to False.
|
|
1005
|
+
local: If True, force local execution even if the agent is deployed.
|
|
1006
|
+
Defaults to False.
|
|
995
1007
|
runtime_config: Optional runtime configuration for tools, MCPs, and agents.
|
|
996
1008
|
Keys can be SDK objects, UUIDs, or names. Example:
|
|
997
1009
|
{
|
|
@@ -1013,16 +1025,19 @@ class Agent:
|
|
|
1013
1025
|
RuntimeError: If server-backed execution fails due to client issues.
|
|
1014
1026
|
"""
|
|
1015
1027
|
# Backend routing: deployed agents use server, undeployed use local (if available)
|
|
1016
|
-
if self.id:
|
|
1028
|
+
if self.id and not local:
|
|
1017
1029
|
# Server-backed execution path (agent is deployed)
|
|
1018
1030
|
agent_client, call_kwargs = self._prepare_run_kwargs(
|
|
1019
|
-
message,
|
|
1031
|
+
message,
|
|
1032
|
+
verbose,
|
|
1033
|
+
runtime_config or kwargs.get("runtime_config"),
|
|
1034
|
+
**kwargs,
|
|
1020
1035
|
)
|
|
1021
1036
|
if chat_history is not None:
|
|
1022
1037
|
call_kwargs["chat_history"] = chat_history
|
|
1023
1038
|
return agent_client.run_agent(**call_kwargs)
|
|
1024
1039
|
|
|
1025
|
-
# Local execution path (agent is not deployed)
|
|
1040
|
+
# Local execution path (agent is not deployed OR local=True)
|
|
1026
1041
|
runner = self._get_local_runner_or_raise()
|
|
1027
1042
|
local_kwargs = self._prepare_local_runner_kwargs(message, verbose, runtime_config, chat_history, **kwargs)
|
|
1028
1043
|
return runner.run(**local_kwargs)
|
|
@@ -1031,6 +1046,7 @@ class Agent:
|
|
|
1031
1046
|
self,
|
|
1032
1047
|
message: str,
|
|
1033
1048
|
verbose: bool = False,
|
|
1049
|
+
local: bool = False,
|
|
1034
1050
|
runtime_config: dict[str, Any] | None = None,
|
|
1035
1051
|
chat_history: list[dict[str, str]] | None = None,
|
|
1036
1052
|
**kwargs: Any,
|
|
@@ -1043,9 +1059,13 @@ class Agent:
|
|
|
1043
1059
|
- **Local**: When the agent is not deployed and glaip-sdk[local] is installed,
|
|
1044
1060
|
execution happens locally via aip-agents (no server required).
|
|
1045
1061
|
|
|
1062
|
+
You can force local execution for a deployed agent by passing `local=True`.
|
|
1063
|
+
|
|
1046
1064
|
Args:
|
|
1047
1065
|
message: The message to send to the agent.
|
|
1048
1066
|
verbose: If True, print streaming output to console. Defaults to False.
|
|
1067
|
+
local: If True, force local execution even if the agent is deployed.
|
|
1068
|
+
Defaults to False.
|
|
1049
1069
|
runtime_config: Optional runtime configuration for tools, MCPs, and agents.
|
|
1050
1070
|
Keys can be SDK objects, UUIDs, or names. Example:
|
|
1051
1071
|
{
|
|
@@ -1067,10 +1087,13 @@ class Agent:
|
|
|
1067
1087
|
RuntimeError: If server-backed execution fails due to client issues.
|
|
1068
1088
|
"""
|
|
1069
1089
|
# Backend routing: deployed agents use server, undeployed use local (if available)
|
|
1070
|
-
if self.id:
|
|
1090
|
+
if self.id and not local:
|
|
1071
1091
|
# Server-backed execution path (agent is deployed)
|
|
1072
1092
|
agent_client, call_kwargs = self._prepare_run_kwargs(
|
|
1073
|
-
message,
|
|
1093
|
+
message,
|
|
1094
|
+
verbose,
|
|
1095
|
+
runtime_config or kwargs.get("runtime_config"),
|
|
1096
|
+
**kwargs,
|
|
1074
1097
|
)
|
|
1075
1098
|
if chat_history is not None:
|
|
1076
1099
|
call_kwargs["chat_history"] = chat_history
|
|
@@ -1079,7 +1102,7 @@ class Agent:
|
|
|
1079
1102
|
yield chunk
|
|
1080
1103
|
return
|
|
1081
1104
|
|
|
1082
|
-
# Local execution path (agent is not deployed)
|
|
1105
|
+
# Local execution path (agent is not deployed OR local=True)
|
|
1083
1106
|
runner = self._get_local_runner_or_raise()
|
|
1084
1107
|
local_kwargs = self._prepare_local_runner_kwargs(message, verbose, runtime_config, chat_history, **kwargs)
|
|
1085
1108
|
result = await runner.arun(**local_kwargs)
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"""Entry point wrapper for early logging configuration.
|
|
2
|
+
|
|
3
|
+
This must be imported BEFORE glaip_sdk.cli.main to catch import-time warnings.
|
|
4
|
+
|
|
5
|
+
Authors:
|
|
6
|
+
Raymond Christopher (raymond.christopher@gdplabs.id)
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
import sys
|
|
10
|
+
|
|
11
|
+
# Configure logging BEFORE importing anything else
|
|
12
|
+
from glaip_sdk.runner.logging_config import setup_cli_logging
|
|
13
|
+
|
|
14
|
+
setup_cli_logging()
|
|
15
|
+
|
|
16
|
+
# Now import and run CLI
|
|
17
|
+
from glaip_sdk.cli import main # noqa: E402
|
|
18
|
+
|
|
19
|
+
if __name__ == "__main__":
|
|
20
|
+
sys.exit(main()) # pylint: disable=no-value-for-parameter
|
glaip_sdk/cli/main.py
CHANGED
|
@@ -73,6 +73,12 @@ def _resolve_client_class() -> type[Any]:
|
|
|
73
73
|
|
|
74
74
|
def _suppress_chatty_loggers() -> None:
|
|
75
75
|
"""Silence noisy SDK/httpx logs for CLI output."""
|
|
76
|
+
# Ensure CLI logging is configured (idempotent)
|
|
77
|
+
from glaip_sdk.runner.logging_config import setup_cli_logging # noqa: PLC0415
|
|
78
|
+
|
|
79
|
+
setup_cli_logging()
|
|
80
|
+
|
|
81
|
+
# Also suppress SDK-specific loggers
|
|
76
82
|
noisy_loggers = [
|
|
77
83
|
"glaip_sdk.client",
|
|
78
84
|
"httpx",
|
glaip_sdk/hitl/__init__.py
CHANGED
|
@@ -13,10 +13,16 @@ Authors:
|
|
|
13
13
|
GLAIP SDK Team
|
|
14
14
|
"""
|
|
15
15
|
|
|
16
|
+
from typing import TYPE_CHECKING, Any
|
|
17
|
+
|
|
18
|
+
# These don't require aip_agents, so import them directly
|
|
16
19
|
from glaip_sdk.hitl.base import HITLCallback, HITLDecision, HITLRequest, HITLResponse
|
|
17
|
-
from glaip_sdk.hitl.
|
|
20
|
+
from glaip_sdk.hitl.callback import PauseResumeCallback
|
|
18
21
|
from glaip_sdk.hitl.remote import RemoteHITLHandler
|
|
19
22
|
|
|
23
|
+
if TYPE_CHECKING:
|
|
24
|
+
from glaip_sdk.hitl.local import LocalPromptHandler
|
|
25
|
+
|
|
20
26
|
__all__ = [
|
|
21
27
|
"LocalPromptHandler",
|
|
22
28
|
"PauseResumeCallback",
|
|
@@ -26,3 +32,17 @@ __all__ = [
|
|
|
26
32
|
"HITLResponse",
|
|
27
33
|
"RemoteHITLHandler",
|
|
28
34
|
]
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def __getattr__(name: str) -> Any: # noqa: ANN401
|
|
38
|
+
"""Lazy import for LocalPromptHandler.
|
|
39
|
+
|
|
40
|
+
This defers the import of aip_agents until LocalPromptHandler is actually accessed,
|
|
41
|
+
preventing ImportError when aip-agents is not installed but HITL is not being used.
|
|
42
|
+
"""
|
|
43
|
+
if name == "LocalPromptHandler":
|
|
44
|
+
from glaip_sdk.hitl.local import LocalPromptHandler # noqa: PLC0415
|
|
45
|
+
|
|
46
|
+
globals()["LocalPromptHandler"] = LocalPromptHandler
|
|
47
|
+
return LocalPromptHandler
|
|
48
|
+
raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
"""Pause/resume callback for HITL renderer control.
|
|
2
|
+
|
|
3
|
+
This module provides PauseResumeCallback which allows HITL prompt handlers
|
|
4
|
+
to control the live renderer without directly coupling to the renderer implementation.
|
|
5
|
+
|
|
6
|
+
Author:
|
|
7
|
+
Putu Ravindra Wiguna (putu.r.wiguna@gdplabs.id)
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from typing import Any
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class PauseResumeCallback:
|
|
14
|
+
"""Simple callback object for pausing/resuming the live renderer.
|
|
15
|
+
|
|
16
|
+
This allows the LocalPromptHandler to control the renderer without
|
|
17
|
+
directly coupling to the renderer implementation.
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
def __init__(self) -> None:
|
|
21
|
+
"""Initialize the callback."""
|
|
22
|
+
self._renderer: Any | None = None
|
|
23
|
+
|
|
24
|
+
def set_renderer(self, renderer: Any) -> None:
|
|
25
|
+
"""Set the renderer instance.
|
|
26
|
+
|
|
27
|
+
Args:
|
|
28
|
+
renderer: RichStreamRenderer instance with pause_live() and resume_live() methods.
|
|
29
|
+
"""
|
|
30
|
+
self._renderer = renderer
|
|
31
|
+
|
|
32
|
+
def pause(self) -> None:
|
|
33
|
+
"""Pause the live renderer before prompting."""
|
|
34
|
+
if self._renderer and hasattr(self._renderer, "_shutdown_live"):
|
|
35
|
+
self._renderer._shutdown_live()
|
|
36
|
+
|
|
37
|
+
def resume(self) -> None:
|
|
38
|
+
"""Resume the live renderer after prompting."""
|
|
39
|
+
if self._renderer and hasattr(self._renderer, "_ensure_live"):
|
|
40
|
+
self._renderer._ensure_live()
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
__all__ = ["PauseResumeCallback"]
|
glaip_sdk/hitl/local.py
CHANGED
|
@@ -118,34 +118,4 @@ class LocalPromptHandler(BasePromptHandler):
|
|
|
118
118
|
self._console.print(f"[dim]Context: {request.context}[/dim]")
|
|
119
119
|
|
|
120
120
|
|
|
121
|
-
|
|
122
|
-
"""Simple callback object for pausing/resuming the live renderer.
|
|
123
|
-
|
|
124
|
-
This allows the LocalPromptHandler to control the renderer without
|
|
125
|
-
directly coupling to the renderer implementation.
|
|
126
|
-
"""
|
|
127
|
-
|
|
128
|
-
def __init__(self) -> None:
|
|
129
|
-
"""Initialize the callback."""
|
|
130
|
-
self._renderer: Any | None = None
|
|
131
|
-
|
|
132
|
-
def set_renderer(self, renderer: Any) -> None:
|
|
133
|
-
"""Set the renderer instance.
|
|
134
|
-
|
|
135
|
-
Args:
|
|
136
|
-
renderer: RichStreamRenderer instance with pause_live() and resume_live() methods.
|
|
137
|
-
"""
|
|
138
|
-
self._renderer = renderer
|
|
139
|
-
|
|
140
|
-
def pause(self) -> None:
|
|
141
|
-
"""Pause the live renderer before prompting."""
|
|
142
|
-
if self._renderer and hasattr(self._renderer, "_shutdown_live"):
|
|
143
|
-
self._renderer._shutdown_live()
|
|
144
|
-
|
|
145
|
-
def resume(self) -> None:
|
|
146
|
-
"""Resume the live renderer after prompting."""
|
|
147
|
-
if self._renderer and hasattr(self._renderer, "_ensure_live"):
|
|
148
|
-
self._renderer._ensure_live()
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
__all__ = ["LocalPromptHandler", "PauseResumeCallback"]
|
|
121
|
+
__all__ = ["LocalPromptHandler"]
|
glaip_sdk/runner/__init__.py
CHANGED
|
@@ -19,18 +19,19 @@ Example:
|
|
|
19
19
|
>>> result = runner.run(agent, "Hello!")
|
|
20
20
|
"""
|
|
21
21
|
|
|
22
|
+
from typing import TYPE_CHECKING, Any
|
|
23
|
+
|
|
22
24
|
from glaip_sdk.runner.deps import (
|
|
23
25
|
LOCAL_RUNTIME_AVAILABLE,
|
|
24
26
|
check_local_runtime_available,
|
|
25
27
|
get_local_runtime_missing_message,
|
|
26
28
|
)
|
|
27
|
-
from glaip_sdk.runner.langgraph import LangGraphRunner
|
|
28
29
|
|
|
29
30
|
# Default runner instance
|
|
30
|
-
_default_runner:
|
|
31
|
+
_default_runner: Any | None = None
|
|
31
32
|
|
|
32
33
|
|
|
33
|
-
def get_default_runner() ->
|
|
34
|
+
def get_default_runner() -> Any:
|
|
34
35
|
"""Get the default runner instance for local agent execution.
|
|
35
36
|
|
|
36
37
|
Returns:
|
|
@@ -45,11 +46,17 @@ def get_default_runner() -> LangGraphRunner:
|
|
|
45
46
|
raise RuntimeError(get_local_runtime_missing_message())
|
|
46
47
|
|
|
47
48
|
if _default_runner is None:
|
|
49
|
+
# Lazy import to avoid requiring aip-agents when runner is not used
|
|
50
|
+
from glaip_sdk.runner.langgraph import LangGraphRunner # noqa: PLC0415
|
|
51
|
+
|
|
48
52
|
_default_runner = LangGraphRunner()
|
|
49
53
|
|
|
50
54
|
return _default_runner
|
|
51
55
|
|
|
52
56
|
|
|
57
|
+
if TYPE_CHECKING:
|
|
58
|
+
from glaip_sdk.runner.langgraph import LangGraphRunner
|
|
59
|
+
|
|
53
60
|
__all__ = [
|
|
54
61
|
"LOCAL_RUNTIME_AVAILABLE",
|
|
55
62
|
"LangGraphRunner",
|
|
@@ -57,3 +64,13 @@ __all__ = [
|
|
|
57
64
|
"get_default_runner",
|
|
58
65
|
"get_local_runtime_missing_message",
|
|
59
66
|
]
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
def __getattr__(name: str) -> Any:
|
|
70
|
+
"""Lazy import for LangGraphRunner to avoid requiring aip-agents when not used."""
|
|
71
|
+
if name == "LangGraphRunner":
|
|
72
|
+
from glaip_sdk.runner.langgraph import LangGraphRunner # noqa: PLC0415
|
|
73
|
+
|
|
74
|
+
globals()["LangGraphRunner"] = LangGraphRunner
|
|
75
|
+
return LangGraphRunner
|
|
76
|
+
raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
|
glaip_sdk/runner/langgraph.py
CHANGED
|
@@ -23,11 +23,10 @@ import logging
|
|
|
23
23
|
from dataclasses import dataclass
|
|
24
24
|
from typing import TYPE_CHECKING, Any
|
|
25
25
|
|
|
26
|
-
from aip_agents.agent.hitl.manager import ApprovalManager # noqa: PLC0415
|
|
27
26
|
from gllm_core.utils import LoggerManager
|
|
28
27
|
|
|
29
28
|
from glaip_sdk.client.run_rendering import AgentRunRenderingManager
|
|
30
|
-
from glaip_sdk.hitl import
|
|
29
|
+
from glaip_sdk.hitl import PauseResumeCallback
|
|
31
30
|
from glaip_sdk.runner.base import BaseRunner
|
|
32
31
|
from glaip_sdk.runner.deps import (
|
|
33
32
|
check_local_runtime_available,
|
|
@@ -434,6 +433,9 @@ class LangGraphRunner(BaseRunner):
|
|
|
434
433
|
hitl_enabled = merged_agent_config.get("hitl_enabled", False)
|
|
435
434
|
if hitl_enabled:
|
|
436
435
|
try:
|
|
436
|
+
from aip_agents.agent.hitl.manager import ApprovalManager # noqa: PLC0415
|
|
437
|
+
from glaip_sdk.hitl import LocalPromptHandler # noqa: PLC0415
|
|
438
|
+
|
|
437
439
|
local_agent.hitl_manager = ApprovalManager(
|
|
438
440
|
prompt_handler=LocalPromptHandler(pause_resume_callback=pause_resume_callback)
|
|
439
441
|
)
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
"""Logging configuration for CLI to suppress noisy dependency warnings.
|
|
2
|
+
|
|
3
|
+
This module provides centralized logging suppression for optional dependencies
|
|
4
|
+
that emit noisy warnings during CLI usage. Warnings are suppressed by default
|
|
5
|
+
but can be shown using GLAIP_LOG_LEVEL=DEBUG.
|
|
6
|
+
|
|
7
|
+
Authors:
|
|
8
|
+
Raymond Christopher (raymond.christopher@gdplabs.id)
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
import logging
|
|
12
|
+
import os
|
|
13
|
+
import warnings
|
|
14
|
+
|
|
15
|
+
NOISY_LOGGERS = ["transformers", "gllm_privacy", "google.cloud.aiplatform"]
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class NameFilter(logging.Filter):
|
|
19
|
+
"""Filter logs by logger name prefix."""
|
|
20
|
+
|
|
21
|
+
def __init__(self, prefixes: list[str]) -> None:
|
|
22
|
+
"""Initialize filter with logger name prefixes to suppress.
|
|
23
|
+
|
|
24
|
+
Args:
|
|
25
|
+
prefixes: List of logger name prefixes to filter out.
|
|
26
|
+
"""
|
|
27
|
+
super().__init__()
|
|
28
|
+
self.prefixes = prefixes
|
|
29
|
+
|
|
30
|
+
def filter(self, record: logging.LogRecord) -> bool:
|
|
31
|
+
"""Filter log records by name prefix.
|
|
32
|
+
|
|
33
|
+
Args:
|
|
34
|
+
record: Log record to filter.
|
|
35
|
+
|
|
36
|
+
Returns:
|
|
37
|
+
False if record should be suppressed, True otherwise.
|
|
38
|
+
"""
|
|
39
|
+
return not any(record.name.startswith(p) for p in self.prefixes)
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def setup_cli_logging() -> None:
|
|
43
|
+
"""Suppress INFO from noisy third-party libraries.
|
|
44
|
+
|
|
45
|
+
Use GLAIP_LOG_LEVEL=DEBUG to see all warnings.
|
|
46
|
+
This function is idempotent - calling it multiple times is safe.
|
|
47
|
+
"""
|
|
48
|
+
# Check env level FIRST before any suppression
|
|
49
|
+
env_level = os.getenv("GLAIP_LOG_LEVEL", "").upper()
|
|
50
|
+
is_debug = env_level == "DEBUG"
|
|
51
|
+
|
|
52
|
+
if is_debug:
|
|
53
|
+
# Debug mode: show everything, no suppression
|
|
54
|
+
if env_level and hasattr(logging, env_level):
|
|
55
|
+
logging.basicConfig(level=getattr(logging, env_level))
|
|
56
|
+
return
|
|
57
|
+
|
|
58
|
+
# Default mode: suppress noisy warnings
|
|
59
|
+
if env_level and hasattr(logging, env_level):
|
|
60
|
+
logging.basicConfig(level=getattr(logging, env_level))
|
|
61
|
+
|
|
62
|
+
# Add handler filter to suppress by name prefix (handles child loggers)
|
|
63
|
+
# Check if filter already exists to ensure idempotency
|
|
64
|
+
root_logger = logging.getLogger()
|
|
65
|
+
has_name_filter = any(isinstance(f, NameFilter) for h in root_logger.handlers for f in h.filters)
|
|
66
|
+
|
|
67
|
+
if not has_name_filter:
|
|
68
|
+
handler = logging.StreamHandler()
|
|
69
|
+
handler.addFilter(NameFilter(NOISY_LOGGERS))
|
|
70
|
+
root_logger.addHandler(handler)
|
|
71
|
+
|
|
72
|
+
# Suppress FutureWarning for GCS (idempotent - multiple calls are safe)
|
|
73
|
+
warnings.filterwarnings(
|
|
74
|
+
"ignore",
|
|
75
|
+
category=FutureWarning,
|
|
76
|
+
message=r".*google-cloud-storage.*",
|
|
77
|
+
)
|
glaip_sdk/utils/bundler.py
CHANGED
|
@@ -14,6 +14,7 @@ import inspect
|
|
|
14
14
|
from pathlib import Path
|
|
15
15
|
|
|
16
16
|
from glaip_sdk.utils.import_resolver import ImportResolver
|
|
17
|
+
from glaip_sdk.utils.tool_detection import is_tool_plugin_decorator
|
|
17
18
|
|
|
18
19
|
|
|
19
20
|
class ToolBundler:
|
|
@@ -50,9 +51,14 @@ class ToolBundler:
|
|
|
50
51
|
self.tool_dir = self.tool_file.parent
|
|
51
52
|
self._import_resolver = ImportResolver(self.tool_dir)
|
|
52
53
|
|
|
53
|
-
def bundle(self) -> str:
|
|
54
|
+
def bundle(self, add_tool_plugin_decorator: bool = True) -> str:
|
|
54
55
|
"""Bundle tool source code with inlined local imports.
|
|
55
56
|
|
|
57
|
+
Args:
|
|
58
|
+
add_tool_plugin_decorator: If True, add @tool_plugin decorator to BaseTool classes.
|
|
59
|
+
Set to False for newer servers (0.1.85+) where decorator is optional.
|
|
60
|
+
Defaults to True for backward compatibility with older servers.
|
|
61
|
+
|
|
56
62
|
Returns:
|
|
57
63
|
Bundled source code with all local dependencies inlined.
|
|
58
64
|
"""
|
|
@@ -62,6 +68,16 @@ class ToolBundler:
|
|
|
62
68
|
tree = ast.parse(full_source)
|
|
63
69
|
local_imports, external_imports = self._import_resolver.categorize_imports(tree)
|
|
64
70
|
|
|
71
|
+
# NOTE: The @tool_plugin decorator is REQUIRED by older servers (< 0.1.85) for remote execution.
|
|
72
|
+
# Newer servers (0.1.85+) make the decorator optional.
|
|
73
|
+
# The server validates uploaded tool code and will reject tools without the decorator
|
|
74
|
+
# with error: "No classes found with @tool_plugin decorator".
|
|
75
|
+
# See: docs/resources/reference/schemas/tools.md - "Plugin Requirements"
|
|
76
|
+
# TESTED: Commenting out this decorator addition causes HTTP 400 ValidationError from older servers.
|
|
77
|
+
# We try without decorator first (for new servers), then retry with decorator if validation fails.
|
|
78
|
+
if add_tool_plugin_decorator:
|
|
79
|
+
self._add_tool_plugin_decorator(tree)
|
|
80
|
+
|
|
65
81
|
# Extract main code nodes (excluding imports, docstrings, glaip_sdk.Tool subclasses)
|
|
66
82
|
main_code_nodes = self._extract_main_code_nodes(tree)
|
|
67
83
|
|
|
@@ -71,6 +87,13 @@ class ToolBundler:
|
|
|
71
87
|
# Merge all external imports
|
|
72
88
|
all_external_imports = external_imports + inlined_external_imports
|
|
73
89
|
|
|
90
|
+
# NOTE: The gllm_plugin.tools import is REQUIRED when decorator is added.
|
|
91
|
+
# Without this import, the decorator will cause a NameError when the server executes the code.
|
|
92
|
+
# TESTED: Commenting out this import causes NameError when server tries to use the decorator.
|
|
93
|
+
# This import is added automatically during bundling so source files can remain clean.
|
|
94
|
+
if add_tool_plugin_decorator:
|
|
95
|
+
self._ensure_tool_plugin_import(all_external_imports)
|
|
96
|
+
|
|
74
97
|
# Build bundled code
|
|
75
98
|
bundled_code = ["# Bundled tool with inlined local imports\n"]
|
|
76
99
|
bundled_code.extend(self._import_resolver.format_external_imports(all_external_imports))
|
|
@@ -109,6 +132,103 @@ class ToolBundler:
|
|
|
109
132
|
main_code_nodes.append(ast.unparse(node))
|
|
110
133
|
return main_code_nodes
|
|
111
134
|
|
|
135
|
+
@staticmethod
|
|
136
|
+
def _add_tool_plugin_decorator(tree: ast.AST) -> None:
|
|
137
|
+
"""Add @tool_plugin decorator to BaseTool classes that don't have it.
|
|
138
|
+
|
|
139
|
+
This allows tools to be clean (without decorator) for local use,
|
|
140
|
+
while the decorator is automatically added during bundling for remote execution.
|
|
141
|
+
|
|
142
|
+
Args:
|
|
143
|
+
tree: AST tree to modify in-place.
|
|
144
|
+
"""
|
|
145
|
+
for node in ast.walk(tree):
|
|
146
|
+
if not isinstance(node, ast.ClassDef):
|
|
147
|
+
continue
|
|
148
|
+
|
|
149
|
+
if not ToolBundler._inherits_from_base_tool(node):
|
|
150
|
+
continue
|
|
151
|
+
|
|
152
|
+
if ToolBundler._has_tool_plugin_decorator(node):
|
|
153
|
+
continue
|
|
154
|
+
|
|
155
|
+
decorator_call = ToolBundler._create_tool_plugin_decorator()
|
|
156
|
+
node.decorator_list.insert(0, decorator_call)
|
|
157
|
+
|
|
158
|
+
@staticmethod
|
|
159
|
+
def _inherits_from_base_tool(class_node: ast.ClassDef) -> bool:
|
|
160
|
+
"""Check if a class inherits from BaseTool.
|
|
161
|
+
|
|
162
|
+
Args:
|
|
163
|
+
class_node: AST ClassDef node to check.
|
|
164
|
+
|
|
165
|
+
Returns:
|
|
166
|
+
True if class inherits from BaseTool.
|
|
167
|
+
"""
|
|
168
|
+
for base in class_node.bases:
|
|
169
|
+
if isinstance(base, ast.Name) and base.id == "BaseTool":
|
|
170
|
+
return True
|
|
171
|
+
if isinstance(base, ast.Attribute) and base.attr == "BaseTool":
|
|
172
|
+
# Handle nested attributes like langchain_core.tools.BaseTool
|
|
173
|
+
# Check if the value chain leads to langchain_core
|
|
174
|
+
value = base.value
|
|
175
|
+
while isinstance(value, ast.Attribute):
|
|
176
|
+
value = value.value
|
|
177
|
+
if isinstance(value, ast.Name) and value.id == "langchain_core":
|
|
178
|
+
return True
|
|
179
|
+
return False
|
|
180
|
+
|
|
181
|
+
@staticmethod
|
|
182
|
+
def _has_tool_plugin_decorator(class_node: ast.ClassDef) -> bool:
|
|
183
|
+
"""Check if a class already has the @tool_plugin decorator.
|
|
184
|
+
|
|
185
|
+
Args:
|
|
186
|
+
class_node: AST ClassDef node to check.
|
|
187
|
+
|
|
188
|
+
Returns:
|
|
189
|
+
True if decorator already exists.
|
|
190
|
+
"""
|
|
191
|
+
for decorator in class_node.decorator_list:
|
|
192
|
+
if is_tool_plugin_decorator(decorator):
|
|
193
|
+
return True
|
|
194
|
+
return False
|
|
195
|
+
|
|
196
|
+
@staticmethod
|
|
197
|
+
def _create_tool_plugin_decorator() -> ast.Call:
|
|
198
|
+
"""Create a @tool_plugin decorator AST node.
|
|
199
|
+
|
|
200
|
+
Returns:
|
|
201
|
+
AST Call node representing @tool_plugin(version="1.0.0").
|
|
202
|
+
"""
|
|
203
|
+
return ast.Call(
|
|
204
|
+
func=ast.Name(id="tool_plugin", ctx=ast.Load()),
|
|
205
|
+
args=[],
|
|
206
|
+
keywords=[ast.keyword(arg="version", value=ast.Constant(value="1.0.0"))],
|
|
207
|
+
)
|
|
208
|
+
|
|
209
|
+
@staticmethod
|
|
210
|
+
def _ensure_tool_plugin_import(external_imports: list) -> None:
|
|
211
|
+
"""Ensure gllm_plugin.tools import is present in external imports.
|
|
212
|
+
|
|
213
|
+
Args:
|
|
214
|
+
external_imports: List of external import nodes (modified in-place).
|
|
215
|
+
"""
|
|
216
|
+
# Check if import already exists
|
|
217
|
+
for import_node in external_imports:
|
|
218
|
+
if isinstance(import_node, ast.ImportFrom) and import_node.module == "gllm_plugin.tools":
|
|
219
|
+
# Check if tool_plugin is in the names
|
|
220
|
+
for alias in import_node.names:
|
|
221
|
+
if alias.name == "tool_plugin":
|
|
222
|
+
return # Import already present
|
|
223
|
+
|
|
224
|
+
# Add the import
|
|
225
|
+
import_node = ast.ImportFrom(
|
|
226
|
+
module="gllm_plugin.tools",
|
|
227
|
+
names=[ast.alias(name="tool_plugin")],
|
|
228
|
+
level=0,
|
|
229
|
+
)
|
|
230
|
+
external_imports.append(import_node)
|
|
231
|
+
|
|
112
232
|
@staticmethod
|
|
113
233
|
def _is_sdk_tool_subclass(node: ast.ClassDef) -> bool:
|
|
114
234
|
"""Check if AST class definition inherits from Tool.
|
|
@@ -135,7 +255,7 @@ class ToolBundler:
|
|
|
135
255
|
return False
|
|
136
256
|
|
|
137
257
|
@classmethod
|
|
138
|
-
def bundle_from_source(cls, file_path: Path) -> tuple[str, str, str]:
|
|
258
|
+
def bundle_from_source(cls, file_path: Path, add_tool_plugin_decorator: bool = True) -> tuple[str, str, str]:
|
|
139
259
|
"""Extract tool info directly from source file without importing.
|
|
140
260
|
|
|
141
261
|
This is used as a fallback when the tool class cannot be imported
|
|
@@ -143,6 +263,9 @@ class ToolBundler:
|
|
|
143
263
|
|
|
144
264
|
Args:
|
|
145
265
|
file_path: Path to the tool source file.
|
|
266
|
+
add_tool_plugin_decorator: If True, add @tool_plugin decorator to BaseTool classes.
|
|
267
|
+
Set to False for newer servers (0.1.85+) where decorator is optional.
|
|
268
|
+
Defaults to True for backward compatibility with older servers.
|
|
146
269
|
|
|
147
270
|
Returns:
|
|
148
271
|
Tuple of (name, description, bundled_source_code).
|
|
@@ -160,6 +283,12 @@ class ToolBundler:
|
|
|
160
283
|
tool_dir = file_path.parent
|
|
161
284
|
import_resolver = ImportResolver(tool_dir)
|
|
162
285
|
|
|
286
|
+
# NOTE: The @tool_plugin decorator is REQUIRED by older servers (< 0.1.85) for remote execution.
|
|
287
|
+
# Newer servers (0.1.85+) make the decorator optional.
|
|
288
|
+
# See bundle() method for detailed explanation.
|
|
289
|
+
if add_tool_plugin_decorator:
|
|
290
|
+
cls._add_tool_plugin_decorator(tree)
|
|
291
|
+
|
|
163
292
|
# Find tool name and description from class definitions
|
|
164
293
|
tool_name, tool_description = cls._extract_tool_metadata(tree, file_path.stem)
|
|
165
294
|
|
|
@@ -180,6 +309,13 @@ class ToolBundler:
|
|
|
180
309
|
|
|
181
310
|
# Build bundled code
|
|
182
311
|
all_external_imports = external_imports + inlined_external_imports
|
|
312
|
+
|
|
313
|
+
# NOTE: The gllm_plugin.tools import is REQUIRED when decorator is added.
|
|
314
|
+
# See bundle() method for detailed explanation.
|
|
315
|
+
# TESTED: Commenting out this import causes NameError when server tries to use the decorator.
|
|
316
|
+
if add_tool_plugin_decorator:
|
|
317
|
+
cls._ensure_tool_plugin_import(all_external_imports)
|
|
318
|
+
|
|
183
319
|
bundled_code = ["# Bundled tool with inlined local imports\n"]
|
|
184
320
|
bundled_code.extend(import_resolver.format_external_imports(all_external_imports))
|
|
185
321
|
|
|
@@ -13,6 +13,8 @@ import ast
|
|
|
13
13
|
import importlib
|
|
14
14
|
from pathlib import Path
|
|
15
15
|
|
|
16
|
+
from glaip_sdk.utils.tool_detection import is_tool_plugin_decorator
|
|
17
|
+
|
|
16
18
|
|
|
17
19
|
class ImportResolver:
|
|
18
20
|
"""Resolves and categorizes Python imports for tool bundling.
|
|
@@ -482,15 +484,7 @@ class ImportResolver:
|
|
|
482
484
|
Returns:
|
|
483
485
|
True if decorator is @tool_plugin.
|
|
484
486
|
"""
|
|
485
|
-
|
|
486
|
-
return True
|
|
487
|
-
if (
|
|
488
|
-
isinstance(decorator, ast.Call)
|
|
489
|
-
and isinstance(decorator.func, ast.Name)
|
|
490
|
-
and decorator.func.id == "tool_plugin"
|
|
491
|
-
):
|
|
492
|
-
return True
|
|
493
|
-
return False
|
|
487
|
+
return is_tool_plugin_decorator(decorator)
|
|
494
488
|
|
|
495
489
|
@staticmethod
|
|
496
490
|
def _filter_bases(bases: list) -> list:
|
glaip_sdk/utils/sync.py
CHANGED
|
@@ -15,6 +15,7 @@ from __future__ import annotations
|
|
|
15
15
|
|
|
16
16
|
from typing import TYPE_CHECKING, Any
|
|
17
17
|
|
|
18
|
+
from glaip_sdk.exceptions import ValidationError
|
|
18
19
|
from glaip_sdk.utils.bundler import ToolBundler
|
|
19
20
|
from glaip_sdk.utils.import_resolver import load_class
|
|
20
21
|
from gllm_core.utils import LoggerManager
|
|
@@ -94,19 +95,38 @@ def update_or_create_tool(tool_ref: Any) -> Tool:
|
|
|
94
95
|
tool_name = _extract_tool_name(tool_class)
|
|
95
96
|
tool_description = _extract_tool_description(tool_class)
|
|
96
97
|
|
|
97
|
-
# Bundle source code
|
|
98
|
+
# Bundle source code - try without decorator first (for newer servers 0.1.85+)
|
|
99
|
+
# If validation fails, retry with decorator for older servers (< 0.1.85)
|
|
98
100
|
bundler = ToolBundler(tool_class)
|
|
99
|
-
bundled_source = bundler.bundle()
|
|
100
101
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
102
|
+
try:
|
|
103
|
+
# Try without decorator first (for newer servers where it's optional)
|
|
104
|
+
bundled_source = bundler.bundle(add_tool_plugin_decorator=False)
|
|
105
|
+
logger.info("Tool info: name='%s', description='%s...'", tool_name, tool_description[:50])
|
|
106
|
+
logger.info("Bundled source code (without decorator): %d characters", len(bundled_source))
|
|
107
|
+
|
|
108
|
+
# Attempt upload without decorator
|
|
109
|
+
return client.tools.upsert_tool(
|
|
110
|
+
tool_name,
|
|
111
|
+
code=bundled_source,
|
|
112
|
+
description=tool_description,
|
|
113
|
+
)
|
|
114
|
+
except ValidationError as e:
|
|
115
|
+
# Check if error is about missing @tool_plugin decorator
|
|
116
|
+
error_message = str(e).lower()
|
|
117
|
+
if "@tool_plugin decorator" in error_message or "no classes found" in error_message:
|
|
118
|
+
# Retry with decorator for older servers (< 0.1.85)
|
|
119
|
+
logger.info("Server requires @tool_plugin decorator, retrying with decorator added")
|
|
120
|
+
bundled_source = bundler.bundle(add_tool_plugin_decorator=True)
|
|
121
|
+
logger.info("Bundled source code (with decorator): %d characters", len(bundled_source))
|
|
122
|
+
|
|
123
|
+
return client.tools.upsert_tool(
|
|
124
|
+
tool_name,
|
|
125
|
+
code=bundled_source,
|
|
126
|
+
description=tool_description,
|
|
127
|
+
)
|
|
128
|
+
# Re-raise if it's a different validation error
|
|
129
|
+
raise
|
|
110
130
|
|
|
111
131
|
|
|
112
132
|
def update_or_create_agent(agent_config: dict[str, Any]) -> Agent:
|
|
@@ -4,6 +4,7 @@ Authors:
|
|
|
4
4
|
Christian Trisno Sen Long Chen (christian.t.s.l.chen@gdplabs.id)
|
|
5
5
|
"""
|
|
6
6
|
|
|
7
|
+
import ast
|
|
7
8
|
from typing import Any
|
|
8
9
|
|
|
9
10
|
|
|
@@ -31,3 +32,23 @@ def is_langchain_tool(ref: Any) -> bool:
|
|
|
31
32
|
pass
|
|
32
33
|
|
|
33
34
|
return False
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def is_tool_plugin_decorator(decorator: ast.expr) -> bool:
|
|
38
|
+
"""Check if an AST decorator node is @tool_plugin.
|
|
39
|
+
|
|
40
|
+
Shared by:
|
|
41
|
+
- ToolBundler._has_tool_plugin_decorator() (for bundling)
|
|
42
|
+
- ImportResolver._is_tool_plugin_decorator() (for import resolution)
|
|
43
|
+
|
|
44
|
+
Args:
|
|
45
|
+
decorator: AST decorator expression node to check.
|
|
46
|
+
|
|
47
|
+
Returns:
|
|
48
|
+
True if decorator is @tool_plugin.
|
|
49
|
+
"""
|
|
50
|
+
if isinstance(decorator, ast.Name) and decorator.id == "tool_plugin":
|
|
51
|
+
return True
|
|
52
|
+
if isinstance(decorator, ast.Call) and isinstance(decorator.func, ast.Name) and decorator.func.id == "tool_plugin":
|
|
53
|
+
return True
|
|
54
|
+
return False
|
|
@@ -5,7 +5,7 @@ glaip_sdk/exceptions.py,sha256=iAChFClkytXRBLP0vZq1_YjoZxA9i4m4bW1gDLiGR1g,2321
|
|
|
5
5
|
glaip_sdk/icons.py,sha256=J5THz0ReAmDwIiIooh1_G3Le-mwTJyEjhJDdJ13KRxM,524
|
|
6
6
|
glaip_sdk/rich_components.py,sha256=44Z0V1ZQleVh9gUDGwRR5mriiYFnVGOhm7fFxZYbP8c,4052
|
|
7
7
|
glaip_sdk/agents/__init__.py,sha256=VfYov56edbWuySXFEbWJ_jLXgwnFzPk1KB-9-mfsUCc,776
|
|
8
|
-
glaip_sdk/agents/base.py,sha256=
|
|
8
|
+
glaip_sdk/agents/base.py,sha256=GQnzCw2cqlrbxwdoWFfhBcBlEDgubY4tlD6gr1b3zps,44539
|
|
9
9
|
glaip_sdk/cli/__init__.py,sha256=xCCfuF1Yc7mpCDcfhHZTX0vizvtrDSLeT8MJ3V7m5A0,156
|
|
10
10
|
glaip_sdk/cli/account_store.py,sha256=TK4iTV93Q1uD9mCY_2ZMT6EazHKU2jX0qhgWfEM4V-4,18459
|
|
11
11
|
glaip_sdk/cli/agent_config.py,sha256=YAbFKrTNTRqNA6b0i0Q3pH-01rhHDRi5v8dxSFwGSwM,2401
|
|
@@ -14,9 +14,10 @@ glaip_sdk/cli/config.py,sha256=s0_xBB1e5YE4I_Wc4q-ayY3dwsBU1JrHAF-8ySlim7Y,3040
|
|
|
14
14
|
glaip_sdk/cli/constants.py,sha256=zqcVtzfj6huW97gbCmhkFqntge1H-c1vnkGqTazADgU,895
|
|
15
15
|
glaip_sdk/cli/context.py,sha256=--Y5vc6lgoAV7cRoUAr9UxSQaLmkMg29FolA7EwoRqM,3803
|
|
16
16
|
glaip_sdk/cli/display.py,sha256=ojgWdGeD5KUnGOmWNqqK4JP-1EaWHWX--DWze3BmIz0,12137
|
|
17
|
+
glaip_sdk/cli/entrypoint.py,sha256=ODrNZT1c7mFtNuXn4CrJgs06-xIhrqUMi1rKzkYJ21c,516
|
|
17
18
|
glaip_sdk/cli/hints.py,sha256=ca4krG103IS43s5BSLr0-N7uRMpte1_LY4nAXVvgDxo,1596
|
|
18
19
|
glaip_sdk/cli/io.py,sha256=ChP6CRKbtuENsNomNEaMDfPDU0iqO-WuVvl4_y7F2io,3871
|
|
19
|
-
glaip_sdk/cli/main.py,sha256=
|
|
20
|
+
glaip_sdk/cli/main.py,sha256=bi_SBrRWWMcdbl28zbNMrzp8i5SKCKTb2CWN-hLIx94,24680
|
|
20
21
|
glaip_sdk/cli/masking.py,sha256=2lrXQ-pfL7N-vNEQRT1s4Xq3JPDPDT8RC61OdaTtkkc,4060
|
|
21
22
|
glaip_sdk/cli/mcp_validators.py,sha256=cwbz7p_p7_9xVuuF96OBQOdmEgo5UObU6iWWQ2X03PI,10047
|
|
22
23
|
glaip_sdk/cli/pager.py,sha256=TmiMDNpUMuZju7QJ6A_ITqIoEf8Dhv8U6mTXx2Fga1k,7935
|
|
@@ -116,9 +117,10 @@ glaip_sdk/client/payloads/agent/__init__.py,sha256=gItEH2zt2secVq6n60oGA-ztdE5mc
|
|
|
116
117
|
glaip_sdk/client/payloads/agent/requests.py,sha256=5FuGEuypaEXlWBhB07JrDca_ecLg4bvo8mjyFBxAV9U,17139
|
|
117
118
|
glaip_sdk/client/payloads/agent/responses.py,sha256=1eRMI4JAIGqTB5zY_7D9ILQDRHPXR06U7JqHSmRp3Qs,1243
|
|
118
119
|
glaip_sdk/config/constants.py,sha256=Y03c6op0e7K0jTQ8bmWXhWAqsnjWxkAhWniq8Z0iEKY,1081
|
|
119
|
-
glaip_sdk/hitl/__init__.py,sha256=
|
|
120
|
+
glaip_sdk/hitl/__init__.py,sha256=hi_SwW1oBimNnSFPo9Yc-mZWVPzpytlnDWNq2h1_fPo,1572
|
|
120
121
|
glaip_sdk/hitl/base.py,sha256=EUN2igzydlYZ6_qmHU46Gyk3Bk9uyalZkCJ06XMRKJ8,1484
|
|
121
|
-
glaip_sdk/hitl/
|
|
122
|
+
glaip_sdk/hitl/callback.py,sha256=icKxxa_f8lxFQuXrZVoTt6baWivFL4a4YioWG_U_8k8,1336
|
|
123
|
+
glaip_sdk/hitl/local.py,sha256=7Qf-O62YcVXpOHdckm1-g4wwvHQCvwg4D1ikK-xwgqA,4642
|
|
122
124
|
glaip_sdk/hitl/remote.py,sha256=cdO-wWwRGdyb0HYNMwIvHfvKwOqhqp-l7efnaC9b85M,18914
|
|
123
125
|
glaip_sdk/mcps/__init__.py,sha256=4jYrt8K__oxrxexHRcmnRBXt-W_tbJN61H9Kf2lVh4Q,551
|
|
124
126
|
glaip_sdk/mcps/base.py,sha256=jWwHjDF67_mtDGRp9p5SolANjVeB8jt1PSwPBtX876M,11654
|
|
@@ -136,10 +138,11 @@ glaip_sdk/registry/agent.py,sha256=F0axW4BIUODqnttIOzxnoS5AqQkLZ1i48FTeZNnYkhA,5
|
|
|
136
138
|
glaip_sdk/registry/base.py,sha256=0x2ZBhiERGUcf9mQeWlksSYs5TxDG6FxBYQToYZa5D4,4143
|
|
137
139
|
glaip_sdk/registry/mcp.py,sha256=kNJmiijIbZL9Btx5o2tFtbaT-WG6O4Xf_nl3wz356Ow,7978
|
|
138
140
|
glaip_sdk/registry/tool.py,sha256=QnbAlk09lYvEb9PEdCsvpg4CGxlLbvvFWBS8WkM1ZoM,12955
|
|
139
|
-
glaip_sdk/runner/__init__.py,sha256=
|
|
141
|
+
glaip_sdk/runner/__init__.py,sha256=orJ3nLR9P-n1qMaAMWZ_xRS4368YnDpdltg-bX5BlUk,2210
|
|
140
142
|
glaip_sdk/runner/base.py,sha256=KIjcSAyDCP9_mn2H4rXR5gu1FZlwD9pe0gkTBmr6Yi4,2663
|
|
141
143
|
glaip_sdk/runner/deps.py,sha256=Du3hr2R5RHOYCRAv7RVmx661x-ayVXIeZ8JD7ODirTA,3884
|
|
142
|
-
glaip_sdk/runner/langgraph.py,sha256
|
|
144
|
+
glaip_sdk/runner/langgraph.py,sha256=HWzEkmkQqvAOKat3lENVf0zDaypj7HMeny5thDyprWY,33031
|
|
145
|
+
glaip_sdk/runner/logging_config.py,sha256=OrQgW23t42qQRqEXKH8U4bFg4JG5EEkUJTlbvtU65iE,2528
|
|
143
146
|
glaip_sdk/runner/mcp_adapter/__init__.py,sha256=Rdttfg3N6kg3-DaTCKqaGXKByZyBt0Mwf6FV8s_5kI8,462
|
|
144
147
|
glaip_sdk/runner/mcp_adapter/base_mcp_adapter.py,sha256=ic56fKgb3zgVZZQm3ClWUZi7pE1t4EVq8mOg6AM6hdA,1374
|
|
145
148
|
glaip_sdk/runner/mcp_adapter/langchain_mcp_adapter.py,sha256=b58GuadPz7q7aXoJyTYs0eeJ_oqp-wLR1tcr_5cbV1s,9723
|
|
@@ -153,7 +156,7 @@ glaip_sdk/tools/__init__.py,sha256=rhGzEqQFCzeMrxmikBuNrMz4PyYczwic28boDKVmoHs,5
|
|
|
153
156
|
glaip_sdk/tools/base.py,sha256=hkz2NZFHW1PqsRiXh3kKTVLIjMPR274Uwml944vH5tg,16325
|
|
154
157
|
glaip_sdk/utils/__init__.py,sha256=ntohV7cxlY2Yksi2nFuFm_Mg2XVJbBbSJVRej7Mi9YE,2770
|
|
155
158
|
glaip_sdk/utils/agent_config.py,sha256=RhcHsSOVwOaSC2ggnPuHn36Aa0keGJhs8KGb2InvzRk,7262
|
|
156
|
-
glaip_sdk/utils/bundler.py,sha256=
|
|
159
|
+
glaip_sdk/utils/bundler.py,sha256=fLumFj1MqqqGA1Mwn05v_cEKPALv3rIPEMvaURpxZ80,15171
|
|
157
160
|
glaip_sdk/utils/client.py,sha256=otPUOIDvLCCsvFBNR8YMZFtRrORggmvvlFjl3YeeTqQ,3121
|
|
158
161
|
glaip_sdk/utils/client_utils.py,sha256=hzHxxNuM37mK4HhgIdS0qg4AqjAA5ai2irPO6Nr1Uzo,15350
|
|
159
162
|
glaip_sdk/utils/datetime_helpers.py,sha256=QLknNLEAY56628-MTRKnCXAffATkF33erOqBubKmU98,1544
|
|
@@ -162,14 +165,14 @@ glaip_sdk/utils/display.py,sha256=zu3SYqxj9hPyEN8G1vIXv_yXBkV8jLLCXEg2rs8NlzM,44
|
|
|
162
165
|
glaip_sdk/utils/export.py,sha256=1NxxE3wGsA1auzecG5oJw5ELB4VmPljoeIkGhrGOh1I,5006
|
|
163
166
|
glaip_sdk/utils/general.py,sha256=3HSVIopUsIymPaim-kP2lqLX75TkkdIVLe6g3UKabZ0,1507
|
|
164
167
|
glaip_sdk/utils/import_export.py,sha256=RCvoydm_6_L7_J1igcE6IYDunqgS5mQUbWT4VGrytMw,5510
|
|
165
|
-
glaip_sdk/utils/import_resolver.py,sha256=
|
|
168
|
+
glaip_sdk/utils/import_resolver.py,sha256=X2qUV4_XmwStccGjnQ0YcxXAFyxZzwaKpfxjAW4Ev2o,17159
|
|
166
169
|
glaip_sdk/utils/instructions.py,sha256=MTk93lsq3I8aRnvnRMSXXNMzcpnaIM_Pm3Aiiiq3GBc,2997
|
|
167
170
|
glaip_sdk/utils/resource_refs.py,sha256=vF34kyAtFBLnaKnQVrsr2st1JiSxVbIZ4yq0DelJvCI,5966
|
|
168
171
|
glaip_sdk/utils/run_renderer.py,sha256=d_VMI6LbvHPUUeRmGqh5wK_lHqDEIAcym2iqpbtDad0,1365
|
|
169
172
|
glaip_sdk/utils/runtime_config.py,sha256=Gl9-CQ4lYZ39vRSgtdfcSU3CXshVDDuTOdSzjvsCgG0,14070
|
|
170
173
|
glaip_sdk/utils/serialization.py,sha256=z-qpvWLSBrGK3wbUclcA1UIKLXJedTnMSwPdq-FF4lo,13308
|
|
171
|
-
glaip_sdk/utils/sync.py,sha256=
|
|
172
|
-
glaip_sdk/utils/tool_detection.py,sha256=
|
|
174
|
+
glaip_sdk/utils/sync.py,sha256=71egWp5qm_8tYpWZyGazvnP4NnyW16rcmzjGVicmQEE,6043
|
|
175
|
+
glaip_sdk/utils/tool_detection.py,sha256=6dHp0naLnvY6jwy_38k4kyTgQnizgcsq9hpeLSjAmcc,1471
|
|
173
176
|
glaip_sdk/utils/tool_storage_provider.py,sha256=lampwUeWu4Uy8nBG7C4ZT-M6AHoWZS0m67HdLx21VDg,5396
|
|
174
177
|
glaip_sdk/utils/validation.py,sha256=hB_k3lvHdIFUiSwHStrC0Eqnhx0OG2UvwqASeem0HuQ,6859
|
|
175
178
|
glaip_sdk/utils/a2a/__init__.py,sha256=_X8AvDOsHeppo5n7rP5TeisVxlAdkZDTFReBk_9lmxo,876
|
|
@@ -203,8 +206,8 @@ glaip_sdk/utils/rendering/steps/format.py,sha256=Chnq7OBaj8XMeBntSBxrX5zSmrYeGcO
|
|
|
203
206
|
glaip_sdk/utils/rendering/steps/manager.py,sha256=BiBmTeQMQhjRMykgICXsXNYh1hGsss-fH9BIGVMWFi0,13194
|
|
204
207
|
glaip_sdk/utils/rendering/viewer/__init__.py,sha256=XrxmE2cMAozqrzo1jtDFm8HqNtvDcYi2mAhXLXn5CjI,457
|
|
205
208
|
glaip_sdk/utils/rendering/viewer/presenter.py,sha256=mlLMTjnyeyPVtsyrAbz1BJu9lFGQSlS-voZ-_Cuugv0,5725
|
|
206
|
-
glaip_sdk-0.7.
|
|
207
|
-
glaip_sdk-0.7.
|
|
208
|
-
glaip_sdk-0.7.
|
|
209
|
-
glaip_sdk-0.7.
|
|
210
|
-
glaip_sdk-0.7.
|
|
209
|
+
glaip_sdk-0.7.4.dist-info/METADATA,sha256=r36rVJdxsiV-fUHo3SRNf_pakOeHayQy1KyL3ZCqN-M,8365
|
|
210
|
+
glaip_sdk-0.7.4.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
211
|
+
glaip_sdk-0.7.4.dist-info/entry_points.txt,sha256=NkhO6FfgX9Zrjn63GuKphf-dLw7KNJvucAcXc7P3aMk,54
|
|
212
|
+
glaip_sdk-0.7.4.dist-info/top_level.txt,sha256=td7yXttiYX2s94-4wFhv-5KdT0rSZ-pnJRSire341hw,10
|
|
213
|
+
glaip_sdk-0.7.4.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|