@unboundcx/sdk 4.13.40 → 4.13.42

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@unboundcx/sdk",
3
- "version": "4.13.40",
3
+ "version": "4.13.42",
4
4
  "description": "Official JavaScript SDK for the Unbound API - A comprehensive toolkit for integrating with Unbound's communication, AI, and data management services",
5
5
  "main": "index.js",
6
6
  "type": "module",
@@ -10,7 +10,8 @@ export class SmsService {
10
10
  /**
11
11
  * Send an SMS/MMS message
12
12
  * @param {Object} params - Message parameters
13
- * @param {string} params.to - Recipient phone number (required)
13
+ * @param {string|string[]} params.to - Recipient phone number, or an
14
+ * array of up to 8 for a group MMS send (required)
14
15
  * @param {string} [params.from] - Sender phone number
15
16
  * @param {string} [params.message] - Message text
16
17
  * @param {string} [params.templateId] - Template ID to use
@@ -50,10 +51,24 @@ export class SmsService {
50
51
  if (taskId) messageData.taskId = taskId;
51
52
  if (force !== undefined) messageData.force = force;
52
53
 
54
+ // `to` is string | string[] (group MMS, up to 8 recipients) --
55
+ // validated by hand since sdk.validateParams has no multi-type support
56
+ // (see TaskService.js's ['string','array'] usage, which hits the same
57
+ // gap) rather than compounding that on a new call site.
58
+ if (to === undefined || to === null) {
59
+ throw new Error('Missing required parameter to');
60
+ }
61
+ if (Array.isArray(to)) {
62
+ if (!to.length || !to.every((n) => typeof n === 'string')) {
63
+ throw new Error('Invalid type for parameter to: expected string or string[]');
64
+ }
65
+ } else if (typeof to !== 'string') {
66
+ throw new Error('Invalid type for parameter to: expected string or string[]');
67
+ }
68
+
53
69
  this.sdk.validateParams(
54
- { to, ...messageData },
70
+ { ...messageData },
55
71
  {
56
- to: { type: 'string', required: true },
57
72
  from: { type: 'string', required: false },
58
73
  message: { type: 'string', required: false },
59
74
  templateId: { type: 'string', required: false },
@@ -9,7 +9,16 @@ export class MetricsService {
9
9
  * Retrieves real-time metrics for task router queues, tasks, and workers.
10
10
  * This provides insights into queue performance, wait times, task counts, and worker activity.
11
11
  *
12
- * @param {Object} params - Metric parameters
12
+ * Accepts either `(params)` or `(accountId, params)` -- every client
13
+ * caller uses the former (e.g. `getCurrent({ queueId })`), and
14
+ * `accountId` is optional (the API route scopes by the authenticated
15
+ * account already). Sent as a query string, not a body: this hits
16
+ * `/taskRouter/metrics/current` over GET, and base.js's `_httpRequest`
17
+ * deletes `body` on any GET request, so a body-only payload here was
18
+ * silently discarded before ever reaching the server.
19
+ *
20
+ * @param {Object|string} [paramsOrAccountId] - Either the params object (preferred) or an accountId string
21
+ * @param {Object} [maybeParams] - Metric parameters, when the first argument is an accountId
13
22
  * @param {string} [params.period] - Time period for metrics calculation. Options: '5min', '15min', '30min', '1hour', '24hour'
14
23
  * @param {string} [params.queueId] - Specific queue ID to filter metrics. If not provided, returns metrics for all queues
15
24
  * @param {string} [params.metricType] - Type of metrics to retrieve: 'queue', 'task', 'worker', or 'all' (default: 'all')
@@ -71,7 +80,11 @@ export class MetricsService {
71
80
  * console.log(taskMetrics.metrics.task.created); // 150
72
81
  * console.log(taskMetrics.metrics.task.completed); // 142
73
82
  */
74
- async getCurrent(accountId, params = {}) {
83
+ async getCurrent(paramsOrAccountId, maybeParams) {
84
+ const isParamsFirst =
85
+ paramsOrAccountId !== null && typeof paramsOrAccountId === 'object';
86
+ const accountId = isParamsFirst ? undefined : paramsOrAccountId;
87
+ const params = (isParamsFirst ? paramsOrAccountId : maybeParams) || {};
75
88
  const { period, queueId, metricType, limit = 100 } = params;
76
89
 
77
90
  this.sdk.validateParams(
@@ -84,28 +97,28 @@ export class MetricsService {
84
97
  },
85
98
  );
86
99
 
87
- const requestParams = {
88
- body: {
89
- limit,
90
- },
91
- };
100
+ const query = { limit };
101
+
102
+ if (accountId !== undefined) {
103
+ query.accountId = accountId;
104
+ }
92
105
 
93
106
  if (period !== undefined) {
94
- requestParams.body.period = period;
107
+ query.period = period;
95
108
  }
96
109
 
97
110
  if (queueId !== undefined) {
98
- requestParams.body.queueId = queueId;
111
+ query.queueId = queueId;
99
112
  }
100
113
 
101
114
  if (metricType !== undefined) {
102
- requestParams.body.metricType = metricType;
115
+ query.metricType = metricType;
103
116
  }
104
117
 
105
- const result = await internalRequest(this.sdk,
118
+ const result = await internalRequest(this.sdk,
106
119
  '/taskRouter/metrics/current',
107
120
  'GET',
108
- requestParams,
121
+ { query },
109
122
  );
110
123
  return result;
111
124
  }
@@ -23,6 +23,7 @@ export class TaskService {
23
23
  * @param {boolean} [options.createEngagement=false] - Whether to automatically create an engagement session for this task
24
24
  * @param {string} [options.relatedObject] - Related object type for metadata tracking (automatically set if createEngagement is true)
25
25
  * @param {string} [options.relatedId] - Related object ID for metadata tracking (automatically set if createEngagement is true)
26
+ * @param {Object} [options.metadata] - Arbitrary metadata to attach to the task at creation (e.g. `{ textConversationId }`). Passed through as-is; whether it is persisted depends on the receiving endpoint honoring `metadata` in the request body.
26
27
  * @returns {Promise<Object>} Object containing the created task information
27
28
  * @returns {string} result.id - The unique identifier for the created task
28
29
  *
@@ -83,6 +84,7 @@ export class TaskService {
83
84
  cdrId,
84
85
  sipCallId,
85
86
  aiChatSessionId,
87
+ metadata,
86
88
  } = options;
87
89
 
88
90
  this.sdk.validateParams(
@@ -102,6 +104,7 @@ export class TaskService {
102
104
  relatedId,
103
105
  sipCallId,
104
106
  aiChatSessionId,
107
+ metadata,
105
108
  },
106
109
  {
107
110
  type: { type: 'string', required: true },
@@ -119,6 +122,7 @@ export class TaskService {
119
122
  relatedId: { type: 'string', required: false },
120
123
  sipCallId: { type: 'string', required: false },
121
124
  aiChatSessionId: { type: 'string', required: false },
125
+ metadata: { type: 'object', required: false },
122
126
  },
123
127
  );
124
128
 
@@ -181,6 +185,10 @@ export class TaskService {
181
185
  params.body.aiChatSessionId = aiChatSessionId;
182
186
  }
183
187
 
188
+ if (metadata !== undefined) {
189
+ params.body.metadata = metadata;
190
+ }
191
+
184
192
  const result = await internalRequest(this.sdk, '/taskRouter/tasks', 'POST', params);
185
193
  return result;
186
194
  }
package/services/text.js CHANGED
@@ -97,6 +97,56 @@ export class TextConversationsService {
97
97
  body: { queueId, workflowId, workflowVersionId },
98
98
  });
99
99
  }
100
+
101
+ /**
102
+ * Move a TASK-owned conversation to a user (or UC Chat group) or to a
103
+ * workflow (sms-routing-plan.md K4, plan §3.4 "task -> user"/"task ->
104
+ * workflow"). Caller must be the task's current worker or a manager --
105
+ * enforced server-side. Moving to a user creates/reuses the UC Chat
106
+ * channel for that (identity, counterparty) pair starting from now --
107
+ * prior message history is NOT backfilled into the channel.
108
+ * @param {string} id - textConversations id (required)
109
+ * @param {Object} options - Parameters
110
+ * @param {'user'|'workflow'} options.to - Move target (required)
111
+ * @param {string} [options.userId] - Target user (required if to:'user' and no groupId)
112
+ * @param {string} [options.groupId] - Target UC Chat group (required if to:'user' and no userId)
113
+ * @param {'private'|'public'} [options.visibility] - New channel visibility (to:'user' only)
114
+ * @param {string} [options.workflowId] - Move to a workflow's current version
115
+ * @param {string} [options.workflowVersionId] - Move to a pinned workflow version
116
+ * @returns {Promise<Object>} The updated conversation row
117
+ */
118
+ async move(id, options = {}) {
119
+ const { to, userId, groupId, visibility, workflowId, workflowVersionId } =
120
+ options;
121
+
122
+ this.sdk.validateParams(
123
+ { id, to, userId, groupId, visibility, workflowId, workflowVersionId },
124
+ {
125
+ id: { type: 'string', required: true },
126
+ to: { type: 'string', required: true },
127
+ userId: { type: 'string', required: false },
128
+ groupId: { type: 'string', required: false },
129
+ visibility: { type: 'string', required: false },
130
+ workflowId: { type: 'string', required: false },
131
+ workflowVersionId: { type: 'string', required: false },
132
+ },
133
+ );
134
+ if (to !== 'user' && to !== 'workflow') {
135
+ throw new Error("move requires to: 'user' or 'workflow'");
136
+ }
137
+ if (to === 'user' && !userId && !groupId) {
138
+ throw new Error("move to:'user' requires userId or groupId");
139
+ }
140
+ if (to === 'workflow' && !workflowId && !workflowVersionId) {
141
+ throw new Error(
142
+ "move to:'workflow' requires workflowId or workflowVersionId",
143
+ );
144
+ }
145
+
146
+ return internalRequest(this.sdk, `/text/conversations/${id}/move`, 'POST', {
147
+ body: { to, userId, groupId, visibility, workflowId, workflowVersionId },
148
+ });
149
+ }
100
150
  }
101
151
 
102
152
  export class TextService {