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,439 @@
|
|
|
1
|
+
"""Schedule client for AIP SDK.
|
|
2
|
+
|
|
3
|
+
Authors:
|
|
4
|
+
Christian Trisno Sen Long Chen (christian.t.s.l.chen@gdplabs.id)
|
|
5
|
+
Putu Ravindra Wiguna (putu.r.wiguna@gdplabs.id)
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from typing import TYPE_CHECKING, Any
|
|
9
|
+
|
|
10
|
+
from glaip_sdk.client._schedule_payloads import ScheduleListParams, normalize_schedule
|
|
11
|
+
from glaip_sdk.client.base import BaseClient
|
|
12
|
+
from glaip_sdk.exceptions import APIError, NotFoundError
|
|
13
|
+
from glaip_sdk.models.agent_runs import RunStatus
|
|
14
|
+
from glaip_sdk.models.schedule import (
|
|
15
|
+
ScheduleConfig,
|
|
16
|
+
ScheduleResponse,
|
|
17
|
+
ScheduleRunResponse,
|
|
18
|
+
ScheduleRunResult,
|
|
19
|
+
)
|
|
20
|
+
from glaip_sdk.schedules import (
|
|
21
|
+
Schedule,
|
|
22
|
+
ScheduleListResult,
|
|
23
|
+
ScheduleRun,
|
|
24
|
+
ScheduleRunListResult,
|
|
25
|
+
)
|
|
26
|
+
|
|
27
|
+
if TYPE_CHECKING:
|
|
28
|
+
from glaip_sdk.models import Agent
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
class ScheduleClient(BaseClient):
|
|
32
|
+
"""Client for managing agent schedules.
|
|
33
|
+
|
|
34
|
+
Provides CRUD operations for scheduled agent executions.
|
|
35
|
+
Schedules allow agents to run automatically at specified times
|
|
36
|
+
using cron-like configurations.
|
|
37
|
+
|
|
38
|
+
Example:
|
|
39
|
+
>>> from glaip_sdk import Client
|
|
40
|
+
>>> from glaip_sdk.models.schedule import ScheduleConfig
|
|
41
|
+
>>>
|
|
42
|
+
>>> client = Client()
|
|
43
|
+
>>> # List all schedules
|
|
44
|
+
>>> result = client.schedules.list()
|
|
45
|
+
>>> for schedule in result:
|
|
46
|
+
... print(f"{schedule.id}: {schedule.next_run_time}")
|
|
47
|
+
>>>
|
|
48
|
+
>>> # Get a specific schedule
|
|
49
|
+
>>> schedule = client.schedules.get("schedule-id")
|
|
50
|
+
>>>
|
|
51
|
+
>>> # Create a schedule for an agent
|
|
52
|
+
>>> schedule = client.schedules.create(
|
|
53
|
+
... agent_id="agent-id",
|
|
54
|
+
... input="Generate daily report",
|
|
55
|
+
... schedule=ScheduleConfig(minute="0", hour="9", day_of_week="1-5")
|
|
56
|
+
... )
|
|
57
|
+
>>>
|
|
58
|
+
>>> # Update a schedule
|
|
59
|
+
>>> schedule = client.schedules.update(
|
|
60
|
+
... schedule_id="schedule-id",
|
|
61
|
+
... input="Updated report input"
|
|
62
|
+
... )
|
|
63
|
+
>>>
|
|
64
|
+
>>> # Delete a schedule
|
|
65
|
+
>>> client.schedules.delete("schedule-id")
|
|
66
|
+
"""
|
|
67
|
+
|
|
68
|
+
def list(
|
|
69
|
+
self,
|
|
70
|
+
*,
|
|
71
|
+
limit: int | None = None,
|
|
72
|
+
page: int | None = None,
|
|
73
|
+
agent_id: str | None = None,
|
|
74
|
+
) -> ScheduleListResult:
|
|
75
|
+
"""List schedules with optional filtering and pagination.
|
|
76
|
+
|
|
77
|
+
Args:
|
|
78
|
+
limit: Maximum number of schedules to return (1-100)
|
|
79
|
+
page: Page number for pagination
|
|
80
|
+
agent_id: Filter schedules by agent ID
|
|
81
|
+
|
|
82
|
+
Returns:
|
|
83
|
+
ScheduleListResult containing schedules and pagination metadata
|
|
84
|
+
"""
|
|
85
|
+
params = ScheduleListParams(limit=limit, page=page, agent_id=agent_id)
|
|
86
|
+
|
|
87
|
+
response = self._request_with_envelope(
|
|
88
|
+
"GET",
|
|
89
|
+
"/agents/schedules",
|
|
90
|
+
params=params.to_query_params(),
|
|
91
|
+
)
|
|
92
|
+
|
|
93
|
+
# Parse schedules from response data
|
|
94
|
+
schedules = [
|
|
95
|
+
Schedule.from_response(ScheduleResponse.model_validate(item), client=self)
|
|
96
|
+
for item in (response.get("data") or [])
|
|
97
|
+
]
|
|
98
|
+
|
|
99
|
+
return ScheduleListResult(
|
|
100
|
+
items=schedules,
|
|
101
|
+
total=response.get("total"),
|
|
102
|
+
page=response.get("page"),
|
|
103
|
+
limit=response.get("limit"),
|
|
104
|
+
has_next=response.get("has_next"),
|
|
105
|
+
has_prev=response.get("has_prev"),
|
|
106
|
+
)
|
|
107
|
+
|
|
108
|
+
def get(self, schedule_id: str) -> Schedule:
|
|
109
|
+
"""Get a schedule by ID.
|
|
110
|
+
|
|
111
|
+
Args:
|
|
112
|
+
schedule_id: The schedule ID to retrieve
|
|
113
|
+
|
|
114
|
+
Returns:
|
|
115
|
+
Schedule instance
|
|
116
|
+
|
|
117
|
+
Raises:
|
|
118
|
+
NotFoundError: If schedule is not found
|
|
119
|
+
AuthenticationError: If API key is invalid
|
|
120
|
+
APIError: If the API request fails
|
|
121
|
+
"""
|
|
122
|
+
data = self._request("GET", f"/agents/schedules/{schedule_id}")
|
|
123
|
+
|
|
124
|
+
if data is None:
|
|
125
|
+
raise NotFoundError(f"Schedule not found: {schedule_id}")
|
|
126
|
+
return Schedule.from_response(ScheduleResponse.model_validate(data), client=self)
|
|
127
|
+
|
|
128
|
+
def create(
|
|
129
|
+
self,
|
|
130
|
+
*,
|
|
131
|
+
agent_id: str,
|
|
132
|
+
input: str,
|
|
133
|
+
schedule: ScheduleConfig | dict[str, str] | str,
|
|
134
|
+
) -> Schedule:
|
|
135
|
+
"""Create a new schedule for an agent.
|
|
136
|
+
|
|
137
|
+
Args:
|
|
138
|
+
agent_id: The agent ID to schedule
|
|
139
|
+
input: Input text for scheduled execution
|
|
140
|
+
schedule: Schedule configuration (ScheduleConfig, dict, or cron string)
|
|
141
|
+
|
|
142
|
+
Returns:
|
|
143
|
+
Created Schedule instance
|
|
144
|
+
|
|
145
|
+
Raises:
|
|
146
|
+
ValueError: If schedule format is invalid
|
|
147
|
+
NotFoundError: If agent is not found
|
|
148
|
+
ValidationError: If schedule configuration is invalid
|
|
149
|
+
AuthenticationError: If API key is invalid
|
|
150
|
+
APIError: If the API request fails
|
|
151
|
+
"""
|
|
152
|
+
schedule_dict = normalize_schedule(schedule)
|
|
153
|
+
if schedule_dict is None:
|
|
154
|
+
raise ValueError("schedule is required")
|
|
155
|
+
|
|
156
|
+
payload = {
|
|
157
|
+
"input": input,
|
|
158
|
+
"schedule": schedule_dict,
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
response = self._request("POST", f"/agents/{agent_id}/schedule", json=payload)
|
|
162
|
+
|
|
163
|
+
# Response contains schedule_id, fetch the full schedule
|
|
164
|
+
schedule_id = response.get("schedule_id")
|
|
165
|
+
if not schedule_id:
|
|
166
|
+
raise APIError("Missing schedule_id in create response")
|
|
167
|
+
|
|
168
|
+
return self.get(schedule_id)
|
|
169
|
+
|
|
170
|
+
def update(
|
|
171
|
+
self,
|
|
172
|
+
schedule_id: str,
|
|
173
|
+
*,
|
|
174
|
+
input: str | None = None,
|
|
175
|
+
schedule: ScheduleConfig | dict[str, str] | str | None = None,
|
|
176
|
+
) -> Schedule:
|
|
177
|
+
"""Update an existing schedule.
|
|
178
|
+
|
|
179
|
+
Args:
|
|
180
|
+
schedule_id: The schedule ID to update
|
|
181
|
+
input: New input text for scheduled execution
|
|
182
|
+
schedule: New schedule configuration (ScheduleConfig, dict, or cron string)
|
|
183
|
+
|
|
184
|
+
Returns:
|
|
185
|
+
Updated Schedule instance
|
|
186
|
+
|
|
187
|
+
Raises:
|
|
188
|
+
NotFoundError: If schedule is not found
|
|
189
|
+
ValueError: If schedule config is required but not provided
|
|
190
|
+
ValidationError: If schedule configuration is invalid
|
|
191
|
+
AuthenticationError: If API key is invalid
|
|
192
|
+
APIError: If the API request fails
|
|
193
|
+
|
|
194
|
+
Note:
|
|
195
|
+
Updates use explicit replacement (not merge). The SDK normalizes partial
|
|
196
|
+
schedule dicts by filling missing cron fields with "*". This is intentional
|
|
197
|
+
for predictability - what you provide is what you get (plus wildcard defaults).
|
|
198
|
+
If the current schedule metadata is missing and no schedule parameter is
|
|
199
|
+
provided, a ValueError is raised.
|
|
200
|
+
"""
|
|
201
|
+
# Get current schedule to merge with updates
|
|
202
|
+
current = self.get(schedule_id)
|
|
203
|
+
|
|
204
|
+
# Handle input - ensure we have valid input data
|
|
205
|
+
if current.input is None and input is None:
|
|
206
|
+
raise ValueError(
|
|
207
|
+
f"Schedule {schedule_id} has missing input metadata and no input parameter provided. "
|
|
208
|
+
"Please provide an input value to update this schedule."
|
|
209
|
+
)
|
|
210
|
+
|
|
211
|
+
# Handle schedule config - ensure we have complete schedule data
|
|
212
|
+
if current.schedule_config is None and schedule is None:
|
|
213
|
+
raise ValueError(
|
|
214
|
+
f"Schedule {schedule_id} has missing metadata and no schedule parameter provided. "
|
|
215
|
+
"Please provide a full schedule configuration to update this schedule."
|
|
216
|
+
)
|
|
217
|
+
|
|
218
|
+
current_input = current.input or ""
|
|
219
|
+
current_schedule = current.schedule_config.model_dump() if current.schedule_config else {}
|
|
220
|
+
|
|
221
|
+
payload: dict[str, Any] = {
|
|
222
|
+
"input": input if input is not None else current_input,
|
|
223
|
+
"schedule": normalize_schedule(schedule) or current_schedule,
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
data = self._request("PUT", f"/agents/schedules/{schedule_id}", json=payload)
|
|
227
|
+
return Schedule.from_response(ScheduleResponse.model_validate(data), client=self)
|
|
228
|
+
|
|
229
|
+
def delete(self, schedule_id: str) -> None:
|
|
230
|
+
"""Delete a schedule.
|
|
231
|
+
|
|
232
|
+
Args:
|
|
233
|
+
schedule_id: The schedule ID to delete
|
|
234
|
+
|
|
235
|
+
Raises:
|
|
236
|
+
NotFoundError: If schedule is not found
|
|
237
|
+
AuthenticationError: If API key is invalid
|
|
238
|
+
APIError: If the API request fails
|
|
239
|
+
"""
|
|
240
|
+
self._request("DELETE", f"/agents/schedules/{schedule_id}")
|
|
241
|
+
|
|
242
|
+
def list_runs(
|
|
243
|
+
self,
|
|
244
|
+
agent_id: str,
|
|
245
|
+
*,
|
|
246
|
+
schedule_id: str | None = None,
|
|
247
|
+
status: RunStatus | None = None,
|
|
248
|
+
limit: int | None = None,
|
|
249
|
+
page: int | None = None,
|
|
250
|
+
) -> ScheduleRunListResult:
|
|
251
|
+
"""List runs for an agent, optionally filtered by schedule ID.
|
|
252
|
+
|
|
253
|
+
Args:
|
|
254
|
+
agent_id: The agent ID to list runs for
|
|
255
|
+
schedule_id: Optional schedule ID to filter by
|
|
256
|
+
status: Optional status filter
|
|
257
|
+
limit: Maximum number of runs to return (1-100)
|
|
258
|
+
page: Page number for pagination
|
|
259
|
+
|
|
260
|
+
Returns:
|
|
261
|
+
ScheduleRunListResult containing runs and pagination metadata
|
|
262
|
+
"""
|
|
263
|
+
params: dict[str, Any] = {"run_type": "schedule"}
|
|
264
|
+
if schedule_id is not None:
|
|
265
|
+
params["schedule_id"] = schedule_id
|
|
266
|
+
if status is not None:
|
|
267
|
+
params["status"] = status
|
|
268
|
+
if limit is not None:
|
|
269
|
+
params["limit"] = limit
|
|
270
|
+
if page is not None:
|
|
271
|
+
params["page"] = page
|
|
272
|
+
|
|
273
|
+
response = self._request_with_envelope(
|
|
274
|
+
"GET",
|
|
275
|
+
f"/agents/{agent_id}/runs",
|
|
276
|
+
params=params,
|
|
277
|
+
)
|
|
278
|
+
|
|
279
|
+
# Parse runs from response data
|
|
280
|
+
runs = [
|
|
281
|
+
ScheduleRun.from_response(ScheduleRunResponse.model_validate(item), client=self)
|
|
282
|
+
for item in (response.get("data") or [])
|
|
283
|
+
]
|
|
284
|
+
|
|
285
|
+
return ScheduleRunListResult(
|
|
286
|
+
items=runs,
|
|
287
|
+
total=response.get("total"),
|
|
288
|
+
page=response.get("page"),
|
|
289
|
+
limit=response.get("limit"),
|
|
290
|
+
has_next=response.get("has_next"),
|
|
291
|
+
has_prev=response.get("has_prev"),
|
|
292
|
+
)
|
|
293
|
+
|
|
294
|
+
def get_run_result(self, agent_id: str, run_id: str) -> ScheduleRunResult:
|
|
295
|
+
"""Get the full output payload for an agent run.
|
|
296
|
+
|
|
297
|
+
Args:
|
|
298
|
+
agent_id: The agent ID the run belongs to
|
|
299
|
+
run_id: The run ID to retrieve
|
|
300
|
+
|
|
301
|
+
Returns:
|
|
302
|
+
ScheduleRunResult containing run details and optional output
|
|
303
|
+
"""
|
|
304
|
+
data = self._request("GET", f"/agents/{agent_id}/runs/{run_id}")
|
|
305
|
+
return ScheduleRunResult.model_validate(data)
|
|
306
|
+
|
|
307
|
+
|
|
308
|
+
class AgentScheduleManager:
|
|
309
|
+
"""Facade for agent-scoped schedule operations.
|
|
310
|
+
|
|
311
|
+
Provides a convenient interface for managing schedules through
|
|
312
|
+
an Agent instance, automatically scoping operations to that agent.
|
|
313
|
+
|
|
314
|
+
Example:
|
|
315
|
+
>>> agent = client.get_agent_by_id("agent-id")
|
|
316
|
+
>>> # List schedules for this agent
|
|
317
|
+
>>> schedules = agent.schedule.list()
|
|
318
|
+
>>> # Create a schedule for this agent
|
|
319
|
+
>>> schedule = agent.schedule.create(
|
|
320
|
+
... input="Daily task",
|
|
321
|
+
... schedule="0 9 * * 1-5"
|
|
322
|
+
... )
|
|
323
|
+
"""
|
|
324
|
+
|
|
325
|
+
def __init__(self, agent: "Agent", client: ScheduleClient) -> None:
|
|
326
|
+
"""Initialize the schedule manager.
|
|
327
|
+
|
|
328
|
+
Args:
|
|
329
|
+
agent: The agent to manage schedules for
|
|
330
|
+
client: The ScheduleClient for API operations
|
|
331
|
+
"""
|
|
332
|
+
self._agent = agent
|
|
333
|
+
self._client = client
|
|
334
|
+
|
|
335
|
+
def list(
|
|
336
|
+
self,
|
|
337
|
+
*,
|
|
338
|
+
limit: int | None = None,
|
|
339
|
+
page: int | None = None,
|
|
340
|
+
) -> ScheduleListResult:
|
|
341
|
+
"""List schedules for this agent.
|
|
342
|
+
|
|
343
|
+
Args:
|
|
344
|
+
limit: Maximum number of schedules to return (1-100)
|
|
345
|
+
page: Page number for pagination
|
|
346
|
+
|
|
347
|
+
Returns:
|
|
348
|
+
ScheduleListResult containing schedules for this agent
|
|
349
|
+
"""
|
|
350
|
+
return self._client.list(limit=limit, page=page, agent_id=self._agent.id)
|
|
351
|
+
|
|
352
|
+
def create(
|
|
353
|
+
self,
|
|
354
|
+
*,
|
|
355
|
+
input: str,
|
|
356
|
+
schedule: ScheduleConfig | dict[str, str] | str,
|
|
357
|
+
) -> Schedule:
|
|
358
|
+
"""Create a schedule for this agent.
|
|
359
|
+
|
|
360
|
+
Args:
|
|
361
|
+
input: Input text for scheduled execution
|
|
362
|
+
schedule: Schedule configuration (ScheduleConfig, dict, or cron string)
|
|
363
|
+
|
|
364
|
+
Returns:
|
|
365
|
+
Created Schedule instance
|
|
366
|
+
"""
|
|
367
|
+
return self._client.create(
|
|
368
|
+
agent_id=self._agent.id,
|
|
369
|
+
input=input,
|
|
370
|
+
schedule=schedule,
|
|
371
|
+
)
|
|
372
|
+
|
|
373
|
+
def get(self, schedule_id: str) -> Schedule:
|
|
374
|
+
"""Get a schedule by ID.
|
|
375
|
+
|
|
376
|
+
Args:
|
|
377
|
+
schedule_id: The schedule ID to retrieve
|
|
378
|
+
|
|
379
|
+
Returns:
|
|
380
|
+
Schedule instance
|
|
381
|
+
|
|
382
|
+
Raises:
|
|
383
|
+
NotFoundError: If schedule is not found
|
|
384
|
+
"""
|
|
385
|
+
return self._client.get(schedule_id)
|
|
386
|
+
|
|
387
|
+
def update(
|
|
388
|
+
self,
|
|
389
|
+
schedule_id: str,
|
|
390
|
+
*,
|
|
391
|
+
input: str | None = None,
|
|
392
|
+
schedule: ScheduleConfig | dict[str, str] | str | None = None,
|
|
393
|
+
) -> Schedule:
|
|
394
|
+
"""Update a schedule.
|
|
395
|
+
|
|
396
|
+
Args:
|
|
397
|
+
schedule_id: The schedule ID to update
|
|
398
|
+
input: New input text for scheduled execution
|
|
399
|
+
schedule: New schedule configuration
|
|
400
|
+
|
|
401
|
+
Returns:
|
|
402
|
+
Updated Schedule instance
|
|
403
|
+
"""
|
|
404
|
+
return self._client.update(schedule_id, input=input, schedule=schedule)
|
|
405
|
+
|
|
406
|
+
def delete(self, schedule_id: str) -> None:
|
|
407
|
+
"""Delete a schedule.
|
|
408
|
+
|
|
409
|
+
Args:
|
|
410
|
+
schedule_id: The schedule ID to delete
|
|
411
|
+
"""
|
|
412
|
+
self._client.delete(schedule_id)
|
|
413
|
+
|
|
414
|
+
def list_runs(
|
|
415
|
+
self,
|
|
416
|
+
schedule_id: str | None = None,
|
|
417
|
+
*,
|
|
418
|
+
status: RunStatus | None = None,
|
|
419
|
+
limit: int | None = None,
|
|
420
|
+
page: int | None = None,
|
|
421
|
+
) -> ScheduleRunListResult:
|
|
422
|
+
"""List runs for this agent.
|
|
423
|
+
|
|
424
|
+
Args:
|
|
425
|
+
schedule_id: Optional schedule ID to filter by
|
|
426
|
+
status: Optional status filter
|
|
427
|
+
limit: Maximum number of runs to return (1-100)
|
|
428
|
+
page: Page number for pagination
|
|
429
|
+
|
|
430
|
+
Returns:
|
|
431
|
+
ScheduleRunListResult containing runs for this agent
|
|
432
|
+
"""
|
|
433
|
+
return self._client.list_runs(
|
|
434
|
+
self._agent.id,
|
|
435
|
+
schedule_id=schedule_id,
|
|
436
|
+
status=status,
|
|
437
|
+
limit=limit,
|
|
438
|
+
page=page,
|
|
439
|
+
)
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"""Shared helpers for client configuration wiring.
|
|
2
|
+
|
|
3
|
+
Authors:
|
|
4
|
+
Raymond Christopher (raymond.christopher@gdplabs.id)
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
from typing import Any
|
|
10
|
+
|
|
11
|
+
from glaip_sdk.client.base import BaseClient
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def build_shared_config(client: BaseClient) -> dict[str, Any]:
|
|
15
|
+
"""Return the keyword arguments used to initialize sub-clients."""
|
|
16
|
+
return {
|
|
17
|
+
"parent_client": client,
|
|
18
|
+
"api_url": client.api_url,
|
|
19
|
+
"api_key": client.api_key,
|
|
20
|
+
"timeout": client._timeout,
|
|
21
|
+
}
|