meshagent-agents 0.0.34__tar.gz → 0.0.36__tar.gz

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.

Files changed (38) hide show
  1. {meshagent_agents-0.0.34 → meshagent_agents-0.0.36}/CHANGELOG.md +6 -0
  2. {meshagent_agents-0.0.34/meshagent_agents.egg-info → meshagent_agents-0.0.36}/PKG-INFO +10 -11
  3. {meshagent_agents-0.0.34 → meshagent_agents-0.0.36}/meshagent/agents/agent.py +1 -2
  4. {meshagent_agents-0.0.34 → meshagent_agents-0.0.36}/meshagent/agents/chat.py +202 -175
  5. {meshagent_agents-0.0.34 → meshagent_agents-0.0.36}/meshagent/agents/hosting.py +3 -3
  6. meshagent_agents-0.0.36/meshagent/agents/version.py +1 -0
  7. {meshagent_agents-0.0.34 → meshagent_agents-0.0.36/meshagent_agents.egg-info}/PKG-INFO +10 -11
  8. {meshagent_agents-0.0.34 → meshagent_agents-0.0.36}/meshagent_agents.egg-info/requires.txt +9 -10
  9. {meshagent_agents-0.0.34 → meshagent_agents-0.0.36}/pyproject.toml +9 -10
  10. meshagent_agents-0.0.34/meshagent/agents/version.py +0 -1
  11. {meshagent_agents-0.0.34 → meshagent_agents-0.0.36}/LICENSE +0 -0
  12. {meshagent_agents-0.0.34 → meshagent_agents-0.0.36}/MANIFEST.in +0 -0
  13. {meshagent_agents-0.0.34 → meshagent_agents-0.0.36}/README.md +0 -0
  14. {meshagent_agents-0.0.34 → meshagent_agents-0.0.36}/meshagent/agents/__init__.py +0 -0
  15. {meshagent_agents-0.0.34 → meshagent_agents-0.0.36}/meshagent/agents/adapter.py +0 -0
  16. {meshagent_agents-0.0.34 → meshagent_agents-0.0.36}/meshagent/agents/context.py +0 -0
  17. {meshagent_agents-0.0.34 → meshagent_agents-0.0.36}/meshagent/agents/development.py +0 -0
  18. {meshagent_agents-0.0.34 → meshagent_agents-0.0.36}/meshagent/agents/indexer.py +0 -0
  19. {meshagent_agents-0.0.34 → meshagent_agents-0.0.36}/meshagent/agents/listener.py +0 -0
  20. {meshagent_agents-0.0.34 → meshagent_agents-0.0.36}/meshagent/agents/mail.py +0 -0
  21. {meshagent_agents-0.0.34 → meshagent_agents-0.0.36}/meshagent/agents/planning.py +0 -0
  22. {meshagent_agents-0.0.34 → meshagent_agents-0.0.36}/meshagent/agents/prompt.py +0 -0
  23. {meshagent_agents-0.0.34 → meshagent_agents-0.0.36}/meshagent/agents/pydantic.py +0 -0
  24. {meshagent_agents-0.0.34 → meshagent_agents-0.0.36}/meshagent/agents/schemas/__init__.py +0 -0
  25. {meshagent_agents-0.0.34 → meshagent_agents-0.0.36}/meshagent/agents/schemas/document.py +0 -0
  26. {meshagent_agents-0.0.34 → meshagent_agents-0.0.36}/meshagent/agents/schemas/gallery.py +0 -0
  27. {meshagent_agents-0.0.34 → meshagent_agents-0.0.36}/meshagent/agents/schemas/presentation.py +0 -0
  28. {meshagent_agents-0.0.34 → meshagent_agents-0.0.36}/meshagent/agents/schemas/schema.py +0 -0
  29. {meshagent_agents-0.0.34 → meshagent_agents-0.0.36}/meshagent/agents/schemas/super_editor_document.py +0 -0
  30. {meshagent_agents-0.0.34 → meshagent_agents-0.0.36}/meshagent/agents/single_shot_writer.py +0 -0
  31. {meshagent_agents-0.0.34 → meshagent_agents-0.0.36}/meshagent/agents/thread_schema.py +0 -0
  32. {meshagent_agents-0.0.34 → meshagent_agents-0.0.36}/meshagent/agents/utils.py +0 -0
  33. {meshagent_agents-0.0.34 → meshagent_agents-0.0.36}/meshagent/agents/worker.py +0 -0
  34. {meshagent_agents-0.0.34 → meshagent_agents-0.0.36}/meshagent/agents/writer.py +0 -0
  35. {meshagent_agents-0.0.34 → meshagent_agents-0.0.36}/meshagent_agents.egg-info/SOURCES.txt +0 -0
  36. {meshagent_agents-0.0.34 → meshagent_agents-0.0.36}/meshagent_agents.egg-info/dependency_links.txt +0 -0
  37. {meshagent_agents-0.0.34 → meshagent_agents-0.0.36}/meshagent_agents.egg-info/top_level.txt +0 -0
  38. {meshagent_agents-0.0.34 → meshagent_agents-0.0.36}/setup.cfg +0 -0
@@ -1,3 +1,9 @@
1
+ ## [0.0.36]
2
+ - Stability
3
+
4
+ ## [0.0.35]
5
+ - Stability
6
+
1
7
  ## [0.0.34]
2
8
  - Stability
3
9
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: meshagent-agents
3
- Version: 0.0.34
3
+ Version: 0.0.36
4
4
  Summary: Agent Building Blocks for Meshagent
5
5
  License-Expression: Apache-2.0
6
6
  Project-URL: Documentation, https://docs.meshagent.com
@@ -9,23 +9,22 @@ Project-URL: Source, https://www.meshagent.com
9
9
  Requires-Python: >=3.12
10
10
  Description-Content-Type: text/markdown
11
11
  License-File: LICENSE
12
- Requires-Dist: pyjwt~=2.10.1
13
- Requires-Dist: pytest~=8.3.5
14
- Requires-Dist: pytest-asyncio~=0.26.0
15
- Requires-Dist: meshagent-api~=0.0.34
16
- Requires-Dist: meshagent-tools~=0.0.34
17
- Requires-Dist: meshagent-openai~=0.0.34
18
- Requires-Dist: pydantic~=2.11.1
19
- Requires-Dist: pydantic-ai~=0.0.48
12
+ Requires-Dist: pyjwt~=2.10
13
+ Requires-Dist: pytest~=8.3
14
+ Requires-Dist: pytest-asyncio~=0.26
15
+ Requires-Dist: meshagent-api~=0.0.36
16
+ Requires-Dist: meshagent-tools~=0.0.36
17
+ Requires-Dist: meshagent-openai~=0.0.36
18
+ Requires-Dist: pydantic~=2.11
20
19
  Requires-Dist: opentelemetry-distro~=0.54b1
21
20
  Provides-Extra: all
22
- Requires-Dist: meshagent-api[all]~=0.0.34; extra == "all"
21
+ Requires-Dist: meshagent-api[all]~=0.0.36; extra == "all"
23
22
  Requires-Dist: chonkie~=0.5.1; extra == "all"
24
23
  Requires-Dist: chonkie[semantic]~=0.5.1; extra == "all"
25
24
  Requires-Dist: chonkie[openai]~=0.5.1; extra == "all"
26
25
  Requires-Dist: aiosmtplib~=4.0.1; extra == "all"
27
26
  Provides-Extra: sync
28
- Requires-Dist: meshagent-api[sync]~=0.0.34; extra == "sync"
27
+ Requires-Dist: meshagent-api[sync]~=0.0.36; extra == "sync"
29
28
  Provides-Extra: mail
30
29
  Requires-Dist: aiosmtplib~=4.0.1; extra == "mail"
31
30
  Provides-Extra: rag
@@ -174,8 +174,7 @@ class SingleRoomAgent(Agent):
174
174
  installed = True
175
175
 
176
176
  schema_path = f".schemas/{requirement.name}.json"
177
-
178
-
177
+
179
178
  if await self._room.storage.exists(path=schema_path):
180
179
  # Schema is already in the room
181
180
  pass
@@ -15,6 +15,7 @@ import json
15
15
  from typing import Literal, Optional
16
16
  import base64
17
17
  from openai.types.responses import ResponseStreamEvent
18
+ from asyncio import CancelledError
18
19
 
19
20
  from opentelemetry import trace
20
21
 
@@ -222,13 +223,15 @@ class ChatBot(SingleRoomAgent):
222
223
  )
223
224
  )
224
225
 
225
- async def _send_and_save_chat(self, messages: Element, path: str, to: RemoteParticipant, id: str, text: str):
226
+ async def _send_and_save_chat(self, messages: Element, path: str, to: RemoteParticipant, id: str, text: str, thread_attributes: dict):
226
227
 
227
- with tracer.start_as_current_span("chatbot.say") as span:
228
+ with tracer.start_as_current_span("chatbot.thread.message") as span:
228
229
 
230
+ span.set_attributes(thread_attributes)
231
+ span.set_attribute("role", "assistant")
232
+ span.set_attribute("from_participant_name", self.room.local_participant.get_attribute("name"))
229
233
  span.set_attributes({
230
234
  "id" : id,
231
- "path" : path,
232
235
  "text" : text
233
236
  })
234
237
 
@@ -242,11 +245,11 @@ class ChatBot(SingleRoomAgent):
242
245
  })
243
246
 
244
247
 
245
- async def greet(self, *, messages: Element, path: str, chat_context: AgentChatContext, participant: RemoteParticipant):
248
+ async def greet(self, *, messages: Element, path: str, chat_context: AgentChatContext, participant: RemoteParticipant, thread_attributes: dict):
246
249
 
247
250
  if self._auto_greet_message != None:
248
251
  chat_context.append_user_message(self._auto_greet_message)
249
- await self._send_and_save_chat(id=str(uuid.uuid4()), to=RemoteParticipant(id=participant.id), messages=messages, path=path, text= self._auto_greet_message)
252
+ await self._send_and_save_chat(id=str(uuid.uuid4()), to=RemoteParticipant(id=participant.id), messages=messages, path=path, text= self._auto_greet_message, thread_attributes=thread_attributes)
250
253
 
251
254
 
252
255
  async def get_thread_participants(self, *, thread: MeshDocument):
@@ -300,16 +303,20 @@ class ChatBot(SingleRoomAgent):
300
303
  self.room.developer.log_nowait(type="chatbot.thread.started", data={ "path" : path })
301
304
  chat_context = await self.init_chat_context()
302
305
  opened = False
303
- thread = None
306
+
304
307
  doc_messages = None
305
308
  current_file = None
306
309
  llm_messages = Chan[ResponseStreamEvent]()
307
310
  thread_context = None
311
+
312
+ thread_attributes = None
308
313
 
309
314
 
310
315
  def done_processing_llm_events(task: asyncio.Task):
311
316
  try:
312
317
  task.result()
318
+ except CancelledError as e:
319
+ pass
313
320
  except Exception as e:
314
321
  logger.error("error sending delta", exc_info=e)
315
322
 
@@ -322,7 +329,7 @@ class ChatBot(SingleRoomAgent):
322
329
  async for evt in llm_messages:
323
330
 
324
331
  for participant in self._room.messaging.get_participants():
325
- logger.info(f"sending event {evt.type} to {participant.get_attribute("name")}")
332
+ logger.debug(f"sending event {evt.type} to {participant.get_attribute("name")}")
326
333
 
327
334
  # self.room.messaging.send_message_nowait(to=participant, type="llm.event", message=json.loads(evt.to_json()))
328
335
 
@@ -348,180 +355,207 @@ class ChatBot(SingleRoomAgent):
348
355
  elif evt.type == "response.output_text.done":
349
356
  content_element = None
350
357
 
358
+ with tracer.start_as_current_span("chatbot.thread.message") as span:
359
+ span.set_attribute("from_participant_name", self.room.local_participant.get_attribute("name"))
360
+ span.set_attribute("role", "assistant")
361
+ span.set_attributes(thread_attributes)
362
+ span.set_attributes({
363
+ "text" : evt.text
364
+ })
351
365
 
352
366
  llm_task = asyncio.create_task(process_llm_events())
353
367
  llm_task.add_done_callback(done_processing_llm_events)
354
368
 
369
+ thread = None
370
+
355
371
  try:
356
372
 
373
+ received = None
374
+
357
375
  while True:
358
376
 
359
377
  while True:
360
-
378
+
379
+ logger.info(f"waiting for message on thread {path}")
361
380
  received = await messages.recv()
381
+ logger.info(f"received message on thread {path}: {received.type}")
362
382
 
363
- with tracer.start_as_current_span("chatbot.thread.receive") as span:
383
+ chat_with_participant = None
384
+ for participant in self._room.messaging.get_participants():
385
+ if participant.id == received.from_participant_id:
386
+ chat_with_participant = participant
387
+ break
388
+
389
+ if chat_with_participant == None:
390
+ logger.warning("participant does not have messaging enabled, skipping message")
391
+ continue
392
+
393
+ thread_attributes = {
394
+ "agent_name" : self.name,
395
+ "agent_participant_id" : self.room.local_participant.id,
396
+ "agent_participant_name" : self.room.local_participant.get_attribute("name"),
397
+ "remote_participant_id" : chat_with_participant.id,
398
+ "remote_participant_name" : chat_with_participant.get_attribute("name"),
399
+ "path" : path,
400
+ }
401
+
402
+ if current_file != chat_with_participant.get_attribute("current_file"):
403
+ logger.info(f"participant is now looking at {chat_with_participant.get_attribute("current_file")}")
404
+ current_file = chat_with_participant.get_attribute("current_file")
405
+
406
+ if current_file != None:
407
+ chat_context.append_assistant_message(message=f"the user is currently viewing the file at the path: {current_file}")
364
408
 
365
- span.set_attributes({
366
- "from_participant_id" : received.from_participant_id,
367
- "type" : received.type,
368
- "has_attachment" : received.attachment != None,
369
- })
409
+ elif current_file != None:
410
+ chat_context.append_assistant_message(message=f"the user is not current viewing any files")
370
411
 
371
- chat_with_participant = None
372
- for participant in self._room.messaging.get_participants():
373
- if participant.id == received.from_participant_id:
374
- chat_with_participant = participant
375
- break
376
-
377
- if chat_with_participant == None:
378
- logger.warning("participant does not have messaging enabled, skipping message")
379
- continue
380
-
381
- if current_file != chat_with_participant.get_attribute("current_file"):
382
- logger.info(f"participant is now looking at {chat_with_participant.get_attribute("current_file")}")
383
- current_file = chat_with_participant.get_attribute("current_file")
384
-
385
- if current_file != None:
386
- chat_context.append_assistant_message(message=f"the user is currently viewing the file at the path: {current_file}")
412
+ if thread == None:
387
413
 
388
- elif current_file != None:
389
- chat_context.append_assistant_message(message=f"the user is not current viewing any files")
414
+ with tracer.start_as_current_span("chatbot.thread.open") as span:
390
415
 
391
-
392
- if thread == None:
393
- with tracer.start_as_current_span("chatbot.open_thread") as span:
416
+ span.set_attributes(thread_attributes)
394
417
 
395
- thread = await self.open_thread(path=path)
418
+ thread = await self.open_thread(path=path)
419
+
420
+ for prop in thread.root.get_children():
396
421
 
397
- for prop in thread.root.get_children():
422
+ if prop.tag_name == "messages":
423
+
424
+ doc_messages = prop
398
425
 
399
- if prop.tag_name == "messages":
426
+ for element in doc_messages.get_children():
427
+
428
+ if isinstance(element, Element):
429
+
430
+ msg = element["text"]
431
+ if element["author_name"] == 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(f"the user attached a file with the path '{child.get_attribute("path")}'")
439
+
440
+ if doc_messages == None:
441
+ raise Exception("thread was not properly initialized")
400
442
 
401
- doc_messages = prop
402
-
403
- for element in doc_messages.get_children():
404
-
405
- if isinstance(element, Element):
406
-
407
- msg = element["text"]
408
- if element["author_name"] == self.room.local_participant.get_attribute("name"):
409
- chat_context.append_assistant_message(msg)
410
- else:
411
- chat_context.append_user_message(msg)
412
-
413
- for child in element.get_children():
414
- if child.tag_name == "file":
415
- chat_context.append_assistant_message(f"the user attached a file with the path '{child.get_attribute("path")}'")
416
-
417
- if doc_messages == None:
418
- raise Exception("thread was not properly initialized")
419
443
 
444
+ if received.type == "opened":
445
+
446
+ if opened == False:
447
+
448
+ opened = True
449
+
450
+ await self.greet(path=path, chat_context=chat_context, participant=chat_with_participant, messages=doc_messages, thread_attributes=thread_attributes)
420
451
 
421
- if received.type == "opened":
452
+ if received.type == "chat":
422
453
 
423
- if opened == False:
424
-
425
- opened = True
426
-
427
- await self.greet(path=path, chat_context=chat_context, participant=chat_with_participant, messages=doc_messages)
454
+
455
+ if thread == None:
428
456
 
429
- if received.type == "chat":
457
+ self.room.developer.log_nowait(type="thread is not open", data={})
458
+ break
430
459
 
431
- with tracer.start_as_current_span("chatbot.handle_chat") as span:
432
-
433
- text = received.message["text"]
434
- span.set_attributes({
435
- "text" : text
436
- })
437
-
438
- if thread == None:
439
460
 
440
- self.room.developer.log_nowait(type="thread is not open", data={})
441
- break
461
+ for participant in get_thread_participants(room=self._room, thread=thread):
462
+ # TODO: async gather
463
+ self._room.messaging.send_message_nowait(to=participant, type="thinking", message={"thinking":True, "path": path})
442
464
 
465
+ if chat_with_participant.id == received.from_participant_id:
466
+ self.room.developer.log_nowait(type="llm.message", data={ "context" : chat_context.id, "participant_id" : self.room.local_participant.id, "participant_name" : self.room.local_participant.get_attribute("name"), "message" : { "content" : { "role" : "user", "text" : received.message["text"] } } })
443
467
 
444
- for participant in get_thread_participants(room=self._room, thread=thread):
445
- # TODO: async gather
446
- self._room.messaging.send_message_nowait(to=participant, type="thinking", message={"thinking":True, "path": path})
468
+ attachments = received.message.get("attachments", [])
469
+ text = received.message["text"]
447
470
 
448
- if chat_with_participant.id == received.from_participant_id:
449
- self.room.developer.log_nowait(type="llm.message", data={ "context" : chat_context.id, "participant_id" : self.room.local_participant.id, "participant_name" : self.room.local_participant.get_attribute("name"), "message" : { "content" : { "role" : "user", "text" : received.message["text"] } } })
471
+ for attachment in attachments:
450
472
 
451
- attachments = received.message.get("attachments", [])
473
+ chat_context.append_assistant_message(message=f"the user attached a file at the path '{attachment["path"]}'")
452
474
 
453
- for attachment in attachments:
475
+ chat_context.append_user_message(message=text)
476
+
454
477
 
455
- chat_context.append_assistant_message(message=f"the user attached a file at the path '{attachment["path"]}'")
456
-
478
+ # if user is typing, wait for typing to stop
479
+ while True:
480
+
481
+ if chat_with_participant.id not in self._is_typing:
482
+ break
483
+
484
+ await asyncio.sleep(.5)
457
485
 
458
- chat_context.append_user_message(message=text)
459
-
486
+ if messages.empty() == True:
487
+ break
488
+
489
+ if received != None:
460
490
 
461
- # if user is typing, wait for typing to stop
462
- while True:
491
+ with tracer.start_as_current_span("chatbot.thread.message") as span:
463
492
 
464
- if chat_with_participant.id not in self._is_typing:
465
- break
466
-
467
- await asyncio.sleep(.5)
493
+ span.set_attributes(thread_attributes)
494
+ span.set_attribute("role", "user")
495
+ span.set_attribute("from_participant_name", chat_with_participant.get_attribute("name"))
468
496
 
469
- if messages.empty() == True:
470
- break
471
-
497
+ attachments = received.message.get("attachments", [])
498
+ span.set_attribute("attachments", attachments)
499
+
500
+ text = received.message["text"]
501
+ span.set_attributes({
502
+ "text" : text
503
+ })
504
+
505
+ try:
506
+
507
+ if thread_context == None:
508
+
509
+ thread_context = ChatThreadContext(
510
+ chat=chat_context,
511
+ thread=thread,
512
+ participants=get_thread_participants(room=self.room, thread=thread)
513
+ )
472
514
 
473
- try:
515
+ def handle_event(evt):
516
+ llm_messages.send_nowait(evt)
474
517
 
518
+ with tracer.start_as_current_span("chatbot.llm") as span:
475
519
 
476
-
477
- if thread_context == None:
478
-
479
- thread_context = ChatThreadContext(
480
- chat=chat_context,
481
- thread=thread,
482
- participants=get_thread_participants(room=self.room, thread=thread)
483
- )
484
-
485
- def handle_event(evt):
486
- llm_messages.send_nowait(evt)
487
-
488
- try:
489
- response = await self._llm_adapter.next(
490
- context=chat_context,
491
- room=self._room,
492
- toolkits=await self.get_thread_toolkits(thread_context=thread_context, participant=participant),
493
- tool_adapter=self._tool_adapter,
494
- event_handler=handle_event
495
- )
496
- except Exception as e:
497
- logger.error("An error was encountered", exc_info=e)
498
- await self._send_and_save_chat(messages=doc_messages, to=chat_with_participant, path=path, id=str(uuid.uuid4()), text="There was an error while communicating with the LLM. Please try again later.")
499
-
500
-
501
- finally:
502
- for participant in get_thread_participants(room=self._room, thread=thread):
503
- # TODO: async gather
504
- self._room.messaging.send_message_nowait(to=participant, type="thinking", message={"thinking":False, "path" : path})
520
+ try:
521
+
522
+ with tracer.start_as_current_span("get_thread_toolkits") as span:
523
+
524
+ thread_toolkits = await self.get_thread_toolkits(thread_context=thread_context, participant=participant)
525
+
526
+ response = await self._llm_adapter.next(
527
+ context=chat_context,
528
+ room=self._room,
529
+ toolkits=thread_toolkits,
530
+ tool_adapter=self._tool_adapter,
531
+ event_handler=handle_event
532
+ )
533
+ except Exception as e:
534
+ logger.error("An error was encountered", exc_info=e)
535
+ await self._send_and_save_chat(messages=doc_messages, to=chat_with_participant, path=path, id=str(uuid.uuid4()), text="There was an error while communicating with the LLM. Please try again later.", thread_attributes=thread_attributes)
536
+
537
+ finally:
538
+ for participant in get_thread_participants(room=self._room, thread=thread):
539
+ # TODO: async gather
540
+ self._room.messaging.send_message_nowait(to=participant, type="thinking", message={"thinking":False, "path" : path})
505
541
 
506
-
507
542
  finally:
508
-
509
-
543
+
510
544
  llm_messages.close()
511
545
 
512
546
  if self.room != None:
547
+ logger.info("thread was ended {path}")
513
548
  self.room.developer.log_nowait(type="chatbot.thread.ended", data={ "path" : path })
514
549
 
515
550
  if thread != None:
516
551
  await self.close_thread(path=path)
517
-
518
552
 
519
- def _get_message_channel(self, participant_id: str) -> Chan[RoomMessage]:
520
- if participant_id not in self._message_channels:
553
+ def _get_message_channel(self, key: str) -> Chan[RoomMessage]:
554
+ if key not in self._message_channels:
521
555
  chan = Chan[RoomMessage]()
522
- self._message_channels[participant_id] = chan
556
+ self._message_channels[key] = chan
523
557
 
524
- chan = self._message_channels[participant_id]
558
+ chan = self._message_channels[key]
525
559
 
526
560
  return chan
527
561
 
@@ -537,67 +571,60 @@ class ChatBot(SingleRoomAgent):
537
571
 
538
572
  await super().start(room=room)
539
573
 
540
- logger.info("Starting chatbot")
574
+ logger.debug("Starting chatbot")
541
575
 
542
576
  await self.room.local_participant.set_attribute("empty_state_title", self._empty_state_title)
543
577
 
544
578
  def on_message(message: RoomMessage):
545
579
 
546
- logger.info(f"received message {message.type}")
547
580
 
548
- with tracer.start_as_current_span("chatbot.receive") as span:
549
-
550
- span.set_attributes({
551
- "type" : message.type,
552
- "from_participant_id" : message.from_participant_id
553
- })
581
+ if message.type == "chat" or message.type == "opened":
554
582
 
555
- messages = self._get_message_channel(participant_id=message.from_participant_id)
556
- if message.type == "chat" or message.type == "opened":
557
- path = message.message["path"]
558
-
559
- span.set_attributes({
560
- "path" : path
561
- })
583
+ path = message.message["path"]
584
+
585
+ messages = self._get_message_channel(path)
562
586
 
563
- messages.send_nowait(message)
587
+ logger.info(f"queued incoming message for thread {path}: {message.type}")
588
+
589
+ messages.send_nowait(message)
564
590
 
565
- logger.info(f"received message for thread {path}")
591
+ if path not in self._thread_tasks or self._thread_tasks[path].done():
566
592
 
567
- if path not in self._thread_tasks or self._thread_tasks[path].cancelled:
568
-
569
- def thread_done(task: asyncio.Task):
593
+ def thread_done(task: asyncio.Task):
570
594
 
571
- self._message_channels.pop(message.from_participant_id)
572
- try:
573
- task.result()
574
- except Exception as e:
575
- logger.error(f"The chat thread ended with an error {e}", exc_info=e)
576
-
577
-
578
- task = asyncio.create_task(self._spawn_thread(messages=messages, path=path))
579
- task.add_done_callback(thread_done)
580
-
581
- self._thread_tasks[path] = task
582
-
583
- elif message.type == "typing":
584
- def callback(task: asyncio.Task):
595
+ self._message_channels.pop(path)
585
596
  try:
586
597
  task.result()
587
- except:
598
+ except CancelledError as e:
588
599
  pass
600
+ except Exception as e:
601
+ logger.error(f"The chat thread ended with an error {e}", exc_info=e)
602
+
589
603
 
590
- async def remove_timeout(id: str):
591
- await asyncio.sleep(1)
592
- self._is_typing.pop(id)
604
+ logger.info(f"spawning chat thread for {path}")
605
+ task = asyncio.create_task(self._spawn_thread(messages=messages, path=path))
606
+ task.add_done_callback(thread_done)
607
+
608
+ self._thread_tasks[path] = task
609
+
610
+ elif message.type == "typing":
611
+ def callback(task: asyncio.Task):
612
+ try:
613
+ task.result()
614
+ except:
615
+ pass
616
+
617
+ async def remove_timeout(id: str):
618
+ await asyncio.sleep(1)
619
+ self._is_typing.pop(id)
593
620
 
594
- if message.from_participant_id in self._is_typing:
595
- self._is_typing[message.from_participant_id].cancel()
621
+ if message.from_participant_id in self._is_typing:
622
+ self._is_typing[message.from_participant_id].cancel()
596
623
 
597
- timeout = asyncio.create_task(remove_timeout(id=message.from_participant_id))
598
- timeout.add_done_callback(callback)
624
+ timeout = asyncio.create_task(remove_timeout(id=message.from_participant_id))
625
+ timeout.add_done_callback(callback)
599
626
 
600
- self._is_typing[message.from_participant_id] = timeout
627
+ self._is_typing[message.from_participant_id] = timeout
601
628
 
602
629
  room.messaging.on("message", on_message)
603
630
 
@@ -611,6 +638,6 @@ class ChatBot(SingleRoomAgent):
611
638
  room.messaging.on("participant_added", on_participant_added)
612
639
 
613
640
 
614
- logger.info("Enabling chatbot messaging")
641
+ logger.debug("Enabling chatbot messaging")
615
642
  await room.messaging.enable()
616
643
 
@@ -39,7 +39,7 @@ class RemoteTaskRunnerServer[T:TaskRunner](WebhookServer):
39
39
 
40
40
  def on_message(message: RoomMessage):
41
41
  if message.type == "dismiss":
42
- logger.info(f"dismissed by {message.from_participant_id}")
42
+ logger.info(f"dismissed task runner by {message.from_participant_id}")
43
43
  dismissed.set_result(True)
44
44
 
45
45
  room.messaging.on("message", on_message)
@@ -81,7 +81,7 @@ class RemoteAgentServer[T:SingleRoomAgent](WebhookServer):
81
81
 
82
82
  async def _spawn(self, *, room_name: str, room_url: str, token: str, arguments: Optional[dict] = None):
83
83
 
84
- logger.info(f"room: {room_name} url: {room_url} token: {token} arguments: {arguments}")
84
+ logger.info(f"spawning agent on room: {room_name} url: {room_url} arguments: {arguments}")
85
85
  agent = self._create_agent(arguments=arguments)
86
86
 
87
87
  async def run():
@@ -91,7 +91,7 @@ class RemoteAgentServer[T:SingleRoomAgent](WebhookServer):
91
91
 
92
92
  def on_message(message: RoomMessage):
93
93
  if message.type == "dismiss":
94
- logger.info(f"dismissed by {message.from_participant_id}")
94
+ logger.info(f"dismissed agent by {message.from_participant_id}")
95
95
  dismissed.set_result(True)
96
96
 
97
97
  room.messaging.on("message", on_message)
@@ -0,0 +1 @@
1
+ __version__ = "0.0.36"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: meshagent-agents
3
- Version: 0.0.34
3
+ Version: 0.0.36
4
4
  Summary: Agent Building Blocks for Meshagent
5
5
  License-Expression: Apache-2.0
6
6
  Project-URL: Documentation, https://docs.meshagent.com
@@ -9,23 +9,22 @@ Project-URL: Source, https://www.meshagent.com
9
9
  Requires-Python: >=3.12
10
10
  Description-Content-Type: text/markdown
11
11
  License-File: LICENSE
12
- Requires-Dist: pyjwt~=2.10.1
13
- Requires-Dist: pytest~=8.3.5
14
- Requires-Dist: pytest-asyncio~=0.26.0
15
- Requires-Dist: meshagent-api~=0.0.34
16
- Requires-Dist: meshagent-tools~=0.0.34
17
- Requires-Dist: meshagent-openai~=0.0.34
18
- Requires-Dist: pydantic~=2.11.1
19
- Requires-Dist: pydantic-ai~=0.0.48
12
+ Requires-Dist: pyjwt~=2.10
13
+ Requires-Dist: pytest~=8.3
14
+ Requires-Dist: pytest-asyncio~=0.26
15
+ Requires-Dist: meshagent-api~=0.0.36
16
+ Requires-Dist: meshagent-tools~=0.0.36
17
+ Requires-Dist: meshagent-openai~=0.0.36
18
+ Requires-Dist: pydantic~=2.11
20
19
  Requires-Dist: opentelemetry-distro~=0.54b1
21
20
  Provides-Extra: all
22
- Requires-Dist: meshagent-api[all]~=0.0.34; extra == "all"
21
+ Requires-Dist: meshagent-api[all]~=0.0.36; extra == "all"
23
22
  Requires-Dist: chonkie~=0.5.1; extra == "all"
24
23
  Requires-Dist: chonkie[semantic]~=0.5.1; extra == "all"
25
24
  Requires-Dist: chonkie[openai]~=0.5.1; extra == "all"
26
25
  Requires-Dist: aiosmtplib~=4.0.1; extra == "all"
27
26
  Provides-Extra: sync
28
- Requires-Dist: meshagent-api[sync]~=0.0.34; extra == "sync"
27
+ Requires-Dist: meshagent-api[sync]~=0.0.36; extra == "sync"
29
28
  Provides-Extra: mail
30
29
  Requires-Dist: aiosmtplib~=4.0.1; extra == "mail"
31
30
  Provides-Extra: rag
@@ -1,15 +1,14 @@
1
- pyjwt~=2.10.1
2
- pytest~=8.3.5
3
- pytest-asyncio~=0.26.0
4
- meshagent-api~=0.0.34
5
- meshagent-tools~=0.0.34
6
- meshagent-openai~=0.0.34
7
- pydantic~=2.11.1
8
- pydantic-ai~=0.0.48
1
+ pyjwt~=2.10
2
+ pytest~=8.3
3
+ pytest-asyncio~=0.26
4
+ meshagent-api~=0.0.36
5
+ meshagent-tools~=0.0.36
6
+ meshagent-openai~=0.0.36
7
+ pydantic~=2.11
9
8
  opentelemetry-distro~=0.54b1
10
9
 
11
10
  [all]
12
- meshagent-api[all]~=0.0.34
11
+ meshagent-api[all]~=0.0.36
13
12
  chonkie~=0.5.1
14
13
  chonkie[semantic]~=0.5.1
15
14
  chonkie[openai]~=0.5.1
@@ -24,4 +23,4 @@ chonkie[semantic]~=0.5.1
24
23
  chonkie[openai]~=0.5.1
25
24
 
26
25
  [sync]
27
- meshagent-api[sync]~=0.0.34
26
+ meshagent-api[sync]~=0.0.36
@@ -14,20 +14,19 @@ license = "Apache-2.0"
14
14
  classifiers = []
15
15
  keywords = []
16
16
  dependencies = [
17
- "pyjwt~=2.10.1",
18
- "pytest~=8.3.5",
19
- "pytest-asyncio~=0.26.0",
20
- "meshagent-api~=0.0.34",
21
- "meshagent-tools~=0.0.34",
22
- "meshagent-openai~=0.0.34",
23
- "pydantic~=2.11.1",
24
- "pydantic-ai~=0.0.48",
17
+ "pyjwt~=2.10",
18
+ "pytest~=8.3",
19
+ "pytest-asyncio~=0.26",
20
+ "meshagent-api~=0.0.36",
21
+ "meshagent-tools~=0.0.36",
22
+ "meshagent-openai~=0.0.36",
23
+ "pydantic~=2.11",
25
24
  "opentelemetry-distro~=0.54b1"
26
25
  ]
27
26
 
28
27
  [project.optional-dependencies]
29
28
  all = [
30
- "meshagent-api[all]~=0.0.34",
29
+ "meshagent-api[all]~=0.0.36",
31
30
  "chonkie~=0.5.1",
32
31
  "chonkie[semantic]~=0.5.1",
33
32
  "chonkie[openai]~=0.5.1",
@@ -35,7 +34,7 @@ all = [
35
34
  ]
36
35
 
37
36
  sync = [
38
- "meshagent-api[sync]~=0.0.34",
37
+ "meshagent-api[sync]~=0.0.36",
39
38
  ]
40
39
 
41
40
  mail = [
@@ -1 +0,0 @@
1
- __version__ = "0.0.34"