activitysmith-cli
Advanced tools
+2
-2
| { | ||
| "name": "activitysmith-cli", | ||
| "version": "1.7.0", | ||
| "version": "1.8.0", | ||
| "description": "Command-line interface for ActivitySmith. Send push notifications and manage Live Activities from your terminal.", | ||
@@ -43,5 +43,5 @@ "keywords": [ | ||
| "dependencies": { | ||
| "activitysmith": "^1.7.0", | ||
| "activitysmith": "^1.8.0", | ||
| "commander": "^12.1.0" | ||
| } | ||
| } |
+44
-2
@@ -342,3 +342,3 @@ # ActivitySmith CLI | ||
| Live Activities can include one optional action button. | ||
| Live Activities can include an action button. | ||
@@ -351,3 +351,3 @@ - `open_url`: open an HTTPS URL. | ||
| <img | ||
| src="https://cdn.activitysmith.com/features/live-activity-with-action.png?v=20260319-1" | ||
| src="https://cdn.activitysmith.com/features/metrics-live-activity-action.png" | ||
| alt="Live Activity with action button" | ||
@@ -419,2 +419,42 @@ width="680" | ||
| #### Secondary action | ||
| <p align="center"> | ||
| <img | ||
| src="https://cdn.activitysmith.com/features/live-activity-secondary-action.png" | ||
| alt="Alert Live Activity with primary and secondary action buttons" | ||
| width="680" | ||
| /> | ||
| </p> | ||
| Use `--secondary-action` when you want a second button beside the primary `--action`. | ||
| The secondary action button is supported for `alert`, `progress`, and `segmented_progress` Live Activities. Both buttons use the same `open_url`, `webhook`, and Apple Shortcut payload shapes. | ||
| ```bash | ||
| activitysmith activity stream agent-approval \ | ||
| --content-state '{ | ||
| "title": "Approval Needed", | ||
| "message": "Should I send the follow-up email to Brightlane?", | ||
| "type": "alert", | ||
| "color": "green", | ||
| "icon": { "symbol": "sparkles", "color": "green" }, | ||
| "badge": { "title": "Agent", "color": "green" } | ||
| }' \ | ||
| --action '{ | ||
| "title": "Send", | ||
| "type": "webhook", | ||
| "url": "https://hooks.example.com/agent/approval", | ||
| "method": "POST", | ||
| "body": { "decision": "send" } | ||
| }' \ | ||
| --secondary-action '{ | ||
| "title": "Deny", | ||
| "type": "webhook", | ||
| "url": "https://hooks.example.com/agent/approval", | ||
| "method": "POST", | ||
| "body": { "decision": "deny" } | ||
| }' | ||
| ``` | ||
| ### Icons and Badges | ||
@@ -561,2 +601,4 @@ | ||
| - `--action-file <path>` | ||
| - `--secondary-action <json>` | ||
| - `--secondary-action-file <path>` | ||
@@ -563,0 +605,0 @@ Targeting options: |
+109
-12
@@ -213,3 +213,11 @@ #!/usr/bin/env node | ||
| .option("--action <json>", "Live Activity action as JSON object") | ||
| .option("--action-file <path>", "Live Activity action JSON file path"); | ||
| .option("--action-file <path>", "Live Activity action JSON file path") | ||
| .option( | ||
| "--secondary-action <json>", | ||
| "Secondary Live Activity action as JSON object" | ||
| ) | ||
| .option( | ||
| "--secondary-action-file <path>", | ||
| "Secondary Live Activity action JSON file path" | ||
| ); | ||
@@ -699,2 +707,28 @@ const getApiKey = (options) => | ||
| const loadLiveActivitySecondaryAction = async (options) => { | ||
| if (options.secondaryAction && options.secondaryActionFile) { | ||
| throw new Error( | ||
| "Provide either --secondary-action or --secondary-action-file, not both." | ||
| ); | ||
| } | ||
| let action; | ||
| if (options.secondaryActionFile) { | ||
| action = await readJsonFile( | ||
| options.secondaryActionFile, | ||
| "secondary-action-file" | ||
| ); | ||
| } | ||
| if (options.secondaryAction) { | ||
| action = parseJsonString(options.secondaryAction, "secondary-action"); | ||
| } | ||
| if (action === undefined) { | ||
| return undefined; | ||
| } | ||
| return parseAction(action, "secondary_action"); | ||
| }; | ||
| const validatePushMediaOptions = ({ media, actions }) => { | ||
@@ -833,3 +867,7 @@ if (media === undefined || actions === undefined) { | ||
| const toApiLiveActivityStartRequest = (contentState, action) => { | ||
| const toApiLiveActivityStartRequest = ( | ||
| contentState, | ||
| action, | ||
| secondaryAction | ||
| ) => { | ||
| const request = { | ||
@@ -843,2 +881,6 @@ content_state: toApiContentState(contentState), | ||
| if (secondaryAction !== undefined) { | ||
| request.secondary_action = secondaryAction; | ||
| } | ||
| return request; | ||
@@ -860,3 +902,8 @@ }; | ||
| const toApiLiveActivityUpdateRequest = (activityId, contentState, action) => { | ||
| const toApiLiveActivityUpdateRequest = ( | ||
| activityId, | ||
| contentState, | ||
| action, | ||
| secondaryAction | ||
| ) => { | ||
| const request = { | ||
@@ -871,6 +918,15 @@ activity_id: activityId, | ||
| if (secondaryAction !== undefined) { | ||
| request.secondary_action = secondaryAction; | ||
| } | ||
| return request; | ||
| }; | ||
| const toApiLiveActivityEndRequest = (activityId, contentState, action) => { | ||
| const toApiLiveActivityEndRequest = ( | ||
| activityId, | ||
| contentState, | ||
| action, | ||
| secondaryAction | ||
| ) => { | ||
| const request = { | ||
@@ -885,6 +941,14 @@ activity_id: activityId, | ||
| if (secondaryAction !== undefined) { | ||
| request.secondary_action = secondaryAction; | ||
| } | ||
| return request; | ||
| }; | ||
| const toApiLiveActivityStreamRequest = (contentState, action) => { | ||
| const toApiLiveActivityStreamRequest = ( | ||
| contentState, | ||
| action, | ||
| secondaryAction | ||
| ) => { | ||
| const request = { | ||
@@ -898,6 +962,14 @@ content_state: toApiContentState(contentState), | ||
| if (secondaryAction !== undefined) { | ||
| request.secondary_action = secondaryAction; | ||
| } | ||
| return request; | ||
| }; | ||
| const toApiLiveActivityStreamDeleteRequest = (contentState, action) => { | ||
| const toApiLiveActivityStreamDeleteRequest = ( | ||
| contentState, | ||
| action, | ||
| secondaryAction | ||
| ) => { | ||
| const request = {}; | ||
@@ -913,2 +985,6 @@ | ||
| if (secondaryAction !== undefined) { | ||
| request.secondary_action = secondaryAction; | ||
| } | ||
| return request; | ||
@@ -1216,2 +1292,3 @@ }; | ||
| const action = await loadLiveActivityAction(options); | ||
| const secondaryAction = await loadLiveActivitySecondaryAction(options); | ||
@@ -1221,3 +1298,7 @@ const response = await client.liveActivities.stream( | ||
| withTargetChannels( | ||
| toApiLiveActivityStreamRequest(contentState, action), | ||
| toApiLiveActivityStreamRequest( | ||
| contentState, | ||
| action, | ||
| secondaryAction | ||
| ), | ||
| options.channels | ||
@@ -1258,6 +1339,11 @@ ) | ||
| const action = await loadLiveActivityAction(options); | ||
| const secondaryAction = await loadLiveActivitySecondaryAction(options); | ||
| const response = await client.liveActivities.startLiveActivity({ | ||
| liveActivityStartRequest: withTargetChannels( | ||
| toApiLiveActivityStartRequest(contentState, action), | ||
| toApiLiveActivityStartRequest( | ||
| contentState, | ||
| action, | ||
| secondaryAction | ||
| ), | ||
| options.channels | ||
@@ -1291,2 +1377,3 @@ ), | ||
| const action = await loadLiveActivityAction(options); | ||
| const secondaryAction = await loadLiveActivitySecondaryAction(options); | ||
@@ -1297,3 +1384,4 @@ const response = await client.liveActivities.updateLiveActivity({ | ||
| contentState, | ||
| action | ||
| action, | ||
| secondaryAction | ||
| ), | ||
@@ -1325,2 +1413,3 @@ }); | ||
| const action = await loadLiveActivityAction(options); | ||
| const secondaryAction = await loadLiveActivitySecondaryAction(options); | ||
@@ -1331,3 +1420,4 @@ const response = await client.liveActivities.endLiveActivity({ | ||
| contentState, | ||
| action | ||
| action, | ||
| secondaryAction | ||
| ), | ||
@@ -1360,6 +1450,13 @@ }); | ||
| const action = await loadLiveActivityAction(options); | ||
| const secondaryAction = await loadLiveActivitySecondaryAction(options); | ||
| const request = | ||
| contentState !== undefined || action !== undefined | ||
| ? toApiLiveActivityStreamDeleteRequest(contentState, action) | ||
| contentState !== undefined || | ||
| action !== undefined || | ||
| secondaryAction !== undefined | ||
| ? toApiLiveActivityStreamDeleteRequest( | ||
| contentState, | ||
| action, | ||
| secondaryAction | ||
| ) | ||
| : undefined; | ||
@@ -1366,0 +1463,0 @@ |
59892
6.07%1238
7.56%625
7.2%Updated