From f96cf3fefdfc76660790306a40c2c83f0f7a2d73 Mon Sep 17 00:00:00 2001 From: activitysmith-bot Date: Mon, 8 Jun 2026 07:44:17 +0000 Subject: [PATCH 1/4] chore: regenerate SDK --- generated/apis/LiveActivitiesApi.ts | 16 ++-- generated/models/index.ts | 114 +++++++++++++++++++++++----- 2 files changed, 103 insertions(+), 27 deletions(-) diff --git a/generated/apis/LiveActivitiesApi.ts b/generated/apis/LiveActivitiesApi.ts index fd5f904..a0ce9ff 100644 --- a/generated/apis/LiveActivitiesApi.ts +++ b/generated/apis/LiveActivitiesApi.ts @@ -61,7 +61,7 @@ export interface UpdateLiveActivityRequest { export class LiveActivitiesApi extends runtime.BaseAPI { /** - * 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. * End a Live Activity (legacy manual lifecycle) */ async endLiveActivityRaw(requestParameters: EndLiveActivityRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise> { @@ -98,7 +98,7 @@ export class LiveActivitiesApi extends runtime.BaseAPI { } /** - * 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. * End a Live Activity (legacy manual lifecycle) */ async endLiveActivity(requestParameters: EndLiveActivityRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise { @@ -153,7 +153,7 @@ export class LiveActivitiesApi extends runtime.BaseAPI { } /** - * 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. * Start a new Live Activity or update an existing one */ async reconcileLiveActivityStreamRaw(requestParameters: ReconcileLiveActivityStreamRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise> { @@ -197,7 +197,7 @@ export class LiveActivitiesApi extends runtime.BaseAPI { } /** - * 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. * Start a new Live Activity or update an existing one */ async reconcileLiveActivityStream(requestParameters: ReconcileLiveActivityStreamRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise { @@ -206,7 +206,7 @@ export class LiveActivitiesApi extends runtime.BaseAPI { } /** - * 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. * Start a Live Activity (legacy manual lifecycle) */ async startLiveActivityRaw(requestParameters: StartLiveActivityRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise> { @@ -243,7 +243,7 @@ export class LiveActivitiesApi extends runtime.BaseAPI { } /** - * 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. * Start a Live Activity (legacy manual lifecycle) */ async startLiveActivity(requestParameters: StartLiveActivityRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise { @@ -252,7 +252,7 @@ export class LiveActivitiesApi extends runtime.BaseAPI { } /** - * 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. * Update a Live Activity (legacy manual lifecycle) */ async updateLiveActivityRaw(requestParameters: UpdateLiveActivityRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise> { @@ -289,7 +289,7 @@ export class LiveActivitiesApi extends runtime.BaseAPI { } /** - * 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. * Update a Live Activity (legacy manual lifecycle) */ async updateLiveActivity(requestParameters: UpdateLiveActivityRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise { diff --git a/generated/models/index.ts b/generated/models/index.ts index 82f378b..e65b022 100644 --- a/generated/models/index.ts +++ b/generated/models/index.ts @@ -112,7 +112,7 @@ export interface ChannelTarget { channels: Array; } /** - * 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. * @export * @interface ContentStateEnd */ @@ -160,6 +160,24 @@ export interface ContentStateEnd { * @memberof ContentStateEnd */ upper_limit?: number; + /** + * Timer duration in seconds. For type=timer, omit duration_seconds on end to preserve and freeze the latest timer state. + * @type {number} + * @memberof ContentStateEnd + */ + duration_seconds?: number; + /** + * 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. + * @type {boolean} + * @memberof ContentStateEnd + */ + counts_down?: boolean; + /** + * Use with type=timer. Defaults to true. Set false to pause/freeze via API; set true on a paused timer to resume. + * @type {boolean} + * @memberof ContentStateEnd + */ + is_running?: boolean; /** * Use for type=metrics or type=stats. * @type {Array} @@ -173,7 +191,7 @@ export interface ContentStateEnd { */ message?: string; /** - * Optional SF Symbol icon. Supported by alert, progress, segmented_progress, metrics, and stats. + * Optional SF Symbol icon. Supported by alert, progress, segmented_progress, metrics, stats, and timer. * @type {LiveActivityAlertIcon} * @memberof ContentStateEnd */ @@ -191,7 +209,7 @@ export interface ContentStateEnd { */ type?: ContentStateEndTypeEnum; /** - * 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. Accent color for progress, segmented_progress, metrics, and timer Live Activities. For Alert Live Activities, this tints the action button when action is included. * @type {string} * @memberof ContentStateEnd */ @@ -225,7 +243,8 @@ export const ContentStateEndTypeEnum = { Progress: 'progress', Metrics: 'metrics', Stats: 'stats', - Alert: 'alert' + Alert: 'alert', + Timer: 'timer' } as const; export type ContentStateEndTypeEnum = typeof ContentStateEndTypeEnum[keyof typeof ContentStateEndTypeEnum]; @@ -281,7 +300,7 @@ export const ContentStateEndStepColorsEnum = { export type ContentStateEndStepColorsEnum = typeof ContentStateEndStepColorsEnum[keyof typeof ContentStateEndStepColorsEnum]; /** - * 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. * @export * @interface ContentStateStart */ @@ -329,6 +348,24 @@ export interface ContentStateStart { * @memberof ContentStateStart */ upper_limit?: number; + /** + * Timer duration in seconds. For type=timer countdowns, required on start when counts_down is true or omitted. + * @type {number} + * @memberof ContentStateStart + */ + duration_seconds?: number; + /** + * 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. + * @type {boolean} + * @memberof ContentStateStart + */ + counts_down?: boolean; + /** + * Use with type=timer. Defaults to true. Set false to pause/freeze via API; set true on a paused timer to resume. + * @type {boolean} + * @memberof ContentStateStart + */ + is_running?: boolean; /** * Use for type=metrics or type=stats. * @type {Array} @@ -342,7 +379,7 @@ export interface ContentStateStart { */ message?: string; /** - * Optional SF Symbol icon. Supported by alert, progress, segmented_progress, metrics, and stats. + * Optional SF Symbol icon. Supported by alert, progress, segmented_progress, metrics, stats, and timer. * @type {LiveActivityAlertIcon} * @memberof ContentStateStart */ @@ -360,7 +397,7 @@ export interface ContentStateStart { */ type: ContentStateStartTypeEnum; /** - * 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. Accent color for progress, segmented_progress, metrics, and timer Live Activities. For Alert Live Activities, this tints the action button when action is included. * @type {string} * @memberof ContentStateStart */ @@ -388,7 +425,8 @@ export const ContentStateStartTypeEnum = { Progress: 'progress', Metrics: 'metrics', Stats: 'stats', - Alert: 'alert' + Alert: 'alert', + Timer: 'timer' } as const; export type ContentStateStartTypeEnum = typeof ContentStateStartTypeEnum[keyof typeof ContentStateStartTypeEnum]; @@ -444,7 +482,7 @@ export const ContentStateStartStepColorsEnum = { export type ContentStateStartStepColorsEnum = typeof ContentStateStartStepColorsEnum[keyof typeof ContentStateStartStepColorsEnum]; /** - * 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. * @export * @interface ContentStateUpdate */ @@ -492,6 +530,24 @@ export interface ContentStateUpdate { * @memberof ContentStateUpdate */ upper_limit?: number; + /** + * 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. + * @type {number} + * @memberof ContentStateUpdate + */ + duration_seconds?: number; + /** + * 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. + * @type {boolean} + * @memberof ContentStateUpdate + */ + counts_down?: boolean; + /** + * Use with type=timer. Defaults to true. Set false to pause/freeze via API; set true on a paused timer to resume. + * @type {boolean} + * @memberof ContentStateUpdate + */ + is_running?: boolean; /** * Use for type=metrics or type=stats. * @type {Array} @@ -505,7 +561,7 @@ export interface ContentStateUpdate { */ message?: string; /** - * Optional SF Symbol icon. Supported by alert, progress, segmented_progress, metrics, and stats. + * Optional SF Symbol icon. Supported by alert, progress, segmented_progress, metrics, stats, and timer. * @type {LiveActivityAlertIcon} * @memberof ContentStateUpdate */ @@ -523,7 +579,7 @@ export interface ContentStateUpdate { */ type?: ContentStateUpdateTypeEnum; /** - * 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. Accent color for progress, segmented_progress, metrics, and timer Live Activities. For Alert Live Activities, this tints the action button when action is included. * @type {string} * @memberof ContentStateUpdate */ @@ -551,7 +607,8 @@ export const ContentStateUpdateTypeEnum = { Progress: 'progress', Metrics: 'metrics', Stats: 'stats', - Alert: 'alert' + Alert: 'alert', + Timer: 'timer' } as const; export type ContentStateUpdateTypeEnum = typeof ContentStateUpdateTypeEnum[keyof typeof ContentStateUpdateTypeEnum]; @@ -646,7 +703,7 @@ export interface LiveActivityAction { */ type: LiveActivityActionType; /** - * 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. + * 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. * @type {string} * @memberof LiveActivityAction */ @@ -1313,7 +1370,7 @@ export interface PushNotificationAction { */ type: PushNotificationActionType; /** - * 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. + * 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. * @type {string} * @memberof PushNotificationAction */ @@ -1374,7 +1431,7 @@ export interface PushNotificationRequest { */ media?: string; /** - * 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 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. * @type {string} * @memberof PushNotificationRequest */ @@ -1486,7 +1543,7 @@ export interface RateLimitError { */ export type SendPushNotification429Response = LiveActivityLimitError | RateLimitError; /** - * 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. * @export * @interface StreamContentState */ @@ -1534,6 +1591,24 @@ export interface StreamContentState { * @memberof StreamContentState */ upper_limit?: number; + /** + * 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. + * @type {number} + * @memberof StreamContentState + */ + duration_seconds?: number; + /** + * 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. + * @type {boolean} + * @memberof StreamContentState + */ + counts_down?: boolean; + /** + * Use with type=timer. Defaults to true. Set false to pause/freeze via API; set true on a paused timer to resume. + * @type {boolean} + * @memberof StreamContentState + */ + is_running?: boolean; /** * Required on the first PUT or whenever the stream cannot infer the current activity type. * @type {string} @@ -1541,7 +1616,7 @@ export interface StreamContentState { */ type?: StreamContentStateTypeEnum; /** - * 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. Accent color for progress, segmented_progress, metrics, and timer Live Activities. For Alert Live Activities, this tints the action button when action is included. * @type {string} * @memberof StreamContentState */ @@ -1571,7 +1646,7 @@ export interface StreamContentState { */ message?: string; /** - * Optional SF Symbol icon. Supported by alert, progress, segmented_progress, metrics, and stats. + * Optional SF Symbol icon. Supported by alert, progress, segmented_progress, metrics, stats, and timer. * @type {LiveActivityAlertIcon} * @memberof StreamContentState */ @@ -1605,7 +1680,8 @@ export const StreamContentStateTypeEnum = { Progress: 'progress', Metrics: 'metrics', Stats: 'stats', - Alert: 'alert' + Alert: 'alert', + Timer: 'timer' } as const; export type StreamContentStateTypeEnum = typeof StreamContentStateTypeEnum[keyof typeof StreamContentStateTypeEnum]; From 8451958e5d1758b5f7d7da5197734a2b96a9f509 Mon Sep 17 00:00:00 2001 From: bardonadam Date: Mon, 8 Jun 2026 19:22:09 +0700 Subject: [PATCH 2/4] feat: add timer live activity DX wrappers --- README.md | 23 +++++++++++++++++++++-- src/ActivitySmith.ts | 3 +++ tests/resources.test.js | 33 +++++++++++++++++++++++++++++++++ 3 files changed, 57 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index c1020a9..949cf0a 100644 --- a/README.md +++ b/README.md @@ -133,10 +133,11 @@ await 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 +- `timer`: best for countdowns and elapsed timers, like benchmark runs, cooking timers, workouts, soak windows, and long-running jobs - `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 @@ -224,6 +225,24 @@ await activitysmith.liveActivities.stream("search-reindex", { }); ``` +#### Timer + +Use `duration_seconds` for a countdown. Omit `counts_down` for the default countdown behavior, or set `counts_down: false` for an elapsed timer. + +```ts +await activitysmith.liveActivities.stream("benchmark-run", { + content_state: { + title: "Benchmark Run", + subtitle: "sampling performance", + type: "timer", + duration_seconds: 300, + color: "cyan", + }, +}); +``` + +Later updates can change the title, subtitle, color, icon, or action without resetting the timer. Include `duration_seconds` again only when you want to restart the timer window from that update. + #### Alert

@@ -343,7 +362,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/src/ActivitySmith.ts b/src/ActivitySmith.ts index 528e2c5..397ddaa 100644 --- a/src/ActivitySmith.ts +++ b/src/ActivitySmith.ts @@ -35,6 +35,7 @@ const LiveActivityTypes = { metrics: "metrics", stats: "stats", alert: "alert", + timer: "timer", } as const; export type LiveActivityType = (typeof LiveActivityTypes)[keyof typeof LiveActivityTypes]; @@ -57,6 +58,8 @@ export type LiveActivityContentState = Record & { icon?: LiveActivityAlertIcon; badge?: LiveActivityAlertBadge; color?: string; + duration_seconds?: number; + counts_down?: boolean; }; type LiveActivityAlertIconOptions = { diff --git a/tests/resources.test.js b/tests/resources.test.js index 575418f..3de51a6 100644 --- a/tests/resources.test.js +++ b/tests/resources.test.js @@ -272,6 +272,39 @@ describe("resource wrappers", () => { expect(startSpy).toHaveBeenCalledWith({ liveActivityStartRequest: payload }, undefined); }); + it("passes through timer content_state fields", async () => { + const ActivitySmith = require("../dist/src/index.js"); + const generated = require("../dist/generated/index.js"); + + const startSpy = vi + .spyOn(generated.LiveActivitiesApi.prototype, "startLiveActivity") + .mockResolvedValue({ activity_id: "act-1" }); + + const client = new ActivitySmith({ apiKey: "test" }); + const payload = { + content_state: ActivitySmith.contentState({ + title: "Benchmark Run", + subtitle: "sampling performance", + type: ActivitySmith.liveActivityTypes.timer, + duration_seconds: 300, + counts_down: true, + color: "cyan", + }), + }; + + await client.liveActivities.start(payload); + + expect(payload.content_state).toEqual({ + title: "Benchmark Run", + subtitle: "sampling performance", + type: "timer", + duration_seconds: 300, + counts_down: true, + color: "cyan", + }); + expect(startSpy).toHaveBeenCalledWith({ liveActivityStartRequest: payload }, undefined); + }); + it("passes through stats content_state with metric accent colors", async () => { const ActivitySmith = require("../dist/src/index.js"); const generated = require("../dist/generated/index.js"); From defabfbaa37d9604f2ae4a2417e7de9bd29cd032 Mon Sep 17 00:00:00 2001 From: bardonadam Date: Mon, 8 Jun 2026 19:46:44 +0700 Subject: [PATCH 3/4] docs: sync timer live activity readme --- README.md | 42 +++++++++++++++++++++++------------------- 1 file changed, 23 insertions(+), 19 deletions(-) diff --git a/README.md b/README.md index 949cf0a..598c82e 100644 --- a/README.md +++ b/README.md @@ -137,10 +137,10 @@ 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 -- `timer`: best for countdowns and elapsed timers, like benchmark runs, cooking timers, workouts, soak windows, and long-running jobs - `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 @@ -225,24 +225,6 @@ await activitysmith.liveActivities.stream("search-reindex", { }); ``` -#### Timer - -Use `duration_seconds` for a countdown. Omit `counts_down` for the default countdown behavior, or set `counts_down: false` for an elapsed timer. - -```ts -await activitysmith.liveActivities.stream("benchmark-run", { - content_state: { - title: "Benchmark Run", - subtitle: "sampling performance", - type: "timer", - duration_seconds: 300, - color: "cyan", - }, -}); -``` - -Later updates can change the title, subtitle, color, icon, or action without resetting the timer. Include `duration_seconds` again only when you want to restart the timer window from that update. - #### Alert

@@ -261,6 +243,28 @@ await activitysmith.liveActivities.stream("customer-ops", { }); ``` +#### Timer + +

+ Timer Live Activity showing a benchmark run countdown +

+ +```ts +await activitysmith.liveActivities.stream("benchmark-run", { + 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 `endStream(...)` with the same `streamKey` 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. From d95eb1c49d05d55f635f6298b4a07a30eb364f02 Mon Sep 17 00:00:00 2001 From: bardonadam Date: Mon, 8 Jun 2026 19:54:22 +0700 Subject: [PATCH 4/4] chore: bump version to 1.7.0 --- package-lock.json | 4 ++-- package.json | 2 +- src/ActivitySmith.ts | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package-lock.json b/package-lock.json index a18c552..fff5f06 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "activitysmith", - "version": "1.6.0", + "version": "1.7.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "activitysmith", - "version": "1.6.0", + "version": "1.7.0", "license": "MIT", "devDependencies": { "typescript": "^5.3.3", diff --git a/package.json b/package.json index bbcdc98..4eafe5d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "activitysmith", - "version": "1.6.0", + "version": "1.7.0", "description": "Official ActivitySmith Node.js SDK", "keywords": [ "activitysmith", diff --git a/src/ActivitySmith.ts b/src/ActivitySmith.ts index 397ddaa..58cbd37 100644 --- a/src/ActivitySmith.ts +++ b/src/ActivitySmith.ts @@ -1,6 +1,6 @@ import { Configuration, PushNotificationsApi, LiveActivitiesApi, MetricsApi } from "../generated/index"; -const SDK_VERSION = "1.6.0"; +const SDK_VERSION = "1.7.0"; const SDK_HEADER_NAME = "X-ActivitySmith-SDK"; const SDK_HEADER_VALUE = `node-v${SDK_VERSION}`;