@toothfairyai/cli 1.0.14 → 1.0.16
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/bin/toothfairy.js +46 -5
- package/package.json +1 -1
- package/src/api.js +108 -12
package/bin/toothfairy.js
CHANGED
|
@@ -114,6 +114,10 @@ program
|
|
|
114
114
|
.option("--customer-id <id>", "Customer ID")
|
|
115
115
|
.option("--provider-id <id>", "SMS provider ID")
|
|
116
116
|
.option("--customer-info <json>", "Customer info as JSON string")
|
|
117
|
+
.option("--image <path>", "Path to image file (png, jpg, jpeg, gif, bmp, svg)")
|
|
118
|
+
.option("--audio <path>", "Path to audio file (wav, mp3, aac, ogg, flac)")
|
|
119
|
+
.option("--video <path>", "Path to video file (mp4, avi, mov, wmv, flv, webm)")
|
|
120
|
+
.option("--file <path...>", "Path to document files (max 5)")
|
|
117
121
|
.option("-o, --output <format>", "Output format (json|text)", "text")
|
|
118
122
|
.option("-v, --verbose", "Show detailed response information")
|
|
119
123
|
.action(async (message, options, command) => {
|
|
@@ -137,12 +141,27 @@ program
|
|
|
137
141
|
try {
|
|
138
142
|
customerInfo = JSON.parse(options.customerInfo);
|
|
139
143
|
} catch (error) {
|
|
140
|
-
console.error(chalk.red(
|
|
144
|
+
console.error(chalk.red('Invalid JSON in customer-info'));
|
|
141
145
|
process.exit(1);
|
|
142
146
|
}
|
|
143
147
|
}
|
|
144
148
|
|
|
145
|
-
|
|
149
|
+
// Process file attachments if provided
|
|
150
|
+
const attachments = {};
|
|
151
|
+
if (options.image) {
|
|
152
|
+
attachments.images = [options.image];
|
|
153
|
+
}
|
|
154
|
+
if (options.audio) {
|
|
155
|
+
attachments.audios = [options.audio];
|
|
156
|
+
}
|
|
157
|
+
if (options.video) {
|
|
158
|
+
attachments.videos = [options.video];
|
|
159
|
+
}
|
|
160
|
+
if (options.file) {
|
|
161
|
+
attachments.files = Array.isArray(options.file) ? options.file : [options.file];
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
const spinner = ora('Sending message to agent...').start();
|
|
146
165
|
|
|
147
166
|
const response = await api.sendMessageToAgent(
|
|
148
167
|
message,
|
|
@@ -150,7 +169,8 @@ program
|
|
|
150
169
|
options.phoneNumber,
|
|
151
170
|
options.customerId,
|
|
152
171
|
options.providerId,
|
|
153
|
-
customerInfo
|
|
172
|
+
customerInfo,
|
|
173
|
+
attachments
|
|
154
174
|
);
|
|
155
175
|
|
|
156
176
|
spinner.stop();
|
|
@@ -221,6 +241,10 @@ program
|
|
|
221
241
|
.option("--customer-id <id>", "Customer ID")
|
|
222
242
|
.option("--provider-id <id>", "SMS provider ID")
|
|
223
243
|
.option("--customer-info <json>", "Customer info as JSON string")
|
|
244
|
+
.option('--image <path>', 'Path to image file (PNG, max 1)')
|
|
245
|
+
.option('--audio <path>', 'Path to audio file (WAV, max 1)')
|
|
246
|
+
.option('--video <path>', 'Path to video file (MP4, max 1)')
|
|
247
|
+
.option('--file <path>', 'Path to file (max 5, can be used multiple times)', (value, previous) => previous.concat([value]), [])
|
|
224
248
|
.option("-o, --output <format>", "Output format (json|text)", "text")
|
|
225
249
|
.option("-v, --verbose", "Show detailed streaming information")
|
|
226
250
|
.option("--show-progress", "Show agent processing status updates")
|
|
@@ -270,6 +294,21 @@ program
|
|
|
270
294
|
}
|
|
271
295
|
}
|
|
272
296
|
|
|
297
|
+
// Process file attachments if provided
|
|
298
|
+
const attachments = {};
|
|
299
|
+
if (options.image) {
|
|
300
|
+
attachments.images = [options.image];
|
|
301
|
+
}
|
|
302
|
+
if (options.audio) {
|
|
303
|
+
attachments.audios = [options.audio];
|
|
304
|
+
}
|
|
305
|
+
if (options.video) {
|
|
306
|
+
attachments.videos = [options.video];
|
|
307
|
+
}
|
|
308
|
+
if (options.file) {
|
|
309
|
+
attachments.files = Array.isArray(options.file) ? options.file : [options.file];
|
|
310
|
+
}
|
|
311
|
+
|
|
273
312
|
console.log(
|
|
274
313
|
chalk.cyan(`Streaming message to agent ${options.agentId}...`)
|
|
275
314
|
);
|
|
@@ -351,7 +390,8 @@ program
|
|
|
351
390
|
)
|
|
352
391
|
);
|
|
353
392
|
}
|
|
354
|
-
}
|
|
393
|
+
},
|
|
394
|
+
attachments
|
|
355
395
|
);
|
|
356
396
|
|
|
357
397
|
console.log(JSON.stringify(allEvents, null, 2));
|
|
@@ -505,7 +545,8 @@ program
|
|
|
505
545
|
console.error(chalk.red(`\n❌ Error: ${errorMsg}`));
|
|
506
546
|
process.exit(1);
|
|
507
547
|
}
|
|
508
|
-
}
|
|
548
|
+
},
|
|
549
|
+
attachments
|
|
509
550
|
);
|
|
510
551
|
|
|
511
552
|
// Clean up spinner after streaming completes
|
package/package.json
CHANGED
package/src/api.js
CHANGED
|
@@ -184,7 +184,8 @@ class ToothFairyAPI {
|
|
|
184
184
|
phoneNumber = null,
|
|
185
185
|
customerId = null,
|
|
186
186
|
providerId = null,
|
|
187
|
-
customerInfo = {}
|
|
187
|
+
customerInfo = {},
|
|
188
|
+
attachments = {}
|
|
188
189
|
) {
|
|
189
190
|
try {
|
|
190
191
|
// Use defaults for optional parameters
|
|
@@ -192,14 +193,17 @@ class ToothFairyAPI {
|
|
|
192
193
|
customerId ||
|
|
193
194
|
`cli-user-${
|
|
194
195
|
Math.abs(
|
|
195
|
-
message.split(
|
|
196
|
+
message.split('').reduce((a, b) => {
|
|
196
197
|
a = (a << 5) - a + b.charCodeAt(0);
|
|
197
198
|
return a & a;
|
|
198
199
|
}, 0)
|
|
199
200
|
) % 10000
|
|
200
201
|
}`;
|
|
201
|
-
phoneNumber = phoneNumber ||
|
|
202
|
-
providerId = providerId ||
|
|
202
|
+
phoneNumber = phoneNumber || '+1234567890';
|
|
203
|
+
providerId = providerId || 'default-sms-provider';
|
|
204
|
+
|
|
205
|
+
// Process file attachments if provided
|
|
206
|
+
const processedAttachments = await this._processAttachments(attachments);
|
|
203
207
|
|
|
204
208
|
const chatData = {
|
|
205
209
|
name: customerId,
|
|
@@ -223,8 +227,9 @@ class ToothFairyAPI {
|
|
|
223
227
|
const messageData = {
|
|
224
228
|
chatID: createdChat.id,
|
|
225
229
|
text: message,
|
|
226
|
-
role:
|
|
227
|
-
userID:
|
|
230
|
+
role: 'user',
|
|
231
|
+
userID: 'CLI',
|
|
232
|
+
...processedAttachments,
|
|
228
233
|
};
|
|
229
234
|
const createdMessage = await this.createMessage(messageData);
|
|
230
235
|
// console.log(`Message created: ${createdMessage.id}`);;
|
|
@@ -329,7 +334,8 @@ class ToothFairyAPI {
|
|
|
329
334
|
customerId = null,
|
|
330
335
|
providerId = null,
|
|
331
336
|
customerInfo = {},
|
|
332
|
-
onEvent
|
|
337
|
+
onEvent,
|
|
338
|
+
attachments = {}
|
|
333
339
|
) {
|
|
334
340
|
try {
|
|
335
341
|
// Use defaults for optional parameters
|
|
@@ -337,14 +343,17 @@ class ToothFairyAPI {
|
|
|
337
343
|
customerId ||
|
|
338
344
|
`cli-user-${
|
|
339
345
|
Math.abs(
|
|
340
|
-
message.split(
|
|
346
|
+
message.split('').reduce((a, b) => {
|
|
341
347
|
a = (a << 5) - a + b.charCodeAt(0);
|
|
342
348
|
return a & a;
|
|
343
349
|
}, 0)
|
|
344
350
|
) % 10000
|
|
345
351
|
}`;
|
|
346
|
-
phoneNumber = phoneNumber ||
|
|
347
|
-
providerId = providerId ||
|
|
352
|
+
phoneNumber = phoneNumber || '+1234567890';
|
|
353
|
+
providerId = providerId || 'default-sms-provider';
|
|
354
|
+
|
|
355
|
+
// Process file attachments if provided
|
|
356
|
+
const processedAttachments = await this._processAttachments(attachments);
|
|
348
357
|
|
|
349
358
|
// Create chat first
|
|
350
359
|
const chatData = {
|
|
@@ -372,8 +381,9 @@ class ToothFairyAPI {
|
|
|
372
381
|
const messageData = {
|
|
373
382
|
chatID: createdChat.id,
|
|
374
383
|
text: message,
|
|
375
|
-
role:
|
|
376
|
-
userID:
|
|
384
|
+
role: 'user',
|
|
385
|
+
userID: 'CLI',
|
|
386
|
+
...processedAttachments,
|
|
377
387
|
};
|
|
378
388
|
const createdMessage = await this.createMessage(messageData);
|
|
379
389
|
if (this.verbose) {
|
|
@@ -1676,6 +1686,92 @@ class ToothFairyAPI {
|
|
|
1676
1686
|
throw error;
|
|
1677
1687
|
}
|
|
1678
1688
|
}
|
|
1689
|
+
|
|
1690
|
+
/**
|
|
1691
|
+
* Process file attachments and upload them for message inclusion
|
|
1692
|
+
*
|
|
1693
|
+
* @param {Object} attachments - Attachment configuration
|
|
1694
|
+
* @param {string[]} attachments.images - Array of image file paths (max 1)
|
|
1695
|
+
* @param {string[]} attachments.audios - Array of audio file paths (max 1)
|
|
1696
|
+
* @param {string[]} attachments.videos - Array of video file paths (max 1)
|
|
1697
|
+
* @param {string[]} attachments.files - Array of document file paths (max 5)
|
|
1698
|
+
* @returns {Promise<Object>} - Processed attachment data for message creation
|
|
1699
|
+
*/
|
|
1700
|
+
async _processAttachments(attachments = {}) {
|
|
1701
|
+
const result = {};
|
|
1702
|
+
|
|
1703
|
+
if (!attachments || Object.keys(attachments).length === 0) {
|
|
1704
|
+
return result;
|
|
1705
|
+
}
|
|
1706
|
+
|
|
1707
|
+
try {
|
|
1708
|
+
// Validate attachment limits
|
|
1709
|
+
if (attachments.images && attachments.images.length > 1) {
|
|
1710
|
+
throw new Error('Maximum 1 image attachment allowed');
|
|
1711
|
+
}
|
|
1712
|
+
if (attachments.audios && attachments.audios.length > 1) {
|
|
1713
|
+
throw new Error('Maximum 1 audio attachment allowed');
|
|
1714
|
+
}
|
|
1715
|
+
if (attachments.videos && attachments.videos.length > 1) {
|
|
1716
|
+
throw new Error('Maximum 1 video attachment allowed');
|
|
1717
|
+
}
|
|
1718
|
+
if (attachments.files && attachments.files.length > 5) {
|
|
1719
|
+
throw new Error('Maximum 5 file attachments allowed');
|
|
1720
|
+
}
|
|
1721
|
+
|
|
1722
|
+
// Process images
|
|
1723
|
+
if (attachments.images && attachments.images.length > 0) {
|
|
1724
|
+
const imageResults = [];
|
|
1725
|
+
for (const imagePath of attachments.images) {
|
|
1726
|
+
const uploadResult = await this.uploadFile(imagePath, this.workspaceId);
|
|
1727
|
+
imageResults.push(uploadResult.filename);
|
|
1728
|
+
}
|
|
1729
|
+
result.images = imageResults;
|
|
1730
|
+
}
|
|
1731
|
+
|
|
1732
|
+
// Process audios
|
|
1733
|
+
if (attachments.audios && attachments.audios.length > 0) {
|
|
1734
|
+
const audioResults = [];
|
|
1735
|
+
for (const audioPath of attachments.audios) {
|
|
1736
|
+
const uploadResult = await this.uploadFile(audioPath, this.workspaceId);
|
|
1737
|
+
audioResults.push(uploadResult.filename);
|
|
1738
|
+
}
|
|
1739
|
+
result.audios = audioResults;
|
|
1740
|
+
}
|
|
1741
|
+
|
|
1742
|
+
// Process videos
|
|
1743
|
+
if (attachments.videos && attachments.videos.length > 0) {
|
|
1744
|
+
const videoResults = [];
|
|
1745
|
+
for (const videoPath of attachments.videos) {
|
|
1746
|
+
const uploadResult = await this.uploadFile(videoPath, this.workspaceId);
|
|
1747
|
+
videoResults.push(uploadResult.filename);
|
|
1748
|
+
}
|
|
1749
|
+
result.videos = videoResults;
|
|
1750
|
+
}
|
|
1751
|
+
|
|
1752
|
+
// Process files
|
|
1753
|
+
if (attachments.files && attachments.files.length > 0) {
|
|
1754
|
+
const fileResults = [];
|
|
1755
|
+
for (const filePath of attachments.files) {
|
|
1756
|
+
const uploadResult = await this.uploadFile(filePath, this.workspaceId);
|
|
1757
|
+
fileResults.push(uploadResult.filename);
|
|
1758
|
+
}
|
|
1759
|
+
result.files = fileResults;
|
|
1760
|
+
}
|
|
1761
|
+
|
|
1762
|
+
if (this.verbose) {
|
|
1763
|
+
const chalk = require('chalk');
|
|
1764
|
+
console.error(chalk.dim('\n--- Processed Attachments ---'));
|
|
1765
|
+
console.error(chalk.dim(`Result: ${JSON.stringify(result, null, 2)}`));
|
|
1766
|
+
console.error(chalk.dim('-----------------------------\n'));
|
|
1767
|
+
}
|
|
1768
|
+
|
|
1769
|
+
return result;
|
|
1770
|
+
} catch (error) {
|
|
1771
|
+
console.error(`Error processing attachments: ${error.message}`);
|
|
1772
|
+
throw error;
|
|
1773
|
+
}
|
|
1774
|
+
}
|
|
1679
1775
|
}
|
|
1680
1776
|
|
|
1681
1777
|
module.exports = ToothFairyAPI;
|