@unboundcx/sdk 2.8.6 → 2.8.8
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/README.md +48 -1
- package/base.js +43 -12
- package/index.js +27 -3
- package/package.json +5 -2
- package/proto/transcription.proto +207 -0
- package/services/ai/SttStream.js +311 -0
- package/services/ai/playbooks.js +958 -0
- package/services/ai.js +1006 -45
- package/services/engagementMetrics.js +6 -2
- package/services/externalOAuth.js +45 -0
- package/services/fax.js +249 -0
- package/services/knowledgeBase.js +229 -0
- package/services/messaging/EmailTemplatesService.js +31 -11
- package/services/messaging/TenDlcCampaignManagementService.js +187 -105
- package/services/messaging/TollFreeCampaignsService.js +263 -110
- package/services/notes.js +27 -2
- package/services/objects.js +92 -3
- package/services/phoneNumbers.js +88 -3
- package/services/portals.js +89 -0
- package/services/sipEndpoints.js +105 -33
- package/services/storage.js +310 -6
- package/services/taskRouter/MetricsService.js +111 -0
- package/services/taskRouter/TaskRouterService.js +12 -0
- package/services/taskRouter/TaskService.js +846 -0
- package/services/taskRouter/WorkerService.js +394 -0
- package/services/taskRouter.js +6 -0
- package/services/video.js +145 -5
- package/services/voice.js +124 -67
- package/services/workflows.js +167 -7
|
@@ -139,7 +139,11 @@ export class EngagementMetricsService {
|
|
|
139
139
|
* @param {string[]} [options.userIds] - Array of user IDs to filter by
|
|
140
140
|
* @returns {Promise<Object>} All metrics
|
|
141
141
|
*/
|
|
142
|
-
async getDashboardMetrics({
|
|
142
|
+
async getDashboardMetrics({
|
|
143
|
+
queueIds = [],
|
|
144
|
+
statuses = [],
|
|
145
|
+
userIds = [],
|
|
146
|
+
} = {}) {
|
|
143
147
|
return this.getMetrics({
|
|
144
148
|
queueIds,
|
|
145
149
|
statuses,
|
|
@@ -150,4 +154,4 @@ export class EngagementMetricsService {
|
|
|
150
154
|
includeAgentPerformance: true,
|
|
151
155
|
});
|
|
152
156
|
}
|
|
153
|
-
}
|
|
157
|
+
}
|
|
@@ -122,4 +122,49 @@ export class ExternalOAuthService {
|
|
|
122
122
|
const result = await this.sdk._fetch('/externalOAuth', 'GET');
|
|
123
123
|
return result;
|
|
124
124
|
}
|
|
125
|
+
|
|
126
|
+
async listUnified() {
|
|
127
|
+
const result = await this.sdk._fetch('/externalOAuth/unified', 'GET');
|
|
128
|
+
return result;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
async providers() {
|
|
132
|
+
const result = await this.sdk._fetch('/externalOAuth/providers', 'GET');
|
|
133
|
+
return result;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
async authorize({
|
|
137
|
+
name,
|
|
138
|
+
provider,
|
|
139
|
+
clientId,
|
|
140
|
+
clientSecret,
|
|
141
|
+
scopes,
|
|
142
|
+
authorizationUrl,
|
|
143
|
+
tokenUrl,
|
|
144
|
+
}) {
|
|
145
|
+
this.sdk.validateParams(
|
|
146
|
+
{ name, provider },
|
|
147
|
+
{
|
|
148
|
+
name: { type: 'string', required: true },
|
|
149
|
+
provider: { type: 'string', required: true },
|
|
150
|
+
clientId: { type: 'string', required: false },
|
|
151
|
+
clientSecret: { type: 'string', required: false },
|
|
152
|
+
scopes: { type: 'array', required: false },
|
|
153
|
+
authorizationUrl: { type: 'string', required: false },
|
|
154
|
+
tokenUrl: { type: 'string', required: false },
|
|
155
|
+
},
|
|
156
|
+
);
|
|
157
|
+
|
|
158
|
+
const body = { name, provider };
|
|
159
|
+
if (clientId) body.clientId = clientId;
|
|
160
|
+
if (clientSecret) body.clientSecret = clientSecret;
|
|
161
|
+
if (scopes) body.scopes = scopes;
|
|
162
|
+
if (authorizationUrl) body.authorizationUrl = authorizationUrl;
|
|
163
|
+
if (tokenUrl) body.tokenUrl = tokenUrl;
|
|
164
|
+
|
|
165
|
+
const result = await this.sdk._fetch('/externalOAuth/authorize', 'POST', {
|
|
166
|
+
body,
|
|
167
|
+
});
|
|
168
|
+
return result;
|
|
169
|
+
}
|
|
125
170
|
}
|
package/services/fax.js
ADDED
|
@@ -0,0 +1,249 @@
|
|
|
1
|
+
export class FaxService {
|
|
2
|
+
constructor(sdk) {
|
|
3
|
+
this.sdk = sdk;
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Create an inbound fax document record with status 'receiving'.
|
|
8
|
+
* Called by the media manager when an inbound fax is first detected.
|
|
9
|
+
* After the fax is fully received, call sdk.fax.status() to update
|
|
10
|
+
* with the final storage IDs and completion metadata.
|
|
11
|
+
*
|
|
12
|
+
* @param {Object} options - Parameters
|
|
13
|
+
* @param {string} options.faxMailboxId - ID of the fax mailbox receiving the fax (required)
|
|
14
|
+
* @param {string} [options.sipCallId] - SIP call correlation ID
|
|
15
|
+
* @param {string} [options.name] - Display name for the fax document
|
|
16
|
+
* @param {string} [options.faxHeader] - TSI header string from the sender
|
|
17
|
+
* @param {string} [options.resolution] - Fax resolution (e.g. 'fine', 'standard')
|
|
18
|
+
* @param {string} [options.toNumber] - Destination number in E.164 format
|
|
19
|
+
* @param {string} [options.fromNumber] - Sender number in E.164 format
|
|
20
|
+
* @returns {Promise<Object>} Created fax document
|
|
21
|
+
* @returns {string} result.id - The fax document ID (use in subsequent status calls)
|
|
22
|
+
* @returns {string} result.status - 'receiving'
|
|
23
|
+
*
|
|
24
|
+
* @example
|
|
25
|
+
* const { id } = await sdk.fax.receive({
|
|
26
|
+
* faxMailboxId: '157abc123...',
|
|
27
|
+
* sipCallId: 'sip-call-uuid',
|
|
28
|
+
* name: 'Fax from +15551234567',
|
|
29
|
+
* toNumber: '+15559876543',
|
|
30
|
+
* fromNumber: '+15551234567',
|
|
31
|
+
* });
|
|
32
|
+
* // Save id for use with sdk.fax.status() after reception completes
|
|
33
|
+
*/
|
|
34
|
+
async receive({
|
|
35
|
+
faxMailboxId,
|
|
36
|
+
sipCallId,
|
|
37
|
+
name,
|
|
38
|
+
faxHeader,
|
|
39
|
+
resolution,
|
|
40
|
+
toNumber,
|
|
41
|
+
fromNumber,
|
|
42
|
+
cId,
|
|
43
|
+
}) {
|
|
44
|
+
this.sdk.validateParams(
|
|
45
|
+
{ faxMailboxId },
|
|
46
|
+
{
|
|
47
|
+
faxMailboxId: { type: 'string', required: true },
|
|
48
|
+
},
|
|
49
|
+
);
|
|
50
|
+
|
|
51
|
+
const params = {
|
|
52
|
+
body: {
|
|
53
|
+
faxMailboxId,
|
|
54
|
+
sipCallId,
|
|
55
|
+
name,
|
|
56
|
+
faxHeader,
|
|
57
|
+
resolution,
|
|
58
|
+
toNumber,
|
|
59
|
+
fromNumber,
|
|
60
|
+
cId,
|
|
61
|
+
},
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
return await this.sdk._fetch('/fax/receive', 'POST', params);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Send an outbound fax.
|
|
69
|
+
* Creates a fax document record, retrieves the document from storage,
|
|
70
|
+
* and publishes to the media manager via NATS to initiate the fax call.
|
|
71
|
+
*
|
|
72
|
+
* @param {Object} options - Parameters
|
|
73
|
+
* @param {string} options.faxMailboxId - ID of the fax mailbox to send from (required)
|
|
74
|
+
* @param {string} options.toNumber - Destination number in E.164 format (required)
|
|
75
|
+
* @param {string} options.fromNumber - Caller ID number in E.164 format (required)
|
|
76
|
+
* @param {string} [options.storageId] - Storage ID of a PDF or TIFF file to fax. The server will
|
|
77
|
+
* automatically convert it to the missing format so both PDF and TIFF are stored.
|
|
78
|
+
* Required if pdfStorageId and tiffStorageId are not provided.
|
|
79
|
+
* @param {string} [options.pdfStorageId] - Storage ID of the PDF version. Required if storageId is not provided.
|
|
80
|
+
* @param {string} [options.tiffStorageId] - Storage ID of the TIFF version. Required if storageId is not provided.
|
|
81
|
+
* @param {string} [options.faxHeader] - TSI header text (defaults to mailbox faxHeader)
|
|
82
|
+
* @param {string} [options.resolution] - Fax resolution (defaults to mailbox resolution)
|
|
83
|
+
* @param {boolean} [options.ecm] - Enable Error Correction Mode (default: true)
|
|
84
|
+
* @param {number} [options.timeout] - Dial timeout in seconds (defaults to mailbox dialTimeout)
|
|
85
|
+
* @returns {Promise<Object>} Send result
|
|
86
|
+
* @returns {string} result.id - The fax document ID
|
|
87
|
+
* @returns {string} result.status - 'sending' on success, 'failed' on NATS error
|
|
88
|
+
* @returns {string} [result.requestId] - NATS request ID (on success)
|
|
89
|
+
* @returns {string} [result.error] - Error message (on failure)
|
|
90
|
+
*
|
|
91
|
+
* @example
|
|
92
|
+
* // Send using a single storageId (PDF or TIFF — server auto-converts the missing format)
|
|
93
|
+
* const result = await sdk.fax.send({
|
|
94
|
+
* faxMailboxId: '157abc123...',
|
|
95
|
+
* toNumber: '+15551234567',
|
|
96
|
+
* fromNumber: '+15559876543',
|
|
97
|
+
* storageId: '017xyz788...',
|
|
98
|
+
* });
|
|
99
|
+
* console.log(result.id); // '158def456...'
|
|
100
|
+
* console.log(result.status); // 'sending'
|
|
101
|
+
*
|
|
102
|
+
* @example
|
|
103
|
+
* // Send using explicit PDF and TIFF storage IDs
|
|
104
|
+
* const result = await sdk.fax.send({
|
|
105
|
+
* faxMailboxId: '157abc123...',
|
|
106
|
+
* toNumber: '+15551234567',
|
|
107
|
+
* fromNumber: '+15559876543',
|
|
108
|
+
* pdfStorageId: '017xyz789...',
|
|
109
|
+
* tiffStorageId: '017xyz788...',
|
|
110
|
+
* faxHeader: 'My Company',
|
|
111
|
+
* resolution: 'fine',
|
|
112
|
+
* ecm: true,
|
|
113
|
+
* timeout: 90,
|
|
114
|
+
* });
|
|
115
|
+
*/
|
|
116
|
+
async send({
|
|
117
|
+
faxMailboxId,
|
|
118
|
+
toNumber,
|
|
119
|
+
fromNumber,
|
|
120
|
+
storageId,
|
|
121
|
+
pdfStorageId,
|
|
122
|
+
tiffStorageId,
|
|
123
|
+
faxHeader,
|
|
124
|
+
resolution,
|
|
125
|
+
ecm,
|
|
126
|
+
timeout,
|
|
127
|
+
}) {
|
|
128
|
+
this.sdk.validateParams(
|
|
129
|
+
{ faxMailboxId, toNumber, fromNumber },
|
|
130
|
+
{
|
|
131
|
+
faxMailboxId: { type: 'string', required: true },
|
|
132
|
+
toNumber: { type: 'string', required: true },
|
|
133
|
+
fromNumber: { type: 'string', required: true },
|
|
134
|
+
storageId: { type: 'string', required: false },
|
|
135
|
+
pdfStorageId: { type: 'string', required: false },
|
|
136
|
+
tiffStorageId: { type: 'string', required: false },
|
|
137
|
+
},
|
|
138
|
+
);
|
|
139
|
+
|
|
140
|
+
if (!storageId && (!pdfStorageId || !tiffStorageId)) {
|
|
141
|
+
throw new Error(
|
|
142
|
+
'Either storageId or both pdfStorageId and tiffStorageId are required.',
|
|
143
|
+
);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
const params = {
|
|
147
|
+
body: {
|
|
148
|
+
faxMailboxId,
|
|
149
|
+
toNumber,
|
|
150
|
+
fromNumber,
|
|
151
|
+
storageId,
|
|
152
|
+
pdfStorageId,
|
|
153
|
+
tiffStorageId,
|
|
154
|
+
faxHeader,
|
|
155
|
+
resolution,
|
|
156
|
+
ecm,
|
|
157
|
+
timeout,
|
|
158
|
+
},
|
|
159
|
+
};
|
|
160
|
+
|
|
161
|
+
return await this.sdk._fetch('/fax/send', 'POST', params);
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* Update the status and metadata of a fax document.
|
|
166
|
+
* Called by the media manager to report progress and completion
|
|
167
|
+
* of both inbound and outbound faxes.
|
|
168
|
+
*
|
|
169
|
+
* @param {Object} options - Parameters
|
|
170
|
+
* @param {string} options.faxDocumentId - ID of the fax document to update (required)
|
|
171
|
+
* @param {string} options.status - New status (required): 'receiving', 'sending', 'sent', 'completed', 'failed'
|
|
172
|
+
* @param {string} [options.sipCallId] - SIP call correlation ID
|
|
173
|
+
* @param {number} [options.pages] - Number of pages transmitted/received
|
|
174
|
+
* @param {number} [options.duration] - Call duration in seconds
|
|
175
|
+
* @param {number} [options.transferRate] - Baud rate (e.g. 14400)
|
|
176
|
+
* @param {number} [options.ecmUsed] - Whether ECM was used (1 or 0)
|
|
177
|
+
* @param {number} [options.isError] - Whether an error occurred (1 or 0)
|
|
178
|
+
* @param {string} [options.errorMessage] - Error description
|
|
179
|
+
* @param {number} [options.sendAttempts] - Number of send attempts made
|
|
180
|
+
* @param {string} [options.pdfStorageId] - Storage ID of the PDF version
|
|
181
|
+
* @param {string} [options.tiffStorageId] - Storage ID of the TIFF version
|
|
182
|
+
* @returns {Promise<Object>} Updated fields
|
|
183
|
+
* @returns {string} result.id - The fax document ID
|
|
184
|
+
*
|
|
185
|
+
* @example
|
|
186
|
+
* // Complete an inbound fax with storage files and metadata
|
|
187
|
+
* await sdk.fax.status({
|
|
188
|
+
* faxDocumentId: '158abc123...',
|
|
189
|
+
* status: 'completed',
|
|
190
|
+
* pdfStorageId: '017pdf456...',
|
|
191
|
+
* tiffStorageId: '017tiff789...',
|
|
192
|
+
* pages: 3,
|
|
193
|
+
* duration: 45,
|
|
194
|
+
* transferRate: 14400,
|
|
195
|
+
* ecmUsed: 1,
|
|
196
|
+
* });
|
|
197
|
+
*
|
|
198
|
+
* @example
|
|
199
|
+
* // Report a fax failure
|
|
200
|
+
* await sdk.fax.status({
|
|
201
|
+
* faxDocumentId: '158abc123...',
|
|
202
|
+
* status: 'failed',
|
|
203
|
+
* isError: 1,
|
|
204
|
+
* errorMessage: 'Remote side disconnected',
|
|
205
|
+
* sendAttempts: 2,
|
|
206
|
+
* });
|
|
207
|
+
*/
|
|
208
|
+
async status({
|
|
209
|
+
faxDocumentId,
|
|
210
|
+
status,
|
|
211
|
+
sipCallId,
|
|
212
|
+
pages,
|
|
213
|
+
duration,
|
|
214
|
+
transferRate,
|
|
215
|
+
ecmUsed,
|
|
216
|
+
isError,
|
|
217
|
+
errorMessage,
|
|
218
|
+
sendAttempts,
|
|
219
|
+
pdfStorageId,
|
|
220
|
+
tiffStorageId,
|
|
221
|
+
}) {
|
|
222
|
+
this.sdk.validateParams(
|
|
223
|
+
{ faxDocumentId, status },
|
|
224
|
+
{
|
|
225
|
+
faxDocumentId: { type: 'string', required: true },
|
|
226
|
+
status: { type: 'string', required: true },
|
|
227
|
+
},
|
|
228
|
+
);
|
|
229
|
+
|
|
230
|
+
const params = {
|
|
231
|
+
body: {
|
|
232
|
+
faxDocumentId,
|
|
233
|
+
status,
|
|
234
|
+
sipCallId,
|
|
235
|
+
pages,
|
|
236
|
+
duration,
|
|
237
|
+
transferRate,
|
|
238
|
+
ecmUsed,
|
|
239
|
+
isError,
|
|
240
|
+
errorMessage,
|
|
241
|
+
sendAttempts,
|
|
242
|
+
pdfStorageId,
|
|
243
|
+
tiffStorageId,
|
|
244
|
+
},
|
|
245
|
+
};
|
|
246
|
+
|
|
247
|
+
return await this.sdk._fetch('/fax/status', 'POST', params);
|
|
248
|
+
}
|
|
249
|
+
}
|
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
export class KnowledgeBaseService {
|
|
2
|
+
constructor(sdk) {
|
|
3
|
+
this.sdk = sdk;
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Hybrid search across knowledge base content
|
|
8
|
+
* Combines keyword (FULLTEXT) and semantic (vector) search with optional LLM reranking
|
|
9
|
+
*
|
|
10
|
+
* @param {Object} params
|
|
11
|
+
* @param {string} params.query - Search query text
|
|
12
|
+
* @param {string} [params.knowledgeBaseId] - Specific KB to search (omit to search all)
|
|
13
|
+
* @param {number} [params.limit] - Max results to return
|
|
14
|
+
* @param {Object} [params.filters] - Optional filters
|
|
15
|
+
* @param {string} [params.filters.categoryId] - Filter by category
|
|
16
|
+
* @param {string} [params.filters.sourceType] - Filter by source type (article, document, source)
|
|
17
|
+
* @param {Array} [params.filters.tags] - Filter by tags
|
|
18
|
+
* @param {boolean} [params.rerank] - Whether to apply LLM reranking (default: true)
|
|
19
|
+
* @returns {Promise<Object>} Search results with source attribution
|
|
20
|
+
*/
|
|
21
|
+
async search({ query, knowledgeBaseId, limit, filters, rerank }) {
|
|
22
|
+
this.sdk.validateParams(
|
|
23
|
+
{ query },
|
|
24
|
+
{
|
|
25
|
+
query: { type: 'string', required: true },
|
|
26
|
+
},
|
|
27
|
+
);
|
|
28
|
+
|
|
29
|
+
const params = {
|
|
30
|
+
body: { query, knowledgeBaseId, limit, filters, rerank },
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
const result = await this.sdk._fetch(
|
|
34
|
+
'/knowledgeBase/search',
|
|
35
|
+
'POST',
|
|
36
|
+
params,
|
|
37
|
+
);
|
|
38
|
+
return result;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Discover pages available at a URL
|
|
43
|
+
* Checks for sitemaps (auto-discovery + direct sitemap URLs) and returns
|
|
44
|
+
* a list of pages the user can select from before ingesting.
|
|
45
|
+
*
|
|
46
|
+
* @param {Object} params
|
|
47
|
+
* @param {string} params.url - URL to discover (base URL or sitemap URL)
|
|
48
|
+
* @returns {Promise<Object>} { url, type, sitemapUrl, pages[], pageCount }
|
|
49
|
+
*/
|
|
50
|
+
async discoverUrl({ url }) {
|
|
51
|
+
this.sdk.validateParams(
|
|
52
|
+
{ url },
|
|
53
|
+
{
|
|
54
|
+
url: { type: 'string', required: true },
|
|
55
|
+
},
|
|
56
|
+
);
|
|
57
|
+
|
|
58
|
+
const params = {
|
|
59
|
+
body: { url },
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
const result = await this.sdk._fetch(
|
|
63
|
+
'/knowledgeBase/discover-url',
|
|
64
|
+
'POST',
|
|
65
|
+
params,
|
|
66
|
+
);
|
|
67
|
+
return result;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Ingest a URL into a knowledge base
|
|
72
|
+
* Creates a kbSources record and triggers async crawl + processing
|
|
73
|
+
*
|
|
74
|
+
* @param {Object} params
|
|
75
|
+
* @param {string} params.knowledgeBaseId - Target knowledge base
|
|
76
|
+
* @param {string} params.url - URL to crawl and ingest
|
|
77
|
+
* @param {string} [params.categoryId] - Category to assign
|
|
78
|
+
* @param {string} [params.title] - Display title (auto-detected from page if omitted)
|
|
79
|
+
* @param {string} [params.refreshInterval] - Recrawl interval: manual, daily, weekly, monthly
|
|
80
|
+
* @returns {Promise<Object>} Created kbSources record
|
|
81
|
+
*/
|
|
82
|
+
async ingestUrl({ knowledgeBaseId, url, categoryId, title, refreshInterval }) {
|
|
83
|
+
this.sdk.validateParams(
|
|
84
|
+
{ knowledgeBaseId, url },
|
|
85
|
+
{
|
|
86
|
+
knowledgeBaseId: { type: 'string', required: true },
|
|
87
|
+
url: { type: 'string', required: true },
|
|
88
|
+
},
|
|
89
|
+
);
|
|
90
|
+
|
|
91
|
+
const params = {
|
|
92
|
+
body: { knowledgeBaseId, url, categoryId, title, refreshInterval },
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
const result = await this.sdk._fetch(
|
|
96
|
+
'/knowledgeBase/ingest/url',
|
|
97
|
+
'POST',
|
|
98
|
+
params,
|
|
99
|
+
);
|
|
100
|
+
return result;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Trigger (re)processing of a knowledge base source
|
|
105
|
+
* Sets processingStatus to pending and publishes NATS event
|
|
106
|
+
*
|
|
107
|
+
* @param {Object} params
|
|
108
|
+
* @param {string} params.sourceType - Type: article, document, or source
|
|
109
|
+
* @param {string} params.id - Source record ID
|
|
110
|
+
* @returns {Promise<Object>} Updated source record
|
|
111
|
+
*/
|
|
112
|
+
async processSource({ sourceType, id }) {
|
|
113
|
+
this.sdk.validateParams(
|
|
114
|
+
{ sourceType, id },
|
|
115
|
+
{
|
|
116
|
+
sourceType: { type: 'string', required: true },
|
|
117
|
+
id: { type: 'string', required: true },
|
|
118
|
+
},
|
|
119
|
+
);
|
|
120
|
+
|
|
121
|
+
const result = await this.sdk._fetch(
|
|
122
|
+
`/knowledgeBase/process/${sourceType}/${id}`,
|
|
123
|
+
'POST',
|
|
124
|
+
);
|
|
125
|
+
return result;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* Check the processing status of a source
|
|
130
|
+
*
|
|
131
|
+
* @param {Object} params
|
|
132
|
+
* @param {string} params.id - Source record ID
|
|
133
|
+
* @returns {Promise<Object>} Processing status { id, processingStatus, processingError }
|
|
134
|
+
*/
|
|
135
|
+
async checkProcessingStatus({ id }) {
|
|
136
|
+
this.sdk.validateParams(
|
|
137
|
+
{ id },
|
|
138
|
+
{
|
|
139
|
+
id: { type: 'string', required: true },
|
|
140
|
+
},
|
|
141
|
+
);
|
|
142
|
+
|
|
143
|
+
const result = await this.sdk._fetch(
|
|
144
|
+
`/knowledgeBase/process/${id}/status`,
|
|
145
|
+
'GET',
|
|
146
|
+
);
|
|
147
|
+
return result;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* Publish a draft article
|
|
152
|
+
* Changes status to published, creates version snapshot, triggers processing
|
|
153
|
+
*
|
|
154
|
+
* @param {Object} params
|
|
155
|
+
* @param {string} params.id - Article ID
|
|
156
|
+
* @returns {Promise<Object>} Updated article record
|
|
157
|
+
*/
|
|
158
|
+
async publishArticle({ id }) {
|
|
159
|
+
this.sdk.validateParams(
|
|
160
|
+
{ id },
|
|
161
|
+
{
|
|
162
|
+
id: { type: 'string', required: true },
|
|
163
|
+
},
|
|
164
|
+
);
|
|
165
|
+
|
|
166
|
+
const result = await this.sdk._fetch(
|
|
167
|
+
`/knowledgeBase/articles/${id}/publish`,
|
|
168
|
+
'POST',
|
|
169
|
+
);
|
|
170
|
+
return result;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
* Get analytics for a knowledge base
|
|
175
|
+
*
|
|
176
|
+
* @param {Object} params
|
|
177
|
+
* @param {string} params.knowledgeBaseId - Knowledge base ID
|
|
178
|
+
* @param {Object} [params.filters] - Optional date range, source type filters
|
|
179
|
+
* @returns {Promise<Object>} Analytics data
|
|
180
|
+
*/
|
|
181
|
+
async getAnalytics({ knowledgeBaseId, ...filters }) {
|
|
182
|
+
this.sdk.validateParams(
|
|
183
|
+
{ knowledgeBaseId },
|
|
184
|
+
{
|
|
185
|
+
knowledgeBaseId: { type: 'string', required: true },
|
|
186
|
+
},
|
|
187
|
+
);
|
|
188
|
+
|
|
189
|
+
const params = {
|
|
190
|
+
query: filters,
|
|
191
|
+
};
|
|
192
|
+
|
|
193
|
+
const result = await this.sdk._fetch(
|
|
194
|
+
`/knowledgeBase/${knowledgeBaseId}/analytics`,
|
|
195
|
+
'GET',
|
|
196
|
+
params,
|
|
197
|
+
);
|
|
198
|
+
return result;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
/**
|
|
202
|
+
* Get content gap analysis for a knowledge base
|
|
203
|
+
* Identifies failed/low-result searches that indicate missing content
|
|
204
|
+
*
|
|
205
|
+
* @param {Object} params
|
|
206
|
+
* @param {string} params.knowledgeBaseId - Knowledge base ID
|
|
207
|
+
* @param {Object} [params.filters] - Optional date range filters
|
|
208
|
+
* @returns {Promise<Object>} Gap analysis data
|
|
209
|
+
*/
|
|
210
|
+
async getGaps({ knowledgeBaseId, ...filters }) {
|
|
211
|
+
this.sdk.validateParams(
|
|
212
|
+
{ knowledgeBaseId },
|
|
213
|
+
{
|
|
214
|
+
knowledgeBaseId: { type: 'string', required: true },
|
|
215
|
+
},
|
|
216
|
+
);
|
|
217
|
+
|
|
218
|
+
const params = {
|
|
219
|
+
query: filters,
|
|
220
|
+
};
|
|
221
|
+
|
|
222
|
+
const result = await this.sdk._fetch(
|
|
223
|
+
`/knowledgeBase/${knowledgeBaseId}/analytics/gaps`,
|
|
224
|
+
'GET',
|
|
225
|
+
params,
|
|
226
|
+
);
|
|
227
|
+
return result;
|
|
228
|
+
}
|
|
229
|
+
}
|
|
@@ -10,18 +10,26 @@ export class EmailTemplatesService {
|
|
|
10
10
|
* @param {string} params.subject - Template subject (required)
|
|
11
11
|
* @param {string} [params.html] - HTML template body
|
|
12
12
|
* @param {string} [params.text] - Plain text template body
|
|
13
|
-
* @
|
|
13
|
+
* @param {Array<Object>} [params.variables] - Variable metadata definitions
|
|
14
|
+
* @param {string} params.variables[].key - Variable key (unique, alphanumeric + underscores)
|
|
15
|
+
* @param {string} params.variables[].label - Human-readable display name
|
|
16
|
+
* @param {string} params.variables[].type - One of: text, textarea, url, image, richtext
|
|
17
|
+
* @param {string} [params.variables[].defaultValue] - Default value
|
|
18
|
+
* @param {boolean} [params.variables[].required] - Whether variable is required
|
|
19
|
+
* @returns {Promise<Object>} Created template details with merged variables
|
|
14
20
|
* @example
|
|
15
|
-
* // Create template with variables in the content
|
|
16
21
|
* const template = await sdk.messaging.email.templates.create({
|
|
17
22
|
* name: 'Welcome Email',
|
|
18
23
|
* subject: 'Welcome {{firstName}}!',
|
|
19
|
-
* html: '<h1>Hello {{firstName}}
|
|
20
|
-
* text: 'Hello {{firstName}}
|
|
24
|
+
* html: '<h1>Hello {{firstName}}</h1><p>{{body}}</p>',
|
|
25
|
+
* text: 'Hello {{firstName}}',
|
|
26
|
+
* variables: [
|
|
27
|
+
* { key: 'firstName', label: 'First Name', type: 'text', required: true },
|
|
28
|
+
* { key: 'body', label: 'Email Body', type: 'richtext' },
|
|
29
|
+
* ],
|
|
21
30
|
* });
|
|
22
|
-
* // Returns: { id, name, variables: ['firstName', 'lastName'] }
|
|
23
31
|
*/
|
|
24
|
-
async create({ name, subject, html, text }) {
|
|
32
|
+
async create({ name, subject, html, text, variables }) {
|
|
25
33
|
this.sdk.validateParams(
|
|
26
34
|
{ name, subject },
|
|
27
35
|
{
|
|
@@ -29,12 +37,14 @@ export class EmailTemplatesService {
|
|
|
29
37
|
subject: { type: 'string', required: true },
|
|
30
38
|
html: { type: 'string', required: false },
|
|
31
39
|
text: { type: 'string', required: false },
|
|
40
|
+
variables: { type: 'array', required: false },
|
|
32
41
|
},
|
|
33
42
|
);
|
|
34
43
|
|
|
35
44
|
const templateData = { name, subject };
|
|
36
45
|
if (html) templateData.html = html;
|
|
37
46
|
if (text) templateData.text = text;
|
|
47
|
+
if (variables) templateData.variables = variables;
|
|
38
48
|
|
|
39
49
|
const options = {
|
|
40
50
|
body: templateData,
|
|
@@ -56,15 +66,23 @@ export class EmailTemplatesService {
|
|
|
56
66
|
* @param {string} [params.subject] - Template subject
|
|
57
67
|
* @param {string} [params.html] - HTML template body
|
|
58
68
|
* @param {string} [params.text] - Plain text template body
|
|
59
|
-
* @
|
|
69
|
+
* @param {Array<Object>} [params.variables] - Variable metadata definitions
|
|
70
|
+
* @param {string} params.variables[].key - Variable key (unique, alphanumeric + underscores)
|
|
71
|
+
* @param {string} params.variables[].label - Human-readable display name
|
|
72
|
+
* @param {string} params.variables[].type - One of: text, textarea, url, image, richtext
|
|
73
|
+
* @param {string} [params.variables[].defaultValue] - Default value
|
|
74
|
+
* @param {boolean} [params.variables[].required] - Whether variable is required
|
|
75
|
+
* @returns {Promise<Object>} Updated template details with merged variables
|
|
60
76
|
* @example
|
|
61
|
-
* // Update template - variables are auto-extracted from content
|
|
62
77
|
* const updated = await sdk.messaging.email.templates.update('tpl_123', {
|
|
63
|
-
* subject: 'Hi {{firstName}}, welcome to {{companyName}}!'
|
|
78
|
+
* subject: 'Hi {{firstName}}, welcome to {{companyName}}!',
|
|
79
|
+
* variables: [
|
|
80
|
+
* { key: 'firstName', label: 'First Name', type: 'text', required: true },
|
|
81
|
+
* { key: 'companyName', label: 'Company Name', type: 'text' },
|
|
82
|
+
* ],
|
|
64
83
|
* });
|
|
65
|
-
* // Returns updated template with variables: ['firstName', 'companyName']
|
|
66
84
|
*/
|
|
67
|
-
async update(id, { name, subject, html, text }) {
|
|
85
|
+
async update(id, { name, subject, html, text, variables }) {
|
|
68
86
|
this.sdk.validateParams(
|
|
69
87
|
{ id },
|
|
70
88
|
{
|
|
@@ -73,6 +91,7 @@ export class EmailTemplatesService {
|
|
|
73
91
|
subject: { type: 'string', required: false },
|
|
74
92
|
html: { type: 'string', required: false },
|
|
75
93
|
text: { type: 'string', required: false },
|
|
94
|
+
variables: { type: 'array', required: false },
|
|
76
95
|
},
|
|
77
96
|
);
|
|
78
97
|
|
|
@@ -81,6 +100,7 @@ export class EmailTemplatesService {
|
|
|
81
100
|
if (subject) updateData.subject = subject;
|
|
82
101
|
if (html) updateData.html = html;
|
|
83
102
|
if (text) updateData.text = text;
|
|
103
|
+
if (variables) updateData.variables = variables;
|
|
84
104
|
|
|
85
105
|
const options = {
|
|
86
106
|
body: updateData,
|