@toothfairyai/cli 1.1.0 ā 1.1.2
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 +868 -856
- package/package.json +1 -1
- package/src/api.js +573 -377
package/bin/toothfairy.js
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
-
const { Command } = require(
|
|
4
|
-
const chalk = require(
|
|
5
|
-
const ora = require(
|
|
6
|
-
const { table } = require(
|
|
7
|
-
require(
|
|
8
|
-
const path = require(
|
|
9
|
-
|
|
10
|
-
const ToothFairyAPI = require(
|
|
3
|
+
const { Command } = require('commander');
|
|
4
|
+
const chalk = require('chalk');
|
|
5
|
+
const ora = require('ora');
|
|
6
|
+
const { table } = require('table');
|
|
7
|
+
require('dotenv').config();
|
|
8
|
+
const path = require('path');
|
|
9
|
+
|
|
10
|
+
const ToothFairyAPI = require('../src/api');
|
|
11
11
|
const {
|
|
12
12
|
loadConfig,
|
|
13
13
|
saveConfig,
|
|
@@ -15,40 +15,40 @@ const {
|
|
|
15
15
|
getConfigPath,
|
|
16
16
|
validateConfiguration,
|
|
17
17
|
validateDocumentConfiguration,
|
|
18
|
-
} = require(
|
|
18
|
+
} = require('../src/config');
|
|
19
19
|
|
|
20
20
|
const program = new Command();
|
|
21
21
|
|
|
22
22
|
program
|
|
23
|
-
.name(
|
|
23
|
+
.name('toothfairy')
|
|
24
24
|
.description(
|
|
25
|
-
|
|
25
|
+
'ToothFairyAI CLI - Interact with ToothFairyAI agents via command line'
|
|
26
26
|
)
|
|
27
|
-
.version(
|
|
27
|
+
.version('1.0.0');
|
|
28
28
|
|
|
29
29
|
program
|
|
30
|
-
.option(
|
|
31
|
-
.option(
|
|
30
|
+
.option('-c, --config <path>', 'path to configuration file')
|
|
31
|
+
.option('-v, --verbose', 'enable verbose logging');
|
|
32
32
|
|
|
33
33
|
// Configure command
|
|
34
34
|
program
|
|
35
|
-
.command(
|
|
36
|
-
.description(
|
|
35
|
+
.command('configure')
|
|
36
|
+
.description('Configure ToothFairy CLI credentials and settings')
|
|
37
37
|
.option(
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
38
|
+
'--base-url <url>',
|
|
39
|
+
'ToothFairy API base URL',
|
|
40
|
+
'https://api.toothfairyai.com'
|
|
41
41
|
)
|
|
42
|
-
.option(
|
|
42
|
+
.option('--ai-url <url>', 'ToothFairyAI URL', 'https://ai.toothfairyai.com')
|
|
43
43
|
.option(
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
44
|
+
'--ai-stream-url <url>',
|
|
45
|
+
'ToothFairyAI Streaming URL',
|
|
46
|
+
'https://ais.toothfairyai.com'
|
|
47
47
|
)
|
|
48
|
-
.option(
|
|
49
|
-
.option(
|
|
50
|
-
.option(
|
|
51
|
-
.option(
|
|
48
|
+
.option('--api-key <key>', 'API key')
|
|
49
|
+
.option('--workspace-id <id>', 'Workspace ID')
|
|
50
|
+
.option('--user-id <id>', 'User ID')
|
|
51
|
+
.option('--config-path <path>', 'Path to save config file')
|
|
52
52
|
.action(async (options) => {
|
|
53
53
|
try {
|
|
54
54
|
// Load existing config if it exists, otherwise use defaults
|
|
@@ -57,44 +57,44 @@ program
|
|
|
57
57
|
existingConfig = loadConfig(options.configPath);
|
|
58
58
|
} catch (error) {
|
|
59
59
|
// No existing config, use empty defaults
|
|
60
|
-
existingConfig = new ToothFairyConfig(
|
|
60
|
+
existingConfig = new ToothFairyConfig('', '', '', '', '', '');
|
|
61
61
|
}
|
|
62
62
|
|
|
63
63
|
// Merge provided options with existing config
|
|
64
64
|
const config = new ToothFairyConfig(
|
|
65
65
|
options.baseUrl ||
|
|
66
66
|
existingConfig.baseUrl ||
|
|
67
|
-
|
|
68
|
-
options.aiUrl || existingConfig.aiUrl ||
|
|
67
|
+
'https://api.toothfairyai.com',
|
|
68
|
+
options.aiUrl || existingConfig.aiUrl || 'https://ai.toothfairyai.com',
|
|
69
69
|
options.aiStreamUrl ||
|
|
70
70
|
existingConfig.aiStreamUrl ||
|
|
71
|
-
|
|
72
|
-
options.apiKey || existingConfig.apiKey ||
|
|
73
|
-
options.workspaceId || existingConfig.workspaceId ||
|
|
74
|
-
options.userId || existingConfig.userId ||
|
|
71
|
+
'https://ais.toothfairyai.com',
|
|
72
|
+
options.apiKey || existingConfig.apiKey || '',
|
|
73
|
+
options.workspaceId || existingConfig.workspaceId || '',
|
|
74
|
+
options.userId || existingConfig.userId || ''
|
|
75
75
|
);
|
|
76
76
|
|
|
77
77
|
// Validate that at least API key and workspace ID are set
|
|
78
78
|
if (!config.apiKey || !config.workspaceId) {
|
|
79
79
|
const missing = [];
|
|
80
|
-
if (!config.apiKey) missing.push(
|
|
81
|
-
if (!config.workspaceId) missing.push(
|
|
80
|
+
if (!config.apiKey) missing.push('--api-key');
|
|
81
|
+
if (!config.workspaceId) missing.push('--workspace-id');
|
|
82
82
|
|
|
83
83
|
console.error(
|
|
84
84
|
chalk.red(
|
|
85
|
-
`Error: Missing required configuration: ${missing.join(
|
|
85
|
+
`Error: Missing required configuration: ${missing.join(' and ')}`
|
|
86
86
|
)
|
|
87
87
|
);
|
|
88
88
|
console.error(
|
|
89
89
|
chalk.yellow(
|
|
90
|
-
|
|
90
|
+
'These fields are required for first-time configuration or when not already set.'
|
|
91
91
|
)
|
|
92
92
|
);
|
|
93
93
|
process.exit(1);
|
|
94
94
|
}
|
|
95
95
|
|
|
96
96
|
saveConfig(config, options.configPath);
|
|
97
|
-
console.log(chalk.green(
|
|
97
|
+
console.log(chalk.green('Configuration saved successfully!'));
|
|
98
98
|
if (!options.configPath) {
|
|
99
99
|
console.log(`Config saved to: ${getConfigPath()}`);
|
|
100
100
|
}
|
|
@@ -106,20 +106,21 @@ program
|
|
|
106
106
|
|
|
107
107
|
// Send command
|
|
108
108
|
program
|
|
109
|
-
.command(
|
|
110
|
-
.description(
|
|
111
|
-
.argument(
|
|
112
|
-
.requiredOption(
|
|
113
|
-
.option(
|
|
114
|
-
.option(
|
|
115
|
-
.option(
|
|
116
|
-
.option(
|
|
117
|
-
.option(
|
|
118
|
-
.option(
|
|
119
|
-
.option(
|
|
120
|
-
.option(
|
|
121
|
-
.option(
|
|
122
|
-
.option(
|
|
109
|
+
.command('send')
|
|
110
|
+
.description('Send a message to a ToothFairyAI agent')
|
|
111
|
+
.argument('<message>', 'message to send')
|
|
112
|
+
.requiredOption('--agent-id <id>', 'Agent ID to send message to')
|
|
113
|
+
.option('--chat-id <id>', 'Chat ID to use existing conversation (optional)')
|
|
114
|
+
.option('--phone-number <number>', 'Phone number for SMS channel')
|
|
115
|
+
.option('--customer-id <id>', 'Customer ID')
|
|
116
|
+
.option('--provider-id <id>', 'SMS provider ID')
|
|
117
|
+
.option('--customer-info <json>', 'Customer info as JSON string')
|
|
118
|
+
.option('--image <path>', 'Path to image file (png, jpg, jpeg, gif, bmp, svg)')
|
|
119
|
+
.option('--audio <path>', 'Path to audio file (wav, mp3, aac, ogg, flac)')
|
|
120
|
+
.option('--video <path>', 'Path to video file (mp4, avi, mov, wmv, flv, webm)')
|
|
121
|
+
.option('--file <path...>', 'Path to document files (max 5)')
|
|
122
|
+
.option('-o, --output <format>', 'Output format (json|text)', 'text')
|
|
123
|
+
.option('-v, --verbose', 'Show detailed response information')
|
|
123
124
|
.action(async (message, options, command) => {
|
|
124
125
|
try {
|
|
125
126
|
const globalOptions = command.parent.opts();
|
|
@@ -170,41 +171,42 @@ program
|
|
|
170
171
|
options.customerId,
|
|
171
172
|
options.providerId,
|
|
172
173
|
customerInfo,
|
|
173
|
-
attachments
|
|
174
|
+
attachments,
|
|
175
|
+
options.chatId
|
|
174
176
|
);
|
|
175
177
|
|
|
176
178
|
spinner.stop();
|
|
177
179
|
|
|
178
|
-
if (options.output ===
|
|
180
|
+
if (options.output === 'json') {
|
|
179
181
|
console.log(JSON.stringify(response, null, 2));
|
|
180
182
|
} else {
|
|
181
183
|
const agentResp = response.agentResponse;
|
|
182
184
|
|
|
183
185
|
if (options.verbose) {
|
|
184
186
|
// Verbose mode: show all details
|
|
185
|
-
console.log(chalk.green.bold(
|
|
187
|
+
console.log(chalk.green.bold('Message sent successfully!'));
|
|
186
188
|
console.log();
|
|
187
189
|
|
|
188
190
|
const data = [
|
|
189
|
-
[
|
|
190
|
-
[
|
|
191
|
-
[
|
|
191
|
+
['Field', 'Value'],
|
|
192
|
+
['Chat ID', response.chatId],
|
|
193
|
+
['Message ID', response.messageId],
|
|
192
194
|
];
|
|
193
195
|
|
|
194
196
|
console.log(
|
|
195
197
|
table(data, {
|
|
196
198
|
header: {
|
|
197
|
-
alignment:
|
|
198
|
-
content:
|
|
199
|
+
alignment: 'center',
|
|
200
|
+
content: 'Response Details',
|
|
199
201
|
},
|
|
200
202
|
})
|
|
201
203
|
);
|
|
202
204
|
|
|
203
205
|
// Show full agent response
|
|
204
|
-
console.log(chalk.blue.bold(
|
|
205
|
-
console.log(
|
|
206
|
+
console.log(chalk.blue.bold('Agent Response (Full):'));
|
|
207
|
+
console.log('ā'.repeat(50));
|
|
206
208
|
console.log(JSON.stringify(agentResp, null, 2));
|
|
207
|
-
console.log(
|
|
209
|
+
console.log('ā'.repeat(50));
|
|
208
210
|
} else {
|
|
209
211
|
// Default mode: show only the clean agent text
|
|
210
212
|
if (agentResp.contents && agentResp.contents.content) {
|
|
@@ -217,7 +219,7 @@ program
|
|
|
217
219
|
// Fallback if no recognizable text format
|
|
218
220
|
console.log(
|
|
219
221
|
chalk.yellow(
|
|
220
|
-
|
|
222
|
+
'No text response found. Use --verbose for full details.'
|
|
221
223
|
)
|
|
222
224
|
);
|
|
223
225
|
}
|
|
@@ -231,23 +233,24 @@ program
|
|
|
231
233
|
|
|
232
234
|
// Send Stream command
|
|
233
235
|
program
|
|
234
|
-
.command(
|
|
236
|
+
.command('send-stream')
|
|
235
237
|
.description(
|
|
236
|
-
|
|
238
|
+
'Send a message to a ToothFairyAI agent with real-time streaming response'
|
|
237
239
|
)
|
|
238
|
-
.argument(
|
|
239
|
-
.requiredOption(
|
|
240
|
-
.option(
|
|
241
|
-
.option(
|
|
242
|
-
.option(
|
|
243
|
-
.option(
|
|
240
|
+
.argument('<message>', 'message to send')
|
|
241
|
+
.requiredOption('--agent-id <id>', 'Agent ID to send message to')
|
|
242
|
+
.option('--chat-id <id>', 'Chat ID to use existing conversation (optional)')
|
|
243
|
+
.option('--phone-number <number>', 'Phone number for SMS channel')
|
|
244
|
+
.option('--customer-id <id>', 'Customer ID')
|
|
245
|
+
.option('--provider-id <id>', 'SMS provider ID')
|
|
246
|
+
.option('--customer-info <json>', 'Customer info as JSON string')
|
|
244
247
|
.option('--image <path>', 'Path to image file (PNG, max 1)')
|
|
245
248
|
.option('--audio <path>', 'Path to audio file (WAV, max 1)')
|
|
246
249
|
.option('--video <path>', 'Path to video file (MP4, max 1)')
|
|
247
250
|
.option('--file <path>', 'Path to file (max 5, can be used multiple times)', (value, previous) => previous.concat([value]), [])
|
|
248
|
-
.option(
|
|
249
|
-
.option(
|
|
250
|
-
.option(
|
|
251
|
+
.option('-o, --output <format>', 'Output format (json|text)', 'text')
|
|
252
|
+
.option('-v, --verbose', 'Show detailed streaming information')
|
|
253
|
+
.option('--show-progress', 'Show agent processing status updates')
|
|
251
254
|
.action(async (message, options, command) => {
|
|
252
255
|
/*
|
|
253
256
|
STREAMING BEHAVIOR EXPLAINED:
|
|
@@ -289,7 +292,7 @@ program
|
|
|
289
292
|
try {
|
|
290
293
|
customerInfo = JSON.parse(options.customerInfo);
|
|
291
294
|
} catch (error) {
|
|
292
|
-
console.error(chalk.red(
|
|
295
|
+
console.error(chalk.red('Invalid JSON in customer-info'));
|
|
293
296
|
process.exit(1);
|
|
294
297
|
}
|
|
295
298
|
}
|
|
@@ -316,7 +319,7 @@ program
|
|
|
316
319
|
console.log();
|
|
317
320
|
|
|
318
321
|
// Initialize variables for streaming
|
|
319
|
-
let currentText =
|
|
322
|
+
let currentText = '';
|
|
320
323
|
let finalResponse = null;
|
|
321
324
|
let processingStatus = null;
|
|
322
325
|
let lastUpdateTime = 0;
|
|
@@ -324,52 +327,52 @@ program
|
|
|
324
327
|
|
|
325
328
|
const mapStateWithLabel = (state) => {
|
|
326
329
|
switch (state) {
|
|
327
|
-
case
|
|
328
|
-
return
|
|
329
|
-
case
|
|
330
|
-
return
|
|
331
|
-
case
|
|
332
|
-
return
|
|
333
|
-
case
|
|
334
|
-
return
|
|
335
|
-
case
|
|
336
|
-
return
|
|
337
|
-
case
|
|
338
|
-
return
|
|
339
|
-
case
|
|
340
|
-
return
|
|
341
|
-
case
|
|
342
|
-
return
|
|
343
|
-
case
|
|
344
|
-
return
|
|
345
|
-
case
|
|
346
|
-
return
|
|
347
|
-
case
|
|
348
|
-
return
|
|
349
|
-
case
|
|
350
|
-
return
|
|
351
|
-
case
|
|
352
|
-
return
|
|
353
|
-
case
|
|
354
|
-
return
|
|
355
|
-
case
|
|
356
|
-
return
|
|
357
|
-
case
|
|
358
|
-
return
|
|
359
|
-
case
|
|
360
|
-
return
|
|
361
|
-
case
|
|
362
|
-
return
|
|
363
|
-
case
|
|
364
|
-
return
|
|
365
|
-
case
|
|
366
|
-
return
|
|
330
|
+
case 'data_processing_completed':
|
|
331
|
+
return 'š **Retrieving data**';
|
|
332
|
+
case 'tools_processing_completed':
|
|
333
|
+
return 'š ļø **Choosing tools**';
|
|
334
|
+
case 'replying':
|
|
335
|
+
return 'š§ **Responding**';
|
|
336
|
+
case 'main_generation_completed':
|
|
337
|
+
return '⨠**Generation completed**';
|
|
338
|
+
case 'memory_updated':
|
|
339
|
+
return 'š¾ Memory updated';
|
|
340
|
+
case 'updating_memory':
|
|
341
|
+
return 'š¾ Updating memory...';
|
|
342
|
+
case 'init':
|
|
343
|
+
return 'š Initializing...';
|
|
344
|
+
case 'initial_setup_completed':
|
|
345
|
+
return 'ā
Setup completed';
|
|
346
|
+
case 'image_analysis_in_progress':
|
|
347
|
+
return 'š¼ļø Analyzing image...';
|
|
348
|
+
case 'video_analysis_in_progress':
|
|
349
|
+
return 'š„ Analyzing video...';
|
|
350
|
+
case 'audio_analysis_in_progress':
|
|
351
|
+
return 'šµ Analyzing audio...';
|
|
352
|
+
case 'image_generation_in_progress':
|
|
353
|
+
return 'šØ Generating image...';
|
|
354
|
+
case 'video_generation_in_progress':
|
|
355
|
+
return 'š¬ Generating video...';
|
|
356
|
+
case '3D_model_generation_in_progress':
|
|
357
|
+
return 'šļø Creating 3D model...';
|
|
358
|
+
case 'code_generation_in_progress':
|
|
359
|
+
return 'š» Generating code...';
|
|
360
|
+
case 'code_execution_in_progress':
|
|
361
|
+
return 'ā” Executing code...';
|
|
362
|
+
case 'internet_search_in_progress':
|
|
363
|
+
return 'š Searching internet...';
|
|
364
|
+
case 'planning_in_progress':
|
|
365
|
+
return 'šŗļø Planning response...';
|
|
366
|
+
case 'handed_off_to_human':
|
|
367
|
+
return 'š¤ Handed off to human';
|
|
368
|
+
case 'completed':
|
|
369
|
+
return 'š Completed';
|
|
367
370
|
default:
|
|
368
371
|
return `š ${state}`;
|
|
369
372
|
}
|
|
370
373
|
};
|
|
371
374
|
|
|
372
|
-
if (options.output ===
|
|
375
|
+
if (options.output === 'json') {
|
|
373
376
|
// JSON mode: collect all events and output at the end
|
|
374
377
|
const allEvents = [];
|
|
375
378
|
|
|
@@ -383,15 +386,17 @@ program
|
|
|
383
386
|
(eventType, eventData) => {
|
|
384
387
|
allEvents.push({ event_type: eventType, event_data: eventData });
|
|
385
388
|
|
|
386
|
-
if (eventType ===
|
|
389
|
+
if (eventType === 'error') {
|
|
387
390
|
console.error(
|
|
388
391
|
chalk.red(
|
|
389
|
-
`Streaming error: ${eventData.message ||
|
|
392
|
+
`Streaming error: ${eventData.message || 'Unknown error'}`
|
|
390
393
|
)
|
|
391
394
|
);
|
|
392
395
|
}
|
|
393
396
|
},
|
|
394
|
-
attachments
|
|
397
|
+
attachments,
|
|
398
|
+
options.showProgress,
|
|
399
|
+
options.chatId
|
|
395
400
|
);
|
|
396
401
|
|
|
397
402
|
console.log(JSON.stringify(allEvents, null, 2));
|
|
@@ -400,14 +405,14 @@ program
|
|
|
400
405
|
let currentSpinner = null;
|
|
401
406
|
|
|
402
407
|
// Function to update display with status filtering
|
|
403
|
-
const updateDisplay = (text, agentStatus, type =
|
|
408
|
+
const updateDisplay = (text, agentStatus, type = 'response') => {
|
|
404
409
|
if (currentSpinner) {
|
|
405
410
|
currentSpinner.stop();
|
|
406
411
|
currentSpinner = null;
|
|
407
412
|
}
|
|
408
413
|
|
|
409
414
|
// Only show text when agent is actually replying
|
|
410
|
-
if (text && type ===
|
|
415
|
+
if (text && type === 'response' && agentStatus === 'replying') {
|
|
411
416
|
const trimmedText = text.trim();
|
|
412
417
|
const now = Date.now();
|
|
413
418
|
|
|
@@ -420,7 +425,7 @@ program
|
|
|
420
425
|
) {
|
|
421
426
|
if (!hasStartedResponse) {
|
|
422
427
|
// First time showing response - print header on new line
|
|
423
|
-
console.log(chalk.green(
|
|
428
|
+
console.log(chalk.green('š§ Responding'));
|
|
424
429
|
hasStartedResponse = true;
|
|
425
430
|
}
|
|
426
431
|
// Stream new text content on new line
|
|
@@ -453,25 +458,30 @@ program
|
|
|
453
458
|
);
|
|
454
459
|
}
|
|
455
460
|
|
|
461
|
+
// Skip processing sse_event types to avoid duplicates - they're for raw debugging only
|
|
462
|
+
if (eventType === 'sse_event') {
|
|
463
|
+
return;
|
|
464
|
+
}
|
|
465
|
+
|
|
456
466
|
// Handle connection status events
|
|
457
|
-
if (eventData.status ===
|
|
467
|
+
if (eventData.status === 'connected') {
|
|
458
468
|
if (options.showProgress) {
|
|
459
|
-
console.log(chalk.green(
|
|
469
|
+
console.log(chalk.green('š Connected to streaming server'));
|
|
460
470
|
}
|
|
461
471
|
return;
|
|
462
472
|
}
|
|
463
473
|
|
|
464
|
-
if (eventData.status ===
|
|
474
|
+
if (eventData.status === 'complete') {
|
|
465
475
|
if (options.showProgress) {
|
|
466
476
|
console.log(
|
|
467
|
-
chalk.green(
|
|
477
|
+
chalk.green('\nš Stream completed successfully!')
|
|
468
478
|
);
|
|
469
479
|
}
|
|
470
480
|
return;
|
|
471
481
|
}
|
|
472
482
|
|
|
473
483
|
// Handle message events
|
|
474
|
-
if (eventData.type ===
|
|
484
|
+
if (eventData.type === 'message') {
|
|
475
485
|
let metadata = {};
|
|
476
486
|
let agentStatus = null;
|
|
477
487
|
|
|
@@ -498,12 +508,12 @@ program
|
|
|
498
508
|
}
|
|
499
509
|
|
|
500
510
|
// Handle progressive text streaming
|
|
501
|
-
if (eventData.text && agentStatus ===
|
|
502
|
-
updateDisplay(eventData.text, agentStatus,
|
|
511
|
+
if (eventData.text && agentStatus === 'replying') {
|
|
512
|
+
updateDisplay(eventData.text, agentStatus, 'response');
|
|
503
513
|
}
|
|
504
514
|
|
|
505
515
|
// Handle fulfilled status (final response)
|
|
506
|
-
if (eventData.status ===
|
|
516
|
+
if (eventData.status === 'fulfilled') {
|
|
507
517
|
finalResponse = eventData;
|
|
508
518
|
if (currentText) {
|
|
509
519
|
// Clean final display with magic wand emoji
|
|
@@ -511,7 +521,7 @@ program
|
|
|
511
521
|
currentSpinner.stop();
|
|
512
522
|
currentSpinner = null;
|
|
513
523
|
}
|
|
514
|
-
console.log(chalk.blue(
|
|
524
|
+
console.log(chalk.blue('šŖ Response complete'));
|
|
515
525
|
}
|
|
516
526
|
}
|
|
517
527
|
|
|
@@ -522,7 +532,7 @@ program
|
|
|
522
532
|
) {
|
|
523
533
|
// These are attachment events - could show notification if needed
|
|
524
534
|
if (options.verbose) {
|
|
525
|
-
console.log(chalk.dim(
|
|
535
|
+
console.log(chalk.dim('\nš Attachments processed'));
|
|
526
536
|
}
|
|
527
537
|
}
|
|
528
538
|
|
|
@@ -530,15 +540,15 @@ program
|
|
|
530
540
|
// Function execution metadata
|
|
531
541
|
if (options.verbose) {
|
|
532
542
|
console.log(
|
|
533
|
-
chalk.dim(
|
|
543
|
+
chalk.dim('\nāļø Function execution metadata received')
|
|
534
544
|
);
|
|
535
545
|
}
|
|
536
546
|
}
|
|
537
547
|
}
|
|
538
548
|
|
|
539
549
|
// Handle errors
|
|
540
|
-
if (eventType ===
|
|
541
|
-
const errorMsg = eventData.message ||
|
|
550
|
+
if (eventType === 'error') {
|
|
551
|
+
const errorMsg = eventData.message || 'Unknown streaming error';
|
|
542
552
|
if (currentSpinner) {
|
|
543
553
|
currentSpinner.stop();
|
|
544
554
|
}
|
|
@@ -546,7 +556,9 @@ program
|
|
|
546
556
|
process.exit(1);
|
|
547
557
|
}
|
|
548
558
|
},
|
|
549
|
-
attachments
|
|
559
|
+
attachments,
|
|
560
|
+
options.showProgress,
|
|
561
|
+
options.chatId
|
|
550
562
|
);
|
|
551
563
|
|
|
552
564
|
// Clean up spinner after streaming completes
|
|
@@ -558,48 +570,48 @@ program
|
|
|
558
570
|
|
|
559
571
|
if (options.verbose && finalResponse) {
|
|
560
572
|
// Show final response metadata in verbose mode
|
|
561
|
-
console.log(chalk.cyan.bold(
|
|
562
|
-
console.log(
|
|
573
|
+
console.log(chalk.cyan.bold('\nš Final Response Metadata'));
|
|
574
|
+
console.log('ā'.repeat(50));
|
|
563
575
|
|
|
564
576
|
// Parse and display metadata from the final response
|
|
565
577
|
if (finalResponse.metadata) {
|
|
566
578
|
try {
|
|
567
579
|
const metadata = JSON.parse(finalResponse.metadata);
|
|
568
580
|
for (const [key, value] of Object.entries(metadata)) {
|
|
569
|
-
if (key ===
|
|
581
|
+
if (key === 'agent_processing_status') {
|
|
570
582
|
console.log(chalk.cyan(`${key}:`), chalk.green(value));
|
|
571
|
-
} else if (key ===
|
|
583
|
+
} else if (key === 'duration') {
|
|
572
584
|
console.log(
|
|
573
585
|
chalk.cyan(`${key}:`),
|
|
574
586
|
chalk.yellow(`${value}s`)
|
|
575
587
|
);
|
|
576
|
-
} else if (key ===
|
|
588
|
+
} else if (key === 'sources' && Array.isArray(value)) {
|
|
577
589
|
console.log(
|
|
578
590
|
chalk.cyan(`${key}:`),
|
|
579
|
-
value.length > 0 ? value.join(
|
|
591
|
+
value.length > 0 ? value.join(', ') : 'None'
|
|
580
592
|
);
|
|
581
593
|
} else {
|
|
582
594
|
console.log(chalk.cyan(`${key}:`), String(value));
|
|
583
595
|
}
|
|
584
596
|
}
|
|
585
597
|
} catch (e) {
|
|
586
|
-
console.log(chalk.red(
|
|
598
|
+
console.log(chalk.red('Could not parse metadata'));
|
|
587
599
|
}
|
|
588
600
|
}
|
|
589
601
|
|
|
590
602
|
// Show additional response fields
|
|
591
603
|
if (finalResponse.message_id) {
|
|
592
|
-
console.log(chalk.cyan(
|
|
604
|
+
console.log(chalk.cyan('message_id:'), finalResponse.message_id);
|
|
593
605
|
}
|
|
594
606
|
if (finalResponse.t_text_summary) {
|
|
595
|
-
console.log(chalk.cyan(
|
|
607
|
+
console.log(chalk.cyan('summary:'), finalResponse.t_text_summary);
|
|
596
608
|
}
|
|
597
609
|
|
|
598
|
-
console.log(
|
|
610
|
+
console.log('ā'.repeat(50));
|
|
599
611
|
}
|
|
600
612
|
|
|
601
613
|
if (!currentText) {
|
|
602
|
-
console.log(chalk.yellow(
|
|
614
|
+
console.log(chalk.yellow('No text response received from agent.'));
|
|
603
615
|
}
|
|
604
616
|
} catch (streamError) {
|
|
605
617
|
if (currentSpinner) {
|
|
@@ -616,22 +628,22 @@ program
|
|
|
616
628
|
|
|
617
629
|
// Search command
|
|
618
630
|
program
|
|
619
|
-
.command(
|
|
620
|
-
.description(
|
|
621
|
-
.argument(
|
|
631
|
+
.command('search')
|
|
632
|
+
.description('Search for documents in the knowledge hub')
|
|
633
|
+
.argument('<query>', 'search query text')
|
|
622
634
|
.option(
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
635
|
+
'-k, --top-k <number>',
|
|
636
|
+
'Number of documents to retrieve (1-50)',
|
|
637
|
+
'10'
|
|
626
638
|
)
|
|
627
639
|
.option(
|
|
628
|
-
|
|
629
|
-
|
|
640
|
+
'--status <status>',
|
|
641
|
+
'Filter by document status (published|suspended)'
|
|
630
642
|
)
|
|
631
|
-
.option(
|
|
632
|
-
.option(
|
|
633
|
-
.option(
|
|
634
|
-
.option(
|
|
643
|
+
.option('--document-id <id>', 'Search within specific document ID')
|
|
644
|
+
.option('--topics <topics>', 'Comma-separated topic IDs to filter by')
|
|
645
|
+
.option('-o, --output <format>', 'Output format (json|text)', 'text')
|
|
646
|
+
.option('-v, --verbose', 'Show detailed search information')
|
|
635
647
|
.action(async (query, options, command) => {
|
|
636
648
|
try {
|
|
637
649
|
const globalOptions = command.parent.opts();
|
|
@@ -651,7 +663,7 @@ program
|
|
|
651
663
|
const topK = parseInt(options.topK);
|
|
652
664
|
if (isNaN(topK) || topK < 1 || topK > 50) {
|
|
653
665
|
console.error(
|
|
654
|
-
chalk.red(
|
|
666
|
+
chalk.red('Error: --top-k must be a number between 1 and 50')
|
|
655
667
|
);
|
|
656
668
|
process.exit(1);
|
|
657
669
|
}
|
|
@@ -659,7 +671,7 @@ program
|
|
|
659
671
|
// Build metadata filters
|
|
660
672
|
const metadata = {};
|
|
661
673
|
if (options.status) {
|
|
662
|
-
if (![
|
|
674
|
+
if (!['published', 'suspended'].includes(options.status)) {
|
|
663
675
|
console.error(
|
|
664
676
|
chalk.red(
|
|
665
677
|
'Error: --status must be either "published" or "suspended"'
|
|
@@ -674,7 +686,7 @@ program
|
|
|
674
686
|
}
|
|
675
687
|
if (options.topics) {
|
|
676
688
|
const topicList = options.topics
|
|
677
|
-
.split(
|
|
689
|
+
.split(',')
|
|
678
690
|
.map((t) => t.trim())
|
|
679
691
|
.filter((t) => t);
|
|
680
692
|
if (topicList.length > 0) {
|
|
@@ -682,7 +694,7 @@ program
|
|
|
682
694
|
}
|
|
683
695
|
}
|
|
684
696
|
|
|
685
|
-
const spinner = ora(
|
|
697
|
+
const spinner = ora('Searching knowledge hub...').start();
|
|
686
698
|
|
|
687
699
|
const results = await api.searchDocuments(
|
|
688
700
|
query,
|
|
@@ -692,7 +704,7 @@ program
|
|
|
692
704
|
|
|
693
705
|
spinner.stop();
|
|
694
706
|
|
|
695
|
-
if (options.output ===
|
|
707
|
+
if (options.output === 'json') {
|
|
696
708
|
console.log(JSON.stringify(results, null, 2));
|
|
697
709
|
} else {
|
|
698
710
|
// Handle different response formats - results might be array or dict
|
|
@@ -701,22 +713,22 @@ program
|
|
|
701
713
|
: results.results || [];
|
|
702
714
|
|
|
703
715
|
if (!documents || documents.length === 0) {
|
|
704
|
-
console.log(chalk.yellow(
|
|
716
|
+
console.log(chalk.yellow('No documents found for your query'));
|
|
705
717
|
return;
|
|
706
718
|
}
|
|
707
719
|
|
|
708
720
|
console.log(chalk.green.bold(`Found ${documents.length} document(s)`));
|
|
709
|
-
console.log(
|
|
721
|
+
console.log('='.repeat(50));
|
|
710
722
|
|
|
711
723
|
documents.forEach((doc) => {
|
|
712
724
|
const score = doc.cosinesim || 0;
|
|
713
|
-
const docId = doc.doc_id || doc.chunk_id ||
|
|
725
|
+
const docId = doc.doc_id || doc.chunk_id || 'N/A';
|
|
714
726
|
|
|
715
727
|
// Extract text content directly from document
|
|
716
|
-
const textContent = doc.raw_text ||
|
|
717
|
-
const docStatus = doc.status ||
|
|
728
|
+
const textContent = doc.raw_text || 'No content available';
|
|
729
|
+
const docStatus = doc.status || 'unknown';
|
|
718
730
|
const docTopics = doc.topics || [];
|
|
719
|
-
const docTitle = doc.title ||
|
|
731
|
+
const docTitle = doc.title || 'Untitled';
|
|
720
732
|
|
|
721
733
|
console.log(
|
|
722
734
|
chalk.cyan.bold(`\n${docTitle}`),
|
|
@@ -726,16 +738,16 @@ program
|
|
|
726
738
|
if (options.verbose) {
|
|
727
739
|
// Verbose mode: show all details
|
|
728
740
|
const data = [
|
|
729
|
-
[
|
|
730
|
-
[
|
|
731
|
-
[
|
|
732
|
-
[
|
|
733
|
-
[
|
|
734
|
-
[
|
|
741
|
+
['Field', 'Value'],
|
|
742
|
+
['Document ID', docId],
|
|
743
|
+
['Title', docTitle],
|
|
744
|
+
['Relevance Score', score.toFixed(4)],
|
|
745
|
+
['Status', docStatus],
|
|
746
|
+
['Topics', docTopics.length > 0 ? docTopics.join(', ') : 'None'],
|
|
735
747
|
[
|
|
736
|
-
|
|
748
|
+
'Content Preview',
|
|
737
749
|
textContent.length > 200
|
|
738
|
-
? textContent.substring(0, 200) +
|
|
750
|
+
? textContent.substring(0, 200) + '...'
|
|
739
751
|
: textContent,
|
|
740
752
|
],
|
|
741
753
|
];
|
|
@@ -743,13 +755,13 @@ program
|
|
|
743
755
|
console.log(table(data));
|
|
744
756
|
} else {
|
|
745
757
|
// Default mode: show clean content
|
|
746
|
-
console.log(
|
|
758
|
+
console.log('ā'.repeat(50));
|
|
747
759
|
const displayContent =
|
|
748
760
|
textContent.length > 500
|
|
749
|
-
? textContent.substring(0, 500) +
|
|
761
|
+
? textContent.substring(0, 500) + '...'
|
|
750
762
|
: textContent;
|
|
751
763
|
console.log(displayContent);
|
|
752
|
-
console.log(
|
|
764
|
+
console.log('ā'.repeat(50));
|
|
753
765
|
}
|
|
754
766
|
});
|
|
755
767
|
}
|
|
@@ -761,9 +773,9 @@ program
|
|
|
761
773
|
|
|
762
774
|
// Chats command
|
|
763
775
|
program
|
|
764
|
-
.command(
|
|
765
|
-
.description(
|
|
766
|
-
.option(
|
|
776
|
+
.command('chats')
|
|
777
|
+
.description('List all chats in the workspace')
|
|
778
|
+
.option('-o, --output <format>', 'Output format (json|text)', 'text')
|
|
767
779
|
.action(async (options, command) => {
|
|
768
780
|
try {
|
|
769
781
|
const globalOptions = command.parent.opts();
|
|
@@ -779,18 +791,18 @@ program
|
|
|
779
791
|
globalOptions.verbose || options.verbose
|
|
780
792
|
);
|
|
781
793
|
|
|
782
|
-
const spinner = ora(
|
|
794
|
+
const spinner = ora('Fetching chats...').start();
|
|
783
795
|
const chatsData = await api.getAllChats();
|
|
784
796
|
spinner.stop();
|
|
785
797
|
|
|
786
|
-
if (options.output ===
|
|
798
|
+
if (options.output === 'json') {
|
|
787
799
|
console.log(JSON.stringify(chatsData, null, 2));
|
|
788
800
|
} else {
|
|
789
801
|
if (
|
|
790
802
|
!chatsData ||
|
|
791
803
|
(Array.isArray(chatsData) && chatsData.length === 0)
|
|
792
804
|
) {
|
|
793
|
-
console.log(chalk.yellow(
|
|
805
|
+
console.log(chalk.yellow('No chats found'));
|
|
794
806
|
return;
|
|
795
807
|
}
|
|
796
808
|
|
|
@@ -798,22 +810,22 @@ program
|
|
|
798
810
|
? chatsData
|
|
799
811
|
: chatsData.items || [];
|
|
800
812
|
|
|
801
|
-
const data = [[
|
|
813
|
+
const data = [['Chat ID', 'Name', 'Customer ID', 'Created']];
|
|
802
814
|
|
|
803
815
|
chatList.forEach((chat) => {
|
|
804
816
|
data.push([
|
|
805
|
-
chat.id ||
|
|
806
|
-
chat.name ||
|
|
807
|
-
chat.customerId ||
|
|
808
|
-
chat.createdAt ||
|
|
817
|
+
chat.id || 'N/A',
|
|
818
|
+
chat.name || 'N/A',
|
|
819
|
+
chat.customerId || 'N/A',
|
|
820
|
+
chat.createdAt || 'N/A',
|
|
809
821
|
]);
|
|
810
822
|
});
|
|
811
823
|
|
|
812
824
|
console.log(
|
|
813
825
|
table(data, {
|
|
814
826
|
header: {
|
|
815
|
-
alignment:
|
|
816
|
-
content:
|
|
827
|
+
alignment: 'center',
|
|
828
|
+
content: 'Workspace Chats',
|
|
817
829
|
},
|
|
818
830
|
})
|
|
819
831
|
);
|
|
@@ -826,10 +838,10 @@ program
|
|
|
826
838
|
|
|
827
839
|
// Chat command (get specific chat)
|
|
828
840
|
program
|
|
829
|
-
.command(
|
|
830
|
-
.description(
|
|
831
|
-
.argument(
|
|
832
|
-
.option(
|
|
841
|
+
.command('chat')
|
|
842
|
+
.description('Get details of a specific chat')
|
|
843
|
+
.argument('<chat-id>', 'Chat ID to retrieve')
|
|
844
|
+
.option('-o, --output <format>', 'Output format (json|text)', 'text')
|
|
833
845
|
.action(async (chatId, options, command) => {
|
|
834
846
|
try {
|
|
835
847
|
const globalOptions = command.parent.opts();
|
|
@@ -849,17 +861,17 @@ program
|
|
|
849
861
|
const chatData = await api.getChat(chatId);
|
|
850
862
|
spinner.stop();
|
|
851
863
|
|
|
852
|
-
if (options.output ===
|
|
864
|
+
if (options.output === 'json') {
|
|
853
865
|
console.log(JSON.stringify(chatData, null, 2));
|
|
854
866
|
} else {
|
|
855
|
-
console.log(chalk.green.bold(
|
|
867
|
+
console.log(chalk.green.bold('Chat Details'));
|
|
856
868
|
console.log();
|
|
857
869
|
|
|
858
|
-
const data = [[
|
|
870
|
+
const data = [['Field', 'Value']];
|
|
859
871
|
|
|
860
872
|
Object.entries(chatData).forEach(([key, value]) => {
|
|
861
873
|
let displayValue = value;
|
|
862
|
-
if (typeof value ===
|
|
874
|
+
if (typeof value === 'object' && value !== null) {
|
|
863
875
|
displayValue = JSON.stringify(value, null, 2);
|
|
864
876
|
}
|
|
865
877
|
data.push([key, String(displayValue)]);
|
|
@@ -932,32 +944,32 @@ program
|
|
|
932
944
|
|
|
933
945
|
// Config show command
|
|
934
946
|
program
|
|
935
|
-
.command(
|
|
936
|
-
.description(
|
|
947
|
+
.command('config-show')
|
|
948
|
+
.description('Show current configuration')
|
|
937
949
|
.action(async (options, command) => {
|
|
938
950
|
try {
|
|
939
951
|
const globalOptions = command.parent.opts();
|
|
940
952
|
const config = loadConfig(globalOptions.config);
|
|
941
953
|
|
|
942
954
|
const data = [
|
|
943
|
-
[
|
|
944
|
-
[
|
|
945
|
-
[
|
|
955
|
+
['Setting', 'Value'],
|
|
956
|
+
['Base URL', config.baseUrl],
|
|
957
|
+
['AI URL', config.aiUrl],
|
|
946
958
|
[
|
|
947
|
-
|
|
959
|
+
'API Key',
|
|
948
960
|
config.apiKey
|
|
949
|
-
? `${
|
|
950
|
-
:
|
|
961
|
+
? `${'*'.repeat(20)}...${config.apiKey.slice(-4)}`
|
|
962
|
+
: 'Not set',
|
|
951
963
|
],
|
|
952
|
-
[
|
|
953
|
-
[
|
|
964
|
+
['Workspace ID', config.workspaceId],
|
|
965
|
+
['User ID', config.userId ? config.userId : 'Not set'],
|
|
954
966
|
];
|
|
955
967
|
|
|
956
968
|
console.log(
|
|
957
969
|
table(data, {
|
|
958
970
|
header: {
|
|
959
|
-
alignment:
|
|
960
|
-
content:
|
|
971
|
+
alignment: 'center',
|
|
972
|
+
content: 'Current Configuration',
|
|
961
973
|
},
|
|
962
974
|
})
|
|
963
975
|
);
|
|
@@ -969,22 +981,22 @@ program
|
|
|
969
981
|
|
|
970
982
|
// Create document command
|
|
971
983
|
program
|
|
972
|
-
.command(
|
|
984
|
+
.command('create-doc')
|
|
973
985
|
.description(
|
|
974
|
-
|
|
986
|
+
'Create a document from a file path or URL with automatic type detection'
|
|
975
987
|
)
|
|
976
|
-
.argument(
|
|
988
|
+
.argument('<file-path-or-url>', 'Path to file or URL to create document from')
|
|
977
989
|
.option(
|
|
978
|
-
|
|
979
|
-
|
|
990
|
+
'--user-id <id>',
|
|
991
|
+
'User ID (optional, uses configured value if not provided)'
|
|
980
992
|
)
|
|
981
|
-
.option(
|
|
982
|
-
.option(
|
|
983
|
-
.option(
|
|
984
|
-
.option(
|
|
985
|
-
.option(
|
|
986
|
-
.option(
|
|
987
|
-
.option(
|
|
993
|
+
.option('--title <title>', 'Document title (defaults to filename or URL)')
|
|
994
|
+
.option('--folder-id <id>', 'Folder ID (defaults to \'mrcRoot\')', 'mrcRoot')
|
|
995
|
+
.option('--topics <topics>', 'Comma-separated topic IDs')
|
|
996
|
+
.option('--status <status>', 'Document status (draft|published)', 'published')
|
|
997
|
+
.option('--scope <scope>', 'Document scope')
|
|
998
|
+
.option('-o, --output <format>', 'Output format (json|text)', 'text')
|
|
999
|
+
.option('-v, --verbose', 'Show detailed creation information')
|
|
988
1000
|
.action(async (filePathOrUrl, options, command) => {
|
|
989
1001
|
try {
|
|
990
1002
|
const globalOptions = command.parent.opts();
|
|
@@ -1004,13 +1016,13 @@ program
|
|
|
1004
1016
|
let topics = [];
|
|
1005
1017
|
if (options.topics) {
|
|
1006
1018
|
topics = options.topics
|
|
1007
|
-
.split(
|
|
1019
|
+
.split(',')
|
|
1008
1020
|
.map((t) => t.trim())
|
|
1009
1021
|
.filter((t) => t);
|
|
1010
1022
|
}
|
|
1011
1023
|
|
|
1012
1024
|
// Validate status
|
|
1013
|
-
if (options.status && ![
|
|
1025
|
+
if (options.status && !['draft', 'published'].includes(options.status)) {
|
|
1014
1026
|
console.error(
|
|
1015
1027
|
chalk.red('Error: --status must be either "draft" or "published"')
|
|
1016
1028
|
);
|
|
@@ -1019,10 +1031,10 @@ program
|
|
|
1019
1031
|
|
|
1020
1032
|
console.log(chalk.cyan(`Creating document from ${filePathOrUrl}...`));
|
|
1021
1033
|
if (options.verbose) {
|
|
1022
|
-
console.log(chalk.dim(`Title: ${options.title ||
|
|
1034
|
+
console.log(chalk.dim(`Title: ${options.title || 'Auto-detected'}`));
|
|
1023
1035
|
console.log(chalk.dim(`Folder ID: ${options.folderId}`));
|
|
1024
1036
|
console.log(
|
|
1025
|
-
chalk.dim(`Topics: ${topics.length > 0 ? topics.join(
|
|
1037
|
+
chalk.dim(`Topics: ${topics.length > 0 ? topics.join(', ') : 'None'}`)
|
|
1026
1038
|
);
|
|
1027
1039
|
console.log(chalk.dim(`Status: ${options.status}`));
|
|
1028
1040
|
if (options.scope) {
|
|
@@ -1030,7 +1042,7 @@ program
|
|
|
1030
1042
|
}
|
|
1031
1043
|
}
|
|
1032
1044
|
|
|
1033
|
-
const spinner = ora(
|
|
1045
|
+
const spinner = ora('Creating document...').start();
|
|
1034
1046
|
|
|
1035
1047
|
// Use provided userId or fall back to configured userId
|
|
1036
1048
|
const userId = options.userId || config.userId;
|
|
@@ -1047,10 +1059,10 @@ program
|
|
|
1047
1059
|
|
|
1048
1060
|
spinner.stop();
|
|
1049
1061
|
|
|
1050
|
-
if (options.output ===
|
|
1062
|
+
if (options.output === 'json') {
|
|
1051
1063
|
console.log(JSON.stringify(result, null, 2));
|
|
1052
1064
|
} else {
|
|
1053
|
-
console.log(chalk.green.bold(
|
|
1065
|
+
console.log(chalk.green.bold('ā
Document created successfully!'));
|
|
1054
1066
|
console.log();
|
|
1055
1067
|
|
|
1056
1068
|
// Extract document info from result
|
|
@@ -1060,14 +1072,14 @@ program
|
|
|
1060
1072
|
|
|
1061
1073
|
documents.forEach((doc, index) => {
|
|
1062
1074
|
const data = [
|
|
1063
|
-
[
|
|
1064
|
-
[
|
|
1065
|
-
[
|
|
1066
|
-
[
|
|
1067
|
-
[
|
|
1068
|
-
[
|
|
1069
|
-
[
|
|
1070
|
-
[
|
|
1075
|
+
['Field', 'Value'],
|
|
1076
|
+
['Document ID', doc.id || 'N/A'],
|
|
1077
|
+
['Title', doc.title || 'N/A'],
|
|
1078
|
+
['Type', doc.type || 'N/A'],
|
|
1079
|
+
['Status', doc.status || 'N/A'],
|
|
1080
|
+
['Folder ID', doc.folderid || doc.folder_id || 'N/A'],
|
|
1081
|
+
['External Path', doc.external_path || 'N/A'],
|
|
1082
|
+
['Created At', doc.created_at || doc.createdAt || 'N/A'],
|
|
1071
1083
|
];
|
|
1072
1084
|
|
|
1073
1085
|
if (documents.length > 1) {
|
|
@@ -1077,14 +1089,14 @@ program
|
|
|
1077
1089
|
console.log(
|
|
1078
1090
|
table(data, {
|
|
1079
1091
|
header: {
|
|
1080
|
-
alignment:
|
|
1081
|
-
content:
|
|
1092
|
+
alignment: 'center',
|
|
1093
|
+
content: 'Document Details',
|
|
1082
1094
|
},
|
|
1083
1095
|
})
|
|
1084
1096
|
);
|
|
1085
1097
|
|
|
1086
1098
|
if (doc.topics && doc.topics.length > 0) {
|
|
1087
|
-
console.log(chalk.cyan(`Topics: ${doc.topics.join(
|
|
1099
|
+
console.log(chalk.cyan(`Topics: ${doc.topics.join(', ')}`));
|
|
1088
1100
|
}
|
|
1089
1101
|
});
|
|
1090
1102
|
}
|
|
@@ -1096,15 +1108,15 @@ program
|
|
|
1096
1108
|
|
|
1097
1109
|
// Update document command
|
|
1098
1110
|
program
|
|
1099
|
-
.command(
|
|
1100
|
-
.description(
|
|
1101
|
-
.argument(
|
|
1102
|
-
.option(
|
|
1103
|
-
.option(
|
|
1104
|
-
.option(
|
|
1105
|
-
.option(
|
|
1106
|
-
.option(
|
|
1107
|
-
.option(
|
|
1111
|
+
.command('update-doc')
|
|
1112
|
+
.description('Update an existing document')
|
|
1113
|
+
.argument('<document-id>', 'ID of the document to update')
|
|
1114
|
+
.option('--type <type>', 'Document type')
|
|
1115
|
+
.option('--rawtext <text>', 'Raw text content')
|
|
1116
|
+
.option('--title <title>', 'Document title')
|
|
1117
|
+
.option('--status <status>', 'Document status (draft|published)')
|
|
1118
|
+
.option('-o, --output <format>', 'Output format (json|text)', 'text')
|
|
1119
|
+
.option('-v, --verbose', 'Show detailed update information')
|
|
1108
1120
|
.action(async (documentId, options, command) => {
|
|
1109
1121
|
try {
|
|
1110
1122
|
const globalOptions = command.parent.opts();
|
|
@@ -1126,7 +1138,7 @@ program
|
|
|
1126
1138
|
if (options.rawtext) fields.rawtext = options.rawtext;
|
|
1127
1139
|
if (options.title) fields.title = options.title;
|
|
1128
1140
|
if (options.status) {
|
|
1129
|
-
if (![
|
|
1141
|
+
if (!['draft', 'published'].includes(options.status)) {
|
|
1130
1142
|
console.error(
|
|
1131
1143
|
chalk.red('Error: --status must be either "draft" or "published"')
|
|
1132
1144
|
);
|
|
@@ -1137,10 +1149,10 @@ program
|
|
|
1137
1149
|
|
|
1138
1150
|
if (Object.keys(fields).length === 0) {
|
|
1139
1151
|
console.error(
|
|
1140
|
-
chalk.red(
|
|
1152
|
+
chalk.red('Error: At least one field must be provided to update')
|
|
1141
1153
|
);
|
|
1142
1154
|
console.error(
|
|
1143
|
-
chalk.yellow(
|
|
1155
|
+
chalk.yellow('Available fields: --type, --rawtext, --title, --status')
|
|
1144
1156
|
);
|
|
1145
1157
|
process.exit(1);
|
|
1146
1158
|
}
|
|
@@ -1148,7 +1160,7 @@ program
|
|
|
1148
1160
|
console.log(chalk.cyan(`Updating document ${documentId}...`));
|
|
1149
1161
|
if (options.verbose) {
|
|
1150
1162
|
console.log(
|
|
1151
|
-
chalk.dim(`Fields to update: ${Object.keys(fields).join(
|
|
1163
|
+
chalk.dim(`Fields to update: ${Object.keys(fields).join(', ')}`)
|
|
1152
1164
|
);
|
|
1153
1165
|
}
|
|
1154
1166
|
|
|
@@ -1157,41 +1169,41 @@ program
|
|
|
1157
1169
|
if (!userId) {
|
|
1158
1170
|
console.error(
|
|
1159
1171
|
chalk.red(
|
|
1160
|
-
|
|
1172
|
+
'Error: User ID is required. Configure it with \'toothfairy configure --user-id YOUR_USER_ID\''
|
|
1161
1173
|
)
|
|
1162
1174
|
);
|
|
1163
1175
|
process.exit(1);
|
|
1164
1176
|
}
|
|
1165
1177
|
|
|
1166
|
-
const spinner = ora(
|
|
1178
|
+
const spinner = ora('Updating document...').start();
|
|
1167
1179
|
|
|
1168
1180
|
const result = await api.updateDocument(documentId, userId, fields);
|
|
1169
1181
|
|
|
1170
1182
|
spinner.stop();
|
|
1171
1183
|
|
|
1172
|
-
if (options.output ===
|
|
1184
|
+
if (options.output === 'json') {
|
|
1173
1185
|
console.log(JSON.stringify(result, null, 2));
|
|
1174
1186
|
} else {
|
|
1175
|
-
console.log(chalk.green.bold(
|
|
1187
|
+
console.log(chalk.green.bold('ā
Document updated successfully!'));
|
|
1176
1188
|
console.log();
|
|
1177
1189
|
|
|
1178
1190
|
const data = [
|
|
1179
|
-
[
|
|
1180
|
-
[
|
|
1181
|
-
[
|
|
1191
|
+
['Field', 'Value'],
|
|
1192
|
+
['Document ID', documentId],
|
|
1193
|
+
['Updated Fields', Object.keys(fields).join(', ')],
|
|
1182
1194
|
];
|
|
1183
1195
|
|
|
1184
1196
|
console.log(
|
|
1185
1197
|
table(data, {
|
|
1186
1198
|
header: {
|
|
1187
|
-
alignment:
|
|
1188
|
-
content:
|
|
1199
|
+
alignment: 'center',
|
|
1200
|
+
content: 'Update Details',
|
|
1189
1201
|
},
|
|
1190
1202
|
})
|
|
1191
1203
|
);
|
|
1192
1204
|
|
|
1193
1205
|
if (options.verbose && result) {
|
|
1194
|
-
console.log(chalk.dim(
|
|
1206
|
+
console.log(chalk.dim('\nAPI Response:'));
|
|
1195
1207
|
console.log(chalk.dim(JSON.stringify(result, null, 2)));
|
|
1196
1208
|
}
|
|
1197
1209
|
}
|
|
@@ -1203,11 +1215,11 @@ program
|
|
|
1203
1215
|
|
|
1204
1216
|
// Get document command
|
|
1205
1217
|
program
|
|
1206
|
-
.command(
|
|
1207
|
-
.description(
|
|
1208
|
-
.argument(
|
|
1209
|
-
.option(
|
|
1210
|
-
.option(
|
|
1218
|
+
.command('get-doc')
|
|
1219
|
+
.description('Get details of a specific document')
|
|
1220
|
+
.argument('<document-id>', 'ID of the document to retrieve')
|
|
1221
|
+
.option('-o, --output <format>', 'Output format (json|text)', 'text')
|
|
1222
|
+
.option('-v, --verbose', 'Show detailed document information')
|
|
1211
1223
|
.action(async (documentId, options, command) => {
|
|
1212
1224
|
try {
|
|
1213
1225
|
const globalOptions = command.parent.opts();
|
|
@@ -1225,58 +1237,58 @@ program
|
|
|
1225
1237
|
|
|
1226
1238
|
console.log(chalk.cyan(`Retrieving document ${documentId}...`));
|
|
1227
1239
|
|
|
1228
|
-
const spinner = ora(
|
|
1240
|
+
const spinner = ora('Fetching document...').start();
|
|
1229
1241
|
|
|
1230
1242
|
const result = await api.getDocument(documentId);
|
|
1231
1243
|
|
|
1232
1244
|
spinner.stop();
|
|
1233
1245
|
|
|
1234
|
-
if (options.output ===
|
|
1246
|
+
if (options.output === 'json') {
|
|
1235
1247
|
console.log(JSON.stringify(result, null, 2));
|
|
1236
1248
|
} else {
|
|
1237
|
-
console.log(chalk.green.bold(
|
|
1249
|
+
console.log(chalk.green.bold('š Document Details'));
|
|
1238
1250
|
console.log();
|
|
1239
1251
|
|
|
1240
1252
|
// Handle different response structures
|
|
1241
1253
|
const doc = result.data[0] || result;
|
|
1242
1254
|
|
|
1243
1255
|
const data = [
|
|
1244
|
-
[
|
|
1245
|
-
[
|
|
1246
|
-
[
|
|
1247
|
-
[
|
|
1248
|
-
[
|
|
1249
|
-
[
|
|
1250
|
-
[
|
|
1251
|
-
[
|
|
1256
|
+
['Field', 'Value'],
|
|
1257
|
+
['Document ID', doc.id || documentId],
|
|
1258
|
+
['Title', doc.title || 'N/A'],
|
|
1259
|
+
['Type', doc.type || 'N/A'],
|
|
1260
|
+
['Status', doc.status || 'N/A'],
|
|
1261
|
+
['Folder ID', doc.folderid || doc.folder_id || 'N/A'],
|
|
1262
|
+
['Created At', doc.created_at || doc.createdAt || 'N/A'],
|
|
1263
|
+
['Updated At', doc.updated_at || doc.updatedAt || 'N/A'],
|
|
1252
1264
|
];
|
|
1253
1265
|
|
|
1254
1266
|
if (doc.external_path) {
|
|
1255
|
-
data.push([
|
|
1267
|
+
data.push(['External Path', doc.external_path]);
|
|
1256
1268
|
}
|
|
1257
1269
|
|
|
1258
1270
|
console.log(
|
|
1259
1271
|
table(data, {
|
|
1260
1272
|
header: {
|
|
1261
|
-
alignment:
|
|
1262
|
-
content:
|
|
1273
|
+
alignment: 'center',
|
|
1274
|
+
content: 'Document Information',
|
|
1263
1275
|
},
|
|
1264
1276
|
})
|
|
1265
1277
|
);
|
|
1266
1278
|
|
|
1267
1279
|
if (doc.topics && doc.topics.length > 0) {
|
|
1268
|
-
console.log(chalk.cyan(`\nTopics: ${doc.topics.join(
|
|
1280
|
+
console.log(chalk.cyan(`\nTopics: ${doc.topics.join(', ')}`));
|
|
1269
1281
|
}
|
|
1270
1282
|
|
|
1271
1283
|
if (doc.rawtext && options.verbose) {
|
|
1272
|
-
console.log(chalk.blue.bold(
|
|
1273
|
-
console.log(
|
|
1284
|
+
console.log(chalk.blue.bold('\nš Raw Text Content:'));
|
|
1285
|
+
console.log('ā'.repeat(50));
|
|
1274
1286
|
const displayText =
|
|
1275
1287
|
doc.rawtext.length > 500
|
|
1276
|
-
? doc.rawtext.substring(0, 500) +
|
|
1288
|
+
? doc.rawtext.substring(0, 500) + '...'
|
|
1277
1289
|
: doc.rawtext;
|
|
1278
1290
|
console.log(displayText);
|
|
1279
|
-
console.log(
|
|
1291
|
+
console.log('ā'.repeat(50));
|
|
1280
1292
|
}
|
|
1281
1293
|
}
|
|
1282
1294
|
} catch (error) {
|
|
@@ -1287,12 +1299,12 @@ program
|
|
|
1287
1299
|
|
|
1288
1300
|
// Delete document command
|
|
1289
1301
|
program
|
|
1290
|
-
.command(
|
|
1291
|
-
.description(
|
|
1292
|
-
.argument(
|
|
1293
|
-
.option(
|
|
1294
|
-
.option(
|
|
1295
|
-
.option(
|
|
1302
|
+
.command('delete-doc')
|
|
1303
|
+
.description('Delete a document')
|
|
1304
|
+
.argument('<document-id>', 'ID of the document to delete')
|
|
1305
|
+
.option('--confirm', 'Skip confirmation prompt')
|
|
1306
|
+
.option('-o, --output <format>', 'Output format (json|text)', 'text')
|
|
1307
|
+
.option('-v, --verbose', 'Show detailed deletion information')
|
|
1296
1308
|
.action(async (documentId, options, command) => {
|
|
1297
1309
|
try {
|
|
1298
1310
|
const globalOptions = command.parent.opts();
|
|
@@ -1310,7 +1322,7 @@ program
|
|
|
1310
1322
|
|
|
1311
1323
|
// Confirmation prompt (unless --confirm flag is used)
|
|
1312
1324
|
if (!options.confirm) {
|
|
1313
|
-
const readline = require(
|
|
1325
|
+
const readline = require('readline');
|
|
1314
1326
|
const rl = readline.createInterface({
|
|
1315
1327
|
input: process.stdin,
|
|
1316
1328
|
output: process.stdout,
|
|
@@ -1327,43 +1339,43 @@ program
|
|
|
1327
1339
|
|
|
1328
1340
|
rl.close();
|
|
1329
1341
|
|
|
1330
|
-
if (answer.toLowerCase() !==
|
|
1331
|
-
console.log(chalk.gray(
|
|
1342
|
+
if (answer.toLowerCase() !== 'y' && answer.toLowerCase() !== 'yes') {
|
|
1343
|
+
console.log(chalk.gray('Deletion cancelled.'));
|
|
1332
1344
|
process.exit(0);
|
|
1333
1345
|
}
|
|
1334
1346
|
}
|
|
1335
1347
|
|
|
1336
1348
|
console.log(chalk.cyan(`Deleting document ${documentId}...`));
|
|
1337
1349
|
|
|
1338
|
-
const spinner = ora(
|
|
1350
|
+
const spinner = ora('Deleting document...').start();
|
|
1339
1351
|
|
|
1340
1352
|
const result = await api.deleteDocument(documentId);
|
|
1341
1353
|
|
|
1342
1354
|
spinner.stop();
|
|
1343
1355
|
|
|
1344
|
-
if (options.output ===
|
|
1356
|
+
if (options.output === 'json') {
|
|
1345
1357
|
console.log(JSON.stringify(result, null, 2));
|
|
1346
1358
|
} else {
|
|
1347
|
-
console.log(chalk.green.bold(
|
|
1359
|
+
console.log(chalk.green.bold('ā
Document deleted successfully!'));
|
|
1348
1360
|
console.log();
|
|
1349
1361
|
|
|
1350
1362
|
const data = [
|
|
1351
|
-
[
|
|
1352
|
-
[
|
|
1353
|
-
[
|
|
1363
|
+
['Field', 'Value'],
|
|
1364
|
+
['Document ID', documentId],
|
|
1365
|
+
['Status', 'Deleted'],
|
|
1354
1366
|
];
|
|
1355
1367
|
|
|
1356
1368
|
console.log(
|
|
1357
1369
|
table(data, {
|
|
1358
1370
|
header: {
|
|
1359
|
-
alignment:
|
|
1360
|
-
content:
|
|
1371
|
+
alignment: 'center',
|
|
1372
|
+
content: 'Deletion Details',
|
|
1361
1373
|
},
|
|
1362
1374
|
})
|
|
1363
1375
|
);
|
|
1364
1376
|
|
|
1365
1377
|
if (options.verbose && result) {
|
|
1366
|
-
console.log(chalk.dim(
|
|
1378
|
+
console.log(chalk.dim('\nAPI Response:'));
|
|
1367
1379
|
console.log(chalk.dim(JSON.stringify(result, null, 2)));
|
|
1368
1380
|
}
|
|
1369
1381
|
}
|
|
@@ -1375,19 +1387,19 @@ program
|
|
|
1375
1387
|
|
|
1376
1388
|
// Upload file command
|
|
1377
1389
|
program
|
|
1378
|
-
.command(
|
|
1379
|
-
.description(
|
|
1380
|
-
.argument(
|
|
1390
|
+
.command('upload')
|
|
1391
|
+
.description('Upload a file to ToothFairy workspace')
|
|
1392
|
+
.argument('<file-path>', 'Path to file to upload')
|
|
1381
1393
|
.option(
|
|
1382
|
-
|
|
1383
|
-
|
|
1394
|
+
'--import-type <type>',
|
|
1395
|
+
'Import type (optional, auto-detected from extension)'
|
|
1384
1396
|
)
|
|
1385
1397
|
.option(
|
|
1386
|
-
|
|
1387
|
-
|
|
1398
|
+
'--content-type <type>',
|
|
1399
|
+
'Content type (optional, auto-detected from extension)'
|
|
1388
1400
|
)
|
|
1389
|
-
.option(
|
|
1390
|
-
.option(
|
|
1401
|
+
.option('-o, --output <format>', 'Output format (json|text)', 'text')
|
|
1402
|
+
.option('-v, --verbose', 'Show detailed upload information')
|
|
1391
1403
|
.action(async (filePath, options, command) => {
|
|
1392
1404
|
try {
|
|
1393
1405
|
const globalOptions = command.parent.opts();
|
|
@@ -1409,54 +1421,54 @@ program
|
|
|
1409
1421
|
|
|
1410
1422
|
// Validate file extension
|
|
1411
1423
|
const validExtensions = [
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
|
|
1451
|
-
|
|
1452
|
-
|
|
1424
|
+
'pdf',
|
|
1425
|
+
'docx',
|
|
1426
|
+
'txt',
|
|
1427
|
+
'csv',
|
|
1428
|
+
'md',
|
|
1429
|
+
'html',
|
|
1430
|
+
'xlsx',
|
|
1431
|
+
'pptx',
|
|
1432
|
+
'ppt',
|
|
1433
|
+
'png',
|
|
1434
|
+
'jpg',
|
|
1435
|
+
'jpeg',
|
|
1436
|
+
'gif',
|
|
1437
|
+
'bmp',
|
|
1438
|
+
'svg',
|
|
1439
|
+
'java',
|
|
1440
|
+
'py',
|
|
1441
|
+
'yaml',
|
|
1442
|
+
'yml',
|
|
1443
|
+
'sql',
|
|
1444
|
+
'sh',
|
|
1445
|
+
'php',
|
|
1446
|
+
'js',
|
|
1447
|
+
'ts',
|
|
1448
|
+
'tsx',
|
|
1449
|
+
'jsx',
|
|
1450
|
+
'csharp',
|
|
1451
|
+
'rb',
|
|
1452
|
+
'jsonl',
|
|
1453
|
+
'wav',
|
|
1454
|
+
'mp3',
|
|
1455
|
+
'aac',
|
|
1456
|
+
'ogg',
|
|
1457
|
+
'flac',
|
|
1458
|
+
'mp4',
|
|
1459
|
+
'avi',
|
|
1460
|
+
'mov',
|
|
1461
|
+
'wmv',
|
|
1462
|
+
'flv',
|
|
1463
|
+
'webm',
|
|
1464
|
+
'json',
|
|
1453
1465
|
];
|
|
1454
1466
|
|
|
1455
1467
|
const ext = path.extname(resolvedPath).toLowerCase().slice(1);
|
|
1456
1468
|
if (!validExtensions.includes(ext)) {
|
|
1457
1469
|
console.error(chalk.red(`Error: Unsupported file extension '.${ext}'`));
|
|
1458
1470
|
console.error(
|
|
1459
|
-
chalk.yellow(`Supported extensions: ${validExtensions.join(
|
|
1471
|
+
chalk.yellow(`Supported extensions: ${validExtensions.join(', ')}`)
|
|
1460
1472
|
);
|
|
1461
1473
|
process.exit(1);
|
|
1462
1474
|
}
|
|
@@ -1466,7 +1478,7 @@ program
|
|
|
1466
1478
|
console.log(chalk.dim(`Local path: ${resolvedPath}`));
|
|
1467
1479
|
}
|
|
1468
1480
|
|
|
1469
|
-
let currentSpinner = ora(
|
|
1481
|
+
let currentSpinner = ora('Preparing upload...').start();
|
|
1470
1482
|
let lastProgress = 0;
|
|
1471
1483
|
|
|
1472
1484
|
const result = await api.uploadFile(
|
|
@@ -1494,33 +1506,33 @@ program
|
|
|
1494
1506
|
currentSpinner.stop();
|
|
1495
1507
|
}
|
|
1496
1508
|
|
|
1497
|
-
if (options.output ===
|
|
1509
|
+
if (options.output === 'json') {
|
|
1498
1510
|
console.log(JSON.stringify(result, null, 2));
|
|
1499
1511
|
} else {
|
|
1500
|
-
console.log(chalk.green.bold(
|
|
1512
|
+
console.log(chalk.green.bold('ā
Upload completed successfully!'));
|
|
1501
1513
|
console.log();
|
|
1502
1514
|
|
|
1503
1515
|
const data = [
|
|
1504
|
-
[
|
|
1505
|
-
[
|
|
1506
|
-
[
|
|
1507
|
-
[
|
|
1508
|
-
[
|
|
1509
|
-
[
|
|
1510
|
-
[
|
|
1516
|
+
['Field', 'Value'],
|
|
1517
|
+
['Original File', result.originalFilename],
|
|
1518
|
+
['Sanitized File', result.sanitizedFilename],
|
|
1519
|
+
['Import Type', result.importType],
|
|
1520
|
+
['Content Type', result.contentType],
|
|
1521
|
+
['Size', `${result.sizeInMB.toFixed(2)}MB`],
|
|
1522
|
+
['Download Name', result.filename],
|
|
1511
1523
|
];
|
|
1512
1524
|
|
|
1513
1525
|
console.log(
|
|
1514
1526
|
table(data, {
|
|
1515
1527
|
header: {
|
|
1516
|
-
alignment:
|
|
1517
|
-
content:
|
|
1528
|
+
alignment: 'center',
|
|
1529
|
+
content: 'Upload Details',
|
|
1518
1530
|
},
|
|
1519
1531
|
})
|
|
1520
1532
|
);
|
|
1521
1533
|
|
|
1522
1534
|
if (options.verbose) {
|
|
1523
|
-
console.log(chalk.dim(`File Key: ${result.fileKey ||
|
|
1535
|
+
console.log(chalk.dim(`File Key: ${result.fileKey || 'N/A'}`));
|
|
1524
1536
|
console.log(chalk.dim(`Upload URL: ${result.uploadURL}`));
|
|
1525
1537
|
}
|
|
1526
1538
|
}
|
|
@@ -1532,24 +1544,24 @@ program
|
|
|
1532
1544
|
|
|
1533
1545
|
// Download file command
|
|
1534
1546
|
program
|
|
1535
|
-
.command(
|
|
1536
|
-
.description(
|
|
1547
|
+
.command('download')
|
|
1548
|
+
.description('Download a file from ToothFairy workspace')
|
|
1537
1549
|
.requiredOption(
|
|
1538
|
-
|
|
1539
|
-
|
|
1550
|
+
'--filename <name>',
|
|
1551
|
+
'Name of the file to download (from upload response)'
|
|
1540
1552
|
)
|
|
1541
1553
|
.option(
|
|
1542
|
-
|
|
1543
|
-
|
|
1554
|
+
'--workspace-id <id>',
|
|
1555
|
+
'Workspace ID (uses config default if not specified)'
|
|
1544
1556
|
)
|
|
1545
|
-
.option(
|
|
1546
|
-
.option(
|
|
1557
|
+
.option('--context <context>', 'Download context (default: pdf)', 'pdf')
|
|
1558
|
+
.option('--output-dir <dir>', 'Output directory', './downloads')
|
|
1547
1559
|
.option(
|
|
1548
|
-
|
|
1549
|
-
|
|
1560
|
+
'--output-name <name>',
|
|
1561
|
+
'Output filename (defaults to original filename)'
|
|
1550
1562
|
)
|
|
1551
|
-
.option(
|
|
1552
|
-
.option(
|
|
1563
|
+
.option('-o, --output <format>', 'Output format (json|text)', 'text')
|
|
1564
|
+
.option('-v, --verbose', 'Show detailed download information')
|
|
1553
1565
|
.action(async (options, command) => {
|
|
1554
1566
|
try {
|
|
1555
1567
|
const globalOptions = command.parent.opts();
|
|
@@ -1579,7 +1591,7 @@ program
|
|
|
1579
1591
|
console.log(chalk.dim(`Output path: ${outputPath}`));
|
|
1580
1592
|
}
|
|
1581
1593
|
|
|
1582
|
-
let currentSpinner = ora(
|
|
1594
|
+
let currentSpinner = ora('Preparing download...').start();
|
|
1583
1595
|
let lastProgress = 0;
|
|
1584
1596
|
|
|
1585
1597
|
const result = await api.downloadFile(
|
|
@@ -1607,25 +1619,25 @@ program
|
|
|
1607
1619
|
currentSpinner.stop();
|
|
1608
1620
|
}
|
|
1609
1621
|
|
|
1610
|
-
if (options.output ===
|
|
1622
|
+
if (options.output === 'json') {
|
|
1611
1623
|
console.log(JSON.stringify(result, null, 2));
|
|
1612
1624
|
} else {
|
|
1613
|
-
console.log(chalk.green.bold(
|
|
1625
|
+
console.log(chalk.green.bold('ā
Download completed successfully!'));
|
|
1614
1626
|
console.log();
|
|
1615
1627
|
|
|
1616
1628
|
const data = [
|
|
1617
|
-
[
|
|
1618
|
-
[
|
|
1619
|
-
[
|
|
1620
|
-
[
|
|
1621
|
-
[
|
|
1629
|
+
['Field', 'Value'],
|
|
1630
|
+
['File', options.filename],
|
|
1631
|
+
['Size', `${result.sizeInMB}MB`],
|
|
1632
|
+
['Output Path', result.outputPath],
|
|
1633
|
+
['Workspace ID', workspaceId],
|
|
1622
1634
|
];
|
|
1623
1635
|
|
|
1624
1636
|
console.log(
|
|
1625
1637
|
table(data, {
|
|
1626
1638
|
header: {
|
|
1627
|
-
alignment:
|
|
1628
|
-
content:
|
|
1639
|
+
alignment: 'center',
|
|
1640
|
+
content: 'Download Details',
|
|
1629
1641
|
},
|
|
1630
1642
|
})
|
|
1631
1643
|
);
|
|
@@ -1638,20 +1650,20 @@ program
|
|
|
1638
1650
|
|
|
1639
1651
|
// Create entity command
|
|
1640
1652
|
program
|
|
1641
|
-
.command(
|
|
1642
|
-
.description(
|
|
1643
|
-
.argument(
|
|
1653
|
+
.command('create-entity')
|
|
1654
|
+
.description('Create a new entity with specified type')
|
|
1655
|
+
.argument('<label>', 'Entity label')
|
|
1644
1656
|
.option(
|
|
1645
|
-
|
|
1646
|
-
|
|
1657
|
+
'--user-id <id>',
|
|
1658
|
+
'User ID (optional, uses configured value if not provided)'
|
|
1647
1659
|
)
|
|
1648
|
-
.option(
|
|
1649
|
-
.option(
|
|
1650
|
-
.option(
|
|
1651
|
-
.option(
|
|
1652
|
-
.option(
|
|
1653
|
-
.option(
|
|
1654
|
-
.option(
|
|
1660
|
+
.option('--type <type>', 'Entity type (intent|ner|topic)', 'topic')
|
|
1661
|
+
.option('--description <desc>', 'Entity description')
|
|
1662
|
+
.option('--emoji <emoji>', 'Entity emoji')
|
|
1663
|
+
.option('--parent-entity <id>', 'Parent entity ID')
|
|
1664
|
+
.option('--background-color <color>', 'Background color (hex format)')
|
|
1665
|
+
.option('-o, --output <format>', 'Output format (json|text)', 'text')
|
|
1666
|
+
.option('-v, --verbose', 'Show detailed creation information')
|
|
1655
1667
|
.action(async (label, options, command) => {
|
|
1656
1668
|
try {
|
|
1657
1669
|
const globalOptions = command.parent.opts();
|
|
@@ -1659,12 +1671,12 @@ program
|
|
|
1659
1671
|
validateDocumentConfiguration(config);
|
|
1660
1672
|
|
|
1661
1673
|
// Validate entity type
|
|
1662
|
-
const validTypes = [
|
|
1674
|
+
const validTypes = ['intent', 'ner', 'topic'];
|
|
1663
1675
|
if (!validTypes.includes(options.type)) {
|
|
1664
1676
|
console.error(
|
|
1665
1677
|
chalk.red(`Error: Invalid entity type '${options.type}'`)
|
|
1666
1678
|
);
|
|
1667
|
-
console.error(chalk.yellow(`Valid types: ${validTypes.join(
|
|
1679
|
+
console.error(chalk.yellow(`Valid types: ${validTypes.join(', ')}`));
|
|
1668
1680
|
process.exit(1);
|
|
1669
1681
|
}
|
|
1670
1682
|
|
|
@@ -1674,7 +1686,7 @@ program
|
|
|
1674
1686
|
if (!hexColorRegex.test(options.backgroundColor)) {
|
|
1675
1687
|
console.error(
|
|
1676
1688
|
chalk.red(
|
|
1677
|
-
|
|
1689
|
+
'Error: Background color must be in hex format (e.g., #FF5733)'
|
|
1678
1690
|
)
|
|
1679
1691
|
);
|
|
1680
1692
|
process.exit(1);
|
|
@@ -1696,7 +1708,7 @@ program
|
|
|
1696
1708
|
chalk.cyan(`Creating entity "${label}" of type "${options.type}"...`)
|
|
1697
1709
|
);
|
|
1698
1710
|
|
|
1699
|
-
const spinner = ora(
|
|
1711
|
+
const spinner = ora('Creating entity...').start();
|
|
1700
1712
|
|
|
1701
1713
|
const result = await api.createEntity(
|
|
1702
1714
|
userId,
|
|
@@ -1710,36 +1722,36 @@ program
|
|
|
1710
1722
|
|
|
1711
1723
|
spinner.stop();
|
|
1712
1724
|
|
|
1713
|
-
if (options.output ===
|
|
1725
|
+
if (options.output === 'json') {
|
|
1714
1726
|
console.log(JSON.stringify(result, null, 2));
|
|
1715
1727
|
} else {
|
|
1716
|
-
console.log(chalk.green.bold(
|
|
1728
|
+
console.log(chalk.green.bold('ā
Entity created successfully!'));
|
|
1717
1729
|
console.log();
|
|
1718
1730
|
|
|
1719
1731
|
const data = [
|
|
1720
|
-
[
|
|
1721
|
-
[
|
|
1722
|
-
[
|
|
1723
|
-
[
|
|
1724
|
-
[
|
|
1725
|
-
[
|
|
1726
|
-
[
|
|
1727
|
-
[
|
|
1728
|
-
[
|
|
1729
|
-
[
|
|
1732
|
+
['Field', 'Value'],
|
|
1733
|
+
['ID', result.id || 'N/A'],
|
|
1734
|
+
['Label', result.label],
|
|
1735
|
+
['Type', result.type],
|
|
1736
|
+
['Description', result.description || 'N/A'],
|
|
1737
|
+
['Emoji', result.emoji || 'N/A'],
|
|
1738
|
+
['Parent Entity', result.parentEntity || 'N/A'],
|
|
1739
|
+
['Background Color', result.backgroundColor || 'N/A'],
|
|
1740
|
+
['Workspace ID', result.workspaceid],
|
|
1741
|
+
['Created By', result.createdBy],
|
|
1730
1742
|
];
|
|
1731
1743
|
|
|
1732
1744
|
console.log(
|
|
1733
1745
|
table(data, {
|
|
1734
1746
|
header: {
|
|
1735
|
-
alignment:
|
|
1736
|
-
content:
|
|
1747
|
+
alignment: 'center',
|
|
1748
|
+
content: 'Entity Details',
|
|
1737
1749
|
},
|
|
1738
1750
|
})
|
|
1739
1751
|
);
|
|
1740
1752
|
|
|
1741
1753
|
if (options.verbose && result) {
|
|
1742
|
-
console.log(chalk.dim(
|
|
1754
|
+
console.log(chalk.dim('\nAPI Response:'));
|
|
1743
1755
|
console.log(chalk.dim(JSON.stringify(result, null, 2)));
|
|
1744
1756
|
}
|
|
1745
1757
|
}
|
|
@@ -1751,17 +1763,17 @@ program
|
|
|
1751
1763
|
|
|
1752
1764
|
// Update entity command
|
|
1753
1765
|
program
|
|
1754
|
-
.command(
|
|
1755
|
-
.description(
|
|
1756
|
-
.argument(
|
|
1757
|
-
.option(
|
|
1758
|
-
.option(
|
|
1759
|
-
.option(
|
|
1760
|
-
.option(
|
|
1761
|
-
.option(
|
|
1762
|
-
.option(
|
|
1763
|
-
.option(
|
|
1764
|
-
.option(
|
|
1766
|
+
.command('update-entity')
|
|
1767
|
+
.description('Update an existing entity')
|
|
1768
|
+
.argument('<id>', 'Entity ID')
|
|
1769
|
+
.option('--label <label>', 'New entity label')
|
|
1770
|
+
.option('--type <type>', 'New entity type (intent|ner|topic)')
|
|
1771
|
+
.option('--description <desc>', 'New entity description')
|
|
1772
|
+
.option('--emoji <emoji>', 'New entity emoji')
|
|
1773
|
+
.option('--parent-entity <id>', 'New parent entity ID')
|
|
1774
|
+
.option('--background-color <color>', 'New background color (hex format)')
|
|
1775
|
+
.option('-o, --output <format>', 'Output format (json|text)', 'text')
|
|
1776
|
+
.option('-v, --verbose', 'Show detailed update information')
|
|
1765
1777
|
.action(async (entityId, options, command) => {
|
|
1766
1778
|
try {
|
|
1767
1779
|
const globalOptions = command.parent.opts();
|
|
@@ -1770,12 +1782,12 @@ program
|
|
|
1770
1782
|
|
|
1771
1783
|
// Validate entity type if provided
|
|
1772
1784
|
if (options.type) {
|
|
1773
|
-
const validTypes = [
|
|
1785
|
+
const validTypes = ['intent', 'ner', 'topic'];
|
|
1774
1786
|
if (!validTypes.includes(options.type)) {
|
|
1775
1787
|
console.error(
|
|
1776
1788
|
chalk.red(`Error: Invalid entity type '${options.type}'`)
|
|
1777
1789
|
);
|
|
1778
|
-
console.error(chalk.yellow(`Valid types: ${validTypes.join(
|
|
1790
|
+
console.error(chalk.yellow(`Valid types: ${validTypes.join(', ')}`));
|
|
1779
1791
|
process.exit(1);
|
|
1780
1792
|
}
|
|
1781
1793
|
}
|
|
@@ -1786,7 +1798,7 @@ program
|
|
|
1786
1798
|
if (!hexColorRegex.test(options.backgroundColor)) {
|
|
1787
1799
|
console.error(
|
|
1788
1800
|
chalk.red(
|
|
1789
|
-
|
|
1801
|
+
'Error: Background color must be in hex format (e.g., #FF5733)'
|
|
1790
1802
|
)
|
|
1791
1803
|
);
|
|
1792
1804
|
process.exit(1);
|
|
@@ -1804,7 +1816,7 @@ program
|
|
|
1804
1816
|
|
|
1805
1817
|
console.log(chalk.cyan(`Updating entity ${entityId}...`));
|
|
1806
1818
|
|
|
1807
|
-
const spinner = ora(
|
|
1819
|
+
const spinner = ora('Updating entity...').start();
|
|
1808
1820
|
|
|
1809
1821
|
const result = await api.updateEntity(
|
|
1810
1822
|
entityId,
|
|
@@ -1818,34 +1830,34 @@ program
|
|
|
1818
1830
|
|
|
1819
1831
|
spinner.stop();
|
|
1820
1832
|
|
|
1821
|
-
if (options.output ===
|
|
1833
|
+
if (options.output === 'json') {
|
|
1822
1834
|
console.log(JSON.stringify(result, null, 2));
|
|
1823
1835
|
} else {
|
|
1824
|
-
console.log(chalk.green.bold(
|
|
1836
|
+
console.log(chalk.green.bold('ā
Entity updated successfully!'));
|
|
1825
1837
|
console.log();
|
|
1826
1838
|
|
|
1827
1839
|
const data = [
|
|
1828
|
-
[
|
|
1829
|
-
[
|
|
1830
|
-
[
|
|
1831
|
-
[
|
|
1832
|
-
[
|
|
1833
|
-
[
|
|
1834
|
-
[
|
|
1835
|
-
[
|
|
1840
|
+
['Field', 'Value'],
|
|
1841
|
+
['ID', result.id || entityId],
|
|
1842
|
+
['Label', result.label || 'N/A'],
|
|
1843
|
+
['Type', result.type || 'N/A'],
|
|
1844
|
+
['Description', result.description || 'N/A'],
|
|
1845
|
+
['Emoji', result.emoji || 'N/A'],
|
|
1846
|
+
['Parent Entity', result.parentEntity || 'N/A'],
|
|
1847
|
+
['Background Color', result.backgroundColor || 'N/A'],
|
|
1836
1848
|
];
|
|
1837
1849
|
|
|
1838
1850
|
console.log(
|
|
1839
1851
|
table(data, {
|
|
1840
1852
|
header: {
|
|
1841
|
-
alignment:
|
|
1842
|
-
content:
|
|
1853
|
+
alignment: 'center',
|
|
1854
|
+
content: 'Updated Entity Details',
|
|
1843
1855
|
},
|
|
1844
1856
|
})
|
|
1845
1857
|
);
|
|
1846
1858
|
|
|
1847
1859
|
if (options.verbose && result) {
|
|
1848
|
-
console.log(chalk.dim(
|
|
1860
|
+
console.log(chalk.dim('\nAPI Response:'));
|
|
1849
1861
|
console.log(chalk.dim(JSON.stringify(result, null, 2)));
|
|
1850
1862
|
}
|
|
1851
1863
|
}
|
|
@@ -1857,11 +1869,11 @@ program
|
|
|
1857
1869
|
|
|
1858
1870
|
// Get entity command
|
|
1859
1871
|
program
|
|
1860
|
-
.command(
|
|
1861
|
-
.description(
|
|
1862
|
-
.argument(
|
|
1863
|
-
.option(
|
|
1864
|
-
.option(
|
|
1872
|
+
.command('get-entity')
|
|
1873
|
+
.description('Get details of a specific entity')
|
|
1874
|
+
.argument('<id>', 'Entity ID')
|
|
1875
|
+
.option('-o, --output <format>', 'Output format (json|text)', 'text')
|
|
1876
|
+
.option('-v, --verbose', 'Show detailed information')
|
|
1865
1877
|
.action(async (entityId, options, command) => {
|
|
1866
1878
|
try {
|
|
1867
1879
|
const globalOptions = command.parent.opts();
|
|
@@ -1879,23 +1891,23 @@ program
|
|
|
1879
1891
|
|
|
1880
1892
|
console.log(chalk.cyan(`Fetching entity ${entityId}...`));
|
|
1881
1893
|
|
|
1882
|
-
const spinner = ora(
|
|
1894
|
+
const spinner = ora('Fetching entity...').start();
|
|
1883
1895
|
|
|
1884
1896
|
const entityData = await api.getEntity(entityId);
|
|
1885
1897
|
|
|
1886
1898
|
spinner.stop();
|
|
1887
1899
|
|
|
1888
|
-
if (options.output ===
|
|
1900
|
+
if (options.output === 'json') {
|
|
1889
1901
|
console.log(JSON.stringify(entityData, null, 2));
|
|
1890
1902
|
} else {
|
|
1891
|
-
console.log(chalk.green.bold(
|
|
1903
|
+
console.log(chalk.green.bold('Entity Details'));
|
|
1892
1904
|
console.log();
|
|
1893
1905
|
|
|
1894
|
-
const data = [[
|
|
1906
|
+
const data = [['Field', 'Value']];
|
|
1895
1907
|
|
|
1896
1908
|
Object.entries(entityData).forEach(([key, value]) => {
|
|
1897
1909
|
let displayValue = value;
|
|
1898
|
-
if (typeof value ===
|
|
1910
|
+
if (typeof value === 'object' && value !== null) {
|
|
1899
1911
|
displayValue = JSON.stringify(value, null, 2);
|
|
1900
1912
|
}
|
|
1901
1913
|
data.push([key, String(displayValue)]);
|
|
@@ -1911,12 +1923,12 @@ program
|
|
|
1911
1923
|
|
|
1912
1924
|
// Delete entity command
|
|
1913
1925
|
program
|
|
1914
|
-
.command(
|
|
1915
|
-
.description(
|
|
1916
|
-
.argument(
|
|
1917
|
-
.option(
|
|
1918
|
-
.option(
|
|
1919
|
-
.option(
|
|
1926
|
+
.command('delete-entity')
|
|
1927
|
+
.description('Delete an entity')
|
|
1928
|
+
.argument('<id>', 'Entity ID')
|
|
1929
|
+
.option('--confirm', 'Skip confirmation prompt')
|
|
1930
|
+
.option('-o, --output <format>', 'Output format (json|text)', 'text')
|
|
1931
|
+
.option('-v, --verbose', 'Show detailed deletion information')
|
|
1920
1932
|
.action(async (entityId, options, command) => {
|
|
1921
1933
|
try {
|
|
1922
1934
|
const globalOptions = command.parent.opts();
|
|
@@ -1934,7 +1946,7 @@ program
|
|
|
1934
1946
|
|
|
1935
1947
|
// Confirmation prompt (unless --confirm flag is used)
|
|
1936
1948
|
if (!options.confirm) {
|
|
1937
|
-
const readline = require(
|
|
1949
|
+
const readline = require('readline');
|
|
1938
1950
|
const rl = readline.createInterface({
|
|
1939
1951
|
input: process.stdin,
|
|
1940
1952
|
output: process.stdout,
|
|
@@ -1951,43 +1963,43 @@ program
|
|
|
1951
1963
|
|
|
1952
1964
|
rl.close();
|
|
1953
1965
|
|
|
1954
|
-
if (answer.toLowerCase() !==
|
|
1955
|
-
console.log(chalk.gray(
|
|
1966
|
+
if (answer.toLowerCase() !== 'y' && answer.toLowerCase() !== 'yes') {
|
|
1967
|
+
console.log(chalk.gray('Deletion cancelled.'));
|
|
1956
1968
|
process.exit(0);
|
|
1957
1969
|
}
|
|
1958
1970
|
}
|
|
1959
1971
|
|
|
1960
1972
|
console.log(chalk.cyan(`Deleting entity ${entityId}...`));
|
|
1961
1973
|
|
|
1962
|
-
const spinner = ora(
|
|
1974
|
+
const spinner = ora('Deleting entity...').start();
|
|
1963
1975
|
|
|
1964
1976
|
const result = await api.deleteEntity(entityId);
|
|
1965
1977
|
|
|
1966
1978
|
spinner.stop();
|
|
1967
1979
|
|
|
1968
|
-
if (options.output ===
|
|
1980
|
+
if (options.output === 'json') {
|
|
1969
1981
|
console.log(JSON.stringify(result, null, 2));
|
|
1970
1982
|
} else {
|
|
1971
|
-
console.log(chalk.green.bold(
|
|
1983
|
+
console.log(chalk.green.bold('ā
Entity deleted successfully!'));
|
|
1972
1984
|
console.log();
|
|
1973
1985
|
|
|
1974
1986
|
const data = [
|
|
1975
|
-
[
|
|
1976
|
-
[
|
|
1977
|
-
[
|
|
1987
|
+
['Field', 'Value'],
|
|
1988
|
+
['Entity ID', entityId],
|
|
1989
|
+
['Status', 'Deleted'],
|
|
1978
1990
|
];
|
|
1979
1991
|
|
|
1980
1992
|
console.log(
|
|
1981
1993
|
table(data, {
|
|
1982
1994
|
header: {
|
|
1983
|
-
alignment:
|
|
1984
|
-
content:
|
|
1995
|
+
alignment: 'center',
|
|
1996
|
+
content: 'Deletion Details',
|
|
1985
1997
|
},
|
|
1986
1998
|
})
|
|
1987
1999
|
);
|
|
1988
2000
|
|
|
1989
2001
|
if (options.verbose && result) {
|
|
1990
|
-
console.log(chalk.dim(
|
|
2002
|
+
console.log(chalk.dim('\nAPI Response:'));
|
|
1991
2003
|
console.log(chalk.dim(JSON.stringify(result, null, 2)));
|
|
1992
2004
|
}
|
|
1993
2005
|
}
|
|
@@ -1999,13 +2011,13 @@ program
|
|
|
1999
2011
|
|
|
2000
2012
|
// List entities command
|
|
2001
2013
|
program
|
|
2002
|
-
.command(
|
|
2003
|
-
.description(
|
|
2004
|
-
.option(
|
|
2005
|
-
.option(
|
|
2006
|
-
.option(
|
|
2007
|
-
.option(
|
|
2008
|
-
.option(
|
|
2014
|
+
.command('list-entities')
|
|
2015
|
+
.description('List all entities in the workspace')
|
|
2016
|
+
.option('--type <type>', 'Filter by entity type (intent|ner|topic)')
|
|
2017
|
+
.option('--limit <number>', 'Maximum number of entities to return', '50')
|
|
2018
|
+
.option('--offset <number>', 'Number of entities to skip', '0')
|
|
2019
|
+
.option('-o, --output <format>', 'Output format (json|text)', 'text')
|
|
2020
|
+
.option('-v, --verbose', 'Show detailed information')
|
|
2009
2021
|
.action(async (options, command) => {
|
|
2010
2022
|
try {
|
|
2011
2023
|
const globalOptions = command.parent.opts();
|
|
@@ -2014,12 +2026,12 @@ program
|
|
|
2014
2026
|
|
|
2015
2027
|
// Validate entity type filter if provided
|
|
2016
2028
|
if (options.type) {
|
|
2017
|
-
const validTypes = [
|
|
2029
|
+
const validTypes = ['intent', 'ner', 'topic'];
|
|
2018
2030
|
if (!validTypes.includes(options.type)) {
|
|
2019
2031
|
console.error(
|
|
2020
2032
|
chalk.red(`Error: Invalid entity type '${options.type}'`)
|
|
2021
2033
|
);
|
|
2022
|
-
console.error(chalk.yellow(`Valid types: ${validTypes.join(
|
|
2034
|
+
console.error(chalk.yellow(`Valid types: ${validTypes.join(', ')}`));
|
|
2023
2035
|
process.exit(1);
|
|
2024
2036
|
}
|
|
2025
2037
|
}
|
|
@@ -2033,9 +2045,9 @@ program
|
|
|
2033
2045
|
globalOptions.verbose || options.verbose
|
|
2034
2046
|
);
|
|
2035
2047
|
|
|
2036
|
-
console.log(chalk.cyan(
|
|
2048
|
+
console.log(chalk.cyan('Fetching entities...'));
|
|
2037
2049
|
|
|
2038
|
-
const spinner = ora(
|
|
2050
|
+
const spinner = ora('Loading entities...').start();
|
|
2039
2051
|
|
|
2040
2052
|
const result = await api.listEntities(
|
|
2041
2053
|
options.type,
|
|
@@ -2045,29 +2057,29 @@ program
|
|
|
2045
2057
|
|
|
2046
2058
|
spinner.stop();
|
|
2047
2059
|
|
|
2048
|
-
if (options.output ===
|
|
2060
|
+
if (options.output === 'json') {
|
|
2049
2061
|
console.log(JSON.stringify(result, null, 2));
|
|
2050
2062
|
} else {
|
|
2051
2063
|
if (!result || result.length === 0) {
|
|
2052
|
-
console.log(chalk.yellow(
|
|
2064
|
+
console.log(chalk.yellow('No entities found.'));
|
|
2053
2065
|
return;
|
|
2054
2066
|
}
|
|
2055
2067
|
|
|
2056
2068
|
console.log(chalk.green.bold(`Found ${result.length} entities`));
|
|
2057
2069
|
console.log();
|
|
2058
2070
|
|
|
2059
|
-
const data = [[
|
|
2071
|
+
const data = [['ID', 'Label', 'Type', 'Description', 'Emoji']];
|
|
2060
2072
|
|
|
2061
2073
|
result.forEach((entity) => {
|
|
2062
2074
|
data.push([
|
|
2063
|
-
(entity.id ||
|
|
2064
|
-
entity.label ||
|
|
2065
|
-
entity.type ||
|
|
2066
|
-
(entity.description ||
|
|
2075
|
+
(entity.id || 'N/A').substring(0, 20) + '...',
|
|
2076
|
+
entity.label || 'N/A',
|
|
2077
|
+
entity.type || 'N/A',
|
|
2078
|
+
(entity.description || 'N/A').substring(0, 30) +
|
|
2067
2079
|
(entity.description && entity.description.length > 30
|
|
2068
|
-
?
|
|
2069
|
-
:
|
|
2070
|
-
entity.emoji ||
|
|
2080
|
+
? '...'
|
|
2081
|
+
: ''),
|
|
2082
|
+
entity.emoji || 'N/A',
|
|
2071
2083
|
]);
|
|
2072
2084
|
});
|
|
2073
2085
|
|
|
@@ -2076,7 +2088,7 @@ program
|
|
|
2076
2088
|
// Note: total count not available in flat array response
|
|
2077
2089
|
|
|
2078
2090
|
if (options.verbose && result) {
|
|
2079
|
-
console.log(chalk.dim(
|
|
2091
|
+
console.log(chalk.dim('\nAPI Response:'));
|
|
2080
2092
|
console.log(chalk.dim(JSON.stringify(result, null, 2)));
|
|
2081
2093
|
}
|
|
2082
2094
|
}
|
|
@@ -2088,19 +2100,19 @@ program
|
|
|
2088
2100
|
|
|
2089
2101
|
// Create folder command
|
|
2090
2102
|
program
|
|
2091
|
-
.command(
|
|
2092
|
-
.description(
|
|
2093
|
-
.argument(
|
|
2103
|
+
.command('create-folder')
|
|
2104
|
+
.description('Create a new folder with specified name')
|
|
2105
|
+
.argument('<name>', 'Folder name')
|
|
2094
2106
|
.option(
|
|
2095
|
-
|
|
2096
|
-
|
|
2107
|
+
'--user-id <id>',
|
|
2108
|
+
'User ID (optional, uses configured value if not provided)'
|
|
2097
2109
|
)
|
|
2098
|
-
.option(
|
|
2099
|
-
.option(
|
|
2100
|
-
.option(
|
|
2101
|
-
.option(
|
|
2102
|
-
.option(
|
|
2103
|
-
.option(
|
|
2110
|
+
.option('--description <desc>', 'Folder description')
|
|
2111
|
+
.option('--emoji <emoji>', 'Folder emoji')
|
|
2112
|
+
.option('--status <status>', 'Folder status')
|
|
2113
|
+
.option('--parent <id>', 'Parent folder ID')
|
|
2114
|
+
.option('-o, --output <format>', 'Output format (json|text)', 'text')
|
|
2115
|
+
.option('-v, --verbose', 'Show detailed creation information')
|
|
2104
2116
|
.action(async (name, options, command) => {
|
|
2105
2117
|
try {
|
|
2106
2118
|
const globalOptions = command.parent.opts();
|
|
@@ -2120,7 +2132,7 @@ program
|
|
|
2120
2132
|
|
|
2121
2133
|
console.log(chalk.cyan(`Creating folder "${name}"...`));
|
|
2122
2134
|
|
|
2123
|
-
const spinner = ora(
|
|
2135
|
+
const spinner = ora('Creating folder...').start();
|
|
2124
2136
|
|
|
2125
2137
|
const result = await api.createFolder(
|
|
2126
2138
|
userId,
|
|
@@ -2133,35 +2145,35 @@ program
|
|
|
2133
2145
|
|
|
2134
2146
|
spinner.stop();
|
|
2135
2147
|
|
|
2136
|
-
if (options.output ===
|
|
2148
|
+
if (options.output === 'json') {
|
|
2137
2149
|
console.log(JSON.stringify(result, null, 2));
|
|
2138
2150
|
} else {
|
|
2139
|
-
console.log(chalk.green.bold(
|
|
2151
|
+
console.log(chalk.green.bold('ā
Folder created successfully!'));
|
|
2140
2152
|
console.log();
|
|
2141
2153
|
|
|
2142
2154
|
const data = [
|
|
2143
|
-
[
|
|
2144
|
-
[
|
|
2145
|
-
[
|
|
2146
|
-
[
|
|
2147
|
-
[
|
|
2148
|
-
[
|
|
2149
|
-
[
|
|
2150
|
-
[
|
|
2151
|
-
[
|
|
2155
|
+
['Field', 'Value'],
|
|
2156
|
+
['ID', result.id || 'N/A'],
|
|
2157
|
+
['Name', result.name],
|
|
2158
|
+
['Description', result.description || 'N/A'],
|
|
2159
|
+
['Emoji', result.emoji || 'N/A'],
|
|
2160
|
+
['Status', result.status || 'N/A'],
|
|
2161
|
+
['Parent', result.parent || 'N/A'],
|
|
2162
|
+
['Workspace ID', result.workspaceID],
|
|
2163
|
+
['Created By', result.createdBy],
|
|
2152
2164
|
];
|
|
2153
2165
|
|
|
2154
2166
|
console.log(
|
|
2155
2167
|
table(data, {
|
|
2156
2168
|
header: {
|
|
2157
|
-
alignment:
|
|
2158
|
-
content:
|
|
2169
|
+
alignment: 'center',
|
|
2170
|
+
content: 'Folder Details',
|
|
2159
2171
|
},
|
|
2160
2172
|
})
|
|
2161
2173
|
);
|
|
2162
2174
|
|
|
2163
2175
|
if (options.verbose && result) {
|
|
2164
|
-
console.log(chalk.dim(
|
|
2176
|
+
console.log(chalk.dim('\nAPI Response:'));
|
|
2165
2177
|
console.log(chalk.dim(JSON.stringify(result, null, 2)));
|
|
2166
2178
|
}
|
|
2167
2179
|
}
|
|
@@ -2173,16 +2185,16 @@ program
|
|
|
2173
2185
|
|
|
2174
2186
|
// Update folder command
|
|
2175
2187
|
program
|
|
2176
|
-
.command(
|
|
2177
|
-
.description(
|
|
2178
|
-
.argument(
|
|
2179
|
-
.option(
|
|
2180
|
-
.option(
|
|
2181
|
-
.option(
|
|
2182
|
-
.option(
|
|
2183
|
-
.option(
|
|
2184
|
-
.option(
|
|
2185
|
-
.option(
|
|
2188
|
+
.command('update-folder')
|
|
2189
|
+
.description('Update an existing folder')
|
|
2190
|
+
.argument('<id>', 'Folder ID')
|
|
2191
|
+
.option('--name <name>', 'New folder name')
|
|
2192
|
+
.option('--description <desc>', 'New folder description')
|
|
2193
|
+
.option('--emoji <emoji>', 'New folder emoji')
|
|
2194
|
+
.option('--status <status>', 'New folder status')
|
|
2195
|
+
.option('--parent <id>', 'New parent folder ID')
|
|
2196
|
+
.option('-o, --output <format>', 'Output format (json|text)', 'text')
|
|
2197
|
+
.option('-v, --verbose', 'Show detailed update information')
|
|
2186
2198
|
.action(async (folderId, options, command) => {
|
|
2187
2199
|
try {
|
|
2188
2200
|
const globalOptions = command.parent.opts();
|
|
@@ -2200,7 +2212,7 @@ program
|
|
|
2200
2212
|
|
|
2201
2213
|
console.log(chalk.cyan(`Updating folder ${folderId}...`));
|
|
2202
2214
|
|
|
2203
|
-
const spinner = ora(
|
|
2215
|
+
const spinner = ora('Updating folder...').start();
|
|
2204
2216
|
|
|
2205
2217
|
const result = await api.updateFolder(
|
|
2206
2218
|
folderId,
|
|
@@ -2213,33 +2225,33 @@ program
|
|
|
2213
2225
|
|
|
2214
2226
|
spinner.stop();
|
|
2215
2227
|
|
|
2216
|
-
if (options.output ===
|
|
2228
|
+
if (options.output === 'json') {
|
|
2217
2229
|
console.log(JSON.stringify(result, null, 2));
|
|
2218
2230
|
} else {
|
|
2219
|
-
console.log(chalk.green.bold(
|
|
2231
|
+
console.log(chalk.green.bold('ā
Folder updated successfully!'));
|
|
2220
2232
|
console.log();
|
|
2221
2233
|
|
|
2222
2234
|
const data = [
|
|
2223
|
-
[
|
|
2224
|
-
[
|
|
2225
|
-
[
|
|
2226
|
-
[
|
|
2227
|
-
[
|
|
2228
|
-
[
|
|
2229
|
-
[
|
|
2235
|
+
['Field', 'Value'],
|
|
2236
|
+
['ID', result.id || folderId],
|
|
2237
|
+
['Name', result.name || 'N/A'],
|
|
2238
|
+
['Description', result.description || 'N/A'],
|
|
2239
|
+
['Emoji', result.emoji || 'N/A'],
|
|
2240
|
+
['Status', result.status || 'N/A'],
|
|
2241
|
+
['Parent', result.parent || 'N/A'],
|
|
2230
2242
|
];
|
|
2231
2243
|
|
|
2232
2244
|
console.log(
|
|
2233
2245
|
table(data, {
|
|
2234
2246
|
header: {
|
|
2235
|
-
alignment:
|
|
2236
|
-
content:
|
|
2247
|
+
alignment: 'center',
|
|
2248
|
+
content: 'Updated Folder Details',
|
|
2237
2249
|
},
|
|
2238
2250
|
})
|
|
2239
2251
|
);
|
|
2240
2252
|
|
|
2241
2253
|
if (options.verbose && result) {
|
|
2242
|
-
console.log(chalk.dim(
|
|
2254
|
+
console.log(chalk.dim('\nAPI Response:'));
|
|
2243
2255
|
console.log(chalk.dim(JSON.stringify(result, null, 2)));
|
|
2244
2256
|
}
|
|
2245
2257
|
}
|
|
@@ -2251,11 +2263,11 @@ program
|
|
|
2251
2263
|
|
|
2252
2264
|
// Get folder command
|
|
2253
2265
|
program
|
|
2254
|
-
.command(
|
|
2255
|
-
.description(
|
|
2256
|
-
.argument(
|
|
2257
|
-
.option(
|
|
2258
|
-
.option(
|
|
2266
|
+
.command('get-folder')
|
|
2267
|
+
.description('Get details of a specific folder')
|
|
2268
|
+
.argument('<id>', 'Folder ID')
|
|
2269
|
+
.option('-o, --output <format>', 'Output format (json|text)', 'text')
|
|
2270
|
+
.option('-v, --verbose', 'Show detailed information')
|
|
2259
2271
|
.action(async (folderId, options, command) => {
|
|
2260
2272
|
try {
|
|
2261
2273
|
const globalOptions = command.parent.opts();
|
|
@@ -2273,23 +2285,23 @@ program
|
|
|
2273
2285
|
|
|
2274
2286
|
console.log(chalk.cyan(`Fetching folder ${folderId}...`));
|
|
2275
2287
|
|
|
2276
|
-
const spinner = ora(
|
|
2288
|
+
const spinner = ora('Fetching folder...').start();
|
|
2277
2289
|
|
|
2278
2290
|
const folderData = await api.getFolder(folderId);
|
|
2279
2291
|
|
|
2280
2292
|
spinner.stop();
|
|
2281
2293
|
|
|
2282
|
-
if (options.output ===
|
|
2294
|
+
if (options.output === 'json') {
|
|
2283
2295
|
console.log(JSON.stringify(folderData, null, 2));
|
|
2284
2296
|
} else {
|
|
2285
|
-
console.log(chalk.green.bold(
|
|
2297
|
+
console.log(chalk.green.bold('Folder Details'));
|
|
2286
2298
|
console.log();
|
|
2287
2299
|
|
|
2288
|
-
const data = [[
|
|
2300
|
+
const data = [['Field', 'Value']];
|
|
2289
2301
|
|
|
2290
2302
|
Object.entries(folderData).forEach(([key, value]) => {
|
|
2291
2303
|
let displayValue = value;
|
|
2292
|
-
if (typeof value ===
|
|
2304
|
+
if (typeof value === 'object' && value !== null) {
|
|
2293
2305
|
displayValue = JSON.stringify(value, null, 2);
|
|
2294
2306
|
}
|
|
2295
2307
|
data.push([key, String(displayValue)]);
|
|
@@ -2305,12 +2317,12 @@ program
|
|
|
2305
2317
|
|
|
2306
2318
|
// Delete folder command
|
|
2307
2319
|
program
|
|
2308
|
-
.command(
|
|
2309
|
-
.description(
|
|
2310
|
-
.argument(
|
|
2311
|
-
.option(
|
|
2312
|
-
.option(
|
|
2313
|
-
.option(
|
|
2320
|
+
.command('delete-folder')
|
|
2321
|
+
.description('Delete a folder')
|
|
2322
|
+
.argument('<id>', 'Folder ID')
|
|
2323
|
+
.option('--confirm', 'Skip confirmation prompt')
|
|
2324
|
+
.option('-o, --output <format>', 'Output format (json|text)', 'text')
|
|
2325
|
+
.option('-v, --verbose', 'Show detailed deletion information')
|
|
2314
2326
|
.action(async (folderId, options, command) => {
|
|
2315
2327
|
try {
|
|
2316
2328
|
const globalOptions = command.parent.opts();
|
|
@@ -2328,7 +2340,7 @@ program
|
|
|
2328
2340
|
|
|
2329
2341
|
// Confirmation prompt (unless --confirm flag is used)
|
|
2330
2342
|
if (!options.confirm) {
|
|
2331
|
-
const readline = require(
|
|
2343
|
+
const readline = require('readline');
|
|
2332
2344
|
const rl = readline.createInterface({
|
|
2333
2345
|
input: process.stdin,
|
|
2334
2346
|
output: process.stdout,
|
|
@@ -2345,43 +2357,43 @@ program
|
|
|
2345
2357
|
|
|
2346
2358
|
rl.close();
|
|
2347
2359
|
|
|
2348
|
-
if (answer.toLowerCase() !==
|
|
2349
|
-
console.log(chalk.gray(
|
|
2360
|
+
if (answer.toLowerCase() !== 'y' && answer.toLowerCase() !== 'yes') {
|
|
2361
|
+
console.log(chalk.gray('Deletion cancelled.'));
|
|
2350
2362
|
process.exit(0);
|
|
2351
2363
|
}
|
|
2352
2364
|
}
|
|
2353
2365
|
|
|
2354
2366
|
console.log(chalk.cyan(`Deleting folder ${folderId}...`));
|
|
2355
2367
|
|
|
2356
|
-
const spinner = ora(
|
|
2368
|
+
const spinner = ora('Deleting folder...').start();
|
|
2357
2369
|
|
|
2358
2370
|
const result = await api.deleteFolder(folderId);
|
|
2359
2371
|
|
|
2360
2372
|
spinner.stop();
|
|
2361
2373
|
|
|
2362
|
-
if (options.output ===
|
|
2374
|
+
if (options.output === 'json') {
|
|
2363
2375
|
console.log(JSON.stringify(result, null, 2));
|
|
2364
2376
|
} else {
|
|
2365
|
-
console.log(chalk.green.bold(
|
|
2377
|
+
console.log(chalk.green.bold('ā
Folder deleted successfully!'));
|
|
2366
2378
|
console.log();
|
|
2367
2379
|
|
|
2368
2380
|
const data = [
|
|
2369
|
-
[
|
|
2370
|
-
[
|
|
2371
|
-
[
|
|
2381
|
+
['Field', 'Value'],
|
|
2382
|
+
['Folder ID', folderId],
|
|
2383
|
+
['Status', 'Deleted'],
|
|
2372
2384
|
];
|
|
2373
2385
|
|
|
2374
2386
|
console.log(
|
|
2375
2387
|
table(data, {
|
|
2376
2388
|
header: {
|
|
2377
|
-
alignment:
|
|
2378
|
-
content:
|
|
2389
|
+
alignment: 'center',
|
|
2390
|
+
content: 'Deletion Details',
|
|
2379
2391
|
},
|
|
2380
2392
|
})
|
|
2381
2393
|
);
|
|
2382
2394
|
|
|
2383
2395
|
if (options.verbose && result) {
|
|
2384
|
-
console.log(chalk.dim(
|
|
2396
|
+
console.log(chalk.dim('\nAPI Response:'));
|
|
2385
2397
|
console.log(chalk.dim(JSON.stringify(result, null, 2)));
|
|
2386
2398
|
}
|
|
2387
2399
|
}
|
|
@@ -2393,13 +2405,13 @@ program
|
|
|
2393
2405
|
|
|
2394
2406
|
// List folders command
|
|
2395
2407
|
program
|
|
2396
|
-
.command(
|
|
2397
|
-
.description(
|
|
2398
|
-
.option(
|
|
2399
|
-
.option(
|
|
2400
|
-
.option(
|
|
2401
|
-
.option(
|
|
2402
|
-
.option(
|
|
2408
|
+
.command('list-folders')
|
|
2409
|
+
.description('List all folders in the workspace')
|
|
2410
|
+
.option('--status <status>', 'Filter by folder status')
|
|
2411
|
+
.option('--limit <number>', 'Maximum number of folders to return', '50')
|
|
2412
|
+
.option('--offset <number>', 'Number of folders to skip', '0')
|
|
2413
|
+
.option('-o, --output <format>', 'Output format (json|text)', 'text')
|
|
2414
|
+
.option('-v, --verbose', 'Show detailed information')
|
|
2403
2415
|
.action(async (options, command) => {
|
|
2404
2416
|
try {
|
|
2405
2417
|
const globalOptions = command.parent.opts();
|
|
@@ -2415,9 +2427,9 @@ program
|
|
|
2415
2427
|
globalOptions.verbose || options.verbose
|
|
2416
2428
|
);
|
|
2417
2429
|
|
|
2418
|
-
console.log(chalk.cyan(
|
|
2430
|
+
console.log(chalk.cyan('Fetching folders...'));
|
|
2419
2431
|
|
|
2420
|
-
const spinner = ora(
|
|
2432
|
+
const spinner = ora('Loading folders...').start();
|
|
2421
2433
|
|
|
2422
2434
|
const result = await api.listFolders(
|
|
2423
2435
|
options.status,
|
|
@@ -2427,29 +2439,29 @@ program
|
|
|
2427
2439
|
|
|
2428
2440
|
spinner.stop();
|
|
2429
2441
|
|
|
2430
|
-
if (options.output ===
|
|
2442
|
+
if (options.output === 'json') {
|
|
2431
2443
|
console.log(JSON.stringify(result, null, 2));
|
|
2432
2444
|
} else {
|
|
2433
2445
|
if (!result || result.length === 0) {
|
|
2434
|
-
console.log(chalk.yellow(
|
|
2446
|
+
console.log(chalk.yellow('No folders found.'));
|
|
2435
2447
|
return;
|
|
2436
2448
|
}
|
|
2437
2449
|
|
|
2438
2450
|
console.log(chalk.green.bold(`Found ${result.length} folders`));
|
|
2439
2451
|
console.log();
|
|
2440
2452
|
|
|
2441
|
-
const data = [[
|
|
2453
|
+
const data = [['ID', 'Name', 'Description', 'Status', 'Emoji']];
|
|
2442
2454
|
|
|
2443
2455
|
result.forEach((folder) => {
|
|
2444
2456
|
data.push([
|
|
2445
|
-
(folder.id ||
|
|
2446
|
-
folder.name ||
|
|
2447
|
-
(folder.description ||
|
|
2457
|
+
(folder.id || 'N/A').substring(0, 20) + '...',
|
|
2458
|
+
folder.name || 'N/A',
|
|
2459
|
+
(folder.description || 'N/A').substring(0, 30) +
|
|
2448
2460
|
(folder.description && folder.description.length > 30
|
|
2449
|
-
?
|
|
2450
|
-
:
|
|
2451
|
-
folder.status ||
|
|
2452
|
-
folder.emoji ||
|
|
2461
|
+
? '...'
|
|
2462
|
+
: ''),
|
|
2463
|
+
folder.status || 'N/A',
|
|
2464
|
+
folder.emoji || 'N/A',
|
|
2453
2465
|
]);
|
|
2454
2466
|
});
|
|
2455
2467
|
|
|
@@ -2458,7 +2470,7 @@ program
|
|
|
2458
2470
|
// Note: total count not available in flat array response
|
|
2459
2471
|
|
|
2460
2472
|
if (options.verbose && result) {
|
|
2461
|
-
console.log(chalk.dim(
|
|
2473
|
+
console.log(chalk.dim('\nAPI Response:'));
|
|
2462
2474
|
console.log(chalk.dim(JSON.stringify(result, null, 2)));
|
|
2463
2475
|
}
|
|
2464
2476
|
}
|
|
@@ -2470,23 +2482,23 @@ program
|
|
|
2470
2482
|
|
|
2471
2483
|
// Create prompt command
|
|
2472
2484
|
program
|
|
2473
|
-
.command(
|
|
2474
|
-
.description(
|
|
2475
|
-
.argument(
|
|
2476
|
-
.argument(
|
|
2477
|
-
.argument(
|
|
2478
|
-
.argument(
|
|
2485
|
+
.command('create-prompt')
|
|
2486
|
+
.description('Create a new prompt with specified parameters')
|
|
2487
|
+
.argument('<type>', 'Prompt type')
|
|
2488
|
+
.argument('<label>', 'Prompt label')
|
|
2489
|
+
.argument('<prompt-length>', 'Prompt length (number)')
|
|
2490
|
+
.argument('<interpolation-string>', 'Interpolation string')
|
|
2479
2491
|
.option(
|
|
2480
|
-
|
|
2481
|
-
|
|
2492
|
+
'--user-id <id>',
|
|
2493
|
+
'User ID (optional, uses configured value if not provided)'
|
|
2482
2494
|
)
|
|
2483
|
-
.option(
|
|
2484
|
-
.option(
|
|
2485
|
-
.option(
|
|
2486
|
-
.option(
|
|
2487
|
-
.option(
|
|
2488
|
-
.option(
|
|
2489
|
-
.option(
|
|
2495
|
+
.option('--scope <scope>', 'Prompt scope')
|
|
2496
|
+
.option('--style <style>', 'Prompt style')
|
|
2497
|
+
.option('--domain <domain>', 'Prompt domain')
|
|
2498
|
+
.option('--prompt-placeholder <placeholder>', 'Prompt placeholder')
|
|
2499
|
+
.option('--available-to-agents <agents>', 'Comma-separated agent IDs')
|
|
2500
|
+
.option('-o, --output <format>', 'Output format (json|text)', 'text')
|
|
2501
|
+
.option('-v, --verbose', 'Show detailed creation information')
|
|
2490
2502
|
.action(
|
|
2491
2503
|
async (
|
|
2492
2504
|
type,
|
|
@@ -2505,7 +2517,7 @@ program
|
|
|
2505
2517
|
const parsedPromptLength = parseFloat(promptLength);
|
|
2506
2518
|
if (isNaN(parsedPromptLength)) {
|
|
2507
2519
|
console.error(
|
|
2508
|
-
chalk.red(
|
|
2520
|
+
chalk.red('Error: Prompt length must be a valid number')
|
|
2509
2521
|
);
|
|
2510
2522
|
process.exit(1);
|
|
2511
2523
|
}
|
|
@@ -2514,7 +2526,7 @@ program
|
|
|
2514
2526
|
let availableToAgents = null;
|
|
2515
2527
|
if (options.availableToAgents) {
|
|
2516
2528
|
availableToAgents = options.availableToAgents
|
|
2517
|
-
.split(
|
|
2529
|
+
.split(',')
|
|
2518
2530
|
.map((id) => id.trim())
|
|
2519
2531
|
.filter((id) => id);
|
|
2520
2532
|
}
|
|
@@ -2534,7 +2546,7 @@ program
|
|
|
2534
2546
|
chalk.cyan(`Creating prompt "${label}" of type "${type}"...`)
|
|
2535
2547
|
);
|
|
2536
2548
|
|
|
2537
|
-
const spinner = ora(
|
|
2549
|
+
const spinner = ora('Creating prompt...').start();
|
|
2538
2550
|
|
|
2539
2551
|
const result = await api.createPrompt(
|
|
2540
2552
|
userId,
|
|
@@ -2551,44 +2563,44 @@ program
|
|
|
2551
2563
|
|
|
2552
2564
|
spinner.stop();
|
|
2553
2565
|
|
|
2554
|
-
if (options.output ===
|
|
2566
|
+
if (options.output === 'json') {
|
|
2555
2567
|
console.log(JSON.stringify(result, null, 2));
|
|
2556
2568
|
} else {
|
|
2557
|
-
console.log(chalk.green.bold(
|
|
2569
|
+
console.log(chalk.green.bold('ā
Prompt created successfully!'));
|
|
2558
2570
|
console.log();
|
|
2559
2571
|
|
|
2560
2572
|
const data = [
|
|
2561
|
-
[
|
|
2562
|
-
[
|
|
2563
|
-
[
|
|
2564
|
-
[
|
|
2565
|
-
[
|
|
2566
|
-
[
|
|
2567
|
-
[
|
|
2568
|
-
[
|
|
2569
|
-
[
|
|
2570
|
-
[
|
|
2573
|
+
['Field', 'Value'],
|
|
2574
|
+
['ID', result.id || 'N/A'],
|
|
2575
|
+
['Type', result.type],
|
|
2576
|
+
['Label', result.label],
|
|
2577
|
+
['Prompt Length', result.promptLength],
|
|
2578
|
+
['Interpolation String', result.interpolationString],
|
|
2579
|
+
['Scope', result.scope || 'N/A'],
|
|
2580
|
+
['Style', result.style || 'N/A'],
|
|
2581
|
+
['Domain', result.domain || 'N/A'],
|
|
2582
|
+
['Prompt Placeholder', result.promptPlaceholder || 'N/A'],
|
|
2571
2583
|
[
|
|
2572
|
-
|
|
2584
|
+
'Available To Agents',
|
|
2573
2585
|
result.availableToAgents
|
|
2574
|
-
? result.availableToAgents.join(
|
|
2575
|
-
:
|
|
2586
|
+
? result.availableToAgents.join(', ')
|
|
2587
|
+
: 'N/A',
|
|
2576
2588
|
],
|
|
2577
|
-
[
|
|
2578
|
-
[
|
|
2589
|
+
['Workspace ID', result.workspaceID],
|
|
2590
|
+
['Created By', result.createdBy],
|
|
2579
2591
|
];
|
|
2580
2592
|
|
|
2581
2593
|
console.log(
|
|
2582
2594
|
table(data, {
|
|
2583
2595
|
header: {
|
|
2584
|
-
alignment:
|
|
2585
|
-
content:
|
|
2596
|
+
alignment: 'center',
|
|
2597
|
+
content: 'Prompt Details',
|
|
2586
2598
|
},
|
|
2587
2599
|
})
|
|
2588
2600
|
);
|
|
2589
2601
|
|
|
2590
2602
|
if (options.verbose && result) {
|
|
2591
|
-
console.log(chalk.dim(
|
|
2603
|
+
console.log(chalk.dim('\nAPI Response:'));
|
|
2592
2604
|
console.log(chalk.dim(JSON.stringify(result, null, 2)));
|
|
2593
2605
|
}
|
|
2594
2606
|
}
|
|
@@ -2601,20 +2613,20 @@ program
|
|
|
2601
2613
|
|
|
2602
2614
|
// Update prompt command
|
|
2603
2615
|
program
|
|
2604
|
-
.command(
|
|
2605
|
-
.description(
|
|
2606
|
-
.argument(
|
|
2607
|
-
.option(
|
|
2608
|
-
.option(
|
|
2609
|
-
.option(
|
|
2610
|
-
.option(
|
|
2611
|
-
.option(
|
|
2612
|
-
.option(
|
|
2613
|
-
.option(
|
|
2614
|
-
.option(
|
|
2615
|
-
.option(
|
|
2616
|
-
.option(
|
|
2617
|
-
.option(
|
|
2616
|
+
.command('update-prompt')
|
|
2617
|
+
.description('Update an existing prompt')
|
|
2618
|
+
.argument('<id>', 'Prompt ID')
|
|
2619
|
+
.option('--type <type>', 'New prompt type')
|
|
2620
|
+
.option('--label <label>', 'New prompt label')
|
|
2621
|
+
.option('--prompt-length <length>', 'New prompt length (number)')
|
|
2622
|
+
.option('--interpolation-string <string>', 'New interpolation string')
|
|
2623
|
+
.option('--scope <scope>', 'New prompt scope')
|
|
2624
|
+
.option('--style <style>', 'New prompt style')
|
|
2625
|
+
.option('--domain <domain>', 'New prompt domain')
|
|
2626
|
+
.option('--prompt-placeholder <placeholder>', 'New prompt placeholder')
|
|
2627
|
+
.option('--available-to-agents <agents>', 'New comma-separated agent IDs')
|
|
2628
|
+
.option('-o, --output <format>', 'Output format (json|text)', 'text')
|
|
2629
|
+
.option('-v, --verbose', 'Show detailed update information')
|
|
2618
2630
|
.action(async (promptId, options, command) => {
|
|
2619
2631
|
try {
|
|
2620
2632
|
const globalOptions = command.parent.opts();
|
|
@@ -2627,7 +2639,7 @@ program
|
|
|
2627
2639
|
parsedPromptLength = parseFloat(options.promptLength);
|
|
2628
2640
|
if (isNaN(parsedPromptLength)) {
|
|
2629
2641
|
console.error(
|
|
2630
|
-
chalk.red(
|
|
2642
|
+
chalk.red('Error: Prompt length must be a valid number')
|
|
2631
2643
|
);
|
|
2632
2644
|
process.exit(1);
|
|
2633
2645
|
}
|
|
@@ -2637,7 +2649,7 @@ program
|
|
|
2637
2649
|
let availableToAgents = null;
|
|
2638
2650
|
if (options.availableToAgents) {
|
|
2639
2651
|
availableToAgents = options.availableToAgents
|
|
2640
|
-
.split(
|
|
2652
|
+
.split(',')
|
|
2641
2653
|
.map((id) => id.trim())
|
|
2642
2654
|
.filter((id) => id);
|
|
2643
2655
|
}
|
|
@@ -2653,7 +2665,7 @@ program
|
|
|
2653
2665
|
|
|
2654
2666
|
console.log(chalk.cyan(`Updating prompt ${promptId}...`));
|
|
2655
2667
|
|
|
2656
|
-
const spinner = ora(
|
|
2668
|
+
const spinner = ora('Updating prompt...').start();
|
|
2657
2669
|
|
|
2658
2670
|
const result = await api.updatePrompt(
|
|
2659
2671
|
promptId,
|
|
@@ -2670,42 +2682,42 @@ program
|
|
|
2670
2682
|
|
|
2671
2683
|
spinner.stop();
|
|
2672
2684
|
|
|
2673
|
-
if (options.output ===
|
|
2685
|
+
if (options.output === 'json') {
|
|
2674
2686
|
console.log(JSON.stringify(result, null, 2));
|
|
2675
2687
|
} else {
|
|
2676
|
-
console.log(chalk.green.bold(
|
|
2688
|
+
console.log(chalk.green.bold('ā
Prompt updated successfully!'));
|
|
2677
2689
|
console.log();
|
|
2678
2690
|
|
|
2679
2691
|
const data = [
|
|
2680
|
-
[
|
|
2681
|
-
[
|
|
2682
|
-
[
|
|
2683
|
-
[
|
|
2684
|
-
[
|
|
2685
|
-
[
|
|
2686
|
-
[
|
|
2687
|
-
[
|
|
2688
|
-
[
|
|
2689
|
-
[
|
|
2692
|
+
['Field', 'Value'],
|
|
2693
|
+
['ID', result.id || promptId],
|
|
2694
|
+
['Type', result.type || 'N/A'],
|
|
2695
|
+
['Label', result.label || 'N/A'],
|
|
2696
|
+
['Prompt Length', result.promptLength || 'N/A'],
|
|
2697
|
+
['Interpolation String', result.interpolationString || 'N/A'],
|
|
2698
|
+
['Scope', result.scope || 'N/A'],
|
|
2699
|
+
['Style', result.style || 'N/A'],
|
|
2700
|
+
['Domain', result.domain || 'N/A'],
|
|
2701
|
+
['Prompt Placeholder', result.promptPlaceholder || 'N/A'],
|
|
2690
2702
|
[
|
|
2691
|
-
|
|
2703
|
+
'Available To Agents',
|
|
2692
2704
|
result.availableToAgents
|
|
2693
|
-
? result.availableToAgents.join(
|
|
2694
|
-
:
|
|
2705
|
+
? result.availableToAgents.join(', ')
|
|
2706
|
+
: 'N/A',
|
|
2695
2707
|
],
|
|
2696
2708
|
];
|
|
2697
2709
|
|
|
2698
2710
|
console.log(
|
|
2699
2711
|
table(data, {
|
|
2700
2712
|
header: {
|
|
2701
|
-
alignment:
|
|
2702
|
-
content:
|
|
2713
|
+
alignment: 'center',
|
|
2714
|
+
content: 'Updated Prompt Details',
|
|
2703
2715
|
},
|
|
2704
2716
|
})
|
|
2705
2717
|
);
|
|
2706
2718
|
|
|
2707
2719
|
if (options.verbose && result) {
|
|
2708
|
-
console.log(chalk.dim(
|
|
2720
|
+
console.log(chalk.dim('\nAPI Response:'));
|
|
2709
2721
|
console.log(chalk.dim(JSON.stringify(result, null, 2)));
|
|
2710
2722
|
}
|
|
2711
2723
|
}
|
|
@@ -2717,11 +2729,11 @@ program
|
|
|
2717
2729
|
|
|
2718
2730
|
// Get prompt command
|
|
2719
2731
|
program
|
|
2720
|
-
.command(
|
|
2721
|
-
.description(
|
|
2722
|
-
.argument(
|
|
2723
|
-
.option(
|
|
2724
|
-
.option(
|
|
2732
|
+
.command('get-prompt')
|
|
2733
|
+
.description('Get details of a specific prompt')
|
|
2734
|
+
.argument('<id>', 'Prompt ID')
|
|
2735
|
+
.option('-o, --output <format>', 'Output format (json|text)', 'text')
|
|
2736
|
+
.option('-v, --verbose', 'Show detailed information')
|
|
2725
2737
|
.action(async (promptId, options, command) => {
|
|
2726
2738
|
try {
|
|
2727
2739
|
const globalOptions = command.parent.opts();
|
|
@@ -2739,23 +2751,23 @@ program
|
|
|
2739
2751
|
|
|
2740
2752
|
console.log(chalk.cyan(`Fetching prompt ${promptId}...`));
|
|
2741
2753
|
|
|
2742
|
-
const spinner = ora(
|
|
2754
|
+
const spinner = ora('Fetching prompt...').start();
|
|
2743
2755
|
|
|
2744
2756
|
const promptData = await api.getPrompt(promptId);
|
|
2745
2757
|
|
|
2746
2758
|
spinner.stop();
|
|
2747
2759
|
|
|
2748
|
-
if (options.output ===
|
|
2760
|
+
if (options.output === 'json') {
|
|
2749
2761
|
console.log(JSON.stringify(promptData, null, 2));
|
|
2750
2762
|
} else {
|
|
2751
|
-
console.log(chalk.green.bold(
|
|
2763
|
+
console.log(chalk.green.bold('Prompt Details'));
|
|
2752
2764
|
console.log();
|
|
2753
2765
|
|
|
2754
|
-
const data = [[
|
|
2766
|
+
const data = [['Field', 'Value']];
|
|
2755
2767
|
|
|
2756
2768
|
Object.entries(promptData).forEach(([key, value]) => {
|
|
2757
2769
|
let displayValue = value;
|
|
2758
|
-
if (typeof value ===
|
|
2770
|
+
if (typeof value === 'object' && value !== null) {
|
|
2759
2771
|
displayValue = JSON.stringify(value, null, 2);
|
|
2760
2772
|
}
|
|
2761
2773
|
data.push([key, String(displayValue)]);
|
|
@@ -2771,12 +2783,12 @@ program
|
|
|
2771
2783
|
|
|
2772
2784
|
// Delete prompt command
|
|
2773
2785
|
program
|
|
2774
|
-
.command(
|
|
2775
|
-
.description(
|
|
2776
|
-
.argument(
|
|
2777
|
-
.option(
|
|
2778
|
-
.option(
|
|
2779
|
-
.option(
|
|
2786
|
+
.command('delete-prompt')
|
|
2787
|
+
.description('Delete a prompt')
|
|
2788
|
+
.argument('<id>', 'Prompt ID')
|
|
2789
|
+
.option('--confirm', 'Skip confirmation prompt')
|
|
2790
|
+
.option('-o, --output <format>', 'Output format (json|text)', 'text')
|
|
2791
|
+
.option('-v, --verbose', 'Show detailed deletion information')
|
|
2780
2792
|
.action(async (promptId, options, command) => {
|
|
2781
2793
|
try {
|
|
2782
2794
|
const globalOptions = command.parent.opts();
|
|
@@ -2794,7 +2806,7 @@ program
|
|
|
2794
2806
|
|
|
2795
2807
|
// Confirmation prompt (unless --confirm flag is used)
|
|
2796
2808
|
if (!options.confirm) {
|
|
2797
|
-
const readline = require(
|
|
2809
|
+
const readline = require('readline');
|
|
2798
2810
|
const rl = readline.createInterface({
|
|
2799
2811
|
input: process.stdin,
|
|
2800
2812
|
output: process.stdout,
|
|
@@ -2811,43 +2823,43 @@ program
|
|
|
2811
2823
|
|
|
2812
2824
|
rl.close();
|
|
2813
2825
|
|
|
2814
|
-
if (answer.toLowerCase() !==
|
|
2815
|
-
console.log(chalk.gray(
|
|
2826
|
+
if (answer.toLowerCase() !== 'y' && answer.toLowerCase() !== 'yes') {
|
|
2827
|
+
console.log(chalk.gray('Deletion cancelled.'));
|
|
2816
2828
|
process.exit(0);
|
|
2817
2829
|
}
|
|
2818
2830
|
}
|
|
2819
2831
|
|
|
2820
2832
|
console.log(chalk.cyan(`Deleting prompt ${promptId}...`));
|
|
2821
2833
|
|
|
2822
|
-
const spinner = ora(
|
|
2834
|
+
const spinner = ora('Deleting prompt...').start();
|
|
2823
2835
|
|
|
2824
2836
|
const result = await api.deletePrompt(promptId);
|
|
2825
2837
|
|
|
2826
2838
|
spinner.stop();
|
|
2827
2839
|
|
|
2828
|
-
if (options.output ===
|
|
2840
|
+
if (options.output === 'json') {
|
|
2829
2841
|
console.log(JSON.stringify(result, null, 2));
|
|
2830
2842
|
} else {
|
|
2831
|
-
console.log(chalk.green.bold(
|
|
2843
|
+
console.log(chalk.green.bold('ā
Prompt deleted successfully!'));
|
|
2832
2844
|
console.log();
|
|
2833
2845
|
|
|
2834
2846
|
const data = [
|
|
2835
|
-
[
|
|
2836
|
-
[
|
|
2837
|
-
[
|
|
2847
|
+
['Field', 'Value'],
|
|
2848
|
+
['Prompt ID', promptId],
|
|
2849
|
+
['Status', 'Deleted'],
|
|
2838
2850
|
];
|
|
2839
2851
|
|
|
2840
2852
|
console.log(
|
|
2841
2853
|
table(data, {
|
|
2842
2854
|
header: {
|
|
2843
|
-
alignment:
|
|
2844
|
-
content:
|
|
2855
|
+
alignment: 'center',
|
|
2856
|
+
content: 'Deletion Details',
|
|
2845
2857
|
},
|
|
2846
2858
|
})
|
|
2847
2859
|
);
|
|
2848
2860
|
|
|
2849
2861
|
if (options.verbose && result) {
|
|
2850
|
-
console.log(chalk.dim(
|
|
2862
|
+
console.log(chalk.dim('\nAPI Response:'));
|
|
2851
2863
|
console.log(chalk.dim(JSON.stringify(result, null, 2)));
|
|
2852
2864
|
}
|
|
2853
2865
|
}
|
|
@@ -2859,13 +2871,13 @@ program
|
|
|
2859
2871
|
|
|
2860
2872
|
// List prompts command
|
|
2861
2873
|
program
|
|
2862
|
-
.command(
|
|
2863
|
-
.description(
|
|
2864
|
-
.option(
|
|
2865
|
-
.option(
|
|
2866
|
-
.option(
|
|
2867
|
-
.option(
|
|
2868
|
-
.option(
|
|
2874
|
+
.command('list-prompts')
|
|
2875
|
+
.description('List all prompts in the workspace')
|
|
2876
|
+
.option('--type <type>', 'Filter by prompt type')
|
|
2877
|
+
.option('--limit <number>', 'Maximum number of prompts to return', '50')
|
|
2878
|
+
.option('--offset <number>', 'Number of prompts to skip', '0')
|
|
2879
|
+
.option('-o, --output <format>', 'Output format (json|text)', 'text')
|
|
2880
|
+
.option('-v, --verbose', 'Show detailed information')
|
|
2869
2881
|
.action(async (options, command) => {
|
|
2870
2882
|
try {
|
|
2871
2883
|
const globalOptions = command.parent.opts();
|
|
@@ -2881,9 +2893,9 @@ program
|
|
|
2881
2893
|
globalOptions.verbose || options.verbose
|
|
2882
2894
|
);
|
|
2883
2895
|
|
|
2884
|
-
console.log(chalk.cyan(
|
|
2896
|
+
console.log(chalk.cyan('Fetching prompts...'));
|
|
2885
2897
|
|
|
2886
|
-
const spinner = ora(
|
|
2898
|
+
const spinner = ora('Loading prompts...').start();
|
|
2887
2899
|
|
|
2888
2900
|
const result = await api.listPrompts(
|
|
2889
2901
|
options.type,
|
|
@@ -2893,27 +2905,27 @@ program
|
|
|
2893
2905
|
|
|
2894
2906
|
spinner.stop();
|
|
2895
2907
|
|
|
2896
|
-
if (options.output ===
|
|
2908
|
+
if (options.output === 'json') {
|
|
2897
2909
|
console.log(JSON.stringify(result, null, 2));
|
|
2898
2910
|
} else {
|
|
2899
2911
|
if (!result || result.length === 0) {
|
|
2900
|
-
console.log(chalk.yellow(
|
|
2912
|
+
console.log(chalk.yellow('No prompts found.'));
|
|
2901
2913
|
return;
|
|
2902
2914
|
}
|
|
2903
2915
|
|
|
2904
2916
|
console.log(chalk.green.bold(`Found ${result.length} prompts`));
|
|
2905
2917
|
console.log();
|
|
2906
2918
|
|
|
2907
|
-
const data = [[
|
|
2919
|
+
const data = [['ID', 'Type', 'Label', 'Length', 'Domain']];
|
|
2908
2920
|
|
|
2909
2921
|
result.forEach((prompt) => {
|
|
2910
2922
|
data.push([
|
|
2911
|
-
(prompt.id ||
|
|
2912
|
-
prompt.type ||
|
|
2913
|
-
(prompt.label ||
|
|
2914
|
-
(prompt.label && prompt.label.length > 30 ?
|
|
2915
|
-
prompt.promptLength ||
|
|
2916
|
-
prompt.domain ||
|
|
2923
|
+
(prompt.id || 'N/A').substring(0, 20) + '...',
|
|
2924
|
+
prompt.type || 'N/A',
|
|
2925
|
+
(prompt.label || 'N/A').substring(0, 30) +
|
|
2926
|
+
(prompt.label && prompt.label.length > 30 ? '...' : ''),
|
|
2927
|
+
prompt.promptLength || 'N/A',
|
|
2928
|
+
prompt.domain || 'N/A',
|
|
2917
2929
|
]);
|
|
2918
2930
|
});
|
|
2919
2931
|
|
|
@@ -2922,7 +2934,7 @@ program
|
|
|
2922
2934
|
// Note: total count not available in flat array response
|
|
2923
2935
|
|
|
2924
2936
|
if (options.verbose && result) {
|
|
2925
|
-
console.log(chalk.dim(
|
|
2937
|
+
console.log(chalk.dim('\nAPI Response:'));
|
|
2926
2938
|
console.log(chalk.dim(JSON.stringify(result, null, 2)));
|
|
2927
2939
|
}
|
|
2928
2940
|
}
|
|
@@ -2934,259 +2946,259 @@ program
|
|
|
2934
2946
|
|
|
2935
2947
|
// Help guide command
|
|
2936
2948
|
program
|
|
2937
|
-
.command(
|
|
2938
|
-
.description(
|
|
2949
|
+
.command('help-guide')
|
|
2950
|
+
.description('Show detailed help and usage examples')
|
|
2939
2951
|
.action(() => {
|
|
2940
|
-
console.log(chalk.cyan.bold(
|
|
2941
|
-
console.log(
|
|
2952
|
+
console.log(chalk.cyan.bold('š ToothFairyAI CLI - Quick Start Guide'));
|
|
2953
|
+
console.log('='.repeat(50));
|
|
2942
2954
|
|
|
2943
|
-
console.log(chalk.green.bold(
|
|
2944
|
-
console.log(
|
|
2955
|
+
console.log(chalk.green.bold('\nš Getting Started'));
|
|
2956
|
+
console.log('1. First, configure your credentials:');
|
|
2945
2957
|
console.log(
|
|
2946
2958
|
chalk.dim(
|
|
2947
|
-
|
|
2959
|
+
' tf configure --api-key YOUR_KEY --workspace-id YOUR_WORKSPACE'
|
|
2948
2960
|
)
|
|
2949
2961
|
);
|
|
2950
2962
|
|
|
2951
|
-
console.log(
|
|
2963
|
+
console.log('\n2. Send a message to an agent:');
|
|
2952
2964
|
console.log(
|
|
2953
2965
|
chalk.dim(' tf send "Hello, I need help" --agent-id YOUR_AGENT_ID')
|
|
2954
2966
|
);
|
|
2955
2967
|
|
|
2956
|
-
console.log(
|
|
2968
|
+
console.log('\n3. Search the knowledge hub:');
|
|
2957
2969
|
console.log(chalk.dim(' tf search "AI configuration help"'));
|
|
2958
2970
|
|
|
2959
|
-
console.log(
|
|
2971
|
+
console.log('\n4. Explore your workspace:');
|
|
2960
2972
|
console.log(
|
|
2961
|
-
chalk.dim(
|
|
2973
|
+
chalk.dim(' tf chats # List all conversations')
|
|
2962
2974
|
);
|
|
2963
2975
|
console.log(
|
|
2964
|
-
chalk.dim(
|
|
2976
|
+
chalk.dim(' tf config-show # View current settings')
|
|
2965
2977
|
);
|
|
2966
2978
|
|
|
2967
|
-
console.log(chalk.blue.bold(
|
|
2979
|
+
console.log(chalk.blue.bold('\nš¬ Agent Communication Examples'));
|
|
2968
2980
|
|
|
2969
2981
|
const agentExamples = [
|
|
2970
2982
|
[
|
|
2971
|
-
|
|
2983
|
+
'Simple message',
|
|
2972
2984
|
'tf send "What are your hours?" --agent-id "info-agent"',
|
|
2973
2985
|
],
|
|
2974
2986
|
[
|
|
2975
|
-
|
|
2987
|
+
'With customer info',
|
|
2976
2988
|
'tf send "Schedule appointment" --agent-id "scheduler" --customer-info \'{"name": "John"}\'',
|
|
2977
2989
|
],
|
|
2978
|
-
[
|
|
2990
|
+
['Verbose output', 'tf send "Hello" --agent-id "agent-123" --verbose'],
|
|
2979
2991
|
[
|
|
2980
|
-
|
|
2992
|
+
'JSON for scripting',
|
|
2981
2993
|
'tf send "Help" --agent-id "agent-123" --output json',
|
|
2982
2994
|
],
|
|
2983
2995
|
];
|
|
2984
2996
|
|
|
2985
|
-
const agentData = [[
|
|
2997
|
+
const agentData = [['Use Case', 'Command'], ...agentExamples];
|
|
2986
2998
|
console.log(
|
|
2987
2999
|
table(agentData, {
|
|
2988
3000
|
header: {
|
|
2989
|
-
alignment:
|
|
2990
|
-
content:
|
|
3001
|
+
alignment: 'center',
|
|
3002
|
+
content: 'Agent Communication',
|
|
2991
3003
|
},
|
|
2992
3004
|
})
|
|
2993
3005
|
);
|
|
2994
3006
|
|
|
2995
|
-
console.log(chalk.magenta.bold(
|
|
3007
|
+
console.log(chalk.magenta.bold('\nš Knowledge Hub Search Examples'));
|
|
2996
3008
|
|
|
2997
3009
|
const searchExamples = [
|
|
2998
|
-
[
|
|
2999
|
-
[
|
|
3000
|
-
[
|
|
3010
|
+
['Basic search', 'tf search "AI agent configuration"'],
|
|
3011
|
+
['Filter by status', 'tf search "machine learning" --status published'],
|
|
3012
|
+
['Limit results', 'tf search "troubleshooting" --top-k 3'],
|
|
3001
3013
|
[
|
|
3002
|
-
|
|
3014
|
+
'Topic filtering',
|
|
3003
3015
|
'tf search "automation" --topics "topic_123,topic_456"',
|
|
3004
3016
|
],
|
|
3005
|
-
[
|
|
3006
|
-
[
|
|
3007
|
-
[
|
|
3017
|
+
['Specific document', 'tf search "settings" --document-id "doc_550..."'],
|
|
3018
|
+
['Verbose details', 'tf search "deployment" --verbose'],
|
|
3019
|
+
['JSON output', 'tf search "API docs" --output json'],
|
|
3008
3020
|
];
|
|
3009
3021
|
|
|
3010
|
-
const searchData = [[
|
|
3022
|
+
const searchData = [['Use Case', 'Command'], ...searchExamples];
|
|
3011
3023
|
console.log(
|
|
3012
3024
|
table(searchData, {
|
|
3013
3025
|
header: {
|
|
3014
|
-
alignment:
|
|
3015
|
-
content:
|
|
3026
|
+
alignment: 'center',
|
|
3027
|
+
content: 'Knowledge Hub Search',
|
|
3016
3028
|
},
|
|
3017
3029
|
})
|
|
3018
3030
|
);
|
|
3019
3031
|
|
|
3020
|
-
console.log(chalk.blue.bold(
|
|
3032
|
+
console.log(chalk.blue.bold('\nš File Management Examples'));
|
|
3021
3033
|
|
|
3022
3034
|
const fileExamples = [
|
|
3023
|
-
[
|
|
3035
|
+
['Upload PDF file', 'tf upload "./document.pdf"'],
|
|
3024
3036
|
[
|
|
3025
|
-
|
|
3037
|
+
'Upload with custom type',
|
|
3026
3038
|
'tf upload "./file.txt" --import-type "imported_doc_files"',
|
|
3027
3039
|
],
|
|
3028
|
-
[
|
|
3040
|
+
['Upload image file', 'tf upload "./photo.jpg"'],
|
|
3029
3041
|
[
|
|
3030
|
-
|
|
3042
|
+
'Upload with content type',
|
|
3031
3043
|
'tf upload "./data.csv" --content-type "text/csv"',
|
|
3032
3044
|
],
|
|
3033
3045
|
[
|
|
3034
|
-
|
|
3046
|
+
'Download uploaded file',
|
|
3035
3047
|
'tf download --filename "imported-image/workspace123/1672531200000image.jpg"',
|
|
3036
3048
|
],
|
|
3037
3049
|
[
|
|
3038
|
-
|
|
3050
|
+
'Download to custom dir',
|
|
3039
3051
|
'tf download --filename "imported_doc_files/workspace123/1672531200000document.pdf" --output-dir "./results"',
|
|
3040
3052
|
],
|
|
3041
3053
|
[
|
|
3042
|
-
|
|
3054
|
+
'Download with custom name',
|
|
3043
3055
|
'tf download --filename "imported_doc_files/workspace123/1672531200000report.docx" --output-name "final-report.docx"',
|
|
3044
3056
|
],
|
|
3045
3057
|
];
|
|
3046
3058
|
|
|
3047
|
-
const fileData = [[
|
|
3059
|
+
const fileData = [['Use Case', 'Command'], ...fileExamples];
|
|
3048
3060
|
console.log(
|
|
3049
3061
|
table(fileData, {
|
|
3050
3062
|
header: {
|
|
3051
|
-
alignment:
|
|
3052
|
-
content:
|
|
3063
|
+
alignment: 'center',
|
|
3064
|
+
content: 'File Management',
|
|
3053
3065
|
},
|
|
3054
3066
|
})
|
|
3055
3067
|
);
|
|
3056
3068
|
|
|
3057
|
-
console.log(chalk.green.bold(
|
|
3069
|
+
console.log(chalk.green.bold('\nš Workspace Management Examples'));
|
|
3058
3070
|
|
|
3059
3071
|
const mgmtExamples = [
|
|
3060
|
-
[
|
|
3061
|
-
[
|
|
3062
|
-
[
|
|
3063
|
-
[
|
|
3072
|
+
['List all chats', 'tf chats'],
|
|
3073
|
+
['View chat details', 'tf chat CHAT_ID'],
|
|
3074
|
+
['Show config', 'tf config-show'],
|
|
3075
|
+
['Detailed help', 'tf help-guide'],
|
|
3064
3076
|
];
|
|
3065
3077
|
|
|
3066
|
-
const mgmtData = [[
|
|
3078
|
+
const mgmtData = [['Use Case', 'Command'], ...mgmtExamples];
|
|
3067
3079
|
console.log(
|
|
3068
3080
|
table(mgmtData, {
|
|
3069
3081
|
header: {
|
|
3070
|
-
alignment:
|
|
3071
|
-
content:
|
|
3082
|
+
alignment: 'center',
|
|
3083
|
+
content: 'Workspace Management',
|
|
3072
3084
|
},
|
|
3073
3085
|
})
|
|
3074
3086
|
);
|
|
3075
3087
|
|
|
3076
|
-
console.log(chalk.yellow.bold(
|
|
3088
|
+
console.log(chalk.yellow.bold('\nš§ Configuration Options'));
|
|
3077
3089
|
const configOptions = [
|
|
3078
|
-
[
|
|
3090
|
+
['Method', 'Description', 'Example'],
|
|
3079
3091
|
[
|
|
3080
|
-
|
|
3081
|
-
|
|
3082
|
-
|
|
3092
|
+
'Environment',
|
|
3093
|
+
'Set environment variables',
|
|
3094
|
+
'export TF_API_KEY=your_key',
|
|
3083
3095
|
],
|
|
3084
3096
|
[
|
|
3085
|
-
|
|
3086
|
-
|
|
3087
|
-
|
|
3097
|
+
'Config file',
|
|
3098
|
+
'Use ~/.toothfairy/config.yml',
|
|
3099
|
+
'api_key: your_key\\nworkspace_id: your_workspace',
|
|
3088
3100
|
],
|
|
3089
3101
|
[
|
|
3090
|
-
|
|
3091
|
-
|
|
3092
|
-
|
|
3102
|
+
'CLI arguments',
|
|
3103
|
+
'Pass config file path',
|
|
3104
|
+
'tf --config /path/to/config.yml send ...',
|
|
3093
3105
|
],
|
|
3094
3106
|
];
|
|
3095
3107
|
|
|
3096
3108
|
console.log(table(configOptions));
|
|
3097
3109
|
|
|
3098
|
-
console.log(chalk.red.bold(
|
|
3110
|
+
console.log(chalk.red.bold('\nā ļø Common Issues & Solutions'));
|
|
3099
3111
|
const issues = [
|
|
3100
|
-
[
|
|
3112
|
+
['Issue', 'Solution'],
|
|
3101
3113
|
[
|
|
3102
|
-
|
|
3103
|
-
|
|
3114
|
+
'Configuration incomplete',
|
|
3115
|
+
'Run: tf configure --api-key YOUR_KEY --workspace-id YOUR_WORKSPACE',
|
|
3104
3116
|
],
|
|
3105
3117
|
[
|
|
3106
|
-
|
|
3107
|
-
|
|
3118
|
+
'No text response found',
|
|
3119
|
+
'Use --verbose flag to see full response details',
|
|
3108
3120
|
],
|
|
3109
|
-
[
|
|
3121
|
+
['Agent not responding', 'Check agent-id is correct and agent is active'],
|
|
3110
3122
|
[
|
|
3111
|
-
|
|
3112
|
-
|
|
3123
|
+
'Network errors',
|
|
3124
|
+
'Verify API endpoints are accessible and credentials are valid',
|
|
3113
3125
|
],
|
|
3114
3126
|
];
|
|
3115
3127
|
|
|
3116
3128
|
console.log(table(issues));
|
|
3117
3129
|
|
|
3118
|
-
console.log(chalk.cyan.bold(
|
|
3119
|
-
console.log(
|
|
3130
|
+
console.log(chalk.cyan.bold('\nš Search Filtering Guide'));
|
|
3131
|
+
console.log('Knowledge Hub search supports powerful filtering options:');
|
|
3120
3132
|
console.log(
|
|
3121
|
-
|
|
3122
|
-
chalk.cyan(
|
|
3123
|
-
|
|
3133
|
+
'⢠' +
|
|
3134
|
+
chalk.cyan('--status') +
|
|
3135
|
+
': Filter documents by \'published\' or \'suspended\' status'
|
|
3124
3136
|
);
|
|
3125
3137
|
console.log(
|
|
3126
|
-
|
|
3127
|
-
chalk.cyan(
|
|
3128
|
-
|
|
3138
|
+
'⢠' +
|
|
3139
|
+
chalk.cyan('--topics') +
|
|
3140
|
+
': Use topic IDs from ToothFairyAI (comma-separated)'
|
|
3129
3141
|
);
|
|
3130
3142
|
console.log(
|
|
3131
|
-
|
|
3143
|
+
'⢠' + chalk.cyan('--document-id') + ': Search within a specific document'
|
|
3132
3144
|
);
|
|
3133
3145
|
console.log(
|
|
3134
|
-
|
|
3146
|
+
'⢠' + chalk.cyan('--top-k') + ': Control number of results (1-50)'
|
|
3135
3147
|
);
|
|
3136
3148
|
console.log(
|
|
3137
|
-
|
|
3149
|
+
'⢠' + chalk.cyan('--verbose') + ': Show relevance scores and metadata'
|
|
3138
3150
|
);
|
|
3139
3151
|
|
|
3140
|
-
console.log(chalk.blue.bold(
|
|
3141
|
-
console.log(
|
|
3152
|
+
console.log(chalk.blue.bold('\nš File Upload/Download Guide'));
|
|
3153
|
+
console.log('File operations support various formats and contexts:');
|
|
3142
3154
|
console.log(
|
|
3143
|
-
|
|
3155
|
+
'⢠' + chalk.cyan('File size limit') + ': 15MB maximum per file'
|
|
3144
3156
|
);
|
|
3145
3157
|
console.log(
|
|
3146
|
-
|
|
3147
|
-
chalk.cyan(
|
|
3148
|
-
|
|
3158
|
+
'⢠' +
|
|
3159
|
+
chalk.cyan('Supported formats') +
|
|
3160
|
+
': pdf, docx, txt, csv, md, html, xlsx, pptx, png, jpg, jpeg, java, py, yaml, sql, js, ts, jsonl, wav, mp4, json'
|
|
3149
3161
|
);
|
|
3150
3162
|
console.log(
|
|
3151
|
-
|
|
3152
|
-
chalk.cyan(
|
|
3153
|
-
|
|
3163
|
+
'⢠' +
|
|
3164
|
+
chalk.cyan('Upload contexts') +
|
|
3165
|
+
': Files are automatically categorized by extension (pdf ā imported-pdf, wav ā imported_audio_files, etc.)'
|
|
3154
3166
|
);
|
|
3155
3167
|
console.log(
|
|
3156
|
-
|
|
3157
|
-
chalk.cyan(
|
|
3158
|
-
|
|
3168
|
+
'⢠' +
|
|
3169
|
+
chalk.cyan('Download') +
|
|
3170
|
+
': Use the filename from upload response to download files'
|
|
3159
3171
|
);
|
|
3160
3172
|
console.log(
|
|
3161
|
-
|
|
3162
|
-
chalk.cyan(
|
|
3163
|
-
|
|
3173
|
+
'⢠' +
|
|
3174
|
+
chalk.cyan('Progress tracking') +
|
|
3175
|
+
': Real-time upload/download progress with size information'
|
|
3164
3176
|
);
|
|
3165
3177
|
|
|
3166
|
-
console.log(chalk.magenta.bold(
|
|
3178
|
+
console.log(chalk.magenta.bold('\nš More Help'));
|
|
3167
3179
|
console.log(
|
|
3168
|
-
|
|
3180
|
+
'⢠Use ' + chalk.cyan('tf COMMAND --help') + ' for command-specific help'
|
|
3169
3181
|
);
|
|
3170
3182
|
console.log(
|
|
3171
|
-
|
|
3172
|
-
chalk.cyan(
|
|
3173
|
-
|
|
3183
|
+
'⢠Use ' +
|
|
3184
|
+
chalk.cyan('--verbose') +
|
|
3185
|
+
' flag to see detailed request/response information'
|
|
3174
3186
|
);
|
|
3175
3187
|
console.log(
|
|
3176
|
-
|
|
3188
|
+
'⢠Use ' + chalk.cyan('--output json') + ' for machine-readable output'
|
|
3177
3189
|
);
|
|
3178
3190
|
console.log(
|
|
3179
|
-
|
|
3191
|
+
'⢠Configuration is loaded from: environment variables ā ~/.toothfairy/config.yml ā CLI args'
|
|
3180
3192
|
);
|
|
3181
3193
|
|
|
3182
|
-
console.log(chalk.green.bold(
|
|
3194
|
+
console.log(chalk.green.bold('\n⨠Pro Tips'));
|
|
3183
3195
|
const tips = [
|
|
3184
|
-
|
|
3185
|
-
|
|
3186
|
-
|
|
3187
|
-
|
|
3188
|
-
|
|
3189
|
-
|
|
3196
|
+
'š¾ Save time: Configure once with \'tf configure\', then just use \'tf send\' and \'tf search\'',
|
|
3197
|
+
'š Debug issues: Use \'--verbose\' to see full API responses and troubleshoot',
|
|
3198
|
+
'š Scripting: Use \'--output json\' and tools like \'jq\' to parse responses',
|
|
3199
|
+
'ā” Quick tests: Only --agent-id is required for send, only query for search',
|
|
3200
|
+
'šÆ Better search: Use --status, --topics, and --document-id for targeted results',
|
|
3201
|
+
'š§ Multiple environments: Use different config files with \'--config\' flag',
|
|
3190
3202
|
];
|
|
3191
3203
|
|
|
3192
3204
|
tips.forEach((tip) => {
|
|
@@ -3195,20 +3207,20 @@ program
|
|
|
3195
3207
|
|
|
3196
3208
|
console.log(
|
|
3197
3209
|
chalk.dim(
|
|
3198
|
-
|
|
3210
|
+
'\nToothFairy CLI v1.0.0 - For more help, visit the documentation'
|
|
3199
3211
|
)
|
|
3200
3212
|
);
|
|
3201
3213
|
});
|
|
3202
3214
|
|
|
3203
3215
|
// Generate speech command
|
|
3204
3216
|
program
|
|
3205
|
-
.command(
|
|
3206
|
-
.description(
|
|
3207
|
-
.argument(
|
|
3208
|
-
.option(
|
|
3209
|
-
.option(
|
|
3210
|
-
.option(
|
|
3211
|
-
.option(
|
|
3217
|
+
.command('generate-speech')
|
|
3218
|
+
.description('Generate speech audio from text using ToothFairyAI')
|
|
3219
|
+
.argument('<text>', 'Text to convert to speech')
|
|
3220
|
+
.option('--chat-id <id>', 'Chat ID for context (optional)')
|
|
3221
|
+
.option('--last-message-id <id>', 'Last message ID for context (optional)')
|
|
3222
|
+
.option('-o, --output <format>', 'Output format (json|text)', 'text')
|
|
3223
|
+
.option('-v, --verbose', 'Show detailed generation information')
|
|
3212
3224
|
.action(async (text, options, command) => {
|
|
3213
3225
|
try {
|
|
3214
3226
|
const globalOptions = command.parent.opts();
|
|
@@ -3224,7 +3236,7 @@ program
|
|
|
3224
3236
|
globalOptions.verbose || options.verbose
|
|
3225
3237
|
);
|
|
3226
3238
|
|
|
3227
|
-
console.log(chalk.cyan(
|
|
3239
|
+
console.log(chalk.cyan('Generating speech from text...'));
|
|
3228
3240
|
if (options.verbose) {
|
|
3229
3241
|
console.log(chalk.dim(`Text: "${text}"`));
|
|
3230
3242
|
if (options.chatId) {
|
|
@@ -3235,7 +3247,7 @@ program
|
|
|
3235
3247
|
}
|
|
3236
3248
|
}
|
|
3237
3249
|
|
|
3238
|
-
const spinner = ora(
|
|
3250
|
+
const spinner = ora('Generating audio...').start();
|
|
3239
3251
|
|
|
3240
3252
|
const result = await api.generateSpeech(
|
|
3241
3253
|
text,
|
|
@@ -3245,44 +3257,44 @@ program
|
|
|
3245
3257
|
|
|
3246
3258
|
spinner.stop();
|
|
3247
3259
|
|
|
3248
|
-
if (options.output ===
|
|
3260
|
+
if (options.output === 'json') {
|
|
3249
3261
|
console.log(JSON.stringify(result, null, 2));
|
|
3250
3262
|
} else {
|
|
3251
|
-
console.log(chalk.green.bold(
|
|
3263
|
+
console.log(chalk.green.bold('šµ Speech generated successfully!'));
|
|
3252
3264
|
console.log();
|
|
3253
3265
|
|
|
3254
3266
|
const data = [
|
|
3255
|
-
[
|
|
3256
|
-
[
|
|
3267
|
+
['Field', 'Value'],
|
|
3268
|
+
['Text Length', `${text.length} characters`],
|
|
3257
3269
|
];
|
|
3258
3270
|
|
|
3259
3271
|
if (result.audioUrl) {
|
|
3260
|
-
data.push([
|
|
3272
|
+
data.push(['Audio URL', result.audioUrl]);
|
|
3261
3273
|
}
|
|
3262
3274
|
if (result.duration) {
|
|
3263
|
-
data.push([
|
|
3275
|
+
data.push(['Duration', `${result.duration}s`]);
|
|
3264
3276
|
}
|
|
3265
3277
|
if (result.format) {
|
|
3266
|
-
data.push([
|
|
3278
|
+
data.push(['Format', result.format]);
|
|
3267
3279
|
}
|
|
3268
3280
|
if (options.chatId) {
|
|
3269
|
-
data.push([
|
|
3281
|
+
data.push(['Chat ID', options.chatId]);
|
|
3270
3282
|
}
|
|
3271
3283
|
if (options.lastMessageId) {
|
|
3272
|
-
data.push([
|
|
3284
|
+
data.push(['Last Message ID', options.lastMessageId]);
|
|
3273
3285
|
}
|
|
3274
3286
|
|
|
3275
3287
|
console.log(
|
|
3276
3288
|
table(data, {
|
|
3277
3289
|
header: {
|
|
3278
|
-
alignment:
|
|
3279
|
-
content:
|
|
3290
|
+
alignment: 'center',
|
|
3291
|
+
content: 'Speech Generation Results',
|
|
3280
3292
|
},
|
|
3281
3293
|
})
|
|
3282
3294
|
);
|
|
3283
3295
|
|
|
3284
3296
|
if (options.verbose && result) {
|
|
3285
|
-
console.log(chalk.dim(
|
|
3297
|
+
console.log(chalk.dim('\nAPI Response:'));
|
|
3286
3298
|
console.log(chalk.dim(JSON.stringify(result, null, 2)));
|
|
3287
3299
|
}
|
|
3288
3300
|
}
|