@livekit/agents 1.0.15 → 1.0.16

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (92) hide show
  1. package/dist/cli.cjs +12 -12
  2. package/dist/cli.cjs.map +1 -1
  3. package/dist/cli.d.cts +3 -3
  4. package/dist/cli.d.ts +3 -3
  5. package/dist/cli.d.ts.map +1 -1
  6. package/dist/cli.js +13 -13
  7. package/dist/cli.js.map +1 -1
  8. package/dist/inference/stt.cjs.map +1 -1
  9. package/dist/inference/stt.d.ts.map +1 -1
  10. package/dist/inference/stt.js +1 -1
  11. package/dist/inference/stt.js.map +1 -1
  12. package/dist/inference/tts.cjs.map +1 -1
  13. package/dist/inference/tts.d.cts +2 -1
  14. package/dist/inference/tts.d.ts +2 -1
  15. package/dist/inference/tts.d.ts.map +1 -1
  16. package/dist/inference/tts.js +1 -5
  17. package/dist/inference/tts.js.map +1 -1
  18. package/dist/llm/chat_context.cjs +78 -0
  19. package/dist/llm/chat_context.cjs.map +1 -1
  20. package/dist/llm/chat_context.d.cts +16 -0
  21. package/dist/llm/chat_context.d.ts +16 -0
  22. package/dist/llm/chat_context.d.ts.map +1 -1
  23. package/dist/llm/chat_context.js +78 -0
  24. package/dist/llm/chat_context.js.map +1 -1
  25. package/dist/llm/chat_context.test.cjs +531 -0
  26. package/dist/llm/chat_context.test.cjs.map +1 -1
  27. package/dist/llm/chat_context.test.js +531 -0
  28. package/dist/llm/chat_context.test.js.map +1 -1
  29. package/dist/llm/tool_context.cjs +40 -0
  30. package/dist/llm/tool_context.cjs.map +1 -1
  31. package/dist/llm/tool_context.d.cts +2 -0
  32. package/dist/llm/tool_context.d.ts +2 -0
  33. package/dist/llm/tool_context.d.ts.map +1 -1
  34. package/dist/llm/tool_context.js +38 -0
  35. package/dist/llm/tool_context.js.map +1 -1
  36. package/dist/metrics/base.cjs.map +1 -1
  37. package/dist/metrics/base.d.cts +7 -0
  38. package/dist/metrics/base.d.ts +7 -0
  39. package/dist/metrics/base.d.ts.map +1 -1
  40. package/dist/stt/stt.cjs +1 -0
  41. package/dist/stt/stt.cjs.map +1 -1
  42. package/dist/stt/stt.d.cts +7 -1
  43. package/dist/stt/stt.d.ts +7 -1
  44. package/dist/stt/stt.d.ts.map +1 -1
  45. package/dist/stt/stt.js +1 -0
  46. package/dist/stt/stt.js.map +1 -1
  47. package/dist/voice/agent_activity.cjs +83 -8
  48. package/dist/voice/agent_activity.cjs.map +1 -1
  49. package/dist/voice/agent_activity.d.cts +6 -2
  50. package/dist/voice/agent_activity.d.ts +6 -2
  51. package/dist/voice/agent_activity.d.ts.map +1 -1
  52. package/dist/voice/agent_activity.js +83 -8
  53. package/dist/voice/agent_activity.js.map +1 -1
  54. package/dist/voice/agent_session.cjs +3 -2
  55. package/dist/voice/agent_session.cjs.map +1 -1
  56. package/dist/voice/agent_session.d.cts +2 -1
  57. package/dist/voice/agent_session.d.ts +2 -1
  58. package/dist/voice/agent_session.d.ts.map +1 -1
  59. package/dist/voice/agent_session.js +3 -2
  60. package/dist/voice/agent_session.js.map +1 -1
  61. package/dist/voice/audio_recognition.cjs +138 -16
  62. package/dist/voice/audio_recognition.cjs.map +1 -1
  63. package/dist/voice/audio_recognition.d.cts +11 -0
  64. package/dist/voice/audio_recognition.d.ts +11 -0
  65. package/dist/voice/audio_recognition.d.ts.map +1 -1
  66. package/dist/voice/audio_recognition.js +138 -16
  67. package/dist/voice/audio_recognition.js.map +1 -1
  68. package/dist/voice/room_io/_input.cjs.map +1 -1
  69. package/dist/voice/room_io/_input.d.ts.map +1 -1
  70. package/dist/voice/room_io/_input.js +0 -1
  71. package/dist/voice/room_io/_input.js.map +1 -1
  72. package/dist/worker.cjs +17 -11
  73. package/dist/worker.cjs.map +1 -1
  74. package/dist/worker.d.cts +16 -9
  75. package/dist/worker.d.ts +16 -9
  76. package/dist/worker.d.ts.map +1 -1
  77. package/dist/worker.js +16 -12
  78. package/dist/worker.js.map +1 -1
  79. package/package.json +1 -1
  80. package/src/cli.ts +17 -17
  81. package/src/inference/stt.ts +2 -1
  82. package/src/inference/tts.ts +2 -5
  83. package/src/llm/chat_context.test.ts +607 -0
  84. package/src/llm/chat_context.ts +106 -0
  85. package/src/llm/tool_context.ts +44 -0
  86. package/src/metrics/base.ts +7 -0
  87. package/src/stt/stt.ts +6 -0
  88. package/src/voice/agent_activity.ts +119 -9
  89. package/src/voice/agent_session.ts +3 -1
  90. package/src/voice/audio_recognition.ts +235 -57
  91. package/src/voice/room_io/_input.ts +1 -1
  92. package/src/worker.ts +29 -18
@@ -382,4 +382,535 @@ describe("ReadonlyChatContext with immutable array", () => {
382
382
  expect(ids).toEqual(["msg_1", "msg_2"]);
383
383
  });
384
384
  });
385
+ describe("ChatContext.isEquivalent", () => {
386
+ it("should return true for same reference", () => {
387
+ const ctx = new ChatContext();
388
+ ctx.addMessage({
389
+ id: "msg_1",
390
+ role: "user",
391
+ content: "Hello"
392
+ });
393
+ expect(ctx.isEquivalent(ctx)).toBe(true);
394
+ });
395
+ it("should return true for identical empty contexts", () => {
396
+ const ctx1 = new ChatContext();
397
+ const ctx2 = new ChatContext();
398
+ expect(ctx1.isEquivalent(ctx2)).toBe(true);
399
+ });
400
+ it("should return false for contexts with different lengths", () => {
401
+ const ctx1 = new ChatContext();
402
+ ctx1.addMessage({
403
+ id: "msg_1",
404
+ role: "user",
405
+ content: "Hello"
406
+ });
407
+ const ctx2 = new ChatContext();
408
+ ctx2.addMessage({
409
+ id: "msg_1",
410
+ role: "user",
411
+ content: "Hello"
412
+ });
413
+ ctx2.addMessage({
414
+ id: "msg_2",
415
+ role: "assistant",
416
+ content: "Hi"
417
+ });
418
+ expect(ctx1.isEquivalent(ctx2)).toBe(false);
419
+ });
420
+ it("should return false for contexts with different item IDs", () => {
421
+ const ctx1 = new ChatContext();
422
+ ctx1.addMessage({
423
+ id: "msg_1",
424
+ role: "user",
425
+ content: "Hello"
426
+ });
427
+ const ctx2 = new ChatContext();
428
+ ctx2.addMessage({
429
+ id: "msg_2",
430
+ role: "user",
431
+ content: "Hello"
432
+ });
433
+ expect(ctx1.isEquivalent(ctx2)).toBe(false);
434
+ });
435
+ it("should return false for contexts with different item types", () => {
436
+ const ctx1 = new ChatContext();
437
+ ctx1.addMessage({
438
+ id: "msg_1",
439
+ role: "user",
440
+ content: "Hello"
441
+ });
442
+ const ctx2 = new ChatContext();
443
+ ctx2.insert(
444
+ new FunctionCall({
445
+ id: "msg_1",
446
+ callId: "call_1",
447
+ name: "test",
448
+ args: "{}"
449
+ })
450
+ );
451
+ expect(ctx1.isEquivalent(ctx2)).toBe(false);
452
+ });
453
+ describe("message comparison", () => {
454
+ it("should return true for identical messages", () => {
455
+ const ctx1 = new ChatContext();
456
+ ctx1.addMessage({
457
+ id: "msg_1",
458
+ role: "user",
459
+ content: "Hello",
460
+ interrupted: false
461
+ });
462
+ const ctx2 = new ChatContext();
463
+ ctx2.addMessage({
464
+ id: "msg_1",
465
+ role: "user",
466
+ content: "Hello",
467
+ interrupted: false
468
+ });
469
+ expect(ctx1.isEquivalent(ctx2)).toBe(true);
470
+ });
471
+ it("should return false for messages with different roles", () => {
472
+ const ctx1 = new ChatContext();
473
+ ctx1.addMessage({
474
+ id: "msg_1",
475
+ role: "user",
476
+ content: "Hello"
477
+ });
478
+ const ctx2 = new ChatContext();
479
+ ctx2.addMessage({
480
+ id: "msg_1",
481
+ role: "assistant",
482
+ content: "Hello"
483
+ });
484
+ expect(ctx1.isEquivalent(ctx2)).toBe(false);
485
+ });
486
+ it("should return false for messages with different interrupted flags", () => {
487
+ const ctx1 = new ChatContext();
488
+ ctx1.addMessage({
489
+ id: "msg_1",
490
+ role: "user",
491
+ content: "Hello",
492
+ interrupted: false
493
+ });
494
+ const ctx2 = new ChatContext();
495
+ ctx2.addMessage({
496
+ id: "msg_1",
497
+ role: "user",
498
+ content: "Hello",
499
+ interrupted: true
500
+ });
501
+ expect(ctx1.isEquivalent(ctx2)).toBe(false);
502
+ });
503
+ it("should return false for messages with different content", () => {
504
+ const ctx1 = new ChatContext();
505
+ ctx1.addMessage({
506
+ id: "msg_1",
507
+ role: "user",
508
+ content: "Hello"
509
+ });
510
+ const ctx2 = new ChatContext();
511
+ ctx2.addMessage({
512
+ id: "msg_1",
513
+ role: "user",
514
+ content: "World"
515
+ });
516
+ expect(ctx1.isEquivalent(ctx2)).toBe(false);
517
+ });
518
+ it("should return true for messages with identical array content", () => {
519
+ const ctx1 = new ChatContext();
520
+ ctx1.addMessage({
521
+ id: "msg_1",
522
+ role: "user",
523
+ content: ["Hello", "World"]
524
+ });
525
+ const ctx2 = new ChatContext();
526
+ ctx2.addMessage({
527
+ id: "msg_1",
528
+ role: "user",
529
+ content: ["Hello", "World"]
530
+ });
531
+ expect(ctx1.isEquivalent(ctx2)).toBe(true);
532
+ });
533
+ it("should return false for messages with different array content", () => {
534
+ const ctx1 = new ChatContext();
535
+ ctx1.addMessage({
536
+ id: "msg_1",
537
+ role: "user",
538
+ content: ["Hello", "World"]
539
+ });
540
+ const ctx2 = new ChatContext();
541
+ ctx2.addMessage({
542
+ id: "msg_1",
543
+ role: "user",
544
+ content: ["Hello"]
545
+ });
546
+ expect(ctx1.isEquivalent(ctx2)).toBe(false);
547
+ });
548
+ it("should return true for messages with identical image content", () => {
549
+ const imageContent = {
550
+ id: "img_1",
551
+ type: "image_content",
552
+ image: "https://example.com/image.jpg",
553
+ inferenceDetail: "high",
554
+ inferenceWidth: 1024,
555
+ inferenceHeight: 768,
556
+ mimeType: "image/jpeg",
557
+ _cache: {}
558
+ };
559
+ const ctx1 = new ChatContext();
560
+ ctx1.addMessage({
561
+ id: "msg_1",
562
+ role: "user",
563
+ content: ["Check this:", imageContent]
564
+ });
565
+ const ctx2 = new ChatContext();
566
+ ctx2.addMessage({
567
+ id: "msg_1",
568
+ role: "user",
569
+ content: ["Check this:", { ...imageContent }]
570
+ });
571
+ expect(ctx1.isEquivalent(ctx2)).toBe(true);
572
+ });
573
+ it("should return false for messages with different image content", () => {
574
+ const imageContent1 = {
575
+ id: "img_1",
576
+ type: "image_content",
577
+ image: "https://example.com/image1.jpg",
578
+ inferenceDetail: "high",
579
+ _cache: {}
580
+ };
581
+ const imageContent2 = {
582
+ id: "img_2",
583
+ type: "image_content",
584
+ image: "https://example.com/image2.jpg",
585
+ inferenceDetail: "high",
586
+ _cache: {}
587
+ };
588
+ const ctx1 = new ChatContext();
589
+ ctx1.addMessage({
590
+ id: "msg_1",
591
+ role: "user",
592
+ content: ["Check this:", imageContent1]
593
+ });
594
+ const ctx2 = new ChatContext();
595
+ ctx2.addMessage({
596
+ id: "msg_1",
597
+ role: "user",
598
+ content: ["Check this:", imageContent2]
599
+ });
600
+ expect(ctx1.isEquivalent(ctx2)).toBe(false);
601
+ });
602
+ });
603
+ describe("function call comparison", () => {
604
+ it("should return true for identical function calls", () => {
605
+ const ctx1 = new ChatContext();
606
+ ctx1.insert(
607
+ new FunctionCall({
608
+ id: "func_1",
609
+ callId: "call_1",
610
+ name: "get_weather",
611
+ args: '{"location": "Paris"}'
612
+ })
613
+ );
614
+ const ctx2 = new ChatContext();
615
+ ctx2.insert(
616
+ new FunctionCall({
617
+ id: "func_1",
618
+ callId: "call_1",
619
+ name: "get_weather",
620
+ args: '{"location": "Paris"}'
621
+ })
622
+ );
623
+ expect(ctx1.isEquivalent(ctx2)).toBe(true);
624
+ });
625
+ it("should return false for function calls with different names", () => {
626
+ const ctx1 = new ChatContext();
627
+ ctx1.insert(
628
+ new FunctionCall({
629
+ id: "func_1",
630
+ callId: "call_1",
631
+ name: "get_weather",
632
+ args: "{}"
633
+ })
634
+ );
635
+ const ctx2 = new ChatContext();
636
+ ctx2.insert(
637
+ new FunctionCall({
638
+ id: "func_1",
639
+ callId: "call_1",
640
+ name: "get_time",
641
+ args: "{}"
642
+ })
643
+ );
644
+ expect(ctx1.isEquivalent(ctx2)).toBe(false);
645
+ });
646
+ it("should return false for function calls with different call IDs", () => {
647
+ const ctx1 = new ChatContext();
648
+ ctx1.insert(
649
+ new FunctionCall({
650
+ id: "func_1",
651
+ callId: "call_1",
652
+ name: "get_weather",
653
+ args: "{}"
654
+ })
655
+ );
656
+ const ctx2 = new ChatContext();
657
+ ctx2.insert(
658
+ new FunctionCall({
659
+ id: "func_1",
660
+ callId: "call_2",
661
+ name: "get_weather",
662
+ args: "{}"
663
+ })
664
+ );
665
+ expect(ctx1.isEquivalent(ctx2)).toBe(false);
666
+ });
667
+ it("should return false for function calls with different arguments", () => {
668
+ const ctx1 = new ChatContext();
669
+ ctx1.insert(
670
+ new FunctionCall({
671
+ id: "func_1",
672
+ callId: "call_1",
673
+ name: "get_weather",
674
+ args: '{"location": "Paris"}'
675
+ })
676
+ );
677
+ const ctx2 = new ChatContext();
678
+ ctx2.insert(
679
+ new FunctionCall({
680
+ id: "func_1",
681
+ callId: "call_1",
682
+ name: "get_weather",
683
+ args: '{"location": "London"}'
684
+ })
685
+ );
686
+ expect(ctx1.isEquivalent(ctx2)).toBe(false);
687
+ });
688
+ it("should ignore timestamps", () => {
689
+ const ctx1 = new ChatContext();
690
+ ctx1.insert(
691
+ new FunctionCall({
692
+ id: "func_1",
693
+ callId: "call_1",
694
+ name: "get_weather",
695
+ args: "{}",
696
+ createdAt: 1e3
697
+ })
698
+ );
699
+ const ctx2 = new ChatContext();
700
+ ctx2.insert(
701
+ new FunctionCall({
702
+ id: "func_1",
703
+ callId: "call_1",
704
+ name: "get_weather",
705
+ args: "{}",
706
+ createdAt: 2e3
707
+ })
708
+ );
709
+ expect(ctx1.isEquivalent(ctx2)).toBe(true);
710
+ });
711
+ });
712
+ describe("function call output comparison", () => {
713
+ it("should return true for identical function call outputs", () => {
714
+ const ctx1 = new ChatContext();
715
+ ctx1.insert(
716
+ new FunctionCallOutput({
717
+ id: "output_1",
718
+ callId: "call_1",
719
+ name: "get_weather",
720
+ output: '{"temperature": 22}',
721
+ isError: false
722
+ })
723
+ );
724
+ const ctx2 = new ChatContext();
725
+ ctx2.insert(
726
+ new FunctionCallOutput({
727
+ id: "output_1",
728
+ callId: "call_1",
729
+ name: "get_weather",
730
+ output: '{"temperature": 22}',
731
+ isError: false
732
+ })
733
+ );
734
+ expect(ctx1.isEquivalent(ctx2)).toBe(true);
735
+ });
736
+ it("should return false for function call outputs with different names", () => {
737
+ const ctx1 = new ChatContext();
738
+ ctx1.insert(
739
+ new FunctionCallOutput({
740
+ id: "output_1",
741
+ callId: "call_1",
742
+ name: "get_weather",
743
+ output: "{}",
744
+ isError: false
745
+ })
746
+ );
747
+ const ctx2 = new ChatContext();
748
+ ctx2.insert(
749
+ new FunctionCallOutput({
750
+ id: "output_1",
751
+ callId: "call_1",
752
+ name: "get_time",
753
+ output: "{}",
754
+ isError: false
755
+ })
756
+ );
757
+ expect(ctx1.isEquivalent(ctx2)).toBe(false);
758
+ });
759
+ it("should return false for function call outputs with different call IDs", () => {
760
+ const ctx1 = new ChatContext();
761
+ ctx1.insert(
762
+ new FunctionCallOutput({
763
+ id: "output_1",
764
+ callId: "call_1",
765
+ name: "get_weather",
766
+ output: "{}",
767
+ isError: false
768
+ })
769
+ );
770
+ const ctx2 = new ChatContext();
771
+ ctx2.insert(
772
+ new FunctionCallOutput({
773
+ id: "output_1",
774
+ callId: "call_2",
775
+ name: "get_weather",
776
+ output: "{}",
777
+ isError: false
778
+ })
779
+ );
780
+ expect(ctx1.isEquivalent(ctx2)).toBe(false);
781
+ });
782
+ it("should return false for function call outputs with different output values", () => {
783
+ const ctx1 = new ChatContext();
784
+ ctx1.insert(
785
+ new FunctionCallOutput({
786
+ id: "output_1",
787
+ callId: "call_1",
788
+ name: "get_weather",
789
+ output: '{"temperature": 22}',
790
+ isError: false
791
+ })
792
+ );
793
+ const ctx2 = new ChatContext();
794
+ ctx2.insert(
795
+ new FunctionCallOutput({
796
+ id: "output_1",
797
+ callId: "call_1",
798
+ name: "get_weather",
799
+ output: '{"temperature": 25}',
800
+ isError: false
801
+ })
802
+ );
803
+ expect(ctx1.isEquivalent(ctx2)).toBe(false);
804
+ });
805
+ it("should return false for function call outputs with different error flags", () => {
806
+ const ctx1 = new ChatContext();
807
+ ctx1.insert(
808
+ new FunctionCallOutput({
809
+ id: "output_1",
810
+ callId: "call_1",
811
+ name: "get_weather",
812
+ output: "Error occurred",
813
+ isError: false
814
+ })
815
+ );
816
+ const ctx2 = new ChatContext();
817
+ ctx2.insert(
818
+ new FunctionCallOutput({
819
+ id: "output_1",
820
+ callId: "call_1",
821
+ name: "get_weather",
822
+ output: "Error occurred",
823
+ isError: true
824
+ })
825
+ );
826
+ expect(ctx1.isEquivalent(ctx2)).toBe(false);
827
+ });
828
+ it("should ignore timestamps", () => {
829
+ const ctx1 = new ChatContext();
830
+ ctx1.insert(
831
+ new FunctionCallOutput({
832
+ id: "output_1",
833
+ callId: "call_1",
834
+ name: "get_weather",
835
+ output: "{}",
836
+ isError: false,
837
+ createdAt: 1e3
838
+ })
839
+ );
840
+ const ctx2 = new ChatContext();
841
+ ctx2.insert(
842
+ new FunctionCallOutput({
843
+ id: "output_1",
844
+ callId: "call_1",
845
+ name: "get_weather",
846
+ output: "{}",
847
+ isError: false,
848
+ createdAt: 2e3
849
+ })
850
+ );
851
+ expect(ctx1.isEquivalent(ctx2)).toBe(true);
852
+ });
853
+ });
854
+ describe("complex context comparison", () => {
855
+ it("should return true for identical complex contexts", () => {
856
+ const ctx1 = new ChatContext();
857
+ ctx1.addMessage({
858
+ id: "msg_1",
859
+ role: "user",
860
+ content: "What is the weather?"
861
+ });
862
+ ctx1.insert(
863
+ new FunctionCall({
864
+ id: "func_1",
865
+ callId: "call_1",
866
+ name: "get_weather",
867
+ args: '{"location": "Paris"}'
868
+ })
869
+ );
870
+ ctx1.insert(
871
+ new FunctionCallOutput({
872
+ id: "output_1",
873
+ callId: "call_1",
874
+ name: "get_weather",
875
+ output: '{"temperature": 22}',
876
+ isError: false
877
+ })
878
+ );
879
+ ctx1.addMessage({
880
+ id: "msg_2",
881
+ role: "assistant",
882
+ content: "The weather is 22\xB0C"
883
+ });
884
+ const ctx2 = new ChatContext();
885
+ ctx2.addMessage({
886
+ id: "msg_1",
887
+ role: "user",
888
+ content: "What is the weather?"
889
+ });
890
+ ctx2.insert(
891
+ new FunctionCall({
892
+ id: "func_1",
893
+ callId: "call_1",
894
+ name: "get_weather",
895
+ args: '{"location": "Paris"}'
896
+ })
897
+ );
898
+ ctx2.insert(
899
+ new FunctionCallOutput({
900
+ id: "output_1",
901
+ callId: "call_1",
902
+ name: "get_weather",
903
+ output: '{"temperature": 22}',
904
+ isError: false
905
+ })
906
+ );
907
+ ctx2.addMessage({
908
+ id: "msg_2",
909
+ role: "assistant",
910
+ content: "The weather is 22\xB0C"
911
+ });
912
+ expect(ctx1.isEquivalent(ctx2)).toBe(true);
913
+ });
914
+ });
915
+ });
385
916
  //# sourceMappingURL=chat_context.test.js.map