meshagent-agents 0.0.1__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.

@@ -0,0 +1,155 @@
1
+
2
+ import logging
3
+ import asyncio
4
+ from typing import Optional
5
+
6
+ from meshagent.agents import TaskRunner
7
+ from meshagent.api.schema_document import Element,Text
8
+ from meshagent.api.room_server_client import RoomClient, MeshDocument
9
+ from meshagent.api.websocket_protocol import WebSocketClientProtocol
10
+
11
+ from typing import Optional
12
+
13
+ logger = logging.getLogger(__name__)
14
+ logger.setLevel(logging.INFO)
15
+
16
+ from meshagent.agents.agent import TaskRunner, AgentChatContext, AgentCallContext
17
+
18
+ class ListenerContext:
19
+ def __init__(self, document: MeshDocument, room: RoomClient, call_context: AgentCallContext):
20
+ self.document = document
21
+ self.call_context = call_context
22
+ self.room = room
23
+
24
+
25
+ # Notifies of new nodes or changed nodes in a document, the document must already exist
26
+ class Listener(TaskRunner):
27
+
28
+ def __init__(self, *, name: str, wait_for_synchronize: bool = True, title: Optional[str] = None, description: Optional[str] = None):
29
+ super().__init__(
30
+ name=name,
31
+ description=description,
32
+ title=title,
33
+ input_schema={
34
+ "type" : "object",
35
+ "required" : ["path"],
36
+ "additionalProperties" : False,
37
+ "properties" : {
38
+ "path" : {
39
+ "type" : "string",
40
+ "description" : "the path of the document to proofread"
41
+ }
42
+ }
43
+ },
44
+ output_schema={
45
+ "type" : "object",
46
+ "additionalProperties" : False,
47
+ "required" : [],
48
+ "properties" : {
49
+ }
50
+ }
51
+ )
52
+ self.wait_for_synchronize = wait_for_synchronize
53
+
54
+ async def on_listening_started(self, listener_context: ListenerContext):
55
+ pass
56
+
57
+ async def on_element_inserted(self, listener_context: ListenerContext, element: Element) -> bool:
58
+ return False
59
+
60
+ async def on_attribute_changed(self, listener_context: ListenerContext, element: Element, attribute: Optional[str]) -> bool:
61
+ return False
62
+
63
+ async def ask(self, *, context: AgentCallContext, arguments: dict):
64
+
65
+ output_path = arguments["path"]
66
+ room = context.room
67
+ logger.info("Visitor connecting to %s", output_path)
68
+ doc = await room.sync.open(path=output_path, create=True)
69
+ try:
70
+ listener_context = ListenerContext(
71
+ document=doc,
72
+ room=room,
73
+ call_context=context,
74
+ )
75
+ logger.info("Visitor connected to %s", output_path)
76
+
77
+ change_queue = list[Element | Text]()
78
+
79
+ def append_children(node:Element):
80
+ for child in node.get_children():
81
+ if child not in change_queue:
82
+ change_queue.append([child])
83
+ if isinstance(child, Element):
84
+ append_children(child)
85
+
86
+ if self.wait_for_synchronize == False:
87
+ change_queue.append([doc.root])
88
+ append_children(doc.root)
89
+ else:
90
+ await doc.synchronized
91
+
92
+
93
+ await self.on_listening_started(listener_context=listener_context)
94
+
95
+ wait_for_changes = asyncio.Future()
96
+
97
+ @doc.on("inserted")
98
+ def on_inserted(e: Element):
99
+ logger.info("element inserted %s", e.tag_name)
100
+ if e not in change_queue:
101
+ change_queue.append([e])
102
+ append_children(e)
103
+
104
+ if wait_for_changes.done() == False:
105
+ wait_for_changes.set_result(True)
106
+
107
+
108
+ @doc.on("updated")
109
+ def on_updated(e: Element, attribute: str):
110
+ logger.info("element updated %s", e.tag_name)
111
+ if e not in change_queue:
112
+ change_queue.append([e, attribute])
113
+ #
114
+ # append_children(e)
115
+
116
+ if wait_for_changes.done() == False:
117
+ wait_for_changes.set_result(True)
118
+
119
+
120
+ waiting_for_end = True
121
+ while waiting_for_end:
122
+ await wait_for_changes
123
+
124
+ while len(change_queue) > 0:
125
+
126
+ change = change_queue.pop(0)
127
+ content = change[0]
128
+ if len(change) > 1:
129
+ done = await self.on_attribute_changed(listener_context, content, change[1])
130
+ if done:
131
+ waiting_for_end = False
132
+
133
+ else:
134
+ done = await self.on_element_inserted(listener_context, content)
135
+ if done:
136
+ waiting_for_end = False
137
+
138
+ if content in change_queue:
139
+ change_queue.remove(content)
140
+
141
+
142
+
143
+ wait_for_changes = asyncio.Future()
144
+ except Exception as e:
145
+ logger.error("Failed to visit", exc_info=e)
146
+ raise
147
+
148
+ finally:
149
+
150
+ logger.info("vistor done")
151
+
152
+ await asyncio.sleep(5)
153
+ await room.sync.close(output_path)
154
+
155
+ return {}