mbxai 0.5.7__tar.gz → 0.5.9__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.
- {mbxai-0.5.7 → mbxai-0.5.9}/.vscode/PythonImportHelper-v2-Completion.json +9 -0
- {mbxai-0.5.7 → mbxai-0.5.9}/PKG-INFO +1 -1
- {mbxai-0.5.7 → mbxai-0.5.9}/pyproject.toml +1 -1
- {mbxai-0.5.7 → mbxai-0.5.9}/setup.py +1 -1
- {mbxai-0.5.7 → mbxai-0.5.9}/src/mbxai/__init__.py +1 -1
- {mbxai-0.5.7 → mbxai-0.5.9}/src/mbxai/mcp/client.py +1 -23
- {mbxai-0.5.7 → mbxai-0.5.9}/src/mbxai/mcp/server.py +1 -1
- {mbxai-0.5.7 → mbxai-0.5.9}/src/mbxai/tools/client.py +56 -8
- {mbxai-0.5.7 → mbxai-0.5.9}/uv.lock +7 -7
- {mbxai-0.5.7 → mbxai-0.5.9}/LICENSE +0 -0
- {mbxai-0.5.7 → mbxai-0.5.9}/README.md +0 -0
- {mbxai-0.5.7 → mbxai-0.5.9}/src/mbxai/core.py +0 -0
- {mbxai-0.5.7 → mbxai-0.5.9}/src/mbxai/mcp/__init__.py +0 -0
- {mbxai-0.5.7 → mbxai-0.5.9}/src/mbxai/mcp/example.py +0 -0
- {mbxai-0.5.7 → mbxai-0.5.9}/src/mbxai/openrouter/__init__.py +0 -0
- {mbxai-0.5.7 → mbxai-0.5.9}/src/mbxai/openrouter/client.py +0 -0
- {mbxai-0.5.7 → mbxai-0.5.9}/src/mbxai/openrouter/config.py +0 -0
- {mbxai-0.5.7 → mbxai-0.5.9}/src/mbxai/openrouter/models.py +0 -0
- {mbxai-0.5.7 → mbxai-0.5.9}/src/mbxai/tools/__init__.py +0 -0
- {mbxai-0.5.7 → mbxai-0.5.9}/src/mbxai/tools/example.py +0 -0
- {mbxai-0.5.7 → mbxai-0.5.9}/src/mbxai/tools/types.py +0 -0
- {mbxai-0.5.7 → mbxai-0.5.9}/tests/test_core.py +0 -0
- {mbxai-0.5.7 → mbxai-0.5.9}/tests/test_mcp.py +0 -0
- {mbxai-0.5.7 → mbxai-0.5.9}/tests/test_openrouter.py +0 -0
- {mbxai-0.5.7 → mbxai-0.5.9}/tests/test_tools.py +0 -0
@@ -430,6 +430,15 @@
|
|
430
430
|
"detail": "enum",
|
431
431
|
"documentation": {}
|
432
432
|
},
|
433
|
+
{
|
434
|
+
"label": "inspect",
|
435
|
+
"kind": 6,
|
436
|
+
"isExtraImport": true,
|
437
|
+
"importPath": "inspect",
|
438
|
+
"description": "inspect",
|
439
|
+
"detail": "inspect",
|
440
|
+
"documentation": {}
|
441
|
+
},
|
433
442
|
{
|
434
443
|
"label": "hello_world",
|
435
444
|
"importPath": "mbxai.core",
|
@@ -94,29 +94,7 @@ class MCPClient(ToolClient):
|
|
94
94
|
)
|
95
95
|
return response.json()
|
96
96
|
|
97
|
-
|
98
|
-
def sync_tool_function(**kwargs: Any) -> Any:
|
99
|
-
try:
|
100
|
-
# Try to get the current event loop
|
101
|
-
loop = asyncio.get_event_loop()
|
102
|
-
except RuntimeError:
|
103
|
-
# If no event loop exists, create a new one
|
104
|
-
loop = asyncio.new_event_loop()
|
105
|
-
asyncio.set_event_loop(loop)
|
106
|
-
|
107
|
-
# Check if we're already in an event loop
|
108
|
-
if loop.is_running():
|
109
|
-
# Create a new event loop for this call
|
110
|
-
new_loop = asyncio.new_event_loop()
|
111
|
-
try:
|
112
|
-
return new_loop.run_until_complete(tool_function(**kwargs))
|
113
|
-
finally:
|
114
|
-
new_loop.close()
|
115
|
-
else:
|
116
|
-
# Use the existing event loop
|
117
|
-
return loop.run_until_complete(tool_function(**kwargs))
|
118
|
-
|
119
|
-
return sync_tool_function
|
97
|
+
return tool_function
|
120
98
|
|
121
99
|
async def register_mcp_server(self, name: str, base_url: str) -> None:
|
122
100
|
"""Register an MCP server and load its tools."""
|
@@ -4,6 +4,7 @@ ToolClient implementation for MBX AI.
|
|
4
4
|
|
5
5
|
from typing import Any, Callable, TypeVar, cast
|
6
6
|
import logging
|
7
|
+
import inspect
|
7
8
|
from pydantic import BaseModel
|
8
9
|
from ..openrouter import OpenRouterClient
|
9
10
|
from .types import Tool, ToolCall
|
@@ -48,7 +49,7 @@ class ToolClient:
|
|
48
49
|
self._tools[name] = tool
|
49
50
|
logger.debug(f"Registered tool: {name}")
|
50
51
|
|
51
|
-
def chat(
|
52
|
+
async def chat(
|
52
53
|
self,
|
53
54
|
messages: list[dict[str, Any]],
|
54
55
|
*,
|
@@ -120,18 +121,41 @@ class ToolClient:
|
|
120
121
|
|
121
122
|
# Call the tool
|
122
123
|
logger.debug(f"Calling tool {tool.name} with arguments: {arguments}")
|
123
|
-
|
124
|
+
if inspect.iscoroutinefunction(tool.function):
|
125
|
+
result = await tool.function(**arguments)
|
126
|
+
else:
|
127
|
+
result = tool.function(**arguments)
|
124
128
|
logger.debug(f"Tool result: {result}")
|
125
129
|
|
126
130
|
# Add the tool response to the messages
|
127
|
-
|
131
|
+
tool_response = {
|
128
132
|
"role": "tool",
|
129
133
|
"tool_call_id": tool_call.id,
|
130
134
|
"name": tool_call.function.name,
|
131
135
|
"content": str(result),
|
132
|
-
}
|
136
|
+
}
|
137
|
+
messages.append(tool_response)
|
138
|
+
logger.debug(f"Added tool response to messages: {tool_response}")
|
133
139
|
|
134
|
-
|
140
|
+
# Get a new response from the model with the tool results
|
141
|
+
response = self._client.chat_completion(
|
142
|
+
messages=messages,
|
143
|
+
model=model,
|
144
|
+
stream=stream,
|
145
|
+
**kwargs,
|
146
|
+
)
|
147
|
+
|
148
|
+
if stream:
|
149
|
+
return response
|
150
|
+
|
151
|
+
message = response.choices[0].message
|
152
|
+
messages.append({"role": "assistant", "content": message.content})
|
153
|
+
|
154
|
+
# If there are no more tool calls, we're done
|
155
|
+
if not message.tool_calls:
|
156
|
+
return response
|
157
|
+
|
158
|
+
async def parse(
|
135
159
|
self,
|
136
160
|
messages: list[dict[str, Any]],
|
137
161
|
response_format: type[T],
|
@@ -206,13 +230,37 @@ class ToolClient:
|
|
206
230
|
|
207
231
|
# Call the tool
|
208
232
|
logger.debug(f"Calling tool {tool.name} with arguments: {arguments}")
|
209
|
-
|
233
|
+
if inspect.iscoroutinefunction(tool.function):
|
234
|
+
result = await tool.function(**arguments)
|
235
|
+
else:
|
236
|
+
result = tool.function(**arguments)
|
210
237
|
logger.debug(f"Tool result: {result}")
|
211
238
|
|
212
239
|
# Add the tool response to the messages
|
213
|
-
|
240
|
+
tool_response = {
|
214
241
|
"role": "tool",
|
215
242
|
"tool_call_id": tool_call.id,
|
216
243
|
"name": tool_call.function.name,
|
217
244
|
"content": str(result),
|
218
|
-
}
|
245
|
+
}
|
246
|
+
messages.append(tool_response)
|
247
|
+
logger.debug(f"Added tool response to messages: {tool_response}")
|
248
|
+
|
249
|
+
# Get a new response from the model with the tool results
|
250
|
+
response = self._client.chat_completion_parse(
|
251
|
+
messages=messages,
|
252
|
+
response_format=response_format,
|
253
|
+
model=model,
|
254
|
+
stream=stream,
|
255
|
+
**kwargs,
|
256
|
+
)
|
257
|
+
|
258
|
+
if stream:
|
259
|
+
return response
|
260
|
+
|
261
|
+
message = response.choices[0].message
|
262
|
+
messages.append({"role": "assistant", "content": message.content})
|
263
|
+
|
264
|
+
# If there are no more tool calls, we're done
|
265
|
+
if not message.tool_calls:
|
266
|
+
return response
|
@@ -292,11 +292,11 @@ wheels = [
|
|
292
292
|
|
293
293
|
[[package]]
|
294
294
|
name = "httpx-sse"
|
295
|
-
version = "0.5.
|
295
|
+
version = "0.5.9"
|
296
296
|
source = { registry = "https://pypi.org/simple" }
|
297
|
-
sdist = { url = "https://files.pythonhosted.org/packages/4c/60/8f4281fa9bbf3c8034fd54c0e7412e66edbab6bc74c4996bd616f8d0406e/httpx-sse-0.5.
|
297
|
+
sdist = { url = "https://files.pythonhosted.org/packages/4c/60/8f4281fa9bbf3c8034fd54c0e7412e66edbab6bc74c4996bd616f8d0406e/httpx-sse-0.5.9.tar.gz", hash = "sha256:1e81a3a3070ce322add1d3529ed42eb5f70817f45ed6ec915ab753f961139721", size = 12624 }
|
298
298
|
wheels = [
|
299
|
-
{ url = "https://files.pythonhosted.org/packages/e1/9b/a181f281f65d776426002f330c31849b86b31fc9d848db62e16f03ff739f/httpx_sse-0.5.
|
299
|
+
{ url = "https://files.pythonhosted.org/packages/e1/9b/a181f281f65d776426002f330c31849b86b31fc9d848db62e16f03ff739f/httpx_sse-0.5.9-py3-none-any.whl", hash = "sha256:f329af6eae57eaa2bdfd962b42524764af68075ea87370a2de920af5341e318f", size = 7819 },
|
300
300
|
]
|
301
301
|
|
302
302
|
[[package]]
|
@@ -446,7 +446,7 @@ wheels = [
|
|
446
446
|
|
447
447
|
[[package]]
|
448
448
|
name = "mbxai"
|
449
|
-
version = "0.5.
|
449
|
+
version = "0.5.9"
|
450
450
|
source = { editable = "." }
|
451
451
|
dependencies = [
|
452
452
|
{ name = "fastapi" },
|
@@ -980,14 +980,14 @@ wheels = [
|
|
980
980
|
|
981
981
|
[[package]]
|
982
982
|
name = "typing-inspection"
|
983
|
-
version = "0.5.
|
983
|
+
version = "0.5.9"
|
984
984
|
source = { registry = "https://pypi.org/simple" }
|
985
985
|
dependencies = [
|
986
986
|
{ name = "typing-extensions" },
|
987
987
|
]
|
988
|
-
sdist = { url = "https://files.pythonhosted.org/packages/82/5c/e6082df02e215b846b4b8c0b887a64d7d08ffaba30605502639d44c06b82/typing_inspection-0.5.
|
988
|
+
sdist = { url = "https://files.pythonhosted.org/packages/82/5c/e6082df02e215b846b4b8c0b887a64d7d08ffaba30605502639d44c06b82/typing_inspection-0.5.9.tar.gz", hash = "sha256:9765c87de36671694a67904bf2c96e395be9c6439bb6c87b5142569dcdd65122", size = 76222 }
|
989
989
|
wheels = [
|
990
|
-
{ url = "https://files.pythonhosted.org/packages/31/08/aa4fdfb71f7de5176385bd9e90852eaf6b5d622735020ad600f2bab54385/typing_inspection-0.5.
|
990
|
+
{ url = "https://files.pythonhosted.org/packages/31/08/aa4fdfb71f7de5176385bd9e90852eaf6b5d622735020ad600f2bab54385/typing_inspection-0.5.9-py3-none-any.whl", hash = "sha256:50e72559fcd2a6367a19f7a7e610e6afcb9fac940c650290eed893d61386832f", size = 14125 },
|
991
991
|
]
|
992
992
|
|
993
993
|
[[package]]
|
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
|