meshagent-tools 0.24.5__tar.gz → 0.25.0__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.
- {meshagent_tools-0.24.5 → meshagent_tools-0.25.0}/CHANGELOG.md +9 -0
- {meshagent_tools-0.24.5/meshagent_tools.egg-info → meshagent_tools-0.25.0}/PKG-INFO +3 -3
- {meshagent_tools-0.24.5 → meshagent_tools-0.25.0}/meshagent/tools/__init__.py +2 -0
- {meshagent_tools-0.24.5 → meshagent_tools-0.25.0}/meshagent/tools/blob.py +2 -2
- {meshagent_tools-0.24.5 → meshagent_tools-0.25.0}/meshagent/tools/database.py +3 -3
- {meshagent_tools-0.24.5 → meshagent_tools-0.25.0}/meshagent/tools/script.py +36 -0
- meshagent_tools-0.25.0/meshagent/tools/tests/tool_decorator_test.py +45 -0
- {meshagent_tools-0.24.5 → meshagent_tools-0.25.0}/meshagent/tools/tool.py +87 -2
- {meshagent_tools-0.24.5 → meshagent_tools-0.25.0}/meshagent/tools/toolkit.py +7 -2
- meshagent_tools-0.25.0/meshagent/tools/version.py +1 -0
- {meshagent_tools-0.24.5 → meshagent_tools-0.25.0/meshagent_tools.egg-info}/PKG-INFO +3 -3
- {meshagent_tools-0.24.5 → meshagent_tools-0.25.0}/meshagent_tools.egg-info/SOURCES.txt +1 -0
- {meshagent_tools-0.24.5 → meshagent_tools-0.25.0}/meshagent_tools.egg-info/requires.txt +2 -2
- {meshagent_tools-0.24.5 → meshagent_tools-0.25.0}/pyproject.toml +2 -2
- meshagent_tools-0.24.5/meshagent/tools/version.py +0 -1
- {meshagent_tools-0.24.5 → meshagent_tools-0.25.0}/LICENSE +0 -0
- {meshagent_tools-0.24.5 → meshagent_tools-0.25.0}/MANIFEST.in +0 -0
- {meshagent_tools-0.24.5 → meshagent_tools-0.25.0}/README.md +0 -0
- {meshagent_tools-0.24.5 → meshagent_tools-0.25.0}/meshagent/tools/config.py +0 -0
- {meshagent_tools-0.24.5 → meshagent_tools-0.25.0}/meshagent/tools/datetime.py +0 -0
- {meshagent_tools-0.24.5 → meshagent_tools-0.25.0}/meshagent/tools/discovery.py +0 -0
- {meshagent_tools-0.24.5 → meshagent_tools-0.25.0}/meshagent/tools/document_tools.py +0 -0
- {meshagent_tools-0.24.5 → meshagent_tools-0.25.0}/meshagent/tools/hosting.py +0 -0
- {meshagent_tools-0.24.5 → meshagent_tools-0.25.0}/meshagent/tools/multi_tool.py +0 -0
- {meshagent_tools-0.24.5 → meshagent_tools-0.25.0}/meshagent/tools/pydantic.py +0 -0
- {meshagent_tools-0.24.5 → meshagent_tools-0.25.0}/meshagent/tools/storage.py +0 -0
- {meshagent_tools-0.24.5 → meshagent_tools-0.25.0}/meshagent/tools/strict_schema.py +0 -0
- {meshagent_tools-0.24.5 → meshagent_tools-0.25.0}/meshagent/tools/uuid.py +0 -0
- {meshagent_tools-0.24.5 → meshagent_tools-0.25.0}/meshagent/tools/web_toolkit.py +0 -0
- {meshagent_tools-0.24.5 → meshagent_tools-0.25.0}/meshagent_tools.egg-info/dependency_links.txt +0 -0
- {meshagent_tools-0.24.5 → meshagent_tools-0.25.0}/meshagent_tools.egg-info/top_level.txt +0 -0
- {meshagent_tools-0.24.5 → meshagent_tools-0.25.0}/setup.cfg +0 -0
|
@@ -1,3 +1,12 @@
|
|
|
1
|
+
## [0.25.0]
|
|
2
|
+
- Added SQL column-schema parsing and CLI support for SQL-like `--columns` when creating tables or adding columns.
|
|
3
|
+
- Breaking: SQL query requests now use a single `params` map for typed bindings instead of `parameters`/`param_values`.
|
|
4
|
+
- Added `published`/`public` port fields in service specs for externally routed services.
|
|
5
|
+
- Secrets set now supports `for_identity` to set secrets on behalf of another identity.
|
|
6
|
+
- Added a Slack events HTTP bot package with dependencies including `pyjwt` 2.10.
|
|
7
|
+
- Breaking: the CLI `exec` command was removed.
|
|
8
|
+
- ThreadAdapter message writing now uses `write_text_message` and accepts participant name strings.
|
|
9
|
+
|
|
1
10
|
## [0.24.5]
|
|
2
11
|
- Stability
|
|
3
12
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: meshagent-tools
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.25.0
|
|
4
4
|
Summary: Tools for Meshagent
|
|
5
5
|
License-Expression: Apache-2.0
|
|
6
6
|
Project-URL: Documentation, https://docs.meshagent.com
|
|
@@ -12,8 +12,8 @@ License-File: LICENSE
|
|
|
12
12
|
Requires-Dist: pyjwt~=2.10
|
|
13
13
|
Requires-Dist: pytest~=8.4
|
|
14
14
|
Requires-Dist: pytest-asyncio~=0.26
|
|
15
|
-
Requires-Dist: meshagent-api~=0.
|
|
16
|
-
Requires-Dist: aiohttp~=3.
|
|
15
|
+
Requires-Dist: meshagent-api~=0.25.0
|
|
16
|
+
Requires-Dist: aiohttp[speedups]~=3.13.0
|
|
17
17
|
Requires-Dist: opentelemetry-distro~=0.54b1
|
|
18
18
|
Dynamic: license-file
|
|
19
19
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
from uuid import uuid4
|
|
2
2
|
import base64
|
|
3
|
-
import
|
|
3
|
+
from meshagent.api.http import new_client_session
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
class Blob:
|
|
@@ -48,7 +48,7 @@ async def get_bytes_from_url(*, url: str) -> Blob:
|
|
|
48
48
|
# file_name = str(uuid.uuid4())+extension
|
|
49
49
|
return Blob(mime_type=mime_type, data=content)
|
|
50
50
|
else:
|
|
51
|
-
async with
|
|
51
|
+
async with new_client_session() as session:
|
|
52
52
|
async with session.get(url=url) as response:
|
|
53
53
|
content = await response.content.read()
|
|
54
54
|
return Blob(mime_type=response.content_type, data=content)
|
|
@@ -128,7 +128,7 @@ class UpdateTool(Tool):
|
|
|
128
128
|
columns = ""
|
|
129
129
|
|
|
130
130
|
for k, v in schema.items():
|
|
131
|
-
columns += f"column {k} => {v.
|
|
131
|
+
columns += f"column {k} => {v.model_dump(mode='json')}"
|
|
132
132
|
|
|
133
133
|
anyOf = []
|
|
134
134
|
|
|
@@ -500,7 +500,7 @@ class AdvancedSearchTool(Tool):
|
|
|
500
500
|
columns = ""
|
|
501
501
|
|
|
502
502
|
for k, v in schema.items():
|
|
503
|
-
columns += f"column {k} => {v.
|
|
503
|
+
columns += f"column {k} => {v.model_dump(mode='json')}\n"
|
|
504
504
|
|
|
505
505
|
input_schema = {
|
|
506
506
|
"type": "object",
|
|
@@ -542,7 +542,7 @@ class AdvancedDeleteRowsTool(Tool):
|
|
|
542
542
|
columns = ""
|
|
543
543
|
|
|
544
544
|
for k, v in schema.items():
|
|
545
|
-
columns += f"column {k} => {v.
|
|
545
|
+
columns += f"column {k} => {v.model_dump(mode='json')}"
|
|
546
546
|
|
|
547
547
|
input_schema = {
|
|
548
548
|
"type": "object",
|
|
@@ -311,3 +311,39 @@ class ScriptTool(Tool):
|
|
|
311
311
|
)
|
|
312
312
|
|
|
313
313
|
return {"results": results}
|
|
314
|
+
|
|
315
|
+
|
|
316
|
+
async def get_script_tools(room: RoomClient):
|
|
317
|
+
services = await room.services.list()
|
|
318
|
+
|
|
319
|
+
st = []
|
|
320
|
+
|
|
321
|
+
for service in services:
|
|
322
|
+
if service.metadata.annotations is not None:
|
|
323
|
+
print("X")
|
|
324
|
+
type = service.metadata.annotations.get("meshagent.tool.type")
|
|
325
|
+
print(type)
|
|
326
|
+
commands_str = service.metadata.annotations.get("meshagent.tool.commands")
|
|
327
|
+
print(commands_str)
|
|
328
|
+
tool_name = service.metadata.annotations.get(
|
|
329
|
+
"meshagent.tool.name", service.metadata.name
|
|
330
|
+
)
|
|
331
|
+
description = service.metadata.annotations.get(
|
|
332
|
+
"meshagent.tool.description", service.metadata.description
|
|
333
|
+
)
|
|
334
|
+
|
|
335
|
+
if type == "script" and tool_name is not None:
|
|
336
|
+
print("FOUND")
|
|
337
|
+
if commands_str is not None:
|
|
338
|
+
commands = commands_str.split("\n")
|
|
339
|
+
|
|
340
|
+
st.append(
|
|
341
|
+
ScriptTool(
|
|
342
|
+
name=tool_name,
|
|
343
|
+
description=description,
|
|
344
|
+
service_id=service.id,
|
|
345
|
+
commands=commands,
|
|
346
|
+
)
|
|
347
|
+
)
|
|
348
|
+
|
|
349
|
+
return st
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import pytest
|
|
2
|
+
from pydantic import BaseModel
|
|
3
|
+
|
|
4
|
+
from meshagent.api.messaging import JsonResponse
|
|
5
|
+
from meshagent.tools import Toolkit, ToolContext, tool
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class Payload(BaseModel):
|
|
9
|
+
name: str
|
|
10
|
+
count: int
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class Result(BaseModel):
|
|
14
|
+
name: str
|
|
15
|
+
count: int
|
|
16
|
+
flag: bool
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
@tool(name="make_payload")
|
|
20
|
+
async def make_payload(context: ToolContext, payload: Payload, flag: bool):
|
|
21
|
+
return Result(name=payload.name, count=payload.count, flag=flag)
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
@pytest.mark.asyncio
|
|
25
|
+
async def test_decorated_tool_executes_with_toolkit():
|
|
26
|
+
toolkit = Toolkit(name="test", tools=[make_payload])
|
|
27
|
+
context = ToolContext(room=object(), caller=object())
|
|
28
|
+
|
|
29
|
+
result = await toolkit.execute(
|
|
30
|
+
context=context,
|
|
31
|
+
name="make_payload",
|
|
32
|
+
arguments={"payload": {"name": "alpha", "count": 2}, "flag": True},
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
assert isinstance(result, JsonResponse)
|
|
36
|
+
assert result.json == {"name": "alpha", "count": 2, "flag": True}
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def test_decorator_schema_is_strict():
|
|
40
|
+
schema = make_payload.input_schema
|
|
41
|
+
|
|
42
|
+
assert schema["type"] == "object"
|
|
43
|
+
assert schema["additionalProperties"] is False
|
|
44
|
+
assert "payload" in schema["properties"]
|
|
45
|
+
assert "flag" in schema["properties"]
|
|
@@ -3,9 +3,15 @@ from meshagent.api.participant import Participant
|
|
|
3
3
|
import logging
|
|
4
4
|
from abc import ABC
|
|
5
5
|
|
|
6
|
-
from typing import Optional, Dict, Any, Callable
|
|
6
|
+
from typing import Optional, Dict, Any, Callable, get_type_hints
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
import inspect
|
|
9
|
+
|
|
10
|
+
from pydantic import BaseModel, create_model
|
|
11
|
+
|
|
12
|
+
from meshagent.tools.strict_schema import ensure_strict_json_schema
|
|
13
|
+
|
|
14
|
+
from meshagent.api.messaging import Response, ensure_response
|
|
9
15
|
|
|
10
16
|
|
|
11
17
|
from opentelemetry import trace
|
|
@@ -117,5 +123,84 @@ class Tool(BaseTool):
|
|
|
117
123
|
if defs is not None:
|
|
118
124
|
openai_schema["$defs"] = {**defs}
|
|
119
125
|
|
|
126
|
+
async def invoke(
|
|
127
|
+
self, context: ToolContext, arguments: dict, attachment: Optional[bytes] = None
|
|
128
|
+
) -> Response:
|
|
129
|
+
return await self.execute(context=context, **arguments)
|
|
130
|
+
|
|
120
131
|
async def execute(self, context: ToolContext, **kwargs) -> Response:
|
|
121
132
|
raise (Exception("Not implemented"))
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
def tool(
|
|
136
|
+
*,
|
|
137
|
+
name: Optional[str] = None,
|
|
138
|
+
title: Optional[str] = None,
|
|
139
|
+
description: Optional[str] = None,
|
|
140
|
+
rules: Optional[list[str]] = None,
|
|
141
|
+
thumbnail_url: Optional[str] = None,
|
|
142
|
+
):
|
|
143
|
+
def decorator(fn: Callable[..., Response]):
|
|
144
|
+
signature = inspect.signature(fn)
|
|
145
|
+
hints = get_type_hints(fn, include_extras=True)
|
|
146
|
+
|
|
147
|
+
supports_context = False
|
|
148
|
+
fields: dict[str, tuple[Any, Any]] = {}
|
|
149
|
+
|
|
150
|
+
for param_name, param in signature.parameters.items():
|
|
151
|
+
annotation = hints.get(param_name, Any)
|
|
152
|
+
if annotation is ToolContext:
|
|
153
|
+
supports_context = True
|
|
154
|
+
continue
|
|
155
|
+
|
|
156
|
+
default = param.default if param.default is not inspect._empty else ...
|
|
157
|
+
fields[param_name] = (annotation, default)
|
|
158
|
+
|
|
159
|
+
InputModel = create_model(f"{fn.__name__}Input", **fields)
|
|
160
|
+
schema = InputModel.model_json_schema()
|
|
161
|
+
strict_schema = ensure_strict_json_schema(schema)
|
|
162
|
+
|
|
163
|
+
tool_name = name or fn.__name__
|
|
164
|
+
tool_title = title or tool_name
|
|
165
|
+
tool_description = (
|
|
166
|
+
description if description is not None else (fn.__doc__ or "").strip()
|
|
167
|
+
)
|
|
168
|
+
|
|
169
|
+
class FunctionTool(Tool):
|
|
170
|
+
def __init__(self):
|
|
171
|
+
super().__init__(
|
|
172
|
+
name=tool_name,
|
|
173
|
+
title=tool_title,
|
|
174
|
+
description=tool_description,
|
|
175
|
+
rules=rules,
|
|
176
|
+
thumbnail_url=thumbnail_url,
|
|
177
|
+
input_schema=strict_schema,
|
|
178
|
+
supports_context=supports_context,
|
|
179
|
+
)
|
|
180
|
+
self.strict = True
|
|
181
|
+
|
|
182
|
+
async def invoke(
|
|
183
|
+
self,
|
|
184
|
+
context: ToolContext,
|
|
185
|
+
arguments: dict,
|
|
186
|
+
attachment: Optional[bytes] = None,
|
|
187
|
+
) -> Response:
|
|
188
|
+
data = InputModel.model_validate(arguments)
|
|
189
|
+
parsed_args = {field: getattr(data, field) for field in fields}
|
|
190
|
+
|
|
191
|
+
if supports_context:
|
|
192
|
+
result = fn(context, **parsed_args)
|
|
193
|
+
else:
|
|
194
|
+
result = fn(**parsed_args)
|
|
195
|
+
|
|
196
|
+
if inspect.isawaitable(result):
|
|
197
|
+
result = await result
|
|
198
|
+
|
|
199
|
+
if isinstance(result, BaseModel):
|
|
200
|
+
result = result.model_dump(mode="json")
|
|
201
|
+
|
|
202
|
+
return ensure_response(result)
|
|
203
|
+
|
|
204
|
+
return FunctionTool()
|
|
205
|
+
|
|
206
|
+
return decorator
|
|
@@ -8,7 +8,7 @@ import json
|
|
|
8
8
|
|
|
9
9
|
from typing import Optional, Literal
|
|
10
10
|
from meshagent.tools.config import ToolkitConfig
|
|
11
|
-
from meshagent.tools.tool import ToolContext, BaseTool
|
|
11
|
+
from meshagent.tools.tool import ToolContext, BaseTool, Tool
|
|
12
12
|
|
|
13
13
|
from opentelemetry import trace
|
|
14
14
|
|
|
@@ -91,7 +91,12 @@ class Toolkit(ToolkitBuilder):
|
|
|
91
91
|
schema["$defs"] = {**tool.defs}
|
|
92
92
|
|
|
93
93
|
validate(arguments, schema)
|
|
94
|
-
|
|
94
|
+
if isinstance(tool, Tool):
|
|
95
|
+
response = await tool.invoke(
|
|
96
|
+
context=context, arguments=arguments, attachment=attachment
|
|
97
|
+
)
|
|
98
|
+
else:
|
|
99
|
+
raise RoomException("tools must extend the Tool class to be invokable")
|
|
95
100
|
response = ensure_response(response)
|
|
96
101
|
|
|
97
102
|
span.set_attribute("response_type", response.to_json()["type"])
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "0.25.0"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: meshagent-tools
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.25.0
|
|
4
4
|
Summary: Tools for Meshagent
|
|
5
5
|
License-Expression: Apache-2.0
|
|
6
6
|
Project-URL: Documentation, https://docs.meshagent.com
|
|
@@ -12,8 +12,8 @@ License-File: LICENSE
|
|
|
12
12
|
Requires-Dist: pyjwt~=2.10
|
|
13
13
|
Requires-Dist: pytest~=8.4
|
|
14
14
|
Requires-Dist: pytest-asyncio~=0.26
|
|
15
|
-
Requires-Dist: meshagent-api~=0.
|
|
16
|
-
Requires-Dist: aiohttp~=3.
|
|
15
|
+
Requires-Dist: meshagent-api~=0.25.0
|
|
16
|
+
Requires-Dist: aiohttp[speedups]~=3.13.0
|
|
17
17
|
Requires-Dist: opentelemetry-distro~=0.54b1
|
|
18
18
|
Dynamic: license-file
|
|
19
19
|
|
|
@@ -21,6 +21,7 @@ meshagent/tools/toolkit.py
|
|
|
21
21
|
meshagent/tools/uuid.py
|
|
22
22
|
meshagent/tools/version.py
|
|
23
23
|
meshagent/tools/web_toolkit.py
|
|
24
|
+
meshagent/tools/tests/tool_decorator_test.py
|
|
24
25
|
meshagent_tools.egg-info/PKG-INFO
|
|
25
26
|
meshagent_tools.egg-info/SOURCES.txt
|
|
26
27
|
meshagent_tools.egg-info/dependency_links.txt
|
|
@@ -12,8 +12,8 @@ dependencies = [
|
|
|
12
12
|
"pyjwt~=2.10",
|
|
13
13
|
"pytest~=8.4",
|
|
14
14
|
"pytest-asyncio~=0.26",
|
|
15
|
-
"meshagent-api~=0.
|
|
16
|
-
"aiohttp~=3.
|
|
15
|
+
"meshagent-api~=0.25.0",
|
|
16
|
+
"aiohttp[speedups]~=3.13.0",
|
|
17
17
|
"opentelemetry-distro~=0.54b1"
|
|
18
18
|
]
|
|
19
19
|
dynamic = ["version", "readme"]
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = "0.24.5"
|
|
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_tools-0.24.5 → meshagent_tools-0.25.0}/meshagent_tools.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|