glaip-sdk 0.6.19__py3-none-any.whl → 0.7.27__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- glaip_sdk/agents/base.py +283 -30
- glaip_sdk/agents/component.py +233 -0
- glaip_sdk/branding.py +113 -2
- glaip_sdk/cli/account_store.py +15 -0
- glaip_sdk/cli/auth.py +14 -8
- glaip_sdk/cli/commands/accounts.py +1 -1
- 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 +1 -1
- glaip_sdk/cli/commands/configure.py +1 -2
- 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 +2 -4
- 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.py → transcripts_original.py} +2 -1
- glaip_sdk/cli/commands/update.py +163 -17
- glaip_sdk/cli/config.py +1 -0
- glaip_sdk/cli/entrypoint.py +20 -0
- glaip_sdk/cli/main.py +112 -35
- glaip_sdk/cli/pager.py +3 -3
- glaip_sdk/cli/resolution.py +2 -1
- glaip_sdk/cli/slash/accounts_controller.py +3 -1
- glaip_sdk/cli/slash/agent_session.py +1 -1
- glaip_sdk/cli/slash/remote_runs_controller.py +3 -1
- glaip_sdk/cli/slash/session.py +343 -20
- glaip_sdk/cli/slash/tui/__init__.py +29 -1
- glaip_sdk/cli/slash/tui/accounts.tcss +97 -6
- glaip_sdk/cli/slash/tui/accounts_app.py +1117 -126
- glaip_sdk/cli/slash/tui/clipboard.py +316 -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 +43 -21
- glaip_sdk/cli/slash/tui/remote_runs_app.py +178 -20
- 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/history.py +1 -1
- glaip_sdk/cli/transcript/viewer.py +1 -1
- glaip_sdk/cli/tui_settings.py +125 -0
- glaip_sdk/cli/update_notifier.py +215 -7
- glaip_sdk/cli/validators.py +1 -1
- glaip_sdk/client/__init__.py +2 -1
- glaip_sdk/client/_schedule_payloads.py +89 -0
- glaip_sdk/client/agents.py +293 -17
- glaip_sdk/client/base.py +25 -0
- glaip_sdk/client/hitl.py +136 -0
- glaip_sdk/client/main.py +7 -5
- glaip_sdk/client/mcps.py +44 -13
- glaip_sdk/client/payloads/agent/__init__.py +23 -0
- glaip_sdk/client/{_agent_payloads.py → payloads/agent/requests.py} +28 -48
- glaip_sdk/client/payloads/agent/responses.py +43 -0
- glaip_sdk/client/run_rendering.py +109 -30
- glaip_sdk/client/schedules.py +439 -0
- glaip_sdk/client/tools.py +52 -23
- glaip_sdk/config/constants.py +22 -2
- glaip_sdk/guardrails/__init__.py +80 -0
- glaip_sdk/guardrails/serializer.py +91 -0
- glaip_sdk/hitl/__init__.py +35 -2
- glaip_sdk/hitl/base.py +64 -0
- glaip_sdk/hitl/callback.py +43 -0
- glaip_sdk/hitl/local.py +1 -31
- glaip_sdk/hitl/remote.py +523 -0
- glaip_sdk/models/__init__.py +47 -1
- glaip_sdk/models/_provider_mappings.py +101 -0
- glaip_sdk/models/_validation.py +97 -0
- glaip_sdk/models/agent.py +2 -1
- glaip_sdk/models/agent_runs.py +2 -1
- glaip_sdk/models/constants.py +141 -0
- glaip_sdk/models/model.py +170 -0
- glaip_sdk/models/schedule.py +224 -0
- glaip_sdk/payload_schemas/agent.py +1 -0
- glaip_sdk/payload_schemas/guardrails.py +34 -0
- glaip_sdk/ptc.py +145 -0
- glaip_sdk/registry/tool.py +270 -57
- glaip_sdk/runner/__init__.py +20 -3
- glaip_sdk/runner/deps.py +4 -1
- glaip_sdk/runner/langgraph.py +251 -27
- glaip_sdk/runner/logging_config.py +77 -0
- glaip_sdk/runner/mcp_adapter/mcp_config_builder.py +30 -9
- glaip_sdk/runner/ptc_adapter.py +98 -0
- glaip_sdk/runner/tool_adapter/langchain_tool_adapter.py +25 -2
- glaip_sdk/schedules/__init__.py +22 -0
- glaip_sdk/schedules/base.py +291 -0
- glaip_sdk/tools/base.py +67 -14
- glaip_sdk/utils/__init__.py +1 -0
- glaip_sdk/utils/agent_config.py +8 -2
- glaip_sdk/utils/bundler.py +138 -2
- glaip_sdk/utils/import_resolver.py +427 -49
- glaip_sdk/utils/runtime_config.py +3 -2
- glaip_sdk/utils/sync.py +31 -11
- glaip_sdk/utils/tool_detection.py +274 -6
- {glaip_sdk-0.6.19.dist-info → glaip_sdk-0.7.27.dist-info}/METADATA +22 -8
- glaip_sdk-0.7.27.dist-info/RECORD +227 -0
- {glaip_sdk-0.6.19.dist-info → glaip_sdk-0.7.27.dist-info}/WHEEL +1 -1
- glaip_sdk-0.7.27.dist-info/entry_points.txt +2 -0
- glaip_sdk/cli/commands/agents.py +0 -1509
- glaip_sdk/cli/commands/mcps.py +0 -1356
- glaip_sdk/cli/commands/tools.py +0 -576
- glaip_sdk/cli/utils.py +0 -263
- glaip_sdk-0.6.19.dist-info/RECORD +0 -163
- glaip_sdk-0.6.19.dist-info/entry_points.txt +0 -2
- {glaip_sdk-0.6.19.dist-info → glaip_sdk-0.7.27.dist-info}/top_level.txt +0 -0
|
@@ -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"]
|
glaip_sdk/models/agent.py
CHANGED
|
@@ -13,9 +13,10 @@ Authors:
|
|
|
13
13
|
from datetime import datetime
|
|
14
14
|
from typing import Any
|
|
15
15
|
|
|
16
|
-
from glaip_sdk.config.constants import DEFAULT_AGENT_RUN_TIMEOUT
|
|
17
16
|
from pydantic import BaseModel
|
|
18
17
|
|
|
18
|
+
from glaip_sdk.config.constants import DEFAULT_AGENT_RUN_TIMEOUT
|
|
19
|
+
|
|
19
20
|
|
|
20
21
|
class AgentResponse(BaseModel):
|
|
21
22
|
"""Pydantic model for Agent API responses.
|
glaip_sdk/models/agent_runs.py
CHANGED
|
@@ -13,6 +13,7 @@ from pydantic import BaseModel, Field, field_validator, model_validator
|
|
|
13
13
|
|
|
14
14
|
# Type alias for SSE event dictionaries
|
|
15
15
|
RunOutputChunk = dict[str, Any]
|
|
16
|
+
RunStatus = Literal["started", "success", "failed", "cancelled", "aborted", "unavailable"]
|
|
16
17
|
|
|
17
18
|
|
|
18
19
|
class RunSummary(BaseModel):
|
|
@@ -22,7 +23,7 @@ class RunSummary(BaseModel):
|
|
|
22
23
|
agent_id: UUID
|
|
23
24
|
run_type: Literal["manual", "schedule"]
|
|
24
25
|
schedule_id: UUID | None = None
|
|
25
|
-
status:
|
|
26
|
+
status: RunStatus
|
|
26
27
|
started_at: datetime
|
|
27
28
|
completed_at: datetime | None = None
|
|
28
29
|
input: str | None = None
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
# pylint: disable=duplicate-code
|
|
2
|
+
"""Model constants for GL AIP SDK.
|
|
3
|
+
|
|
4
|
+
Typed constants for popular AI models matching AIP Server's language_models.yaml keys.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
__all__ = [
|
|
10
|
+
"ModelProvider",
|
|
11
|
+
"OpenAI",
|
|
12
|
+
"Anthropic",
|
|
13
|
+
"Google",
|
|
14
|
+
"AzureOpenAI",
|
|
15
|
+
"DeepInfra",
|
|
16
|
+
"DeepSeek",
|
|
17
|
+
"Bedrock",
|
|
18
|
+
"DEFAULT_MODEL",
|
|
19
|
+
]
|
|
20
|
+
|
|
21
|
+
# Note: DeepInfra provider changed to 'openai-compatible' for aip_agents compatibility
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class ModelProvider:
|
|
25
|
+
"""Supported model providers."""
|
|
26
|
+
|
|
27
|
+
OPENAI = "openai"
|
|
28
|
+
ANTHROPIC = "anthropic"
|
|
29
|
+
AZURE_OPENAI = "azure-openai"
|
|
30
|
+
GOOGLE = "google"
|
|
31
|
+
DEEPINFRA = "deepinfra"
|
|
32
|
+
DEEPSEEK = "deepseek"
|
|
33
|
+
OPENAI_COMPATIBLE = "openai-compatible"
|
|
34
|
+
BEDROCK = "bedrock"
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
class OpenAI:
|
|
38
|
+
"""OpenAI model constants."""
|
|
39
|
+
|
|
40
|
+
GPT_4O_MINI = "openai/gpt-4o-mini"
|
|
41
|
+
GPT_4O = "openai/gpt-4o"
|
|
42
|
+
GPT_4_1 = "openai/gpt-4.1"
|
|
43
|
+
GPT_4_1_NANO = "openai/gpt-4.1-nano"
|
|
44
|
+
GPT_4_1_MINI = "openai/gpt-4.1-mini"
|
|
45
|
+
GPT_5 = "openai/gpt-5"
|
|
46
|
+
GPT_5_MINI = "openai/gpt-5-mini"
|
|
47
|
+
GPT_5_NANO = "openai/gpt-5-nano"
|
|
48
|
+
GPT_5_LOW = "openai/gpt-5-low"
|
|
49
|
+
GPT_5_MINIMAL = "openai/gpt-5-minimal"
|
|
50
|
+
GPT_5_MEDIUM = "openai/gpt-5-medium"
|
|
51
|
+
GPT_5_HIGH = "openai/gpt-5-high"
|
|
52
|
+
GPT_5_1 = "openai/gpt-5.1"
|
|
53
|
+
GPT_5_1_LOW = "openai/gpt-5.1-low"
|
|
54
|
+
GPT_5_1_MEDIUM = "openai/gpt-5.1-medium"
|
|
55
|
+
GPT_5_1_HIGH = "openai/gpt-5.1-high"
|
|
56
|
+
GPT_5_2 = "openai/gpt-5.2"
|
|
57
|
+
GPT_5_2_LOW = "openai/gpt-5.2-low"
|
|
58
|
+
GPT_5_2_MEDIUM = "openai/gpt-5.2-medium"
|
|
59
|
+
GPT_5_2_HIGH = "openai/gpt-5.2-high"
|
|
60
|
+
GPT_5_2_XHIGH = "openai/gpt-5.2-xhigh"
|
|
61
|
+
GPT_4O_2024_11_20 = "openai/gpt-4o-2024-11-20"
|
|
62
|
+
O4_MINI = "openai/o4-mini"
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
class Anthropic:
|
|
66
|
+
"""Anthropic model constants."""
|
|
67
|
+
|
|
68
|
+
CLAUDE_3_5_SONNET_LATEST = "anthropic/claude-3-5-sonnet-latest"
|
|
69
|
+
CLAUDE_3_7_SONNET_LATEST = "anthropic/claude-3-7-sonnet-latest"
|
|
70
|
+
CLAUDE_SONNET_4_0 = "anthropic/claude-sonnet-4-0"
|
|
71
|
+
CLAUDE_OPUS_4_0 = "anthropic/claude-opus-4-0"
|
|
72
|
+
CLAUDE_OPUS_4_1 = "anthropic/claude-opus-4-1"
|
|
73
|
+
CLAUDE_SONNET_4_5 = "anthropic/claude-sonnet-4-5"
|
|
74
|
+
# DX Alias
|
|
75
|
+
CLAUDE_3_5_SONNET = CLAUDE_3_5_SONNET_LATEST
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
class Google:
|
|
79
|
+
"""Google model constants."""
|
|
80
|
+
|
|
81
|
+
GEMINI_2_5_FLASH = "google/gemini-2.5-flash"
|
|
82
|
+
GEMINI_3_FLASH_PREVIEW = "google/gemini-3-flash-preview"
|
|
83
|
+
GEMINI_3_PRO_PREVIEW = "google/gemini-3-pro-preview"
|
|
84
|
+
GEMINI_2_5_PRO = "google/gemini-2.5-pro"
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
class AzureOpenAI:
|
|
88
|
+
"""Azure OpenAI model constants."""
|
|
89
|
+
|
|
90
|
+
GPT_4O = "azure-openai/gpt-4o"
|
|
91
|
+
GPT_4O_MINI = "azure-openai/gpt-4o-mini"
|
|
92
|
+
GPT_4_1 = "azure-openai/gpt-4.1"
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
class DeepInfra:
|
|
96
|
+
"""DeepInfra model constants.
|
|
97
|
+
|
|
98
|
+
Note: DeepInfra models use the openai-compatible driver internally,
|
|
99
|
+
but we expose them with the 'deepinfra/' prefix for better DX.
|
|
100
|
+
The SDK handles the mapping to 'openai-compatible/' automatically.
|
|
101
|
+
"""
|
|
102
|
+
|
|
103
|
+
QWEN3_235B_A22B_INSTRUCT_2507 = "deepinfra/Qwen/Qwen3-235B-A22B-Instruct-2507"
|
|
104
|
+
KIMI_K2_INSTRUCT = "deepinfra/moonshotai/Kimi-K2-Instruct"
|
|
105
|
+
QWEN3_30B_A3B = "deepinfra/Qwen/Qwen3-30B-A3B"
|
|
106
|
+
GLM_4_5_AIR = "deepinfra/zai-org/GLM-4.5-Air"
|
|
107
|
+
QWEN3_32B = "deepinfra/Qwen/Qwen3-32B"
|
|
108
|
+
QWEN3_NEXT_80B_A3B_THINKING = "deepinfra/Qwen/Qwen3-Next-80B-A3B-Thinking"
|
|
109
|
+
QWEN3_NEXT_80B_A3B_INSTRUCT = "deepinfra/Qwen/Qwen3-Next-80B-A3B-Instruct"
|
|
110
|
+
QWEN3_14B = "deepinfra/Qwen/Qwen3-14B"
|
|
111
|
+
GLM_4_5 = "deepinfra/zai-org/GLM-4.5"
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
class DeepSeek:
|
|
115
|
+
"""DeepSeek model constants.
|
|
116
|
+
|
|
117
|
+
Note: DeepSeek models use the openai-compatible driver internally,
|
|
118
|
+
but we expose them with the 'deepseek/' prefix for better DX.
|
|
119
|
+
The SDK handles the mapping to 'openai-compatible/' automatically.
|
|
120
|
+
"""
|
|
121
|
+
|
|
122
|
+
DEEPSEEK_CHAT = "deepseek/deepseek-chat"
|
|
123
|
+
DEEPSEEK_V3_1 = "deepseek/deepseek-ai/DeepSeek-V3.1"
|
|
124
|
+
DEEPSEEK_V3_1_TERMINUS = "deepseek/deepseek-ai/DeepSeek-V3.1-Terminus"
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
class Bedrock:
|
|
128
|
+
"""AWS Bedrock model constants."""
|
|
129
|
+
|
|
130
|
+
CLAUDE_SONNET_4_20250514_V1_0 = "bedrock/us.anthropic.claude-sonnet-4-20250514-v1:0"
|
|
131
|
+
CLAUDE_3_5_HAIKU_20241022_V1_0 = "bedrock/us.anthropic.claude-3-5-haiku-20241022-v1:0"
|
|
132
|
+
CLAUDE_SONNET_4_5_20250929_V1_0 = "bedrock/us.anthropic.claude-sonnet-4-5-20250929-v1:0"
|
|
133
|
+
|
|
134
|
+
# DX Aliases
|
|
135
|
+
ANTHROPIC_CLAUDE_SONNET_4 = CLAUDE_SONNET_4_20250514_V1_0
|
|
136
|
+
ANTHROPIC_CLAUDE_3_5_HAIKU = CLAUDE_3_5_HAIKU_20241022_V1_0
|
|
137
|
+
ANTHROPIC_CLAUDE_SONNET_4_5 = CLAUDE_SONNET_4_5_20250929_V1_0
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
# Default model selection
|
|
141
|
+
DEFAULT_MODEL = OpenAI.GPT_5_NANO
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
"""Model configuration class for GL AIP SDK.
|
|
2
|
+
|
|
3
|
+
Provides a structured way to specify models, credentials, and hyperparameters
|
|
4
|
+
for local execution.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
from typing import Any
|
|
10
|
+
|
|
11
|
+
from pydantic import BaseModel, field_validator
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class Model(BaseModel):
|
|
15
|
+
"""Model configuration class for local execution.
|
|
16
|
+
|
|
17
|
+
Bundles model identity with credentials and hyperparameters.
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
id: str
|
|
21
|
+
credentials: dict[str, Any] | str | None = None
|
|
22
|
+
hyperparameters: dict[str, Any] | None = None
|
|
23
|
+
base_url: str | None = None
|
|
24
|
+
|
|
25
|
+
@field_validator("id")
|
|
26
|
+
@classmethod
|
|
27
|
+
def validate_id(cls, v: str) -> str:
|
|
28
|
+
"""Validate model ID format.
|
|
29
|
+
|
|
30
|
+
Args:
|
|
31
|
+
v: Model identifier string.
|
|
32
|
+
|
|
33
|
+
Returns:
|
|
34
|
+
Validated model identifier in 'provider/model' format.
|
|
35
|
+
|
|
36
|
+
Raises:
|
|
37
|
+
ValueError: If model format is invalid.
|
|
38
|
+
"""
|
|
39
|
+
from glaip_sdk.models._validation import _validate_model # noqa: PLC0415
|
|
40
|
+
|
|
41
|
+
return _validate_model(v)
|
|
42
|
+
|
|
43
|
+
def to_aip_agents_format(self) -> tuple[str, dict[str, Any]]:
|
|
44
|
+
"""Convert Model to aip_agents format.
|
|
45
|
+
|
|
46
|
+
Converts provider/model format to driver/model format for aip_agents.
|
|
47
|
+
For custom models with base_url, uses format: openai-compatible/base_url:model_name
|
|
48
|
+
|
|
49
|
+
Returns:
|
|
50
|
+
Tuple of (model_string, agent_config_dict).
|
|
51
|
+
"""
|
|
52
|
+
if "/" not in self.id:
|
|
53
|
+
return self.id, {}
|
|
54
|
+
|
|
55
|
+
parts = self.id.split("/", 1)
|
|
56
|
+
provider = parts[0]
|
|
57
|
+
model_name = parts[1]
|
|
58
|
+
|
|
59
|
+
config = self._build_agent_config(provider)
|
|
60
|
+
model_string = self._build_model_string(provider, model_name, config)
|
|
61
|
+
|
|
62
|
+
return model_string, config
|
|
63
|
+
|
|
64
|
+
def _build_agent_config(self, provider: str) -> dict[str, Any]:
|
|
65
|
+
"""Build agent config dict from Model attributes.
|
|
66
|
+
|
|
67
|
+
Args:
|
|
68
|
+
provider: Provider name extracted from model id.
|
|
69
|
+
|
|
70
|
+
Returns:
|
|
71
|
+
Configuration dict with credentials, hyperparameters, and base_url.
|
|
72
|
+
"""
|
|
73
|
+
config: dict[str, Any] = {}
|
|
74
|
+
|
|
75
|
+
if self.credentials:
|
|
76
|
+
if isinstance(self.credentials, str):
|
|
77
|
+
config["lm_api_key"] = self.credentials
|
|
78
|
+
elif isinstance(self.credentials, dict):
|
|
79
|
+
config["lm_credentials"] = self.credentials
|
|
80
|
+
|
|
81
|
+
if self.hyperparameters:
|
|
82
|
+
config["lm_hyperparameters"] = self.hyperparameters
|
|
83
|
+
|
|
84
|
+
base_url = self._resolve_base_url(provider)
|
|
85
|
+
if base_url:
|
|
86
|
+
config["lm_base_url"] = base_url
|
|
87
|
+
|
|
88
|
+
return config
|
|
89
|
+
|
|
90
|
+
def _resolve_base_url(self, provider: str) -> str | None:
|
|
91
|
+
"""Resolve base URL for the provider.
|
|
92
|
+
|
|
93
|
+
Uses centralized provider configurations to determine base_url.
|
|
94
|
+
Users can override by explicitly setting base_url attribute.
|
|
95
|
+
|
|
96
|
+
Args:
|
|
97
|
+
provider: Provider name from model ID (e.g., "deepinfra").
|
|
98
|
+
|
|
99
|
+
Returns:
|
|
100
|
+
Base URL string or None.
|
|
101
|
+
|
|
102
|
+
Examples:
|
|
103
|
+
>>> model = Model(id="deepinfra/Qwen/Qwen3-30B")
|
|
104
|
+
>>> model._resolve_base_url("deepinfra")
|
|
105
|
+
"https://api.deepinfra.com/v1/openai"
|
|
106
|
+
"""
|
|
107
|
+
if self.base_url:
|
|
108
|
+
return self.base_url
|
|
109
|
+
|
|
110
|
+
# Get base_url from provider config
|
|
111
|
+
from glaip_sdk.models._provider_mappings import get_base_url # noqa: PLC0415
|
|
112
|
+
|
|
113
|
+
base_url = get_base_url(provider)
|
|
114
|
+
if base_url:
|
|
115
|
+
return base_url
|
|
116
|
+
|
|
117
|
+
return None
|
|
118
|
+
|
|
119
|
+
def _build_model_string(self, provider: str, model_name: str, config: dict[str, Any]) -> str:
|
|
120
|
+
"""Build normalized model string for aip_agents.
|
|
121
|
+
|
|
122
|
+
Converts provider names to their driver implementations for local execution.
|
|
123
|
+
|
|
124
|
+
Conversion strategy:
|
|
125
|
+
1. Custom models with base_url: Use colon format (openai-compatible/{base_url}:{model_name})
|
|
126
|
+
This allows aip_agents to parse base_url and model_name separately.
|
|
127
|
+
2. Standard providers: Map to driver and use slash format (driver/{model_name})
|
|
128
|
+
aip_agents will handle provider/model format internally.
|
|
129
|
+
|
|
130
|
+
Args:
|
|
131
|
+
provider: Provider name from model ID (e.g., "deepinfra", "openai").
|
|
132
|
+
model_name: Model name after provider prefix.
|
|
133
|
+
config: Agent config dict (may contain base_url).
|
|
134
|
+
|
|
135
|
+
Returns:
|
|
136
|
+
Normalized model string in provider/model format with driver name.
|
|
137
|
+
|
|
138
|
+
Examples:
|
|
139
|
+
>>> _build_model_string("deepinfra", "Qwen/Qwen3-30B", {})
|
|
140
|
+
"openai-compatible/Qwen/Qwen3-30B"
|
|
141
|
+
>>> _build_model_string("openai", "gpt-4o", {})
|
|
142
|
+
"openai/gpt-4o"
|
|
143
|
+
"""
|
|
144
|
+
from glaip_sdk.models._provider_mappings import get_driver # noqa: PLC0415
|
|
145
|
+
|
|
146
|
+
# Map provider to driver (e.g., deepinfra → openai-compatible)
|
|
147
|
+
driver = get_driver(provider)
|
|
148
|
+
|
|
149
|
+
if provider == "custom":
|
|
150
|
+
base_url = config.get("lm_base_url")
|
|
151
|
+
if base_url:
|
|
152
|
+
return f"{driver}/{base_url}:{model_name}"
|
|
153
|
+
|
|
154
|
+
# Standard case: driver with slash format
|
|
155
|
+
# aip_agents will handle provider/model format internally
|
|
156
|
+
return f"{driver}/{model_name}"
|
|
157
|
+
|
|
158
|
+
def __repr__(self) -> str:
|
|
159
|
+
"""Return string representation of Model.
|
|
160
|
+
|
|
161
|
+
Note: Credentials are masked to avoid leaking secrets in logs.
|
|
162
|
+
Hyperparameters and base_url are shown if present.
|
|
163
|
+
"""
|
|
164
|
+
creds_repr = "***" if self.credentials else "None"
|
|
165
|
+
return (
|
|
166
|
+
f"Model(id={self.id!r}, "
|
|
167
|
+
f"credentials={creds_repr}, "
|
|
168
|
+
f"hyperparameters={self.hyperparameters!r}, "
|
|
169
|
+
f"base_url={self.base_url!r})"
|
|
170
|
+
)
|
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""Schedule DTO models for AIP SDK.
|
|
3
|
+
|
|
4
|
+
These models represent API payloads and responses. They are intentionally DTO-only
|
|
5
|
+
and do not contain runtime behavior.
|
|
6
|
+
|
|
7
|
+
Authors:
|
|
8
|
+
Raymond Christopher (raymond.christopher@gdplabs.id)
|
|
9
|
+
Christian Trisno Sen Long Chen (christian.t.s.l.chen@gdplabs.id)
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
from datetime import datetime
|
|
13
|
+
from typing import Any
|
|
14
|
+
|
|
15
|
+
from pydantic import BaseModel, ConfigDict
|
|
16
|
+
|
|
17
|
+
from glaip_sdk.models.agent_runs import RunStatus
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class ScheduleConfig(BaseModel):
|
|
21
|
+
"""Cron-like schedule configuration matching backend ScheduleConfig.
|
|
22
|
+
|
|
23
|
+
All fields accept cron-style values:
|
|
24
|
+
- Specific values: "0", "9", "1"
|
|
25
|
+
- Wildcards: "*"
|
|
26
|
+
- Intervals: "*/5", "*/2"
|
|
27
|
+
- Ranges: "1-5", "9-17"
|
|
28
|
+
- Lists: "1,3,5"
|
|
29
|
+
|
|
30
|
+
Note: day_of_week uses 0-6 where 0=Monday.
|
|
31
|
+
"""
|
|
32
|
+
|
|
33
|
+
minute: str = "*"
|
|
34
|
+
hour: str = "*"
|
|
35
|
+
day_of_month: str = "*"
|
|
36
|
+
month: str = "*"
|
|
37
|
+
day_of_week: str = "*"
|
|
38
|
+
|
|
39
|
+
model_config = ConfigDict(from_attributes=True)
|
|
40
|
+
|
|
41
|
+
def to_cron_string(self) -> str:
|
|
42
|
+
"""Convert to standard cron string format.
|
|
43
|
+
|
|
44
|
+
Returns:
|
|
45
|
+
Cron string in format "minute hour day_of_month month day_of_week"
|
|
46
|
+
"""
|
|
47
|
+
return f"{self.minute} {self.hour} {self.day_of_month} {self.month} {self.day_of_week}"
|
|
48
|
+
|
|
49
|
+
@classmethod
|
|
50
|
+
def from_cron_string(cls, cron: str) -> "ScheduleConfig":
|
|
51
|
+
"""Parse a cron string into ScheduleConfig.
|
|
52
|
+
|
|
53
|
+
Args:
|
|
54
|
+
cron: Cron string in format "minute hour day_of_month month day_of_week"
|
|
55
|
+
|
|
56
|
+
Returns:
|
|
57
|
+
ScheduleConfig instance
|
|
58
|
+
|
|
59
|
+
Raises:
|
|
60
|
+
ValueError: If cron string doesn't have exactly 5 fields
|
|
61
|
+
"""
|
|
62
|
+
parts = cron.split()
|
|
63
|
+
if len(parts) != 5:
|
|
64
|
+
raise ValueError(f"Invalid cron string: expected 5 fields, got {len(parts)}")
|
|
65
|
+
return cls(
|
|
66
|
+
minute=parts[0],
|
|
67
|
+
hour=parts[1],
|
|
68
|
+
day_of_month=parts[2],
|
|
69
|
+
month=parts[3],
|
|
70
|
+
day_of_week=parts[4],
|
|
71
|
+
)
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
class ScheduleMetadata(BaseModel):
|
|
75
|
+
"""Metadata embedded in schedule responses.
|
|
76
|
+
|
|
77
|
+
Contains the agent association, input text, and cron configuration.
|
|
78
|
+
"""
|
|
79
|
+
|
|
80
|
+
agent_id: str
|
|
81
|
+
input: str
|
|
82
|
+
schedule: ScheduleConfig
|
|
83
|
+
|
|
84
|
+
model_config = ConfigDict(from_attributes=True)
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
class ScheduleResponse(BaseModel):
|
|
88
|
+
"""Schedule response DTO.
|
|
89
|
+
|
|
90
|
+
Attributes:
|
|
91
|
+
id: Schedule ID.
|
|
92
|
+
next_run_time: Next run time as returned by the API.
|
|
93
|
+
time_until_next_run: Human-readable duration until next run.
|
|
94
|
+
metadata: Schedule metadata.
|
|
95
|
+
created_at: Creation timestamp.
|
|
96
|
+
updated_at: Update timestamp.
|
|
97
|
+
agent_id: Agent ID derived from metadata.
|
|
98
|
+
input: Input text derived from metadata.
|
|
99
|
+
schedule_config: ScheduleConfig derived from metadata.
|
|
100
|
+
"""
|
|
101
|
+
|
|
102
|
+
id: str
|
|
103
|
+
next_run_time: str | None = None
|
|
104
|
+
time_until_next_run: str | None = None
|
|
105
|
+
metadata: ScheduleMetadata | None = None
|
|
106
|
+
created_at: datetime | None = None
|
|
107
|
+
updated_at: datetime | None = None
|
|
108
|
+
|
|
109
|
+
model_config = ConfigDict(from_attributes=True)
|
|
110
|
+
|
|
111
|
+
@property
|
|
112
|
+
def agent_id(self) -> str | None:
|
|
113
|
+
"""Get the agent ID from metadata."""
|
|
114
|
+
return self.metadata.agent_id if self.metadata else None
|
|
115
|
+
|
|
116
|
+
@property
|
|
117
|
+
def input(self) -> str | None:
|
|
118
|
+
"""Get the scheduled input text from metadata."""
|
|
119
|
+
return self.metadata.input if self.metadata else None
|
|
120
|
+
|
|
121
|
+
@property
|
|
122
|
+
def schedule_config(self) -> ScheduleConfig | None:
|
|
123
|
+
"""Get the schedule configuration from metadata."""
|
|
124
|
+
return self.metadata.schedule if self.metadata else None
|
|
125
|
+
|
|
126
|
+
def __repr__(self) -> str:
|
|
127
|
+
"""Return a readable representation of the schedule."""
|
|
128
|
+
parts = [f"ScheduleResponse(id={self.id!r}"]
|
|
129
|
+
if self.next_run_time:
|
|
130
|
+
parts.append(f"next_run_time={self.next_run_time!r}")
|
|
131
|
+
if self.time_until_next_run:
|
|
132
|
+
parts.append(f"time_until_next_run={self.time_until_next_run!r}")
|
|
133
|
+
if self.agent_id:
|
|
134
|
+
parts.append(f"agent_id={self.agent_id!r}")
|
|
135
|
+
if self.created_at:
|
|
136
|
+
parts.append(f"created_at={self.created_at!r}")
|
|
137
|
+
return ", ".join(parts) + ")"
|
|
138
|
+
|
|
139
|
+
def __str__(self) -> str:
|
|
140
|
+
"""Return a readable string representation."""
|
|
141
|
+
return self.__repr__()
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
# Type alias for SSE event dictionaries
|
|
145
|
+
ScheduleRunOutputChunk = dict[str, Any]
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
class ScheduleRunResponse(BaseModel):
|
|
149
|
+
"""Schedule run response DTO."""
|
|
150
|
+
|
|
151
|
+
id: str
|
|
152
|
+
agent_id: str
|
|
153
|
+
schedule_id: str | None = None # May be None for non-scheduled runs
|
|
154
|
+
status: RunStatus # Backend uses lowercase.
|
|
155
|
+
run_type: str | None = None # "schedule" for scheduled runs
|
|
156
|
+
started_at: datetime | None = None
|
|
157
|
+
completed_at: datetime | None = None
|
|
158
|
+
input: str | None = None # Input used for the execution.
|
|
159
|
+
config: ScheduleConfig | dict[str, str] | None = None # Schedule config used.
|
|
160
|
+
created_at: datetime | None = None
|
|
161
|
+
updated_at: datetime | None = None
|
|
162
|
+
|
|
163
|
+
model_config = ConfigDict(from_attributes=True, extra="ignore")
|
|
164
|
+
|
|
165
|
+
@property
|
|
166
|
+
def duration(self) -> str | None:
|
|
167
|
+
"""Calculate the duration of the run.
|
|
168
|
+
|
|
169
|
+
Returns:
|
|
170
|
+
Formatted duration string (HH:MM:SS) or None if incomplete
|
|
171
|
+
"""
|
|
172
|
+
if self.started_at and self.completed_at:
|
|
173
|
+
delta = self.completed_at - self.started_at
|
|
174
|
+
total_seconds = int(delta.total_seconds())
|
|
175
|
+
hours, remainder = divmod(total_seconds, 3600)
|
|
176
|
+
minutes, seconds = divmod(remainder, 60)
|
|
177
|
+
return f"{hours:02d}:{minutes:02d}:{seconds:02d}"
|
|
178
|
+
return None
|
|
179
|
+
|
|
180
|
+
def __repr__(self) -> str:
|
|
181
|
+
"""Return a readable representation of the run."""
|
|
182
|
+
parts = [f"ScheduleRunResponse(id={self.id!r}"]
|
|
183
|
+
parts.append(f"status={self.status!r}")
|
|
184
|
+
if self.started_at:
|
|
185
|
+
parts.append(f"started_at={self.started_at.isoformat()!r}")
|
|
186
|
+
if self.duration:
|
|
187
|
+
parts.append(f"duration={self.duration!r}")
|
|
188
|
+
return ", ".join(parts) + ")"
|
|
189
|
+
|
|
190
|
+
def __str__(self) -> str:
|
|
191
|
+
"""Return a readable string representation."""
|
|
192
|
+
return self.__repr__()
|
|
193
|
+
|
|
194
|
+
|
|
195
|
+
class ScheduleRunResult(BaseModel):
|
|
196
|
+
"""Full output payload for a schedule run.
|
|
197
|
+
|
|
198
|
+
Maps to the backend's AgentRunWithOutputResponse which includes
|
|
199
|
+
run metadata plus the output stream.
|
|
200
|
+
"""
|
|
201
|
+
|
|
202
|
+
id: str
|
|
203
|
+
agent_id: str
|
|
204
|
+
schedule_id: str | None = None
|
|
205
|
+
status: RunStatus
|
|
206
|
+
run_type: str | None = None
|
|
207
|
+
started_at: datetime | None = None
|
|
208
|
+
completed_at: datetime | None = None
|
|
209
|
+
input: str | None = None # Input used for the execution.
|
|
210
|
+
config: ScheduleConfig | dict[str, str] | None = None # Schedule config used.
|
|
211
|
+
output: list[ScheduleRunOutputChunk] | None = None
|
|
212
|
+
created_at: datetime | None = None
|
|
213
|
+
updated_at: datetime | None = None
|
|
214
|
+
|
|
215
|
+
model_config = ConfigDict(from_attributes=True, extra="ignore")
|
|
216
|
+
|
|
217
|
+
def __repr__(self) -> str:
|
|
218
|
+
"""Return a readable representation of the result."""
|
|
219
|
+
output_count = len(self.output) if self.output else 0
|
|
220
|
+
return f"ScheduleRunResult(id={self.id!r}, status={self.status!r}, output_chunks={output_count})"
|
|
221
|
+
|
|
222
|
+
def __str__(self) -> str:
|
|
223
|
+
"""Return a readable string representation."""
|
|
224
|
+
return self.__repr__()
|
|
@@ -57,6 +57,7 @@ AGENT_FIELD_RULES: Mapping[str, FieldRule] = {
|
|
|
57
57
|
"timeout": FieldRule(cli_managed_create=True, cli_managed_update=True),
|
|
58
58
|
# Fields requiring sanitisation before sending to the API
|
|
59
59
|
"agent_config": FieldRule(requires_sanitization=True),
|
|
60
|
+
"guardrail": FieldRule(requires_sanitization=True),
|
|
60
61
|
}
|
|
61
62
|
|
|
62
63
|
|