@toothfairyai/cli 1.0.8 → 1.0.9

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.
Files changed (2) hide show
  1. package/bin/toothfairy.js +103 -45
  2. package/package.json +1 -1
package/bin/toothfairy.js CHANGED
@@ -321,7 +321,7 @@ program
321
321
  let currentSpinner = null;
322
322
 
323
323
  // Function to update display with status filtering
324
- const updateDisplay = (text, agentStatus, type = 'response') => {
324
+ const updateDisplay = (text, agentStatus, messageId, type = 'response') => {
325
325
  if (currentSpinner) {
326
326
  currentSpinner.stop();
327
327
  currentSpinner = null;
@@ -333,7 +333,7 @@ program
333
333
  if (text !== currentText) {
334
334
  // For real-time streaming, we overwrite the current line
335
335
  process.stdout.write('\r\x1b[K'); // Clear current line
336
- process.stdout.write(chalk.green('🧚 Response: ') + text);
336
+ process.stdout.write(chalk.green('🧚 Response: ') + text.trim());
337
337
  currentText = text;
338
338
  }
339
339
  }
@@ -361,25 +361,39 @@ program
361
361
  );
362
362
  }
363
363
 
364
- if (eventType === 'status') {
365
- if (eventData.status === 'connected') {
366
- if (options.showProgress) {
367
- console.log(
368
- chalk.green('šŸ”— Connected to streaming server')
369
- );
370
- }
371
- } else if (eventData.status === 'complete') {
372
- if (options.showProgress) {
373
- console.log(
374
- chalk.green('\nšŸŽ‰ Stream completed successfully!')
375
- );
364
+ // Handle connection status events
365
+ if (eventData.status === 'connected') {
366
+ if (options.showProgress) {
367
+ console.log(chalk.green('šŸ”— Connected to streaming server'));
368
+ }
369
+ return;
370
+ }
371
+
372
+ if (eventData.status === 'complete') {
373
+ if (options.showProgress) {
374
+ console.log(chalk.green('\nšŸŽ‰ Stream completed successfully!'));
375
+ }
376
+ return;
377
+ }
378
+
379
+ // Handle message events
380
+ if (eventData.type === 'message') {
381
+ let metadata = {};
382
+ let agentStatus = null;
383
+
384
+ // Parse metadata if available
385
+ if (eventData.metadata) {
386
+ try {
387
+ metadata = JSON.parse(eventData.metadata);
388
+ agentStatus = metadata.agent_processing_status;
389
+ } catch (e) {
390
+ // Metadata parsing failed, continue without it
376
391
  }
377
392
  }
378
- } else if (eventType === 'progress') {
379
- // Agent processing status updates
380
- const newStatus = eventData.processing_status;
381
- if (newStatus && newStatus !== processingStatus) {
382
- processingStatus = newStatus;
393
+
394
+ // Handle status changes
395
+ if (agentStatus && agentStatus !== processingStatus) {
396
+ processingStatus = agentStatus;
383
397
  if (options.showProgress) {
384
398
  const statusMsg = mapStateWithLabel(processingStatus);
385
399
  if (currentSpinner) {
@@ -388,24 +402,49 @@ program
388
402
  currentSpinner = ora(chalk.yellow(statusMsg)).start();
389
403
  }
390
404
  }
391
- } else if (eventType === 'data') {
392
- // Streaming text data - pass current agent status for filtering
393
- if (eventData.text) {
394
- updateDisplay(eventData.text.trim(), processingStatus);
405
+
406
+ // Handle progressive text streaming
407
+ if (eventData.text && agentStatus === 'replying') {
408
+ updateDisplay(
409
+ eventData.text,
410
+ agentStatus,
411
+ eventData.message_id,
412
+ 'response'
413
+ );
414
+ }
415
+
416
+ // Handle fulfilled status (final response)
417
+ if (eventData.status === 'fulfilled') {
418
+ finalResponse = eventData;
419
+ if (currentText) {
420
+ // Clean final display with magic wand emoji
421
+ if (currentSpinner) {
422
+ currentSpinner.stop();
423
+ currentSpinner = null;
424
+ }
425
+ process.stdout.write('\r\x1b[K'); // Clear current line
426
+ process.stdout.write(chalk.blue('šŸŖ„ ') + currentText.trim());
427
+ }
428
+ }
429
+
430
+ // Handle additional metadata events (images, files, callback metadata)
431
+ if (eventData.images !== undefined || eventData.files !== undefined) {
432
+ // These are attachment events - could show notification if needed
433
+ if (options.verbose) {
434
+ console.log(chalk.dim('\nšŸ“Ž Attachments processed'));
435
+ }
395
436
  }
396
- } else if (eventType === 'complete') {
397
- // Final response with all metadata
398
- finalResponse = eventData;
399
- if (currentText) {
400
- // Ensure we have a clean final display - just add the final emoji
401
- if (currentSpinner) {
402
- currentSpinner.stop();
403
- currentSpinner = null;
437
+
438
+ if (eventData.callbackMetadata) {
439
+ // Function execution metadata
440
+ if (options.verbose) {
441
+ console.log(chalk.dim('\nāš™ļø Function execution metadata received'));
404
442
  }
405
- process.stdout.write('\r\x1b[K'); // Clear current line
406
- process.stdout.write(chalk.blue('šŸŖ„ ') + currentText.trim());
407
443
  }
408
- } else if (eventType === 'error') {
444
+ }
445
+
446
+ // Handle errors
447
+ if (eventType === 'error') {
409
448
  const errorMsg = eventData.message || 'Unknown streaming error';
410
449
  if (currentSpinner) {
411
450
  currentSpinner.stop();
@@ -425,19 +464,38 @@ program
425
464
 
426
465
  if (options.verbose && finalResponse) {
427
466
  // Show final response metadata in verbose mode
428
- console.log(chalk.cyan.bold('šŸ“Š Final Response Metadata'));
429
- console.log('─'.repeat(40));
430
-
431
- if (finalResponse.metadata_parsed) {
432
- const metadata = finalResponse.metadata_parsed;
433
- for (const [key, value] of Object.entries(metadata)) {
434
- if (key !== 'agent_processing_status') {
435
- // Already shown during streaming
436
- console.log(chalk.cyan(`${key}:`), String(value));
467
+ console.log(chalk.cyan.bold('\nšŸ“Š Final Response Metadata'));
468
+ console.log('─'.repeat(50));
469
+
470
+ // Parse and display metadata from the final response
471
+ if (finalResponse.metadata) {
472
+ try {
473
+ const metadata = JSON.parse(finalResponse.metadata);
474
+ for (const [key, value] of Object.entries(metadata)) {
475
+ if (key === 'agent_processing_status') {
476
+ console.log(chalk.cyan(`${key}:`), chalk.green(value));
477
+ } else if (key === 'duration') {
478
+ console.log(chalk.cyan(`${key}:`), chalk.yellow(`${value}s`));
479
+ } else if (key === 'sources' && Array.isArray(value)) {
480
+ console.log(chalk.cyan(`${key}:`), value.length > 0 ? value.join(', ') : 'None');
481
+ } else {
482
+ console.log(chalk.cyan(`${key}:`), String(value));
483
+ }
437
484
  }
485
+ } catch (e) {
486
+ console.log(chalk.red('Could not parse metadata'));
438
487
  }
439
488
  }
440
- console.log('─'.repeat(40));
489
+
490
+ // Show additional response fields
491
+ if (finalResponse.message_id) {
492
+ console.log(chalk.cyan('message_id:'), finalResponse.message_id);
493
+ }
494
+ if (finalResponse.t_text_summary) {
495
+ console.log(chalk.cyan('summary:'), finalResponse.t_text_summary);
496
+ }
497
+
498
+ console.log('─'.repeat(50));
441
499
  }
442
500
 
443
501
  if (!currentText) {
@@ -719,7 +777,7 @@ program
719
777
  program
720
778
  .command('config-show')
721
779
  .description('Show current configuration')
722
- .action(async (options, command) => {
780
+ .action(async (command) => {
723
781
  try {
724
782
  const globalOptions = command.parent.opts();
725
783
  const config = loadConfig(globalOptions.config);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@toothfairyai/cli",
3
- "version": "1.0.8",
3
+ "version": "1.0.9",
4
4
  "description": "Command-line interface for ToothFairy AI API",
5
5
  "main": "index.js",
6
6
  "bin": {