meshagent-computers 0.0.7__tar.gz → 0.0.8__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-computers might be problematic. Click here for more details.
- {meshagent_computers-0.0.7 → meshagent_computers-0.0.8}/CHANGELOG.md +3 -0
- meshagent_computers-0.0.8/MANIFEST.in +1 -0
- {meshagent_computers-0.0.7/meshagent_computers.egg-info → meshagent_computers-0.0.8}/PKG-INFO +5 -12
- {meshagent_computers-0.0.7 → meshagent_computers-0.0.8}/meshagent/computers/__init__.py +1 -0
- meshagent_computers-0.0.8/meshagent/computers/agent.py +228 -0
- {meshagent_computers-0.0.7 → meshagent_computers-0.0.8}/meshagent/computers/utils.py +1 -1
- meshagent_computers-0.0.8/meshagent/computers/version.py +1 -0
- {meshagent_computers-0.0.7 → meshagent_computers-0.0.8/meshagent_computers.egg-info}/PKG-INFO +5 -12
- {meshagent_computers-0.0.7 → meshagent_computers-0.0.8}/meshagent_computers.egg-info/SOURCES.txt +1 -2
- {meshagent_computers-0.0.7 → meshagent_computers-0.0.8}/meshagent_computers.egg-info/requires.txt +3 -3
- meshagent_computers-0.0.8/pyproject.toml +39 -0
- meshagent_computers-0.0.7/MANIFEST.in +0 -2
- meshagent_computers-0.0.7/meshagent/computers/agent.py +0 -225
- meshagent_computers-0.0.7/pyproject.toml +0 -5
- meshagent_computers-0.0.7/setup.py +0 -46
- meshagent_computers-0.0.7/version.py +0 -1
- {meshagent_computers-0.0.7 → meshagent_computers-0.0.8}/LICENSE +0 -0
- {meshagent_computers-0.0.7 → meshagent_computers-0.0.8}/README.md +0 -0
- {meshagent_computers-0.0.7 → meshagent_computers-0.0.8}/meshagent/computers/base_playwright.py +0 -0
- {meshagent_computers-0.0.7 → meshagent_computers-0.0.8}/meshagent/computers/browserbase.py +0 -0
- {meshagent_computers-0.0.7 → meshagent_computers-0.0.8}/meshagent/computers/computer.py +0 -0
- {meshagent_computers-0.0.7 → meshagent_computers-0.0.8}/meshagent/computers/docker.py +0 -0
- {meshagent_computers-0.0.7 → meshagent_computers-0.0.8}/meshagent/computers/local_playwright.py +0 -0
- {meshagent_computers-0.0.7 → meshagent_computers-0.0.8}/meshagent/computers/operator.py +0 -0
- {meshagent_computers-0.0.7 → meshagent_computers-0.0.8}/meshagent/computers/scrapybara.py +0 -0
- {meshagent_computers-0.0.7 → meshagent_computers-0.0.8}/meshagent_computers.egg-info/dependency_links.txt +0 -0
- {meshagent_computers-0.0.7 → meshagent_computers-0.0.8}/meshagent_computers.egg-info/top_level.txt +0 -0
- {meshagent_computers-0.0.7 → meshagent_computers-0.0.8}/setup.cfg +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
include CHANGELOG.md
|
{meshagent_computers-0.0.7/meshagent_computers.egg-info → meshagent_computers-0.0.8}/PKG-INFO
RENAMED
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: meshagent-computers
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.8
|
|
4
4
|
Summary: Computer Building Blocks for Meshagent
|
|
5
|
-
|
|
6
|
-
License: Apache License 2.0
|
|
5
|
+
License-Expression: Apache-2.0
|
|
7
6
|
Project-URL: Documentation, https://meshagent.com
|
|
8
7
|
Project-URL: Website, https://meshagent.com
|
|
9
8
|
Project-URL: Source, https://github.com/meshagent
|
|
@@ -13,16 +12,10 @@ License-File: LICENSE
|
|
|
13
12
|
Requires-Dist: pytest>=8.3.4
|
|
14
13
|
Requires-Dist: pytest-asyncio>=0.24.0
|
|
15
14
|
Requires-Dist: openai>=1.66.2
|
|
16
|
-
Requires-Dist: meshagent-api>=0.0.
|
|
17
|
-
Requires-Dist: meshagent-agents>=0.0.
|
|
18
|
-
Requires-Dist: meshagent-tools>=0.0.
|
|
15
|
+
Requires-Dist: meshagent-api>=0.0.8
|
|
16
|
+
Requires-Dist: meshagent-agents>=0.0.8
|
|
17
|
+
Requires-Dist: meshagent-tools>=0.0.8
|
|
19
18
|
Requires-Dist: playwright~=1.50.0
|
|
20
19
|
Requires-Dist: browserbase~=1.2.0
|
|
21
20
|
Requires-Dist: scrapybara~=2.4.1
|
|
22
|
-
Dynamic: description-content-type
|
|
23
|
-
Dynamic: license
|
|
24
21
|
Dynamic: license-file
|
|
25
|
-
Dynamic: project-url
|
|
26
|
-
Dynamic: requires-dist
|
|
27
|
-
Dynamic: requires-python
|
|
28
|
-
Dynamic: summary
|
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
from meshagent.agents import LLMAdapter
|
|
2
|
+
from meshagent.tools import Tool, Toolkit, ToolContext
|
|
3
|
+
from meshagent.computers import Computer, Operator, BrowserbaseBrowser
|
|
4
|
+
from meshagent.agents.chat import ChatBot, ChatThreadContext
|
|
5
|
+
from meshagent.api import RequiredToolkit, RemoteParticipant
|
|
6
|
+
from meshagent.api.messaging import RawOutputs
|
|
7
|
+
from meshagent.tools.toolkit import register_toolkit_factory
|
|
8
|
+
|
|
9
|
+
from typing import Optional, Type, Callable
|
|
10
|
+
import base64
|
|
11
|
+
import logging
|
|
12
|
+
|
|
13
|
+
logging.basicConfig()
|
|
14
|
+
logger = logging.getLogger("computer")
|
|
15
|
+
logger.setLevel(logging.INFO)
|
|
16
|
+
|
|
17
|
+
def make_computer_toolkit(*, operator_cls: Type[Operator], computer_cls: Type[Computer], render_screen: Callable[[bytes],None]):
|
|
18
|
+
|
|
19
|
+
operator = operator_cls()
|
|
20
|
+
computer = computer_cls()
|
|
21
|
+
started = False
|
|
22
|
+
|
|
23
|
+
class ComputerTool(Tool):
|
|
24
|
+
def __init__(self, *, operator: Operator, computer: Computer, title = "computer_call", description = "handle computer calls from computer use preview", rules = [], thumbnail_url = None, defs = None):
|
|
25
|
+
super().__init__(
|
|
26
|
+
name="computer_call",
|
|
27
|
+
# TODO: give a correct schema
|
|
28
|
+
input_schema={
|
|
29
|
+
"additionalProperties" : False,
|
|
30
|
+
"type" : "object",
|
|
31
|
+
"required" : [],
|
|
32
|
+
"properties" : {}
|
|
33
|
+
},
|
|
34
|
+
title=title,
|
|
35
|
+
description=description,
|
|
36
|
+
rules=rules,
|
|
37
|
+
thumbnail_url=thumbnail_url,
|
|
38
|
+
defs=defs,
|
|
39
|
+
|
|
40
|
+
)
|
|
41
|
+
self.computer = computer
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
@property
|
|
45
|
+
def options(self):
|
|
46
|
+
return {
|
|
47
|
+
"type": "computer-preview",
|
|
48
|
+
"display_width": self.computer.dimensions[0],
|
|
49
|
+
"display_height": self.computer.dimensions[1],
|
|
50
|
+
"environment": self.computer.environment,
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
async def execute(self, context: ToolContext, *, arguments):
|
|
54
|
+
|
|
55
|
+
nonlocal started
|
|
56
|
+
if started == False:
|
|
57
|
+
await self.computer.__aenter__()
|
|
58
|
+
started = True
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
outputs = await operator.play(computer=self.computer, item=arguments)
|
|
62
|
+
for output in outputs:
|
|
63
|
+
if output["type"] == "computer_call_output":
|
|
64
|
+
if output["output"] != None:
|
|
65
|
+
if output["output"]["type"] == "input_image":
|
|
66
|
+
|
|
67
|
+
b64 : str = output["output"]["image_url"]
|
|
68
|
+
image_data_b64 = b64.split(",", 1)
|
|
69
|
+
|
|
70
|
+
image_bytes = base64.b64decode(image_data_b64[1])
|
|
71
|
+
render_screen(image_bytes)
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
nonlocal computer_toolkit
|
|
75
|
+
if len(computer_toolkit.tools) == 1:
|
|
76
|
+
# HACK: after looking at the page, add the other tools,
|
|
77
|
+
# if we add these first then the computer-use-preview mode fails if it calls them before using the computer
|
|
78
|
+
computer_toolkit.tools.extend([
|
|
79
|
+
ScreenshotTool(computer=computer),
|
|
80
|
+
GotoURL(computer=computer),
|
|
81
|
+
])
|
|
82
|
+
return RawOutputs(outputs=outputs)
|
|
83
|
+
|
|
84
|
+
class ScreenshotTool(Tool):
|
|
85
|
+
def __init__(self, computer: Computer):
|
|
86
|
+
self.computer = computer
|
|
87
|
+
|
|
88
|
+
super().__init__(
|
|
89
|
+
name="screenshot",
|
|
90
|
+
# TODO: give a correct schema
|
|
91
|
+
input_schema={
|
|
92
|
+
"additionalProperties" : False,
|
|
93
|
+
"type" : "object",
|
|
94
|
+
"required" : ["full_page","save_path"],
|
|
95
|
+
"properties" : {
|
|
96
|
+
"full_page" : {
|
|
97
|
+
"type" : "boolean"
|
|
98
|
+
},
|
|
99
|
+
"save_path" : {
|
|
100
|
+
"type" : "string",
|
|
101
|
+
"description" : "a file path to save the screenshot to (should end with .png)"
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
},
|
|
105
|
+
description="take a screenshot of the current page",
|
|
106
|
+
)
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
async def execute(self, context: ToolContext, save_path: str, full_page: bool):
|
|
110
|
+
nonlocal started
|
|
111
|
+
if started == False:
|
|
112
|
+
await self.computer.__aenter__()
|
|
113
|
+
started = True
|
|
114
|
+
|
|
115
|
+
screenshot_bytes = await self.computer.screenshot_bytes(full_page=full_page)
|
|
116
|
+
handle = await context.room.storage.open(path=save_path, overwrite=True)
|
|
117
|
+
await context.room.storage.write(handle=handle, data=screenshot_bytes)
|
|
118
|
+
await context.room.storage.close(handle=handle)
|
|
119
|
+
|
|
120
|
+
return f"saved screenshot to {save_path}"
|
|
121
|
+
|
|
122
|
+
class GotoURL(Tool):
|
|
123
|
+
def __init__(self, computer: Computer):
|
|
124
|
+
self.computer = computer
|
|
125
|
+
|
|
126
|
+
super().__init__(
|
|
127
|
+
name="goto",
|
|
128
|
+
description="goes to a specific URL. Make sure it starts with http:// or https://",
|
|
129
|
+
# TODO: give a correct schema
|
|
130
|
+
input_schema={
|
|
131
|
+
"additionalProperties" : False,
|
|
132
|
+
"type" : "object",
|
|
133
|
+
"required" : ["url"],
|
|
134
|
+
"properties" : {
|
|
135
|
+
"url" : {
|
|
136
|
+
"type" : "string",
|
|
137
|
+
"description": "Fully qualified URL to navigate to.",
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
},
|
|
141
|
+
)
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
async def execute(self, context: ToolContext, url: str):
|
|
145
|
+
nonlocal started
|
|
146
|
+
if started == False:
|
|
147
|
+
await self.computer.__aenter__()
|
|
148
|
+
started = True
|
|
149
|
+
|
|
150
|
+
if url.startswith("https://") == False and url.startswith("http://") == False:
|
|
151
|
+
url = "https://"+url
|
|
152
|
+
|
|
153
|
+
await self.computer.goto(url)
|
|
154
|
+
|
|
155
|
+
render_screen(await self.computer.screenshot_bytes(full_page=False))
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
computer_tool = ComputerTool(computer=computer, operator=operator)
|
|
159
|
+
|
|
160
|
+
computer_toolkit = Toolkit(name="meshagent.openai.computer", tools=[
|
|
161
|
+
computer_tool
|
|
162
|
+
])
|
|
163
|
+
|
|
164
|
+
return computer_toolkit
|
|
165
|
+
|
|
166
|
+
async def make_browserbase_toolkit(context: ToolContext, requirement: RequiredToolkit):
|
|
167
|
+
return make_computer_toolkit(operator_cls=Operator(), computer_cls=BrowserbaseBrowser())
|
|
168
|
+
|
|
169
|
+
register_toolkit_factory("browserbase", make_browserbase_toolkit)
|
|
170
|
+
|
|
171
|
+
|
|
172
|
+
class ComputerAgent(ChatBot):
|
|
173
|
+
def __init__(self, *, name,
|
|
174
|
+
title=None,
|
|
175
|
+
description=None,
|
|
176
|
+
requires=None,
|
|
177
|
+
labels = None,
|
|
178
|
+
computer_cls: Type[Computer],
|
|
179
|
+
operator_cls: Type[Operator],
|
|
180
|
+
rules: Optional[list[str]] = None,
|
|
181
|
+
llm_adapter: Optional[LLMAdapter] = None,
|
|
182
|
+
toolkits: list[Toolkit] = None
|
|
183
|
+
):
|
|
184
|
+
|
|
185
|
+
if rules == None:
|
|
186
|
+
rules=[
|
|
187
|
+
"if asked to go to a URL, you MUST use the goto function to go to the url if it is available",
|
|
188
|
+
"after going directly to a URL, the screen will change so you should take a look at it to know what to do next"
|
|
189
|
+
]
|
|
190
|
+
super().__init__(
|
|
191
|
+
name=name,
|
|
192
|
+
title=title,
|
|
193
|
+
description=description,
|
|
194
|
+
requires=requires,
|
|
195
|
+
labels=labels,
|
|
196
|
+
llm_adapter=llm_adapter,
|
|
197
|
+
toolkits=toolkits,
|
|
198
|
+
rules=rules
|
|
199
|
+
)
|
|
200
|
+
self.computer_cls = computer_cls
|
|
201
|
+
self.operator_cls = operator_cls
|
|
202
|
+
|
|
203
|
+
|
|
204
|
+
async def get_thread_toolkits(self, *, thread_context: ChatThreadContext, participant: RemoteParticipant):
|
|
205
|
+
|
|
206
|
+
toolkits = await super().get_thread_toolkits(thread_context=thread_context, participant=participant)
|
|
207
|
+
|
|
208
|
+
def render_screen(image_bytes: bytes):
|
|
209
|
+
for participant in thread_context.participants:
|
|
210
|
+
self.room.messaging.send_message_nowait(
|
|
211
|
+
to=participant,
|
|
212
|
+
type="computer_screen",
|
|
213
|
+
message={
|
|
214
|
+
},
|
|
215
|
+
attachment=image_bytes
|
|
216
|
+
)
|
|
217
|
+
|
|
218
|
+
computer_toolkit = make_computer_toolkit(
|
|
219
|
+
operator_cls=self.operator_cls,
|
|
220
|
+
computer_cls=self.computer_cls,
|
|
221
|
+
render_screen=render_screen
|
|
222
|
+
)
|
|
223
|
+
return [
|
|
224
|
+
computer_toolkit,
|
|
225
|
+
*toolkits
|
|
226
|
+
]
|
|
227
|
+
|
|
228
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "0.0.8"
|
{meshagent_computers-0.0.7 → meshagent_computers-0.0.8/meshagent_computers.egg-info}/PKG-INFO
RENAMED
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: meshagent-computers
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.8
|
|
4
4
|
Summary: Computer Building Blocks for Meshagent
|
|
5
|
-
|
|
6
|
-
License: Apache License 2.0
|
|
5
|
+
License-Expression: Apache-2.0
|
|
7
6
|
Project-URL: Documentation, https://meshagent.com
|
|
8
7
|
Project-URL: Website, https://meshagent.com
|
|
9
8
|
Project-URL: Source, https://github.com/meshagent
|
|
@@ -13,16 +12,10 @@ License-File: LICENSE
|
|
|
13
12
|
Requires-Dist: pytest>=8.3.4
|
|
14
13
|
Requires-Dist: pytest-asyncio>=0.24.0
|
|
15
14
|
Requires-Dist: openai>=1.66.2
|
|
16
|
-
Requires-Dist: meshagent-api>=0.0.
|
|
17
|
-
Requires-Dist: meshagent-agents>=0.0.
|
|
18
|
-
Requires-Dist: meshagent-tools>=0.0.
|
|
15
|
+
Requires-Dist: meshagent-api>=0.0.8
|
|
16
|
+
Requires-Dist: meshagent-agents>=0.0.8
|
|
17
|
+
Requires-Dist: meshagent-tools>=0.0.8
|
|
19
18
|
Requires-Dist: playwright~=1.50.0
|
|
20
19
|
Requires-Dist: browserbase~=1.2.0
|
|
21
20
|
Requires-Dist: scrapybara~=2.4.1
|
|
22
|
-
Dynamic: description-content-type
|
|
23
|
-
Dynamic: license
|
|
24
21
|
Dynamic: license-file
|
|
25
|
-
Dynamic: project-url
|
|
26
|
-
Dynamic: requires-dist
|
|
27
|
-
Dynamic: requires-python
|
|
28
|
-
Dynamic: summary
|
{meshagent_computers-0.0.7 → meshagent_computers-0.0.8}/meshagent_computers.egg-info/SOURCES.txt
RENAMED
|
@@ -3,8 +3,6 @@ LICENSE
|
|
|
3
3
|
MANIFEST.in
|
|
4
4
|
README.md
|
|
5
5
|
pyproject.toml
|
|
6
|
-
setup.py
|
|
7
|
-
version.py
|
|
8
6
|
meshagent/computers/__init__.py
|
|
9
7
|
meshagent/computers/agent.py
|
|
10
8
|
meshagent/computers/base_playwright.py
|
|
@@ -15,6 +13,7 @@ meshagent/computers/local_playwright.py
|
|
|
15
13
|
meshagent/computers/operator.py
|
|
16
14
|
meshagent/computers/scrapybara.py
|
|
17
15
|
meshagent/computers/utils.py
|
|
16
|
+
meshagent/computers/version.py
|
|
18
17
|
meshagent_computers.egg-info/PKG-INFO
|
|
19
18
|
meshagent_computers.egg-info/SOURCES.txt
|
|
20
19
|
meshagent_computers.egg-info/dependency_links.txt
|
{meshagent_computers-0.0.7 → meshagent_computers-0.0.8}/meshagent_computers.egg-info/requires.txt
RENAMED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
pytest>=8.3.4
|
|
2
2
|
pytest-asyncio>=0.24.0
|
|
3
3
|
openai>=1.66.2
|
|
4
|
-
meshagent-api>=0.0.
|
|
5
|
-
meshagent-agents>=0.0.
|
|
6
|
-
meshagent-tools>=0.0.
|
|
4
|
+
meshagent-api>=0.0.8
|
|
5
|
+
meshagent-agents>=0.0.8
|
|
6
|
+
meshagent-tools>=0.0.8
|
|
7
7
|
playwright~=1.50.0
|
|
8
8
|
browserbase~=1.2.0
|
|
9
9
|
scrapybara~=2.4.1
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = [
|
|
3
|
+
"setuptools>=42",
|
|
4
|
+
"wheel"
|
|
5
|
+
]
|
|
6
|
+
build-backend = "setuptools.build_meta"
|
|
7
|
+
|
|
8
|
+
[project]
|
|
9
|
+
name = "meshagent-computers"
|
|
10
|
+
dynamic = ["version", "readme"]
|
|
11
|
+
description = "Computer Building Blocks for Meshagent"
|
|
12
|
+
requires-python = ">=3.9.0"
|
|
13
|
+
license = "Apache-2.0"
|
|
14
|
+
dependencies = [
|
|
15
|
+
"pytest>=8.3.4",
|
|
16
|
+
"pytest-asyncio>=0.24.0",
|
|
17
|
+
"openai>=1.66.2",
|
|
18
|
+
"meshagent-api>=0.0.8",
|
|
19
|
+
"meshagent-agents>=0.0.8",
|
|
20
|
+
"meshagent-tools>=0.0.8",
|
|
21
|
+
"playwright~=1.50.0",
|
|
22
|
+
"browserbase~=1.2.0",
|
|
23
|
+
"scrapybara~=2.4.1"
|
|
24
|
+
]
|
|
25
|
+
|
|
26
|
+
[project.urls]
|
|
27
|
+
Documentation = "https://meshagent.com"
|
|
28
|
+
Website = "https://meshagent.com"
|
|
29
|
+
Source = "https://github.com/meshagent"
|
|
30
|
+
|
|
31
|
+
[tool.setuptools.packages.find]
|
|
32
|
+
include = ["meshagent.*"]
|
|
33
|
+
|
|
34
|
+
[tool.setuptools.package-data]
|
|
35
|
+
"meshagent.computers" = ["py.typed", "*.pyi", "**/*.pyi", "**/*.js" ]
|
|
36
|
+
|
|
37
|
+
[tool.setuptools.dynamic]
|
|
38
|
+
version = {attr = "meshagent.computers.version.__version__"}
|
|
39
|
+
readme = { file = "README.md", content-type = "text/markdown" }
|
|
@@ -1,225 +0,0 @@
|
|
|
1
|
-
from meshagent.openai import OpenAIResponsesAdapter
|
|
2
|
-
from meshagent.agents import LLMAdapter, AgentChatContext
|
|
3
|
-
from meshagent.tools import Tool, Toolkit, ToolContext
|
|
4
|
-
from meshagent.agents.prompt import PromptAgent
|
|
5
|
-
from meshagent.computers import Computer, Operator
|
|
6
|
-
from meshagent.agents.chat import ChatBot, ChatThreadContext
|
|
7
|
-
from meshagent.api import RemoteParticipant, FileResponse
|
|
8
|
-
from meshagent.api.messaging import RawOutputs
|
|
9
|
-
|
|
10
|
-
from typing import Optional
|
|
11
|
-
import base64
|
|
12
|
-
import json
|
|
13
|
-
import logging
|
|
14
|
-
|
|
15
|
-
logging.basicConfig()
|
|
16
|
-
logger = logging.getLogger("computer")
|
|
17
|
-
logger.setLevel(logging.INFO)
|
|
18
|
-
|
|
19
|
-
class ComputerAgent[ComputerType:Computer, OperatorType:Operator](ChatBot):
|
|
20
|
-
def __init__(self, *, name,
|
|
21
|
-
title=None,
|
|
22
|
-
description=None,
|
|
23
|
-
requires=None,
|
|
24
|
-
labels = None,
|
|
25
|
-
computer_cls: ComputerType,
|
|
26
|
-
operator_cls: OperatorType,
|
|
27
|
-
rules: Optional[list[str]] = None,
|
|
28
|
-
llm_adapter: Optional[LLMAdapter] = None,
|
|
29
|
-
toolkits: list[Toolkit] = None
|
|
30
|
-
):
|
|
31
|
-
|
|
32
|
-
if rules == None:
|
|
33
|
-
rules=[
|
|
34
|
-
"if asked to go to a URL, you MUST use the goto function to go to the url if it is available",
|
|
35
|
-
"after going directly to a URL, the screen will change so you should take a look at it to know what to do next"
|
|
36
|
-
]
|
|
37
|
-
super().__init__(
|
|
38
|
-
name=name,
|
|
39
|
-
title=title,
|
|
40
|
-
description=description,
|
|
41
|
-
requires=requires,
|
|
42
|
-
labels=labels,
|
|
43
|
-
llm_adapter=llm_adapter,
|
|
44
|
-
toolkits=toolkits,
|
|
45
|
-
rules=rules
|
|
46
|
-
)
|
|
47
|
-
self.computer_cls = computer_cls
|
|
48
|
-
self.operator_cls = operator_cls
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
async def init_thread_context(self, *, thread_context: ChatThreadContext):
|
|
52
|
-
|
|
53
|
-
operator : Operator = self.operator_cls()
|
|
54
|
-
computer : Computer = self.computer_cls()
|
|
55
|
-
started = False
|
|
56
|
-
|
|
57
|
-
class ComputerTool(Tool):
|
|
58
|
-
def __init__(self, *, operator: Operator, computer: Computer, title = "computer_call", description = "handle computer calls from computer use preview", rules = [], thumbnail_url = None, defs = None):
|
|
59
|
-
super().__init__(
|
|
60
|
-
name="computer_call",
|
|
61
|
-
# TODO: give a correct schema
|
|
62
|
-
input_schema={
|
|
63
|
-
"additionalProperties" : False,
|
|
64
|
-
"type" : "object",
|
|
65
|
-
"required" : [],
|
|
66
|
-
"properties" : {}
|
|
67
|
-
},
|
|
68
|
-
title=title,
|
|
69
|
-
description=description,
|
|
70
|
-
rules=rules,
|
|
71
|
-
thumbnail_url=thumbnail_url,
|
|
72
|
-
defs=defs,
|
|
73
|
-
|
|
74
|
-
)
|
|
75
|
-
self.computer = computer
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
@property
|
|
79
|
-
def options(self):
|
|
80
|
-
return {
|
|
81
|
-
"type": "computer-preview",
|
|
82
|
-
"display_width": self.computer.dimensions[0],
|
|
83
|
-
"display_height": self.computer.dimensions[1],
|
|
84
|
-
"environment": self.computer.environment,
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
async def execute(self, context: ToolContext, *, arguments):
|
|
88
|
-
|
|
89
|
-
nonlocal started
|
|
90
|
-
if started == False:
|
|
91
|
-
await self.computer.__aenter__()
|
|
92
|
-
started = True
|
|
93
|
-
|
|
94
|
-
for participant in thread_context.participants:
|
|
95
|
-
await context.room.messaging.send_message(
|
|
96
|
-
to=participant,
|
|
97
|
-
type="computer_use",
|
|
98
|
-
message={
|
|
99
|
-
"arguments" : arguments
|
|
100
|
-
}
|
|
101
|
-
)
|
|
102
|
-
|
|
103
|
-
outputs = await operator.play(computer=self.computer, item=arguments)
|
|
104
|
-
for output in outputs:
|
|
105
|
-
if output["type"] == "computer_call_output":
|
|
106
|
-
if output["output"] != None:
|
|
107
|
-
if output["output"]["type"] == "input_image":
|
|
108
|
-
|
|
109
|
-
b64 : str = output["output"]["image_url"]
|
|
110
|
-
image_data_b64 = b64.split(",", 1)
|
|
111
|
-
|
|
112
|
-
image_bytes = base64.b64decode(image_data_b64[1])
|
|
113
|
-
|
|
114
|
-
for participant in thread_context.participants:
|
|
115
|
-
context.room.messaging.send_message_nowait(
|
|
116
|
-
to=participant,
|
|
117
|
-
type="computer_screen",
|
|
118
|
-
message={
|
|
119
|
-
},
|
|
120
|
-
attachment=image_bytes
|
|
121
|
-
)
|
|
122
|
-
|
|
123
|
-
nonlocal computer_toolkit
|
|
124
|
-
if len(computer_toolkit.tools) == 1:
|
|
125
|
-
# HACK: after looking at the page, add the other tools,
|
|
126
|
-
# if we add these first then the computer-use-preview mode fails if it calls them before using the computer
|
|
127
|
-
computer_toolkit.tools.extend([
|
|
128
|
-
ScreenshotTool(computer=computer),
|
|
129
|
-
GotoURL(computer=computer),
|
|
130
|
-
])
|
|
131
|
-
return RawOutputs(outputs=outputs)
|
|
132
|
-
|
|
133
|
-
class ScreenshotTool(Tool):
|
|
134
|
-
def __init__(self, computer: Computer):
|
|
135
|
-
self.computer = computer
|
|
136
|
-
|
|
137
|
-
super().__init__(
|
|
138
|
-
name="screenshot",
|
|
139
|
-
# TODO: give a correct schema
|
|
140
|
-
input_schema={
|
|
141
|
-
"additionalProperties" : False,
|
|
142
|
-
"type" : "object",
|
|
143
|
-
"required" : ["full_page","save_path"],
|
|
144
|
-
"properties" : {
|
|
145
|
-
"full_page" : {
|
|
146
|
-
"type" : "boolean"
|
|
147
|
-
},
|
|
148
|
-
"save_path" : {
|
|
149
|
-
"type" : "string",
|
|
150
|
-
"description" : "a file path to save the screenshot to (should end with .png)"
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
},
|
|
154
|
-
description="take a screenshot of the current page",
|
|
155
|
-
)
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
async def execute(self, context: ToolContext, save_path: str, full_page: bool):
|
|
159
|
-
nonlocal started
|
|
160
|
-
if started == False:
|
|
161
|
-
await self.computer.__aenter__()
|
|
162
|
-
started = True
|
|
163
|
-
|
|
164
|
-
screenshot_bytes = await self.computer.screenshot_bytes(full_page=full_page)
|
|
165
|
-
handle = await context.room.storage.open(path=save_path, overwrite=True)
|
|
166
|
-
await context.room.storage.write(handle=handle, data=screenshot_bytes)
|
|
167
|
-
await context.room.storage.close(handle=handle)
|
|
168
|
-
|
|
169
|
-
return f"saved screenshot to {save_path}"
|
|
170
|
-
|
|
171
|
-
class GotoURL(Tool):
|
|
172
|
-
def __init__(self, computer: Computer):
|
|
173
|
-
self.computer = computer
|
|
174
|
-
|
|
175
|
-
super().__init__(
|
|
176
|
-
name="goto",
|
|
177
|
-
description="goes to a specific URL. Make sure it starts with http:// or https://",
|
|
178
|
-
# TODO: give a correct schema
|
|
179
|
-
input_schema={
|
|
180
|
-
"additionalProperties" : False,
|
|
181
|
-
"type" : "object",
|
|
182
|
-
"required" : ["url"],
|
|
183
|
-
"properties" : {
|
|
184
|
-
"url" : {
|
|
185
|
-
"type" : "string",
|
|
186
|
-
"description": "Fully qualified URL to navigate to.",
|
|
187
|
-
}
|
|
188
|
-
}
|
|
189
|
-
},
|
|
190
|
-
)
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
async def execute(self, context: ToolContext, url: str):
|
|
194
|
-
nonlocal started
|
|
195
|
-
if started == False:
|
|
196
|
-
await self.computer.__aenter__()
|
|
197
|
-
started = True
|
|
198
|
-
|
|
199
|
-
if url.startswith("https://") == False and url.startswith("http://") == False:
|
|
200
|
-
url = "https://"+url
|
|
201
|
-
|
|
202
|
-
await self.computer.goto(url)
|
|
203
|
-
|
|
204
|
-
# send an updated screen out
|
|
205
|
-
for participant in thread_context.participants:
|
|
206
|
-
context.room.messaging.send_message_nowait(
|
|
207
|
-
to=participant,
|
|
208
|
-
type="computer_screen",
|
|
209
|
-
message={
|
|
210
|
-
},
|
|
211
|
-
attachment = await self.computer.screenshot_bytes(full_page=False)
|
|
212
|
-
)
|
|
213
|
-
|
|
214
|
-
computer_tool = ComputerTool(computer=computer, operator=operator)
|
|
215
|
-
|
|
216
|
-
computer_toolkit = Toolkit(name="meshagent.openai.computer", tools=[
|
|
217
|
-
computer_tool
|
|
218
|
-
])
|
|
219
|
-
|
|
220
|
-
thread_context.toolkits = [
|
|
221
|
-
computer_toolkit,
|
|
222
|
-
*thread_context.toolkits
|
|
223
|
-
]
|
|
224
|
-
|
|
225
|
-
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
import os
|
|
2
|
-
import pathlib
|
|
3
|
-
from typing import Any, Dict
|
|
4
|
-
|
|
5
|
-
import setuptools # type: ignore
|
|
6
|
-
|
|
7
|
-
here = pathlib.Path(__file__).parent.resolve()
|
|
8
|
-
about: Dict[Any, Any] = {}
|
|
9
|
-
with open(os.path.join(here, "version.py"), "r") as f:
|
|
10
|
-
exec(f.read(), about)
|
|
11
|
-
|
|
12
|
-
setuptools.setup(
|
|
13
|
-
name="meshagent-computers",
|
|
14
|
-
version=about["__version__"],
|
|
15
|
-
description="Computer Building Blocks for Meshagent",
|
|
16
|
-
long_description=(here / "README.md").read_text(encoding="utf-8"),
|
|
17
|
-
long_description_content_type="text/markdown",
|
|
18
|
-
url="",
|
|
19
|
-
classifiers=[
|
|
20
|
-
],
|
|
21
|
-
keywords=[],
|
|
22
|
-
license="Apache License 2.0",
|
|
23
|
-
packages=setuptools.find_namespace_packages(include=[
|
|
24
|
-
"meshagent.*",
|
|
25
|
-
]),
|
|
26
|
-
python_requires=">=3.9.0",
|
|
27
|
-
install_requires=[
|
|
28
|
-
"pytest>=8.3.4",
|
|
29
|
-
"pytest-asyncio>=0.24.0",
|
|
30
|
-
"openai>=1.66.2",
|
|
31
|
-
"meshagent-api>=0.0.7",
|
|
32
|
-
"meshagent-agents>=0.0.7",
|
|
33
|
-
"meshagent-tools>=0.0.7",
|
|
34
|
-
"playwright~=1.50.0",
|
|
35
|
-
"browserbase~=1.2.0",
|
|
36
|
-
"scrapybara~=2.4.1",
|
|
37
|
-
],
|
|
38
|
-
package_data={
|
|
39
|
-
"meshagent.computers": ["py.typed", "*.pyi", "**/*.pyi", "**/*.js"],
|
|
40
|
-
},
|
|
41
|
-
project_urls={
|
|
42
|
-
"Documentation": "https://meshagent.com",
|
|
43
|
-
"Website": "https://meshagent.com",
|
|
44
|
-
"Source": "https://github.com/meshagent",
|
|
45
|
-
},
|
|
46
|
-
)
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = "0.0.7"
|
|
File without changes
|
|
File without changes
|
{meshagent_computers-0.0.7 → meshagent_computers-0.0.8}/meshagent/computers/base_playwright.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{meshagent_computers-0.0.7 → meshagent_computers-0.0.8}/meshagent/computers/local_playwright.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{meshagent_computers-0.0.7 → meshagent_computers-0.0.8}/meshagent_computers.egg-info/top_level.txt
RENAMED
|
File without changes
|
|
File without changes
|