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
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
"""Agent response model for AIP SDK.
|
|
2
|
+
|
|
3
|
+
This module contains the Pydantic model for Agent API responses.
|
|
4
|
+
This is a pure data model with no runtime behavior.
|
|
5
|
+
|
|
6
|
+
For the runtime Agent class with deploy/run methods, use glaip_sdk.agents.Agent.
|
|
7
|
+
|
|
8
|
+
Authors:
|
|
9
|
+
Raymond Christopher (raymond.christopher@gdplabs.id)
|
|
10
|
+
Christian Trisno Sen Long Chen (christian.t.s.l.chen@gdplabs.id)
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
from datetime import datetime
|
|
14
|
+
from typing import Any
|
|
15
|
+
|
|
16
|
+
from pydantic import BaseModel
|
|
17
|
+
|
|
18
|
+
from glaip_sdk.config.constants import DEFAULT_AGENT_RUN_TIMEOUT
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class AgentResponse(BaseModel):
|
|
22
|
+
"""Pydantic model for Agent API responses.
|
|
23
|
+
|
|
24
|
+
This is a pure data model for deserializing API responses.
|
|
25
|
+
It does NOT have runtime methods (run, update, delete).
|
|
26
|
+
|
|
27
|
+
For the runtime Agent class, use glaip_sdk.agents.Agent.
|
|
28
|
+
"""
|
|
29
|
+
|
|
30
|
+
id: str
|
|
31
|
+
name: str
|
|
32
|
+
instruction: str | None = None
|
|
33
|
+
description: str | None = None
|
|
34
|
+
type: str | None = None
|
|
35
|
+
framework: str | None = None
|
|
36
|
+
version: str | None = None
|
|
37
|
+
tools: list[dict[str, Any]] | None = None
|
|
38
|
+
agents: list[dict[str, Any]] | None = None
|
|
39
|
+
mcps: list[dict[str, Any]] | None = None
|
|
40
|
+
tool_configs: dict[str, Any] | None = None
|
|
41
|
+
mcp_configs: dict[str, Any] | None = None
|
|
42
|
+
agent_config: dict[str, Any] | None = None
|
|
43
|
+
timeout: int = DEFAULT_AGENT_RUN_TIMEOUT
|
|
44
|
+
metadata: dict[str, Any] | None = None
|
|
45
|
+
language_model_id: str | None = None
|
|
46
|
+
a2a_profile: dict[str, Any] | None = None
|
|
47
|
+
created_at: datetime | None = None
|
|
48
|
+
updated_at: datetime | None = None
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""Agent run models for AIP SDK.
|
|
3
|
+
|
|
4
|
+
Authors:
|
|
5
|
+
Raymond Christopher (raymond.christopher@gdplabs.id)
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from datetime import datetime, timedelta
|
|
9
|
+
from typing import Any, Literal
|
|
10
|
+
from uuid import UUID
|
|
11
|
+
|
|
12
|
+
from pydantic import BaseModel, Field, field_validator, model_validator
|
|
13
|
+
|
|
14
|
+
# Type alias for SSE event dictionaries
|
|
15
|
+
RunOutputChunk = dict[str, Any]
|
|
16
|
+
RunStatus = Literal["started", "success", "failed", "cancelled", "aborted", "unavailable"]
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class RunSummary(BaseModel):
|
|
20
|
+
"""Represents a single agent run in list/table views with metadata only."""
|
|
21
|
+
|
|
22
|
+
id: UUID
|
|
23
|
+
agent_id: UUID
|
|
24
|
+
run_type: Literal["manual", "schedule"]
|
|
25
|
+
schedule_id: UUID | None = None
|
|
26
|
+
status: RunStatus
|
|
27
|
+
started_at: datetime
|
|
28
|
+
completed_at: datetime | None = None
|
|
29
|
+
input: str | None = None
|
|
30
|
+
config: dict[str, Any] | None = None
|
|
31
|
+
created_at: datetime
|
|
32
|
+
updated_at: datetime
|
|
33
|
+
|
|
34
|
+
@field_validator("completed_at")
|
|
35
|
+
@classmethod
|
|
36
|
+
def validate_completed_after_started(cls, v: datetime | None, info) -> datetime | None:
|
|
37
|
+
"""Validate that completed_at is after started_at if present."""
|
|
38
|
+
if v is not None and "started_at" in info.data:
|
|
39
|
+
started_at = info.data["started_at"]
|
|
40
|
+
if v < started_at:
|
|
41
|
+
raise ValueError("completed_at must be after started_at")
|
|
42
|
+
return v
|
|
43
|
+
|
|
44
|
+
def duration(self) -> timedelta | None:
|
|
45
|
+
"""Calculate duration from started_at to completed_at.
|
|
46
|
+
|
|
47
|
+
Returns:
|
|
48
|
+
Duration as timedelta if completed_at exists, None otherwise
|
|
49
|
+
"""
|
|
50
|
+
if self.completed_at is not None:
|
|
51
|
+
return self.completed_at - self.started_at
|
|
52
|
+
return None
|
|
53
|
+
|
|
54
|
+
def duration_formatted(self) -> str:
|
|
55
|
+
"""Format duration as HH:MM:SS string.
|
|
56
|
+
|
|
57
|
+
Returns:
|
|
58
|
+
Formatted duration string or "—" if not completed
|
|
59
|
+
"""
|
|
60
|
+
duration = self.duration()
|
|
61
|
+
if duration is None:
|
|
62
|
+
return "—"
|
|
63
|
+
total_seconds = int(duration.total_seconds())
|
|
64
|
+
hours = total_seconds // 3600
|
|
65
|
+
minutes = (total_seconds % 3600) // 60
|
|
66
|
+
seconds = total_seconds % 60
|
|
67
|
+
return f"{hours:02d}:{minutes:02d}:{seconds:02d}"
|
|
68
|
+
|
|
69
|
+
def input_preview(self, max_length: int = 120) -> str:
|
|
70
|
+
"""Generate truncated input preview for table display.
|
|
71
|
+
|
|
72
|
+
Args:
|
|
73
|
+
max_length: Maximum length of preview string
|
|
74
|
+
|
|
75
|
+
Returns:
|
|
76
|
+
Truncated input string or "—" if input is None or empty
|
|
77
|
+
"""
|
|
78
|
+
if not self.input:
|
|
79
|
+
return "—"
|
|
80
|
+
# Strip newlines and collapse whitespace
|
|
81
|
+
preview = " ".join(self.input.split())
|
|
82
|
+
if len(preview) > max_length:
|
|
83
|
+
return preview[:max_length] + "…"
|
|
84
|
+
return preview
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
class RunsPage(BaseModel):
|
|
88
|
+
"""Represents a paginated collection of run summaries from the list endpoint."""
|
|
89
|
+
|
|
90
|
+
data: list[RunSummary]
|
|
91
|
+
total: int = Field(ge=0)
|
|
92
|
+
page: int = Field(ge=1)
|
|
93
|
+
limit: int = Field(ge=1, le=100)
|
|
94
|
+
has_next: bool
|
|
95
|
+
has_prev: bool
|
|
96
|
+
|
|
97
|
+
@model_validator(mode="after")
|
|
98
|
+
def validate_pagination_consistency(self) -> "RunsPage":
|
|
99
|
+
"""Validate pagination consistency."""
|
|
100
|
+
# If has_next is True, then page * limit < total
|
|
101
|
+
if self.has_next and self.page * self.limit >= self.total:
|
|
102
|
+
raise ValueError("has_next inconsistency: page * limit must be < total when has_next is True")
|
|
103
|
+
return self
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
class RunWithOutput(RunSummary):
|
|
107
|
+
"""Extends RunSummary with the complete SSE event stream for detailed viewing."""
|
|
108
|
+
|
|
109
|
+
output: list[RunOutputChunk] = Field(default_factory=list)
|
|
110
|
+
|
|
111
|
+
@field_validator("output", mode="before")
|
|
112
|
+
@classmethod
|
|
113
|
+
def normalize_output(cls, v: Any) -> list[RunOutputChunk]:
|
|
114
|
+
"""Normalize output field to empty list when null."""
|
|
115
|
+
if v is None:
|
|
116
|
+
return []
|
|
117
|
+
return v
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
"""Common models for AIP SDK.
|
|
2
|
+
|
|
3
|
+
This module contains common models that don't fit into specific categories.
|
|
4
|
+
|
|
5
|
+
Authors:
|
|
6
|
+
Raymond Christopher (raymond.christopher@gdplabs.id)
|
|
7
|
+
Christian Trisno Sen Long Chen (christian.t.s.l.chen@gdplabs.id)
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from pydantic import BaseModel
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class LanguageModelResponse(BaseModel):
|
|
14
|
+
"""Language model response model."""
|
|
15
|
+
|
|
16
|
+
name: str
|
|
17
|
+
provider: str
|
|
18
|
+
description: str | None = None
|
|
19
|
+
capabilities: list[str] | None = None
|
|
20
|
+
max_tokens: int | None = None
|
|
21
|
+
supports_streaming: bool = False
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class TTYRenderer:
|
|
25
|
+
"""Simple TTY renderer for non-Rich environments."""
|
|
26
|
+
|
|
27
|
+
def __init__(self, use_color: bool = True):
|
|
28
|
+
"""Initialize the TTY renderer.
|
|
29
|
+
|
|
30
|
+
Args:
|
|
31
|
+
use_color: Whether to use color output
|
|
32
|
+
"""
|
|
33
|
+
self.use_color = use_color
|
|
34
|
+
|
|
35
|
+
def render_message(self, message: str, event_type: str = "message") -> None:
|
|
36
|
+
"""Render a message with optional color."""
|
|
37
|
+
if event_type == "error":
|
|
38
|
+
print(f"ERROR: {message}", flush=True)
|
|
39
|
+
elif event_type == "done":
|
|
40
|
+
print(f"\n✅ {message}", flush=True)
|
|
41
|
+
else:
|
|
42
|
+
print(message, flush=True)
|
|
@@ -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
|
glaip_sdk/models/mcp.py
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
"""MCP response model for AIP SDK.
|
|
2
|
+
|
|
3
|
+
This module contains the Pydantic model for MCP API responses.
|
|
4
|
+
This is a pure data model with no runtime behavior.
|
|
5
|
+
|
|
6
|
+
For the runtime MCP class with update/delete methods, use glaip_sdk.mcps.MCP.
|
|
7
|
+
|
|
8
|
+
Authors:
|
|
9
|
+
Raymond Christopher (raymond.christopher@gdplabs.id)
|
|
10
|
+
Christian Trisno Sen Long Chen (christian.t.s.l.chen@gdplabs.id)
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
from typing import Any
|
|
14
|
+
|
|
15
|
+
from pydantic import BaseModel
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class MCPResponse(BaseModel):
|
|
19
|
+
"""Pydantic model for MCP API responses.
|
|
20
|
+
|
|
21
|
+
This is a pure data model for deserializing API responses.
|
|
22
|
+
It does NOT have runtime methods (update, delete, get_tools).
|
|
23
|
+
|
|
24
|
+
For the runtime MCP class, use glaip_sdk.mcps.MCP.
|
|
25
|
+
"""
|
|
26
|
+
|
|
27
|
+
id: str
|
|
28
|
+
name: str
|
|
29
|
+
description: str | None = None
|
|
30
|
+
config: dict[str, Any] | None = None
|
|
31
|
+
transport: str | None = None # "sse" or "http"
|
|
32
|
+
authentication: dict[str, Any] | None = None
|
|
33
|
+
metadata: dict[str, Any] | None = None
|
|
@@ -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
|
+
)
|