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.
- {meshagent_agents-0.0.34 → meshagent_agents-0.0.36}/CHANGELOG.md +6 -0
- {meshagent_agents-0.0.34/meshagent_agents.egg-info → meshagent_agents-0.0.36}/PKG-INFO +10 -11
- {meshagent_agents-0.0.34 → meshagent_agents-0.0.36}/meshagent/agents/agent.py +1 -2
- {meshagent_agents-0.0.34 → meshagent_agents-0.0.36}/meshagent/agents/chat.py +202 -175
- {meshagent_agents-0.0.34 → meshagent_agents-0.0.36}/meshagent/agents/hosting.py +3 -3
- meshagent_agents-0.0.36/meshagent/agents/version.py +1 -0
- {meshagent_agents-0.0.34 → meshagent_agents-0.0.36/meshagent_agents.egg-info}/PKG-INFO +10 -11
- {meshagent_agents-0.0.34 → meshagent_agents-0.0.36}/meshagent_agents.egg-info/requires.txt +9 -10
- {meshagent_agents-0.0.34 → meshagent_agents-0.0.36}/pyproject.toml +9 -10
- meshagent_agents-0.0.34/meshagent/agents/version.py +0 -1
- {meshagent_agents-0.0.34 → meshagent_agents-0.0.36}/LICENSE +0 -0
- {meshagent_agents-0.0.34 → meshagent_agents-0.0.36}/MANIFEST.in +0 -0
- {meshagent_agents-0.0.34 → meshagent_agents-0.0.36}/README.md +0 -0
- {meshagent_agents-0.0.34 → meshagent_agents-0.0.36}/meshagent/agents/__init__.py +0 -0
- {meshagent_agents-0.0.34 → meshagent_agents-0.0.36}/meshagent/agents/adapter.py +0 -0
- {meshagent_agents-0.0.34 → meshagent_agents-0.0.36}/meshagent/agents/context.py +0 -0
- {meshagent_agents-0.0.34 → meshagent_agents-0.0.36}/meshagent/agents/development.py +0 -0
- {meshagent_agents-0.0.34 → meshagent_agents-0.0.36}/meshagent/agents/indexer.py +0 -0
- {meshagent_agents-0.0.34 → meshagent_agents-0.0.36}/meshagent/agents/listener.py +0 -0
- {meshagent_agents-0.0.34 → meshagent_agents-0.0.36}/meshagent/agents/mail.py +0 -0
- {meshagent_agents-0.0.34 → meshagent_agents-0.0.36}/meshagent/agents/planning.py +0 -0
- {meshagent_agents-0.0.34 → meshagent_agents-0.0.36}/meshagent/agents/prompt.py +0 -0
- {meshagent_agents-0.0.34 → meshagent_agents-0.0.36}/meshagent/agents/pydantic.py +0 -0
- {meshagent_agents-0.0.34 → meshagent_agents-0.0.36}/meshagent/agents/schemas/__init__.py +0 -0
- {meshagent_agents-0.0.34 → meshagent_agents-0.0.36}/meshagent/agents/schemas/document.py +0 -0
- {meshagent_agents-0.0.34 → meshagent_agents-0.0.36}/meshagent/agents/schemas/gallery.py +0 -0
- {meshagent_agents-0.0.34 → meshagent_agents-0.0.36}/meshagent/agents/schemas/presentation.py +0 -0
- {meshagent_agents-0.0.34 → meshagent_agents-0.0.36}/meshagent/agents/schemas/schema.py +0 -0
- {meshagent_agents-0.0.34 → meshagent_agents-0.0.36}/meshagent/agents/schemas/super_editor_document.py +0 -0
- {meshagent_agents-0.0.34 → meshagent_agents-0.0.36}/meshagent/agents/single_shot_writer.py +0 -0
- {meshagent_agents-0.0.34 → meshagent_agents-0.0.36}/meshagent/agents/thread_schema.py +0 -0
- {meshagent_agents-0.0.34 → meshagent_agents-0.0.36}/meshagent/agents/utils.py +0 -0
- {meshagent_agents-0.0.34 → meshagent_agents-0.0.36}/meshagent/agents/worker.py +0 -0
- {meshagent_agents-0.0.34 → meshagent_agents-0.0.36}/meshagent/agents/writer.py +0 -0
- {meshagent_agents-0.0.34 → meshagent_agents-0.0.36}/meshagent_agents.egg-info/SOURCES.txt +0 -0
- {meshagent_agents-0.0.34 → meshagent_agents-0.0.36}/meshagent_agents.egg-info/dependency_links.txt +0 -0
- {meshagent_agents-0.0.34 → meshagent_agents-0.0.36}/meshagent_agents.egg-info/top_level.txt +0 -0
- {meshagent_agents-0.0.34 → meshagent_agents-0.0.36}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: meshagent-agents
|
|
3
|
-
Version: 0.0.
|
|
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
|
|
13
|
-
Requires-Dist: pytest~=8.3
|
|
14
|
-
Requires-Dist: pytest-asyncio~=0.26
|
|
15
|
-
Requires-Dist: meshagent-api~=0.0.
|
|
16
|
-
Requires-Dist: meshagent-tools~=0.0.
|
|
17
|
-
Requires-Dist: meshagent-openai~=0.0.
|
|
18
|
-
Requires-Dist: pydantic~=2.11
|
|
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.
|
|
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.
|
|
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
|
|
@@ -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.
|
|
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
|
-
|
|
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.
|
|
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
|
-
|
|
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
|
-
|
|
366
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
418
|
+
thread = await self.open_thread(path=path)
|
|
419
|
+
|
|
420
|
+
for prop in thread.root.get_children():
|
|
396
421
|
|
|
397
|
-
|
|
422
|
+
if prop.tag_name == "messages":
|
|
423
|
+
|
|
424
|
+
doc_messages = prop
|
|
398
425
|
|
|
399
|
-
|
|
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
|
-
|
|
452
|
+
if received.type == "chat":
|
|
422
453
|
|
|
423
|
-
|
|
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
|
-
|
|
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
|
-
|
|
441
|
-
|
|
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
|
-
|
|
445
|
-
|
|
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
|
-
|
|
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
|
-
|
|
473
|
+
chat_context.append_assistant_message(message=f"the user attached a file at the path '{attachment["path"]}'")
|
|
452
474
|
|
|
453
|
-
|
|
475
|
+
chat_context.append_user_message(message=text)
|
|
476
|
+
|
|
454
477
|
|
|
455
|
-
|
|
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
|
-
|
|
459
|
-
|
|
486
|
+
if messages.empty() == True:
|
|
487
|
+
break
|
|
488
|
+
|
|
489
|
+
if received != None:
|
|
460
490
|
|
|
461
|
-
|
|
462
|
-
while True:
|
|
491
|
+
with tracer.start_as_current_span("chatbot.thread.message") as span:
|
|
463
492
|
|
|
464
|
-
|
|
465
|
-
|
|
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
|
-
|
|
470
|
-
|
|
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
|
-
|
|
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
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
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,
|
|
520
|
-
if
|
|
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[
|
|
556
|
+
self._message_channels[key] = chan
|
|
523
557
|
|
|
524
|
-
chan = self._message_channels[
|
|
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.
|
|
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
|
-
|
|
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
|
-
|
|
556
|
-
|
|
557
|
-
|
|
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
|
-
|
|
587
|
+
logger.info(f"queued incoming message for thread {path}: {message.type}")
|
|
588
|
+
|
|
589
|
+
messages.send_nowait(message)
|
|
564
590
|
|
|
565
|
-
|
|
591
|
+
if path not in self._thread_tasks or self._thread_tasks[path].done():
|
|
566
592
|
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
def thread_done(task: asyncio.Task):
|
|
593
|
+
def thread_done(task: asyncio.Task):
|
|
570
594
|
|
|
571
|
-
|
|
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
|
-
|
|
591
|
-
|
|
592
|
-
|
|
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
|
-
|
|
595
|
-
|
|
621
|
+
if message.from_participant_id in self._is_typing:
|
|
622
|
+
self._is_typing[message.from_participant_id].cancel()
|
|
596
623
|
|
|
597
|
-
|
|
598
|
-
|
|
624
|
+
timeout = asyncio.create_task(remove_timeout(id=message.from_participant_id))
|
|
625
|
+
timeout.add_done_callback(callback)
|
|
599
626
|
|
|
600
|
-
|
|
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.
|
|
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}
|
|
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.
|
|
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
|
|
13
|
-
Requires-Dist: pytest~=8.3
|
|
14
|
-
Requires-Dist: pytest-asyncio~=0.26
|
|
15
|
-
Requires-Dist: meshagent-api~=0.0.
|
|
16
|
-
Requires-Dist: meshagent-tools~=0.0.
|
|
17
|
-
Requires-Dist: meshagent-openai~=0.0.
|
|
18
|
-
Requires-Dist: pydantic~=2.11
|
|
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.
|
|
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.
|
|
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
|
|
2
|
-
pytest~=8.3
|
|
3
|
-
pytest-asyncio~=0.26
|
|
4
|
-
meshagent-api~=0.0.
|
|
5
|
-
meshagent-tools~=0.0.
|
|
6
|
-
meshagent-openai~=0.0.
|
|
7
|
-
pydantic~=2.11
|
|
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.
|
|
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.
|
|
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
|
|
18
|
-
"pytest~=8.3
|
|
19
|
-
"pytest-asyncio~=0.26
|
|
20
|
-
"meshagent-api~=0.0.
|
|
21
|
-
"meshagent-tools~=0.0.
|
|
22
|
-
"meshagent-openai~=0.0.
|
|
23
|
-
"pydantic~=2.11
|
|
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.
|
|
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.
|
|
37
|
+
"meshagent-api[sync]~=0.0.36",
|
|
39
38
|
]
|
|
40
39
|
|
|
41
40
|
mail = [
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = "0.0.34"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{meshagent_agents-0.0.34 → meshagent_agents-0.0.36}/meshagent/agents/schemas/presentation.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{meshagent_agents-0.0.34 → meshagent_agents-0.0.36}/meshagent_agents.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|