meshagent-agents 0.0.30__py3-none-any.whl → 0.0.31__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/agent.py +21 -13
- meshagent/agents/chat.py +268 -116
- meshagent/agents/hosting.py +2 -1
- meshagent/agents/version.py +1 -1
- {meshagent_agents-0.0.30.dist-info → meshagent_agents-0.0.31.dist-info}/METADATA +7 -6
- {meshagent_agents-0.0.30.dist-info → meshagent_agents-0.0.31.dist-info}/RECORD +9 -9
- {meshagent_agents-0.0.30.dist-info → meshagent_agents-0.0.31.dist-info}/WHEEL +0 -0
- {meshagent_agents-0.0.30.dist-info → meshagent_agents-0.0.31.dist-info}/licenses/LICENSE +0 -0
- {meshagent_agents-0.0.30.dist-info → meshagent_agents-0.0.31.dist-info}/top_level.txt +0 -0
meshagent/agents/agent.py
CHANGED
|
@@ -3,6 +3,7 @@ from copy import deepcopy
|
|
|
3
3
|
|
|
4
4
|
from typing import Optional
|
|
5
5
|
|
|
6
|
+
from meshagent.api.messaging import unpack_message, pack_message
|
|
6
7
|
from meshagent.api.room_server_client import RoomException, RequiredToolkit, Requirement, RequiredSchema
|
|
7
8
|
from meshagent.api import WebSocketClientProtocol, ToolDescription, ToolkitDescription, Participant, RemoteParticipant, meshagent_base_url, StorageEntry, JsonResponse
|
|
8
9
|
from meshagent.api.protocol import Protocol
|
|
@@ -169,17 +170,24 @@ class SingleRoomAgent(Agent):
|
|
|
169
170
|
elif isinstance(requirement, RequiredSchema):
|
|
170
171
|
|
|
171
172
|
if requirement.name not in schemas_by_name:
|
|
172
|
-
|
|
173
|
+
|
|
173
174
|
installed = True
|
|
174
175
|
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
if requirement.name.startswith("https://"):
|
|
178
|
-
url = requirement.name
|
|
179
|
-
else:
|
|
180
|
-
url = f"{meshagent_base_url()}/schemas/{requirement.name}"
|
|
176
|
+
schema_path = f".schemas/{requirement.name}.json"
|
|
181
177
|
|
|
182
|
-
|
|
178
|
+
|
|
179
|
+
if await self._room.storage.exists(path=schema_path):
|
|
180
|
+
# Schema is already in the room
|
|
181
|
+
pass
|
|
182
|
+
else:
|
|
183
|
+
logger.info(f"Installing required tool {requirement.name}")
|
|
184
|
+
|
|
185
|
+
if requirement.name.startswith("https://"):
|
|
186
|
+
url = requirement.name
|
|
187
|
+
else:
|
|
188
|
+
url = f"{meshagent_base_url()}/schemas/{requirement.name}"
|
|
189
|
+
|
|
190
|
+
await self._room.agents.make_call(url=url, name=requirement.name, arguments={})
|
|
183
191
|
|
|
184
192
|
else:
|
|
185
193
|
raise RoomException("unsupported requirement")
|
|
@@ -376,7 +384,7 @@ class TaskRunner(SingleRoomAgent):
|
|
|
376
384
|
|
|
377
385
|
async def worker():
|
|
378
386
|
# Decode and parse the message
|
|
379
|
-
message =
|
|
387
|
+
message, _ = unpack_message(data)
|
|
380
388
|
logger.info("agent got message %s", message)
|
|
381
389
|
args = message["arguments"]
|
|
382
390
|
task_id = message["task_id"]
|
|
@@ -456,7 +464,7 @@ class TaskRunner(SingleRoomAgent):
|
|
|
456
464
|
|
|
457
465
|
response = await self.ask(context=context, arguments=args)
|
|
458
466
|
|
|
459
|
-
await protocol.send(type="agent.ask_response", data=
|
|
467
|
+
await protocol.send(type="agent.ask_response", data=pack_message({
|
|
460
468
|
"task_id" : task_id,
|
|
461
469
|
"answer" : response,
|
|
462
470
|
"caller_context" : {
|
|
@@ -468,7 +476,7 @@ class TaskRunner(SingleRoomAgent):
|
|
|
468
476
|
logger.error("Task runner failed to complete task", exc_info=e)
|
|
469
477
|
if chat_context != None:
|
|
470
478
|
|
|
471
|
-
await protocol.send(type="agent.ask_response", data=
|
|
479
|
+
await protocol.send(type="agent.ask_response", data=pack_message({
|
|
472
480
|
"task_id" : task_id,
|
|
473
481
|
"error" : str(e),
|
|
474
482
|
"caller_context" : {
|
|
@@ -476,7 +484,7 @@ class TaskRunner(SingleRoomAgent):
|
|
|
476
484
|
}
|
|
477
485
|
}))
|
|
478
486
|
else:
|
|
479
|
-
await protocol.send(type="agent.ask_response", data=
|
|
487
|
+
await protocol.send(type="agent.ask_response", data=pack_message({
|
|
480
488
|
"task_id" : task_id,
|
|
481
489
|
"error" : str(e),
|
|
482
490
|
}))
|
|
@@ -522,4 +530,4 @@ async def make_run_task_tool(context: ToolContext, toolkit: RequiredToolkit):
|
|
|
522
530
|
tools=tools
|
|
523
531
|
)
|
|
524
532
|
|
|
525
|
-
register_toolkit_factory("agents", make_run_task_tool)
|
|
533
|
+
register_toolkit_factory("agents", make_run_task_tool)
|
meshagent/agents/chat.py
CHANGED
|
@@ -3,6 +3,7 @@ from meshagent.api.chan import Chan
|
|
|
3
3
|
from meshagent.api import RoomMessage, RoomException, RoomClient, RemoteParticipant, RequiredSchema, Requirement, Element, MeshDocument
|
|
4
4
|
from meshagent.tools import Toolkit, ToolContext
|
|
5
5
|
from .adapter import LLMAdapter, ToolResponseAdapter
|
|
6
|
+
from meshagent.openai.tools.responses_adapter import ImageGenerationTool
|
|
6
7
|
import asyncio
|
|
7
8
|
from typing import Optional
|
|
8
9
|
import logging
|
|
@@ -11,12 +12,128 @@ import urllib
|
|
|
11
12
|
import uuid
|
|
12
13
|
import datetime
|
|
13
14
|
import json
|
|
15
|
+
from typing import Literal, Optional
|
|
16
|
+
import base64
|
|
14
17
|
from openai.types.responses import ResponseStreamEvent
|
|
15
18
|
|
|
19
|
+
from opentelemetry import trace
|
|
20
|
+
|
|
21
|
+
tracer = trace.get_tracer("meshagent.chatbot")
|
|
22
|
+
|
|
16
23
|
logger = logging.getLogger("chat")
|
|
17
24
|
|
|
18
25
|
|
|
19
|
-
|
|
26
|
+
|
|
27
|
+
class ChatBotThreadOpenAIImageGenerationTool(ImageGenerationTool):
|
|
28
|
+
def __init__(self,
|
|
29
|
+
*,
|
|
30
|
+
background: Literal["transparent","opaque","auto"] = None,
|
|
31
|
+
input_image_mask_url: Optional[str] = None,
|
|
32
|
+
model: Optional[str] = None,
|
|
33
|
+
moderation: Optional[str] = None,
|
|
34
|
+
output_compression: Optional[int] = None,
|
|
35
|
+
output_format: Optional[Literal["png","webp","jpeg"]] = None,
|
|
36
|
+
partial_images: Optional[int] = None,
|
|
37
|
+
quality: Optional[Literal["auto", "low", "medium", "high"]] = None,
|
|
38
|
+
size: Optional[Literal["1024x1024","1024x1536","1536x1024","auto"]] = None,
|
|
39
|
+
thread_context: 'ChatThreadContext'
|
|
40
|
+
):
|
|
41
|
+
super().__init__(
|
|
42
|
+
background=background,
|
|
43
|
+
input_image_mask_url=input_image_mask_url,
|
|
44
|
+
model=model,
|
|
45
|
+
moderation=moderation,
|
|
46
|
+
output_compression=output_compression,
|
|
47
|
+
output_format=output_format,
|
|
48
|
+
partial_images=partial_images,
|
|
49
|
+
quality=quality,
|
|
50
|
+
size=size
|
|
51
|
+
)
|
|
52
|
+
|
|
53
|
+
self.thread_context = thread_context
|
|
54
|
+
|
|
55
|
+
async def on_image_generation_partial(self, context, *, item_id, output_index, sequence_number, type, partial_image_b64, partial_image_index, size, quality, background, output_format, **extra):
|
|
56
|
+
|
|
57
|
+
output_format = self.output_format
|
|
58
|
+
if output_format == None:
|
|
59
|
+
output_format = "png"
|
|
60
|
+
|
|
61
|
+
image_name = f"{str(uuid.uuid4())}.{output_format}"
|
|
62
|
+
|
|
63
|
+
handle = await context.room.storage.open(path=image_name)
|
|
64
|
+
await context.room.storage.write(handle=handle, data=base64.b64decode(partial_image_b64))
|
|
65
|
+
await context.room.storage.close(handle=handle)
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
messages = None
|
|
69
|
+
|
|
70
|
+
for prop in self.thread_context.thread.root.get_children():
|
|
71
|
+
|
|
72
|
+
if prop.tag_name == "messages":
|
|
73
|
+
|
|
74
|
+
messages = prop
|
|
75
|
+
|
|
76
|
+
for child in messages.get_children():
|
|
77
|
+
|
|
78
|
+
if child.get_attribute("id") == item_id:
|
|
79
|
+
|
|
80
|
+
for file in child.get_children():
|
|
81
|
+
file.set_attribute("path", image_name)
|
|
82
|
+
|
|
83
|
+
return
|
|
84
|
+
|
|
85
|
+
message_element = messages.append_child(
|
|
86
|
+
tag_name="message",
|
|
87
|
+
attributes={
|
|
88
|
+
"id" : item_id,
|
|
89
|
+
"text" : "",
|
|
90
|
+
"created_at" : datetime.datetime.now(datetime.timezone.utc).isoformat().replace("+00:00","Z"),
|
|
91
|
+
"author_name" : context.room.local_participant.get_attribute("name"),
|
|
92
|
+
}
|
|
93
|
+
)
|
|
94
|
+
message_element.append_child(tag_name="file", attributes={ "path" : image_name })
|
|
95
|
+
|
|
96
|
+
async def on_image_generated(self, context: ToolContext, *, item_id: str, data: bytes, status: str, size: str, quality: str, background: str, output_format: str, **extra):
|
|
97
|
+
|
|
98
|
+
output_format = self.output_format
|
|
99
|
+
if output_format == None:
|
|
100
|
+
output_format = "png"
|
|
101
|
+
|
|
102
|
+
image_name = f"{str(uuid.uuid4())}.{output_format}"
|
|
103
|
+
|
|
104
|
+
handle = await context.room.storage.open(path=image_name)
|
|
105
|
+
await context.room.storage.write(handle=handle, data=data)
|
|
106
|
+
await context.room.storage.close(handle=handle)
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
messages = None
|
|
110
|
+
|
|
111
|
+
for prop in self.thread_context.thread.root.get_children():
|
|
112
|
+
|
|
113
|
+
if prop.tag_name == "messages":
|
|
114
|
+
|
|
115
|
+
messages = prop
|
|
116
|
+
|
|
117
|
+
for child in messages.get_children():
|
|
118
|
+
|
|
119
|
+
if child.get_attribute("id") == item_id:
|
|
120
|
+
|
|
121
|
+
for file in child.get_children():
|
|
122
|
+
file.set_attribute("path", image_name)
|
|
123
|
+
|
|
124
|
+
return
|
|
125
|
+
|
|
126
|
+
message_element = messages.append_child(
|
|
127
|
+
tag_name="message",
|
|
128
|
+
attributes={
|
|
129
|
+
"id" : item_id,
|
|
130
|
+
"text" : "",
|
|
131
|
+
"created_at" : datetime.datetime.now(datetime.timezone.utc).isoformat().replace("+00:00","Z"),
|
|
132
|
+
"author_name" : context.room.local_participant.get_attribute("name"),
|
|
133
|
+
}
|
|
134
|
+
)
|
|
135
|
+
message_element.append_child(tag_name="file", attributes={ "path" : image_name })
|
|
136
|
+
|
|
20
137
|
|
|
21
138
|
def get_thread_participants(*, room: RoomClient, thread: MeshDocument) -> list[RemoteParticipant]:
|
|
22
139
|
|
|
@@ -46,6 +163,7 @@ class ChatThreadContext:
|
|
|
46
163
|
self.participants = participants
|
|
47
164
|
self.chat = chat
|
|
48
165
|
|
|
166
|
+
# todo: thread should stop when participant stops?
|
|
49
167
|
class ChatBot(SingleRoomAgent):
|
|
50
168
|
def __init__(self, *, name, title = None, description = None, requires : Optional[list[Requirement]] = None, llm_adapter: LLMAdapter, tool_adapter: Optional[ToolResponseAdapter] = None, toolkits: Optional[list[Toolkit]] = None, rules : Optional[list[str]] = None, auto_greet_message : Optional[str] = None, empty_state_title : Optional[str] = None, labels: Optional[str] = None):
|
|
51
169
|
|
|
@@ -102,14 +220,22 @@ class ChatBot(SingleRoomAgent):
|
|
|
102
220
|
|
|
103
221
|
async def _send_and_save_chat(self, messages: Element, path: str, to: RemoteParticipant, id: str, text: str):
|
|
104
222
|
|
|
105
|
-
|
|
223
|
+
with tracer.start_as_current_span("chatbot.say") as span:
|
|
106
224
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
225
|
+
span.set_attributes({
|
|
226
|
+
"id" : id,
|
|
227
|
+
"path" : path,
|
|
228
|
+
"text" : text
|
|
229
|
+
})
|
|
230
|
+
|
|
231
|
+
await self.room.messaging.send_message(to=to, type="chat", message={ "path" : path, "text" : text })
|
|
232
|
+
|
|
233
|
+
messages.append_child(tag_name="message", attributes={
|
|
234
|
+
"id" : id,
|
|
235
|
+
"text" : text,
|
|
236
|
+
"created_at" : datetime.datetime.now(datetime.timezone.utc).isoformat().replace("+00:00","Z"),
|
|
237
|
+
"author_name" : self.room.local_participant.get_attribute("name"),
|
|
238
|
+
})
|
|
113
239
|
|
|
114
240
|
|
|
115
241
|
async def greet(self, *, messages: Element, path: str, chat_context: AgentChatContext, participant: RemoteParticipant):
|
|
@@ -219,113 +345,128 @@ class ChatBot(SingleRoomAgent):
|
|
|
219
345
|
|
|
220
346
|
elif evt.type == "response.output_text.done":
|
|
221
347
|
content_element = None
|
|
348
|
+
|
|
222
349
|
|
|
223
350
|
llm_task = asyncio.create_task(process_llm_events())
|
|
224
351
|
llm_task.add_done_callback(done_processing_llm_events)
|
|
225
352
|
|
|
226
353
|
try:
|
|
354
|
+
|
|
227
355
|
while True:
|
|
228
|
-
|
|
356
|
+
|
|
229
357
|
while True:
|
|
230
358
|
|
|
231
359
|
received = await messages.recv()
|
|
232
360
|
|
|
233
|
-
|
|
234
|
-
for participant in self._room.messaging.get_participants():
|
|
235
|
-
if participant.id == received.from_participant_id:
|
|
236
|
-
chat_with_participant = participant
|
|
237
|
-
break
|
|
238
|
-
|
|
239
|
-
if chat_with_participant == None:
|
|
240
|
-
logger.warning("participant does not have messaging enabled, skipping message")
|
|
241
|
-
continue
|
|
242
|
-
|
|
243
|
-
if current_file != chat_with_participant.get_attribute("current_file"):
|
|
244
|
-
logger.info(f"participant is now looking at {chat_with_participant.get_attribute("current_file")}")
|
|
245
|
-
current_file = chat_with_participant.get_attribute("current_file")
|
|
246
|
-
|
|
247
|
-
if current_file != None:
|
|
248
|
-
chat_context.append_assistant_message(message=f"the user is currently viewing the file at the path: {current_file}")
|
|
361
|
+
with tracer.start_as_current_span("chatbot.thread.receive") as span:
|
|
249
362
|
|
|
250
|
-
|
|
251
|
-
|
|
363
|
+
span.set_attributes({
|
|
364
|
+
"from_participant_id" : received.from_participant_id,
|
|
365
|
+
"type" : received.type,
|
|
366
|
+
"has_attachment" : received.attachment != None,
|
|
367
|
+
})
|
|
252
368
|
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
369
|
+
chat_with_participant = None
|
|
370
|
+
for participant in self._room.messaging.get_participants():
|
|
371
|
+
if participant.id == received.from_participant_id:
|
|
372
|
+
chat_with_participant = participant
|
|
373
|
+
break
|
|
374
|
+
|
|
375
|
+
if chat_with_participant == None:
|
|
376
|
+
logger.warning("participant does not have messaging enabled, skipping message")
|
|
377
|
+
continue
|
|
378
|
+
|
|
379
|
+
if current_file != chat_with_participant.get_attribute("current_file"):
|
|
380
|
+
logger.info(f"participant is now looking at {chat_with_participant.get_attribute("current_file")}")
|
|
381
|
+
current_file = chat_with_participant.get_attribute("current_file")
|
|
258
382
|
|
|
259
|
-
|
|
383
|
+
if current_file != None:
|
|
384
|
+
chat_context.append_assistant_message(message=f"the user is currently viewing the file at the path: {current_file}")
|
|
260
385
|
|
|
261
|
-
|
|
386
|
+
elif current_file != None:
|
|
387
|
+
chat_context.append_assistant_message(message=f"the user is not current viewing any files")
|
|
388
|
+
|
|
389
|
+
|
|
390
|
+
if thread == None:
|
|
391
|
+
with tracer.start_as_current_span("chatbot.open_thread") as span:
|
|
392
|
+
|
|
393
|
+
thread = await self.open_thread(path=path)
|
|
262
394
|
|
|
263
|
-
for
|
|
395
|
+
for prop in thread.root.get_children():
|
|
396
|
+
|
|
397
|
+
if prop.tag_name == "messages":
|
|
264
398
|
|
|
265
|
-
|
|
399
|
+
doc_messages = prop
|
|
266
400
|
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
401
|
+
for element in doc_messages.get_children():
|
|
402
|
+
|
|
403
|
+
if isinstance(element, Element):
|
|
404
|
+
|
|
405
|
+
msg = element["text"]
|
|
406
|
+
if element["author_name"] == self.room.local_participant.get_attribute("name"):
|
|
407
|
+
chat_context.append_assistant_message(msg)
|
|
408
|
+
else:
|
|
409
|
+
chat_context.append_user_message(msg)
|
|
410
|
+
|
|
411
|
+
for child in element.get_children():
|
|
412
|
+
if child.tag_name == "file":
|
|
413
|
+
chat_context.append_assistant_message(f"the user attached a file with the path '{child.get_attribute("path")}'")
|
|
414
|
+
|
|
415
|
+
if doc_messages == None:
|
|
416
|
+
raise Exception("thread was not properly initialized")
|
|
279
417
|
|
|
280
418
|
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
if opened == False:
|
|
284
|
-
|
|
285
|
-
opened = True
|
|
419
|
+
if received.type == "opened":
|
|
286
420
|
|
|
287
|
-
|
|
421
|
+
if opened == False:
|
|
422
|
+
|
|
423
|
+
opened = True
|
|
424
|
+
|
|
425
|
+
await self.greet(path=path, chat_context=chat_context, participant=chat_with_participant, messages=doc_messages)
|
|
288
426
|
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
if thread == None:
|
|
427
|
+
if received.type == "chat":
|
|
292
428
|
|
|
293
|
-
|
|
429
|
+
with tracer.start_as_current_span("chatbot.handle_chat") as span:
|
|
430
|
+
|
|
431
|
+
text = received.message["text"]
|
|
432
|
+
span.set_attributes({
|
|
433
|
+
"text" : text
|
|
434
|
+
})
|
|
435
|
+
|
|
436
|
+
if thread == None:
|
|
294
437
|
|
|
295
|
-
|
|
438
|
+
self.room.developer.log_nowait(type="thread is not open", data={})
|
|
439
|
+
break
|
|
296
440
|
|
|
297
441
|
|
|
298
|
-
|
|
299
|
-
|
|
442
|
+
for participant in get_thread_participants(room=self._room, thread=thread):
|
|
443
|
+
# TODO: async gather
|
|
444
|
+
self._room.messaging.send_message_nowait(to=participant, type="thinking", message={"thinking":True, "path": path})
|
|
300
445
|
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
self._room.messaging.send_message_nowait(to=participant, type="thinking", message={"thinking":True, "path": path})
|
|
446
|
+
if chat_with_participant.id == received.from_participant_id:
|
|
447
|
+
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"] } } })
|
|
304
448
|
|
|
305
|
-
|
|
306
|
-
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"] } } })
|
|
449
|
+
attachments = received.message.get("attachments", [])
|
|
307
450
|
|
|
308
|
-
|
|
451
|
+
for attachment in attachments:
|
|
309
452
|
|
|
310
|
-
|
|
453
|
+
chat_context.append_assistant_message(message=f"the user attached a file at the path '{attachment["path"]}'")
|
|
454
|
+
|
|
311
455
|
|
|
312
|
-
|
|
313
|
-
|
|
456
|
+
chat_context.append_user_message(message=text)
|
|
457
|
+
|
|
314
458
|
|
|
315
|
-
|
|
459
|
+
# if user is typing, wait for typing to stop
|
|
460
|
+
while True:
|
|
461
|
+
|
|
462
|
+
if chat_with_participant.id not in self._is_typing:
|
|
463
|
+
break
|
|
316
464
|
|
|
465
|
+
await asyncio.sleep(.5)
|
|
317
466
|
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
if chat_with_participant.id not in self._is_typing:
|
|
322
|
-
break
|
|
323
|
-
|
|
324
|
-
await asyncio.sleep(.5)
|
|
325
|
-
|
|
326
|
-
if messages.empty() == True:
|
|
327
|
-
break
|
|
328
|
-
|
|
467
|
+
if messages.empty() == True:
|
|
468
|
+
break
|
|
469
|
+
|
|
329
470
|
|
|
330
471
|
try:
|
|
331
472
|
|
|
@@ -401,49 +542,60 @@ class ChatBot(SingleRoomAgent):
|
|
|
401
542
|
def on_message(message: RoomMessage):
|
|
402
543
|
|
|
403
544
|
logger.info(f"received message {message.type}")
|
|
404
|
-
|
|
545
|
+
|
|
546
|
+
with tracer.start_as_current_span("chatbot.receive") as span:
|
|
547
|
+
|
|
548
|
+
span.set_attributes({
|
|
549
|
+
"type" : message.type,
|
|
550
|
+
"from_participant_id" : message.from_participant_id
|
|
551
|
+
})
|
|
405
552
|
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
553
|
+
messages = self._get_message_channel(participant_id=message.from_participant_id)
|
|
554
|
+
if message.type == "chat" or message.type == "opened":
|
|
555
|
+
path = message.message["path"]
|
|
409
556
|
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
if path not in self._thread_tasks or self._thread_tasks[path].cancelled:
|
|
414
|
-
|
|
415
|
-
def thread_done(task: asyncio.Task):
|
|
557
|
+
span.set_attributes({
|
|
558
|
+
"path" : path
|
|
559
|
+
})
|
|
416
560
|
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
except Exception as e:
|
|
421
|
-
logger.error(f"The chat thread ended with an error {e}", exc_info=e)
|
|
422
|
-
|
|
561
|
+
messages.send_nowait(message)
|
|
562
|
+
|
|
563
|
+
logger.info(f"received message for thread {path}")
|
|
423
564
|
|
|
424
|
-
|
|
425
|
-
|
|
565
|
+
if path not in self._thread_tasks or self._thread_tasks[path].cancelled:
|
|
566
|
+
|
|
567
|
+
def thread_done(task: asyncio.Task):
|
|
426
568
|
|
|
427
|
-
|
|
569
|
+
self._message_channels.pop(message.from_participant_id)
|
|
570
|
+
try:
|
|
571
|
+
task.result()
|
|
572
|
+
except Exception as e:
|
|
573
|
+
logger.error(f"The chat thread ended with an error {e}", exc_info=e)
|
|
574
|
+
|
|
575
|
+
|
|
576
|
+
task = asyncio.create_task(self._spawn_thread(messages=messages, path=path))
|
|
577
|
+
task.add_done_callback(thread_done)
|
|
428
578
|
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
579
|
+
self._thread_tasks[path] = task
|
|
580
|
+
|
|
581
|
+
elif message.type == "typing":
|
|
582
|
+
def callback(task: asyncio.Task):
|
|
583
|
+
try:
|
|
584
|
+
task.result()
|
|
585
|
+
except:
|
|
586
|
+
pass
|
|
587
|
+
|
|
588
|
+
async def remove_timeout(id: str):
|
|
589
|
+
await asyncio.sleep(1)
|
|
590
|
+
self._is_typing.pop(id)
|
|
439
591
|
|
|
440
|
-
|
|
441
|
-
|
|
592
|
+
if message.from_participant_id in self._is_typing:
|
|
593
|
+
self._is_typing[message.from_participant_id].cancel()
|
|
442
594
|
|
|
443
|
-
|
|
444
|
-
|
|
595
|
+
timeout = asyncio.create_task(remove_timeout(id=message.from_participant_id))
|
|
596
|
+
timeout.add_done_callback(callback)
|
|
445
597
|
|
|
446
|
-
|
|
598
|
+
self._is_typing[message.from_participant_id] = timeout
|
|
447
599
|
|
|
448
600
|
room.messaging.on("message", on_message)
|
|
449
601
|
|
meshagent/agents/hosting.py
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import logging
|
|
2
2
|
|
|
3
3
|
from meshagent.api import websocket_protocol, RoomMessage
|
|
4
|
-
from meshagent.api.webhooks import WebhookServer, RoomStartedEvent, RoomEndedEvent,
|
|
4
|
+
from meshagent.api.webhooks import WebhookServer, RoomStartedEvent, RoomEndedEvent, CallEvent
|
|
5
|
+
from meshagent.api import WebSocketClientProtocol
|
|
5
6
|
from meshagent.api.room_server_client import RoomClient
|
|
6
7
|
from meshagent.agents import SingleRoomAgent
|
|
7
8
|
from aiohttp import web
|
meshagent/agents/version.py
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
__version__ = "0.0.
|
|
1
|
+
__version__ = "0.0.31"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: meshagent-agents
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.31
|
|
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,20 @@ License-File: LICENSE
|
|
|
12
12
|
Requires-Dist: pyjwt~=2.10.1
|
|
13
13
|
Requires-Dist: pytest~=8.3.5
|
|
14
14
|
Requires-Dist: pytest-asyncio~=0.26.0
|
|
15
|
-
Requires-Dist: meshagent-api~=0.0.
|
|
16
|
-
Requires-Dist: meshagent-tools~=0.0.
|
|
17
|
-
Requires-Dist: meshagent-openai~=0.0.
|
|
15
|
+
Requires-Dist: meshagent-api~=0.0.31
|
|
16
|
+
Requires-Dist: meshagent-tools~=0.0.31
|
|
17
|
+
Requires-Dist: meshagent-openai~=0.0.31
|
|
18
18
|
Requires-Dist: pydantic~=2.11.1
|
|
19
19
|
Requires-Dist: pydantic-ai~=0.0.48
|
|
20
|
+
Requires-Dist: opentelemetry-distro~=0.54b1
|
|
20
21
|
Provides-Extra: all
|
|
21
|
-
Requires-Dist: meshagent-api[all]~=0.0.
|
|
22
|
+
Requires-Dist: meshagent-api[all]~=0.0.31; extra == "all"
|
|
22
23
|
Requires-Dist: chonkie~=0.5.1; extra == "all"
|
|
23
24
|
Requires-Dist: chonkie[semantic]~=0.5.1; extra == "all"
|
|
24
25
|
Requires-Dist: chonkie[openai]~=0.5.1; extra == "all"
|
|
25
26
|
Requires-Dist: aiosmtplib~=4.0.1; extra == "all"
|
|
26
27
|
Provides-Extra: sync
|
|
27
|
-
Requires-Dist: meshagent-api[sync]~=0.0.
|
|
28
|
+
Requires-Dist: meshagent-api[sync]~=0.0.31; extra == "sync"
|
|
28
29
|
Provides-Extra: mail
|
|
29
30
|
Requires-Dist: aiosmtplib~=4.0.1; extra == "mail"
|
|
30
31
|
Provides-Extra: rag
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
meshagent/agents/__init__.py,sha256=S83622vDM9hWErcgfwZg8lJT2ncu00OEgnxoIbY3VcM,376
|
|
2
2
|
meshagent/agents/adapter.py,sha256=_83Q2XiA8e6Xh37xYnJ9z75AbDWskR-mmKH-LLq6mpA,1318
|
|
3
|
-
meshagent/agents/agent.py,sha256=
|
|
4
|
-
meshagent/agents/chat.py,sha256=
|
|
3
|
+
meshagent/agents/agent.py,sha256=CDxhHWIDj418zEwqsGJ68p3MJc0Ces2GdaJ9BvpSx6I,19423
|
|
4
|
+
meshagent/agents/chat.py,sha256=LjiyQmNEcp5iMeBT26bVfngeXZF3IRJ7muVGrqGFD2w,24491
|
|
5
5
|
meshagent/agents/context.py,sha256=6eFK7wizjzZmZyhbqwazlT_E_e_Cpb17Qa3tBk2BJzw,3804
|
|
6
6
|
meshagent/agents/development.py,sha256=04VYL1Q_BWUTQeVuiVOpyjcs8bzUIX1eQ4VyTtjc5s0,926
|
|
7
|
-
meshagent/agents/hosting.py,sha256=
|
|
7
|
+
meshagent/agents/hosting.py,sha256=O_extmPJ9J6hKSD8dGED35F75PAbRJa0VEPC-67sLqc,4961
|
|
8
8
|
meshagent/agents/indexer.py,sha256=Lz7hJvC7hbvnmiFQLEzmakw_1OPh93pp96iSwIv1fQc,19410
|
|
9
9
|
meshagent/agents/listener.py,sha256=39u20ZwTNUVR0CRUOi4CTgBreg2ZPbrHQOohwjsfijg,5359
|
|
10
10
|
meshagent/agents/mail.py,sha256=bDQdJphKJr0Sl1_XiVhdd1J7E2DBqbjvxvnIVxGt5UU,10951
|
|
@@ -14,7 +14,7 @@ meshagent/agents/pydantic.py,sha256=My9sv1A56unA0qVoPSH-mYtxcgl0AKyxFgyOM70pjLM,
|
|
|
14
14
|
meshagent/agents/single_shot_writer.py,sha256=QsGvTIw1qtp8nGLfzuJwdZj6ucY4cW9rdecqNwv83FA,3355
|
|
15
15
|
meshagent/agents/thread_schema.py,sha256=-KGAMNxQsVuXpvc0avV-OYHe2LMXpjTu5PyQ-1nBnyE,2667
|
|
16
16
|
meshagent/agents/utils.py,sha256=upMbvG4KODZijeTO3IdW4GgzFPz4jXTzNhZBDmtroic,1431
|
|
17
|
-
meshagent/agents/version.py,sha256=
|
|
17
|
+
meshagent/agents/version.py,sha256=JkmidIUbQFwwAhFKnz2l-8dxIwGERIblSCC4CXcpX08,22
|
|
18
18
|
meshagent/agents/worker.py,sha256=G2Q3UpUCQQ8GtPK5_LW4q8uDOyuJXJM_zdRPsx4puck,3260
|
|
19
19
|
meshagent/agents/writer.py,sha256=2Nk52JcjdRz3EnGBO4EHnv49QzByWiije1LKMNuCAIo,2687
|
|
20
20
|
meshagent/agents/schemas/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
@@ -23,8 +23,8 @@ meshagent/agents/schemas/gallery.py,sha256=fzAdlDrn_dJz4FDPkSTH9ir7QmRpV8wFjj6RT
|
|
|
23
23
|
meshagent/agents/schemas/presentation.py,sha256=DreBXAU7Lx92NBPTlEOZq1gdaRs0OkZrJgPT5N7fYH4,1265
|
|
24
24
|
meshagent/agents/schemas/schema.py,sha256=O52T5nUGRNQ8AsamZ_W_IQ8WRDqSBo3vWFDSQcC7Lcg,4473
|
|
25
25
|
meshagent/agents/schemas/super_editor_document.py,sha256=lFpbZn_s_6hchimddzpnGneJ7LaB6dTN_AnLZsx2r9c,1469
|
|
26
|
-
meshagent_agents-0.0.
|
|
27
|
-
meshagent_agents-0.0.
|
|
28
|
-
meshagent_agents-0.0.
|
|
29
|
-
meshagent_agents-0.0.
|
|
30
|
-
meshagent_agents-0.0.
|
|
26
|
+
meshagent_agents-0.0.31.dist-info/licenses/LICENSE,sha256=eTt0SPW-sVNdkZe9PS_S8WfCIyLjRXRl7sUBWdlteFg,10254
|
|
27
|
+
meshagent_agents-0.0.31.dist-info/METADATA,sha256=ldKAbJie7sfVTBaEEyGypPN7irHEKJCTXGlcx74wiHE,1351
|
|
28
|
+
meshagent_agents-0.0.31.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
29
|
+
meshagent_agents-0.0.31.dist-info/top_level.txt,sha256=GlcXnHtRP6m7zlG3Df04M35OsHtNXy_DY09oFwWrH74,10
|
|
30
|
+
meshagent_agents-0.0.31.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|