@toothfairyai/cli 1.0.8 → 1.0.10

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