diff --git a/README.md b/README.md index ca538f0..6a418d7 100644 --- a/README.md +++ b/README.md @@ -139,13 +139,14 @@ activitysmith.notifications.send( ## Live Activities -There are five types of Live Activities: +There are six types of Live Activities: - `stats`: best for showing business numbers side by side, such as revenue, sales, new users, conversion, refunds, or any other value you want visible at a glance - `metrics`: best for live percentage values that change often, like server CPU, memory usage, disk usage, or error rate - `segmented_progress`: best for anything that moves through clear stages, like deployments, onboarding flows, backups, ETL pipelines, migrations, and AI agent runs - `progress`: best for tracking real-time progress with percentage, like tasks, backups, migrations, syncs, or uploads - `alert`: best for status updates, such as feature adoption, reactivation, onboarding blockers, incidents, escalations, and other operational states +- `timer`: best for countdowns and elapsed runtime, like benchmark runs, uploads, backups, transcodes, and long-running jobs ### Start & Update Live Activity @@ -273,6 +274,33 @@ activitysmith.live_activities.stream( ) ``` +#### Timer + +

+ Timer Live Activity showing a benchmark run countdown +

+ +```python +activitysmith.live_activities.stream( + "benchmark-run", + content_state=content_state( + title="Benchmark Run", + subtitle="sampling", + type="timer", + duration_seconds=300, + color="cyan", + ), +) +``` + +For a countdown, send `duration_seconds`. You can update `title`, `subtitle`, `color`, or any other visible field as the work changes. Leave `duration_seconds` out unless you want to change the timer. + +To start at 00:00 and count up, set `counts_down: false` and leave out `duration_seconds`. + ### End Live Activity Call `end_stream(...)` with the same `stream_key` to dismiss the Live Activity. You can include final values before it is removed. By default, iOS removes the Live Activity after two minutes. Set `auto_dismiss_minutes` to choose a different dismissal time, including `0` for immediate dismissal. @@ -382,7 +410,7 @@ Add more context to Live Activities with icons and badges. #### Icon -Supported Live Activity types: `stats`, `metrics`, `progress`, `segmented_progress`, and `alert`. +Supported Live Activity types: `stats`, `metrics`, `progress`, `segmented_progress`, `alert`, and `timer`.

Metrics Live Activity with an SF Symbol icon on the iPhone Lock Screen diff --git a/activitysmith/client.py b/activitysmith/client.py index c6840c2..1eeffb9 100644 --- a/activitysmith/client.py +++ b/activitysmith/client.py @@ -10,7 +10,7 @@ from activitysmith_openapi.api.metrics_api import MetricsApi from activitysmith_openapi.api.push_notifications_api import PushNotificationsApi -SDK_VERSION = "1.6.0" +SDK_VERSION = "1.7.0" SDK_HEADER_NAME = "X-ActivitySmith-SDK" SDK_HEADER_VALUE = f"python-v{SDK_VERSION}" @@ -166,6 +166,8 @@ def content_state( percentage: int | float | None = None, value: int | float | None = None, upper_limit: int | float | None = None, + duration_seconds: int | float | None = None, + counts_down: bool | None = None, color: str | None = None, step_color: str | None = None, auto_dismiss_seconds: int | None = None, @@ -185,6 +187,8 @@ def content_state( "percentage": percentage, "value": value, "upper_limit": upper_limit, + "duration_seconds": duration_seconds, + "counts_down": counts_down, "color": color, "step_color": step_color, "auto_dismiss_seconds": auto_dismiss_seconds, @@ -265,6 +269,8 @@ def _build_live_activity_request( percentage: Any | None = None, value: Any | None = None, upper_limit: Any | None = None, + duration_seconds: Any | None = None, + counts_down: Any | None = None, color: Any | None = None, step_color: Any | None = None, auto_dismiss_seconds: Any | None = None, @@ -288,6 +294,8 @@ def _build_live_activity_request( "percentage": percentage, "value": value, "upper_limit": upper_limit, + "duration_seconds": duration_seconds, + "counts_down": counts_down, "color": color, "step_color": step_color, "auto_dismiss_seconds": auto_dismiss_seconds, @@ -387,6 +395,7 @@ class LiveActivitiesResource: TYPE_METRICS = "metrics" TYPE_STATS = "stats" TYPE_ALERT = "alert" + TYPE_TIMER = "timer" def __init__(self, api: LiveActivitiesApi) -> None: self._api = api @@ -434,6 +443,8 @@ def start( percentage: Any | None = None, value: Any | None = None, upper_limit: Any | None = None, + duration_seconds: Any | None = None, + counts_down: Any | None = None, color: Any | None = None, step_color: Any | None = None, action: Any | None = None, @@ -456,6 +467,8 @@ def start( percentage=percentage, value=value, upper_limit=upper_limit, + duration_seconds=duration_seconds, + counts_down=counts_down, color=color, step_color=step_color, action=action, @@ -485,6 +498,8 @@ def update( percentage: Any | None = None, value: Any | None = None, upper_limit: Any | None = None, + duration_seconds: Any | None = None, + counts_down: Any | None = None, color: Any | None = None, step_color: Any | None = None, action: Any | None = None, @@ -505,6 +520,8 @@ def update( percentage=percentage, value=value, upper_limit=upper_limit, + duration_seconds=duration_seconds, + counts_down=counts_down, color=color, step_color=step_color, action=action, @@ -529,6 +546,8 @@ def end( percentage: Any | None = None, value: Any | None = None, upper_limit: Any | None = None, + duration_seconds: Any | None = None, + counts_down: Any | None = None, color: Any | None = None, step_color: Any | None = None, auto_dismiss_minutes: Any | None = None, @@ -550,6 +569,8 @@ def end( percentage=percentage, value=value, upper_limit=upper_limit, + duration_seconds=duration_seconds, + counts_down=counts_down, color=color, step_color=step_color, auto_dismiss_minutes=auto_dismiss_minutes, @@ -575,6 +596,8 @@ def stream( percentage: Any | None = None, value: Any | None = None, upper_limit: Any | None = None, + duration_seconds: Any | None = None, + counts_down: Any | None = None, color: Any | None = None, step_color: Any | None = None, action: Any | None = None, @@ -597,6 +620,8 @@ def stream( percentage=percentage, value=value, upper_limit=upper_limit, + duration_seconds=duration_seconds, + counts_down=counts_down, color=color, step_color=step_color, action=action, @@ -627,6 +652,8 @@ def end_stream( percentage: Any | None = None, value: Any | None = None, upper_limit: Any | None = None, + duration_seconds: Any | None = None, + counts_down: Any | None = None, color: Any | None = None, step_color: Any | None = None, auto_dismiss_minutes: Any | None = None, @@ -648,6 +675,8 @@ def end_stream( percentage=percentage, value=value, upper_limit=upper_limit, + duration_seconds=duration_seconds, + counts_down=counts_down, color=color, step_color=step_color, auto_dismiss_minutes=auto_dismiss_minutes, diff --git a/activitysmith_openapi/api/live_activities_api.py b/activitysmith_openapi/api/live_activities_api.py index 547edce..001d0ac 100644 --- a/activitysmith_openapi/api/live_activities_api.py +++ b/activitysmith_openapi/api/live_activities_api.py @@ -67,7 +67,7 @@ def end_live_activity( ) -> LiveActivityEndResponse: """End a Live Activity (legacy manual lifecycle) - Legacy manual lifecycle endpoint. For new integrations, use DELETE /live-activity/stream/{stream_key} to end a managed Live Activity stream. This endpoint remains supported for existing integrations and advanced lifecycle control. Ends a Live Activity and archives its lifecycle. Supports segmented_progress, progress, metrics, stats, and alert activity types. For segmented_progress activities, you can send the latest number_of_steps here if the workflow changed after start. + Legacy manual lifecycle endpoint. For new integrations, use DELETE /live-activity/stream/{stream_key} to end a managed Live Activity stream. This endpoint remains supported for existing integrations and advanced lifecycle control. Ends a Live Activity and archives its lifecycle. Supports segmented_progress, progress, metrics, stats, alert, and timer activity types. For segmented_progress activities, you can send the latest number_of_steps here if the workflow changed after start. :param live_activity_end_request: (required) :type live_activity_end_request: LiveActivityEndRequest @@ -136,7 +136,7 @@ def end_live_activity_with_http_info( ) -> ApiResponse[LiveActivityEndResponse]: """End a Live Activity (legacy manual lifecycle) - Legacy manual lifecycle endpoint. For new integrations, use DELETE /live-activity/stream/{stream_key} to end a managed Live Activity stream. This endpoint remains supported for existing integrations and advanced lifecycle control. Ends a Live Activity and archives its lifecycle. Supports segmented_progress, progress, metrics, stats, and alert activity types. For segmented_progress activities, you can send the latest number_of_steps here if the workflow changed after start. + Legacy manual lifecycle endpoint. For new integrations, use DELETE /live-activity/stream/{stream_key} to end a managed Live Activity stream. This endpoint remains supported for existing integrations and advanced lifecycle control. Ends a Live Activity and archives its lifecycle. Supports segmented_progress, progress, metrics, stats, alert, and timer activity types. For segmented_progress activities, you can send the latest number_of_steps here if the workflow changed after start. :param live_activity_end_request: (required) :type live_activity_end_request: LiveActivityEndRequest @@ -205,7 +205,7 @@ def end_live_activity_without_preload_content( ) -> RESTResponseType: """End a Live Activity (legacy manual lifecycle) - Legacy manual lifecycle endpoint. For new integrations, use DELETE /live-activity/stream/{stream_key} to end a managed Live Activity stream. This endpoint remains supported for existing integrations and advanced lifecycle control. Ends a Live Activity and archives its lifecycle. Supports segmented_progress, progress, metrics, stats, and alert activity types. For segmented_progress activities, you can send the latest number_of_steps here if the workflow changed after start. + Legacy manual lifecycle endpoint. For new integrations, use DELETE /live-activity/stream/{stream_key} to end a managed Live Activity stream. This endpoint remains supported for existing integrations and advanced lifecycle control. Ends a Live Activity and archives its lifecycle. Supports segmented_progress, progress, metrics, stats, alert, and timer activity types. For segmented_progress activities, you can send the latest number_of_steps here if the workflow changed after start. :param live_activity_end_request: (required) :type live_activity_end_request: LiveActivityEndRequest @@ -642,7 +642,7 @@ def reconcile_live_activity_stream( ) -> LiveActivityStreamPutResponse: """Start a new Live Activity or update an existing one - Use a stable stream_key for each ongoing thing you want to show as a Live Activity. Send the latest content_state whenever it changes, and ActivitySmith will keep the Live Activity in sync. + Use a stable stream_key for each ongoing thing you want to show as a Live Activity. Send the latest content_state whenever it changes, and ActivitySmith will keep the Live Activity in sync. For timer streams, send duration_seconds to start or reset the timer; omit duration_seconds on later updates to preserve the existing timer window. :param stream_key: Stable identifier for one ongoing thing. Allowed characters: letters, numbers, underscores, and hyphens. (required) :type stream_key: str @@ -717,7 +717,7 @@ def reconcile_live_activity_stream_with_http_info( ) -> ApiResponse[LiveActivityStreamPutResponse]: """Start a new Live Activity or update an existing one - Use a stable stream_key for each ongoing thing you want to show as a Live Activity. Send the latest content_state whenever it changes, and ActivitySmith will keep the Live Activity in sync. + Use a stable stream_key for each ongoing thing you want to show as a Live Activity. Send the latest content_state whenever it changes, and ActivitySmith will keep the Live Activity in sync. For timer streams, send duration_seconds to start or reset the timer; omit duration_seconds on later updates to preserve the existing timer window. :param stream_key: Stable identifier for one ongoing thing. Allowed characters: letters, numbers, underscores, and hyphens. (required) :type stream_key: str @@ -792,7 +792,7 @@ def reconcile_live_activity_stream_without_preload_content( ) -> RESTResponseType: """Start a new Live Activity or update an existing one - Use a stable stream_key for each ongoing thing you want to show as a Live Activity. Send the latest content_state whenever it changes, and ActivitySmith will keep the Live Activity in sync. + Use a stable stream_key for each ongoing thing you want to show as a Live Activity. Send the latest content_state whenever it changes, and ActivitySmith will keep the Live Activity in sync. For timer streams, send duration_seconds to start or reset the timer; omit duration_seconds on later updates to preserve the existing timer window. :param stream_key: Stable identifier for one ongoing thing. Allowed characters: letters, numbers, underscores, and hyphens. (required) :type stream_key: str @@ -940,7 +940,7 @@ def start_live_activity( ) -> LiveActivityStartResponse: """Start a Live Activity (legacy manual lifecycle) - Legacy manual lifecycle endpoint. For new integrations, use PUT /live-activity/stream/{stream_key} so ActivitySmith can manage start, update, rotation, and end state for you. This endpoint remains supported for existing integrations and advanced lifecycle control. Starts a Live Activity on devices matched by API key scope and optional target channels. Supports segmented_progress, progress, metrics, stats, and alert activity types. For segmented_progress activities, number_of_steps can be changed later during update or end calls if the workflow changes. + Legacy manual lifecycle endpoint. For new integrations, use PUT /live-activity/stream/{stream_key} so ActivitySmith can manage start, update, rotation, and end state for you. This endpoint remains supported for existing integrations and advanced lifecycle control. Starts a Live Activity on devices matched by API key scope and optional target channels. Supports segmented_progress, progress, metrics, stats, alert, and timer activity types. For segmented_progress activities, number_of_steps can be changed later during update or end calls if the workflow changes. :param live_activity_start_request: (required) :type live_activity_start_request: LiveActivityStartRequest @@ -1011,7 +1011,7 @@ def start_live_activity_with_http_info( ) -> ApiResponse[LiveActivityStartResponse]: """Start a Live Activity (legacy manual lifecycle) - Legacy manual lifecycle endpoint. For new integrations, use PUT /live-activity/stream/{stream_key} so ActivitySmith can manage start, update, rotation, and end state for you. This endpoint remains supported for existing integrations and advanced lifecycle control. Starts a Live Activity on devices matched by API key scope and optional target channels. Supports segmented_progress, progress, metrics, stats, and alert activity types. For segmented_progress activities, number_of_steps can be changed later during update or end calls if the workflow changes. + Legacy manual lifecycle endpoint. For new integrations, use PUT /live-activity/stream/{stream_key} so ActivitySmith can manage start, update, rotation, and end state for you. This endpoint remains supported for existing integrations and advanced lifecycle control. Starts a Live Activity on devices matched by API key scope and optional target channels. Supports segmented_progress, progress, metrics, stats, alert, and timer activity types. For segmented_progress activities, number_of_steps can be changed later during update or end calls if the workflow changes. :param live_activity_start_request: (required) :type live_activity_start_request: LiveActivityStartRequest @@ -1082,7 +1082,7 @@ def start_live_activity_without_preload_content( ) -> RESTResponseType: """Start a Live Activity (legacy manual lifecycle) - Legacy manual lifecycle endpoint. For new integrations, use PUT /live-activity/stream/{stream_key} so ActivitySmith can manage start, update, rotation, and end state for you. This endpoint remains supported for existing integrations and advanced lifecycle control. Starts a Live Activity on devices matched by API key scope and optional target channels. Supports segmented_progress, progress, metrics, stats, and alert activity types. For segmented_progress activities, number_of_steps can be changed later during update or end calls if the workflow changes. + Legacy manual lifecycle endpoint. For new integrations, use PUT /live-activity/stream/{stream_key} so ActivitySmith can manage start, update, rotation, and end state for you. This endpoint remains supported for existing integrations and advanced lifecycle control. Starts a Live Activity on devices matched by API key scope and optional target channels. Supports segmented_progress, progress, metrics, stats, alert, and timer activity types. For segmented_progress activities, number_of_steps can be changed later during update or end calls if the workflow changes. :param live_activity_start_request: (required) :type live_activity_start_request: LiveActivityStartRequest @@ -1224,7 +1224,7 @@ def update_live_activity( ) -> LiveActivityUpdateResponse: """Update a Live Activity (legacy manual lifecycle) - Legacy manual lifecycle endpoint. For new integrations, use PUT /live-activity/stream/{stream_key} so ActivitySmith can manage start, update, rotation, and end state for you. This endpoint remains supported for existing integrations and advanced lifecycle control. Updates an existing Live Activity. If the per-activity token is not registered yet, the update is queued. Supports segmented_progress, progress, metrics, stats, and alert activity types. For segmented_progress activities, you can increase or decrease number_of_steps here as the workflow changes. + Legacy manual lifecycle endpoint. For new integrations, use PUT /live-activity/stream/{stream_key} so ActivitySmith can manage start, update, rotation, and end state for you. This endpoint remains supported for existing integrations and advanced lifecycle control. Updates an existing Live Activity. If the per-activity token is not registered yet, the update is queued. Supports segmented_progress, progress, metrics, stats, alert, and timer activity types. For segmented_progress activities, you can increase or decrease number_of_steps here as the workflow changes. For timer activities, send duration_seconds only when you want to reset the timer window; omit it to keep the current timer running. :param live_activity_update_request: (required) :type live_activity_update_request: LiveActivityUpdateRequest @@ -1293,7 +1293,7 @@ def update_live_activity_with_http_info( ) -> ApiResponse[LiveActivityUpdateResponse]: """Update a Live Activity (legacy manual lifecycle) - Legacy manual lifecycle endpoint. For new integrations, use PUT /live-activity/stream/{stream_key} so ActivitySmith can manage start, update, rotation, and end state for you. This endpoint remains supported for existing integrations and advanced lifecycle control. Updates an existing Live Activity. If the per-activity token is not registered yet, the update is queued. Supports segmented_progress, progress, metrics, stats, and alert activity types. For segmented_progress activities, you can increase or decrease number_of_steps here as the workflow changes. + Legacy manual lifecycle endpoint. For new integrations, use PUT /live-activity/stream/{stream_key} so ActivitySmith can manage start, update, rotation, and end state for you. This endpoint remains supported for existing integrations and advanced lifecycle control. Updates an existing Live Activity. If the per-activity token is not registered yet, the update is queued. Supports segmented_progress, progress, metrics, stats, alert, and timer activity types. For segmented_progress activities, you can increase or decrease number_of_steps here as the workflow changes. For timer activities, send duration_seconds only when you want to reset the timer window; omit it to keep the current timer running. :param live_activity_update_request: (required) :type live_activity_update_request: LiveActivityUpdateRequest @@ -1362,7 +1362,7 @@ def update_live_activity_without_preload_content( ) -> RESTResponseType: """Update a Live Activity (legacy manual lifecycle) - Legacy manual lifecycle endpoint. For new integrations, use PUT /live-activity/stream/{stream_key} so ActivitySmith can manage start, update, rotation, and end state for you. This endpoint remains supported for existing integrations and advanced lifecycle control. Updates an existing Live Activity. If the per-activity token is not registered yet, the update is queued. Supports segmented_progress, progress, metrics, stats, and alert activity types. For segmented_progress activities, you can increase or decrease number_of_steps here as the workflow changes. + Legacy manual lifecycle endpoint. For new integrations, use PUT /live-activity/stream/{stream_key} so ActivitySmith can manage start, update, rotation, and end state for you. This endpoint remains supported for existing integrations and advanced lifecycle control. Updates an existing Live Activity. If the per-activity token is not registered yet, the update is queued. Supports segmented_progress, progress, metrics, stats, alert, and timer activity types. For segmented_progress activities, you can increase or decrease number_of_steps here as the workflow changes. For timer activities, send duration_seconds only when you want to reset the timer window; omit it to keep the current timer running. :param live_activity_update_request: (required) :type live_activity_update_request: LiveActivityUpdateRequest diff --git a/activitysmith_openapi/docs/ContentStateEnd.md b/activitysmith_openapi/docs/ContentStateEnd.md index c608784..5fbc8bf 100644 --- a/activitysmith_openapi/docs/ContentStateEnd.md +++ b/activitysmith_openapi/docs/ContentStateEnd.md @@ -1,6 +1,6 @@ # ContentStateEnd -End payload requires title. For segmented_progress include current_step and optionally number_of_steps. For progress include percentage or value with upper_limit. For metrics and stats include a non-empty metrics array. For alert include message. Optional icon is supported by all Live Activity types. Optional badge is supported by alert, progress, and segmented_progress. Type is optional when ending an existing activity. You can send an updated number_of_steps here if the workflow changed after start. +End payload requires title. For segmented_progress include current_step and optionally number_of_steps. For progress include percentage or value with upper_limit. For metrics and stats include a non-empty metrics array. For alert include message. For timer, omit duration_seconds to preserve and freeze the latest timer state. Optional icon is supported by all Live Activity types. Optional badge is supported by alert, progress, and segmented_progress. Type is optional when ending an existing activity. You can send an updated number_of_steps here if the workflow changed after start. ## Properties @@ -13,12 +13,15 @@ Name | Type | Description | Notes **percentage** | **float** | Progress percentage (0–100). Use for type=progress. Takes precedence over value/upper_limit if both are provided. | [optional] **value** | **float** | Current progress value. Use with upper_limit for type=progress. | [optional] **upper_limit** | **float** | Maximum progress value. Use with value for type=progress. | [optional] +**duration_seconds** | **float** | Timer duration in seconds. For type=timer, omit duration_seconds on end to preserve and freeze the latest timer state. | [optional] +**counts_down** | **bool** | Use with type=timer. When true or omitted, the timer counts down from duration_seconds. Set false for an elapsed timer; omit duration_seconds for an open-ended elapsed timer. | [optional] [default to True] +**is_running** | **bool** | Use with type=timer. Defaults to true. Set false to pause/freeze via API; set true on a paused timer to resume. | [optional] [default to True] **metrics** | [**List[ActivityMetric]**](ActivityMetric.md) | Use for type=metrics or type=stats. | [optional] **message** | **str** | Alert message. Use for type=alert. | [optional] -**icon** | [**LiveActivityAlertIcon**](LiveActivityAlertIcon.md) | Optional SF Symbol icon. Supported by alert, progress, segmented_progress, metrics, and stats. | [optional] +**icon** | [**LiveActivityAlertIcon**](LiveActivityAlertIcon.md) | Optional SF Symbol icon. Supported by alert, progress, segmented_progress, metrics, stats, and timer. | [optional] **badge** | [**LiveActivityAlertBadge**](LiveActivityAlertBadge.md) | Optional badge. Supported by alert, progress, and segmented_progress. | [optional] **type** | **str** | Optional. When omitted, the API uses the existing Live Activity type. | [optional] -**color** | **str** | Optional. Accent color for progress, segmented_progress, and metrics Live Activities. For Alert Live Activities, this tints the action button when action is included. | [optional] +**color** | **str** | Optional. Accent color for progress, segmented_progress, metrics, and timer Live Activities. For Alert Live Activities, this tints the action button when action is included. | [optional] **step_color** | **str** | Optional. Overrides color for the current step. Only applies to type=segmented_progress. | [optional] **step_colors** | **List[str]** | Optional. Colors for completed steps. When used with segmented_progress, the array length should match current_step. | [optional] **auto_dismiss_minutes** | **int** | Optional. Minutes before the ended Live Activity is dismissed. Default 3. Set 0 for immediate dismissal. iOS will dismiss ended Live Activities after ~4 hours max. | [optional] [default to 3] diff --git a/activitysmith_openapi/docs/ContentStateStart.md b/activitysmith_openapi/docs/ContentStateStart.md index 6036e3f..cb504f7 100644 --- a/activitysmith_openapi/docs/ContentStateStart.md +++ b/activitysmith_openapi/docs/ContentStateStart.md @@ -1,6 +1,6 @@ # ContentStateStart -Start payload requires title and type. For segmented_progress include number_of_steps and current_step. For progress include percentage or value with upper_limit. For metrics and stats include a non-empty metrics array. For alert include message. Optional icon is supported by all Live Activity types. Optional badge is supported by alert, progress, and segmented_progress. For segmented_progress, number_of_steps is not locked and can be changed in later update or end calls. +Start payload requires title and type. For segmented_progress include number_of_steps and current_step. For progress include percentage or value with upper_limit. For metrics and stats include a non-empty metrics array. For alert include message. For timer include duration_seconds for countdowns, or set counts_down false without duration_seconds for an open-ended elapsed timer. Optional icon is supported by all Live Activity types. Optional badge is supported by alert, progress, and segmented_progress. For segmented_progress, number_of_steps is not locked and can be changed in later update or end calls. ## Properties @@ -13,12 +13,15 @@ Name | Type | Description | Notes **percentage** | **float** | Progress percentage (0–100). Use for type=progress. Takes precedence over value/upper_limit if both are provided. | [optional] **value** | **float** | Current progress value. Use with upper_limit for type=progress. | [optional] **upper_limit** | **float** | Maximum progress value. Use with value for type=progress. | [optional] +**duration_seconds** | **float** | Timer duration in seconds. For type=timer countdowns, required on start when counts_down is true or omitted. | [optional] +**counts_down** | **bool** | Use with type=timer. When true or omitted, the timer counts down from duration_seconds. Set false for an elapsed timer; omit duration_seconds for an open-ended elapsed timer. | [optional] [default to True] +**is_running** | **bool** | Use with type=timer. Defaults to true. Set false to pause/freeze via API; set true on a paused timer to resume. | [optional] [default to True] **metrics** | [**List[ActivityMetric]**](ActivityMetric.md) | Use for type=metrics or type=stats. | [optional] **message** | **str** | Required for type=alert. | [optional] -**icon** | [**LiveActivityAlertIcon**](LiveActivityAlertIcon.md) | Optional SF Symbol icon. Supported by alert, progress, segmented_progress, metrics, and stats. | [optional] +**icon** | [**LiveActivityAlertIcon**](LiveActivityAlertIcon.md) | Optional SF Symbol icon. Supported by alert, progress, segmented_progress, metrics, stats, and timer. | [optional] **badge** | [**LiveActivityAlertBadge**](LiveActivityAlertBadge.md) | Optional badge. Supported by alert, progress, and segmented_progress. | [optional] **type** | **str** | | -**color** | **str** | Optional. Accent color for progress, segmented_progress, and metrics Live Activities. For Alert Live Activities, this tints the action button when action is included. | [optional] +**color** | **str** | Optional. Accent color for progress, segmented_progress, metrics, and timer Live Activities. For Alert Live Activities, this tints the action button when action is included. | [optional] **step_color** | **str** | Optional. Overrides color for the current step. Only applies to type=segmented_progress. | [optional] **step_colors** | **List[str]** | Optional. Colors for completed steps. When used with segmented_progress, the array length should match current_step. | [optional] diff --git a/activitysmith_openapi/docs/ContentStateUpdate.md b/activitysmith_openapi/docs/ContentStateUpdate.md index d506517..4717477 100644 --- a/activitysmith_openapi/docs/ContentStateUpdate.md +++ b/activitysmith_openapi/docs/ContentStateUpdate.md @@ -1,6 +1,6 @@ # ContentStateUpdate -Update payload requires title. For segmented_progress include current_step and optionally number_of_steps. For progress include percentage or value with upper_limit. For metrics and stats include a non-empty metrics array. For alert include message. Optional icon is supported by all Live Activity types. Optional badge is supported by alert, progress, and segmented_progress. Type is optional when updating an existing activity. You can increase or decrease number_of_steps during updates. +Update payload requires title. For segmented_progress include current_step and optionally number_of_steps. For progress include percentage or value with upper_limit. For metrics and stats include a non-empty metrics array. For alert include message. For timer, omit duration_seconds to preserve the current timer window or send duration_seconds to reset the timer from the update request time. Optional icon is supported by all Live Activity types. Optional badge is supported by alert, progress, and segmented_progress. Type is optional when updating an existing activity. You can increase or decrease number_of_steps during updates. ## Properties @@ -13,12 +13,15 @@ Name | Type | Description | Notes **percentage** | **float** | Progress percentage (0–100). Use for type=progress. Takes precedence over value/upper_limit if both are provided. | [optional] **value** | **float** | Current progress value. Use with upper_limit for type=progress. | [optional] **upper_limit** | **float** | Maximum progress value. Use with value for type=progress. | [optional] +**duration_seconds** | **float** | Timer duration in seconds. For type=timer, sending duration_seconds resets the timer window from the update request time; omit it to preserve the existing timer window. | [optional] +**counts_down** | **bool** | Use with type=timer. When true or omitted, the timer counts down from duration_seconds. Set false for an elapsed timer; omit duration_seconds for an open-ended elapsed timer. | [optional] [default to True] +**is_running** | **bool** | Use with type=timer. Defaults to true. Set false to pause/freeze via API; set true on a paused timer to resume. | [optional] [default to True] **metrics** | [**List[ActivityMetric]**](ActivityMetric.md) | Use for type=metrics or type=stats. | [optional] **message** | **str** | Alert message. Use for type=alert. | [optional] -**icon** | [**LiveActivityAlertIcon**](LiveActivityAlertIcon.md) | Optional SF Symbol icon. Supported by alert, progress, segmented_progress, metrics, and stats. | [optional] +**icon** | [**LiveActivityAlertIcon**](LiveActivityAlertIcon.md) | Optional SF Symbol icon. Supported by alert, progress, segmented_progress, metrics, stats, and timer. | [optional] **badge** | [**LiveActivityAlertBadge**](LiveActivityAlertBadge.md) | Optional badge. Supported by alert, progress, and segmented_progress. | [optional] **type** | **str** | Optional. When omitted, the API uses the existing Live Activity type. | [optional] -**color** | **str** | Optional. Accent color for progress, segmented_progress, and metrics Live Activities. For Alert Live Activities, this tints the action button when action is included. | [optional] +**color** | **str** | Optional. Accent color for progress, segmented_progress, metrics, and timer Live Activities. For Alert Live Activities, this tints the action button when action is included. | [optional] **step_color** | **str** | Optional. Overrides color for the current step. Only applies to type=segmented_progress. | [optional] **step_colors** | **List[str]** | Optional. Colors for completed steps. When used with segmented_progress, the array length should match current_step. | [optional] diff --git a/activitysmith_openapi/docs/LiveActivitiesApi.md b/activitysmith_openapi/docs/LiveActivitiesApi.md index 1f32675..b28ca3e 100644 --- a/activitysmith_openapi/docs/LiveActivitiesApi.md +++ b/activitysmith_openapi/docs/LiveActivitiesApi.md @@ -16,7 +16,7 @@ Method | HTTP request | Description End a Live Activity (legacy manual lifecycle) -Legacy manual lifecycle endpoint. For new integrations, use DELETE /live-activity/stream/{stream_key} to end a managed Live Activity stream. This endpoint remains supported for existing integrations and advanced lifecycle control. Ends a Live Activity and archives its lifecycle. Supports segmented_progress, progress, metrics, stats, and alert activity types. For segmented_progress activities, you can send the latest number_of_steps here if the workflow changed after start. +Legacy manual lifecycle endpoint. For new integrations, use DELETE /live-activity/stream/{stream_key} to end a managed Live Activity stream. This endpoint remains supported for existing integrations and advanced lifecycle control. Ends a Live Activity and archives its lifecycle. Supports segmented_progress, progress, metrics, stats, alert, and timer activity types. For segmented_progress activities, you can send the latest number_of_steps here if the workflow changed after start. ### Example @@ -181,7 +181,7 @@ Name | Type | Description | Notes Start a new Live Activity or update an existing one -Use a stable stream_key for each ongoing thing you want to show as a Live Activity. Send the latest content_state whenever it changes, and ActivitySmith will keep the Live Activity in sync. +Use a stable stream_key for each ongoing thing you want to show as a Live Activity. Send the latest content_state whenever it changes, and ActivitySmith will keep the Live Activity in sync. For timer streams, send duration_seconds to start or reset the timer; omit duration_seconds on later updates to preserve the existing timer window. ### Example @@ -266,7 +266,7 @@ Name | Type | Description | Notes Start a Live Activity (legacy manual lifecycle) -Legacy manual lifecycle endpoint. For new integrations, use PUT /live-activity/stream/{stream_key} so ActivitySmith can manage start, update, rotation, and end state for you. This endpoint remains supported for existing integrations and advanced lifecycle control. Starts a Live Activity on devices matched by API key scope and optional target channels. Supports segmented_progress, progress, metrics, stats, and alert activity types. For segmented_progress activities, number_of_steps can be changed later during update or end calls if the workflow changes. +Legacy manual lifecycle endpoint. For new integrations, use PUT /live-activity/stream/{stream_key} so ActivitySmith can manage start, update, rotation, and end state for you. This endpoint remains supported for existing integrations and advanced lifecycle control. Starts a Live Activity on devices matched by API key scope and optional target channels. Supports segmented_progress, progress, metrics, stats, alert, and timer activity types. For segmented_progress activities, number_of_steps can be changed later during update or end calls if the workflow changes. ### Example @@ -349,7 +349,7 @@ Name | Type | Description | Notes Update a Live Activity (legacy manual lifecycle) -Legacy manual lifecycle endpoint. For new integrations, use PUT /live-activity/stream/{stream_key} so ActivitySmith can manage start, update, rotation, and end state for you. This endpoint remains supported for existing integrations and advanced lifecycle control. Updates an existing Live Activity. If the per-activity token is not registered yet, the update is queued. Supports segmented_progress, progress, metrics, stats, and alert activity types. For segmented_progress activities, you can increase or decrease number_of_steps here as the workflow changes. +Legacy manual lifecycle endpoint. For new integrations, use PUT /live-activity/stream/{stream_key} so ActivitySmith can manage start, update, rotation, and end state for you. This endpoint remains supported for existing integrations and advanced lifecycle control. Updates an existing Live Activity. If the per-activity token is not registered yet, the update is queued. Supports segmented_progress, progress, metrics, stats, alert, and timer activity types. For segmented_progress activities, you can increase or decrease number_of_steps here as the workflow changes. For timer activities, send duration_seconds only when you want to reset the timer window; omit it to keep the current timer running. ### Example diff --git a/activitysmith_openapi/docs/LiveActivityAction.md b/activitysmith_openapi/docs/LiveActivityAction.md index 6967e1c..642d317 100644 --- a/activitysmith_openapi/docs/LiveActivityAction.md +++ b/activitysmith_openapi/docs/LiveActivityAction.md @@ -8,7 +8,7 @@ Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- **title** | **str** | Button title displayed in the Live Activity UI. | **type** | [**LiveActivityActionType**](LiveActivityActionType.md) | | -**url** | **str** | Action URL. For open_url, use an HTTPS URL or a shortcuts://run-shortcut?name=... URL. For webhook, use an HTTPS URL called by the ActivitySmith backend. | +**url** | **str** | Action URL. For open_url, use an HTTPS URL or a shortcuts://run-shortcut?name=... URL that runs a specific iPhone Shortcut. For webhook, use an HTTPS URL called by the ActivitySmith backend. | **method** | [**LiveActivityWebhookMethod**](LiveActivityWebhookMethod.md) | Webhook HTTP method. Used only when type=webhook. | [optional] [default to LiveActivityWebhookMethod.POST] **body** | **Dict[str, object]** | Optional webhook payload body. Used only when type=webhook. | [optional] diff --git a/activitysmith_openapi/docs/PushNotificationAction.md b/activitysmith_openapi/docs/PushNotificationAction.md index a5484db..c7a203b 100644 --- a/activitysmith_openapi/docs/PushNotificationAction.md +++ b/activitysmith_openapi/docs/PushNotificationAction.md @@ -7,7 +7,7 @@ Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- **title** | **str** | Button title displayed in iOS expanded notification UI. | **type** | [**PushNotificationActionType**](PushNotificationActionType.md) | | -**url** | **str** | Action URL. For open_url, use an HTTPS URL or a shortcuts://run-shortcut?name=... URL. For webhook, use an HTTPS URL called by the ActivitySmith backend. | +**url** | **str** | Action URL. For open_url, use an HTTPS URL or a shortcuts://run-shortcut?name=... URL that runs a specific iPhone Shortcut. For webhook, use an HTTPS URL called by the ActivitySmith backend. | **method** | [**PushNotificationWebhookMethod**](PushNotificationWebhookMethod.md) | Webhook HTTP method. Used only when type=webhook. | [optional] [default to PushNotificationWebhookMethod.POST] **body** | **Dict[str, object]** | Optional webhook payload body. Used only when type=webhook. | [optional] diff --git a/activitysmith_openapi/docs/PushNotificationRequest.md b/activitysmith_openapi/docs/PushNotificationRequest.md index 926281b..a1aa74d 100644 --- a/activitysmith_openapi/docs/PushNotificationRequest.md +++ b/activitysmith_openapi/docs/PushNotificationRequest.md @@ -9,7 +9,7 @@ Name | Type | Description | Notes **message** | **str** | | [optional] **subtitle** | **str** | | [optional] **media** | **str** | Optional HTTPS URL for an image, audio file, or video that users can preview or play when they expand the notification. If `redirection` is omitted, tapping the notification opens this URL. Cannot be combined with `actions`. | [optional] -**redirection** | **str** | Optional HTTPS URL or shortcuts://run-shortcut?name=... URL opened when user taps the notification body. Overrides the default tap target from `media` when both are provided. | [optional] +**redirection** | **str** | Optional HTTPS URL or shortcuts://run-shortcut?name=... URL opened when the user taps the notification body. Use shortcuts://run-shortcut?name=... to run a specific iPhone Shortcut that already exists on the user's device. Overrides the default tap target from `media` when both are provided. | [optional] **actions** | [**List[PushNotificationAction]**](PushNotificationAction.md) | Optional interactive actions shown when users expand the notification. Cannot be combined with `media`. | [optional] **payload** | **Dict[str, object]** | | [optional] **badge** | **int** | | [optional] diff --git a/activitysmith_openapi/docs/StreamContentState.md b/activitysmith_openapi/docs/StreamContentState.md index 72ae196..3d50ea1 100644 --- a/activitysmith_openapi/docs/StreamContentState.md +++ b/activitysmith_openapi/docs/StreamContentState.md @@ -1,6 +1,6 @@ # StreamContentState -Current state for a managed Live Activity stream. Include type on the first PUT, and whenever the stream may need to start a fresh activity. Supports segmented_progress, progress, metrics, stats, and alert types. +Current state for a managed Live Activity stream. Include type on the first PUT, and whenever the stream may need to start a fresh activity. Supports segmented_progress, progress, metrics, stats, alert, and timer types. For timer, send duration_seconds to start or reset a bounded timer; omit duration_seconds on later updates to preserve the existing timer window. ## Properties @@ -13,13 +13,16 @@ Name | Type | Description | Notes **percentage** | **float** | Use for progress. Takes precedence over value/upper_limit if both are provided. | [optional] **value** | **float** | Current progress value. Use with upper_limit for progress. | [optional] **upper_limit** | **float** | Maximum progress value. Use with value for progress. | [optional] +**duration_seconds** | **float** | Timer duration in seconds. For type=timer, send duration_seconds to start or reset the timer window; omit it on later stream updates to preserve the existing timer window. | [optional] +**counts_down** | **bool** | Use with type=timer. When true or omitted, the timer counts down from duration_seconds. Set false for an elapsed timer; omit duration_seconds for an open-ended elapsed timer. | [optional] [default to True] +**is_running** | **bool** | Use with type=timer. Defaults to true. Set false to pause/freeze via API; set true on a paused timer to resume. | [optional] [default to True] **type** | **str** | Required on the first PUT or whenever the stream cannot infer the current activity type. | [optional] -**color** | **str** | Optional. Accent color for progress, segmented_progress, and metrics Live Activities. For Alert Live Activities, this tints the action button when action is included. | [optional] +**color** | **str** | Optional. Accent color for progress, segmented_progress, metrics, and timer Live Activities. For Alert Live Activities, this tints the action button when action is included. | [optional] **step_color** | **str** | Optional. Overrides color for the current step. Only applies to segmented_progress. | [optional] **step_colors** | **List[str]** | Optional. Colors for completed steps. When used with segmented_progress, the array length should match current_step. | [optional] **metrics** | [**List[ActivityMetric]**](ActivityMetric.md) | Use for metrics and stats activities. | [optional] **message** | **str** | Required for type=alert. | [optional] -**icon** | [**LiveActivityAlertIcon**](LiveActivityAlertIcon.md) | Optional SF Symbol icon. Supported by alert, progress, segmented_progress, metrics, and stats. | [optional] +**icon** | [**LiveActivityAlertIcon**](LiveActivityAlertIcon.md) | Optional SF Symbol icon. Supported by alert, progress, segmented_progress, metrics, stats, and timer. | [optional] **badge** | [**LiveActivityAlertBadge**](LiveActivityAlertBadge.md) | Optional badge. Supported by alert, progress, and segmented_progress. | [optional] **auto_dismiss_seconds** | **int** | Optional. Seconds before the ended Live Activity is dismissed. | [optional] **auto_dismiss_minutes** | **int** | Optional. Minutes before the ended Live Activity is dismissed. | [optional] diff --git a/activitysmith_openapi/models/content_state_end.py b/activitysmith_openapi/models/content_state_end.py index 2e28aa1..f5b41bd 100644 --- a/activitysmith_openapi/models/content_state_end.py +++ b/activitysmith_openapi/models/content_state_end.py @@ -17,7 +17,7 @@ import re # noqa: F401 import json -from pydantic import BaseModel, ConfigDict, Field, StrictFloat, StrictInt, StrictStr, field_validator +from pydantic import BaseModel, ConfigDict, Field, StrictBool, StrictFloat, StrictInt, StrictStr, field_validator from typing import Any, ClassVar, Dict, List, Optional, Union from typing_extensions import Annotated from activitysmith_openapi.models.activity_metric import ActivityMetric @@ -28,7 +28,7 @@ class ContentStateEnd(BaseModel): """ - End payload requires title. For segmented_progress include current_step and optionally number_of_steps. For progress include percentage or value with upper_limit. For metrics and stats include a non-empty metrics array. For alert include message. Optional icon is supported by all Live Activity types. Optional badge is supported by alert, progress, and segmented_progress. Type is optional when ending an existing activity. You can send an updated number_of_steps here if the workflow changed after start. + End payload requires title. For segmented_progress include current_step and optionally number_of_steps. For progress include percentage or value with upper_limit. For metrics and stats include a non-empty metrics array. For alert include message. For timer, omit duration_seconds to preserve and freeze the latest timer state. Optional icon is supported by all Live Activity types. Optional badge is supported by alert, progress, and segmented_progress. Type is optional when ending an existing activity. You can send an updated number_of_steps here if the workflow changed after start. """ # noqa: E501 title: StrictStr subtitle: Optional[StrictStr] = None @@ -37,17 +37,20 @@ class ContentStateEnd(BaseModel): percentage: Optional[Union[Annotated[float, Field(le=100, strict=True, ge=0)], Annotated[int, Field(le=100, strict=True, ge=0)]]] = Field(default=None, description="Progress percentage (0–100). Use for type=progress. Takes precedence over value/upper_limit if both are provided.") value: Optional[Union[StrictFloat, StrictInt]] = Field(default=None, description="Current progress value. Use with upper_limit for type=progress.") upper_limit: Optional[Union[StrictFloat, StrictInt]] = Field(default=None, description="Maximum progress value. Use with value for type=progress.") + duration_seconds: Optional[Union[StrictFloat, StrictInt]] = Field(default=None, description="Timer duration in seconds. For type=timer, omit duration_seconds on end to preserve and freeze the latest timer state.") + counts_down: Optional[StrictBool] = Field(default=True, description="Use with type=timer. When true or omitted, the timer counts down from duration_seconds. Set false for an elapsed timer; omit duration_seconds for an open-ended elapsed timer.") + is_running: Optional[StrictBool] = Field(default=True, description="Use with type=timer. Defaults to true. Set false to pause/freeze via API; set true on a paused timer to resume.") metrics: Optional[Annotated[List[ActivityMetric], Field(min_length=1, max_length=8)]] = Field(default=None, description="Use for type=metrics or type=stats.") message: Optional[Annotated[str, Field(min_length=1, strict=True)]] = Field(default=None, description="Alert message. Use for type=alert.") - icon: Optional[LiveActivityAlertIcon] = Field(default=None, description="Optional SF Symbol icon. Supported by alert, progress, segmented_progress, metrics, and stats.") + icon: Optional[LiveActivityAlertIcon] = Field(default=None, description="Optional SF Symbol icon. Supported by alert, progress, segmented_progress, metrics, stats, and timer.") badge: Optional[LiveActivityAlertBadge] = Field(default=None, description="Optional badge. Supported by alert, progress, and segmented_progress.") type: Optional[StrictStr] = Field(default=None, description="Optional. When omitted, the API uses the existing Live Activity type.") - color: Optional[StrictStr] = Field(default=None, description="Optional. Accent color for progress, segmented_progress, and metrics Live Activities. For Alert Live Activities, this tints the action button when action is included.") + color: Optional[StrictStr] = Field(default=None, description="Optional. Accent color for progress, segmented_progress, metrics, and timer Live Activities. For Alert Live Activities, this tints the action button when action is included.") step_color: Optional[StrictStr] = Field(default=None, description="Optional. Overrides color for the current step. Only applies to type=segmented_progress.") step_colors: Optional[List[StrictStr]] = Field(default=None, description="Optional. Colors for completed steps. When used with segmented_progress, the array length should match current_step.") auto_dismiss_minutes: Optional[Annotated[int, Field(strict=True, ge=0)]] = Field(default=3, description="Optional. Minutes before the ended Live Activity is dismissed. Default 3. Set 0 for immediate dismissal. iOS will dismiss ended Live Activities after ~4 hours max.") additional_properties: Dict[str, Any] = {} - __properties: ClassVar[List[str]] = ["title", "subtitle", "number_of_steps", "current_step", "percentage", "value", "upper_limit", "metrics", "message", "icon", "badge", "type", "color", "step_color", "step_colors", "auto_dismiss_minutes"] + __properties: ClassVar[List[str]] = ["title", "subtitle", "number_of_steps", "current_step", "percentage", "value", "upper_limit", "duration_seconds", "counts_down", "is_running", "metrics", "message", "icon", "badge", "type", "color", "step_color", "step_colors", "auto_dismiss_minutes"] @field_validator('type') def type_validate_enum(cls, value): @@ -55,8 +58,8 @@ def type_validate_enum(cls, value): if value is None: return value - if value not in set(['segmented_progress', 'progress', 'metrics', 'stats', 'alert']): - raise ValueError("must be one of enum values ('segmented_progress', 'progress', 'metrics', 'stats', 'alert')") + if value not in set(['segmented_progress', 'progress', 'metrics', 'stats', 'alert', 'timer']): + raise ValueError("must be one of enum values ('segmented_progress', 'progress', 'metrics', 'stats', 'alert', 'timer')") return value @field_validator('color') @@ -168,6 +171,9 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: "percentage": obj.get("percentage"), "value": obj.get("value"), "upper_limit": obj.get("upper_limit"), + "duration_seconds": obj.get("duration_seconds"), + "counts_down": obj.get("counts_down") if obj.get("counts_down") is not None else True, + "is_running": obj.get("is_running") if obj.get("is_running") is not None else True, "metrics": [ActivityMetric.from_dict(_item) for _item in obj["metrics"]] if obj.get("metrics") is not None else None, "message": obj.get("message"), "icon": LiveActivityAlertIcon.from_dict(obj["icon"]) if obj.get("icon") is not None else None, diff --git a/activitysmith_openapi/models/content_state_start.py b/activitysmith_openapi/models/content_state_start.py index 11d2cc0..2c63b66 100644 --- a/activitysmith_openapi/models/content_state_start.py +++ b/activitysmith_openapi/models/content_state_start.py @@ -17,7 +17,7 @@ import re # noqa: F401 import json -from pydantic import BaseModel, ConfigDict, Field, StrictFloat, StrictInt, StrictStr, field_validator +from pydantic import BaseModel, ConfigDict, Field, StrictBool, StrictFloat, StrictInt, StrictStr, field_validator from typing import Any, ClassVar, Dict, List, Optional, Union from typing_extensions import Annotated from activitysmith_openapi.models.activity_metric import ActivityMetric @@ -28,7 +28,7 @@ class ContentStateStart(BaseModel): """ - Start payload requires title and type. For segmented_progress include number_of_steps and current_step. For progress include percentage or value with upper_limit. For metrics and stats include a non-empty metrics array. For alert include message. Optional icon is supported by all Live Activity types. Optional badge is supported by alert, progress, and segmented_progress. For segmented_progress, number_of_steps is not locked and can be changed in later update or end calls. + Start payload requires title and type. For segmented_progress include number_of_steps and current_step. For progress include percentage or value with upper_limit. For metrics and stats include a non-empty metrics array. For alert include message. For timer include duration_seconds for countdowns, or set counts_down false without duration_seconds for an open-ended elapsed timer. Optional icon is supported by all Live Activity types. Optional badge is supported by alert, progress, and segmented_progress. For segmented_progress, number_of_steps is not locked and can be changed in later update or end calls. """ # noqa: E501 title: StrictStr subtitle: Optional[StrictStr] = None @@ -37,22 +37,25 @@ class ContentStateStart(BaseModel): percentage: Optional[Union[Annotated[float, Field(le=100, strict=True, ge=0)], Annotated[int, Field(le=100, strict=True, ge=0)]]] = Field(default=None, description="Progress percentage (0–100). Use for type=progress. Takes precedence over value/upper_limit if both are provided.") value: Optional[Union[StrictFloat, StrictInt]] = Field(default=None, description="Current progress value. Use with upper_limit for type=progress.") upper_limit: Optional[Union[StrictFloat, StrictInt]] = Field(default=None, description="Maximum progress value. Use with value for type=progress.") + duration_seconds: Optional[Union[StrictFloat, StrictInt]] = Field(default=None, description="Timer duration in seconds. For type=timer countdowns, required on start when counts_down is true or omitted.") + counts_down: Optional[StrictBool] = Field(default=True, description="Use with type=timer. When true or omitted, the timer counts down from duration_seconds. Set false for an elapsed timer; omit duration_seconds for an open-ended elapsed timer.") + is_running: Optional[StrictBool] = Field(default=True, description="Use with type=timer. Defaults to true. Set false to pause/freeze via API; set true on a paused timer to resume.") metrics: Optional[Annotated[List[ActivityMetric], Field(min_length=1, max_length=8)]] = Field(default=None, description="Use for type=metrics or type=stats.") message: Optional[Annotated[str, Field(min_length=1, strict=True)]] = Field(default=None, description="Required for type=alert.") - icon: Optional[LiveActivityAlertIcon] = Field(default=None, description="Optional SF Symbol icon. Supported by alert, progress, segmented_progress, metrics, and stats.") + icon: Optional[LiveActivityAlertIcon] = Field(default=None, description="Optional SF Symbol icon. Supported by alert, progress, segmented_progress, metrics, stats, and timer.") badge: Optional[LiveActivityAlertBadge] = Field(default=None, description="Optional badge. Supported by alert, progress, and segmented_progress.") type: StrictStr - color: Optional[StrictStr] = Field(default=None, description="Optional. Accent color for progress, segmented_progress, and metrics Live Activities. For Alert Live Activities, this tints the action button when action is included.") + color: Optional[StrictStr] = Field(default=None, description="Optional. Accent color for progress, segmented_progress, metrics, and timer Live Activities. For Alert Live Activities, this tints the action button when action is included.") step_color: Optional[StrictStr] = Field(default=None, description="Optional. Overrides color for the current step. Only applies to type=segmented_progress.") step_colors: Optional[List[StrictStr]] = Field(default=None, description="Optional. Colors for completed steps. When used with segmented_progress, the array length should match current_step.") additional_properties: Dict[str, Any] = {} - __properties: ClassVar[List[str]] = ["title", "subtitle", "number_of_steps", "current_step", "percentage", "value", "upper_limit", "metrics", "message", "icon", "badge", "type", "color", "step_color", "step_colors"] + __properties: ClassVar[List[str]] = ["title", "subtitle", "number_of_steps", "current_step", "percentage", "value", "upper_limit", "duration_seconds", "counts_down", "is_running", "metrics", "message", "icon", "badge", "type", "color", "step_color", "step_colors"] @field_validator('type') def type_validate_enum(cls, value): """Validates the enum""" - if value not in set(['segmented_progress', 'progress', 'metrics', 'stats', 'alert']): - raise ValueError("must be one of enum values ('segmented_progress', 'progress', 'metrics', 'stats', 'alert')") + if value not in set(['segmented_progress', 'progress', 'metrics', 'stats', 'alert', 'timer']): + raise ValueError("must be one of enum values ('segmented_progress', 'progress', 'metrics', 'stats', 'alert', 'timer')") return value @field_validator('color') @@ -164,6 +167,9 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: "percentage": obj.get("percentage"), "value": obj.get("value"), "upper_limit": obj.get("upper_limit"), + "duration_seconds": obj.get("duration_seconds"), + "counts_down": obj.get("counts_down") if obj.get("counts_down") is not None else True, + "is_running": obj.get("is_running") if obj.get("is_running") is not None else True, "metrics": [ActivityMetric.from_dict(_item) for _item in obj["metrics"]] if obj.get("metrics") is not None else None, "message": obj.get("message"), "icon": LiveActivityAlertIcon.from_dict(obj["icon"]) if obj.get("icon") is not None else None, diff --git a/activitysmith_openapi/models/content_state_update.py b/activitysmith_openapi/models/content_state_update.py index 08c7972..bfad292 100644 --- a/activitysmith_openapi/models/content_state_update.py +++ b/activitysmith_openapi/models/content_state_update.py @@ -17,7 +17,7 @@ import re # noqa: F401 import json -from pydantic import BaseModel, ConfigDict, Field, StrictFloat, StrictInt, StrictStr, field_validator +from pydantic import BaseModel, ConfigDict, Field, StrictBool, StrictFloat, StrictInt, StrictStr, field_validator from typing import Any, ClassVar, Dict, List, Optional, Union from typing_extensions import Annotated from activitysmith_openapi.models.activity_metric import ActivityMetric @@ -28,7 +28,7 @@ class ContentStateUpdate(BaseModel): """ - Update payload requires title. For segmented_progress include current_step and optionally number_of_steps. For progress include percentage or value with upper_limit. For metrics and stats include a non-empty metrics array. For alert include message. Optional icon is supported by all Live Activity types. Optional badge is supported by alert, progress, and segmented_progress. Type is optional when updating an existing activity. You can increase or decrease number_of_steps during updates. + Update payload requires title. For segmented_progress include current_step and optionally number_of_steps. For progress include percentage or value with upper_limit. For metrics and stats include a non-empty metrics array. For alert include message. For timer, omit duration_seconds to preserve the current timer window or send duration_seconds to reset the timer from the update request time. Optional icon is supported by all Live Activity types. Optional badge is supported by alert, progress, and segmented_progress. Type is optional when updating an existing activity. You can increase or decrease number_of_steps during updates. """ # noqa: E501 title: StrictStr subtitle: Optional[StrictStr] = None @@ -37,16 +37,19 @@ class ContentStateUpdate(BaseModel): percentage: Optional[Union[Annotated[float, Field(le=100, strict=True, ge=0)], Annotated[int, Field(le=100, strict=True, ge=0)]]] = Field(default=None, description="Progress percentage (0–100). Use for type=progress. Takes precedence over value/upper_limit if both are provided.") value: Optional[Union[StrictFloat, StrictInt]] = Field(default=None, description="Current progress value. Use with upper_limit for type=progress.") upper_limit: Optional[Union[StrictFloat, StrictInt]] = Field(default=None, description="Maximum progress value. Use with value for type=progress.") + duration_seconds: Optional[Union[StrictFloat, StrictInt]] = Field(default=None, description="Timer duration in seconds. For type=timer, sending duration_seconds resets the timer window from the update request time; omit it to preserve the existing timer window.") + counts_down: Optional[StrictBool] = Field(default=True, description="Use with type=timer. When true or omitted, the timer counts down from duration_seconds. Set false for an elapsed timer; omit duration_seconds for an open-ended elapsed timer.") + is_running: Optional[StrictBool] = Field(default=True, description="Use with type=timer. Defaults to true. Set false to pause/freeze via API; set true on a paused timer to resume.") metrics: Optional[Annotated[List[ActivityMetric], Field(min_length=1, max_length=8)]] = Field(default=None, description="Use for type=metrics or type=stats.") message: Optional[Annotated[str, Field(min_length=1, strict=True)]] = Field(default=None, description="Alert message. Use for type=alert.") - icon: Optional[LiveActivityAlertIcon] = Field(default=None, description="Optional SF Symbol icon. Supported by alert, progress, segmented_progress, metrics, and stats.") + icon: Optional[LiveActivityAlertIcon] = Field(default=None, description="Optional SF Symbol icon. Supported by alert, progress, segmented_progress, metrics, stats, and timer.") badge: Optional[LiveActivityAlertBadge] = Field(default=None, description="Optional badge. Supported by alert, progress, and segmented_progress.") type: Optional[StrictStr] = Field(default=None, description="Optional. When omitted, the API uses the existing Live Activity type.") - color: Optional[StrictStr] = Field(default=None, description="Optional. Accent color for progress, segmented_progress, and metrics Live Activities. For Alert Live Activities, this tints the action button when action is included.") + color: Optional[StrictStr] = Field(default=None, description="Optional. Accent color for progress, segmented_progress, metrics, and timer Live Activities. For Alert Live Activities, this tints the action button when action is included.") step_color: Optional[StrictStr] = Field(default=None, description="Optional. Overrides color for the current step. Only applies to type=segmented_progress.") step_colors: Optional[List[StrictStr]] = Field(default=None, description="Optional. Colors for completed steps. When used with segmented_progress, the array length should match current_step.") additional_properties: Dict[str, Any] = {} - __properties: ClassVar[List[str]] = ["title", "subtitle", "number_of_steps", "current_step", "percentage", "value", "upper_limit", "metrics", "message", "icon", "badge", "type", "color", "step_color", "step_colors"] + __properties: ClassVar[List[str]] = ["title", "subtitle", "number_of_steps", "current_step", "percentage", "value", "upper_limit", "duration_seconds", "counts_down", "is_running", "metrics", "message", "icon", "badge", "type", "color", "step_color", "step_colors"] @field_validator('type') def type_validate_enum(cls, value): @@ -54,8 +57,8 @@ def type_validate_enum(cls, value): if value is None: return value - if value not in set(['segmented_progress', 'progress', 'metrics', 'stats', 'alert']): - raise ValueError("must be one of enum values ('segmented_progress', 'progress', 'metrics', 'stats', 'alert')") + if value not in set(['segmented_progress', 'progress', 'metrics', 'stats', 'alert', 'timer']): + raise ValueError("must be one of enum values ('segmented_progress', 'progress', 'metrics', 'stats', 'alert', 'timer')") return value @field_validator('color') @@ -167,6 +170,9 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: "percentage": obj.get("percentage"), "value": obj.get("value"), "upper_limit": obj.get("upper_limit"), + "duration_seconds": obj.get("duration_seconds"), + "counts_down": obj.get("counts_down") if obj.get("counts_down") is not None else True, + "is_running": obj.get("is_running") if obj.get("is_running") is not None else True, "metrics": [ActivityMetric.from_dict(_item) for _item in obj["metrics"]] if obj.get("metrics") is not None else None, "message": obj.get("message"), "icon": LiveActivityAlertIcon.from_dict(obj["icon"]) if obj.get("icon") is not None else None, diff --git a/activitysmith_openapi/models/live_activity_action.py b/activitysmith_openapi/models/live_activity_action.py index d6ba4ec..011ff37 100644 --- a/activitysmith_openapi/models/live_activity_action.py +++ b/activitysmith_openapi/models/live_activity_action.py @@ -17,7 +17,7 @@ import re # noqa: F401 import json -from pydantic import BaseModel, ConfigDict, Field, StrictStr, model_validator +from pydantic import BaseModel, ConfigDict, Field, StrictStr from typing import Any, ClassVar, Dict, List, Optional from activitysmith_openapi.models.live_activity_action_type import LiveActivityActionType from activitysmith_openapi.models.live_activity_webhook_method import LiveActivityWebhookMethod @@ -30,7 +30,7 @@ class LiveActivityAction(BaseModel): """ # noqa: E501 title: StrictStr = Field(description="Button title displayed in the Live Activity UI.") type: LiveActivityActionType - url: StrictStr = Field(description="Action URL. For open_url, use an HTTPS URL or a shortcuts://run-shortcut?name=... URL. For webhook, use an HTTPS URL called by the ActivitySmith backend.") + url: StrictStr = Field(description="Action URL. For open_url, use an HTTPS URL or a shortcuts://run-shortcut?name=... URL that runs a specific iPhone Shortcut. For webhook, use an HTTPS URL called by the ActivitySmith backend.") method: Optional[LiveActivityWebhookMethod] = Field(default=LiveActivityWebhookMethod.POST, description="Webhook HTTP method. Used only when type=webhook.") body: Optional[Dict[str, Any]] = Field(default=None, description="Optional webhook payload body. Used only when type=webhook.") additional_properties: Dict[str, Any] = {} @@ -42,14 +42,6 @@ class LiveActivityAction(BaseModel): protected_namespaces=(), ) - @model_validator(mode="after") - def validate_url_for_type(self) -> Self: - if self.type == LiveActivityActionType.OPEN_URL and not (self.url.startswith("https://") or self.url.startswith("shortcuts://")): - raise ValueError("open_url action url must use https or shortcuts") - if self.type == LiveActivityActionType.WEBHOOK and not self.url.startswith("https://"): - raise ValueError("webhook action url must use https") - return self - def to_str(self) -> str: """Returns the string representation of the model using alias""" @@ -110,3 +102,4 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: return _obj + diff --git a/activitysmith_openapi/models/push_notification_action.py b/activitysmith_openapi/models/push_notification_action.py index 10df546..65fcdbc 100644 --- a/activitysmith_openapi/models/push_notification_action.py +++ b/activitysmith_openapi/models/push_notification_action.py @@ -17,7 +17,7 @@ import re # noqa: F401 import json -from pydantic import BaseModel, ConfigDict, Field, StrictStr, model_validator +from pydantic import BaseModel, ConfigDict, Field, StrictStr from typing import Any, ClassVar, Dict, List, Optional from activitysmith_openapi.models.push_notification_action_type import PushNotificationActionType from activitysmith_openapi.models.push_notification_webhook_method import PushNotificationWebhookMethod @@ -30,7 +30,7 @@ class PushNotificationAction(BaseModel): """ # noqa: E501 title: StrictStr = Field(description="Button title displayed in iOS expanded notification UI.") type: PushNotificationActionType - url: StrictStr = Field(description="Action URL. For open_url, use an HTTPS URL or a shortcuts://run-shortcut?name=... URL. For webhook, use an HTTPS URL called by the ActivitySmith backend.") + url: StrictStr = Field(description="Action URL. For open_url, use an HTTPS URL or a shortcuts://run-shortcut?name=... URL that runs a specific iPhone Shortcut. For webhook, use an HTTPS URL called by the ActivitySmith backend.") method: Optional[PushNotificationWebhookMethod] = Field(default=PushNotificationWebhookMethod.POST, description="Webhook HTTP method. Used only when type=webhook.") body: Optional[Dict[str, Any]] = Field(default=None, description="Optional webhook payload body. Used only when type=webhook.") additional_properties: Dict[str, Any] = {} @@ -42,14 +42,6 @@ class PushNotificationAction(BaseModel): protected_namespaces=(), ) - @model_validator(mode="after") - def validate_url_for_type(self) -> Self: - if self.type == PushNotificationActionType.OPEN_URL and not (self.url.startswith("https://") or self.url.startswith("shortcuts://")): - raise ValueError("open_url action url must use https or shortcuts") - if self.type == PushNotificationActionType.WEBHOOK and not self.url.startswith("https://"): - raise ValueError("webhook action url must use https") - return self - def to_str(self) -> str: """Returns the string representation of the model using alias""" @@ -110,3 +102,4 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: return _obj + diff --git a/activitysmith_openapi/models/push_notification_request.py b/activitysmith_openapi/models/push_notification_request.py index 01d3b47..9f3a236 100644 --- a/activitysmith_openapi/models/push_notification_request.py +++ b/activitysmith_openapi/models/push_notification_request.py @@ -33,7 +33,7 @@ class PushNotificationRequest(BaseModel): message: Optional[StrictStr] = None subtitle: Optional[StrictStr] = None media: Optional[Annotated[str, Field(strict=True)]] = Field(default=None, description="Optional HTTPS URL for an image, audio file, or video that users can preview or play when they expand the notification. If `redirection` is omitted, tapping the notification opens this URL. Cannot be combined with `actions`.") - redirection: Optional[Annotated[str, Field(strict=True)]] = Field(default=None, description="Optional HTTPS URL or shortcuts://run-shortcut?name=... URL opened when user taps the notification body. Overrides the default tap target from `media` when both are provided.") + redirection: Optional[Annotated[str, Field(strict=True)]] = Field(default=None, description="Optional HTTPS URL or shortcuts://run-shortcut?name=... URL opened when the user taps the notification body. Use shortcuts://run-shortcut?name=... to run a specific iPhone Shortcut that already exists on the user's device. Overrides the default tap target from `media` when both are provided.") actions: Optional[Annotated[List[PushNotificationAction], Field(max_length=4)]] = Field(default=None, description="Optional interactive actions shown when users expand the notification. Cannot be combined with `media`.") payload: Optional[Dict[str, Any]] = None badge: Optional[StrictInt] = None diff --git a/activitysmith_openapi/models/stream_content_state.py b/activitysmith_openapi/models/stream_content_state.py index c07f8ad..219daf0 100644 --- a/activitysmith_openapi/models/stream_content_state.py +++ b/activitysmith_openapi/models/stream_content_state.py @@ -17,7 +17,7 @@ import re # noqa: F401 import json -from pydantic import BaseModel, ConfigDict, Field, StrictFloat, StrictInt, StrictStr, field_validator +from pydantic import BaseModel, ConfigDict, Field, StrictBool, StrictFloat, StrictInt, StrictStr, field_validator from typing import Any, ClassVar, Dict, List, Optional, Union from typing_extensions import Annotated from activitysmith_openapi.models.activity_metric import ActivityMetric @@ -28,7 +28,7 @@ class StreamContentState(BaseModel): """ - Current state for a managed Live Activity stream. Include type on the first PUT, and whenever the stream may need to start a fresh activity. Supports segmented_progress, progress, metrics, stats, and alert types. + Current state for a managed Live Activity stream. Include type on the first PUT, and whenever the stream may need to start a fresh activity. Supports segmented_progress, progress, metrics, stats, alert, and timer types. For timer, send duration_seconds to start or reset a bounded timer; omit duration_seconds on later updates to preserve the existing timer window. """ # noqa: E501 title: StrictStr subtitle: Optional[StrictStr] = None @@ -37,18 +37,21 @@ class StreamContentState(BaseModel): percentage: Optional[Union[Annotated[float, Field(le=100, strict=True, ge=0)], Annotated[int, Field(le=100, strict=True, ge=0)]]] = Field(default=None, description="Use for progress. Takes precedence over value/upper_limit if both are provided.") value: Optional[Union[StrictFloat, StrictInt]] = Field(default=None, description="Current progress value. Use with upper_limit for progress.") upper_limit: Optional[Union[StrictFloat, StrictInt]] = Field(default=None, description="Maximum progress value. Use with value for progress.") + duration_seconds: Optional[Union[StrictFloat, StrictInt]] = Field(default=None, description="Timer duration in seconds. For type=timer, send duration_seconds to start or reset the timer window; omit it on later stream updates to preserve the existing timer window.") + counts_down: Optional[StrictBool] = Field(default=True, description="Use with type=timer. When true or omitted, the timer counts down from duration_seconds. Set false for an elapsed timer; omit duration_seconds for an open-ended elapsed timer.") + is_running: Optional[StrictBool] = Field(default=True, description="Use with type=timer. Defaults to true. Set false to pause/freeze via API; set true on a paused timer to resume.") type: Optional[StrictStr] = Field(default=None, description="Required on the first PUT or whenever the stream cannot infer the current activity type.") - color: Optional[StrictStr] = Field(default=None, description="Optional. Accent color for progress, segmented_progress, and metrics Live Activities. For Alert Live Activities, this tints the action button when action is included.") + color: Optional[StrictStr] = Field(default=None, description="Optional. Accent color for progress, segmented_progress, metrics, and timer Live Activities. For Alert Live Activities, this tints the action button when action is included.") step_color: Optional[StrictStr] = Field(default=None, description="Optional. Overrides color for the current step. Only applies to segmented_progress.") step_colors: Optional[List[StrictStr]] = Field(default=None, description="Optional. Colors for completed steps. When used with segmented_progress, the array length should match current_step.") metrics: Optional[Annotated[List[ActivityMetric], Field(min_length=1, max_length=8)]] = Field(default=None, description="Use for metrics and stats activities.") message: Optional[Annotated[str, Field(min_length=1, strict=True)]] = Field(default=None, description="Required for type=alert.") - icon: Optional[LiveActivityAlertIcon] = Field(default=None, description="Optional SF Symbol icon. Supported by alert, progress, segmented_progress, metrics, and stats.") + icon: Optional[LiveActivityAlertIcon] = Field(default=None, description="Optional SF Symbol icon. Supported by alert, progress, segmented_progress, metrics, stats, and timer.") badge: Optional[LiveActivityAlertBadge] = Field(default=None, description="Optional badge. Supported by alert, progress, and segmented_progress.") auto_dismiss_seconds: Optional[Annotated[int, Field(strict=True, ge=0)]] = Field(default=None, description="Optional. Seconds before the ended Live Activity is dismissed.") auto_dismiss_minutes: Optional[Annotated[int, Field(strict=True, ge=0)]] = Field(default=None, description="Optional. Minutes before the ended Live Activity is dismissed.") additional_properties: Dict[str, Any] = {} - __properties: ClassVar[List[str]] = ["title", "subtitle", "number_of_steps", "current_step", "percentage", "value", "upper_limit", "type", "color", "step_color", "step_colors", "metrics", "message", "icon", "badge", "auto_dismiss_seconds", "auto_dismiss_minutes"] + __properties: ClassVar[List[str]] = ["title", "subtitle", "number_of_steps", "current_step", "percentage", "value", "upper_limit", "duration_seconds", "counts_down", "is_running", "type", "color", "step_color", "step_colors", "metrics", "message", "icon", "badge", "auto_dismiss_seconds", "auto_dismiss_minutes"] @field_validator('type') def type_validate_enum(cls, value): @@ -56,8 +59,8 @@ def type_validate_enum(cls, value): if value is None: return value - if value not in set(['segmented_progress', 'progress', 'metrics', 'stats', 'alert']): - raise ValueError("must be one of enum values ('segmented_progress', 'progress', 'metrics', 'stats', 'alert')") + if value not in set(['segmented_progress', 'progress', 'metrics', 'stats', 'alert', 'timer']): + raise ValueError("must be one of enum values ('segmented_progress', 'progress', 'metrics', 'stats', 'alert', 'timer')") return value @field_validator('color') @@ -169,6 +172,9 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: "percentage": obj.get("percentage"), "value": obj.get("value"), "upper_limit": obj.get("upper_limit"), + "duration_seconds": obj.get("duration_seconds"), + "counts_down": obj.get("counts_down") if obj.get("counts_down") is not None else True, + "is_running": obj.get("is_running") if obj.get("is_running") is not None else True, "type": obj.get("type"), "color": obj.get("color"), "step_color": obj.get("step_color"), diff --git a/activitysmith_openapi/test/test_content_state_end.py b/activitysmith_openapi/test/test_content_state_end.py index caa5d26..220fdfe 100644 --- a/activitysmith_openapi/test/test_content_state_end.py +++ b/activitysmith_openapi/test/test_content_state_end.py @@ -42,6 +42,9 @@ def make_instance(self, include_optional) -> ContentStateEnd: percentage = 0, value = 1.337, upper_limit = 1.337, + duration_seconds = 1.337, + counts_down = True, + is_running = True, metrics = [ { } ], diff --git a/activitysmith_openapi/test/test_content_state_start.py b/activitysmith_openapi/test/test_content_state_start.py index 0df0b04..ccdbb6c 100644 --- a/activitysmith_openapi/test/test_content_state_start.py +++ b/activitysmith_openapi/test/test_content_state_start.py @@ -42,6 +42,9 @@ def make_instance(self, include_optional) -> ContentStateStart: percentage = 0, value = 1.337, upper_limit = 1.337, + duration_seconds = 1.337, + counts_down = True, + is_running = True, metrics = [ { } ], diff --git a/activitysmith_openapi/test/test_content_state_update.py b/activitysmith_openapi/test/test_content_state_update.py index 2d347f7..c0b9056 100644 --- a/activitysmith_openapi/test/test_content_state_update.py +++ b/activitysmith_openapi/test/test_content_state_update.py @@ -42,6 +42,9 @@ def make_instance(self, include_optional) -> ContentStateUpdate: percentage = 0, value = 1.337, upper_limit = 1.337, + duration_seconds = 1.337, + counts_down = True, + is_running = True, metrics = [ { } ], diff --git a/activitysmith_openapi/test/test_live_activity_action.py b/activitysmith_openapi/test/test_live_activity_action.py index e88a849..ec696ec 100644 --- a/activitysmith_openapi/test/test_live_activity_action.py +++ b/activitysmith_openapi/test/test_live_activity_action.py @@ -15,7 +15,6 @@ import unittest from activitysmith_openapi.models.live_activity_action import LiveActivityAction -from activitysmith_openapi.models.live_activity_action_type import LiveActivityActionType class TestLiveActivityAction(unittest.TestCase): """LiveActivityAction unit test stubs""" @@ -55,22 +54,5 @@ def testLiveActivityAction(self): # inst_req_only = self.make_instance(include_optional=False) # inst_req_and_optional = self.make_instance(include_optional=True) - def test_open_url_allows_shortcuts_url(self): - action = LiveActivityAction( - title="Chat", - type=LiveActivityActionType.OPEN_URL, - url="shortcuts://run-shortcut?name=JARVIS", - ) - - self.assertEqual("shortcuts://run-shortcut?name=JARVIS", action.url) - - def test_webhook_rejects_shortcuts_url(self): - with self.assertRaises(ValueError): - LiveActivityAction( - title="Chat", - type=LiveActivityActionType.WEBHOOK, - url="shortcuts://run-shortcut?name=JARVIS", - ) - if __name__ == '__main__': unittest.main() diff --git a/activitysmith_openapi/test/test_push_notification_action.py b/activitysmith_openapi/test/test_push_notification_action.py index e670103..88bdba2 100644 --- a/activitysmith_openapi/test/test_push_notification_action.py +++ b/activitysmith_openapi/test/test_push_notification_action.py @@ -15,7 +15,6 @@ import unittest from activitysmith_openapi.models.push_notification_action import PushNotificationAction -from activitysmith_openapi.models.push_notification_action_type import PushNotificationActionType class TestPushNotificationAction(unittest.TestCase): """PushNotificationAction unit test stubs""" @@ -55,22 +54,5 @@ def testPushNotificationAction(self): # inst_req_only = self.make_instance(include_optional=False) # inst_req_and_optional = self.make_instance(include_optional=True) - def test_open_url_allows_shortcuts_url(self): - action = PushNotificationAction( - title="Chat", - type=PushNotificationActionType.OPEN_URL, - url="shortcuts://run-shortcut?name=JARVIS", - ) - - self.assertEqual("shortcuts://run-shortcut?name=JARVIS", action.url) - - def test_webhook_rejects_shortcuts_url(self): - with self.assertRaises(ValueError): - PushNotificationAction( - title="Chat", - type=PushNotificationActionType.WEBHOOK, - url="shortcuts://run-shortcut?name=JARVIS", - ) - if __name__ == '__main__': unittest.main() diff --git a/activitysmith_openapi/test/test_stream_content_state.py b/activitysmith_openapi/test/test_stream_content_state.py index a44de74..be39ec3 100644 --- a/activitysmith_openapi/test/test_stream_content_state.py +++ b/activitysmith_openapi/test/test_stream_content_state.py @@ -42,6 +42,9 @@ def make_instance(self, include_optional) -> StreamContentState: percentage = 0, value = 1.337, upper_limit = 1.337, + duration_seconds = 1.337, + counts_down = True, + is_running = True, type = 'segmented_progress', color = 'lime', step_color = 'lime', diff --git a/pyproject.toml b/pyproject.toml index 6bdbad7..986b09a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "activitysmith" -version = "1.6.0" +version = "1.7.0" description = "Official ActivitySmith Python SDK" readme = "README.md" requires-python = ">=3.9" diff --git a/tests/test_resources.py b/tests/test_resources.py index 6d87606..9cf5a92 100644 --- a/tests/test_resources.py +++ b/tests/test_resources.py @@ -305,6 +305,62 @@ def test_live_activities_support_progress_payloads(monkeypatch): ] +def test_live_activities_support_timer_payloads(monkeypatch): + monkeypatch.setattr(client_module, "PushNotificationsApi", FakePushNotificationsApi) + monkeypatch.setattr(client_module, "LiveActivitiesApi", FakeLiveActivitiesApi) + monkeypatch.setattr(client_module, "MetricsApi", FakeMetricsApi) + + client = ActivitySmith(api_key="x") + + client.live_activities.start( + title="Benchmark Run", + subtitle="sampling performance", + type=client.live_activities.TYPE_TIMER, + duration_seconds=300, + counts_down=True, + color="cyan", + ) + client.live_activities.update( + activity_id="act-1", + title="Benchmark Run", + type=client.live_activities.TYPE_TIMER, + subtitle="complete", + color="cyan", + ) + + assert client.live_activities._api.calls == [ + ( + "start", + { + "live_activity_start_request": { + "content_state": { + "title": "Benchmark Run", + "subtitle": "sampling performance", + "type": "timer", + "duration_seconds": 300, + "counts_down": True, + "color": "cyan", + } + } + }, + ), + ( + "update", + { + "live_activity_update_request": { + "activity_id": "act-1", + "content_state": { + "title": "Benchmark Run", + "type": "timer", + "subtitle": "complete", + "color": "cyan", + }, + } + }, + ), + ] + + def test_live_activities_support_stats_payloads(monkeypatch): monkeypatch.setattr(client_module, "PushNotificationsApi", FakePushNotificationsApi) monkeypatch.setattr(client_module, "LiveActivitiesApi", FakeLiveActivitiesApi)