glaip-sdk 0.1.2__py3-none-any.whl → 0.7.17__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/__init__.py +44 -4
- glaip_sdk/_version.py +9 -0
- glaip_sdk/agents/__init__.py +27 -0
- glaip_sdk/agents/base.py +1413 -0
- glaip_sdk/branding.py +126 -2
- glaip_sdk/cli/account_store.py +555 -0
- glaip_sdk/cli/auth.py +260 -15
- glaip_sdk/cli/commands/__init__.py +2 -2
- glaip_sdk/cli/commands/accounts.py +746 -0
- glaip_sdk/cli/commands/agents/__init__.py +116 -0
- glaip_sdk/cli/commands/agents/_common.py +562 -0
- glaip_sdk/cli/commands/agents/create.py +155 -0
- glaip_sdk/cli/commands/agents/delete.py +64 -0
- glaip_sdk/cli/commands/agents/get.py +89 -0
- glaip_sdk/cli/commands/agents/list.py +129 -0
- glaip_sdk/cli/commands/agents/run.py +264 -0
- glaip_sdk/cli/commands/agents/sync_langflow.py +72 -0
- glaip_sdk/cli/commands/agents/update.py +112 -0
- glaip_sdk/cli/commands/common_config.py +104 -0
- glaip_sdk/cli/commands/configure.py +728 -113
- glaip_sdk/cli/commands/mcps/__init__.py +94 -0
- glaip_sdk/cli/commands/mcps/_common.py +459 -0
- glaip_sdk/cli/commands/mcps/connect.py +82 -0
- glaip_sdk/cli/commands/mcps/create.py +152 -0
- glaip_sdk/cli/commands/mcps/delete.py +73 -0
- glaip_sdk/cli/commands/mcps/get.py +212 -0
- glaip_sdk/cli/commands/mcps/list.py +69 -0
- glaip_sdk/cli/commands/mcps/tools.py +235 -0
- glaip_sdk/cli/commands/mcps/update.py +190 -0
- glaip_sdk/cli/commands/models.py +12 -8
- glaip_sdk/cli/commands/shared/__init__.py +21 -0
- glaip_sdk/cli/commands/shared/formatters.py +91 -0
- glaip_sdk/cli/commands/tools/__init__.py +69 -0
- glaip_sdk/cli/commands/tools/_common.py +80 -0
- glaip_sdk/cli/commands/tools/create.py +228 -0
- glaip_sdk/cli/commands/tools/delete.py +61 -0
- glaip_sdk/cli/commands/tools/get.py +103 -0
- glaip_sdk/cli/commands/tools/list.py +69 -0
- glaip_sdk/cli/commands/tools/script.py +49 -0
- glaip_sdk/cli/commands/tools/update.py +102 -0
- glaip_sdk/cli/commands/transcripts/__init__.py +90 -0
- glaip_sdk/cli/commands/transcripts/_common.py +9 -0
- glaip_sdk/cli/commands/transcripts/clear.py +5 -0
- glaip_sdk/cli/commands/transcripts/detail.py +5 -0
- glaip_sdk/cli/commands/transcripts_original.py +756 -0
- glaip_sdk/cli/commands/update.py +163 -17
- glaip_sdk/cli/config.py +49 -4
- glaip_sdk/cli/constants.py +38 -0
- glaip_sdk/cli/context.py +8 -0
- glaip_sdk/cli/core/__init__.py +79 -0
- glaip_sdk/cli/core/context.py +124 -0
- glaip_sdk/cli/core/output.py +851 -0
- glaip_sdk/cli/core/prompting.py +649 -0
- glaip_sdk/cli/core/rendering.py +187 -0
- glaip_sdk/cli/display.py +41 -20
- glaip_sdk/cli/entrypoint.py +20 -0
- glaip_sdk/cli/hints.py +57 -0
- glaip_sdk/cli/io.py +6 -3
- glaip_sdk/cli/main.py +340 -143
- glaip_sdk/cli/masking.py +21 -33
- glaip_sdk/cli/pager.py +12 -13
- glaip_sdk/cli/parsers/__init__.py +1 -3
- glaip_sdk/cli/resolution.py +2 -1
- glaip_sdk/cli/slash/__init__.py +0 -9
- glaip_sdk/cli/slash/accounts_controller.py +580 -0
- glaip_sdk/cli/slash/accounts_shared.py +75 -0
- glaip_sdk/cli/slash/agent_session.py +62 -21
- glaip_sdk/cli/slash/prompt.py +21 -0
- glaip_sdk/cli/slash/remote_runs_controller.py +568 -0
- glaip_sdk/cli/slash/session.py +1105 -153
- glaip_sdk/cli/slash/tui/__init__.py +36 -0
- glaip_sdk/cli/slash/tui/accounts.tcss +177 -0
- glaip_sdk/cli/slash/tui/accounts_app.py +1853 -0
- glaip_sdk/cli/slash/tui/background_tasks.py +72 -0
- glaip_sdk/cli/slash/tui/clipboard.py +195 -0
- glaip_sdk/cli/slash/tui/context.py +92 -0
- glaip_sdk/cli/slash/tui/indicators.py +341 -0
- glaip_sdk/cli/slash/tui/keybind_registry.py +235 -0
- glaip_sdk/cli/slash/tui/layouts/__init__.py +14 -0
- glaip_sdk/cli/slash/tui/layouts/harlequin.py +184 -0
- glaip_sdk/cli/slash/tui/loading.py +80 -0
- glaip_sdk/cli/slash/tui/remote_runs_app.py +760 -0
- glaip_sdk/cli/slash/tui/terminal.py +407 -0
- glaip_sdk/cli/slash/tui/theme/__init__.py +15 -0
- glaip_sdk/cli/slash/tui/theme/catalog.py +79 -0
- glaip_sdk/cli/slash/tui/theme/manager.py +112 -0
- glaip_sdk/cli/slash/tui/theme/tokens.py +55 -0
- glaip_sdk/cli/slash/tui/toast.py +388 -0
- glaip_sdk/cli/transcript/__init__.py +12 -52
- glaip_sdk/cli/transcript/cache.py +255 -44
- glaip_sdk/cli/transcript/capture.py +66 -1
- glaip_sdk/cli/transcript/history.py +815 -0
- glaip_sdk/cli/transcript/viewer.py +72 -463
- glaip_sdk/cli/tui_settings.py +125 -0
- glaip_sdk/cli/update_notifier.py +227 -10
- glaip_sdk/cli/validators.py +5 -6
- glaip_sdk/client/__init__.py +3 -1
- glaip_sdk/client/_schedule_payloads.py +89 -0
- glaip_sdk/client/agent_runs.py +147 -0
- glaip_sdk/client/agents.py +576 -44
- glaip_sdk/client/base.py +26 -0
- glaip_sdk/client/hitl.py +136 -0
- glaip_sdk/client/main.py +25 -14
- glaip_sdk/client/mcps.py +165 -24
- glaip_sdk/client/payloads/agent/__init__.py +23 -0
- glaip_sdk/client/{_agent_payloads.py → payloads/agent/requests.py} +63 -47
- glaip_sdk/client/payloads/agent/responses.py +43 -0
- glaip_sdk/client/run_rendering.py +546 -92
- glaip_sdk/client/schedules.py +439 -0
- glaip_sdk/client/shared.py +21 -0
- glaip_sdk/client/tools.py +206 -32
- glaip_sdk/config/constants.py +33 -2
- glaip_sdk/guardrails/__init__.py +80 -0
- glaip_sdk/guardrails/serializer.py +89 -0
- glaip_sdk/hitl/__init__.py +48 -0
- glaip_sdk/hitl/base.py +64 -0
- glaip_sdk/hitl/callback.py +43 -0
- glaip_sdk/hitl/local.py +121 -0
- glaip_sdk/hitl/remote.py +523 -0
- glaip_sdk/mcps/__init__.py +21 -0
- glaip_sdk/mcps/base.py +345 -0
- glaip_sdk/models/__init__.py +136 -0
- glaip_sdk/models/_provider_mappings.py +101 -0
- glaip_sdk/models/_validation.py +97 -0
- glaip_sdk/models/agent.py +48 -0
- glaip_sdk/models/agent_runs.py +117 -0
- glaip_sdk/models/common.py +42 -0
- glaip_sdk/models/constants.py +141 -0
- glaip_sdk/models/mcp.py +33 -0
- glaip_sdk/models/model.py +170 -0
- glaip_sdk/models/schedule.py +224 -0
- glaip_sdk/models/tool.py +33 -0
- glaip_sdk/payload_schemas/__init__.py +1 -13
- glaip_sdk/payload_schemas/agent.py +1 -0
- glaip_sdk/payload_schemas/guardrails.py +34 -0
- glaip_sdk/registry/__init__.py +55 -0
- glaip_sdk/registry/agent.py +164 -0
- glaip_sdk/registry/base.py +139 -0
- glaip_sdk/registry/mcp.py +253 -0
- glaip_sdk/registry/tool.py +445 -0
- glaip_sdk/rich_components.py +58 -2
- glaip_sdk/runner/__init__.py +76 -0
- glaip_sdk/runner/base.py +84 -0
- glaip_sdk/runner/deps.py +115 -0
- glaip_sdk/runner/langgraph.py +1055 -0
- glaip_sdk/runner/logging_config.py +77 -0
- glaip_sdk/runner/mcp_adapter/__init__.py +13 -0
- glaip_sdk/runner/mcp_adapter/base_mcp_adapter.py +43 -0
- glaip_sdk/runner/mcp_adapter/langchain_mcp_adapter.py +257 -0
- glaip_sdk/runner/mcp_adapter/mcp_config_builder.py +116 -0
- glaip_sdk/runner/tool_adapter/__init__.py +18 -0
- glaip_sdk/runner/tool_adapter/base_tool_adapter.py +44 -0
- glaip_sdk/runner/tool_adapter/langchain_tool_adapter.py +242 -0
- glaip_sdk/schedules/__init__.py +22 -0
- glaip_sdk/schedules/base.py +291 -0
- glaip_sdk/tools/__init__.py +22 -0
- glaip_sdk/tools/base.py +488 -0
- glaip_sdk/utils/__init__.py +59 -12
- glaip_sdk/utils/a2a/__init__.py +34 -0
- glaip_sdk/utils/a2a/event_processor.py +188 -0
- glaip_sdk/utils/agent_config.py +8 -2
- glaip_sdk/utils/bundler.py +403 -0
- glaip_sdk/utils/client.py +111 -0
- glaip_sdk/utils/client_utils.py +39 -7
- glaip_sdk/utils/datetime_helpers.py +58 -0
- glaip_sdk/utils/discovery.py +78 -0
- glaip_sdk/utils/display.py +23 -15
- glaip_sdk/utils/export.py +143 -0
- glaip_sdk/utils/general.py +0 -33
- glaip_sdk/utils/import_export.py +12 -7
- glaip_sdk/utils/import_resolver.py +524 -0
- glaip_sdk/utils/instructions.py +101 -0
- glaip_sdk/utils/rendering/__init__.py +115 -1
- glaip_sdk/utils/rendering/formatting.py +5 -30
- glaip_sdk/utils/rendering/layout/__init__.py +64 -0
- glaip_sdk/utils/rendering/{renderer → layout}/panels.py +9 -0
- glaip_sdk/utils/rendering/{renderer → layout}/progress.py +70 -1
- glaip_sdk/utils/rendering/layout/summary.py +74 -0
- glaip_sdk/utils/rendering/layout/transcript.py +606 -0
- glaip_sdk/utils/rendering/models.py +1 -0
- glaip_sdk/utils/rendering/renderer/__init__.py +9 -47
- glaip_sdk/utils/rendering/renderer/base.py +299 -1434
- glaip_sdk/utils/rendering/renderer/config.py +1 -5
- glaip_sdk/utils/rendering/renderer/debug.py +26 -20
- glaip_sdk/utils/rendering/renderer/factory.py +138 -0
- glaip_sdk/utils/rendering/renderer/stream.py +4 -33
- glaip_sdk/utils/rendering/renderer/summary_window.py +79 -0
- glaip_sdk/utils/rendering/renderer/thinking.py +273 -0
- glaip_sdk/utils/rendering/renderer/tool_panels.py +442 -0
- glaip_sdk/utils/rendering/renderer/transcript_mode.py +162 -0
- glaip_sdk/utils/rendering/state.py +204 -0
- glaip_sdk/utils/rendering/steps/__init__.py +34 -0
- glaip_sdk/utils/rendering/{steps.py → steps/event_processor.py} +53 -440
- glaip_sdk/utils/rendering/steps/format.py +176 -0
- glaip_sdk/utils/rendering/steps/manager.py +387 -0
- glaip_sdk/utils/rendering/timing.py +36 -0
- glaip_sdk/utils/rendering/viewer/__init__.py +21 -0
- glaip_sdk/utils/rendering/viewer/presenter.py +184 -0
- glaip_sdk/utils/resource_refs.py +25 -13
- glaip_sdk/utils/runtime_config.py +426 -0
- glaip_sdk/utils/serialization.py +18 -0
- glaip_sdk/utils/sync.py +162 -0
- glaip_sdk/utils/tool_detection.py +301 -0
- glaip_sdk/utils/tool_storage_provider.py +140 -0
- glaip_sdk/utils/validation.py +16 -24
- {glaip_sdk-0.1.2.dist-info → glaip_sdk-0.7.17.dist-info}/METADATA +69 -23
- glaip_sdk-0.7.17.dist-info/RECORD +224 -0
- {glaip_sdk-0.1.2.dist-info → glaip_sdk-0.7.17.dist-info}/WHEEL +2 -1
- glaip_sdk-0.7.17.dist-info/entry_points.txt +2 -0
- glaip_sdk-0.7.17.dist-info/top_level.txt +1 -0
- glaip_sdk/cli/commands/agents.py +0 -1369
- glaip_sdk/cli/commands/mcps.py +0 -1187
- glaip_sdk/cli/commands/tools.py +0 -584
- glaip_sdk/cli/utils.py +0 -1278
- glaip_sdk/models.py +0 -240
- glaip_sdk-0.1.2.dist-info/RECORD +0 -82
- glaip_sdk-0.1.2.dist-info/entry_points.txt +0 -3
glaip_sdk/mcps/base.py
ADDED
|
@@ -0,0 +1,345 @@
|
|
|
1
|
+
"""MCP (Model Context Protocol) helper for glaip_sdk.
|
|
2
|
+
|
|
3
|
+
Provides a simple, migration-ready way to declare and resolve MCPs with
|
|
4
|
+
in-memory caching and create-on-missing functionality.
|
|
5
|
+
|
|
6
|
+
The MCP class also supports runtime operations (update, delete, get_tools)
|
|
7
|
+
when retrieved from the API via client.mcps.get().
|
|
8
|
+
|
|
9
|
+
Authors:
|
|
10
|
+
Christian Trisno Sen Long Chen (christian.t.s.l.chen@gdplabs.id)
|
|
11
|
+
|
|
12
|
+
Example - Lazy Reference:
|
|
13
|
+
>>> from glaip_sdk.mcps import MCP
|
|
14
|
+
>>>
|
|
15
|
+
>>> # Create from known ID
|
|
16
|
+
>>> mcp = MCP.from_id("mcp_abc123")
|
|
17
|
+
>>>
|
|
18
|
+
>>> # Create lookup-only by name (error if not found)
|
|
19
|
+
>>> mcp = MCP.from_native("arxiv-search")
|
|
20
|
+
>>>
|
|
21
|
+
>>> # Create for lookup/creation by name (create if missing)
|
|
22
|
+
>>> mcp = MCP(name="my-filesystem-mcp", transport="sse", config={"url": "..."})
|
|
23
|
+
|
|
24
|
+
Example - Runtime Operations:
|
|
25
|
+
>>> from glaip_sdk import Glaip
|
|
26
|
+
>>>
|
|
27
|
+
>>> client = Glaip()
|
|
28
|
+
>>> mcp = client.mcps.get("mcp-123")
|
|
29
|
+
>>> tools = mcp.get_tools() # Get tools from MCP
|
|
30
|
+
>>> mcp.update(description="Updated description")
|
|
31
|
+
>>> mcp.delete()
|
|
32
|
+
"""
|
|
33
|
+
|
|
34
|
+
from __future__ import annotations
|
|
35
|
+
|
|
36
|
+
from typing import TYPE_CHECKING, Any
|
|
37
|
+
|
|
38
|
+
if TYPE_CHECKING:
|
|
39
|
+
from glaip_sdk.models import MCPResponse
|
|
40
|
+
|
|
41
|
+
# Type alias for MCP configuration values
|
|
42
|
+
MCPConfigValue = str | int | bool | list[str] | dict[str, str]
|
|
43
|
+
|
|
44
|
+
_MCP_NOT_DEPLOYED_MSG = "MCP not available on platform. No ID set."
|
|
45
|
+
_CLIENT_NOT_AVAILABLE_MSG = "Client not available. Use client.mcps.get() to get a client-connected MCP."
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
class MCP:
|
|
49
|
+
"""MCP reference helper for declaring MCPs in Agent definitions.
|
|
50
|
+
|
|
51
|
+
Supports both lazy references and runtime operations:
|
|
52
|
+
- Lazy reference: Created via from_native() or from_id()
|
|
53
|
+
- Runtime: Created via from_response() or client.mcps.get()
|
|
54
|
+
|
|
55
|
+
Attributes:
|
|
56
|
+
name: Human-readable MCP name (used for lookup/creation).
|
|
57
|
+
id: Backend MCP ID (used for direct fetch if known).
|
|
58
|
+
transport: Transport type (e.g., "sse", "stdio", "websocket").
|
|
59
|
+
config: Transport configuration dict (URLs, args, env vars).
|
|
60
|
+
description: Optional description for the MCP.
|
|
61
|
+
metadata: Optional additional metadata dict.
|
|
62
|
+
authentication: Authentication configuration.
|
|
63
|
+
|
|
64
|
+
Example - Lazy Reference:
|
|
65
|
+
>>> # Create from known ID
|
|
66
|
+
>>> mcp = MCP.from_id("mcp_abc123")
|
|
67
|
+
>>>
|
|
68
|
+
>>> # Create lookup-only by name (error if not found)
|
|
69
|
+
>>> mcp = MCP.from_native("arxiv-search")
|
|
70
|
+
>>>
|
|
71
|
+
>>> # Create for lookup/creation by name (create if missing)
|
|
72
|
+
>>> mcp = MCP(name="my-filesystem-mcp", transport="sse", config={"url": "..."})
|
|
73
|
+
|
|
74
|
+
Example - Runtime Operations:
|
|
75
|
+
>>> mcp = client.mcps.get("mcp-123")
|
|
76
|
+
>>> mcp.update(description="New description")
|
|
77
|
+
>>> mcp.delete()
|
|
78
|
+
"""
|
|
79
|
+
|
|
80
|
+
def __init__(
|
|
81
|
+
self,
|
|
82
|
+
name: str | None = None,
|
|
83
|
+
*,
|
|
84
|
+
id: str | None = None, # noqa: A002 - Allow shadowing builtin for API compat
|
|
85
|
+
transport: str | None = None,
|
|
86
|
+
config: dict[str, MCPConfigValue] | None = None,
|
|
87
|
+
description: str | None = None,
|
|
88
|
+
metadata: dict[str, Any] | None = None,
|
|
89
|
+
authentication: dict[str, Any] | None = None,
|
|
90
|
+
_lookup_only: bool = False,
|
|
91
|
+
_client: Any = None,
|
|
92
|
+
) -> None:
|
|
93
|
+
"""Initialize an MCP.
|
|
94
|
+
|
|
95
|
+
Args:
|
|
96
|
+
name: Human-readable MCP name.
|
|
97
|
+
id: Backend MCP ID.
|
|
98
|
+
transport: Transport type (e.g., "sse", "stdio").
|
|
99
|
+
config: Transport configuration dict.
|
|
100
|
+
description: Optional description.
|
|
101
|
+
metadata: Optional metadata dict.
|
|
102
|
+
authentication: Authentication configuration.
|
|
103
|
+
_lookup_only: If True, don't create if not found.
|
|
104
|
+
_client: Internal client reference.
|
|
105
|
+
|
|
106
|
+
Raises:
|
|
107
|
+
ValueError: If neither name nor id is provided.
|
|
108
|
+
"""
|
|
109
|
+
if not name and not id:
|
|
110
|
+
raise ValueError("At least one of 'name' or 'id' must be provided")
|
|
111
|
+
|
|
112
|
+
self.name = name
|
|
113
|
+
self._id = id
|
|
114
|
+
self.transport = transport
|
|
115
|
+
self.config = config
|
|
116
|
+
self.description = description
|
|
117
|
+
self.metadata = metadata
|
|
118
|
+
self.authentication = authentication
|
|
119
|
+
self._lookup_only = _lookup_only
|
|
120
|
+
self._client = _client
|
|
121
|
+
|
|
122
|
+
@property
|
|
123
|
+
def id(self) -> str | None: # noqa: A003 - Allow shadowing builtin for API compat
|
|
124
|
+
"""MCP ID on the platform."""
|
|
125
|
+
return self._id
|
|
126
|
+
|
|
127
|
+
@id.setter
|
|
128
|
+
def id(self, value: str | None) -> None: # noqa: A003
|
|
129
|
+
"""Set the MCP ID."""
|
|
130
|
+
self._id = value
|
|
131
|
+
|
|
132
|
+
def __repr__(self) -> str:
|
|
133
|
+
"""Return string representation."""
|
|
134
|
+
if self._id:
|
|
135
|
+
return f"MCP(id={self._id!r}, name={self.name!r})"
|
|
136
|
+
if self._lookup_only:
|
|
137
|
+
return f"MCP.from_native({self.name!r})"
|
|
138
|
+
return f"MCP(name={self.name!r})"
|
|
139
|
+
|
|
140
|
+
def __eq__(self, other: object) -> bool:
|
|
141
|
+
"""Check equality based on id if available, else name."""
|
|
142
|
+
if not isinstance(other, MCP):
|
|
143
|
+
return NotImplemented
|
|
144
|
+
if self._id and other._id:
|
|
145
|
+
return self._id == other._id
|
|
146
|
+
return self.name == other.name
|
|
147
|
+
|
|
148
|
+
def __hash__(self) -> int:
|
|
149
|
+
"""Hash based on id if available, else name."""
|
|
150
|
+
if self._id:
|
|
151
|
+
return hash(self._id)
|
|
152
|
+
return hash(self.name)
|
|
153
|
+
|
|
154
|
+
def model_dump(self, *, exclude_none: bool = False) -> dict[str, Any]:
|
|
155
|
+
"""Return a dict representation of the MCP.
|
|
156
|
+
|
|
157
|
+
Provides Pydantic-style serialization for backward compatibility.
|
|
158
|
+
|
|
159
|
+
Args:
|
|
160
|
+
exclude_none: If True, exclude None values from the output.
|
|
161
|
+
|
|
162
|
+
Returns:
|
|
163
|
+
Dictionary containing MCP attributes.
|
|
164
|
+
"""
|
|
165
|
+
data = {
|
|
166
|
+
"id": self._id,
|
|
167
|
+
"name": self.name,
|
|
168
|
+
"transport": self.transport,
|
|
169
|
+
"config": self.config,
|
|
170
|
+
"description": self.description,
|
|
171
|
+
"metadata": self.metadata,
|
|
172
|
+
"authentication": self.authentication,
|
|
173
|
+
}
|
|
174
|
+
if exclude_none:
|
|
175
|
+
return {k: v for k, v in data.items() if v is not None}
|
|
176
|
+
return data
|
|
177
|
+
|
|
178
|
+
@classmethod
|
|
179
|
+
def from_native(cls, name: str) -> MCP:
|
|
180
|
+
"""Create a lookup-only MCP reference by name.
|
|
181
|
+
|
|
182
|
+
Use this when referencing an MCP that already exists on the platform.
|
|
183
|
+
Resolution will NOT create the MCP if not found - it will raise an error.
|
|
184
|
+
|
|
185
|
+
Args:
|
|
186
|
+
name: The name of the existing MCP.
|
|
187
|
+
|
|
188
|
+
Returns:
|
|
189
|
+
MCP instance configured for lookup-only resolution.
|
|
190
|
+
|
|
191
|
+
Raises:
|
|
192
|
+
ValueError: If name is empty.
|
|
193
|
+
|
|
194
|
+
Example:
|
|
195
|
+
>>> mcp = MCP.from_native("arxiv-search")
|
|
196
|
+
>>> # Registry will find by name, error if not found or ambiguous
|
|
197
|
+
"""
|
|
198
|
+
if not name:
|
|
199
|
+
raise ValueError("Name cannot be empty")
|
|
200
|
+
return cls(name=name, _lookup_only=True)
|
|
201
|
+
|
|
202
|
+
@classmethod
|
|
203
|
+
def from_id(cls, mcp_id: str) -> MCP:
|
|
204
|
+
"""Create an MCP helper for lookup-only by ID.
|
|
205
|
+
|
|
206
|
+
This creates a minimal MCP reference that will be resolved
|
|
207
|
+
from the backend using the ID. Use this when you know the
|
|
208
|
+
backend MCP ID but don't have the full configuration.
|
|
209
|
+
|
|
210
|
+
Args:
|
|
211
|
+
mcp_id: The backend MCP ID.
|
|
212
|
+
|
|
213
|
+
Returns:
|
|
214
|
+
An MCP instance with only the ID set, marked for lookup-only.
|
|
215
|
+
|
|
216
|
+
Raises:
|
|
217
|
+
ValueError: If mcp_id is empty.
|
|
218
|
+
|
|
219
|
+
Example:
|
|
220
|
+
>>> mcp = MCP.from_id("550e8400-e29b-41d4-a716-446655440000")
|
|
221
|
+
>>> # Registry will fetch directly by ID
|
|
222
|
+
"""
|
|
223
|
+
if not mcp_id:
|
|
224
|
+
raise ValueError("ID cannot be empty")
|
|
225
|
+
return cls(id=mcp_id, _lookup_only=True)
|
|
226
|
+
|
|
227
|
+
# ─────────────────────────────────────────────────────────────────
|
|
228
|
+
# Runtime Methods (require client connection)
|
|
229
|
+
# ─────────────────────────────────────────────────────────────────
|
|
230
|
+
|
|
231
|
+
def _set_client(self, client: Any) -> MCP:
|
|
232
|
+
"""Set the client reference for this MCP.
|
|
233
|
+
|
|
234
|
+
Args:
|
|
235
|
+
client: The Glaip client instance.
|
|
236
|
+
|
|
237
|
+
Returns:
|
|
238
|
+
Self for method chaining.
|
|
239
|
+
"""
|
|
240
|
+
self._client = client
|
|
241
|
+
return self
|
|
242
|
+
|
|
243
|
+
def get_tools(self) -> list[dict[str, Any]]:
|
|
244
|
+
"""Get tools available from this MCP.
|
|
245
|
+
|
|
246
|
+
Returns:
|
|
247
|
+
List of tool definitions from the MCP.
|
|
248
|
+
|
|
249
|
+
Raises:
|
|
250
|
+
ValueError: If the MCP has no ID.
|
|
251
|
+
RuntimeError: If client is not available.
|
|
252
|
+
"""
|
|
253
|
+
if not self._id:
|
|
254
|
+
raise ValueError(_MCP_NOT_DEPLOYED_MSG)
|
|
255
|
+
if not self._client:
|
|
256
|
+
raise RuntimeError(_CLIENT_NOT_AVAILABLE_MSG)
|
|
257
|
+
|
|
258
|
+
# Delegate to the client's MCP tools endpoint
|
|
259
|
+
return self._client.mcps.get_tools(mcp_id=self._id)
|
|
260
|
+
|
|
261
|
+
def update(self, **kwargs: Any) -> MCP:
|
|
262
|
+
"""Update the MCP with new configuration.
|
|
263
|
+
|
|
264
|
+
Args:
|
|
265
|
+
**kwargs: MCP properties to update (name, description, config, etc.).
|
|
266
|
+
|
|
267
|
+
Returns:
|
|
268
|
+
Self with updated properties.
|
|
269
|
+
|
|
270
|
+
Raises:
|
|
271
|
+
ValueError: If the MCP has no ID.
|
|
272
|
+
RuntimeError: If client is not available.
|
|
273
|
+
"""
|
|
274
|
+
if not self._id:
|
|
275
|
+
raise ValueError(_MCP_NOT_DEPLOYED_MSG)
|
|
276
|
+
if not self._client:
|
|
277
|
+
raise RuntimeError(_CLIENT_NOT_AVAILABLE_MSG)
|
|
278
|
+
|
|
279
|
+
response = self._client.mcps.update(mcp_id=self._id, **kwargs)
|
|
280
|
+
|
|
281
|
+
# Update local properties from response
|
|
282
|
+
if hasattr(response, "name") and response.name:
|
|
283
|
+
self.name = response.name
|
|
284
|
+
if hasattr(response, "description"):
|
|
285
|
+
self.description = response.description
|
|
286
|
+
if hasattr(response, "config"):
|
|
287
|
+
self.config = response.config
|
|
288
|
+
if hasattr(response, "transport"):
|
|
289
|
+
self.transport = response.transport
|
|
290
|
+
|
|
291
|
+
return self
|
|
292
|
+
|
|
293
|
+
def delete(self) -> None:
|
|
294
|
+
"""Delete the MCP from the platform.
|
|
295
|
+
|
|
296
|
+
Raises:
|
|
297
|
+
ValueError: If the MCP has no ID.
|
|
298
|
+
RuntimeError: If client is not available.
|
|
299
|
+
"""
|
|
300
|
+
if not self._id:
|
|
301
|
+
raise ValueError(_MCP_NOT_DEPLOYED_MSG)
|
|
302
|
+
if not self._client:
|
|
303
|
+
raise RuntimeError(_CLIENT_NOT_AVAILABLE_MSG)
|
|
304
|
+
|
|
305
|
+
self._client.mcps.delete(mcp_id=self._id)
|
|
306
|
+
self._id = None
|
|
307
|
+
self._client = None
|
|
308
|
+
|
|
309
|
+
@classmethod
|
|
310
|
+
def from_response(
|
|
311
|
+
cls,
|
|
312
|
+
response: MCPResponse,
|
|
313
|
+
client: Any = None,
|
|
314
|
+
) -> MCP:
|
|
315
|
+
"""Create an MCP instance from an API response.
|
|
316
|
+
|
|
317
|
+
This allows you to work with MCPs retrieved from the API
|
|
318
|
+
as full MCP instances with all methods available.
|
|
319
|
+
|
|
320
|
+
Args:
|
|
321
|
+
response: The MCPResponse from an API call.
|
|
322
|
+
client: The Glaip client instance for API operations.
|
|
323
|
+
|
|
324
|
+
Returns:
|
|
325
|
+
An MCP instance initialized from the response.
|
|
326
|
+
|
|
327
|
+
Example:
|
|
328
|
+
>>> response = client.mcps.get("mcp-123")
|
|
329
|
+
>>> mcp = MCP.from_response(response, client)
|
|
330
|
+
>>> tools = mcp.get_tools()
|
|
331
|
+
"""
|
|
332
|
+
mcp = cls(
|
|
333
|
+
name=response.name,
|
|
334
|
+
id=response.id,
|
|
335
|
+
description=getattr(response, "description", None),
|
|
336
|
+
transport=getattr(response, "transport", None),
|
|
337
|
+
config=getattr(response, "config", None),
|
|
338
|
+
metadata=getattr(response, "metadata", None),
|
|
339
|
+
authentication=getattr(response, "authentication", None),
|
|
340
|
+
)
|
|
341
|
+
|
|
342
|
+
if client:
|
|
343
|
+
mcp._set_client(client)
|
|
344
|
+
|
|
345
|
+
return mcp
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
# pylint: disable=duplicate-code
|
|
2
|
+
"""Models package for AIP SDK.
|
|
3
|
+
|
|
4
|
+
This package provides Pydantic models for API responses.
|
|
5
|
+
|
|
6
|
+
For the public runtime API with methods like run(), deploy(), update(), delete():
|
|
7
|
+
- glaip_sdk.agents.Agent
|
|
8
|
+
- glaip_sdk.tools.Tool
|
|
9
|
+
- glaip_sdk.mcps.MCP
|
|
10
|
+
|
|
11
|
+
The Agent, Tool, and MCP exports from this module are DEPRECATED.
|
|
12
|
+
They redirect to glaip_sdk.agents.Agent, glaip_sdk.tools.Tool, glaip_sdk.mcps.MCP
|
|
13
|
+
respectively with deprecation warnings.
|
|
14
|
+
|
|
15
|
+
Authors:
|
|
16
|
+
Raymond Christopher (raymond.christopher@gdplabs.id)
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
import warnings
|
|
20
|
+
|
|
21
|
+
from glaip_sdk.models._validation import _validate_model, convert_model_for_local_execution
|
|
22
|
+
from glaip_sdk.models.agent import AgentResponse
|
|
23
|
+
from glaip_sdk.models.agent_runs import (
|
|
24
|
+
RunOutputChunk,
|
|
25
|
+
RunsPage,
|
|
26
|
+
RunSummary,
|
|
27
|
+
RunWithOutput,
|
|
28
|
+
)
|
|
29
|
+
from glaip_sdk.models.common import LanguageModelResponse, TTYRenderer
|
|
30
|
+
|
|
31
|
+
# Pure Pydantic models for API responses (no runtime methods)
|
|
32
|
+
# Import model constants and validation (absolute imports)
|
|
33
|
+
from glaip_sdk.models.constants import (
|
|
34
|
+
DEFAULT_MODEL,
|
|
35
|
+
Anthropic,
|
|
36
|
+
AzureOpenAI,
|
|
37
|
+
Bedrock,
|
|
38
|
+
DeepInfra,
|
|
39
|
+
DeepSeek,
|
|
40
|
+
Google,
|
|
41
|
+
ModelProvider,
|
|
42
|
+
OpenAI,
|
|
43
|
+
)
|
|
44
|
+
from glaip_sdk.models.mcp import MCPResponse
|
|
45
|
+
from glaip_sdk.models.model import Model
|
|
46
|
+
|
|
47
|
+
# Export schedule models
|
|
48
|
+
from glaip_sdk.models.schedule import ( # noqa: F401
|
|
49
|
+
ScheduleConfig,
|
|
50
|
+
ScheduleMetadata,
|
|
51
|
+
ScheduleResponse,
|
|
52
|
+
ScheduleRunOutputChunk,
|
|
53
|
+
ScheduleRunResponse,
|
|
54
|
+
ScheduleRunResult,
|
|
55
|
+
)
|
|
56
|
+
from glaip_sdk.models.tool import ToolResponse
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def __getattr__(name: str) -> type:
|
|
60
|
+
"""Deprecation warnings for backward compatibility."""
|
|
61
|
+
if name == "Agent":
|
|
62
|
+
warnings.warn(
|
|
63
|
+
"Importing Agent from glaip_sdk.models is deprecated. "
|
|
64
|
+
"Use 'from glaip_sdk.agents import Agent' instead. "
|
|
65
|
+
"This will be removed in v1.0.0",
|
|
66
|
+
DeprecationWarning,
|
|
67
|
+
stacklevel=2,
|
|
68
|
+
)
|
|
69
|
+
from glaip_sdk.agents import Agent # noqa: PLC0415
|
|
70
|
+
|
|
71
|
+
return Agent
|
|
72
|
+
|
|
73
|
+
if name == "Tool":
|
|
74
|
+
warnings.warn(
|
|
75
|
+
"Importing Tool from glaip_sdk.models is deprecated. "
|
|
76
|
+
"Use 'from glaip_sdk.tools import Tool' instead. "
|
|
77
|
+
"This will be removed in v1.0.0",
|
|
78
|
+
DeprecationWarning,
|
|
79
|
+
stacklevel=2,
|
|
80
|
+
)
|
|
81
|
+
from glaip_sdk.tools import Tool # noqa: PLC0415
|
|
82
|
+
|
|
83
|
+
return Tool
|
|
84
|
+
|
|
85
|
+
if name == "MCP":
|
|
86
|
+
warnings.warn(
|
|
87
|
+
"Importing MCP from glaip_sdk.models is deprecated. "
|
|
88
|
+
"Use 'from glaip_sdk.mcps import MCP' instead. "
|
|
89
|
+
"This will be removed in v1.0.0",
|
|
90
|
+
DeprecationWarning,
|
|
91
|
+
stacklevel=2,
|
|
92
|
+
)
|
|
93
|
+
from glaip_sdk.mcps import MCP # noqa: PLC0415
|
|
94
|
+
|
|
95
|
+
return MCP
|
|
96
|
+
|
|
97
|
+
raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
__all__ = [
|
|
101
|
+
# Model constants and validation
|
|
102
|
+
"OpenAI",
|
|
103
|
+
"Anthropic",
|
|
104
|
+
"Google",
|
|
105
|
+
"AzureOpenAI",
|
|
106
|
+
"DeepInfra",
|
|
107
|
+
"DeepSeek",
|
|
108
|
+
"Bedrock",
|
|
109
|
+
"Model",
|
|
110
|
+
"ModelProvider",
|
|
111
|
+
"DEFAULT_MODEL",
|
|
112
|
+
"_validate_model",
|
|
113
|
+
"convert_model_for_local_execution",
|
|
114
|
+
# Pure Pydantic response models (recommended for type hints)
|
|
115
|
+
"AgentResponse",
|
|
116
|
+
"ToolResponse",
|
|
117
|
+
"MCPResponse",
|
|
118
|
+
# Deprecated aliases (redirect to runtime classes with warning)
|
|
119
|
+
"Agent",
|
|
120
|
+
"Tool",
|
|
121
|
+
"MCP",
|
|
122
|
+
# Other models
|
|
123
|
+
"LanguageModelResponse",
|
|
124
|
+
"TTYRenderer",
|
|
125
|
+
"RunSummary",
|
|
126
|
+
"RunsPage",
|
|
127
|
+
"RunWithOutput",
|
|
128
|
+
"RunOutputChunk",
|
|
129
|
+
# Schedule models
|
|
130
|
+
"ScheduleConfig",
|
|
131
|
+
"ScheduleMetadata",
|
|
132
|
+
"ScheduleResponse",
|
|
133
|
+
"ScheduleRunResponse",
|
|
134
|
+
"ScheduleRunOutputChunk",
|
|
135
|
+
"ScheduleRunResult",
|
|
136
|
+
]
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
"""Provider configuration for model name standardization.
|
|
2
|
+
|
|
3
|
+
This module centralizes provider configurations, including how provider names
|
|
4
|
+
map to server implementations and their base URLs for local execution.
|
|
5
|
+
|
|
6
|
+
Authors:
|
|
7
|
+
Christian Trisno Sen Long Chen (christian.t.s.l.chen@gdplabs.id)
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
__all__ = ["PROVIDERS", "ProviderConfig", "get_driver", "get_base_url"]
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class ProviderConfig:
|
|
14
|
+
"""Configuration for a model provider.
|
|
15
|
+
|
|
16
|
+
Defines how a provider is referenced in SDK constants and how it maps to
|
|
17
|
+
the underlying driver implementation and API endpoints.
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
def __init__(
|
|
21
|
+
self,
|
|
22
|
+
name: str,
|
|
23
|
+
driver: str,
|
|
24
|
+
base_url: str | None = None,
|
|
25
|
+
):
|
|
26
|
+
"""Initialize provider configuration.
|
|
27
|
+
|
|
28
|
+
Args:
|
|
29
|
+
name: User-facing provider name used in SDK constants (e.g., "deepinfra").
|
|
30
|
+
driver: Driver implementation name in language_models.yaml (e.g., "openai-compatible").
|
|
31
|
+
base_url: Base URL for the provider's API (required for local execution).
|
|
32
|
+
"""
|
|
33
|
+
self.name = name
|
|
34
|
+
self.driver = driver
|
|
35
|
+
self.base_url = base_url
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
# Centralized provider configurations
|
|
39
|
+
# Key: provider name (used in SDK constants)
|
|
40
|
+
# Value: ProviderConfig with driver mapping and base URL
|
|
41
|
+
PROVIDERS: dict[str, ProviderConfig] = {
|
|
42
|
+
"deepinfra": ProviderConfig(
|
|
43
|
+
name="deepinfra",
|
|
44
|
+
driver="openai-compatible",
|
|
45
|
+
base_url="https://api.deepinfra.com/v1/openai",
|
|
46
|
+
),
|
|
47
|
+
"deepseek": ProviderConfig(
|
|
48
|
+
name="deepseek",
|
|
49
|
+
driver="openai-compatible",
|
|
50
|
+
base_url="https://api.deepseek.com",
|
|
51
|
+
),
|
|
52
|
+
"custom": ProviderConfig(
|
|
53
|
+
name="custom",
|
|
54
|
+
driver="openai-compatible",
|
|
55
|
+
base_url=None, # User-provided via Model.base_url
|
|
56
|
+
),
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def get_driver(provider: str) -> str:
|
|
61
|
+
"""Get driver name for a given provider.
|
|
62
|
+
|
|
63
|
+
Maps SDK provider names to their underlying driver implementations.
|
|
64
|
+
For providers not in the config, returns the provider name unchanged
|
|
65
|
+
(assumes provider name matches driver name).
|
|
66
|
+
|
|
67
|
+
Args:
|
|
68
|
+
provider: Provider name from SDK constants (e.g., "deepinfra", "openai").
|
|
69
|
+
|
|
70
|
+
Returns:
|
|
71
|
+
Driver name (e.g., "openai-compatible" for deepinfra, "openai" for openai).
|
|
72
|
+
|
|
73
|
+
Examples:
|
|
74
|
+
>>> get_driver("deepinfra")
|
|
75
|
+
"openai-compatible"
|
|
76
|
+
>>> get_driver("openai")
|
|
77
|
+
"openai"
|
|
78
|
+
"""
|
|
79
|
+
config = PROVIDERS.get(provider)
|
|
80
|
+
return config.driver if config else provider
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
def get_base_url(provider: str) -> str | None:
|
|
84
|
+
"""Get default base URL for a provider.
|
|
85
|
+
|
|
86
|
+
Returns the configured base URL for local execution, if available.
|
|
87
|
+
|
|
88
|
+
Args:
|
|
89
|
+
provider: Provider name from SDK constants (e.g., "deepinfra").
|
|
90
|
+
|
|
91
|
+
Returns:
|
|
92
|
+
Base URL string, or None if no config exists or no base_url configured.
|
|
93
|
+
|
|
94
|
+
Examples:
|
|
95
|
+
>>> get_base_url("deepinfra")
|
|
96
|
+
"https://api.deepinfra.com/v1/openai"
|
|
97
|
+
>>> get_base_url("openai")
|
|
98
|
+
None
|
|
99
|
+
"""
|
|
100
|
+
config = PROVIDERS.get(provider)
|
|
101
|
+
return config.base_url if config else None
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
"""Model validation utility for GL AIP SDK.
|
|
2
|
+
|
|
3
|
+
Validates model names in 'provider/model' format and provides
|
|
4
|
+
helpful error messages for invalid formats.
|
|
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
|
+
import warnings
|
|
13
|
+
from typing import Any
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def _validate_model(model: str) -> str:
|
|
17
|
+
"""Validate model format and deprecate bare names.
|
|
18
|
+
|
|
19
|
+
Args:
|
|
20
|
+
model: Model string to validate
|
|
21
|
+
|
|
22
|
+
Returns:
|
|
23
|
+
Normalized model string in provider/model format
|
|
24
|
+
|
|
25
|
+
Raises:
|
|
26
|
+
ValueError: If model format is invalid
|
|
27
|
+
"""
|
|
28
|
+
if "/" not in model:
|
|
29
|
+
warnings.warn(
|
|
30
|
+
f"Bare model name '{model}' is deprecated. "
|
|
31
|
+
f"Use 'provider/model' format (e.g., 'openai/{model}'). "
|
|
32
|
+
f"This will be an error in v2.0. Use constants: from glaip_sdk.models import OpenAI",
|
|
33
|
+
DeprecationWarning,
|
|
34
|
+
stacklevel=2,
|
|
35
|
+
)
|
|
36
|
+
return f"openai/{model}"
|
|
37
|
+
|
|
38
|
+
provider, model_name = model.split("/", 1)
|
|
39
|
+
if not provider or not model_name:
|
|
40
|
+
raise ValueError(
|
|
41
|
+
f"Invalid model format: '{model}'. "
|
|
42
|
+
f"Expected 'provider/model' format (e.g., 'openai/gpt-4o-mini'). "
|
|
43
|
+
f"Use constants: from glaip_sdk.models import OpenAI; Agent(model=OpenAI.GPT_4O_MINI)."
|
|
44
|
+
)
|
|
45
|
+
return model
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def convert_model_for_local_execution(model: str | Any) -> tuple[str, dict[str, Any]]:
|
|
49
|
+
"""Convert model to aip_agents format for local execution.
|
|
50
|
+
|
|
51
|
+
Converts provider/model format appropriately for aip_agents.
|
|
52
|
+
Handles both Model objects and string models.
|
|
53
|
+
|
|
54
|
+
Args:
|
|
55
|
+
model: Model object or string identifier.
|
|
56
|
+
|
|
57
|
+
Returns:
|
|
58
|
+
Tuple of (model_string, config_dict) where:
|
|
59
|
+
- model_string: Model in format expected by aip_agents (provider/model)
|
|
60
|
+
- config_dict: Configuration dict with credentials, hyperparameters, etc.
|
|
61
|
+
"""
|
|
62
|
+
from glaip_sdk.models import Model # noqa: PLC0415
|
|
63
|
+
|
|
64
|
+
# Handle Model objects
|
|
65
|
+
if isinstance(model, Model):
|
|
66
|
+
return model.to_aip_agents_format()
|
|
67
|
+
|
|
68
|
+
# Handle string models
|
|
69
|
+
if isinstance(model, str):
|
|
70
|
+
if "/" not in model:
|
|
71
|
+
return model, {}
|
|
72
|
+
|
|
73
|
+
parts = model.split("/", 1)
|
|
74
|
+
provider = parts[0]
|
|
75
|
+
model_name = parts[1]
|
|
76
|
+
|
|
77
|
+
# Map provider to driver and get base_url from config
|
|
78
|
+
from glaip_sdk.models._provider_mappings import ( # noqa: PLC0415
|
|
79
|
+
get_base_url,
|
|
80
|
+
get_driver,
|
|
81
|
+
)
|
|
82
|
+
|
|
83
|
+
driver = get_driver(provider)
|
|
84
|
+
base_url = get_base_url(provider)
|
|
85
|
+
|
|
86
|
+
config: dict[str, Any] = {}
|
|
87
|
+
if base_url:
|
|
88
|
+
config["lm_base_url"] = base_url
|
|
89
|
+
|
|
90
|
+
# Return with driver name
|
|
91
|
+
return f"{driver}/{model_name}", config
|
|
92
|
+
|
|
93
|
+
# For other types (None, etc.), return as-is
|
|
94
|
+
return model, {}
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
__all__ = ["_validate_model", "convert_model_for_local_execution"]
|