activitysmith 0.1.7 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (24) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +337 -77
  3. data/generated/activitysmith_openapi/api/live_activities_api.rb +168 -6
  4. data/generated/activitysmith_openapi/models/activity_metric.rb +293 -0
  5. data/generated/activitysmith_openapi/models/content_state_end.rb +47 -4
  6. data/generated/activitysmith_openapi/models/content_state_start.rb +50 -7
  7. data/generated/activitysmith_openapi/models/content_state_update.rb +50 -7
  8. data/generated/activitysmith_openapi/models/live_activity_action.rb +323 -0
  9. data/generated/activitysmith_openapi/models/live_activity_action_type.rb +40 -0
  10. data/generated/activitysmith_openapi/models/live_activity_end_request.rb +13 -4
  11. data/generated/activitysmith_openapi/models/live_activity_start_request.rb +10 -1
  12. data/generated/activitysmith_openapi/models/live_activity_stream_delete_request.rb +233 -0
  13. data/generated/activitysmith_openapi/models/live_activity_stream_delete_response.rb +332 -0
  14. data/generated/activitysmith_openapi/models/live_activity_stream_put_response.rb +361 -0
  15. data/generated/activitysmith_openapi/models/live_activity_stream_request.rb +280 -0
  16. data/generated/activitysmith_openapi/models/live_activity_update_request.rb +13 -4
  17. data/generated/activitysmith_openapi/models/live_activity_webhook_method.rb +40 -0
  18. data/generated/activitysmith_openapi/models/not_found_error.rb +237 -0
  19. data/generated/activitysmith_openapi/models/stream_content_state.rb +538 -0
  20. data/generated/activitysmith_openapi/version.rb +1 -1
  21. data/generated/activitysmith_openapi.rb +10 -0
  22. data/lib/activitysmith/live_activities.rb +19 -0
  23. data/lib/activitysmith/version.rb +1 -1
  24. metadata +12 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6be18d3495ded4e85d34cb9dfa10b9108f9dbd5e35ace8bd6303867fb6b31172
4
- data.tar.gz: 64b2d345bf824795d5b809d0ce5e9e40ee239d7f86878c20213704892f95db4e
3
+ metadata.gz: 9ca64934e2eee58c310acc66bcff641a6b8e8bd7223701702d1cf913a81f7ae0
4
+ data.tar.gz: 752924606d9ffb0d623e81a7c3ea1c159d8eeff827e15bfea86f9350c7d10537
5
5
  SHA512:
6
- metadata.gz: 72f3a210715d8e9e660142c12ba0b5ae1d99bcd87fd49196c1aa8a6f4732b6aa83fd4408b11afc5816ef3e214804dfded8ba7dd23eb1ded669f805e1067df442
7
- data.tar.gz: a022698cba1e043612fb3490fe3fc8805c20ef61dd8104137d74b3f8a0b36b9e378522ce76e5b4123a520a29ce2f1359f3fad6238758a701e7e672bca508ce8f
6
+ metadata.gz: 5dcf355adad083329d44b3b42fbd691e60996165ccb0af954027b08d2af27fe913f6bb45cb33a225581790589b1f2ff9d42a9cacff32fbf8b23159e5ed7cbfea
7
+ data.tar.gz: fbd8e68d0fcf453c4431780db2883ffd906e972e5e8b240e4dc68471da0f0919730b4ee61728045e958c624a3df15b81cdc7a79bd876bb7a1d029d141630cd37
data/README.md CHANGED
@@ -20,7 +20,7 @@ require "activitysmith"
20
20
  activitysmith = ActivitySmith::Client.new(api_key: ENV.fetch("ACTIVITYSMITH_API_KEY"))
21
21
  ```
22
22
 
23
- ## Usage
23
+ ## Push Notifications
24
24
 
25
25
  ### Send a Push Notification
26
26
 
@@ -29,40 +29,306 @@ activitysmith = ActivitySmith::Client.new(api_key: ENV.fetch("ACTIVITYSMITH_API_
29
29
  </p>
30
30
 
31
31
  ```ruby
32
- response = activitysmith.notifications.send(
32
+ activitysmith.notifications.send(
33
33
  {
34
34
  title: "New subscription 💸",
35
35
  message: "Customer upgraded to Pro plan"
36
36
  }
37
37
  )
38
+ ```
39
+
40
+ ### Rich Push Notifications with Media
41
+
42
+ <p align="center">
43
+ <img src="https://cdn.activitysmith.com/features/rich-push-notification-with-image.png" alt="Rich push notification with image" width="680" />
44
+ </p>
38
45
 
39
- puts response.success
40
- puts response.devices_notified
46
+ ```ruby
47
+ activitysmith.notifications.send(
48
+ {
49
+ title: "Homepage ready",
50
+ message: "Your agent finished the redesign.",
51
+ media: "https://cdn.example.com/output/homepage-v2.png",
52
+ redirection: "https://github.com/acme/web/pull/482"
53
+ }
54
+ )
55
+ ```
56
+
57
+ Send images, videos, or audio with your push notifications, press and hold to preview media directly from the notification, then tap through to open the linked content.
58
+
59
+ <p align="center">
60
+ <img src="https://cdn.activitysmith.com/features/rich-push-notification-with-audio.png" alt="Rich push notification with audio" width="680" />
61
+ </p>
62
+
63
+ What will work:
64
+
65
+ - direct image URL: `.jpg`, `.png`, `.gif`, etc.
66
+ - direct audio file URL: `.mp3`, `.m4a`, etc.
67
+ - direct video file URL: `.mp4`, `.mov`, etc.
68
+ - URL that responds with a proper media `Content-Type`, even if the path has no extension
69
+
70
+ ### Actionable Push Notifications
71
+
72
+ <p align="center">
73
+ <img src="https://cdn.activitysmith.com/features/actionable-push-notifications-2.png" alt="Actionable push notification example" width="680" />
74
+ </p>
75
+
76
+ Actionable push notifications can open a URL on tap or trigger actions when someone long-presses the notification.
77
+ Webhooks are executed by the ActivitySmith backend.
78
+
79
+ ```ruby
80
+ activitysmith.notifications.send(
81
+ {
82
+ title: "New subscription 💸",
83
+ message: "Customer upgraded to Pro plan",
84
+ redirection: "https://crm.example.com/customers/cus_9f3a1d", # Optional
85
+ actions: [ # Optional (max 4)
86
+ {
87
+ title: "Open CRM Profile",
88
+ type: "open_url",
89
+ url: "https://crm.example.com/customers/cus_9f3a1d"
90
+ },
91
+ {
92
+ title: "Start Onboarding Workflow",
93
+ type: "webhook",
94
+ url: "https://hooks.example.com/activitysmith/onboarding/start",
95
+ method: "POST",
96
+ body: {
97
+ customer_id: "cus_9f3a1d",
98
+ plan: "pro"
99
+ }
100
+ }
101
+ ]
102
+ }
103
+ )
41
104
  ```
42
105
 
43
106
  ## Live Activities
44
107
 
45
- Live Activities come in two UI types, but the lifecycle stays the same:
46
- start the activity, keep the returned `activity_id`, update it as state
47
- changes, then end it when the work is done.
108
+ <p align="center">
109
+ <img src="https://cdn.activitysmith.com/features/metrics-live-activity-action.png" alt="Live Activities example" width="680" />
110
+ </p>
111
+
112
+ ActivitySmith supports two ways to drive Live Activities:
113
+
114
+ - Recommended: stream updates with `activitysmith.live_activities.stream(...)`
115
+ - Advanced: manual lifecycle control with `start`, `update`, and `end`
116
+
117
+ Use stream updates when you want the easiest, stateless flow. You don't need to
118
+ store `activity_id` or manage lifecycle state yourself. Send the latest state
119
+ for a stable `stream_key` and ActivitySmith will start or update the Live
120
+ Activity for you. When the tracked process is over, call `end_stream(...)`.
121
+
122
+ Use the manual lifecycle methods when you need direct control over a specific
123
+ Live Activity instance.
124
+
125
+ Live Activity UI types:
126
+
127
+ - `metrics`: best for live operational stats like server CPU and memory, queue depth, or replica lag
128
+ - `segmented_progress`: best for step-based workflows like deployments, backups, and ETL pipelines
129
+ - `progress`: best for continuous jobs like uploads, reindexes, and long-running migrations tracked as a percentage
130
+
131
+ ### Recommended: Stream updates
132
+
133
+ Use a stable `stream_key` to identify the system or workflow you are tracking,
134
+ such as a server, deployment, build pipeline, cron job, or charging session.
135
+ This is especially useful for cron jobs and other scheduled tasks where you do
136
+ not want to store `activity_id` between runs.
137
+
138
+ #### Metrics
139
+
140
+ <p align="center">
141
+ <img src="https://cdn.activitysmith.com/features/metrics-live-activity-start.png" alt="Metrics stream example" width="680" />
142
+ </p>
143
+
144
+ ```ruby
145
+ status = activitysmith.live_activities.stream(
146
+ "prod-web-1",
147
+ {
148
+ content_state: {
149
+ title: "Server Health",
150
+ subtitle: "prod-web-1",
151
+ type: "metrics",
152
+ metrics: [
153
+ { label: "CPU", value: 9, unit: "%" },
154
+ { label: "MEM", value: 45, unit: "%" }
155
+ ]
156
+ }
157
+ }
158
+ )
159
+ ```
160
+
161
+ #### Segmented progress
162
+
163
+ <p align="center">
164
+ <img src="https://cdn.activitysmith.com/features/update-live-activity.png" alt="Segmented progress stream example" width="680" />
165
+ </p>
166
+
167
+ ```ruby
168
+ activitysmith.live_activities.stream(
169
+ "nightly-backup",
170
+ {
171
+ content_state: {
172
+ title: "Nightly Backup",
173
+ subtitle: "upload archive",
174
+ type: "segmented_progress",
175
+ number_of_steps: 3,
176
+ current_step: 2
177
+ }
178
+ }
179
+ )
180
+ ```
181
+
182
+ #### Progress
183
+
184
+ <p align="center">
185
+ <img src="https://cdn.activitysmith.com/features/progress-live-activity.png" alt="Progress stream example" width="680" />
186
+ </p>
187
+
188
+ ```ruby
189
+ activitysmith.live_activities.stream(
190
+ "search-reindex",
191
+ {
192
+ content_state: {
193
+ title: "Search Reindex",
194
+ subtitle: "catalog-v2",
195
+ type: "progress",
196
+ percentage: 42
197
+ }
198
+ }
199
+ )
200
+ ```
201
+
202
+ Call `stream(...)` again with the same `stream_key` whenever the state changes.
203
+
204
+ #### End a stream
205
+
206
+ Use this when the tracked process is finished and you no longer want the Live
207
+ Activity on devices. `content_state` is optional here; include it if you want
208
+ to end the stream with a final state.
209
+
210
+ ```ruby
211
+ activitysmith.live_activities.end_stream(
212
+ "prod-web-1",
213
+ {
214
+ content_state: {
215
+ title: "Server Health",
216
+ subtitle: "prod-web-1",
217
+ type: "metrics",
218
+ metrics: [
219
+ { label: "CPU", value: 7, unit: "%" },
220
+ { label: "MEM", value: 38, unit: "%" }
221
+ ]
222
+ }
223
+ }
224
+ )
225
+ ```
226
+
227
+ If you later send another `stream(...)` request with the same `stream_key`,
228
+ ActivitySmith starts a new Live Activity for that stream again.
229
+
230
+ Stream responses include an `operation` field:
48
231
 
49
- - `segmented_progress`: best for jobs tracked in steps
50
- - `progress`: best for jobs tracked as a percentage or numeric range
232
+ - `started`: ActivitySmith started a new Live Activity for this `stream_key`
233
+ - `updated`: ActivitySmith updated the current Live Activity
234
+ - `rotated`: ActivitySmith ended the previous Live Activity and started a new one
235
+ - `noop`: the incoming state matched the current state, so no update was sent
236
+ - `paused`: the stream is paused, so no Live Activity was started or updated
237
+ - `ended`: returned by `end_stream(...)` after the stream is ended
51
238
 
52
- ### Shared flow
239
+ ### Advanced: Manual lifecycle control
240
+
241
+ Use these methods when you want to manage the Live Activity lifecycle yourself.
242
+
243
+ #### Shared flow
53
244
 
54
245
  1. Call `activitysmith.live_activities.start(...)`.
55
246
  2. Save the returned `activity_id`.
56
247
  3. Call `activitysmith.live_activities.update(...)` as progress changes.
57
248
  4. Call `activitysmith.live_activities.end(...)` when the work is finished.
58
249
 
250
+ ### Metrics Type
251
+
252
+ Use `metrics` when you want to keep a small set of live stats visible, such as
253
+ server health, queue pressure, or database load.
254
+
255
+ #### Start
256
+
257
+ <p align="center">
258
+ <img src="https://cdn.activitysmith.com/features/metrics-live-activity-start.png" alt="Metrics start example" width="680" />
259
+ </p>
260
+
261
+ ```ruby
262
+ start = activitysmith.live_activities.start(
263
+ {
264
+ content_state: {
265
+ title: "Server Health",
266
+ subtitle: "prod-web-1",
267
+ type: "metrics",
268
+ metrics: [
269
+ { label: "CPU", value: 9, unit: "%" },
270
+ { label: "MEM", value: 45, unit: "%" }
271
+ ]
272
+ }
273
+ }
274
+ )
275
+
276
+ activity_id = start.activity_id
277
+ ```
278
+
279
+ #### Update
280
+
281
+ <p align="center">
282
+ <img src="https://cdn.activitysmith.com/features/metrics-live-activity-update.png" alt="Metrics update example" width="680" />
283
+ </p>
284
+
285
+ ```ruby
286
+ activitysmith.live_activities.update(
287
+ {
288
+ activity_id: activity_id,
289
+ content_state: {
290
+ title: "Server Health",
291
+ subtitle: "prod-web-1",
292
+ type: "metrics",
293
+ metrics: [
294
+ { label: "CPU", value: 76, unit: "%" },
295
+ { label: "MEM", value: 52, unit: "%" }
296
+ ]
297
+ }
298
+ }
299
+ )
300
+ ```
301
+
302
+ #### End
303
+
304
+ <p align="center">
305
+ <img src="https://cdn.activitysmith.com/features/metrics-live-activity-end.png" alt="Metrics end example" width="680" />
306
+ </p>
307
+
308
+ ```ruby
309
+ activitysmith.live_activities.end(
310
+ {
311
+ activity_id: activity_id,
312
+ content_state: {
313
+ title: "Server Health",
314
+ subtitle: "prod-web-1",
315
+ type: "metrics",
316
+ metrics: [
317
+ { label: "CPU", value: 7, unit: "%" },
318
+ { label: "MEM", value: 38, unit: "%" }
319
+ ],
320
+ auto_dismiss_minutes: 2
321
+ }
322
+ }
323
+ )
324
+ ```
325
+
59
326
  ### Segmented Progress Type
60
327
 
61
328
  Use `segmented_progress` when progress is easier to follow as steps instead of a
62
329
  raw percentage. It fits jobs like backups, deployments, ETL pipelines, and
63
- checklists where "step 2 of 3" is more useful than "67%".
64
- `number_of_steps` is dynamic, so you can increase or decrease it later if the
65
- workflow changes.
330
+ checklists where "step 2 of 3" is more useful than "67%". `number_of_steps` is
331
+ dynamic, so you can increase or decrease it later if the workflow changes.
66
332
 
67
333
  #### Start
68
334
 
@@ -80,8 +346,7 @@ start = activitysmith.live_activities.start(
80
346
  current_step: 1,
81
347
  type: "segmented_progress",
82
348
  color: "yellow"
83
- },
84
- channels: ["devs", "ops"] # Optional
349
+ }
85
350
  }
86
351
  )
87
352
 
@@ -95,19 +360,17 @@ activity_id = start.activity_id
95
360
  </p>
96
361
 
97
362
  ```ruby
98
- update = activitysmith.live_activities.update(
363
+ activitysmith.live_activities.update(
99
364
  {
100
365
  activity_id: activity_id,
101
366
  content_state: {
102
367
  title: "Nightly database backup",
103
368
  subtitle: "upload archive",
104
- number_of_steps: 4,
369
+ number_of_steps: 3,
105
370
  current_step: 2
106
371
  }
107
372
  }
108
373
  )
109
-
110
- puts update.devices_notified
111
374
  ```
112
375
 
113
376
  #### End
@@ -117,20 +380,18 @@ puts update.devices_notified
117
380
  </p>
118
381
 
119
382
  ```ruby
120
- finish = activitysmith.live_activities.end(
383
+ activitysmith.live_activities.end(
121
384
  {
122
385
  activity_id: activity_id,
123
386
  content_state: {
124
387
  title: "Nightly database backup",
125
388
  subtitle: "verify restore",
126
- number_of_steps: 4,
127
- current_step: 4,
389
+ number_of_steps: 3,
390
+ current_step: 3,
128
391
  auto_dismiss_minutes: 2
129
392
  }
130
393
  }
131
394
  )
132
-
133
- puts finish.success
134
395
  ```
135
396
 
136
397
  ### Progress Type
@@ -152,8 +413,7 @@ start = activitysmith.live_activities.start(
152
413
  title: "EV Charging",
153
414
  subtitle: "Added 30 mi range",
154
415
  type: "progress",
155
- percentage: 15,
156
- color: "lime"
416
+ percentage: 15
157
417
  }
158
418
  }
159
419
  )
@@ -200,78 +460,78 @@ activitysmith.live_activities.end(
200
460
  )
201
461
  ```
202
462
 
203
- ## Channels
463
+ ### Live Activity Action
204
464
 
205
- Channels are used to target specific team members or devices. Can be used for both push notifications and live activities.
465
+ Just like Actionable Push Notifications, Live Activities can have a button that opens a URL in a browser or triggers a webhook. Webhooks are executed by the ActivitySmith backend.
466
+
467
+ <p align="center">
468
+ <img src="https://cdn.activitysmith.com/features/metrics-live-activity-action.png" alt="Metrics Live Activity with action" width="680" />
469
+ </p>
470
+
471
+ #### Open URL action
206
472
 
207
473
  ```ruby
208
- response = activitysmith.notifications.send(
474
+ start = activitysmith.live_activities.start(
209
475
  {
210
- title: "New subscription 💸",
211
- message: "Customer upgraded to Pro plan",
212
- channels: ["sales", "customer-success"] # Optional
476
+ content_state: {
477
+ title: "Server Health",
478
+ subtitle: "prod-web-1",
479
+ type: "metrics",
480
+ metrics: [
481
+ { label: "CPU", value: 76, unit: "%" },
482
+ { label: "MEM", value: 52, unit: "%" }
483
+ ]
484
+ },
485
+ action: {
486
+ title: "Open Dashboard",
487
+ type: "open_url",
488
+ url: "https://ops.example.com/servers/prod-web-1"
489
+ }
213
490
  }
214
491
  )
492
+
493
+ activity_id = start.activity_id
215
494
  ```
216
495
 
217
- ## Rich Push Notifications with Media
218
-
219
- <p align="center">
220
- <img src="https://cdn.activitysmith.com/features/rich-push-notification-with-image.png" alt="Rich push notification with image" width="680" />
221
- </p>
496
+ #### Webhook action
222
497
 
223
498
  ```ruby
224
- response = activitysmith.notifications.send(
499
+ activitysmith.live_activities.update(
225
500
  {
226
- title: "Homepage ready",
227
- message: "Your agent finished the redesign.",
228
- media: "https://cdn.example.com/output/homepage-v2.png",
229
- redirection: "https://github.com/acme/web/pull/482"
501
+ activity_id: activity_id,
502
+ content_state: {
503
+ title: "Server Health",
504
+ subtitle: "prod-web-1",
505
+ type: "metrics",
506
+ metrics: [
507
+ { label: "CPU", value: 91, unit: "%" },
508
+ { label: "MEM", value: 57, unit: "%" }
509
+ ]
510
+ },
511
+ action: {
512
+ title: "Restart Service",
513
+ type: "webhook",
514
+ url: "https://ops.example.com/hooks/servers/prod-web-1/restart",
515
+ method: "POST",
516
+ body: {
517
+ server_id: "prod-web-1",
518
+ requested_by: "activitysmith-ruby"
519
+ }
520
+ }
230
521
  }
231
522
  )
232
523
  ```
233
524
 
234
- Send images, videos, or audio with your push notifications, press and hold to preview media directly from the notification, then tap through to open the linked content.
235
-
236
- <p align="center">
237
- <img src="https://cdn.activitysmith.com/features/rich-push-notification-with-audio.png" alt="Rich push notification with audio" width="680" />
238
- </p>
239
-
240
- What will work:
241
-
242
- - direct image URL: `.jpg`, `.png`, `.gif`, etc.
243
- - direct audio file URL: `.mp3`, `.m4a`, etc.
244
- - direct video file URL: `.mp4`, `.mov`, etc.
245
- - URL that responds with a proper media `Content-Type`, even if the path has no extension
246
-
247
- ## Push Notification Redirection and Actions
525
+ ## Channels
248
526
 
249
- Push notification redirection and actions are optional and can be used to redirect the user to a specific URL when they tap the notification or to trigger a specific action when they long-press the notification.
250
- Webhooks are executed by ActivitySmith backend.
527
+ Channels are used to target specific team members or devices. Can be used for both push notifications and live activities.
251
528
 
252
529
  ```ruby
253
- response = activitysmith.notifications.send(
530
+ activitysmith.notifications.send(
254
531
  {
255
532
  title: "New subscription 💸",
256
533
  message: "Customer upgraded to Pro plan",
257
- redirection: "https://crm.example.com/customers/cus_9f3a1d", # Optional
258
- actions: [ # Optional (max 4)
259
- {
260
- title: "Open CRM Profile",
261
- type: "open_url",
262
- url: "https://crm.example.com/customers/cus_9f3a1d"
263
- },
264
- {
265
- title: "Start Onboarding Workflow",
266
- type: "webhook",
267
- url: "https://hooks.example.com/activitysmith/onboarding/start",
268
- method: "POST",
269
- body: {
270
- customer_id: "cus_9f3a1d",
271
- plan: "pro"
272
- }
273
- }
274
- ]
534
+ channels: ["sales", "customer-success"] # Optional
275
535
  }
276
536
  )
277
537
  ```