meshagent-agents 0.5.3__py3-none-any.whl → 0.5.4__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.

meshagent/agents/chat.py CHANGED
@@ -1,4 +1,4 @@
1
- from .agent import SingleRoomAgent, AgentChatContext
1
+ from meshagent.agents.agent import SingleRoomAgent, AgentChatContext
2
2
  from meshagent.api.chan import Chan
3
3
  from meshagent.api import (
4
4
  RoomMessage,
@@ -10,7 +10,7 @@ from meshagent.api import (
10
10
  MeshDocument,
11
11
  )
12
12
  from meshagent.tools import Toolkit, ToolContext
13
- from .adapter import LLMAdapter, ToolResponseAdapter
13
+ from meshagent.agents.adapter import LLMAdapter, ToolResponseAdapter
14
14
  from meshagent.openai.tools.responses_adapter import ImageGenerationTool, LocalShellTool
15
15
  import asyncio
16
16
  from typing import Optional
@@ -22,6 +22,7 @@ from typing import Literal
22
22
  import base64
23
23
  from openai.types.responses import ResponseStreamEvent
24
24
  from asyncio import CancelledError
25
+ from meshagent.api import RoomException
25
26
 
26
27
  from opentelemetry import trace
27
28
  import shlex
@@ -307,13 +308,22 @@ class ChatBot(SingleRoomAgent):
307
308
 
308
309
  async def _send_and_save_chat(
309
310
  self,
310
- messages: Element,
311
+ thread: MeshDocument,
311
312
  path: str,
312
313
  to: RemoteParticipant,
313
314
  id: str,
314
315
  text: str,
315
316
  thread_attributes: dict,
316
317
  ):
318
+ messages = None
319
+
320
+ for prop in thread.root.get_children():
321
+ if prop.tag_name == "messages":
322
+ messages = prop
323
+
324
+ if messages is None:
325
+ raise RoomException("messages element was not found in thread document")
326
+
317
327
  with tracer.start_as_current_span("chatbot.thread.message") as span:
318
328
  span.set_attributes(thread_attributes)
319
329
  span.set_attribute("role", "assistant")
@@ -339,10 +349,10 @@ class ChatBot(SingleRoomAgent):
339
349
  },
340
350
  )
341
351
 
342
- async def greet(
352
+ async def _greet(
343
353
  self,
344
354
  *,
345
- messages: Element,
355
+ thread: MeshDocument,
346
356
  path: str,
347
357
  chat_context: AgentChatContext,
348
358
  participant: RemoteParticipant,
@@ -353,7 +363,7 @@ class ChatBot(SingleRoomAgent):
353
363
  await self._send_and_save_chat(
354
364
  id=str(uuid.uuid4()),
355
365
  to=RemoteParticipant(id=participant.id),
356
- messages=messages,
366
+ thread=thread,
357
367
  path=path,
358
368
  text=self._auto_greet_message,
359
369
  thread_attributes=thread_attributes,
@@ -403,107 +413,149 @@ class ChatBot(SingleRoomAgent):
403
413
  async def close_thread(self, *, path: str):
404
414
  return await self.room.sync.close(path=path)
405
415
 
406
- async def _spawn_thread(self, path: str, messages: Chan[RoomMessage]):
407
- self.room.developer.log_nowait(
408
- type="chatbot.thread.started", data={"path": path}
409
- )
410
- chat_context = await self.init_chat_context()
411
- opened = False
416
+ async def load_thread_context(self, *, thread_context: ChatThreadContext):
417
+ """
418
+ load the thread from the thread document by inserting the current messages in the thread into the chat context
419
+ """
420
+ thread = thread_context.thread
421
+ chat_context = thread_context.chat
422
+ for prop in thread.root.get_children():
423
+ if prop.tag_name == "messages":
424
+ doc_messages = prop
425
+
426
+ for element in doc_messages.get_children():
427
+ if isinstance(element, Element) and element.tag_name == "message":
428
+ msg = element["text"]
429
+ if element[
430
+ "author_name"
431
+ ] == self.room.local_participant.get_attribute("name"):
432
+ chat_context.append_assistant_message(msg)
433
+ else:
434
+ chat_context.append_user_message(msg)
435
+
436
+ for child in element.get_children():
437
+ if child.tag_name == "file":
438
+ chat_context.append_assistant_message(
439
+ f"the user attached a file with the path '{child.get_attribute('path')}'"
440
+ )
412
441
 
442
+ if doc_messages is None:
443
+ raise Exception("thread was not properly initialized")
444
+
445
+ async def prepare_llm_context(self, *, context: ChatThreadContext):
446
+ """
447
+ called prior to sending the request to the LLM in case the agent needs to modify the context prior to sending
448
+ """
449
+ pass
450
+
451
+ async def _process_llm_events(
452
+ self,
453
+ *,
454
+ thread_context: ChatThreadContext,
455
+ llm_messages: asyncio.Queue,
456
+ thread_attributes: dict,
457
+ ):
458
+ thread = thread_context.thread
413
459
  doc_messages = None
414
- current_file = None
415
- llm_messages = Chan[ResponseStreamEvent]()
416
- thread_context = None
460
+ for prop in thread.root.get_children():
461
+ if prop.tag_name == "messages":
462
+ doc_messages = prop
417
463
 
418
- thread_attributes = None
464
+ if doc_messages is None:
465
+ raise RoomException("messages element is missing from thread document")
466
+
467
+ context_message = None
468
+ updates = asyncio.Queue()
419
469
 
420
- def done_processing_llm_events(task: asyncio.Task):
470
+ # throttle updates so we don't send too many syncs over the wire at once
471
+ async def update_thread():
421
472
  try:
422
- task.result()
423
- except Exception as e:
424
- logger.error("error sending delta", exc_info=e)
425
-
426
- async def process_llm_events():
427
- context_message = None
428
- updates = asyncio.Queue()
429
-
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
473
+ changes = {}
474
+ while True:
475
+ try:
476
+ element, partial = updates.get_nowait()
477
+ changes[element] = partial
438
478
 
439
- except asyncio.QueueEmpty:
440
- for e, p in changes.items():
441
- e["text"] = p
479
+ except asyncio.QueueEmpty:
480
+ for e, p in changes.items():
481
+ e["text"] = p
442
482
 
443
- changes.clear()
483
+ changes.clear()
444
484
 
445
- e, p = await updates.get()
446
- changes[e] = p
485
+ e, p = await updates.get()
486
+ changes[e] = p
447
487
 
448
- await asyncio.sleep(0.1)
488
+ await asyncio.sleep(0.1)
449
489
 
450
- except asyncio.QueueShutDown:
451
- pass
490
+ except asyncio.QueueShutDown:
491
+ # flush any pending changes
492
+ for e, p in changes.items():
493
+ e["text"] = p
452
494
 
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
- )
495
+ changes.clear()
496
+ pass
460
497
 
461
- # self.room.messaging.send_message_nowait(to=participant, type="llm.event", message=json.loads(evt.to_json()))
498
+ update_thread_task = asyncio.create_task(update_thread())
499
+ try:
500
+ while True:
501
+ evt = await llm_messages.get()
502
+ for participant in self._room.messaging.get_participants():
503
+ logger.debug(
504
+ f"sending event {evt.type} to {participant.get_attribute('name')}"
505
+ )
462
506
 
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
- },
478
- )
507
+ # self.room.messaging.send_message_nowait(to=participant, type="llm.event", message=json.loads(evt.to_json()))
508
+
509
+ if evt.type == "response.content_part.added":
510
+ partial = ""
511
+
512
+ content_element = doc_messages.append_child(
513
+ tag_name="message",
514
+ attributes={
515
+ "text": "",
516
+ "created_at": datetime.datetime.now(datetime.timezone.utc)
517
+ .isoformat()
518
+ .replace("+00:00", "Z"),
519
+ "author_name": self.room.local_participant.get_attribute(
520
+ "name"
521
+ ),
522
+ },
523
+ )
479
524
 
480
- context_message = {"role": "assistant", "content": ""}
481
- chat_context.messages.append(context_message)
525
+ context_message = {"role": "assistant", "content": ""}
526
+ thread_context.chat.messages.append(context_message)
482
527
 
483
- elif evt.type == "response.output_text.delta":
484
- partial += evt.delta
485
- updates.put_nowait((content_element, partial))
486
- context_message["content"] = partial
528
+ elif evt.type == "response.output_text.delta":
529
+ partial += evt.delta
530
+ updates.put_nowait((content_element, partial))
531
+ context_message["content"] = partial
487
532
 
488
- elif evt.type == "response.output_text.done":
489
- content_element = None
533
+ elif evt.type == "response.output_text.done":
534
+ content_element = None
490
535
 
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
536
+ with tracer.start_as_current_span("chatbot.thread.message") as span:
537
+ span.set_attribute(
538
+ "from_participant_name",
539
+ self.room.local_participant.get_attribute("name"),
540
+ )
541
+ span.set_attribute("role", "assistant")
542
+ span.set_attributes(thread_attributes)
543
+ span.set_attributes({"text": evt.text})
544
+ except asyncio.QueueShutDown:
545
+ pass
546
+ finally:
547
+ updates.shutdown()
548
+ await update_thread_task
504
549
 
505
- llm_task = asyncio.create_task(process_llm_events())
506
- llm_task.add_done_callback(done_processing_llm_events)
550
+ async def _spawn_thread(self, path: str, messages: Chan[RoomMessage]):
551
+ logger.debug("chatbot is starting a thread", extra={"path": path})
552
+ chat_context = await self.init_chat_context()
553
+ opened = False
554
+
555
+ current_file = None
556
+ thread_context = None
557
+
558
+ thread_attributes = None
507
559
 
508
560
  thread = None
509
561
 
@@ -512,9 +564,9 @@ class ChatBot(SingleRoomAgent):
512
564
 
513
565
  while True:
514
566
  while True:
515
- logger.info(f"waiting for message on thread {path}")
567
+ logger.debug(f"waiting for message on thread {path}")
516
568
  received = await messages.recv()
517
- logger.info(f"received message on thread {path}: {received.type}")
569
+ logger.debug(f"received message on thread {path}: {received.type}")
518
570
 
519
571
  chat_with_participant = None
520
572
  for participant in self._room.messaging.get_participants():
@@ -569,83 +621,57 @@ class ChatBot(SingleRoomAgent):
569
621
 
570
622
  thread = await self.open_thread(path=path)
571
623
 
572
- for prop in thread.root.get_children():
573
- if prop.tag_name == "messages":
574
- doc_messages = prop
575
-
576
- for element in doc_messages.get_children():
577
- if (
578
- isinstance(element, Element)
579
- and element.tag_name == "message"
580
- ):
581
- msg = element["text"]
582
- if (
583
- element["author_name"]
584
- == self.room.local_participant.get_attribute(
585
- "name"
586
- )
587
- ):
588
- chat_context.append_assistant_message(
589
- msg
590
- )
591
- else:
592
- chat_context.append_user_message(msg)
593
-
594
- for child in element.get_children():
595
- if child.tag_name == "file":
596
- chat_context.append_assistant_message(
597
- f"the user attached a file with the path '{child.get_attribute('path')}'"
598
- )
599
-
600
- if doc_messages is None:
601
- raise Exception("thread was not properly initialized")
624
+ thread_context = ChatThreadContext(
625
+ path=path,
626
+ chat=chat_context,
627
+ thread=thread,
628
+ participants=get_thread_participants(
629
+ room=self.room, thread=thread
630
+ ),
631
+ )
632
+
633
+ await self.load_thread_context(
634
+ thread_context=thread_context
635
+ )
602
636
 
603
637
  if received.type == "opened":
604
638
  if not opened:
605
639
  opened = True
606
640
 
607
- await self.greet(
641
+ await self._greet(
608
642
  path=path,
609
643
  chat_context=chat_context,
610
644
  participant=chat_with_participant,
611
- messages=doc_messages,
645
+ thread=thread,
612
646
  thread_attributes=thread_attributes,
613
647
  )
614
648
 
615
649
  if received.type == "chat":
616
650
  if thread is None:
617
- self.room.developer.log_nowait(
618
- type="thread is not open", data={}
619
- )
651
+ logger.info("thread is not open", extra={"path": path})
620
652
  break
621
653
 
622
- if chat_with_participant.id == received.from_participant_id:
623
- self.room.developer.log_nowait(
624
- type="llm.message",
625
- data={
626
- "context": chat_context.id,
627
- "participant_id": self.room.local_participant.id,
628
- "participant_name": self.room.local_participant.get_attribute(
629
- "name"
630
- ),
631
- "message": {
632
- "content": {
633
- "role": "user",
634
- "text": received.message["text"],
635
- }
636
- },
637
- },
638
- )
654
+ logger.debug(
655
+ "chatbot received a chat",
656
+ extra={
657
+ "context": chat_context.id,
658
+ "participant_id": self.room.local_participant.id,
659
+ "participant_name": self.room.local_participant.get_attribute(
660
+ "name"
661
+ ),
662
+ "text": received.message["text"],
663
+ },
664
+ )
639
665
 
640
- attachments = received.message.get("attachments", [])
641
- text = received.message["text"]
666
+ attachments = received.message.get("attachments", [])
667
+ text = received.message["text"]
642
668
 
643
- for attachment in attachments:
644
- chat_context.append_assistant_message(
645
- message=f"the user attached a file at the path '{attachment['path']}'"
646
- )
669
+ for attachment in attachments:
670
+ chat_context.append_assistant_message(
671
+ message=f"the user attached a file at the path '{attachment['path']}'"
672
+ )
647
673
 
648
- chat_context.append_user_message(message=text)
674
+ chat_context.append_user_message(message=text)
649
675
 
650
676
  if messages.empty():
651
677
  break
@@ -690,9 +716,6 @@ class ChatBot(SingleRoomAgent):
690
716
  room=self.room, thread=thread
691
717
  )
692
718
 
693
- def handle_event(evt):
694
- llm_messages.send_nowait(evt)
695
-
696
719
  with tracer.start_as_current_span("chatbot.llm") as span:
697
720
  try:
698
721
  with tracer.start_as_current_span(
@@ -705,6 +728,23 @@ class ChatBot(SingleRoomAgent):
705
728
  )
706
729
  )
707
730
 
731
+ await self.prepare_llm_context(
732
+ context=thread_context
733
+ )
734
+
735
+ llm_messages = asyncio.Queue[ResponseStreamEvent]()
736
+
737
+ def handle_event(evt):
738
+ llm_messages.put_nowait(evt)
739
+
740
+ llm_task = asyncio.create_task(
741
+ self._process_llm_events(
742
+ thread_context=thread_context,
743
+ llm_messages=llm_messages,
744
+ thread_attributes=thread_attributes,
745
+ )
746
+ )
747
+
708
748
  await self._llm_adapter.next(
709
749
  context=chat_context,
710
750
  room=self._room,
@@ -713,10 +753,13 @@ class ChatBot(SingleRoomAgent):
713
753
  event_handler=handle_event,
714
754
  )
715
755
 
756
+ llm_messages.shutdown()
757
+ await llm_task
758
+
716
759
  except Exception as e:
717
760
  logger.error("An error was encountered", exc_info=e)
718
761
  await self._send_and_save_chat(
719
- messages=doc_messages,
762
+ thread=thread,
720
763
  to=chat_with_participant,
721
764
  path=path,
722
765
  id=str(uuid.uuid4()),
@@ -741,13 +784,9 @@ class ChatBot(SingleRoomAgent):
741
784
  finally:
742
785
 
743
786
  async def cleanup():
744
- llm_messages.close()
745
-
746
787
  if self.room is not None:
747
788
  logger.info(f"thread was ended {path}")
748
- self.room.developer.log_nowait(
749
- type="chatbot.thread.ended", data={"path": path}
750
- )
789
+ logger.info("chatbot thread ended", extra={"path": path})
751
790
 
752
791
  if thread is not None:
753
792
  await self.close_thread(path=path)
@@ -786,7 +825,7 @@ class ChatBot(SingleRoomAgent):
786
825
 
787
826
  messages = self._get_message_channel(path)
788
827
 
789
- logger.info(
828
+ logger.debug(
790
829
  f"queued incoming message for thread {path}: {message.type}"
791
830
  )
792
831
 
@@ -806,7 +845,7 @@ class ChatBot(SingleRoomAgent):
806
845
  f"The chat thread ended with an error {e}", exc_info=e
807
846
  )
808
847
 
809
- logger.info(f"spawning chat thread for {path}")
848
+ logger.debug(f"spawning chat thread for {path}")
810
849
  task = asyncio.create_task(
811
850
  self._spawn_thread(messages=messages, path=path)
812
851
  )
@@ -1 +1 @@
1
- __version__ = "0.5.3"
1
+ __version__ = "0.5.4"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: meshagent-agents
3
- Version: 0.5.3
3
+ Version: 0.5.4
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.3
16
- Requires-Dist: meshagent-tools~=0.5.3
17
- Requires-Dist: meshagent-openai~=0.5.3
15
+ Requires-Dist: meshagent-api~=0.5.4
16
+ Requires-Dist: meshagent-tools~=0.5.4
17
+ Requires-Dist: meshagent-openai~=0.5.4
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.3; extra == "all"
21
+ Requires-Dist: meshagent-api[all]~=0.5.4; 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.3; extra == "sync"
27
+ Requires-Dist: meshagent-api[sync]~=0.5.4; 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
2
  meshagent/agents/adapter.py,sha256=dMuejpjl__bdZ-Qmt-k4e81g-i10vZup7WE1JCZ_Sy4,1392
3
3
  meshagent/agents/agent.py,sha256=w14hM63YXiH15VEF1T2eZCvggvrUkE00a1kQkaMRBM0,20354
4
- meshagent/agents/chat.py,sha256=137LU0qkVxF53SQDV1gSHq2QeSFh4m17sGmXg_Ym77U,31964
4
+ meshagent/agents/chat.py,sha256=xnXQTRiiCL-rzZw8Gv1LJy09frQpHAoAHoK2-gzP6MM,32737
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=tgzuqHKcEdKBaP57F5oXxq4XlW2n9J4Fj8ZGu7nGOZg,22
17
+ meshagent/agents/version.py,sha256=DITpct-LrdIsTgwx2NgH5Ghx5y8Xgz1YMimy1ZV5RTY,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.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,,
26
+ meshagent_agents-0.5.4.dist-info/licenses/LICENSE,sha256=eTt0SPW-sVNdkZe9PS_S8WfCIyLjRXRl7sUBWdlteFg,10254
27
+ meshagent_agents-0.5.4.dist-info/METADATA,sha256=slVBBDAZPV--6XZANlTd_H-qRKuDmlE6alIVIViLq9g,3773
28
+ meshagent_agents-0.5.4.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
29
+ meshagent_agents-0.5.4.dist-info/top_level.txt,sha256=GlcXnHtRP6m7zlG3Df04M35OsHtNXy_DY09oFwWrH74,10
30
+ meshagent_agents-0.5.4.dist-info/RECORD,,