meshagent-agents 0.5.1__py3-none-any.whl → 0.5.3__py3-none-any.whl

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.

Potentially problematic release.


This version of meshagent-agents might be problematic. Click here for more details.

@@ -44,7 +44,7 @@ class LLMAdapter(Generic[T]):
44
44
  *,
45
45
  context: AgentChatContext,
46
46
  room: RoomClient,
47
- toolkits: Toolkit,
47
+ toolkits: list[Toolkit],
48
48
  tool_adapter: Optional[ToolResponseAdapter] = None,
49
49
  output_schema: Optional[dict] = None,
50
50
  event_handler: Optional[Callable[[T], None]] = None,
meshagent/agents/agent.py CHANGED
@@ -335,7 +335,7 @@ class TaskRunner(SingleRoomAgent):
335
335
  requires=None,
336
336
  supports_tools: Optional[bool] = None,
337
337
  input_schema: dict,
338
- output_schema: dict,
338
+ output_schema: Optional[dict] = None,
339
339
  labels: Optional[list[str]] = None,
340
340
  toolkits: Optional[list[Toolkit]] = None,
341
341
  ):
meshagent/agents/chat.py CHANGED
@@ -420,58 +420,87 @@ class ChatBot(SingleRoomAgent):
420
420
  def done_processing_llm_events(task: asyncio.Task):
421
421
  try:
422
422
  task.result()
423
- except CancelledError:
424
- pass
425
423
  except Exception as e:
426
424
  logger.error("error sending delta", exc_info=e)
427
425
 
428
426
  async def process_llm_events():
429
- partial = ""
430
- content_element = None
431
427
  context_message = None
428
+ updates = asyncio.Queue()
432
429
 
433
- async for evt in llm_messages:
434
- for participant in self._room.messaging.get_participants():
435
- logger.debug(
436
- f"sending event {evt.type} to {participant.get_attribute('name')}"
437
- )
430
+ # throttle updates so we don't send too many syncs over the wire at once
431
+ async def update_thread():
432
+ try:
433
+ changes = {}
434
+ while True:
435
+ try:
436
+ element, partial = updates.get_nowait()
437
+ changes[element] = partial
438
438
 
439
- # self.room.messaging.send_message_nowait(to=participant, type="llm.event", message=json.loads(evt.to_json()))
440
-
441
- if evt.type == "response.content_part.added":
442
- partial = ""
443
- content_element = doc_messages.append_child(
444
- tag_name="message",
445
- attributes={
446
- "text": "",
447
- "created_at": datetime.datetime.now(datetime.timezone.utc)
448
- .isoformat()
449
- .replace("+00:00", "Z"),
450
- "author_name": self.room.local_participant.get_attribute(
451
- "name"
452
- ),
453
- },
454
- )
439
+ except asyncio.QueueEmpty:
440
+ for e, p in changes.items():
441
+ e["text"] = p
455
442
 
456
- context_message = {"role": "assistant", "content": ""}
457
- chat_context.messages.append(context_message)
443
+ changes.clear()
458
444
 
459
- elif evt.type == "response.output_text.delta":
460
- partial += evt.delta
461
- content_element["text"] = partial
462
- context_message["content"] = partial
445
+ e, p = await updates.get()
446
+ changes[e] = p
463
447
 
464
- elif evt.type == "response.output_text.done":
465
- content_element = None
448
+ await asyncio.sleep(0.1)
466
449
 
467
- with tracer.start_as_current_span("chatbot.thread.message") as span:
468
- span.set_attribute(
469
- "from_participant_name",
470
- self.room.local_participant.get_attribute("name"),
450
+ except asyncio.QueueShutDown:
451
+ pass
452
+
453
+ update_thread_task = asyncio.create_task(update_thread())
454
+ try:
455
+ async for evt in llm_messages:
456
+ for participant in self._room.messaging.get_participants():
457
+ logger.debug(
458
+ f"sending event {evt.type} to {participant.get_attribute('name')}"
459
+ )
460
+
461
+ # self.room.messaging.send_message_nowait(to=participant, type="llm.event", message=json.loads(evt.to_json()))
462
+
463
+ if evt.type == "response.content_part.added":
464
+ partial = ""
465
+ content_element = doc_messages.append_child(
466
+ tag_name="message",
467
+ attributes={
468
+ "text": "",
469
+ "created_at": datetime.datetime.now(
470
+ datetime.timezone.utc
471
+ )
472
+ .isoformat()
473
+ .replace("+00:00", "Z"),
474
+ "author_name": self.room.local_participant.get_attribute(
475
+ "name"
476
+ ),
477
+ },
471
478
  )
472
- span.set_attribute("role", "assistant")
473
- span.set_attributes(thread_attributes)
474
- span.set_attributes({"text": evt.text})
479
+
480
+ context_message = {"role": "assistant", "content": ""}
481
+ chat_context.messages.append(context_message)
482
+
483
+ elif evt.type == "response.output_text.delta":
484
+ partial += evt.delta
485
+ updates.put_nowait((content_element, partial))
486
+ context_message["content"] = partial
487
+
488
+ elif evt.type == "response.output_text.done":
489
+ content_element = None
490
+
491
+ with tracer.start_as_current_span(
492
+ "chatbot.thread.message"
493
+ ) as span:
494
+ span.set_attribute(
495
+ "from_participant_name",
496
+ self.room.local_participant.get_attribute("name"),
497
+ )
498
+ span.set_attribute("role", "assistant")
499
+ span.set_attributes(thread_attributes)
500
+ span.set_attributes({"text": evt.text})
501
+ finally:
502
+ updates.shutdown()
503
+ await update_thread_task
475
504
 
476
505
  llm_task = asyncio.create_task(process_llm_events())
477
506
  llm_task.add_done_callback(done_processing_llm_events)
@@ -590,16 +619,6 @@ class ChatBot(SingleRoomAgent):
590
619
  )
591
620
  break
592
621
 
593
- for participant in get_thread_participants(
594
- room=self._room, thread=thread
595
- ):
596
- # TODO: async gather
597
- self._room.messaging.send_message_nowait(
598
- to=participant,
599
- type="thinking",
600
- message={"thinking": True, "path": path},
601
- )
602
-
603
622
  if chat_with_participant.id == received.from_participant_id:
604
623
  self.room.developer.log_nowait(
605
624
  type="llm.message",
@@ -628,13 +647,6 @@ class ChatBot(SingleRoomAgent):
628
647
 
629
648
  chat_context.append_user_message(message=text)
630
649
 
631
- # if user is typing, wait for typing to stop
632
- while True:
633
- if chat_with_participant.id not in self._is_typing:
634
- break
635
-
636
- await asyncio.sleep(0.5)
637
-
638
650
  if messages.empty():
639
651
  break
640
652
 
@@ -654,6 +666,16 @@ class ChatBot(SingleRoomAgent):
654
666
  span.set_attributes({"text": text})
655
667
 
656
668
  try:
669
+ for participant in get_thread_participants(
670
+ room=self._room, thread=thread
671
+ ):
672
+ # TODO: async gather
673
+ self._room.messaging.send_message_nowait(
674
+ to=participant,
675
+ type="thinking",
676
+ message={"thinking": True, "path": path},
677
+ )
678
+
657
679
  if thread_context is None:
658
680
  thread_context = ChatThreadContext(
659
681
  path=path,
@@ -690,6 +712,7 @@ class ChatBot(SingleRoomAgent):
690
712
  tool_adapter=self._tool_adapter,
691
713
  event_handler=handle_event,
692
714
  )
715
+
693
716
  except Exception as e:
694
717
  logger.error("An error was encountered", exc_info=e)
695
718
  await self._send_and_save_chat(
@@ -702,27 +725,34 @@ class ChatBot(SingleRoomAgent):
702
725
  )
703
726
 
704
727
  finally:
705
- for participant in get_thread_participants(
706
- room=self._room, thread=thread
707
- ):
708
- # TODO: async gather
709
- self._room.messaging.send_message_nowait(
710
- to=participant,
711
- type="thinking",
712
- message={"thinking": False, "path": path},
713
- )
728
+
729
+ async def cleanup():
730
+ for participant in get_thread_participants(
731
+ room=self._room, thread=thread
732
+ ):
733
+ self._room.messaging.send_message_nowait(
734
+ to=participant,
735
+ type="thinking",
736
+ message={"thinking": False, "path": path},
737
+ )
738
+
739
+ asyncio.shield(cleanup())
714
740
 
715
741
  finally:
716
- llm_messages.close()
717
742
 
718
- if self.room is not None:
719
- logger.info("thread was ended {path}")
720
- self.room.developer.log_nowait(
721
- type="chatbot.thread.ended", data={"path": path}
722
- )
743
+ async def cleanup():
744
+ llm_messages.close()
745
+
746
+ if self.room is not None:
747
+ logger.info(f"thread was ended {path}")
748
+ self.room.developer.log_nowait(
749
+ type="chatbot.thread.ended", data={"path": path}
750
+ )
723
751
 
724
- if thread is not None:
725
- await self.close_thread(path=path)
752
+ if thread is not None:
753
+ await self.close_thread(path=path)
754
+
755
+ asyncio.shield(cleanup())
726
756
 
727
757
  def _get_message_channel(self, key: str) -> Chan[RoomMessage]:
728
758
  if key not in self._message_channels:
@@ -765,6 +795,7 @@ class ChatBot(SingleRoomAgent):
765
795
  if path not in self._thread_tasks or self._thread_tasks[path].done():
766
796
 
767
797
  def thread_done(task: asyncio.Task):
798
+ self._thread_tasks.pop(path)
768
799
  self._message_channels.pop(path)
769
800
  try:
770
801
  task.result()
@@ -783,6 +814,11 @@ class ChatBot(SingleRoomAgent):
783
814
 
784
815
  self._thread_tasks[path] = task
785
816
 
817
+ elif message.type == "cancel":
818
+ path = message.message["path"]
819
+ if path in self._thread_tasks:
820
+ self._thread_tasks[path].cancel()
821
+
786
822
  elif message.type == "typing":
787
823
 
788
824
  def callback(task: asyncio.Task):
@@ -1 +1 @@
1
- __version__ = "0.5.1"
1
+ __version__ = "0.5.3"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: meshagent-agents
3
- Version: 0.5.1
3
+ Version: 0.5.3
4
4
  Summary: Agent Building Blocks for Meshagent
5
5
  License-Expression: Apache-2.0
6
6
  Project-URL: Documentation, https://docs.meshagent.com
@@ -12,19 +12,19 @@ License-File: LICENSE
12
12
  Requires-Dist: pyjwt~=2.10
13
13
  Requires-Dist: pytest~=8.4
14
14
  Requires-Dist: pytest-asyncio~=0.26
15
- Requires-Dist: meshagent-api~=0.5.1
16
- Requires-Dist: meshagent-tools~=0.5.1
17
- Requires-Dist: meshagent-openai~=0.5.1
15
+ Requires-Dist: meshagent-api~=0.5.3
16
+ Requires-Dist: meshagent-tools~=0.5.3
17
+ Requires-Dist: meshagent-openai~=0.5.3
18
18
  Requires-Dist: pydantic~=2.11
19
19
  Requires-Dist: opentelemetry-distro~=0.54b1
20
20
  Provides-Extra: all
21
- Requires-Dist: meshagent-api[all]~=0.5.1; extra == "all"
21
+ Requires-Dist: meshagent-api[all]~=0.5.3; extra == "all"
22
22
  Requires-Dist: chonkie~=0.5.1; extra == "all"
23
23
  Requires-Dist: chonkie[semantic]~=0.5.1; extra == "all"
24
24
  Requires-Dist: chonkie[openai]~=0.5.1; extra == "all"
25
25
  Requires-Dist: aiosmtplib~=4.0.1; extra == "all"
26
26
  Provides-Extra: sync
27
- Requires-Dist: meshagent-api[sync]~=0.5.1; extra == "sync"
27
+ Requires-Dist: meshagent-api[sync]~=0.5.3; extra == "sync"
28
28
  Provides-Extra: mail
29
29
  Requires-Dist: aiosmtplib~=4.0.1; extra == "mail"
30
30
  Provides-Extra: rag
@@ -1,7 +1,7 @@
1
1
  meshagent/agents/__init__.py,sha256=d2cplyLH8xqDWqP_GoPQ8ApHzuv8Iiq4rz-vYBlGMTw,706
2
- meshagent/agents/adapter.py,sha256=CZgVzUTTY8dyPBYA7O_Kaawb40maxAbUUhBFk1YjbsI,1386
3
- meshagent/agents/agent.py,sha256=OaWjjccOsU_n-Pr6WdA90LePGQflHQlL-X5lJ72s3pc,20337
4
- meshagent/agents/chat.py,sha256=HocrfVSV6kJaNUG5umKhi22AKwyq0ySCfVM--7ytjtE,30595
2
+ meshagent/agents/adapter.py,sha256=dMuejpjl__bdZ-Qmt-k4e81g-i10vZup7WE1JCZ_Sy4,1392
3
+ meshagent/agents/agent.py,sha256=w14hM63YXiH15VEF1T2eZCvggvrUkE00a1kQkaMRBM0,20354
4
+ meshagent/agents/chat.py,sha256=137LU0qkVxF53SQDV1gSHq2QeSFh4m17sGmXg_Ym77U,31964
5
5
  meshagent/agents/context.py,sha256=6txCXA22aHQaikvIKED6YjPyasM_bPqGqCE4HGj04_E,4035
6
6
  meshagent/agents/development.py,sha256=AEBkkycNZDRLYIdmX2LkrVZv715ALswiwSR9CiV3HE4,894
7
7
  meshagent/agents/hosting.py,sha256=tCcswAweEhlMxGaBR_m2YvUkwZiaHbTBT64urRHfK7I,5446
@@ -14,7 +14,7 @@ meshagent/agents/pydantic.py,sha256=RrdOESZg-n_FyxbfkOBwRPVxV39IOjxK2unsyAGn9as,
14
14
  meshagent/agents/single_shot_writer.py,sha256=miWVMo4NX8Hib0yHwDmiwuk8GraJwg1JzljsgFyTl4Y,3237
15
15
  meshagent/agents/thread_schema.py,sha256=OGQ-H5c2fJgNOYHC3Pas8iqTi2RUSxP2bytf0SK-SYc,4208
16
16
  meshagent/agents/utils.py,sha256=6D9GXpYu9xx5XlfD3DiGFdyOwq46e5-sTYOF_FYep1o,1446
17
- meshagent/agents/version.py,sha256=eZ1bOun1DDVV0YLOBW4wj2FP1ajReLjbIrGmzN7ASBw,22
17
+ meshagent/agents/version.py,sha256=tgzuqHKcEdKBaP57F5oXxq4XlW2n9J4Fj8ZGu7nGOZg,22
18
18
  meshagent/agents/worker.py,sha256=SkrPhxIQ-Chyjg-eZGOlehkbrVYmsas8zmZnrTsAl3o,3910
19
19
  meshagent/agents/writer.py,sha256=dXglYgHwBrBJIaapMqBDyD3kmwSyi94tOdHH44itODc,2682
20
20
  meshagent/agents/schemas/__init__.py,sha256=_xAhrkxvFdfer3NolrynragGxcLElGR51LSribT3deU,299
@@ -23,8 +23,8 @@ meshagent/agents/schemas/gallery.py,sha256=65IsrH2wiFIR-DNo8est-nCOC72i1Aa5EmVNU
23
23
  meshagent/agents/schemas/presentation.py,sha256=aaMzkFQryurbHd1fbzTQPdN7v8QIhsjXuvbE8ZiuXNY,1589
24
24
  meshagent/agents/schemas/schema.py,sha256=8OXGCLVouoPg6eHBU9mgf1pTGTMvVZqiKNq15wkQJe0,5310
25
25
  meshagent/agents/schemas/super_editor_document.py,sha256=iRv4Q-DE_5kUdsAD5Rm4GwHek8L_7ZEpxIZ1x2dWjdg,1813
26
- meshagent_agents-0.5.1.dist-info/licenses/LICENSE,sha256=eTt0SPW-sVNdkZe9PS_S8WfCIyLjRXRl7sUBWdlteFg,10254
27
- meshagent_agents-0.5.1.dist-info/METADATA,sha256=f-ytgdDrFU5ZaW4R3NzYgDYpv886BnLXoTiW5HMOC6A,3773
28
- meshagent_agents-0.5.1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
29
- meshagent_agents-0.5.1.dist-info/top_level.txt,sha256=GlcXnHtRP6m7zlG3Df04M35OsHtNXy_DY09oFwWrH74,10
30
- meshagent_agents-0.5.1.dist-info/RECORD,,
26
+ meshagent_agents-0.5.3.dist-info/licenses/LICENSE,sha256=eTt0SPW-sVNdkZe9PS_S8WfCIyLjRXRl7sUBWdlteFg,10254
27
+ meshagent_agents-0.5.3.dist-info/METADATA,sha256=_Fi7KmyntVN55jJ73d6eLDgs8a6QoljVVH-SCOVx9zE,3773
28
+ meshagent_agents-0.5.3.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
29
+ meshagent_agents-0.5.3.dist-info/top_level.txt,sha256=GlcXnHtRP6m7zlG3Df04M35OsHtNXy_DY09oFwWrH74,10
30
+ meshagent_agents-0.5.3.dist-info/RECORD,,