diff --git a/.stats.yml b/.stats.yml index 60af41b79..d91ae254d 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ -configured_endpoints: 65 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/sgp/agentex-sdk-cd43ba4b554ca024dd7ee7b74e4f4700a743282c17def704a0967e6ff251c09b.yml -openapi_spec_hash: 9369ccc9c0289e9d6f641a526d244d1c -config_hash: 1ae003838971335aac550f3ad5872f54 +configured_endpoints: 72 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/sgp/agentex-sdk-ad493b43ecb1652a9e522451c616e33775e628c1d79c224dff34855bd82c8c7c.yml +openapi_spec_hash: 77044dc5774eb88f1541ebbe53b413a7 +config_hash: 50803c6c42bb738099163f3f4d3cdeed diff --git a/README.md b/README.md index 2233ae76f..cfe1611d8 100644 --- a/README.md +++ b/README.md @@ -139,6 +139,23 @@ Nested request parameters are [TypedDicts](https://docs.python.org/3/library/typ Typed requests and responses provide autocomplete and documentation within your editor. If you would like to see type errors in VS Code to help catch bugs earlier, set `python.analysis.typeCheckingMode` to `basic`. +## Nested params + +Nested parameters are dictionaries, typed using `TypedDict`, for example: + +```python +from agentex import Agentex + +client = Agentex() + +schedule = client.agents.schedules.create( + agent_id="agent_id", + initial_input={"content": "content"}, + name="name", +) +print(schedule.initial_input) +``` + ## Handling errors When the library is unable to connect to the API (for example, due to network connection problems or a timeout), a subclass of `agentex.APIConnectionError` is raised. diff --git a/adk/pyproject.toml b/adk/pyproject.toml index 183d2999a..d8968334e 100644 --- a/adk/pyproject.toml +++ b/adk/pyproject.toml @@ -41,7 +41,14 @@ dependencies = [ # LLM provider integrations "litellm>=1.83.7,<2", "openai-agents>=0.14.3,<0.15", - "openai>=2.2,<3", # Required by openai-agents; litellm now supports openai 2.x (issue #13711 resolved: https://github.com/BerriAI/litellm/issues/13711) + # Cap <2.45: openai 2.45.0 makes InputTokensDetails.cache_write_tokens a + # required field, but openai-agents 0.14.x still builds + # InputTokensDetails(cached_tokens=0) (agents/usage.py), so every + # Runner.run_streamed raises a pydantic ValidationError at context setup. + # openai-agents 0.14.8 is the latest release, so there is no newer version + # to bump to; drop this ceiling once openai-agents ships a fix. + # litellm now supports openai 2.x (issue #13711 resolved: https://github.com/BerriAI/litellm/issues/13711) + "openai>=2.2,<2.45", "claude-agent-sdk>=0.1.0", "pydantic-ai-slim>=1.0,<2", "langgraph-checkpoint>=2.0.0", diff --git a/api.md b/api.md index 7c1b4eb68..f313dd62a 100644 --- a/api.md +++ b/api.md @@ -69,22 +69,35 @@ Types: from agentex.types.agents import ( ScheduleCreateResponse, ScheduleRetrieveResponse, + ScheduleUpdateResponse, ScheduleListResponse, SchedulePauseResponse, + SchedulePauseByNameResponse, + ScheduleResumeResponse, + ScheduleResumeByNameResponse, + ScheduleRetrieveByNameResponse, ScheduleTriggerResponse, - ScheduleUnpauseResponse, + ScheduleTriggerByNameResponse, + ScheduleUpdateByNameResponse, ) ``` Methods: - client.agents.schedules.create(agent_id, \*\*params) -> ScheduleCreateResponse -- client.agents.schedules.retrieve(schedule_name, \*, agent_id) -> ScheduleRetrieveResponse +- client.agents.schedules.retrieve(schedule_id, \*, agent_id) -> ScheduleRetrieveResponse +- client.agents.schedules.update(schedule_id, \*, agent_id, \*\*params) -> ScheduleUpdateResponse - client.agents.schedules.list(agent_id, \*\*params) -> ScheduleListResponse -- client.agents.schedules.delete(schedule_name, \*, agent_id) -> DeleteResponse -- client.agents.schedules.pause(schedule_name, \*, agent_id, \*\*params) -> SchedulePauseResponse -- client.agents.schedules.trigger(schedule_name, \*, agent_id) -> ScheduleTriggerResponse -- client.agents.schedules.unpause(schedule_name, \*, agent_id, \*\*params) -> ScheduleUnpauseResponse +- client.agents.schedules.delete(schedule_id, \*, agent_id) -> DeleteResponse +- client.agents.schedules.delete_by_name(name, \*, agent_id) -> DeleteResponse +- client.agents.schedules.pause(schedule_id, \*, agent_id, \*\*params) -> SchedulePauseResponse +- client.agents.schedules.pause_by_name(name, \*, agent_id, \*\*params) -> SchedulePauseByNameResponse +- client.agents.schedules.resume(schedule_id, \*, agent_id, \*\*params) -> ScheduleResumeResponse +- client.agents.schedules.resume_by_name(name, \*, agent_id, \*\*params) -> ScheduleResumeByNameResponse +- client.agents.schedules.retrieve_by_name(name, \*, agent_id) -> ScheduleRetrieveByNameResponse +- client.agents.schedules.trigger(schedule_id, \*, agent_id) -> ScheduleTriggerResponse +- client.agents.schedules.trigger_by_name(name, \*, agent_id) -> ScheduleTriggerByNameResponse +- client.agents.schedules.update_by_name(path_name, \*, agent_id, \*\*params) -> ScheduleUpdateByNameResponse # Tasks diff --git a/src/agentex/lib/core/tracing/processors/sgp_tracing_processor.py b/src/agentex/lib/core/tracing/processors/sgp_tracing_processor.py index 627b34d7b..6d186de5f 100644 --- a/src/agentex/lib/core/tracing/processors/sgp_tracing_processor.py +++ b/src/agentex/lib/core/tracing/processors/sgp_tracing_processor.py @@ -15,6 +15,7 @@ from agentex.lib.utils.logging import make_logger from agentex.lib.core.observability import tracing_metrics_recording as _metrics from agentex.lib.environment_variables import EnvironmentVariables +from agentex.lib.core.tracing.span_error import get_span_error from agentex.lib.core.tracing.processors.tracing_processor_interface import ( SyncTracingProcessor, AsyncTracingProcessor, @@ -83,6 +84,9 @@ def _build_sgp_span(span: Span, env_vars: EnvironmentVariables) -> SGPSpan: ), ) sgp_span.start_time = span.start_time.isoformat() # type: ignore[union-attr] + error = get_span_error(span) + if error is not None: + sgp_span.set_error(error_type=error["type"], error_message=error["message"]) return sgp_span diff --git a/src/agentex/lib/core/tracing/span_error.py b/src/agentex/lib/core/tracing/span_error.py new file mode 100644 index 000000000..508c5e800 --- /dev/null +++ b/src/agentex/lib/core/tracing/span_error.py @@ -0,0 +1,36 @@ +from __future__ import annotations + +from typing import Any + +from agentex.types.span import Span + +# Reserved key under ``Span.data`` carrying failure info for a span whose +# context-manager body raised. Mirrors the existing ``__span_type__`` / +# ``__source__`` reserved-key convention already read/written by the SGP +# processor. Stored in ``data`` because the Span model is generated from the +# OpenAPI spec and has no first-class status/error field; ``data`` is a real +# field, so it survives ``model_copy(deep=True)`` and round-trips to both the +# SGP and agentex-native span stores. +SPAN_ERROR_KEY = "__error__" + + +def set_span_error(span: Span, exc: BaseException) -> None: + """Record an exception on ``span`` under ``data[SPAN_ERROR_KEY]``. + + No-op when ``span.data`` is a list (matching ``_add_source_to_span``, which + only attaches metadata to dict-shaped data). + """ + error = {"type": type(exc).__name__, "message": str(exc)} + if span.data is None: + span.data = {} + if isinstance(span.data, dict): + span.data[SPAN_ERROR_KEY] = error + + +def get_span_error(span: Span) -> dict[str, Any] | None: + """Return the error recorded by :func:`set_span_error`, or ``None``.""" + if isinstance(span.data, dict): + value = span.data.get(SPAN_ERROR_KEY) + if isinstance(value, dict): + return value + return None diff --git a/src/agentex/lib/core/tracing/trace.py b/src/agentex/lib/core/tracing/trace.py index 70b268b18..a22bfd658 100644 --- a/src/agentex/lib/core/tracing/trace.py +++ b/src/agentex/lib/core/tracing/trace.py @@ -11,6 +11,7 @@ from agentex.types.span import Span from agentex.lib.utils.logging import make_logger from agentex.lib.utils.model_utils import recursive_model_dump +from agentex.lib.core.tracing.span_error import set_span_error from agentex.lib.core.tracing.span_queue import ( SpanEventType, AsyncSpanQueue, @@ -165,6 +166,9 @@ def span( span = self.start_span(name, parent_id, input, data, task_id=task_id) try: yield span + except Exception as exc: + set_span_error(span, exc) + raise finally: self.end_span(span) @@ -321,5 +325,8 @@ async def span( span = await self.start_span(name, parent_id, input, data, task_id=task_id) try: yield span + except Exception as exc: + set_span_error(span, exc) + raise finally: await self.end_span(span) diff --git a/src/agentex/resources/agents/schedules.py b/src/agentex/resources/agents/schedules.py index 271f6c835..a5c971322 100644 --- a/src/agentex/resources/agents/schedules.py +++ b/src/agentex/resources/agents/schedules.py @@ -18,14 +18,29 @@ async_to_streamed_response_wrapper, ) from ..._base_client import make_request_options -from ...types.agents import schedule_list_params, schedule_pause_params, schedule_create_params, schedule_unpause_params +from ...types.agents import ( + schedule_list_params, + schedule_pause_params, + schedule_create_params, + schedule_resume_params, + schedule_update_params, + schedule_pause_by_name_params, + schedule_resume_by_name_params, + schedule_update_by_name_params, +) from ...types.shared.delete_response import DeleteResponse from ...types.agents.schedule_list_response import ScheduleListResponse from ...types.agents.schedule_pause_response import SchedulePauseResponse from ...types.agents.schedule_create_response import ScheduleCreateResponse +from ...types.agents.schedule_resume_response import ScheduleResumeResponse +from ...types.agents.schedule_update_response import ScheduleUpdateResponse from ...types.agents.schedule_trigger_response import ScheduleTriggerResponse -from ...types.agents.schedule_unpause_response import ScheduleUnpauseResponse from ...types.agents.schedule_retrieve_response import ScheduleRetrieveResponse +from ...types.agents.schedule_pause_by_name_response import SchedulePauseByNameResponse +from ...types.agents.schedule_resume_by_name_response import ScheduleResumeByNameResponse +from ...types.agents.schedule_update_by_name_response import ScheduleUpdateByNameResponse +from ...types.agents.schedule_trigger_by_name_response import ScheduleTriggerByNameResponse +from ...types.agents.schedule_retrieve_by_name_response import ScheduleRetrieveByNameResponse __all__ = ["SchedulesResource", "AsyncSchedulesResource"] @@ -42,28 +57,724 @@ def with_raw_response(self) -> SchedulesResourceWithRawResponse: return SchedulesResourceWithRawResponse(self) @cached_property - def with_streaming_response(self) -> SchedulesResourceWithStreamingResponse: + def with_streaming_response(self) -> SchedulesResourceWithStreamingResponse: + """ + An alternative to `.with_raw_response` that doesn't eagerly read the response body. + + For more information, see https://www.github.com/scaleapi/scale-agentex-python#with_streaming_response + """ + return SchedulesResourceWithStreamingResponse(self) + + def create( + self, + agent_id: str, + *, + initial_input: schedule_create_params.InitialInput, + name: str, + cron_expression: Optional[str] | Omit = omit, + description: Optional[str] | Omit = omit, + end_at: Union[str, datetime, None] | Omit = omit, + interval_seconds: Optional[int] | Omit = omit, + paused: bool | Omit = omit, + start_at: Union[str, datetime, None] | Omit = omit, + task_metadata: Optional[Dict[str, object]] | Omit = omit, + task_params: Optional[Dict[str, object]] | Omit = omit, + timezone: str | Omit = omit, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> ScheduleCreateResponse: + """ + Create a recurring schedule that starts a fresh agent run on each fire. + + Args: + initial_input: The first input delivered to each created task. + + name: Human-readable name, unique among active schedules for the agent. + + cron_expression: Cron expression for the cadence (e.g. '0 17 \\** \\** MON-FRI'). Mutually exclusive + with interval_seconds. + + description: Optional description of what this schedule does. + + end_at: When the schedule should stop being active. + + interval_seconds: Interval cadence in seconds. Mutually exclusive with cron_expression. + + paused: Whether to create the schedule in a paused state. + + start_at: When the schedule should start being active. + + task_metadata: Metadata copied onto each created task at fire time. + + task_params: Resolved config forwarded as task `params` at fire time. + + timezone: IANA timezone the cron expression is evaluated in (e.g. 'America/New_York'). + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not agent_id: + raise ValueError(f"Expected a non-empty value for `agent_id` but received {agent_id!r}") + return self._post( + path_template("/agents/{agent_id}/schedules", agent_id=agent_id), + body=maybe_transform( + { + "initial_input": initial_input, + "name": name, + "cron_expression": cron_expression, + "description": description, + "end_at": end_at, + "interval_seconds": interval_seconds, + "paused": paused, + "start_at": start_at, + "task_metadata": task_metadata, + "task_params": task_params, + "timezone": timezone, + }, + schedule_create_params.ScheduleCreateParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=ScheduleCreateResponse, + ) + + def retrieve( + self, + schedule_id: str, + *, + agent_id: str, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> ScheduleRetrieveResponse: + """ + Get a run schedule by its id. + + Args: + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not agent_id: + raise ValueError(f"Expected a non-empty value for `agent_id` but received {agent_id!r}") + if not schedule_id: + raise ValueError(f"Expected a non-empty value for `schedule_id` but received {schedule_id!r}") + return self._get( + path_template("/agents/{agent_id}/schedules/{schedule_id}", agent_id=agent_id, schedule_id=schedule_id), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=ScheduleRetrieveResponse, + ) + + def update( + self, + schedule_id: str, + *, + agent_id: str, + cron_expression: Optional[str] | Omit = omit, + description: Optional[str] | Omit = omit, + end_at: Union[str, datetime, None] | Omit = omit, + initial_input: Optional[schedule_update_params.InitialInput] | Omit = omit, + interval_seconds: Optional[int] | Omit = omit, + name: Optional[str] | Omit = omit, + paused: Optional[bool] | Omit = omit, + start_at: Union[str, datetime, None] | Omit = omit, + task_metadata: Optional[Dict[str, object]] | Omit = omit, + task_params: Optional[Dict[str, object]] | Omit = omit, + timezone: Optional[str] | Omit = omit, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> ScheduleUpdateResponse: + """ + Partially update a run schedule's definition (cadence, window, input, etc.). + + Args: + cron_expression: New cron cadence. Mutually exclusive with interval_seconds. + + description: Optional description of what this schedule does. + + end_at: When the schedule should stop being active. + + initial_input: The first input delivered to each freshly created scheduled task. + + interval_seconds: New interval cadence in seconds. Mutually exclusive with cron_expression. + + name: Human-readable name, unique among active schedules for the agent. + + paused: Pause/resume the schedule as part of the update. + + start_at: When the schedule should start being active. + + task_metadata: Metadata copied onto each created task at fire time. + + task_params: Resolved config forwarded as task `params` at fire time. + + timezone: IANA timezone the cron expression is evaluated in. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not agent_id: + raise ValueError(f"Expected a non-empty value for `agent_id` but received {agent_id!r}") + if not schedule_id: + raise ValueError(f"Expected a non-empty value for `schedule_id` but received {schedule_id!r}") + return self._patch( + path_template("/agents/{agent_id}/schedules/{schedule_id}", agent_id=agent_id, schedule_id=schedule_id), + body=maybe_transform( + { + "cron_expression": cron_expression, + "description": description, + "end_at": end_at, + "initial_input": initial_input, + "interval_seconds": interval_seconds, + "name": name, + "paused": paused, + "start_at": start_at, + "task_metadata": task_metadata, + "task_params": task_params, + "timezone": timezone, + }, + schedule_update_params.ScheduleUpdateParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=ScheduleUpdateResponse, + ) + + def list( + self, + agent_id: str, + *, + limit: int | Omit = omit, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> ScheduleListResponse: + """ + List run schedules for an agent. + + Args: + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not agent_id: + raise ValueError(f"Expected a non-empty value for `agent_id` but received {agent_id!r}") + return self._get( + path_template("/agents/{agent_id}/schedules", agent_id=agent_id), + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=maybe_transform({"limit": limit}, schedule_list_params.ScheduleListParams), + ), + cast_to=ScheduleListResponse, + ) + + def delete( + self, + schedule_id: str, + *, + agent_id: str, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> DeleteResponse: + """ + Delete a run schedule permanently. + + Args: + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not agent_id: + raise ValueError(f"Expected a non-empty value for `agent_id` but received {agent_id!r}") + if not schedule_id: + raise ValueError(f"Expected a non-empty value for `schedule_id` but received {schedule_id!r}") + return self._delete( + path_template("/agents/{agent_id}/schedules/{schedule_id}", agent_id=agent_id, schedule_id=schedule_id), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=DeleteResponse, + ) + + def delete_by_name( + self, + name: str, + *, + agent_id: str, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> DeleteResponse: + """ + Delete a run schedule by its active name. + + Args: + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not agent_id: + raise ValueError(f"Expected a non-empty value for `agent_id` but received {agent_id!r}") + if not name: + raise ValueError(f"Expected a non-empty value for `name` but received {name!r}") + return self._delete( + path_template("/agents/{agent_id}/schedules/name/{name}", agent_id=agent_id, name=name), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=DeleteResponse, + ) + + def pause( + self, + schedule_id: str, + *, + agent_id: str, + note: Optional[str] | Omit = omit, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> SchedulePauseResponse: + """ + Pause a run schedule so it stops firing. + + Args: + note: Optional note explaining the pause. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not agent_id: + raise ValueError(f"Expected a non-empty value for `agent_id` but received {agent_id!r}") + if not schedule_id: + raise ValueError(f"Expected a non-empty value for `schedule_id` but received {schedule_id!r}") + return self._post( + path_template( + "/agents/{agent_id}/schedules/{schedule_id}/pause", agent_id=agent_id, schedule_id=schedule_id + ), + body=maybe_transform({"note": note}, schedule_pause_params.SchedulePauseParams), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=SchedulePauseResponse, + ) + + def pause_by_name( + self, + name: str, + *, + agent_id: str, + note: Optional[str] | Omit = omit, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> SchedulePauseByNameResponse: + """ + Pause a run schedule by its active name. + + Args: + note: Optional note explaining the pause. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not agent_id: + raise ValueError(f"Expected a non-empty value for `agent_id` but received {agent_id!r}") + if not name: + raise ValueError(f"Expected a non-empty value for `name` but received {name!r}") + return self._post( + path_template("/agents/{agent_id}/schedules/name/{name}/pause", agent_id=agent_id, name=name), + body=maybe_transform({"note": note}, schedule_pause_by_name_params.SchedulePauseByNameParams), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=SchedulePauseByNameResponse, + ) + + def resume( + self, + schedule_id: str, + *, + agent_id: str, + note: Optional[str] | Omit = omit, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> ScheduleResumeResponse: + """ + Resume a paused run schedule so it fires again. + + Args: + note: Optional note explaining the resume. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not agent_id: + raise ValueError(f"Expected a non-empty value for `agent_id` but received {agent_id!r}") + if not schedule_id: + raise ValueError(f"Expected a non-empty value for `schedule_id` but received {schedule_id!r}") + return self._post( + path_template( + "/agents/{agent_id}/schedules/{schedule_id}/resume", agent_id=agent_id, schedule_id=schedule_id + ), + body=maybe_transform({"note": note}, schedule_resume_params.ScheduleResumeParams), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=ScheduleResumeResponse, + ) + + def resume_by_name( + self, + name: str, + *, + agent_id: str, + note: Optional[str] | Omit = omit, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> ScheduleResumeByNameResponse: + """ + Resume a paused run schedule by its active name. + + Args: + note: Optional note explaining the resume. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not agent_id: + raise ValueError(f"Expected a non-empty value for `agent_id` but received {agent_id!r}") + if not name: + raise ValueError(f"Expected a non-empty value for `name` but received {name!r}") + return self._post( + path_template("/agents/{agent_id}/schedules/name/{name}/resume", agent_id=agent_id, name=name), + body=maybe_transform({"note": note}, schedule_resume_by_name_params.ScheduleResumeByNameParams), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=ScheduleResumeByNameResponse, + ) + + def retrieve_by_name( + self, + name: str, + *, + agent_id: str, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> ScheduleRetrieveByNameResponse: + """ + Get a run schedule by its active name. + + Args: + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not agent_id: + raise ValueError(f"Expected a non-empty value for `agent_id` but received {agent_id!r}") + if not name: + raise ValueError(f"Expected a non-empty value for `name` but received {name!r}") + return self._get( + path_template("/agents/{agent_id}/schedules/name/{name}", agent_id=agent_id, name=name), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=ScheduleRetrieveByNameResponse, + ) + + def trigger( + self, + schedule_id: str, + *, + agent_id: str, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> ScheduleTriggerResponse: + """ + Trigger an immediate, out-of-band run of the schedule (in addition to its + cadence). + + Args: + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not agent_id: + raise ValueError(f"Expected a non-empty value for `agent_id` but received {agent_id!r}") + if not schedule_id: + raise ValueError(f"Expected a non-empty value for `schedule_id` but received {schedule_id!r}") + return self._post( + path_template( + "/agents/{agent_id}/schedules/{schedule_id}/trigger", agent_id=agent_id, schedule_id=schedule_id + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=ScheduleTriggerResponse, + ) + + def trigger_by_name( + self, + name: str, + *, + agent_id: str, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> ScheduleTriggerByNameResponse: + """ + Trigger an immediate, out-of-band run of the schedule by its active name. + + Args: + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not agent_id: + raise ValueError(f"Expected a non-empty value for `agent_id` but received {agent_id!r}") + if not name: + raise ValueError(f"Expected a non-empty value for `name` but received {name!r}") + return self._post( + path_template("/agents/{agent_id}/schedules/name/{name}/trigger", agent_id=agent_id, name=name), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=ScheduleTriggerByNameResponse, + ) + + def update_by_name( + self, + path_name: str, + *, + agent_id: str, + cron_expression: Optional[str] | Omit = omit, + description: Optional[str] | Omit = omit, + end_at: Union[str, datetime, None] | Omit = omit, + initial_input: Optional[schedule_update_by_name_params.InitialInput] | Omit = omit, + interval_seconds: Optional[int] | Omit = omit, + body_name: Optional[str] | Omit = omit, + paused: Optional[bool] | Omit = omit, + start_at: Union[str, datetime, None] | Omit = omit, + task_metadata: Optional[Dict[str, object]] | Omit = omit, + task_params: Optional[Dict[str, object]] | Omit = omit, + timezone: Optional[str] | Omit = omit, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> ScheduleUpdateByNameResponse: + """ + Partially update a run schedule's definition by its active name. + + Args: + cron_expression: New cron cadence. Mutually exclusive with interval_seconds. + + description: Optional description of what this schedule does. + + end_at: When the schedule should stop being active. + + initial_input: The first input delivered to each freshly created scheduled task. + + interval_seconds: New interval cadence in seconds. Mutually exclusive with cron_expression. + + body_name: Human-readable name, unique among active schedules for the agent. + + paused: Pause/resume the schedule as part of the update. + + start_at: When the schedule should start being active. + + task_metadata: Metadata copied onto each created task at fire time. + + task_params: Resolved config forwarded as task `params` at fire time. + + timezone: IANA timezone the cron expression is evaluated in. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not agent_id: + raise ValueError(f"Expected a non-empty value for `agent_id` but received {agent_id!r}") + if not path_name: + raise ValueError(f"Expected a non-empty value for `path_name` but received {path_name!r}") + return self._patch( + path_template("/agents/{agent_id}/schedules/name/{path_name}", agent_id=agent_id, path_name=path_name), + body=maybe_transform( + { + "cron_expression": cron_expression, + "description": description, + "end_at": end_at, + "initial_input": initial_input, + "interval_seconds": interval_seconds, + "body_name": body_name, + "paused": paused, + "start_at": start_at, + "task_metadata": task_metadata, + "task_params": task_params, + "timezone": timezone, + }, + schedule_update_by_name_params.ScheduleUpdateByNameParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=ScheduleUpdateByNameResponse, + ) + + +class AsyncSchedulesResource(AsyncAPIResource): + @cached_property + def with_raw_response(self) -> AsyncSchedulesResourceWithRawResponse: + """ + This property can be used as a prefix for any HTTP method call to return + the raw response object instead of the parsed content. + + For more information, see https://www.github.com/scaleapi/scale-agentex-python#accessing-raw-response-data-eg-headers + """ + return AsyncSchedulesResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> AsyncSchedulesResourceWithStreamingResponse: """ An alternative to `.with_raw_response` that doesn't eagerly read the response body. For more information, see https://www.github.com/scaleapi/scale-agentex-python#with_streaming_response """ - return SchedulesResourceWithStreamingResponse(self) + return AsyncSchedulesResourceWithStreamingResponse(self) - def create( + async def create( self, agent_id: str, *, + initial_input: schedule_create_params.InitialInput, name: str, - task_queue: str, - workflow_name: str, cron_expression: Optional[str] | Omit = omit, + description: Optional[str] | Omit = omit, end_at: Union[str, datetime, None] | Omit = omit, - execution_timeout_seconds: Optional[int] | Omit = omit, interval_seconds: Optional[int] | Omit = omit, paused: bool | Omit = omit, start_at: Union[str, datetime, None] | Omit = omit, - workflow_params: Optional[Dict[str, object]] | Omit = omit, + task_metadata: Optional[Dict[str, object]] | Omit = omit, + task_params: Optional[Dict[str, object]] | Omit = omit, + timezone: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -72,29 +783,31 @@ def create( timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> ScheduleCreateResponse: """ - Create a new schedule for recurring workflow execution for an agent. + Create a recurring schedule that starts a fresh agent run on each fire. Args: - name: Human-readable name for the schedule (e.g., 'weekly-profiling'). Will be - combined with agent_id to form the full schedule_id. + initial_input: The first input delivered to each created task. + + name: Human-readable name, unique among active schedules for the agent. - task_queue: Temporal task queue where the agent's worker is listening + cron_expression: Cron expression for the cadence (e.g. '0 17 \\** \\** MON-FRI'). Mutually exclusive + with interval_seconds. - workflow_name: Name of the Temporal workflow to execute (e.g., 'sae-orchestrator') + description: Optional description of what this schedule does. - cron_expression: Cron expression for scheduling (e.g., '0 0 \\** \\** 0' for weekly on Sunday) + end_at: When the schedule should stop being active. - end_at: When the schedule should stop being active + interval_seconds: Interval cadence in seconds. Mutually exclusive with cron_expression. - execution_timeout_seconds: Maximum time in seconds for each workflow execution + paused: Whether to create the schedule in a paused state. - interval_seconds: Alternative to cron - run every N seconds + start_at: When the schedule should start being active. - paused: Whether to create the schedule in a paused state + task_metadata: Metadata copied onto each created task at fire time. - start_at: When the schedule should start being active + task_params: Resolved config forwarded as task `params` at fire time. - workflow_params: Parameters to pass to the workflow + timezone: IANA timezone the cron expression is evaluated in (e.g. 'America/New_York'). extra_headers: Send extra headers @@ -106,20 +819,21 @@ def create( """ if not agent_id: raise ValueError(f"Expected a non-empty value for `agent_id` but received {agent_id!r}") - return self._post( + return await self._post( path_template("/agents/{agent_id}/schedules", agent_id=agent_id), - body=maybe_transform( + body=await async_maybe_transform( { + "initial_input": initial_input, "name": name, - "task_queue": task_queue, - "workflow_name": workflow_name, "cron_expression": cron_expression, + "description": description, "end_at": end_at, - "execution_timeout_seconds": execution_timeout_seconds, "interval_seconds": interval_seconds, "paused": paused, "start_at": start_at, - "workflow_params": workflow_params, + "task_metadata": task_metadata, + "task_params": task_params, + "timezone": timezone, }, schedule_create_params.ScheduleCreateParams, ), @@ -129,9 +843,9 @@ def create( cast_to=ScheduleCreateResponse, ) - def retrieve( + async def retrieve( self, - schedule_name: str, + schedule_id: str, *, agent_id: str, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. @@ -142,7 +856,7 @@ def retrieve( timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> ScheduleRetrieveResponse: """ - Get details of a schedule by its name. + Get a run schedule by its id. Args: extra_headers: Send extra headers @@ -155,34 +869,65 @@ def retrieve( """ if not agent_id: raise ValueError(f"Expected a non-empty value for `agent_id` but received {agent_id!r}") - if not schedule_name: - raise ValueError(f"Expected a non-empty value for `schedule_name` but received {schedule_name!r}") - return self._get( - path_template( - "/agents/{agent_id}/schedules/{schedule_name}", agent_id=agent_id, schedule_name=schedule_name - ), + if not schedule_id: + raise ValueError(f"Expected a non-empty value for `schedule_id` but received {schedule_id!r}") + return await self._get( + path_template("/agents/{agent_id}/schedules/{schedule_id}", agent_id=agent_id, schedule_id=schedule_id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), cast_to=ScheduleRetrieveResponse, ) - def list( + async def update( self, - agent_id: str, + schedule_id: str, *, - page_size: int | Omit = omit, + agent_id: str, + cron_expression: Optional[str] | Omit = omit, + description: Optional[str] | Omit = omit, + end_at: Union[str, datetime, None] | Omit = omit, + initial_input: Optional[schedule_update_params.InitialInput] | Omit = omit, + interval_seconds: Optional[int] | Omit = omit, + name: Optional[str] | Omit = omit, + paused: Optional[bool] | Omit = omit, + start_at: Union[str, datetime, None] | Omit = omit, + task_metadata: Optional[Dict[str, object]] | Omit = omit, + task_params: Optional[Dict[str, object]] | Omit = omit, + timezone: Optional[str] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> ScheduleListResponse: + ) -> ScheduleUpdateResponse: """ - List all schedules for an agent. + Partially update a run schedule's definition (cadence, window, input, etc.). Args: + cron_expression: New cron cadence. Mutually exclusive with interval_seconds. + + description: Optional description of what this schedule does. + + end_at: When the schedule should stop being active. + + initial_input: The first input delivered to each freshly created scheduled task. + + interval_seconds: New interval cadence in seconds. Mutually exclusive with cron_expression. + + name: Human-readable name, unique among active schedules for the agent. + + paused: Pause/resume the schedule as part of the update. + + start_at: When the schedule should start being active. + + task_metadata: Metadata copied onto each created task at fire time. + + task_params: Resolved config forwarded as task `params` at fire time. + + timezone: IANA timezone the cron expression is evaluated in. + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -193,32 +938,46 @@ def list( """ if not agent_id: raise ValueError(f"Expected a non-empty value for `agent_id` but received {agent_id!r}") - return self._get( - path_template("/agents/{agent_id}/schedules", agent_id=agent_id), + if not schedule_id: + raise ValueError(f"Expected a non-empty value for `schedule_id` but received {schedule_id!r}") + return await self._patch( + path_template("/agents/{agent_id}/schedules/{schedule_id}", agent_id=agent_id, schedule_id=schedule_id), + body=await async_maybe_transform( + { + "cron_expression": cron_expression, + "description": description, + "end_at": end_at, + "initial_input": initial_input, + "interval_seconds": interval_seconds, + "name": name, + "paused": paused, + "start_at": start_at, + "task_metadata": task_metadata, + "task_params": task_params, + "timezone": timezone, + }, + schedule_update_params.ScheduleUpdateParams, + ), options=make_request_options( - extra_headers=extra_headers, - extra_query=extra_query, - extra_body=extra_body, - timeout=timeout, - query=maybe_transform({"page_size": page_size}, schedule_list_params.ScheduleListParams), + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), - cast_to=ScheduleListResponse, + cast_to=ScheduleUpdateResponse, ) - def delete( + async def list( self, - schedule_name: str, - *, agent_id: str, + *, + limit: int | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> DeleteResponse: + ) -> ScheduleListResponse: """ - Delete a schedule permanently. + List run schedules for an agent. Args: extra_headers: Send extra headers @@ -231,37 +990,34 @@ def delete( """ if not agent_id: raise ValueError(f"Expected a non-empty value for `agent_id` but received {agent_id!r}") - if not schedule_name: - raise ValueError(f"Expected a non-empty value for `schedule_name` but received {schedule_name!r}") - return self._delete( - path_template( - "/agents/{agent_id}/schedules/{schedule_name}", agent_id=agent_id, schedule_name=schedule_name - ), + return await self._get( + path_template("/agents/{agent_id}/schedules", agent_id=agent_id), options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=await async_maybe_transform({"limit": limit}, schedule_list_params.ScheduleListParams), ), - cast_to=DeleteResponse, + cast_to=ScheduleListResponse, ) - def pause( + async def delete( self, - schedule_name: str, + schedule_id: str, *, agent_id: str, - note: Optional[str] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> SchedulePauseResponse: + ) -> DeleteResponse: """ - Pause a schedule to stop it from executing. + Delete a run schedule permanently. Args: - note: Optional note explaining why the schedule was paused - extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -272,22 +1028,19 @@ def pause( """ if not agent_id: raise ValueError(f"Expected a non-empty value for `agent_id` but received {agent_id!r}") - if not schedule_name: - raise ValueError(f"Expected a non-empty value for `schedule_name` but received {schedule_name!r}") - return self._post( - path_template( - "/agents/{agent_id}/schedules/{schedule_name}/pause", agent_id=agent_id, schedule_name=schedule_name - ), - body=maybe_transform({"note": note}, schedule_pause_params.SchedulePauseParams), + if not schedule_id: + raise ValueError(f"Expected a non-empty value for `schedule_id` but received {schedule_id!r}") + return await self._delete( + path_template("/agents/{agent_id}/schedules/{schedule_id}", agent_id=agent_id, schedule_id=schedule_id), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), - cast_to=SchedulePauseResponse, + cast_to=DeleteResponse, ) - def trigger( + async def delete_by_name( self, - schedule_name: str, + name: str, *, agent_id: str, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. @@ -296,9 +1049,9 @@ def trigger( extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> ScheduleTriggerResponse: + ) -> DeleteResponse: """ - Trigger a schedule to run immediately, regardless of its regular schedule. + Delete a run schedule by its active name. Args: extra_headers: Send extra headers @@ -311,21 +1064,19 @@ def trigger( """ if not agent_id: raise ValueError(f"Expected a non-empty value for `agent_id` but received {agent_id!r}") - if not schedule_name: - raise ValueError(f"Expected a non-empty value for `schedule_name` but received {schedule_name!r}") - return self._post( - path_template( - "/agents/{agent_id}/schedules/{schedule_name}/trigger", agent_id=agent_id, schedule_name=schedule_name - ), + if not name: + raise ValueError(f"Expected a non-empty value for `name` but received {name!r}") + return await self._delete( + path_template("/agents/{agent_id}/schedules/name/{name}", agent_id=agent_id, name=name), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), - cast_to=ScheduleTriggerResponse, + cast_to=DeleteResponse, ) - def unpause( + async def pause( self, - schedule_name: str, + schedule_id: str, *, agent_id: str, note: Optional[str] | Omit = omit, @@ -335,12 +1086,12 @@ def unpause( extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> ScheduleUnpauseResponse: + ) -> SchedulePauseResponse: """ - Unpause/resume a schedule to allow it to execute again. + Pause a run schedule so it stops firing. Args: - note: Optional note explaining why the schedule was unpaused + note: Optional note explaining the pause. extra_headers: Send extra headers @@ -352,85 +1103,37 @@ def unpause( """ if not agent_id: raise ValueError(f"Expected a non-empty value for `agent_id` but received {agent_id!r}") - if not schedule_name: - raise ValueError(f"Expected a non-empty value for `schedule_name` but received {schedule_name!r}") - return self._post( + if not schedule_id: + raise ValueError(f"Expected a non-empty value for `schedule_id` but received {schedule_id!r}") + return await self._post( path_template( - "/agents/{agent_id}/schedules/{schedule_name}/unpause", agent_id=agent_id, schedule_name=schedule_name + "/agents/{agent_id}/schedules/{schedule_id}/pause", agent_id=agent_id, schedule_id=schedule_id ), - body=maybe_transform({"note": note}, schedule_unpause_params.ScheduleUnpauseParams), + body=await async_maybe_transform({"note": note}, schedule_pause_params.SchedulePauseParams), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), - cast_to=ScheduleUnpauseResponse, + cast_to=SchedulePauseResponse, ) - -class AsyncSchedulesResource(AsyncAPIResource): - @cached_property - def with_raw_response(self) -> AsyncSchedulesResourceWithRawResponse: - """ - This property can be used as a prefix for any HTTP method call to return - the raw response object instead of the parsed content. - - For more information, see https://www.github.com/scaleapi/scale-agentex-python#accessing-raw-response-data-eg-headers - """ - return AsyncSchedulesResourceWithRawResponse(self) - - @cached_property - def with_streaming_response(self) -> AsyncSchedulesResourceWithStreamingResponse: - """ - An alternative to `.with_raw_response` that doesn't eagerly read the response body. - - For more information, see https://www.github.com/scaleapi/scale-agentex-python#with_streaming_response - """ - return AsyncSchedulesResourceWithStreamingResponse(self) - - async def create( + async def pause_by_name( self, - agent_id: str, - *, name: str, - task_queue: str, - workflow_name: str, - cron_expression: Optional[str] | Omit = omit, - end_at: Union[str, datetime, None] | Omit = omit, - execution_timeout_seconds: Optional[int] | Omit = omit, - interval_seconds: Optional[int] | Omit = omit, - paused: bool | Omit = omit, - start_at: Union[str, datetime, None] | Omit = omit, - workflow_params: Optional[Dict[str, object]] | Omit = omit, + *, + agent_id: str, + note: Optional[str] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> ScheduleCreateResponse: + ) -> SchedulePauseByNameResponse: """ - Create a new schedule for recurring workflow execution for an agent. + Pause a run schedule by its active name. Args: - name: Human-readable name for the schedule (e.g., 'weekly-profiling'). Will be - combined with agent_id to form the full schedule_id. - - task_queue: Temporal task queue where the agent's worker is listening - - workflow_name: Name of the Temporal workflow to execute (e.g., 'sae-orchestrator') - - cron_expression: Cron expression for scheduling (e.g., '0 0 \\** \\** 0' for weekly on Sunday) - - end_at: When the schedule should stop being active - - execution_timeout_seconds: Maximum time in seconds for each workflow execution - - interval_seconds: Alternative to cron - run every N seconds - - paused: Whether to create the schedule in a paused state - - start_at: When the schedule should start being active - - workflow_params: Parameters to pass to the workflow + note: Optional note explaining the pause. extra_headers: Send extra headers @@ -442,45 +1145,36 @@ async def create( """ if not agent_id: raise ValueError(f"Expected a non-empty value for `agent_id` but received {agent_id!r}") + if not name: + raise ValueError(f"Expected a non-empty value for `name` but received {name!r}") return await self._post( - path_template("/agents/{agent_id}/schedules", agent_id=agent_id), - body=await async_maybe_transform( - { - "name": name, - "task_queue": task_queue, - "workflow_name": workflow_name, - "cron_expression": cron_expression, - "end_at": end_at, - "execution_timeout_seconds": execution_timeout_seconds, - "interval_seconds": interval_seconds, - "paused": paused, - "start_at": start_at, - "workflow_params": workflow_params, - }, - schedule_create_params.ScheduleCreateParams, - ), + path_template("/agents/{agent_id}/schedules/name/{name}/pause", agent_id=agent_id, name=name), + body=await async_maybe_transform({"note": note}, schedule_pause_by_name_params.SchedulePauseByNameParams), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), - cast_to=ScheduleCreateResponse, + cast_to=SchedulePauseByNameResponse, ) - async def retrieve( + async def resume( self, - schedule_name: str, + schedule_id: str, *, agent_id: str, + note: Optional[str] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> ScheduleRetrieveResponse: + ) -> ScheduleResumeResponse: """ - Get details of a schedule by its name. + Resume a paused run schedule so it fires again. Args: + note: Optional note explaining the resume. + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -491,34 +1185,38 @@ async def retrieve( """ if not agent_id: raise ValueError(f"Expected a non-empty value for `agent_id` but received {agent_id!r}") - if not schedule_name: - raise ValueError(f"Expected a non-empty value for `schedule_name` but received {schedule_name!r}") - return await self._get( + if not schedule_id: + raise ValueError(f"Expected a non-empty value for `schedule_id` but received {schedule_id!r}") + return await self._post( path_template( - "/agents/{agent_id}/schedules/{schedule_name}", agent_id=agent_id, schedule_name=schedule_name + "/agents/{agent_id}/schedules/{schedule_id}/resume", agent_id=agent_id, schedule_id=schedule_id ), + body=await async_maybe_transform({"note": note}, schedule_resume_params.ScheduleResumeParams), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), - cast_to=ScheduleRetrieveResponse, + cast_to=ScheduleResumeResponse, ) - async def list( + async def resume_by_name( self, - agent_id: str, + name: str, *, - page_size: int | Omit = omit, + agent_id: str, + note: Optional[str] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> ScheduleListResponse: + ) -> ScheduleResumeByNameResponse: """ - List all schedules for an agent. + Resume a paused run schedule by its active name. Args: + note: Optional note explaining the resume. + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -529,21 +1227,20 @@ async def list( """ if not agent_id: raise ValueError(f"Expected a non-empty value for `agent_id` but received {agent_id!r}") - return await self._get( - path_template("/agents/{agent_id}/schedules", agent_id=agent_id), + if not name: + raise ValueError(f"Expected a non-empty value for `name` but received {name!r}") + return await self._post( + path_template("/agents/{agent_id}/schedules/name/{name}/resume", agent_id=agent_id, name=name), + body=await async_maybe_transform({"note": note}, schedule_resume_by_name_params.ScheduleResumeByNameParams), options=make_request_options( - extra_headers=extra_headers, - extra_query=extra_query, - extra_body=extra_body, - timeout=timeout, - query=await async_maybe_transform({"page_size": page_size}, schedule_list_params.ScheduleListParams), + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), - cast_to=ScheduleListResponse, + cast_to=ScheduleResumeByNameResponse, ) - async def delete( + async def retrieve_by_name( self, - schedule_name: str, + name: str, *, agent_id: str, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. @@ -552,9 +1249,9 @@ async def delete( extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> DeleteResponse: + ) -> ScheduleRetrieveByNameResponse: """ - Delete a schedule permanently. + Get a run schedule by its active name. Args: extra_headers: Send extra headers @@ -567,37 +1264,33 @@ async def delete( """ if not agent_id: raise ValueError(f"Expected a non-empty value for `agent_id` but received {agent_id!r}") - if not schedule_name: - raise ValueError(f"Expected a non-empty value for `schedule_name` but received {schedule_name!r}") - return await self._delete( - path_template( - "/agents/{agent_id}/schedules/{schedule_name}", agent_id=agent_id, schedule_name=schedule_name - ), + if not name: + raise ValueError(f"Expected a non-empty value for `name` but received {name!r}") + return await self._get( + path_template("/agents/{agent_id}/schedules/name/{name}", agent_id=agent_id, name=name), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), - cast_to=DeleteResponse, + cast_to=ScheduleRetrieveByNameResponse, ) - async def pause( + async def trigger( self, - schedule_name: str, + schedule_id: str, *, agent_id: str, - note: Optional[str] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> SchedulePauseResponse: + ) -> ScheduleTriggerResponse: """ - Pause a schedule to stop it from executing. + Trigger an immediate, out-of-band run of the schedule (in addition to its + cadence). Args: - note: Optional note explaining why the schedule was paused - extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -608,22 +1301,21 @@ async def pause( """ if not agent_id: raise ValueError(f"Expected a non-empty value for `agent_id` but received {agent_id!r}") - if not schedule_name: - raise ValueError(f"Expected a non-empty value for `schedule_name` but received {schedule_name!r}") + if not schedule_id: + raise ValueError(f"Expected a non-empty value for `schedule_id` but received {schedule_id!r}") return await self._post( path_template( - "/agents/{agent_id}/schedules/{schedule_name}/pause", agent_id=agent_id, schedule_name=schedule_name + "/agents/{agent_id}/schedules/{schedule_id}/trigger", agent_id=agent_id, schedule_id=schedule_id ), - body=await async_maybe_transform({"note": note}, schedule_pause_params.SchedulePauseParams), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), - cast_to=SchedulePauseResponse, + cast_to=ScheduleTriggerResponse, ) - async def trigger( + async def trigger_by_name( self, - schedule_name: str, + name: str, *, agent_id: str, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. @@ -632,9 +1324,9 @@ async def trigger( extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> ScheduleTriggerResponse: + ) -> ScheduleTriggerByNameResponse: """ - Trigger a schedule to run immediately, regardless of its regular schedule. + Trigger an immediate, out-of-band run of the schedule by its active name. Args: extra_headers: Send extra headers @@ -647,36 +1339,64 @@ async def trigger( """ if not agent_id: raise ValueError(f"Expected a non-empty value for `agent_id` but received {agent_id!r}") - if not schedule_name: - raise ValueError(f"Expected a non-empty value for `schedule_name` but received {schedule_name!r}") + if not name: + raise ValueError(f"Expected a non-empty value for `name` but received {name!r}") return await self._post( - path_template( - "/agents/{agent_id}/schedules/{schedule_name}/trigger", agent_id=agent_id, schedule_name=schedule_name - ), + path_template("/agents/{agent_id}/schedules/name/{name}/trigger", agent_id=agent_id, name=name), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), - cast_to=ScheduleTriggerResponse, + cast_to=ScheduleTriggerByNameResponse, ) - async def unpause( + async def update_by_name( self, - schedule_name: str, + path_name: str, *, agent_id: str, - note: Optional[str] | Omit = omit, + cron_expression: Optional[str] | Omit = omit, + description: Optional[str] | Omit = omit, + end_at: Union[str, datetime, None] | Omit = omit, + initial_input: Optional[schedule_update_by_name_params.InitialInput] | Omit = omit, + interval_seconds: Optional[int] | Omit = omit, + body_name: Optional[str] | Omit = omit, + paused: Optional[bool] | Omit = omit, + start_at: Union[str, datetime, None] | Omit = omit, + task_metadata: Optional[Dict[str, object]] | Omit = omit, + task_params: Optional[Dict[str, object]] | Omit = omit, + timezone: Optional[str] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> ScheduleUnpauseResponse: + ) -> ScheduleUpdateByNameResponse: """ - Unpause/resume a schedule to allow it to execute again. + Partially update a run schedule's definition by its active name. Args: - note: Optional note explaining why the schedule was unpaused + cron_expression: New cron cadence. Mutually exclusive with interval_seconds. + + description: Optional description of what this schedule does. + + end_at: When the schedule should stop being active. + + initial_input: The first input delivered to each freshly created scheduled task. + + interval_seconds: New interval cadence in seconds. Mutually exclusive with cron_expression. + + body_name: Human-readable name, unique among active schedules for the agent. + + paused: Pause/resume the schedule as part of the update. + + start_at: When the schedule should start being active. + + task_metadata: Metadata copied onto each created task at fire time. + + task_params: Resolved config forwarded as task `params` at fire time. + + timezone: IANA timezone the cron expression is evaluated in. extra_headers: Send extra headers @@ -688,17 +1408,30 @@ async def unpause( """ if not agent_id: raise ValueError(f"Expected a non-empty value for `agent_id` but received {agent_id!r}") - if not schedule_name: - raise ValueError(f"Expected a non-empty value for `schedule_name` but received {schedule_name!r}") - return await self._post( - path_template( - "/agents/{agent_id}/schedules/{schedule_name}/unpause", agent_id=agent_id, schedule_name=schedule_name + if not path_name: + raise ValueError(f"Expected a non-empty value for `path_name` but received {path_name!r}") + return await self._patch( + path_template("/agents/{agent_id}/schedules/name/{path_name}", agent_id=agent_id, path_name=path_name), + body=await async_maybe_transform( + { + "cron_expression": cron_expression, + "description": description, + "end_at": end_at, + "initial_input": initial_input, + "interval_seconds": interval_seconds, + "body_name": body_name, + "paused": paused, + "start_at": start_at, + "task_metadata": task_metadata, + "task_params": task_params, + "timezone": timezone, + }, + schedule_update_by_name_params.ScheduleUpdateByNameParams, ), - body=await async_maybe_transform({"note": note}, schedule_unpause_params.ScheduleUnpauseParams), options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), - cast_to=ScheduleUnpauseResponse, + cast_to=ScheduleUpdateByNameResponse, ) @@ -712,20 +1445,41 @@ def __init__(self, schedules: SchedulesResource) -> None: self.retrieve = to_raw_response_wrapper( schedules.retrieve, ) + self.update = to_raw_response_wrapper( + schedules.update, + ) self.list = to_raw_response_wrapper( schedules.list, ) self.delete = to_raw_response_wrapper( schedules.delete, ) + self.delete_by_name = to_raw_response_wrapper( + schedules.delete_by_name, + ) self.pause = to_raw_response_wrapper( schedules.pause, ) + self.pause_by_name = to_raw_response_wrapper( + schedules.pause_by_name, + ) + self.resume = to_raw_response_wrapper( + schedules.resume, + ) + self.resume_by_name = to_raw_response_wrapper( + schedules.resume_by_name, + ) + self.retrieve_by_name = to_raw_response_wrapper( + schedules.retrieve_by_name, + ) self.trigger = to_raw_response_wrapper( schedules.trigger, ) - self.unpause = to_raw_response_wrapper( - schedules.unpause, + self.trigger_by_name = to_raw_response_wrapper( + schedules.trigger_by_name, + ) + self.update_by_name = to_raw_response_wrapper( + schedules.update_by_name, ) @@ -739,20 +1493,41 @@ def __init__(self, schedules: AsyncSchedulesResource) -> None: self.retrieve = async_to_raw_response_wrapper( schedules.retrieve, ) + self.update = async_to_raw_response_wrapper( + schedules.update, + ) self.list = async_to_raw_response_wrapper( schedules.list, ) self.delete = async_to_raw_response_wrapper( schedules.delete, ) + self.delete_by_name = async_to_raw_response_wrapper( + schedules.delete_by_name, + ) self.pause = async_to_raw_response_wrapper( schedules.pause, ) + self.pause_by_name = async_to_raw_response_wrapper( + schedules.pause_by_name, + ) + self.resume = async_to_raw_response_wrapper( + schedules.resume, + ) + self.resume_by_name = async_to_raw_response_wrapper( + schedules.resume_by_name, + ) + self.retrieve_by_name = async_to_raw_response_wrapper( + schedules.retrieve_by_name, + ) self.trigger = async_to_raw_response_wrapper( schedules.trigger, ) - self.unpause = async_to_raw_response_wrapper( - schedules.unpause, + self.trigger_by_name = async_to_raw_response_wrapper( + schedules.trigger_by_name, + ) + self.update_by_name = async_to_raw_response_wrapper( + schedules.update_by_name, ) @@ -766,20 +1541,41 @@ def __init__(self, schedules: SchedulesResource) -> None: self.retrieve = to_streamed_response_wrapper( schedules.retrieve, ) + self.update = to_streamed_response_wrapper( + schedules.update, + ) self.list = to_streamed_response_wrapper( schedules.list, ) self.delete = to_streamed_response_wrapper( schedules.delete, ) + self.delete_by_name = to_streamed_response_wrapper( + schedules.delete_by_name, + ) self.pause = to_streamed_response_wrapper( schedules.pause, ) + self.pause_by_name = to_streamed_response_wrapper( + schedules.pause_by_name, + ) + self.resume = to_streamed_response_wrapper( + schedules.resume, + ) + self.resume_by_name = to_streamed_response_wrapper( + schedules.resume_by_name, + ) + self.retrieve_by_name = to_streamed_response_wrapper( + schedules.retrieve_by_name, + ) self.trigger = to_streamed_response_wrapper( schedules.trigger, ) - self.unpause = to_streamed_response_wrapper( - schedules.unpause, + self.trigger_by_name = to_streamed_response_wrapper( + schedules.trigger_by_name, + ) + self.update_by_name = to_streamed_response_wrapper( + schedules.update_by_name, ) @@ -793,18 +1589,39 @@ def __init__(self, schedules: AsyncSchedulesResource) -> None: self.retrieve = async_to_streamed_response_wrapper( schedules.retrieve, ) + self.update = async_to_streamed_response_wrapper( + schedules.update, + ) self.list = async_to_streamed_response_wrapper( schedules.list, ) self.delete = async_to_streamed_response_wrapper( schedules.delete, ) + self.delete_by_name = async_to_streamed_response_wrapper( + schedules.delete_by_name, + ) self.pause = async_to_streamed_response_wrapper( schedules.pause, ) + self.pause_by_name = async_to_streamed_response_wrapper( + schedules.pause_by_name, + ) + self.resume = async_to_streamed_response_wrapper( + schedules.resume, + ) + self.resume_by_name = async_to_streamed_response_wrapper( + schedules.resume_by_name, + ) + self.retrieve_by_name = async_to_streamed_response_wrapper( + schedules.retrieve_by_name, + ) self.trigger = async_to_streamed_response_wrapper( schedules.trigger, ) - self.unpause = async_to_streamed_response_wrapper( - schedules.unpause, + self.trigger_by_name = async_to_streamed_response_wrapper( + schedules.trigger_by_name, + ) + self.update_by_name = async_to_streamed_response_wrapper( + schedules.update_by_name, ) diff --git a/src/agentex/types/agents/__init__.py b/src/agentex/types/agents/__init__.py index 27c802742..670456942 100644 --- a/src/agentex/types/agents/__init__.py +++ b/src/agentex/types/agents/__init__.py @@ -7,15 +7,25 @@ from .deployment_list_params import DeploymentListParams as DeploymentListParams from .schedule_create_params import ScheduleCreateParams as ScheduleCreateParams from .schedule_list_response import ScheduleListResponse as ScheduleListResponse +from .schedule_resume_params import ScheduleResumeParams as ScheduleResumeParams +from .schedule_update_params import ScheduleUpdateParams as ScheduleUpdateParams from .schedule_pause_response import SchedulePauseResponse as SchedulePauseResponse -from .schedule_unpause_params import ScheduleUnpauseParams as ScheduleUnpauseParams from .deployment_create_params import DeploymentCreateParams as DeploymentCreateParams from .deployment_list_response import DeploymentListResponse as DeploymentListResponse from .schedule_create_response import ScheduleCreateResponse as ScheduleCreateResponse +from .schedule_resume_response import ScheduleResumeResponse as ScheduleResumeResponse +from .schedule_update_response import ScheduleUpdateResponse as ScheduleUpdateResponse from .schedule_trigger_response import ScheduleTriggerResponse as ScheduleTriggerResponse -from .schedule_unpause_response import ScheduleUnpauseResponse as ScheduleUnpauseResponse from .deployment_create_response import DeploymentCreateResponse as DeploymentCreateResponse from .schedule_retrieve_response import ScheduleRetrieveResponse as ScheduleRetrieveResponse from .deployment_promote_response import DeploymentPromoteResponse as DeploymentPromoteResponse from .deployment_retrieve_response import DeploymentRetrieveResponse as DeploymentRetrieveResponse from .deployment_preview_rpc_params import DeploymentPreviewRpcParams as DeploymentPreviewRpcParams +from .schedule_pause_by_name_params import SchedulePauseByNameParams as SchedulePauseByNameParams +from .schedule_resume_by_name_params import ScheduleResumeByNameParams as ScheduleResumeByNameParams +from .schedule_update_by_name_params import ScheduleUpdateByNameParams as ScheduleUpdateByNameParams +from .schedule_pause_by_name_response import SchedulePauseByNameResponse as SchedulePauseByNameResponse +from .schedule_resume_by_name_response import ScheduleResumeByNameResponse as ScheduleResumeByNameResponse +from .schedule_update_by_name_response import ScheduleUpdateByNameResponse as ScheduleUpdateByNameResponse +from .schedule_trigger_by_name_response import ScheduleTriggerByNameResponse as ScheduleTriggerByNameResponse +from .schedule_retrieve_by_name_response import ScheduleRetrieveByNameResponse as ScheduleRetrieveByNameResponse diff --git a/src/agentex/types/agents/schedule_create_params.py b/src/agentex/types/agents/schedule_create_params.py index bfb2e0013..2210ad873 100644 --- a/src/agentex/types/agents/schedule_create_params.py +++ b/src/agentex/types/agents/schedule_create_params.py @@ -4,43 +4,60 @@ from typing import Dict, Union, Optional from datetime import datetime -from typing_extensions import Required, Annotated, TypedDict +from typing_extensions import Literal, Required, Annotated, TypedDict from ..._utils import PropertyInfo +from ..message_author import MessageAuthor -__all__ = ["ScheduleCreateParams"] +__all__ = ["ScheduleCreateParams", "InitialInput"] class ScheduleCreateParams(TypedDict, total=False): - name: Required[str] - """Human-readable name for the schedule (e.g., 'weekly-profiling'). + initial_input: Required[InitialInput] + """The first input delivered to each created task.""" - Will be combined with agent_id to form the full schedule_id. - """ + name: Required[str] + """Human-readable name, unique among active schedules for the agent.""" - task_queue: Required[str] - """Temporal task queue where the agent's worker is listening""" + cron_expression: Optional[str] + """Cron expression for the cadence (e.g. - workflow_name: Required[str] - """Name of the Temporal workflow to execute (e.g., 'sae-orchestrator')""" + '0 17 \\** \\** MON-FRI'). Mutually exclusive with interval_seconds. + """ - cron_expression: Optional[str] - """Cron expression for scheduling (e.g., '0 0 \\** \\** 0' for weekly on Sunday)""" + description: Optional[str] + """Optional description of what this schedule does.""" end_at: Annotated[Union[str, datetime, None], PropertyInfo(format="iso8601")] - """When the schedule should stop being active""" - - execution_timeout_seconds: Optional[int] - """Maximum time in seconds for each workflow execution""" + """When the schedule should stop being active.""" interval_seconds: Optional[int] - """Alternative to cron - run every N seconds""" + """Interval cadence in seconds. Mutually exclusive with cron_expression.""" paused: bool - """Whether to create the schedule in a paused state""" + """Whether to create the schedule in a paused state.""" start_at: Annotated[Union[str, datetime, None], PropertyInfo(format="iso8601")] - """When the schedule should start being active""" + """When the schedule should start being active.""" + + task_metadata: Optional[Dict[str, object]] + """Metadata copied onto each created task at fire time.""" + + task_params: Optional[Dict[str, object]] + """Resolved config forwarded as task `params` at fire time.""" + + timezone: str + """IANA timezone the cron expression is evaluated in (e.g. 'America/New_York').""" + + +class InitialInput(TypedDict, total=False): + """The first input delivered to each created task.""" + + content: Required[str] + """The initial prompt delivered to the task.""" + + author: MessageAuthor + """The author attributed to the initial input.""" - workflow_params: Optional[Dict[str, object]] - """Parameters to pass to the workflow""" + type: Literal["text"] + """Input content type.""" diff --git a/src/agentex/types/agents/schedule_create_response.py b/src/agentex/types/agents/schedule_create_response.py index 7f717d7a5..4440629a2 100644 --- a/src/agentex/types/agents/schedule_create_response.py +++ b/src/agentex/types/agents/schedule_create_response.py @@ -1,78 +1,117 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -from typing import List, Optional +from typing import Dict, List, Optional from datetime import datetime from typing_extensions import Literal from ..._models import BaseModel +from ..message_author import MessageAuthor -__all__ = ["ScheduleCreateResponse", "Action", "Spec"] +__all__ = ["ScheduleCreateResponse", "InitialInput", "CreatorPrincipal"] -class Action(BaseModel): - """Information about the scheduled action""" +class InitialInput(BaseModel): + """The initial input.""" - task_queue: str - """Task queue for the workflow""" + content: str + """The initial prompt delivered to the task.""" - workflow_id_prefix: str - """Prefix for workflow execution IDs""" + author: Optional[MessageAuthor] = None + """The author attributed to the initial input.""" - workflow_name: str - """Name of the workflow being executed""" + type: Optional[Literal["text"]] = None + """Input content type.""" - workflow_params: Optional[List[object]] = None - """Parameters passed to the workflow""" +class CreatorPrincipal(BaseModel): + """Credential-free creator identity stored with the schedule. -class Spec(BaseModel): - """Schedule specification""" + Never carries cookies, JWTs, API keys, OAuth tokens, or request headers — it + is creator *context* used only for AuthZ and ownership at fire time. + """ - cron_expressions: Optional[List[str]] = None - """Cron expressions for the schedule""" + account_id: Optional[str] = None + """Account/workspace id of the creator.""" - end_at: Optional[datetime] = None - """When the schedule stops being active""" + principal_type: Optional[str] = None + """e.g. 'user' or 'service_account'.""" - intervals_seconds: Optional[List[int]] = None - """Interval specifications in seconds""" + service_account_id: Optional[str] = None + """Creator service-account id, if a service principal.""" - start_at: Optional[datetime] = None - """When the schedule starts being active""" + user_id: Optional[str] = None + """Creator user id, if a user principal.""" class ScheduleCreateResponse(BaseModel): - """Response model for schedule operations""" + """Response model describing a scheduled agent run.""" - action: Action - """Information about the scheduled action""" + id: str + """The unique identifier of the run schedule.""" agent_id: str - """ID of the agent this schedule belongs to""" + """The agent this schedule belongs to.""" + + initial_input: InitialInput + """The initial input.""" + + initial_input_method: str + """Delivery method, inferred from the agent's ACP type.""" name: str - """Human-readable name for the schedule""" + """Human-readable schedule name.""" + + created_at: Optional[datetime] = None + """When the schedule was created.""" - schedule_id: str - """Unique identifier for the schedule""" + creator_principal: Optional[CreatorPrincipal] = None + """Credential-free creator identity stored with the schedule. - spec: Spec - """Schedule specification""" + Never carries cookies, JWTs, API keys, OAuth tokens, or request headers — it is + creator _context_ used only for AuthZ and ownership at fire time. + """ - state: Literal["ACTIVE", "PAUSED"] - """Current state of the schedule""" + cron_expression: Optional[str] = None + """Cron cadence, if cron-based.""" - created_at: Optional[datetime] = None - """When the schedule was created""" + description: Optional[str] = None + """Optional description.""" + + end_at: Optional[datetime] = None + """Schedule deactivation time.""" + + interval_seconds: Optional[int] = None + """Interval cadence in seconds, if interval-based.""" last_action_time: Optional[datetime] = None - """When the schedule last executed""" + """When the schedule last fired.""" next_action_times: Optional[List[datetime]] = None - """Upcoming scheduled execution times""" - - num_actions_missed: Optional[int] = None - """Number of scheduled executions that were missed""" + """Upcoming scheduled fire times.""" num_actions_taken: Optional[int] = None - """Number of times the schedule has executed""" + """Number of times the schedule has fired.""" + + paused: Optional[bool] = None + """Whether the schedule is paused.""" + + skipped_action_times: Optional[List[datetime]] = None + """Skipped one-off scheduled fire times.""" + + start_at: Optional[datetime] = None + """Schedule activation time.""" + + state: Optional[Literal["ACTIVE", "PAUSED"]] = None + """Live schedule state from Temporal.""" + + task_metadata: Optional[Dict[str, object]] = None + """Task metadata at fire time.""" + + task_params: Optional[Dict[str, object]] = None + """Task params at fire time.""" + + timezone: Optional[str] = None + """Timezone the cron expression is evaluated in.""" + + updated_at: Optional[datetime] = None + """When the schedule was updated.""" diff --git a/src/agentex/types/agents/schedule_list_params.py b/src/agentex/types/agents/schedule_list_params.py index 210f8f557..8a1d5561a 100644 --- a/src/agentex/types/agents/schedule_list_params.py +++ b/src/agentex/types/agents/schedule_list_params.py @@ -8,4 +8,4 @@ class ScheduleListParams(TypedDict, total=False): - page_size: int + limit: int diff --git a/src/agentex/types/agents/schedule_list_response.py b/src/agentex/types/agents/schedule_list_response.py index fe54e11f1..182bd53eb 100644 --- a/src/agentex/types/agents/schedule_list_response.py +++ b/src/agentex/types/agents/schedule_list_response.py @@ -1,41 +1,127 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -from typing import List, Optional +from typing import Dict, List, Optional from datetime import datetime from typing_extensions import Literal from ..._models import BaseModel +from ..message_author import MessageAuthor -__all__ = ["ScheduleListResponse", "Schedule"] +__all__ = ["ScheduleListResponse", "RunSchedule", "RunScheduleInitialInput", "RunScheduleCreatorPrincipal"] -class Schedule(BaseModel): - """Abbreviated schedule info for list responses""" +class RunScheduleInitialInput(BaseModel): + """The initial input.""" + + content: str + """The initial prompt delivered to the task.""" + + author: Optional[MessageAuthor] = None + """The author attributed to the initial input.""" + + type: Optional[Literal["text"]] = None + """Input content type.""" + + +class RunScheduleCreatorPrincipal(BaseModel): + """Credential-free creator identity stored with the schedule. + + Never carries cookies, JWTs, API keys, OAuth tokens, or request headers — it + is creator *context* used only for AuthZ and ownership at fire time. + """ + + account_id: Optional[str] = None + """Account/workspace id of the creator.""" + + principal_type: Optional[str] = None + """e.g. 'user' or 'service_account'.""" + + service_account_id: Optional[str] = None + """Creator service-account id, if a service principal.""" + + user_id: Optional[str] = None + """Creator user id, if a user principal.""" + + +class RunSchedule(BaseModel): + """Response model describing a scheduled agent run.""" + + id: str + """The unique identifier of the run schedule.""" agent_id: str - """ID of the agent this schedule belongs to""" + """The agent this schedule belongs to.""" + + initial_input: RunScheduleInitialInput + """The initial input.""" + + initial_input_method: str + """Delivery method, inferred from the agent's ACP type.""" name: str - """Human-readable name for the schedule""" + """Human-readable schedule name.""" + + created_at: Optional[datetime] = None + """When the schedule was created.""" + + creator_principal: Optional[RunScheduleCreatorPrincipal] = None + """Credential-free creator identity stored with the schedule. + + Never carries cookies, JWTs, API keys, OAuth tokens, or request headers — it is + creator _context_ used only for AuthZ and ownership at fire time. + """ + + cron_expression: Optional[str] = None + """Cron cadence, if cron-based.""" + + description: Optional[str] = None + """Optional description.""" + + end_at: Optional[datetime] = None + """Schedule deactivation time.""" + + interval_seconds: Optional[int] = None + """Interval cadence in seconds, if interval-based.""" + + last_action_time: Optional[datetime] = None + """When the schedule last fired.""" + + next_action_times: Optional[List[datetime]] = None + """Upcoming scheduled fire times.""" + + num_actions_taken: Optional[int] = None + """Number of times the schedule has fired.""" + + paused: Optional[bool] = None + """Whether the schedule is paused.""" + + skipped_action_times: Optional[List[datetime]] = None + """Skipped one-off scheduled fire times.""" + + start_at: Optional[datetime] = None + """Schedule activation time.""" + + state: Optional[Literal["ACTIVE", "PAUSED"]] = None + """Live schedule state from Temporal.""" - schedule_id: str - """Unique identifier for the schedule""" + task_metadata: Optional[Dict[str, object]] = None + """Task metadata at fire time.""" - state: Literal["ACTIVE", "PAUSED"] - """Current state of the schedule""" + task_params: Optional[Dict[str, object]] = None + """Task params at fire time.""" - next_action_time: Optional[datetime] = None - """Next scheduled execution time""" + timezone: Optional[str] = None + """Timezone the cron expression is evaluated in.""" - workflow_name: Optional[str] = None - """Name of the scheduled workflow""" + updated_at: Optional[datetime] = None + """When the schedule was updated.""" class ScheduleListResponse(BaseModel): - """Response model for listing schedules""" + """Response model for listing run schedules.""" - schedules: List[Schedule] - """List of schedules""" + run_schedules: List[RunSchedule] + """The list of run schedules.""" total: int - """Total number of schedules""" + """The number of run schedules returned.""" diff --git a/src/agentex/types/agents/schedule_unpause_params.py b/src/agentex/types/agents/schedule_pause_by_name_params.py similarity index 62% rename from src/agentex/types/agents/schedule_unpause_params.py rename to src/agentex/types/agents/schedule_pause_by_name_params.py index fa6341b96..4afc26a82 100644 --- a/src/agentex/types/agents/schedule_unpause_params.py +++ b/src/agentex/types/agents/schedule_pause_by_name_params.py @@ -5,11 +5,11 @@ from typing import Optional from typing_extensions import Required, TypedDict -__all__ = ["ScheduleUnpauseParams"] +__all__ = ["SchedulePauseByNameParams"] -class ScheduleUnpauseParams(TypedDict, total=False): +class SchedulePauseByNameParams(TypedDict, total=False): agent_id: Required[str] note: Optional[str] - """Optional note explaining why the schedule was unpaused""" + """Optional note explaining the pause.""" diff --git a/src/agentex/types/agents/schedule_pause_by_name_response.py b/src/agentex/types/agents/schedule_pause_by_name_response.py new file mode 100644 index 000000000..4c0ce1061 --- /dev/null +++ b/src/agentex/types/agents/schedule_pause_by_name_response.py @@ -0,0 +1,117 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import Dict, List, Optional +from datetime import datetime +from typing_extensions import Literal + +from ..._models import BaseModel +from ..message_author import MessageAuthor + +__all__ = ["SchedulePauseByNameResponse", "InitialInput", "CreatorPrincipal"] + + +class InitialInput(BaseModel): + """The initial input.""" + + content: str + """The initial prompt delivered to the task.""" + + author: Optional[MessageAuthor] = None + """The author attributed to the initial input.""" + + type: Optional[Literal["text"]] = None + """Input content type.""" + + +class CreatorPrincipal(BaseModel): + """Credential-free creator identity stored with the schedule. + + Never carries cookies, JWTs, API keys, OAuth tokens, or request headers — it + is creator *context* used only for AuthZ and ownership at fire time. + """ + + account_id: Optional[str] = None + """Account/workspace id of the creator.""" + + principal_type: Optional[str] = None + """e.g. 'user' or 'service_account'.""" + + service_account_id: Optional[str] = None + """Creator service-account id, if a service principal.""" + + user_id: Optional[str] = None + """Creator user id, if a user principal.""" + + +class SchedulePauseByNameResponse(BaseModel): + """Response model describing a scheduled agent run.""" + + id: str + """The unique identifier of the run schedule.""" + + agent_id: str + """The agent this schedule belongs to.""" + + initial_input: InitialInput + """The initial input.""" + + initial_input_method: str + """Delivery method, inferred from the agent's ACP type.""" + + name: str + """Human-readable schedule name.""" + + created_at: Optional[datetime] = None + """When the schedule was created.""" + + creator_principal: Optional[CreatorPrincipal] = None + """Credential-free creator identity stored with the schedule. + + Never carries cookies, JWTs, API keys, OAuth tokens, or request headers — it is + creator _context_ used only for AuthZ and ownership at fire time. + """ + + cron_expression: Optional[str] = None + """Cron cadence, if cron-based.""" + + description: Optional[str] = None + """Optional description.""" + + end_at: Optional[datetime] = None + """Schedule deactivation time.""" + + interval_seconds: Optional[int] = None + """Interval cadence in seconds, if interval-based.""" + + last_action_time: Optional[datetime] = None + """When the schedule last fired.""" + + next_action_times: Optional[List[datetime]] = None + """Upcoming scheduled fire times.""" + + num_actions_taken: Optional[int] = None + """Number of times the schedule has fired.""" + + paused: Optional[bool] = None + """Whether the schedule is paused.""" + + skipped_action_times: Optional[List[datetime]] = None + """Skipped one-off scheduled fire times.""" + + start_at: Optional[datetime] = None + """Schedule activation time.""" + + state: Optional[Literal["ACTIVE", "PAUSED"]] = None + """Live schedule state from Temporal.""" + + task_metadata: Optional[Dict[str, object]] = None + """Task metadata at fire time.""" + + task_params: Optional[Dict[str, object]] = None + """Task params at fire time.""" + + timezone: Optional[str] = None + """Timezone the cron expression is evaluated in.""" + + updated_at: Optional[datetime] = None + """When the schedule was updated.""" diff --git a/src/agentex/types/agents/schedule_pause_params.py b/src/agentex/types/agents/schedule_pause_params.py index 9832a49e2..73b9f5140 100644 --- a/src/agentex/types/agents/schedule_pause_params.py +++ b/src/agentex/types/agents/schedule_pause_params.py @@ -12,4 +12,4 @@ class SchedulePauseParams(TypedDict, total=False): agent_id: Required[str] note: Optional[str] - """Optional note explaining why the schedule was paused""" + """Optional note explaining the pause.""" diff --git a/src/agentex/types/agents/schedule_pause_response.py b/src/agentex/types/agents/schedule_pause_response.py index 2897fe810..c14c83443 100644 --- a/src/agentex/types/agents/schedule_pause_response.py +++ b/src/agentex/types/agents/schedule_pause_response.py @@ -1,78 +1,117 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -from typing import List, Optional +from typing import Dict, List, Optional from datetime import datetime from typing_extensions import Literal from ..._models import BaseModel +from ..message_author import MessageAuthor -__all__ = ["SchedulePauseResponse", "Action", "Spec"] +__all__ = ["SchedulePauseResponse", "InitialInput", "CreatorPrincipal"] -class Action(BaseModel): - """Information about the scheduled action""" +class InitialInput(BaseModel): + """The initial input.""" - task_queue: str - """Task queue for the workflow""" + content: str + """The initial prompt delivered to the task.""" - workflow_id_prefix: str - """Prefix for workflow execution IDs""" + author: Optional[MessageAuthor] = None + """The author attributed to the initial input.""" - workflow_name: str - """Name of the workflow being executed""" + type: Optional[Literal["text"]] = None + """Input content type.""" - workflow_params: Optional[List[object]] = None - """Parameters passed to the workflow""" +class CreatorPrincipal(BaseModel): + """Credential-free creator identity stored with the schedule. -class Spec(BaseModel): - """Schedule specification""" + Never carries cookies, JWTs, API keys, OAuth tokens, or request headers — it + is creator *context* used only for AuthZ and ownership at fire time. + """ - cron_expressions: Optional[List[str]] = None - """Cron expressions for the schedule""" + account_id: Optional[str] = None + """Account/workspace id of the creator.""" - end_at: Optional[datetime] = None - """When the schedule stops being active""" + principal_type: Optional[str] = None + """e.g. 'user' or 'service_account'.""" - intervals_seconds: Optional[List[int]] = None - """Interval specifications in seconds""" + service_account_id: Optional[str] = None + """Creator service-account id, if a service principal.""" - start_at: Optional[datetime] = None - """When the schedule starts being active""" + user_id: Optional[str] = None + """Creator user id, if a user principal.""" class SchedulePauseResponse(BaseModel): - """Response model for schedule operations""" + """Response model describing a scheduled agent run.""" - action: Action - """Information about the scheduled action""" + id: str + """The unique identifier of the run schedule.""" agent_id: str - """ID of the agent this schedule belongs to""" + """The agent this schedule belongs to.""" + + initial_input: InitialInput + """The initial input.""" + + initial_input_method: str + """Delivery method, inferred from the agent's ACP type.""" name: str - """Human-readable name for the schedule""" + """Human-readable schedule name.""" + + created_at: Optional[datetime] = None + """When the schedule was created.""" - schedule_id: str - """Unique identifier for the schedule""" + creator_principal: Optional[CreatorPrincipal] = None + """Credential-free creator identity stored with the schedule. - spec: Spec - """Schedule specification""" + Never carries cookies, JWTs, API keys, OAuth tokens, or request headers — it is + creator _context_ used only for AuthZ and ownership at fire time. + """ - state: Literal["ACTIVE", "PAUSED"] - """Current state of the schedule""" + cron_expression: Optional[str] = None + """Cron cadence, if cron-based.""" - created_at: Optional[datetime] = None - """When the schedule was created""" + description: Optional[str] = None + """Optional description.""" + + end_at: Optional[datetime] = None + """Schedule deactivation time.""" + + interval_seconds: Optional[int] = None + """Interval cadence in seconds, if interval-based.""" last_action_time: Optional[datetime] = None - """When the schedule last executed""" + """When the schedule last fired.""" next_action_times: Optional[List[datetime]] = None - """Upcoming scheduled execution times""" - - num_actions_missed: Optional[int] = None - """Number of scheduled executions that were missed""" + """Upcoming scheduled fire times.""" num_actions_taken: Optional[int] = None - """Number of times the schedule has executed""" + """Number of times the schedule has fired.""" + + paused: Optional[bool] = None + """Whether the schedule is paused.""" + + skipped_action_times: Optional[List[datetime]] = None + """Skipped one-off scheduled fire times.""" + + start_at: Optional[datetime] = None + """Schedule activation time.""" + + state: Optional[Literal["ACTIVE", "PAUSED"]] = None + """Live schedule state from Temporal.""" + + task_metadata: Optional[Dict[str, object]] = None + """Task metadata at fire time.""" + + task_params: Optional[Dict[str, object]] = None + """Task params at fire time.""" + + timezone: Optional[str] = None + """Timezone the cron expression is evaluated in.""" + + updated_at: Optional[datetime] = None + """When the schedule was updated.""" diff --git a/src/agentex/types/agents/schedule_resume_by_name_params.py b/src/agentex/types/agents/schedule_resume_by_name_params.py new file mode 100644 index 000000000..b8e5c514b --- /dev/null +++ b/src/agentex/types/agents/schedule_resume_by_name_params.py @@ -0,0 +1,15 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import Optional +from typing_extensions import Required, TypedDict + +__all__ = ["ScheduleResumeByNameParams"] + + +class ScheduleResumeByNameParams(TypedDict, total=False): + agent_id: Required[str] + + note: Optional[str] + """Optional note explaining the resume.""" diff --git a/src/agentex/types/agents/schedule_resume_by_name_response.py b/src/agentex/types/agents/schedule_resume_by_name_response.py new file mode 100644 index 000000000..6bdbcd329 --- /dev/null +++ b/src/agentex/types/agents/schedule_resume_by_name_response.py @@ -0,0 +1,117 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import Dict, List, Optional +from datetime import datetime +from typing_extensions import Literal + +from ..._models import BaseModel +from ..message_author import MessageAuthor + +__all__ = ["ScheduleResumeByNameResponse", "InitialInput", "CreatorPrincipal"] + + +class InitialInput(BaseModel): + """The initial input.""" + + content: str + """The initial prompt delivered to the task.""" + + author: Optional[MessageAuthor] = None + """The author attributed to the initial input.""" + + type: Optional[Literal["text"]] = None + """Input content type.""" + + +class CreatorPrincipal(BaseModel): + """Credential-free creator identity stored with the schedule. + + Never carries cookies, JWTs, API keys, OAuth tokens, or request headers — it + is creator *context* used only for AuthZ and ownership at fire time. + """ + + account_id: Optional[str] = None + """Account/workspace id of the creator.""" + + principal_type: Optional[str] = None + """e.g. 'user' or 'service_account'.""" + + service_account_id: Optional[str] = None + """Creator service-account id, if a service principal.""" + + user_id: Optional[str] = None + """Creator user id, if a user principal.""" + + +class ScheduleResumeByNameResponse(BaseModel): + """Response model describing a scheduled agent run.""" + + id: str + """The unique identifier of the run schedule.""" + + agent_id: str + """The agent this schedule belongs to.""" + + initial_input: InitialInput + """The initial input.""" + + initial_input_method: str + """Delivery method, inferred from the agent's ACP type.""" + + name: str + """Human-readable schedule name.""" + + created_at: Optional[datetime] = None + """When the schedule was created.""" + + creator_principal: Optional[CreatorPrincipal] = None + """Credential-free creator identity stored with the schedule. + + Never carries cookies, JWTs, API keys, OAuth tokens, or request headers — it is + creator _context_ used only for AuthZ and ownership at fire time. + """ + + cron_expression: Optional[str] = None + """Cron cadence, if cron-based.""" + + description: Optional[str] = None + """Optional description.""" + + end_at: Optional[datetime] = None + """Schedule deactivation time.""" + + interval_seconds: Optional[int] = None + """Interval cadence in seconds, if interval-based.""" + + last_action_time: Optional[datetime] = None + """When the schedule last fired.""" + + next_action_times: Optional[List[datetime]] = None + """Upcoming scheduled fire times.""" + + num_actions_taken: Optional[int] = None + """Number of times the schedule has fired.""" + + paused: Optional[bool] = None + """Whether the schedule is paused.""" + + skipped_action_times: Optional[List[datetime]] = None + """Skipped one-off scheduled fire times.""" + + start_at: Optional[datetime] = None + """Schedule activation time.""" + + state: Optional[Literal["ACTIVE", "PAUSED"]] = None + """Live schedule state from Temporal.""" + + task_metadata: Optional[Dict[str, object]] = None + """Task metadata at fire time.""" + + task_params: Optional[Dict[str, object]] = None + """Task params at fire time.""" + + timezone: Optional[str] = None + """Timezone the cron expression is evaluated in.""" + + updated_at: Optional[datetime] = None + """When the schedule was updated.""" diff --git a/src/agentex/types/agents/schedule_resume_params.py b/src/agentex/types/agents/schedule_resume_params.py new file mode 100644 index 000000000..7ebe2451d --- /dev/null +++ b/src/agentex/types/agents/schedule_resume_params.py @@ -0,0 +1,15 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import Optional +from typing_extensions import Required, TypedDict + +__all__ = ["ScheduleResumeParams"] + + +class ScheduleResumeParams(TypedDict, total=False): + agent_id: Required[str] + + note: Optional[str] + """Optional note explaining the resume.""" diff --git a/src/agentex/types/agents/schedule_resume_response.py b/src/agentex/types/agents/schedule_resume_response.py new file mode 100644 index 000000000..907792401 --- /dev/null +++ b/src/agentex/types/agents/schedule_resume_response.py @@ -0,0 +1,117 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import Dict, List, Optional +from datetime import datetime +from typing_extensions import Literal + +from ..._models import BaseModel +from ..message_author import MessageAuthor + +__all__ = ["ScheduleResumeResponse", "InitialInput", "CreatorPrincipal"] + + +class InitialInput(BaseModel): + """The initial input.""" + + content: str + """The initial prompt delivered to the task.""" + + author: Optional[MessageAuthor] = None + """The author attributed to the initial input.""" + + type: Optional[Literal["text"]] = None + """Input content type.""" + + +class CreatorPrincipal(BaseModel): + """Credential-free creator identity stored with the schedule. + + Never carries cookies, JWTs, API keys, OAuth tokens, or request headers — it + is creator *context* used only for AuthZ and ownership at fire time. + """ + + account_id: Optional[str] = None + """Account/workspace id of the creator.""" + + principal_type: Optional[str] = None + """e.g. 'user' or 'service_account'.""" + + service_account_id: Optional[str] = None + """Creator service-account id, if a service principal.""" + + user_id: Optional[str] = None + """Creator user id, if a user principal.""" + + +class ScheduleResumeResponse(BaseModel): + """Response model describing a scheduled agent run.""" + + id: str + """The unique identifier of the run schedule.""" + + agent_id: str + """The agent this schedule belongs to.""" + + initial_input: InitialInput + """The initial input.""" + + initial_input_method: str + """Delivery method, inferred from the agent's ACP type.""" + + name: str + """Human-readable schedule name.""" + + created_at: Optional[datetime] = None + """When the schedule was created.""" + + creator_principal: Optional[CreatorPrincipal] = None + """Credential-free creator identity stored with the schedule. + + Never carries cookies, JWTs, API keys, OAuth tokens, or request headers — it is + creator _context_ used only for AuthZ and ownership at fire time. + """ + + cron_expression: Optional[str] = None + """Cron cadence, if cron-based.""" + + description: Optional[str] = None + """Optional description.""" + + end_at: Optional[datetime] = None + """Schedule deactivation time.""" + + interval_seconds: Optional[int] = None + """Interval cadence in seconds, if interval-based.""" + + last_action_time: Optional[datetime] = None + """When the schedule last fired.""" + + next_action_times: Optional[List[datetime]] = None + """Upcoming scheduled fire times.""" + + num_actions_taken: Optional[int] = None + """Number of times the schedule has fired.""" + + paused: Optional[bool] = None + """Whether the schedule is paused.""" + + skipped_action_times: Optional[List[datetime]] = None + """Skipped one-off scheduled fire times.""" + + start_at: Optional[datetime] = None + """Schedule activation time.""" + + state: Optional[Literal["ACTIVE", "PAUSED"]] = None + """Live schedule state from Temporal.""" + + task_metadata: Optional[Dict[str, object]] = None + """Task metadata at fire time.""" + + task_params: Optional[Dict[str, object]] = None + """Task params at fire time.""" + + timezone: Optional[str] = None + """Timezone the cron expression is evaluated in.""" + + updated_at: Optional[datetime] = None + """When the schedule was updated.""" diff --git a/src/agentex/types/agents/schedule_retrieve_by_name_response.py b/src/agentex/types/agents/schedule_retrieve_by_name_response.py new file mode 100644 index 000000000..31663f41a --- /dev/null +++ b/src/agentex/types/agents/schedule_retrieve_by_name_response.py @@ -0,0 +1,117 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import Dict, List, Optional +from datetime import datetime +from typing_extensions import Literal + +from ..._models import BaseModel +from ..message_author import MessageAuthor + +__all__ = ["ScheduleRetrieveByNameResponse", "InitialInput", "CreatorPrincipal"] + + +class InitialInput(BaseModel): + """The initial input.""" + + content: str + """The initial prompt delivered to the task.""" + + author: Optional[MessageAuthor] = None + """The author attributed to the initial input.""" + + type: Optional[Literal["text"]] = None + """Input content type.""" + + +class CreatorPrincipal(BaseModel): + """Credential-free creator identity stored with the schedule. + + Never carries cookies, JWTs, API keys, OAuth tokens, or request headers — it + is creator *context* used only for AuthZ and ownership at fire time. + """ + + account_id: Optional[str] = None + """Account/workspace id of the creator.""" + + principal_type: Optional[str] = None + """e.g. 'user' or 'service_account'.""" + + service_account_id: Optional[str] = None + """Creator service-account id, if a service principal.""" + + user_id: Optional[str] = None + """Creator user id, if a user principal.""" + + +class ScheduleRetrieveByNameResponse(BaseModel): + """Response model describing a scheduled agent run.""" + + id: str + """The unique identifier of the run schedule.""" + + agent_id: str + """The agent this schedule belongs to.""" + + initial_input: InitialInput + """The initial input.""" + + initial_input_method: str + """Delivery method, inferred from the agent's ACP type.""" + + name: str + """Human-readable schedule name.""" + + created_at: Optional[datetime] = None + """When the schedule was created.""" + + creator_principal: Optional[CreatorPrincipal] = None + """Credential-free creator identity stored with the schedule. + + Never carries cookies, JWTs, API keys, OAuth tokens, or request headers — it is + creator _context_ used only for AuthZ and ownership at fire time. + """ + + cron_expression: Optional[str] = None + """Cron cadence, if cron-based.""" + + description: Optional[str] = None + """Optional description.""" + + end_at: Optional[datetime] = None + """Schedule deactivation time.""" + + interval_seconds: Optional[int] = None + """Interval cadence in seconds, if interval-based.""" + + last_action_time: Optional[datetime] = None + """When the schedule last fired.""" + + next_action_times: Optional[List[datetime]] = None + """Upcoming scheduled fire times.""" + + num_actions_taken: Optional[int] = None + """Number of times the schedule has fired.""" + + paused: Optional[bool] = None + """Whether the schedule is paused.""" + + skipped_action_times: Optional[List[datetime]] = None + """Skipped one-off scheduled fire times.""" + + start_at: Optional[datetime] = None + """Schedule activation time.""" + + state: Optional[Literal["ACTIVE", "PAUSED"]] = None + """Live schedule state from Temporal.""" + + task_metadata: Optional[Dict[str, object]] = None + """Task metadata at fire time.""" + + task_params: Optional[Dict[str, object]] = None + """Task params at fire time.""" + + timezone: Optional[str] = None + """Timezone the cron expression is evaluated in.""" + + updated_at: Optional[datetime] = None + """When the schedule was updated.""" diff --git a/src/agentex/types/agents/schedule_retrieve_response.py b/src/agentex/types/agents/schedule_retrieve_response.py index e3a840a63..20375347e 100644 --- a/src/agentex/types/agents/schedule_retrieve_response.py +++ b/src/agentex/types/agents/schedule_retrieve_response.py @@ -1,78 +1,117 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -from typing import List, Optional +from typing import Dict, List, Optional from datetime import datetime from typing_extensions import Literal from ..._models import BaseModel +from ..message_author import MessageAuthor -__all__ = ["ScheduleRetrieveResponse", "Action", "Spec"] +__all__ = ["ScheduleRetrieveResponse", "InitialInput", "CreatorPrincipal"] -class Action(BaseModel): - """Information about the scheduled action""" +class InitialInput(BaseModel): + """The initial input.""" - task_queue: str - """Task queue for the workflow""" + content: str + """The initial prompt delivered to the task.""" - workflow_id_prefix: str - """Prefix for workflow execution IDs""" + author: Optional[MessageAuthor] = None + """The author attributed to the initial input.""" - workflow_name: str - """Name of the workflow being executed""" + type: Optional[Literal["text"]] = None + """Input content type.""" - workflow_params: Optional[List[object]] = None - """Parameters passed to the workflow""" +class CreatorPrincipal(BaseModel): + """Credential-free creator identity stored with the schedule. -class Spec(BaseModel): - """Schedule specification""" + Never carries cookies, JWTs, API keys, OAuth tokens, or request headers — it + is creator *context* used only for AuthZ and ownership at fire time. + """ - cron_expressions: Optional[List[str]] = None - """Cron expressions for the schedule""" + account_id: Optional[str] = None + """Account/workspace id of the creator.""" - end_at: Optional[datetime] = None - """When the schedule stops being active""" + principal_type: Optional[str] = None + """e.g. 'user' or 'service_account'.""" - intervals_seconds: Optional[List[int]] = None - """Interval specifications in seconds""" + service_account_id: Optional[str] = None + """Creator service-account id, if a service principal.""" - start_at: Optional[datetime] = None - """When the schedule starts being active""" + user_id: Optional[str] = None + """Creator user id, if a user principal.""" class ScheduleRetrieveResponse(BaseModel): - """Response model for schedule operations""" + """Response model describing a scheduled agent run.""" - action: Action - """Information about the scheduled action""" + id: str + """The unique identifier of the run schedule.""" agent_id: str - """ID of the agent this schedule belongs to""" + """The agent this schedule belongs to.""" + + initial_input: InitialInput + """The initial input.""" + + initial_input_method: str + """Delivery method, inferred from the agent's ACP type.""" name: str - """Human-readable name for the schedule""" + """Human-readable schedule name.""" + + created_at: Optional[datetime] = None + """When the schedule was created.""" - schedule_id: str - """Unique identifier for the schedule""" + creator_principal: Optional[CreatorPrincipal] = None + """Credential-free creator identity stored with the schedule. - spec: Spec - """Schedule specification""" + Never carries cookies, JWTs, API keys, OAuth tokens, or request headers — it is + creator _context_ used only for AuthZ and ownership at fire time. + """ - state: Literal["ACTIVE", "PAUSED"] - """Current state of the schedule""" + cron_expression: Optional[str] = None + """Cron cadence, if cron-based.""" - created_at: Optional[datetime] = None - """When the schedule was created""" + description: Optional[str] = None + """Optional description.""" + + end_at: Optional[datetime] = None + """Schedule deactivation time.""" + + interval_seconds: Optional[int] = None + """Interval cadence in seconds, if interval-based.""" last_action_time: Optional[datetime] = None - """When the schedule last executed""" + """When the schedule last fired.""" next_action_times: Optional[List[datetime]] = None - """Upcoming scheduled execution times""" - - num_actions_missed: Optional[int] = None - """Number of scheduled executions that were missed""" + """Upcoming scheduled fire times.""" num_actions_taken: Optional[int] = None - """Number of times the schedule has executed""" + """Number of times the schedule has fired.""" + + paused: Optional[bool] = None + """Whether the schedule is paused.""" + + skipped_action_times: Optional[List[datetime]] = None + """Skipped one-off scheduled fire times.""" + + start_at: Optional[datetime] = None + """Schedule activation time.""" + + state: Optional[Literal["ACTIVE", "PAUSED"]] = None + """Live schedule state from Temporal.""" + + task_metadata: Optional[Dict[str, object]] = None + """Task metadata at fire time.""" + + task_params: Optional[Dict[str, object]] = None + """Task params at fire time.""" + + timezone: Optional[str] = None + """Timezone the cron expression is evaluated in.""" + + updated_at: Optional[datetime] = None + """When the schedule was updated.""" diff --git a/src/agentex/types/agents/schedule_trigger_by_name_response.py b/src/agentex/types/agents/schedule_trigger_by_name_response.py new file mode 100644 index 000000000..036cf72f3 --- /dev/null +++ b/src/agentex/types/agents/schedule_trigger_by_name_response.py @@ -0,0 +1,117 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import Dict, List, Optional +from datetime import datetime +from typing_extensions import Literal + +from ..._models import BaseModel +from ..message_author import MessageAuthor + +__all__ = ["ScheduleTriggerByNameResponse", "InitialInput", "CreatorPrincipal"] + + +class InitialInput(BaseModel): + """The initial input.""" + + content: str + """The initial prompt delivered to the task.""" + + author: Optional[MessageAuthor] = None + """The author attributed to the initial input.""" + + type: Optional[Literal["text"]] = None + """Input content type.""" + + +class CreatorPrincipal(BaseModel): + """Credential-free creator identity stored with the schedule. + + Never carries cookies, JWTs, API keys, OAuth tokens, or request headers — it + is creator *context* used only for AuthZ and ownership at fire time. + """ + + account_id: Optional[str] = None + """Account/workspace id of the creator.""" + + principal_type: Optional[str] = None + """e.g. 'user' or 'service_account'.""" + + service_account_id: Optional[str] = None + """Creator service-account id, if a service principal.""" + + user_id: Optional[str] = None + """Creator user id, if a user principal.""" + + +class ScheduleTriggerByNameResponse(BaseModel): + """Response model describing a scheduled agent run.""" + + id: str + """The unique identifier of the run schedule.""" + + agent_id: str + """The agent this schedule belongs to.""" + + initial_input: InitialInput + """The initial input.""" + + initial_input_method: str + """Delivery method, inferred from the agent's ACP type.""" + + name: str + """Human-readable schedule name.""" + + created_at: Optional[datetime] = None + """When the schedule was created.""" + + creator_principal: Optional[CreatorPrincipal] = None + """Credential-free creator identity stored with the schedule. + + Never carries cookies, JWTs, API keys, OAuth tokens, or request headers — it is + creator _context_ used only for AuthZ and ownership at fire time. + """ + + cron_expression: Optional[str] = None + """Cron cadence, if cron-based.""" + + description: Optional[str] = None + """Optional description.""" + + end_at: Optional[datetime] = None + """Schedule deactivation time.""" + + interval_seconds: Optional[int] = None + """Interval cadence in seconds, if interval-based.""" + + last_action_time: Optional[datetime] = None + """When the schedule last fired.""" + + next_action_times: Optional[List[datetime]] = None + """Upcoming scheduled fire times.""" + + num_actions_taken: Optional[int] = None + """Number of times the schedule has fired.""" + + paused: Optional[bool] = None + """Whether the schedule is paused.""" + + skipped_action_times: Optional[List[datetime]] = None + """Skipped one-off scheduled fire times.""" + + start_at: Optional[datetime] = None + """Schedule activation time.""" + + state: Optional[Literal["ACTIVE", "PAUSED"]] = None + """Live schedule state from Temporal.""" + + task_metadata: Optional[Dict[str, object]] = None + """Task metadata at fire time.""" + + task_params: Optional[Dict[str, object]] = None + """Task params at fire time.""" + + timezone: Optional[str] = None + """Timezone the cron expression is evaluated in.""" + + updated_at: Optional[datetime] = None + """When the schedule was updated.""" diff --git a/src/agentex/types/agents/schedule_trigger_response.py b/src/agentex/types/agents/schedule_trigger_response.py index ab65d1789..22695f9c0 100644 --- a/src/agentex/types/agents/schedule_trigger_response.py +++ b/src/agentex/types/agents/schedule_trigger_response.py @@ -1,78 +1,117 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -from typing import List, Optional +from typing import Dict, List, Optional from datetime import datetime from typing_extensions import Literal from ..._models import BaseModel +from ..message_author import MessageAuthor -__all__ = ["ScheduleTriggerResponse", "Action", "Spec"] +__all__ = ["ScheduleTriggerResponse", "InitialInput", "CreatorPrincipal"] -class Action(BaseModel): - """Information about the scheduled action""" +class InitialInput(BaseModel): + """The initial input.""" - task_queue: str - """Task queue for the workflow""" + content: str + """The initial prompt delivered to the task.""" - workflow_id_prefix: str - """Prefix for workflow execution IDs""" + author: Optional[MessageAuthor] = None + """The author attributed to the initial input.""" - workflow_name: str - """Name of the workflow being executed""" + type: Optional[Literal["text"]] = None + """Input content type.""" - workflow_params: Optional[List[object]] = None - """Parameters passed to the workflow""" +class CreatorPrincipal(BaseModel): + """Credential-free creator identity stored with the schedule. -class Spec(BaseModel): - """Schedule specification""" + Never carries cookies, JWTs, API keys, OAuth tokens, or request headers — it + is creator *context* used only for AuthZ and ownership at fire time. + """ - cron_expressions: Optional[List[str]] = None - """Cron expressions for the schedule""" + account_id: Optional[str] = None + """Account/workspace id of the creator.""" - end_at: Optional[datetime] = None - """When the schedule stops being active""" + principal_type: Optional[str] = None + """e.g. 'user' or 'service_account'.""" - intervals_seconds: Optional[List[int]] = None - """Interval specifications in seconds""" + service_account_id: Optional[str] = None + """Creator service-account id, if a service principal.""" - start_at: Optional[datetime] = None - """When the schedule starts being active""" + user_id: Optional[str] = None + """Creator user id, if a user principal.""" class ScheduleTriggerResponse(BaseModel): - """Response model for schedule operations""" + """Response model describing a scheduled agent run.""" - action: Action - """Information about the scheduled action""" + id: str + """The unique identifier of the run schedule.""" agent_id: str - """ID of the agent this schedule belongs to""" + """The agent this schedule belongs to.""" + + initial_input: InitialInput + """The initial input.""" + + initial_input_method: str + """Delivery method, inferred from the agent's ACP type.""" name: str - """Human-readable name for the schedule""" + """Human-readable schedule name.""" + + created_at: Optional[datetime] = None + """When the schedule was created.""" - schedule_id: str - """Unique identifier for the schedule""" + creator_principal: Optional[CreatorPrincipal] = None + """Credential-free creator identity stored with the schedule. - spec: Spec - """Schedule specification""" + Never carries cookies, JWTs, API keys, OAuth tokens, or request headers — it is + creator _context_ used only for AuthZ and ownership at fire time. + """ - state: Literal["ACTIVE", "PAUSED"] - """Current state of the schedule""" + cron_expression: Optional[str] = None + """Cron cadence, if cron-based.""" - created_at: Optional[datetime] = None - """When the schedule was created""" + description: Optional[str] = None + """Optional description.""" + + end_at: Optional[datetime] = None + """Schedule deactivation time.""" + + interval_seconds: Optional[int] = None + """Interval cadence in seconds, if interval-based.""" last_action_time: Optional[datetime] = None - """When the schedule last executed""" + """When the schedule last fired.""" next_action_times: Optional[List[datetime]] = None - """Upcoming scheduled execution times""" - - num_actions_missed: Optional[int] = None - """Number of scheduled executions that were missed""" + """Upcoming scheduled fire times.""" num_actions_taken: Optional[int] = None - """Number of times the schedule has executed""" + """Number of times the schedule has fired.""" + + paused: Optional[bool] = None + """Whether the schedule is paused.""" + + skipped_action_times: Optional[List[datetime]] = None + """Skipped one-off scheduled fire times.""" + + start_at: Optional[datetime] = None + """Schedule activation time.""" + + state: Optional[Literal["ACTIVE", "PAUSED"]] = None + """Live schedule state from Temporal.""" + + task_metadata: Optional[Dict[str, object]] = None + """Task metadata at fire time.""" + + task_params: Optional[Dict[str, object]] = None + """Task params at fire time.""" + + timezone: Optional[str] = None + """Timezone the cron expression is evaluated in.""" + + updated_at: Optional[datetime] = None + """When the schedule was updated.""" diff --git a/src/agentex/types/agents/schedule_unpause_response.py b/src/agentex/types/agents/schedule_unpause_response.py deleted file mode 100644 index 188567a20..000000000 --- a/src/agentex/types/agents/schedule_unpause_response.py +++ /dev/null @@ -1,78 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from typing import List, Optional -from datetime import datetime -from typing_extensions import Literal - -from ..._models import BaseModel - -__all__ = ["ScheduleUnpauseResponse", "Action", "Spec"] - - -class Action(BaseModel): - """Information about the scheduled action""" - - task_queue: str - """Task queue for the workflow""" - - workflow_id_prefix: str - """Prefix for workflow execution IDs""" - - workflow_name: str - """Name of the workflow being executed""" - - workflow_params: Optional[List[object]] = None - """Parameters passed to the workflow""" - - -class Spec(BaseModel): - """Schedule specification""" - - cron_expressions: Optional[List[str]] = None - """Cron expressions for the schedule""" - - end_at: Optional[datetime] = None - """When the schedule stops being active""" - - intervals_seconds: Optional[List[int]] = None - """Interval specifications in seconds""" - - start_at: Optional[datetime] = None - """When the schedule starts being active""" - - -class ScheduleUnpauseResponse(BaseModel): - """Response model for schedule operations""" - - action: Action - """Information about the scheduled action""" - - agent_id: str - """ID of the agent this schedule belongs to""" - - name: str - """Human-readable name for the schedule""" - - schedule_id: str - """Unique identifier for the schedule""" - - spec: Spec - """Schedule specification""" - - state: Literal["ACTIVE", "PAUSED"] - """Current state of the schedule""" - - created_at: Optional[datetime] = None - """When the schedule was created""" - - last_action_time: Optional[datetime] = None - """When the schedule last executed""" - - next_action_times: Optional[List[datetime]] = None - """Upcoming scheduled execution times""" - - num_actions_missed: Optional[int] = None - """Number of scheduled executions that were missed""" - - num_actions_taken: Optional[int] = None - """Number of times the schedule has executed""" diff --git a/src/agentex/types/agents/schedule_update_by_name_params.py b/src/agentex/types/agents/schedule_update_by_name_params.py new file mode 100644 index 000000000..0c15e199f --- /dev/null +++ b/src/agentex/types/agents/schedule_update_by_name_params.py @@ -0,0 +1,62 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import Dict, Union, Optional +from datetime import datetime +from typing_extensions import Literal, Required, Annotated, TypedDict + +from ..._utils import PropertyInfo +from ..message_author import MessageAuthor + +__all__ = ["ScheduleUpdateByNameParams", "InitialInput"] + + +class ScheduleUpdateByNameParams(TypedDict, total=False): + agent_id: Required[str] + + cron_expression: Optional[str] + """New cron cadence. Mutually exclusive with interval_seconds.""" + + description: Optional[str] + """Optional description of what this schedule does.""" + + end_at: Annotated[Union[str, datetime, None], PropertyInfo(format="iso8601")] + """When the schedule should stop being active.""" + + initial_input: Optional[InitialInput] + """The first input delivered to each freshly created scheduled task.""" + + interval_seconds: Optional[int] + """New interval cadence in seconds. Mutually exclusive with cron_expression.""" + + body_name: Annotated[Optional[str], PropertyInfo(alias="name")] + """Human-readable name, unique among active schedules for the agent.""" + + paused: Optional[bool] + """Pause/resume the schedule as part of the update.""" + + start_at: Annotated[Union[str, datetime, None], PropertyInfo(format="iso8601")] + """When the schedule should start being active.""" + + task_metadata: Optional[Dict[str, object]] + """Metadata copied onto each created task at fire time.""" + + task_params: Optional[Dict[str, object]] + """Resolved config forwarded as task `params` at fire time.""" + + timezone: Optional[str] + """IANA timezone the cron expression is evaluated in.""" + + +class InitialInput(TypedDict, total=False): + """The first input delivered to each freshly created scheduled task.""" + + content: Required[str] + """The initial prompt delivered to the task.""" + + author: MessageAuthor + """The author attributed to the initial input.""" + + type: Literal["text"] + """Input content type.""" diff --git a/src/agentex/types/agents/schedule_update_by_name_response.py b/src/agentex/types/agents/schedule_update_by_name_response.py new file mode 100644 index 000000000..8e8fd2112 --- /dev/null +++ b/src/agentex/types/agents/schedule_update_by_name_response.py @@ -0,0 +1,117 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import Dict, List, Optional +from datetime import datetime +from typing_extensions import Literal + +from ..._models import BaseModel +from ..message_author import MessageAuthor + +__all__ = ["ScheduleUpdateByNameResponse", "InitialInput", "CreatorPrincipal"] + + +class InitialInput(BaseModel): + """The initial input.""" + + content: str + """The initial prompt delivered to the task.""" + + author: Optional[MessageAuthor] = None + """The author attributed to the initial input.""" + + type: Optional[Literal["text"]] = None + """Input content type.""" + + +class CreatorPrincipal(BaseModel): + """Credential-free creator identity stored with the schedule. + + Never carries cookies, JWTs, API keys, OAuth tokens, or request headers — it + is creator *context* used only for AuthZ and ownership at fire time. + """ + + account_id: Optional[str] = None + """Account/workspace id of the creator.""" + + principal_type: Optional[str] = None + """e.g. 'user' or 'service_account'.""" + + service_account_id: Optional[str] = None + """Creator service-account id, if a service principal.""" + + user_id: Optional[str] = None + """Creator user id, if a user principal.""" + + +class ScheduleUpdateByNameResponse(BaseModel): + """Response model describing a scheduled agent run.""" + + id: str + """The unique identifier of the run schedule.""" + + agent_id: str + """The agent this schedule belongs to.""" + + initial_input: InitialInput + """The initial input.""" + + initial_input_method: str + """Delivery method, inferred from the agent's ACP type.""" + + name: str + """Human-readable schedule name.""" + + created_at: Optional[datetime] = None + """When the schedule was created.""" + + creator_principal: Optional[CreatorPrincipal] = None + """Credential-free creator identity stored with the schedule. + + Never carries cookies, JWTs, API keys, OAuth tokens, or request headers — it is + creator _context_ used only for AuthZ and ownership at fire time. + """ + + cron_expression: Optional[str] = None + """Cron cadence, if cron-based.""" + + description: Optional[str] = None + """Optional description.""" + + end_at: Optional[datetime] = None + """Schedule deactivation time.""" + + interval_seconds: Optional[int] = None + """Interval cadence in seconds, if interval-based.""" + + last_action_time: Optional[datetime] = None + """When the schedule last fired.""" + + next_action_times: Optional[List[datetime]] = None + """Upcoming scheduled fire times.""" + + num_actions_taken: Optional[int] = None + """Number of times the schedule has fired.""" + + paused: Optional[bool] = None + """Whether the schedule is paused.""" + + skipped_action_times: Optional[List[datetime]] = None + """Skipped one-off scheduled fire times.""" + + start_at: Optional[datetime] = None + """Schedule activation time.""" + + state: Optional[Literal["ACTIVE", "PAUSED"]] = None + """Live schedule state from Temporal.""" + + task_metadata: Optional[Dict[str, object]] = None + """Task metadata at fire time.""" + + task_params: Optional[Dict[str, object]] = None + """Task params at fire time.""" + + timezone: Optional[str] = None + """Timezone the cron expression is evaluated in.""" + + updated_at: Optional[datetime] = None + """When the schedule was updated.""" diff --git a/src/agentex/types/agents/schedule_update_params.py b/src/agentex/types/agents/schedule_update_params.py new file mode 100644 index 000000000..0c3b6254b --- /dev/null +++ b/src/agentex/types/agents/schedule_update_params.py @@ -0,0 +1,62 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import Dict, Union, Optional +from datetime import datetime +from typing_extensions import Literal, Required, Annotated, TypedDict + +from ..._utils import PropertyInfo +from ..message_author import MessageAuthor + +__all__ = ["ScheduleUpdateParams", "InitialInput"] + + +class ScheduleUpdateParams(TypedDict, total=False): + agent_id: Required[str] + + cron_expression: Optional[str] + """New cron cadence. Mutually exclusive with interval_seconds.""" + + description: Optional[str] + """Optional description of what this schedule does.""" + + end_at: Annotated[Union[str, datetime, None], PropertyInfo(format="iso8601")] + """When the schedule should stop being active.""" + + initial_input: Optional[InitialInput] + """The first input delivered to each freshly created scheduled task.""" + + interval_seconds: Optional[int] + """New interval cadence in seconds. Mutually exclusive with cron_expression.""" + + name: Optional[str] + """Human-readable name, unique among active schedules for the agent.""" + + paused: Optional[bool] + """Pause/resume the schedule as part of the update.""" + + start_at: Annotated[Union[str, datetime, None], PropertyInfo(format="iso8601")] + """When the schedule should start being active.""" + + task_metadata: Optional[Dict[str, object]] + """Metadata copied onto each created task at fire time.""" + + task_params: Optional[Dict[str, object]] + """Resolved config forwarded as task `params` at fire time.""" + + timezone: Optional[str] + """IANA timezone the cron expression is evaluated in.""" + + +class InitialInput(TypedDict, total=False): + """The first input delivered to each freshly created scheduled task.""" + + content: Required[str] + """The initial prompt delivered to the task.""" + + author: MessageAuthor + """The author attributed to the initial input.""" + + type: Literal["text"] + """Input content type.""" diff --git a/src/agentex/types/agents/schedule_update_response.py b/src/agentex/types/agents/schedule_update_response.py new file mode 100644 index 000000000..a27701d21 --- /dev/null +++ b/src/agentex/types/agents/schedule_update_response.py @@ -0,0 +1,117 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import Dict, List, Optional +from datetime import datetime +from typing_extensions import Literal + +from ..._models import BaseModel +from ..message_author import MessageAuthor + +__all__ = ["ScheduleUpdateResponse", "InitialInput", "CreatorPrincipal"] + + +class InitialInput(BaseModel): + """The initial input.""" + + content: str + """The initial prompt delivered to the task.""" + + author: Optional[MessageAuthor] = None + """The author attributed to the initial input.""" + + type: Optional[Literal["text"]] = None + """Input content type.""" + + +class CreatorPrincipal(BaseModel): + """Credential-free creator identity stored with the schedule. + + Never carries cookies, JWTs, API keys, OAuth tokens, or request headers — it + is creator *context* used only for AuthZ and ownership at fire time. + """ + + account_id: Optional[str] = None + """Account/workspace id of the creator.""" + + principal_type: Optional[str] = None + """e.g. 'user' or 'service_account'.""" + + service_account_id: Optional[str] = None + """Creator service-account id, if a service principal.""" + + user_id: Optional[str] = None + """Creator user id, if a user principal.""" + + +class ScheduleUpdateResponse(BaseModel): + """Response model describing a scheduled agent run.""" + + id: str + """The unique identifier of the run schedule.""" + + agent_id: str + """The agent this schedule belongs to.""" + + initial_input: InitialInput + """The initial input.""" + + initial_input_method: str + """Delivery method, inferred from the agent's ACP type.""" + + name: str + """Human-readable schedule name.""" + + created_at: Optional[datetime] = None + """When the schedule was created.""" + + creator_principal: Optional[CreatorPrincipal] = None + """Credential-free creator identity stored with the schedule. + + Never carries cookies, JWTs, API keys, OAuth tokens, or request headers — it is + creator _context_ used only for AuthZ and ownership at fire time. + """ + + cron_expression: Optional[str] = None + """Cron cadence, if cron-based.""" + + description: Optional[str] = None + """Optional description.""" + + end_at: Optional[datetime] = None + """Schedule deactivation time.""" + + interval_seconds: Optional[int] = None + """Interval cadence in seconds, if interval-based.""" + + last_action_time: Optional[datetime] = None + """When the schedule last fired.""" + + next_action_times: Optional[List[datetime]] = None + """Upcoming scheduled fire times.""" + + num_actions_taken: Optional[int] = None + """Number of times the schedule has fired.""" + + paused: Optional[bool] = None + """Whether the schedule is paused.""" + + skipped_action_times: Optional[List[datetime]] = None + """Skipped one-off scheduled fire times.""" + + start_at: Optional[datetime] = None + """Schedule activation time.""" + + state: Optional[Literal["ACTIVE", "PAUSED"]] = None + """Live schedule state from Temporal.""" + + task_metadata: Optional[Dict[str, object]] = None + """Task metadata at fire time.""" + + task_params: Optional[Dict[str, object]] = None + """Task params at fire time.""" + + timezone: Optional[str] = None + """Timezone the cron expression is evaluated in.""" + + updated_at: Optional[datetime] = None + """When the schedule was updated.""" diff --git a/tests/api_resources/agents/test_schedules.py b/tests/api_resources/agents/test_schedules.py index 0431de18e..ff8d75117 100644 --- a/tests/api_resources/agents/test_schedules.py +++ b/tests/api_resources/agents/test_schedules.py @@ -13,9 +13,15 @@ ScheduleListResponse, SchedulePauseResponse, ScheduleCreateResponse, + ScheduleResumeResponse, + ScheduleUpdateResponse, ScheduleTriggerResponse, - ScheduleUnpauseResponse, ScheduleRetrieveResponse, + SchedulePauseByNameResponse, + ScheduleResumeByNameResponse, + ScheduleUpdateByNameResponse, + ScheduleTriggerByNameResponse, + ScheduleRetrieveByNameResponse, ) from agentex.types.shared import DeleteResponse @@ -32,9 +38,8 @@ class TestSchedules: def test_method_create(self, client: Agentex) -> None: schedule = client.agents.schedules.create( agent_id="agent_id", + initial_input={"content": "content"}, name="name", - task_queue="task_queue", - workflow_name="workflow_name", ) assert_matches_type(ScheduleCreateResponse, schedule, path=["response"]) @@ -43,16 +48,21 @@ def test_method_create(self, client: Agentex) -> None: def test_method_create_with_all_params(self, client: Agentex) -> None: schedule = client.agents.schedules.create( agent_id="agent_id", + initial_input={ + "content": "content", + "author": "user", + "type": "text", + }, name="name", - task_queue="task_queue", - workflow_name="workflow_name", cron_expression="cron_expression", + description="description", end_at=parse_datetime("2019-12-27T18:11:19.117Z"), - execution_timeout_seconds=1, interval_seconds=1, paused=True, start_at=parse_datetime("2019-12-27T18:11:19.117Z"), - workflow_params={"foo": "bar"}, + task_metadata={"foo": "bar"}, + task_params={"foo": "bar"}, + timezone="timezone", ) assert_matches_type(ScheduleCreateResponse, schedule, path=["response"]) @@ -61,9 +71,8 @@ def test_method_create_with_all_params(self, client: Agentex) -> None: def test_raw_response_create(self, client: Agentex) -> None: response = client.agents.schedules.with_raw_response.create( agent_id="agent_id", + initial_input={"content": "content"}, name="name", - task_queue="task_queue", - workflow_name="workflow_name", ) assert response.is_closed is True @@ -76,9 +85,8 @@ def test_raw_response_create(self, client: Agentex) -> None: def test_streaming_response_create(self, client: Agentex) -> None: with client.agents.schedules.with_streaming_response.create( agent_id="agent_id", + initial_input={"content": "content"}, name="name", - task_queue="task_queue", - workflow_name="workflow_name", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -94,16 +102,15 @@ def test_path_params_create(self, client: Agentex) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `agent_id` but received ''"): client.agents.schedules.with_raw_response.create( agent_id="", + initial_input={"content": "content"}, name="name", - task_queue="task_queue", - workflow_name="workflow_name", ) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize def test_method_retrieve(self, client: Agentex) -> None: schedule = client.agents.schedules.retrieve( - schedule_name="schedule_name", + schedule_id="schedule_id", agent_id="agent_id", ) assert_matches_type(ScheduleRetrieveResponse, schedule, path=["response"]) @@ -112,7 +119,7 @@ def test_method_retrieve(self, client: Agentex) -> None: @parametrize def test_raw_response_retrieve(self, client: Agentex) -> None: response = client.agents.schedules.with_raw_response.retrieve( - schedule_name="schedule_name", + schedule_id="schedule_id", agent_id="agent_id", ) @@ -125,7 +132,7 @@ def test_raw_response_retrieve(self, client: Agentex) -> None: @parametrize def test_streaming_response_retrieve(self, client: Agentex) -> None: with client.agents.schedules.with_streaming_response.retrieve( - schedule_name="schedule_name", + schedule_id="schedule_id", agent_id="agent_id", ) as response: assert not response.is_closed @@ -141,13 +148,89 @@ def test_streaming_response_retrieve(self, client: Agentex) -> None: def test_path_params_retrieve(self, client: Agentex) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `agent_id` but received ''"): client.agents.schedules.with_raw_response.retrieve( - schedule_name="schedule_name", + schedule_id="schedule_id", agent_id="", ) - with pytest.raises(ValueError, match=r"Expected a non-empty value for `schedule_name` but received ''"): + with pytest.raises(ValueError, match=r"Expected a non-empty value for `schedule_id` but received ''"): client.agents.schedules.with_raw_response.retrieve( - schedule_name="", + schedule_id="", + agent_id="agent_id", + ) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_method_update(self, client: Agentex) -> None: + schedule = client.agents.schedules.update( + schedule_id="schedule_id", + agent_id="agent_id", + ) + assert_matches_type(ScheduleUpdateResponse, schedule, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_method_update_with_all_params(self, client: Agentex) -> None: + schedule = client.agents.schedules.update( + schedule_id="schedule_id", + agent_id="agent_id", + cron_expression="cron_expression", + description="description", + end_at=parse_datetime("2019-12-27T18:11:19.117Z"), + initial_input={ + "content": "content", + "author": "user", + "type": "text", + }, + interval_seconds=1, + name="name", + paused=True, + start_at=parse_datetime("2019-12-27T18:11:19.117Z"), + task_metadata={"foo": "bar"}, + task_params={"foo": "bar"}, + timezone="timezone", + ) + assert_matches_type(ScheduleUpdateResponse, schedule, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_raw_response_update(self, client: Agentex) -> None: + response = client.agents.schedules.with_raw_response.update( + schedule_id="schedule_id", + agent_id="agent_id", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + schedule = response.parse() + assert_matches_type(ScheduleUpdateResponse, schedule, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_streaming_response_update(self, client: Agentex) -> None: + with client.agents.schedules.with_streaming_response.update( + schedule_id="schedule_id", + agent_id="agent_id", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + schedule = response.parse() + assert_matches_type(ScheduleUpdateResponse, schedule, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_path_params_update(self, client: Agentex) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `agent_id` but received ''"): + client.agents.schedules.with_raw_response.update( + schedule_id="schedule_id", + agent_id="", + ) + + with pytest.raises(ValueError, match=r"Expected a non-empty value for `schedule_id` but received ''"): + client.agents.schedules.with_raw_response.update( + schedule_id="", agent_id="agent_id", ) @@ -164,7 +247,7 @@ def test_method_list(self, client: Agentex) -> None: def test_method_list_with_all_params(self, client: Agentex) -> None: schedule = client.agents.schedules.list( agent_id="agent_id", - page_size=1, + limit=1, ) assert_matches_type(ScheduleListResponse, schedule, path=["response"]) @@ -206,7 +289,7 @@ def test_path_params_list(self, client: Agentex) -> None: @parametrize def test_method_delete(self, client: Agentex) -> None: schedule = client.agents.schedules.delete( - schedule_name="schedule_name", + schedule_id="schedule_id", agent_id="agent_id", ) assert_matches_type(DeleteResponse, schedule, path=["response"]) @@ -215,7 +298,7 @@ def test_method_delete(self, client: Agentex) -> None: @parametrize def test_raw_response_delete(self, client: Agentex) -> None: response = client.agents.schedules.with_raw_response.delete( - schedule_name="schedule_name", + schedule_id="schedule_id", agent_id="agent_id", ) @@ -228,7 +311,7 @@ def test_raw_response_delete(self, client: Agentex) -> None: @parametrize def test_streaming_response_delete(self, client: Agentex) -> None: with client.agents.schedules.with_streaming_response.delete( - schedule_name="schedule_name", + schedule_id="schedule_id", agent_id="agent_id", ) as response: assert not response.is_closed @@ -244,13 +327,65 @@ def test_streaming_response_delete(self, client: Agentex) -> None: def test_path_params_delete(self, client: Agentex) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `agent_id` but received ''"): client.agents.schedules.with_raw_response.delete( - schedule_name="schedule_name", + schedule_id="schedule_id", agent_id="", ) - with pytest.raises(ValueError, match=r"Expected a non-empty value for `schedule_name` but received ''"): + with pytest.raises(ValueError, match=r"Expected a non-empty value for `schedule_id` but received ''"): client.agents.schedules.with_raw_response.delete( - schedule_name="", + schedule_id="", + agent_id="agent_id", + ) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_method_delete_by_name(self, client: Agentex) -> None: + schedule = client.agents.schedules.delete_by_name( + name="name", + agent_id="agent_id", + ) + assert_matches_type(DeleteResponse, schedule, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_raw_response_delete_by_name(self, client: Agentex) -> None: + response = client.agents.schedules.with_raw_response.delete_by_name( + name="name", + agent_id="agent_id", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + schedule = response.parse() + assert_matches_type(DeleteResponse, schedule, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_streaming_response_delete_by_name(self, client: Agentex) -> None: + with client.agents.schedules.with_streaming_response.delete_by_name( + name="name", + agent_id="agent_id", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + schedule = response.parse() + assert_matches_type(DeleteResponse, schedule, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_path_params_delete_by_name(self, client: Agentex) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `agent_id` but received ''"): + client.agents.schedules.with_raw_response.delete_by_name( + name="name", + agent_id="", + ) + + with pytest.raises(ValueError, match=r"Expected a non-empty value for `name` but received ''"): + client.agents.schedules.with_raw_response.delete_by_name( + name="", agent_id="agent_id", ) @@ -258,7 +393,7 @@ def test_path_params_delete(self, client: Agentex) -> None: @parametrize def test_method_pause(self, client: Agentex) -> None: schedule = client.agents.schedules.pause( - schedule_name="schedule_name", + schedule_id="schedule_id", agent_id="agent_id", ) assert_matches_type(SchedulePauseResponse, schedule, path=["response"]) @@ -267,7 +402,7 @@ def test_method_pause(self, client: Agentex) -> None: @parametrize def test_method_pause_with_all_params(self, client: Agentex) -> None: schedule = client.agents.schedules.pause( - schedule_name="schedule_name", + schedule_id="schedule_id", agent_id="agent_id", note="note", ) @@ -277,7 +412,7 @@ def test_method_pause_with_all_params(self, client: Agentex) -> None: @parametrize def test_raw_response_pause(self, client: Agentex) -> None: response = client.agents.schedules.with_raw_response.pause( - schedule_name="schedule_name", + schedule_id="schedule_id", agent_id="agent_id", ) @@ -290,7 +425,7 @@ def test_raw_response_pause(self, client: Agentex) -> None: @parametrize def test_streaming_response_pause(self, client: Agentex) -> None: with client.agents.schedules.with_streaming_response.pause( - schedule_name="schedule_name", + schedule_id="schedule_id", agent_id="agent_id", ) as response: assert not response.is_closed @@ -306,430 +441,1101 @@ def test_streaming_response_pause(self, client: Agentex) -> None: def test_path_params_pause(self, client: Agentex) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `agent_id` but received ''"): client.agents.schedules.with_raw_response.pause( - schedule_name="schedule_name", + schedule_id="schedule_id", agent_id="", ) - with pytest.raises(ValueError, match=r"Expected a non-empty value for `schedule_name` but received ''"): + with pytest.raises(ValueError, match=r"Expected a non-empty value for `schedule_id` but received ''"): client.agents.schedules.with_raw_response.pause( - schedule_name="", + schedule_id="", agent_id="agent_id", ) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize - def test_method_trigger(self, client: Agentex) -> None: - schedule = client.agents.schedules.trigger( - schedule_name="schedule_name", + def test_method_pause_by_name(self, client: Agentex) -> None: + schedule = client.agents.schedules.pause_by_name( + name="name", agent_id="agent_id", ) - assert_matches_type(ScheduleTriggerResponse, schedule, path=["response"]) + assert_matches_type(SchedulePauseByNameResponse, schedule, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize - def test_raw_response_trigger(self, client: Agentex) -> None: - response = client.agents.schedules.with_raw_response.trigger( - schedule_name="schedule_name", + def test_method_pause_by_name_with_all_params(self, client: Agentex) -> None: + schedule = client.agents.schedules.pause_by_name( + name="name", + agent_id="agent_id", + note="note", + ) + assert_matches_type(SchedulePauseByNameResponse, schedule, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_raw_response_pause_by_name(self, client: Agentex) -> None: + response = client.agents.schedules.with_raw_response.pause_by_name( + name="name", agent_id="agent_id", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" schedule = response.parse() - assert_matches_type(ScheduleTriggerResponse, schedule, path=["response"]) + assert_matches_type(SchedulePauseByNameResponse, schedule, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize - def test_streaming_response_trigger(self, client: Agentex) -> None: - with client.agents.schedules.with_streaming_response.trigger( - schedule_name="schedule_name", + def test_streaming_response_pause_by_name(self, client: Agentex) -> None: + with client.agents.schedules.with_streaming_response.pause_by_name( + name="name", agent_id="agent_id", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" schedule = response.parse() - assert_matches_type(ScheduleTriggerResponse, schedule, path=["response"]) + assert_matches_type(SchedulePauseByNameResponse, schedule, path=["response"]) assert cast(Any, response.is_closed) is True @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize - def test_path_params_trigger(self, client: Agentex) -> None: + def test_path_params_pause_by_name(self, client: Agentex) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `agent_id` but received ''"): - client.agents.schedules.with_raw_response.trigger( - schedule_name="schedule_name", + client.agents.schedules.with_raw_response.pause_by_name( + name="name", agent_id="", ) - with pytest.raises(ValueError, match=r"Expected a non-empty value for `schedule_name` but received ''"): - client.agents.schedules.with_raw_response.trigger( - schedule_name="", + with pytest.raises(ValueError, match=r"Expected a non-empty value for `name` but received ''"): + client.agents.schedules.with_raw_response.pause_by_name( + name="", agent_id="agent_id", ) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize - def test_method_unpause(self, client: Agentex) -> None: - schedule = client.agents.schedules.unpause( - schedule_name="schedule_name", + def test_method_resume(self, client: Agentex) -> None: + schedule = client.agents.schedules.resume( + schedule_id="schedule_id", agent_id="agent_id", ) - assert_matches_type(ScheduleUnpauseResponse, schedule, path=["response"]) + assert_matches_type(ScheduleResumeResponse, schedule, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize - def test_method_unpause_with_all_params(self, client: Agentex) -> None: - schedule = client.agents.schedules.unpause( - schedule_name="schedule_name", + def test_method_resume_with_all_params(self, client: Agentex) -> None: + schedule = client.agents.schedules.resume( + schedule_id="schedule_id", agent_id="agent_id", note="note", ) - assert_matches_type(ScheduleUnpauseResponse, schedule, path=["response"]) + assert_matches_type(ScheduleResumeResponse, schedule, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize - def test_raw_response_unpause(self, client: Agentex) -> None: - response = client.agents.schedules.with_raw_response.unpause( - schedule_name="schedule_name", + def test_raw_response_resume(self, client: Agentex) -> None: + response = client.agents.schedules.with_raw_response.resume( + schedule_id="schedule_id", agent_id="agent_id", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" schedule = response.parse() - assert_matches_type(ScheduleUnpauseResponse, schedule, path=["response"]) + assert_matches_type(ScheduleResumeResponse, schedule, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize - def test_streaming_response_unpause(self, client: Agentex) -> None: - with client.agents.schedules.with_streaming_response.unpause( - schedule_name="schedule_name", + def test_streaming_response_resume(self, client: Agentex) -> None: + with client.agents.schedules.with_streaming_response.resume( + schedule_id="schedule_id", agent_id="agent_id", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" schedule = response.parse() - assert_matches_type(ScheduleUnpauseResponse, schedule, path=["response"]) + assert_matches_type(ScheduleResumeResponse, schedule, path=["response"]) assert cast(Any, response.is_closed) is True @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize - def test_path_params_unpause(self, client: Agentex) -> None: + def test_path_params_resume(self, client: Agentex) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `agent_id` but received ''"): - client.agents.schedules.with_raw_response.unpause( - schedule_name="schedule_name", + client.agents.schedules.with_raw_response.resume( + schedule_id="schedule_id", agent_id="", ) - with pytest.raises(ValueError, match=r"Expected a non-empty value for `schedule_name` but received ''"): - client.agents.schedules.with_raw_response.unpause( - schedule_name="", + with pytest.raises(ValueError, match=r"Expected a non-empty value for `schedule_id` but received ''"): + client.agents.schedules.with_raw_response.resume( + schedule_id="", agent_id="agent_id", ) - -class TestAsyncSchedules: - parametrize = pytest.mark.parametrize( - "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] - ) - @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize - async def test_method_create(self, async_client: AsyncAgentex) -> None: - schedule = await async_client.agents.schedules.create( - agent_id="agent_id", + def test_method_resume_by_name(self, client: Agentex) -> None: + schedule = client.agents.schedules.resume_by_name( name="name", - task_queue="task_queue", - workflow_name="workflow_name", + agent_id="agent_id", ) - assert_matches_type(ScheduleCreateResponse, schedule, path=["response"]) + assert_matches_type(ScheduleResumeByNameResponse, schedule, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize - async def test_method_create_with_all_params(self, async_client: AsyncAgentex) -> None: - schedule = await async_client.agents.schedules.create( - agent_id="agent_id", + def test_method_resume_by_name_with_all_params(self, client: Agentex) -> None: + schedule = client.agents.schedules.resume_by_name( name="name", - task_queue="task_queue", - workflow_name="workflow_name", - cron_expression="cron_expression", - end_at=parse_datetime("2019-12-27T18:11:19.117Z"), - execution_timeout_seconds=1, - interval_seconds=1, - paused=True, - start_at=parse_datetime("2019-12-27T18:11:19.117Z"), - workflow_params={"foo": "bar"}, + agent_id="agent_id", + note="note", ) - assert_matches_type(ScheduleCreateResponse, schedule, path=["response"]) + assert_matches_type(ScheduleResumeByNameResponse, schedule, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize - async def test_raw_response_create(self, async_client: AsyncAgentex) -> None: - response = await async_client.agents.schedules.with_raw_response.create( - agent_id="agent_id", + def test_raw_response_resume_by_name(self, client: Agentex) -> None: + response = client.agents.schedules.with_raw_response.resume_by_name( name="name", - task_queue="task_queue", - workflow_name="workflow_name", + agent_id="agent_id", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" - schedule = await response.parse() - assert_matches_type(ScheduleCreateResponse, schedule, path=["response"]) + schedule = response.parse() + assert_matches_type(ScheduleResumeByNameResponse, schedule, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize - async def test_streaming_response_create(self, async_client: AsyncAgentex) -> None: - async with async_client.agents.schedules.with_streaming_response.create( - agent_id="agent_id", + def test_streaming_response_resume_by_name(self, client: Agentex) -> None: + with client.agents.schedules.with_streaming_response.resume_by_name( name="name", - task_queue="task_queue", - workflow_name="workflow_name", + agent_id="agent_id", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" - schedule = await response.parse() - assert_matches_type(ScheduleCreateResponse, schedule, path=["response"]) + schedule = response.parse() + assert_matches_type(ScheduleResumeByNameResponse, schedule, path=["response"]) assert cast(Any, response.is_closed) is True @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize - async def test_path_params_create(self, async_client: AsyncAgentex) -> None: + def test_path_params_resume_by_name(self, client: Agentex) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `agent_id` but received ''"): - await async_client.agents.schedules.with_raw_response.create( - agent_id="", + client.agents.schedules.with_raw_response.resume_by_name( name="name", - task_queue="task_queue", - workflow_name="workflow_name", + agent_id="", + ) + + with pytest.raises(ValueError, match=r"Expected a non-empty value for `name` but received ''"): + client.agents.schedules.with_raw_response.resume_by_name( + name="", + agent_id="agent_id", ) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize - async def test_method_retrieve(self, async_client: AsyncAgentex) -> None: - schedule = await async_client.agents.schedules.retrieve( - schedule_name="schedule_name", + def test_method_retrieve_by_name(self, client: Agentex) -> None: + schedule = client.agents.schedules.retrieve_by_name( + name="name", agent_id="agent_id", ) - assert_matches_type(ScheduleRetrieveResponse, schedule, path=["response"]) + assert_matches_type(ScheduleRetrieveByNameResponse, schedule, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize - async def test_raw_response_retrieve(self, async_client: AsyncAgentex) -> None: - response = await async_client.agents.schedules.with_raw_response.retrieve( - schedule_name="schedule_name", + def test_raw_response_retrieve_by_name(self, client: Agentex) -> None: + response = client.agents.schedules.with_raw_response.retrieve_by_name( + name="name", agent_id="agent_id", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" - schedule = await response.parse() - assert_matches_type(ScheduleRetrieveResponse, schedule, path=["response"]) + schedule = response.parse() + assert_matches_type(ScheduleRetrieveByNameResponse, schedule, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize - async def test_streaming_response_retrieve(self, async_client: AsyncAgentex) -> None: - async with async_client.agents.schedules.with_streaming_response.retrieve( - schedule_name="schedule_name", + def test_streaming_response_retrieve_by_name(self, client: Agentex) -> None: + with client.agents.schedules.with_streaming_response.retrieve_by_name( + name="name", agent_id="agent_id", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" - schedule = await response.parse() - assert_matches_type(ScheduleRetrieveResponse, schedule, path=["response"]) + schedule = response.parse() + assert_matches_type(ScheduleRetrieveByNameResponse, schedule, path=["response"]) assert cast(Any, response.is_closed) is True @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize - async def test_path_params_retrieve(self, async_client: AsyncAgentex) -> None: + def test_path_params_retrieve_by_name(self, client: Agentex) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `agent_id` but received ''"): - await async_client.agents.schedules.with_raw_response.retrieve( - schedule_name="schedule_name", + client.agents.schedules.with_raw_response.retrieve_by_name( + name="name", agent_id="", ) - with pytest.raises(ValueError, match=r"Expected a non-empty value for `schedule_name` but received ''"): - await async_client.agents.schedules.with_raw_response.retrieve( - schedule_name="", + with pytest.raises(ValueError, match=r"Expected a non-empty value for `name` but received ''"): + client.agents.schedules.with_raw_response.retrieve_by_name( + name="", agent_id="agent_id", ) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize - async def test_method_list(self, async_client: AsyncAgentex) -> None: - schedule = await async_client.agents.schedules.list( - agent_id="agent_id", - ) - assert_matches_type(ScheduleListResponse, schedule, path=["response"]) - - @pytest.mark.skip(reason="Mock server tests are disabled") - @parametrize - async def test_method_list_with_all_params(self, async_client: AsyncAgentex) -> None: - schedule = await async_client.agents.schedules.list( + def test_method_trigger(self, client: Agentex) -> None: + schedule = client.agents.schedules.trigger( + schedule_id="schedule_id", agent_id="agent_id", - page_size=1, ) - assert_matches_type(ScheduleListResponse, schedule, path=["response"]) + assert_matches_type(ScheduleTriggerResponse, schedule, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize - async def test_raw_response_list(self, async_client: AsyncAgentex) -> None: - response = await async_client.agents.schedules.with_raw_response.list( + def test_raw_response_trigger(self, client: Agentex) -> None: + response = client.agents.schedules.with_raw_response.trigger( + schedule_id="schedule_id", agent_id="agent_id", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" - schedule = await response.parse() - assert_matches_type(ScheduleListResponse, schedule, path=["response"]) + schedule = response.parse() + assert_matches_type(ScheduleTriggerResponse, schedule, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize - async def test_streaming_response_list(self, async_client: AsyncAgentex) -> None: - async with async_client.agents.schedules.with_streaming_response.list( + def test_streaming_response_trigger(self, client: Agentex) -> None: + with client.agents.schedules.with_streaming_response.trigger( + schedule_id="schedule_id", agent_id="agent_id", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" - schedule = await response.parse() - assert_matches_type(ScheduleListResponse, schedule, path=["response"]) + schedule = response.parse() + assert_matches_type(ScheduleTriggerResponse, schedule, path=["response"]) assert cast(Any, response.is_closed) is True @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize - async def test_path_params_list(self, async_client: AsyncAgentex) -> None: + def test_path_params_trigger(self, client: Agentex) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `agent_id` but received ''"): - await async_client.agents.schedules.with_raw_response.list( + client.agents.schedules.with_raw_response.trigger( + schedule_id="schedule_id", agent_id="", ) + with pytest.raises(ValueError, match=r"Expected a non-empty value for `schedule_id` but received ''"): + client.agents.schedules.with_raw_response.trigger( + schedule_id="", + agent_id="agent_id", + ) + @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize - async def test_method_delete(self, async_client: AsyncAgentex) -> None: - schedule = await async_client.agents.schedules.delete( - schedule_name="schedule_name", + def test_method_trigger_by_name(self, client: Agentex) -> None: + schedule = client.agents.schedules.trigger_by_name( + name="name", agent_id="agent_id", ) - assert_matches_type(DeleteResponse, schedule, path=["response"]) + assert_matches_type(ScheduleTriggerByNameResponse, schedule, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize - async def test_raw_response_delete(self, async_client: AsyncAgentex) -> None: - response = await async_client.agents.schedules.with_raw_response.delete( - schedule_name="schedule_name", + def test_raw_response_trigger_by_name(self, client: Agentex) -> None: + response = client.agents.schedules.with_raw_response.trigger_by_name( + name="name", agent_id="agent_id", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" - schedule = await response.parse() - assert_matches_type(DeleteResponse, schedule, path=["response"]) + schedule = response.parse() + assert_matches_type(ScheduleTriggerByNameResponse, schedule, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize - async def test_streaming_response_delete(self, async_client: AsyncAgentex) -> None: - async with async_client.agents.schedules.with_streaming_response.delete( - schedule_name="schedule_name", + def test_streaming_response_trigger_by_name(self, client: Agentex) -> None: + with client.agents.schedules.with_streaming_response.trigger_by_name( + name="name", agent_id="agent_id", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" - schedule = await response.parse() - assert_matches_type(DeleteResponse, schedule, path=["response"]) + schedule = response.parse() + assert_matches_type(ScheduleTriggerByNameResponse, schedule, path=["response"]) assert cast(Any, response.is_closed) is True @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize - async def test_path_params_delete(self, async_client: AsyncAgentex) -> None: + def test_path_params_trigger_by_name(self, client: Agentex) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `agent_id` but received ''"): - await async_client.agents.schedules.with_raw_response.delete( - schedule_name="schedule_name", + client.agents.schedules.with_raw_response.trigger_by_name( + name="name", agent_id="", ) - with pytest.raises(ValueError, match=r"Expected a non-empty value for `schedule_name` but received ''"): - await async_client.agents.schedules.with_raw_response.delete( - schedule_name="", + with pytest.raises(ValueError, match=r"Expected a non-empty value for `name` but received ''"): + client.agents.schedules.with_raw_response.trigger_by_name( + name="", agent_id="agent_id", ) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize - async def test_method_pause(self, async_client: AsyncAgentex) -> None: - schedule = await async_client.agents.schedules.pause( - schedule_name="schedule_name", + def test_method_update_by_name(self, client: Agentex) -> None: + schedule = client.agents.schedules.update_by_name( + path_name="name", agent_id="agent_id", ) - assert_matches_type(SchedulePauseResponse, schedule, path=["response"]) + assert_matches_type(ScheduleUpdateByNameResponse, schedule, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize - async def test_method_pause_with_all_params(self, async_client: AsyncAgentex) -> None: - schedule = await async_client.agents.schedules.pause( - schedule_name="schedule_name", + def test_method_update_by_name_with_all_params(self, client: Agentex) -> None: + schedule = client.agents.schedules.update_by_name( + path_name="name", agent_id="agent_id", - note="note", + cron_expression="cron_expression", + description="description", + end_at=parse_datetime("2019-12-27T18:11:19.117Z"), + initial_input={ + "content": "content", + "author": "user", + "type": "text", + }, + interval_seconds=1, + body_name="name", + paused=True, + start_at=parse_datetime("2019-12-27T18:11:19.117Z"), + task_metadata={"foo": "bar"}, + task_params={"foo": "bar"}, + timezone="timezone", ) - assert_matches_type(SchedulePauseResponse, schedule, path=["response"]) + assert_matches_type(ScheduleUpdateByNameResponse, schedule, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize - async def test_raw_response_pause(self, async_client: AsyncAgentex) -> None: - response = await async_client.agents.schedules.with_raw_response.pause( - schedule_name="schedule_name", + def test_raw_response_update_by_name(self, client: Agentex) -> None: + response = client.agents.schedules.with_raw_response.update_by_name( + path_name="name", agent_id="agent_id", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" - schedule = await response.parse() - assert_matches_type(SchedulePauseResponse, schedule, path=["response"]) + schedule = response.parse() + assert_matches_type(ScheduleUpdateByNameResponse, schedule, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize - async def test_streaming_response_pause(self, async_client: AsyncAgentex) -> None: - async with async_client.agents.schedules.with_streaming_response.pause( - schedule_name="schedule_name", + def test_streaming_response_update_by_name(self, client: Agentex) -> None: + with client.agents.schedules.with_streaming_response.update_by_name( + path_name="name", agent_id="agent_id", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" - schedule = await response.parse() - assert_matches_type(SchedulePauseResponse, schedule, path=["response"]) + schedule = response.parse() + assert_matches_type(ScheduleUpdateByNameResponse, schedule, path=["response"]) assert cast(Any, response.is_closed) is True @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize - async def test_path_params_pause(self, async_client: AsyncAgentex) -> None: + def test_path_params_update_by_name(self, client: Agentex) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `agent_id` but received ''"): - await async_client.agents.schedules.with_raw_response.pause( - schedule_name="schedule_name", + client.agents.schedules.with_raw_response.update_by_name( + path_name="name", agent_id="", ) - with pytest.raises(ValueError, match=r"Expected a non-empty value for `schedule_name` but received ''"): - await async_client.agents.schedules.with_raw_response.pause( - schedule_name="", + with pytest.raises(ValueError, match=r"Expected a non-empty value for `path_name` but received ''"): + client.agents.schedules.with_raw_response.update_by_name( + path_name="", agent_id="agent_id", ) - @pytest.mark.skip(reason="Mock server tests are disabled") + +class TestAsyncSchedules: + parametrize = pytest.mark.parametrize( + "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] + ) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_method_create(self, async_client: AsyncAgentex) -> None: + schedule = await async_client.agents.schedules.create( + agent_id="agent_id", + initial_input={"content": "content"}, + name="name", + ) + assert_matches_type(ScheduleCreateResponse, schedule, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_method_create_with_all_params(self, async_client: AsyncAgentex) -> None: + schedule = await async_client.agents.schedules.create( + agent_id="agent_id", + initial_input={ + "content": "content", + "author": "user", + "type": "text", + }, + name="name", + cron_expression="cron_expression", + description="description", + end_at=parse_datetime("2019-12-27T18:11:19.117Z"), + interval_seconds=1, + paused=True, + start_at=parse_datetime("2019-12-27T18:11:19.117Z"), + task_metadata={"foo": "bar"}, + task_params={"foo": "bar"}, + timezone="timezone", + ) + assert_matches_type(ScheduleCreateResponse, schedule, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_raw_response_create(self, async_client: AsyncAgentex) -> None: + response = await async_client.agents.schedules.with_raw_response.create( + agent_id="agent_id", + initial_input={"content": "content"}, + name="name", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + schedule = await response.parse() + assert_matches_type(ScheduleCreateResponse, schedule, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_streaming_response_create(self, async_client: AsyncAgentex) -> None: + async with async_client.agents.schedules.with_streaming_response.create( + agent_id="agent_id", + initial_input={"content": "content"}, + name="name", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + schedule = await response.parse() + assert_matches_type(ScheduleCreateResponse, schedule, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_path_params_create(self, async_client: AsyncAgentex) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `agent_id` but received ''"): + await async_client.agents.schedules.with_raw_response.create( + agent_id="", + initial_input={"content": "content"}, + name="name", + ) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_method_retrieve(self, async_client: AsyncAgentex) -> None: + schedule = await async_client.agents.schedules.retrieve( + schedule_id="schedule_id", + agent_id="agent_id", + ) + assert_matches_type(ScheduleRetrieveResponse, schedule, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_raw_response_retrieve(self, async_client: AsyncAgentex) -> None: + response = await async_client.agents.schedules.with_raw_response.retrieve( + schedule_id="schedule_id", + agent_id="agent_id", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + schedule = await response.parse() + assert_matches_type(ScheduleRetrieveResponse, schedule, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_streaming_response_retrieve(self, async_client: AsyncAgentex) -> None: + async with async_client.agents.schedules.with_streaming_response.retrieve( + schedule_id="schedule_id", + agent_id="agent_id", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + schedule = await response.parse() + assert_matches_type(ScheduleRetrieveResponse, schedule, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_path_params_retrieve(self, async_client: AsyncAgentex) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `agent_id` but received ''"): + await async_client.agents.schedules.with_raw_response.retrieve( + schedule_id="schedule_id", + agent_id="", + ) + + with pytest.raises(ValueError, match=r"Expected a non-empty value for `schedule_id` but received ''"): + await async_client.agents.schedules.with_raw_response.retrieve( + schedule_id="", + agent_id="agent_id", + ) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_method_update(self, async_client: AsyncAgentex) -> None: + schedule = await async_client.agents.schedules.update( + schedule_id="schedule_id", + agent_id="agent_id", + ) + assert_matches_type(ScheduleUpdateResponse, schedule, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_method_update_with_all_params(self, async_client: AsyncAgentex) -> None: + schedule = await async_client.agents.schedules.update( + schedule_id="schedule_id", + agent_id="agent_id", + cron_expression="cron_expression", + description="description", + end_at=parse_datetime("2019-12-27T18:11:19.117Z"), + initial_input={ + "content": "content", + "author": "user", + "type": "text", + }, + interval_seconds=1, + name="name", + paused=True, + start_at=parse_datetime("2019-12-27T18:11:19.117Z"), + task_metadata={"foo": "bar"}, + task_params={"foo": "bar"}, + timezone="timezone", + ) + assert_matches_type(ScheduleUpdateResponse, schedule, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_raw_response_update(self, async_client: AsyncAgentex) -> None: + response = await async_client.agents.schedules.with_raw_response.update( + schedule_id="schedule_id", + agent_id="agent_id", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + schedule = await response.parse() + assert_matches_type(ScheduleUpdateResponse, schedule, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_streaming_response_update(self, async_client: AsyncAgentex) -> None: + async with async_client.agents.schedules.with_streaming_response.update( + schedule_id="schedule_id", + agent_id="agent_id", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + schedule = await response.parse() + assert_matches_type(ScheduleUpdateResponse, schedule, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_path_params_update(self, async_client: AsyncAgentex) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `agent_id` but received ''"): + await async_client.agents.schedules.with_raw_response.update( + schedule_id="schedule_id", + agent_id="", + ) + + with pytest.raises(ValueError, match=r"Expected a non-empty value for `schedule_id` but received ''"): + await async_client.agents.schedules.with_raw_response.update( + schedule_id="", + agent_id="agent_id", + ) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_method_list(self, async_client: AsyncAgentex) -> None: + schedule = await async_client.agents.schedules.list( + agent_id="agent_id", + ) + assert_matches_type(ScheduleListResponse, schedule, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_method_list_with_all_params(self, async_client: AsyncAgentex) -> None: + schedule = await async_client.agents.schedules.list( + agent_id="agent_id", + limit=1, + ) + assert_matches_type(ScheduleListResponse, schedule, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_raw_response_list(self, async_client: AsyncAgentex) -> None: + response = await async_client.agents.schedules.with_raw_response.list( + agent_id="agent_id", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + schedule = await response.parse() + assert_matches_type(ScheduleListResponse, schedule, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_streaming_response_list(self, async_client: AsyncAgentex) -> None: + async with async_client.agents.schedules.with_streaming_response.list( + agent_id="agent_id", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + schedule = await response.parse() + assert_matches_type(ScheduleListResponse, schedule, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_path_params_list(self, async_client: AsyncAgentex) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `agent_id` but received ''"): + await async_client.agents.schedules.with_raw_response.list( + agent_id="", + ) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_method_delete(self, async_client: AsyncAgentex) -> None: + schedule = await async_client.agents.schedules.delete( + schedule_id="schedule_id", + agent_id="agent_id", + ) + assert_matches_type(DeleteResponse, schedule, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_raw_response_delete(self, async_client: AsyncAgentex) -> None: + response = await async_client.agents.schedules.with_raw_response.delete( + schedule_id="schedule_id", + agent_id="agent_id", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + schedule = await response.parse() + assert_matches_type(DeleteResponse, schedule, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_streaming_response_delete(self, async_client: AsyncAgentex) -> None: + async with async_client.agents.schedules.with_streaming_response.delete( + schedule_id="schedule_id", + agent_id="agent_id", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + schedule = await response.parse() + assert_matches_type(DeleteResponse, schedule, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_path_params_delete(self, async_client: AsyncAgentex) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `agent_id` but received ''"): + await async_client.agents.schedules.with_raw_response.delete( + schedule_id="schedule_id", + agent_id="", + ) + + with pytest.raises(ValueError, match=r"Expected a non-empty value for `schedule_id` but received ''"): + await async_client.agents.schedules.with_raw_response.delete( + schedule_id="", + agent_id="agent_id", + ) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_method_delete_by_name(self, async_client: AsyncAgentex) -> None: + schedule = await async_client.agents.schedules.delete_by_name( + name="name", + agent_id="agent_id", + ) + assert_matches_type(DeleteResponse, schedule, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_raw_response_delete_by_name(self, async_client: AsyncAgentex) -> None: + response = await async_client.agents.schedules.with_raw_response.delete_by_name( + name="name", + agent_id="agent_id", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + schedule = await response.parse() + assert_matches_type(DeleteResponse, schedule, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_streaming_response_delete_by_name(self, async_client: AsyncAgentex) -> None: + async with async_client.agents.schedules.with_streaming_response.delete_by_name( + name="name", + agent_id="agent_id", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + schedule = await response.parse() + assert_matches_type(DeleteResponse, schedule, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_path_params_delete_by_name(self, async_client: AsyncAgentex) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `agent_id` but received ''"): + await async_client.agents.schedules.with_raw_response.delete_by_name( + name="name", + agent_id="", + ) + + with pytest.raises(ValueError, match=r"Expected a non-empty value for `name` but received ''"): + await async_client.agents.schedules.with_raw_response.delete_by_name( + name="", + agent_id="agent_id", + ) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_method_pause(self, async_client: AsyncAgentex) -> None: + schedule = await async_client.agents.schedules.pause( + schedule_id="schedule_id", + agent_id="agent_id", + ) + assert_matches_type(SchedulePauseResponse, schedule, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_method_pause_with_all_params(self, async_client: AsyncAgentex) -> None: + schedule = await async_client.agents.schedules.pause( + schedule_id="schedule_id", + agent_id="agent_id", + note="note", + ) + assert_matches_type(SchedulePauseResponse, schedule, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_raw_response_pause(self, async_client: AsyncAgentex) -> None: + response = await async_client.agents.schedules.with_raw_response.pause( + schedule_id="schedule_id", + agent_id="agent_id", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + schedule = await response.parse() + assert_matches_type(SchedulePauseResponse, schedule, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_streaming_response_pause(self, async_client: AsyncAgentex) -> None: + async with async_client.agents.schedules.with_streaming_response.pause( + schedule_id="schedule_id", + agent_id="agent_id", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + schedule = await response.parse() + assert_matches_type(SchedulePauseResponse, schedule, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_path_params_pause(self, async_client: AsyncAgentex) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `agent_id` but received ''"): + await async_client.agents.schedules.with_raw_response.pause( + schedule_id="schedule_id", + agent_id="", + ) + + with pytest.raises(ValueError, match=r"Expected a non-empty value for `schedule_id` but received ''"): + await async_client.agents.schedules.with_raw_response.pause( + schedule_id="", + agent_id="agent_id", + ) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_method_pause_by_name(self, async_client: AsyncAgentex) -> None: + schedule = await async_client.agents.schedules.pause_by_name( + name="name", + agent_id="agent_id", + ) + assert_matches_type(SchedulePauseByNameResponse, schedule, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_method_pause_by_name_with_all_params(self, async_client: AsyncAgentex) -> None: + schedule = await async_client.agents.schedules.pause_by_name( + name="name", + agent_id="agent_id", + note="note", + ) + assert_matches_type(SchedulePauseByNameResponse, schedule, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_raw_response_pause_by_name(self, async_client: AsyncAgentex) -> None: + response = await async_client.agents.schedules.with_raw_response.pause_by_name( + name="name", + agent_id="agent_id", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + schedule = await response.parse() + assert_matches_type(SchedulePauseByNameResponse, schedule, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_streaming_response_pause_by_name(self, async_client: AsyncAgentex) -> None: + async with async_client.agents.schedules.with_streaming_response.pause_by_name( + name="name", + agent_id="agent_id", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + schedule = await response.parse() + assert_matches_type(SchedulePauseByNameResponse, schedule, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_path_params_pause_by_name(self, async_client: AsyncAgentex) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `agent_id` but received ''"): + await async_client.agents.schedules.with_raw_response.pause_by_name( + name="name", + agent_id="", + ) + + with pytest.raises(ValueError, match=r"Expected a non-empty value for `name` but received ''"): + await async_client.agents.schedules.with_raw_response.pause_by_name( + name="", + agent_id="agent_id", + ) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_method_resume(self, async_client: AsyncAgentex) -> None: + schedule = await async_client.agents.schedules.resume( + schedule_id="schedule_id", + agent_id="agent_id", + ) + assert_matches_type(ScheduleResumeResponse, schedule, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_method_resume_with_all_params(self, async_client: AsyncAgentex) -> None: + schedule = await async_client.agents.schedules.resume( + schedule_id="schedule_id", + agent_id="agent_id", + note="note", + ) + assert_matches_type(ScheduleResumeResponse, schedule, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_raw_response_resume(self, async_client: AsyncAgentex) -> None: + response = await async_client.agents.schedules.with_raw_response.resume( + schedule_id="schedule_id", + agent_id="agent_id", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + schedule = await response.parse() + assert_matches_type(ScheduleResumeResponse, schedule, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_streaming_response_resume(self, async_client: AsyncAgentex) -> None: + async with async_client.agents.schedules.with_streaming_response.resume( + schedule_id="schedule_id", + agent_id="agent_id", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + schedule = await response.parse() + assert_matches_type(ScheduleResumeResponse, schedule, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_path_params_resume(self, async_client: AsyncAgentex) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `agent_id` but received ''"): + await async_client.agents.schedules.with_raw_response.resume( + schedule_id="schedule_id", + agent_id="", + ) + + with pytest.raises(ValueError, match=r"Expected a non-empty value for `schedule_id` but received ''"): + await async_client.agents.schedules.with_raw_response.resume( + schedule_id="", + agent_id="agent_id", + ) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_method_resume_by_name(self, async_client: AsyncAgentex) -> None: + schedule = await async_client.agents.schedules.resume_by_name( + name="name", + agent_id="agent_id", + ) + assert_matches_type(ScheduleResumeByNameResponse, schedule, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_method_resume_by_name_with_all_params(self, async_client: AsyncAgentex) -> None: + schedule = await async_client.agents.schedules.resume_by_name( + name="name", + agent_id="agent_id", + note="note", + ) + assert_matches_type(ScheduleResumeByNameResponse, schedule, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_raw_response_resume_by_name(self, async_client: AsyncAgentex) -> None: + response = await async_client.agents.schedules.with_raw_response.resume_by_name( + name="name", + agent_id="agent_id", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + schedule = await response.parse() + assert_matches_type(ScheduleResumeByNameResponse, schedule, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_streaming_response_resume_by_name(self, async_client: AsyncAgentex) -> None: + async with async_client.agents.schedules.with_streaming_response.resume_by_name( + name="name", + agent_id="agent_id", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + schedule = await response.parse() + assert_matches_type(ScheduleResumeByNameResponse, schedule, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_path_params_resume_by_name(self, async_client: AsyncAgentex) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `agent_id` but received ''"): + await async_client.agents.schedules.with_raw_response.resume_by_name( + name="name", + agent_id="", + ) + + with pytest.raises(ValueError, match=r"Expected a non-empty value for `name` but received ''"): + await async_client.agents.schedules.with_raw_response.resume_by_name( + name="", + agent_id="agent_id", + ) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_method_retrieve_by_name(self, async_client: AsyncAgentex) -> None: + schedule = await async_client.agents.schedules.retrieve_by_name( + name="name", + agent_id="agent_id", + ) + assert_matches_type(ScheduleRetrieveByNameResponse, schedule, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_raw_response_retrieve_by_name(self, async_client: AsyncAgentex) -> None: + response = await async_client.agents.schedules.with_raw_response.retrieve_by_name( + name="name", + agent_id="agent_id", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + schedule = await response.parse() + assert_matches_type(ScheduleRetrieveByNameResponse, schedule, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_streaming_response_retrieve_by_name(self, async_client: AsyncAgentex) -> None: + async with async_client.agents.schedules.with_streaming_response.retrieve_by_name( + name="name", + agent_id="agent_id", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + schedule = await response.parse() + assert_matches_type(ScheduleRetrieveByNameResponse, schedule, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_path_params_retrieve_by_name(self, async_client: AsyncAgentex) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `agent_id` but received ''"): + await async_client.agents.schedules.with_raw_response.retrieve_by_name( + name="name", + agent_id="", + ) + + with pytest.raises(ValueError, match=r"Expected a non-empty value for `name` but received ''"): + await async_client.agents.schedules.with_raw_response.retrieve_by_name( + name="", + agent_id="agent_id", + ) + + @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize async def test_method_trigger(self, async_client: AsyncAgentex) -> None: schedule = await async_client.agents.schedules.trigger( - schedule_name="schedule_name", + schedule_id="schedule_id", agent_id="agent_id", ) assert_matches_type(ScheduleTriggerResponse, schedule, path=["response"]) @@ -738,7 +1544,7 @@ async def test_method_trigger(self, async_client: AsyncAgentex) -> None: @parametrize async def test_raw_response_trigger(self, async_client: AsyncAgentex) -> None: response = await async_client.agents.schedules.with_raw_response.trigger( - schedule_name="schedule_name", + schedule_id="schedule_id", agent_id="agent_id", ) @@ -751,7 +1557,7 @@ async def test_raw_response_trigger(self, async_client: AsyncAgentex) -> None: @parametrize async def test_streaming_response_trigger(self, async_client: AsyncAgentex) -> None: async with async_client.agents.schedules.with_streaming_response.trigger( - schedule_name="schedule_name", + schedule_id="schedule_id", agent_id="agent_id", ) as response: assert not response.is_closed @@ -767,74 +1573,140 @@ async def test_streaming_response_trigger(self, async_client: AsyncAgentex) -> N async def test_path_params_trigger(self, async_client: AsyncAgentex) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `agent_id` but received ''"): await async_client.agents.schedules.with_raw_response.trigger( - schedule_name="schedule_name", + schedule_id="schedule_id", agent_id="", ) - with pytest.raises(ValueError, match=r"Expected a non-empty value for `schedule_name` but received ''"): + with pytest.raises(ValueError, match=r"Expected a non-empty value for `schedule_id` but received ''"): await async_client.agents.schedules.with_raw_response.trigger( - schedule_name="", + schedule_id="", agent_id="agent_id", ) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize - async def test_method_unpause(self, async_client: AsyncAgentex) -> None: - schedule = await async_client.agents.schedules.unpause( - schedule_name="schedule_name", + async def test_method_trigger_by_name(self, async_client: AsyncAgentex) -> None: + schedule = await async_client.agents.schedules.trigger_by_name( + name="name", agent_id="agent_id", ) - assert_matches_type(ScheduleUnpauseResponse, schedule, path=["response"]) + assert_matches_type(ScheduleTriggerByNameResponse, schedule, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize - async def test_method_unpause_with_all_params(self, async_client: AsyncAgentex) -> None: - schedule = await async_client.agents.schedules.unpause( - schedule_name="schedule_name", + async def test_raw_response_trigger_by_name(self, async_client: AsyncAgentex) -> None: + response = await async_client.agents.schedules.with_raw_response.trigger_by_name( + name="name", agent_id="agent_id", - note="note", ) - assert_matches_type(ScheduleUnpauseResponse, schedule, path=["response"]) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + schedule = await response.parse() + assert_matches_type(ScheduleTriggerByNameResponse, schedule, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_streaming_response_trigger_by_name(self, async_client: AsyncAgentex) -> None: + async with async_client.agents.schedules.with_streaming_response.trigger_by_name( + name="name", + agent_id="agent_id", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + schedule = await response.parse() + assert_matches_type(ScheduleTriggerByNameResponse, schedule, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_path_params_trigger_by_name(self, async_client: AsyncAgentex) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `agent_id` but received ''"): + await async_client.agents.schedules.with_raw_response.trigger_by_name( + name="name", + agent_id="", + ) + + with pytest.raises(ValueError, match=r"Expected a non-empty value for `name` but received ''"): + await async_client.agents.schedules.with_raw_response.trigger_by_name( + name="", + agent_id="agent_id", + ) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_method_update_by_name(self, async_client: AsyncAgentex) -> None: + schedule = await async_client.agents.schedules.update_by_name( + path_name="name", + agent_id="agent_id", + ) + assert_matches_type(ScheduleUpdateByNameResponse, schedule, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_method_update_by_name_with_all_params(self, async_client: AsyncAgentex) -> None: + schedule = await async_client.agents.schedules.update_by_name( + path_name="name", + agent_id="agent_id", + cron_expression="cron_expression", + description="description", + end_at=parse_datetime("2019-12-27T18:11:19.117Z"), + initial_input={ + "content": "content", + "author": "user", + "type": "text", + }, + interval_seconds=1, + body_name="name", + paused=True, + start_at=parse_datetime("2019-12-27T18:11:19.117Z"), + task_metadata={"foo": "bar"}, + task_params={"foo": "bar"}, + timezone="timezone", + ) + assert_matches_type(ScheduleUpdateByNameResponse, schedule, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize - async def test_raw_response_unpause(self, async_client: AsyncAgentex) -> None: - response = await async_client.agents.schedules.with_raw_response.unpause( - schedule_name="schedule_name", + async def test_raw_response_update_by_name(self, async_client: AsyncAgentex) -> None: + response = await async_client.agents.schedules.with_raw_response.update_by_name( + path_name="name", agent_id="agent_id", ) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" schedule = await response.parse() - assert_matches_type(ScheduleUnpauseResponse, schedule, path=["response"]) + assert_matches_type(ScheduleUpdateByNameResponse, schedule, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize - async def test_streaming_response_unpause(self, async_client: AsyncAgentex) -> None: - async with async_client.agents.schedules.with_streaming_response.unpause( - schedule_name="schedule_name", + async def test_streaming_response_update_by_name(self, async_client: AsyncAgentex) -> None: + async with async_client.agents.schedules.with_streaming_response.update_by_name( + path_name="name", agent_id="agent_id", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" schedule = await response.parse() - assert_matches_type(ScheduleUnpauseResponse, schedule, path=["response"]) + assert_matches_type(ScheduleUpdateByNameResponse, schedule, path=["response"]) assert cast(Any, response.is_closed) is True @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize - async def test_path_params_unpause(self, async_client: AsyncAgentex) -> None: + async def test_path_params_update_by_name(self, async_client: AsyncAgentex) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `agent_id` but received ''"): - await async_client.agents.schedules.with_raw_response.unpause( - schedule_name="schedule_name", + await async_client.agents.schedules.with_raw_response.update_by_name( + path_name="name", agent_id="", ) - with pytest.raises(ValueError, match=r"Expected a non-empty value for `schedule_name` but received ''"): - await async_client.agents.schedules.with_raw_response.unpause( - schedule_name="", + with pytest.raises(ValueError, match=r"Expected a non-empty value for `path_name` but received ''"): + await async_client.agents.schedules.with_raw_response.update_by_name( + path_name="", agent_id="agent_id", ) diff --git a/tests/lib/core/tracing/test_span_error.py b/tests/lib/core/tracing/test_span_error.py new file mode 100644 index 000000000..18116dcb3 --- /dev/null +++ b/tests/lib/core/tracing/test_span_error.py @@ -0,0 +1,151 @@ +from __future__ import annotations + +import uuid +from typing import Any +from datetime import UTC, datetime +from unittest.mock import MagicMock, patch + +import pytest + +from agentex.types.span import Span +from agentex.lib.core.tracing.trace import Trace, AsyncTrace +from agentex.lib.core.tracing.span_error import ( + SPAN_ERROR_KEY, + get_span_error, + set_span_error, +) + +PROCESSOR_MODULE = "agentex.lib.core.tracing.processors.sgp_tracing_processor" + + +def _make_span(data=None) -> Span: + return Span( + id=str(uuid.uuid4()), + name="test-span", + start_time=datetime.now(UTC), + trace_id="trace-1", + data=data, + ) + + +# --------------------------------------------------------------------------- +# Helpers: set_span_error / get_span_error +# --------------------------------------------------------------------------- + + +class TestSpanErrorHelpers: + def test_set_then_get_on_none_data(self): + span = _make_span(data=None) + set_span_error(span, ValueError("boom")) + assert get_span_error(span) == {"type": "ValueError", "message": "boom"} + assert isinstance(span.data, dict) + assert span.data[SPAN_ERROR_KEY] == {"type": "ValueError", "message": "boom"} + + def test_set_preserves_existing_dict_keys(self): + span = _make_span(data={"__span_type__": "LLM"}) + set_span_error(span, RuntimeError("nope")) + assert isinstance(span.data, dict) + assert span.data["__span_type__"] == "LLM" + err = get_span_error(span) + assert err is not None + assert err["type"] == "RuntimeError" + + def test_get_returns_none_when_no_error(self): + assert get_span_error(_make_span(data={"foo": "bar"})) is None + assert get_span_error(_make_span(data=None)) is None + + def test_set_is_noop_on_list_data(self): + span = _make_span(data=[{"a": 1}]) + set_span_error(span, ValueError("boom")) + # list-shaped data is left untouched (mirrors _add_source_to_span) + assert span.data == [{"a": 1}] + assert get_span_error(span) is None + + +# --------------------------------------------------------------------------- +# Capture: the context managers record body exceptions onto the span +# --------------------------------------------------------------------------- + + +class TestContextManagerCapture: + def test_sync_span_records_error_and_reraises(self): + trace = Trace(processors=[], client=MagicMock(), trace_id="t1") + captured = {} + with pytest.raises(ValueError, match="boom"): + with trace.span("op") as span: + captured["span"] = span + raise ValueError("boom") + err = get_span_error(captured["span"]) + assert err == {"type": "ValueError", "message": "boom"} + + def test_sync_span_success_has_no_error(self): + trace = Trace(processors=[], client=MagicMock(), trace_id="t1") + with trace.span("op") as span: + pass + assert get_span_error(span) is None + + @pytest.mark.asyncio + async def test_async_span_records_error_and_reraises(self): + trace = AsyncTrace(processors=[], client=MagicMock(), trace_id="t1") + captured = {} + with pytest.raises(RuntimeError, match="kaboom"): + async with trace.span("op") as span: + captured["span"] = span + raise RuntimeError("kaboom") + err = get_span_error(captured["span"]) + assert err == {"type": "RuntimeError", "message": "kaboom"} + + +# --------------------------------------------------------------------------- +# Map: _build_sgp_span translates the recorded error into SGP status=ERROR +# --------------------------------------------------------------------------- + + +class _FakeSGPSpan: + def __init__(self, metadata: dict[str, Any] | None) -> None: + self.status = "SUCCESS" + self.metadata: dict[str, Any] = metadata if metadata is not None else {} + self.start_time = None + + def set_error( + self, + error_type: str | None = None, + error_message: str | None = None, + exception: BaseException | None = None, + ) -> None: + self.status = "ERROR" + self.metadata["error"] = True + self.metadata["error_type"] = error_type + self.metadata["error_message"] = error_message + + +def _fake_create_span(**kwargs: Any) -> _FakeSGPSpan: + return _FakeSGPSpan(kwargs.get("metadata")) + + +class TestBuildSGPSpanMapping: + @staticmethod + def _env(): + return MagicMock(ACP_TYPE=None, AGENT_NAME=None, AGENT_ID=None) + + def test_error_maps_to_status_error(self): + from agentex.lib.core.tracing.processors.sgp_tracing_processor import _build_sgp_span + + span = _make_span(data={SPAN_ERROR_KEY: {"type": "ValueError", "message": "boom"}}) + with patch(f"{PROCESSOR_MODULE}.create_span", side_effect=_fake_create_span): + sgp_span = _build_sgp_span(span, self._env()) + + assert sgp_span.status == "ERROR" + assert sgp_span.metadata["error"] is True + assert sgp_span.metadata["error_type"] == "ValueError" + assert sgp_span.metadata["error_message"] == "boom" + + def test_no_error_leaves_status_success(self): + from agentex.lib.core.tracing.processors.sgp_tracing_processor import _build_sgp_span + + span = _make_span(data={"__span_type__": "LLM"}) + with patch(f"{PROCESSOR_MODULE}.create_span", side_effect=_fake_create_span): + sgp_span = _build_sgp_span(span, self._env()) + + assert sgp_span.status == "SUCCESS" + assert "error" not in sgp_span.metadata diff --git a/uv.lock b/uv.lock index 8a41ba29c..43de6493c 100644 --- a/uv.lock +++ b/uv.lock @@ -15,7 +15,7 @@ members = [ [[package]] name = "agentex-client" -version = "0.13.0" +version = "0.17.0" source = { editable = "." } dependencies = [ { name = "anyio" }, @@ -91,7 +91,7 @@ dev = [ [[package]] name = "agentex-sdk" -version = "0.13.0" +version = "0.17.0" source = { editable = "adk" } dependencies = [ { name = "agentex-client" }, @@ -144,7 +144,7 @@ requires-dist = [ { name = "langgraph-checkpoint", specifier = ">=2.0.0" }, { name = "litellm", specifier = ">=1.83.7,<2" }, { name = "mcp", specifier = ">=1.4.1" }, - { name = "openai", specifier = ">=2.2,<3" }, + { name = "openai", specifier = ">=2.2,<2.45" }, { name = "openai-agents", specifier = ">=0.14.3,<0.15" }, { name = "opentelemetry-api", specifier = ">=1.20.0" }, { name = "opentelemetry-sdk", specifier = ">=1.20.0" },