@toothfairyai/cli 1.1.5 → 1.4.0

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@toothfairyai/cli",
3
- "version": "1.1.5",
3
+ "version": "1.4.0",
4
4
  "description": "Command-line interface for ToothFairyAI API",
5
5
  "main": "index.js",
6
6
  "bin": {
@@ -37,18 +37,20 @@
37
37
  },
38
38
  "homepage": "https://gitea.toothfairyai.com/ToothFairyAI/tooth-fairy-website/toothfairy-cli#readme",
39
39
  "dependencies": {
40
- "commander": "^9.4.1",
41
40
  "axios": "^1.4.0",
42
41
  "chalk": "^4.1.2",
42
+ "commander": "^9.4.1",
43
43
  "dotenv": "^16.0.3",
44
+ "eventsource": "^2.0.2",
45
+ "glob": "^10.3.0",
44
46
  "js-yaml": "^4.1.0",
45
47
  "ora": "^5.4.1",
46
- "table": "^6.8.1",
47
- "eventsource": "^2.0.2"
48
+ "table": "^6.8.1"
48
49
  },
49
50
  "devDependencies": {
50
51
  "eslint": "^8.32.0",
51
- "jest": "^29.3.1"
52
+ "jest": "^29.3.1",
53
+ "typescript": "^5.9.3"
52
54
  },
53
55
  "engines": {
54
56
  "node": ">=14.0.0"
package/src/api.js CHANGED
@@ -367,6 +367,8 @@ class ToothFairyAPI {
367
367
  * @param {Function} onEvent - Callback function called for each event
368
368
  * @param {Object} attachments - File attachments (images, audios, videos, files)
369
369
  * @param {boolean} showProgress - Show all progress events from SSE endpoint (default: false)
370
+ * @param {string|null} chatId - Existing chat ID to continue conversation (default: null, creates new chat)
371
+ * @param {boolean} rawStream - Enable raw streaming mode for chunk-by-chunk output (default: false)
370
372
  * @returns {Promise<void>} - Promise resolves when streaming is complete
371
373
  *
372
374
  * Event Types Explained:
@@ -399,7 +401,8 @@ class ToothFairyAPI {
399
401
  onEvent,
400
402
  attachments = {},
401
403
  showProgress = false,
402
- chatId = null
404
+ chatId = null,
405
+ rawStream = false
403
406
  ) {
404
407
  try {
405
408
  // Use defaults for optional parameters
@@ -463,6 +466,7 @@ class ToothFairyAPI {
463
466
  chatid: chatId,
464
467
  messages: [messageData],
465
468
  agentid: agentId,
469
+ raw_stream: rawStream,
466
470
  };
467
471
 
468
472
  // Stream the agent response using the dedicated streaming URL
@@ -511,7 +515,14 @@ class ToothFairyAPI {
511
515
  }
512
516
 
513
517
  // Standard event processing (always executed for backward compatibility)
514
- if (eventData.status) {
518
+ // Handle raw_stream token events (streaming text chunks)
519
+ if (eventData.type === 'token' && eventData.chunk !== undefined) {
520
+ // Token streaming event - emit as 'data' with text field for compatibility
521
+ onEvent('data', {
522
+ ...eventData,
523
+ text: eventData.chunk,
524
+ });
525
+ } else if (eventData.status) {
515
526
  if (eventData.status === 'connected') {
516
527
  onEvent('status', eventData);
517
528
  } else if (eventData.status === 'complete') {
@@ -520,10 +531,15 @@ class ToothFairyAPI {
520
531
  // Parse metadata to understand what's happening
521
532
  let metadata = {};
522
533
  if (eventData.metadata) {
523
- try {
524
- metadata = JSON.parse(eventData.metadata);
525
- } catch (e) {
526
- metadata = { raw_metadata: eventData.metadata };
534
+ // metadata can be an object or a JSON string
535
+ if (typeof eventData.metadata === 'object') {
536
+ metadata = eventData.metadata;
537
+ } else {
538
+ try {
539
+ metadata = JSON.parse(eventData.metadata);
540
+ } catch (e) {
541
+ metadata = { raw_metadata: eventData.metadata };
542
+ }
527
543
  }
528
544
  }
529
545
 
@@ -550,8 +566,17 @@ class ToothFairyAPI {
550
566
  eventData.text &&
551
567
  eventData.type === 'message'
552
568
  ) {
553
- // This is streaming text data
569
+ // This is streaming text data (non-raw_stream mode)
554
570
  onEvent('data', eventData);
571
+ } else if (
572
+ eventData.type === 'message' &&
573
+ eventData.chat_created === true
574
+ ) {
575
+ // Chat creation event from raw_stream mode
576
+ onEvent('chat_created', {
577
+ ...eventData,
578
+ chatId: eventData.chatid,
579
+ });
555
580
  } else if (
556
581
  eventData.type === 'message' &&
557
582
  eventData.images !== undefined
@@ -568,7 +593,7 @@ class ToothFairyAPI {
568
593
  eventData.type === 'chat_created' ||
569
594
  eventData.event === 'chat_created'
570
595
  ) {
571
- // Chat creation event
596
+ // Chat creation event (legacy format)
572
597
  onEvent('chat_created', eventData);
573
598
  } else {
574
599
  // Generic event data
@@ -660,6 +685,7 @@ class ToothFairyAPI {
660
685
  customerId: customerId,
661
686
  providerId: providerId,
662
687
  customerInfo: customerInfo,
688
+ raw_stream: rawStream,
663
689
  };
664
690
 
665
691
  // Stream the agent response using the dedicated streaming URL
@@ -708,7 +734,14 @@ class ToothFairyAPI {
708
734
  }
709
735
 
710
736
  // Standard event processing (always executed for backward compatibility)
711
- if (eventData.status) {
737
+ // Handle raw_stream token events (streaming text chunks)
738
+ if (eventData.type === 'token' && eventData.chunk !== undefined) {
739
+ // Token streaming event - emit as 'data' with text field for compatibility
740
+ onEvent('data', {
741
+ ...eventData,
742
+ text: eventData.chunk,
743
+ });
744
+ } else if (eventData.status) {
712
745
  if (eventData.status === 'connected') {
713
746
  onEvent('status', eventData);
714
747
  } else if (eventData.status === 'complete') {
@@ -717,10 +750,15 @@ class ToothFairyAPI {
717
750
  // Parse metadata to understand what's happening
718
751
  let metadata = {};
719
752
  if (eventData.metadata) {
720
- try {
721
- metadata = JSON.parse(eventData.metadata);
722
- } catch (e) {
723
- metadata = { raw_metadata: eventData.metadata };
753
+ // metadata can be an object or a JSON string
754
+ if (typeof eventData.metadata === 'object') {
755
+ metadata = eventData.metadata;
756
+ } else {
757
+ try {
758
+ metadata = JSON.parse(eventData.metadata);
759
+ } catch (e) {
760
+ metadata = { raw_metadata: eventData.metadata };
761
+ }
724
762
  }
725
763
  }
726
764
 
@@ -747,8 +785,17 @@ class ToothFairyAPI {
747
785
  eventData.text &&
748
786
  eventData.type === 'message'
749
787
  ) {
750
- // This is streaming text data
788
+ // This is streaming text data (non-raw_stream mode)
751
789
  onEvent('data', eventData);
790
+ } else if (
791
+ eventData.type === 'message' &&
792
+ eventData.chat_created === true
793
+ ) {
794
+ // Chat creation event from raw_stream mode
795
+ onEvent('chat_created', {
796
+ ...eventData,
797
+ chatId: eventData.chatid,
798
+ });
752
799
  } else if (
753
800
  eventData.type === 'message' &&
754
801
  eventData.images !== undefined
@@ -765,7 +812,7 @@ class ToothFairyAPI {
765
812
  eventData.type === 'chat_created' ||
766
813
  eventData.event === 'chat_created'
767
814
  ) {
768
- // Chat creation event
815
+ // Chat creation event (legacy format)
769
816
  onEvent('chat_created', eventData);
770
817
  } else {
771
818
  // Generic event data
package/src/config.js CHANGED
@@ -4,13 +4,14 @@ const os = require('os');
4
4
  const yaml = require('js-yaml');
5
5
 
6
6
  class ToothFairyConfig {
7
- constructor(baseUrl, aiUrl, aiStreamUrl, apiKey, workspaceId, userId) {
7
+ constructor(baseUrl, aiUrl, aiStreamUrl, apiKey, workspaceId, userId, defaultAgentId = '') {
8
8
  this.baseUrl = baseUrl;
9
9
  this.aiUrl = aiUrl;
10
10
  this.aiStreamUrl = aiStreamUrl;
11
11
  this.apiKey = apiKey;
12
12
  this.workspaceId = workspaceId;
13
13
  this.userId = userId;
14
+ this.defaultAgentId = defaultAgentId;
14
15
  }
15
16
 
16
17
  static fromEnv() {
@@ -20,7 +21,8 @@ class ToothFairyConfig {
20
21
  process.env.TF_AI_STREAM_URL || 'https://ais.toothfairyai.com',
21
22
  process.env.TF_API_KEY || '',
22
23
  process.env.TF_WORKSPACE_ID || '',
23
- process.env.TF_USER_ID || ''
24
+ process.env.TF_USER_ID || '',
25
+ process.env.TF_DEFAULT_AGENT_ID || ''
24
26
  );
25
27
  }
26
28
 
@@ -44,7 +46,8 @@ class ToothFairyConfig {
44
46
  data.ai_stream_url || 'https://ais.toothfairyai.com',
45
47
  data.api_key || '',
46
48
  data.workspace_id || '',
47
- data.user_id || ''
49
+ data.user_id || '',
50
+ data.default_agent_id || ''
48
51
  );
49
52
  }
50
53
 
@@ -64,6 +67,7 @@ class ToothFairyConfig {
64
67
  api_key: this.apiKey,
65
68
  workspace_id: this.workspaceId,
66
69
  user_id: this.userId,
70
+ default_agent_id: this.defaultAgentId,
67
71
  };
68
72
  }
69
73
  }