mbxai 0.5.3__tar.gz → 0.5.5__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.3 → mbxai-0.5.5}/.vscode/PythonImportHelper-v2-Completion.json +27 -34
- {mbxai-0.5.3 → mbxai-0.5.5}/PKG-INFO +1 -1
- {mbxai-0.5.3 → mbxai-0.5.5}/pyproject.toml +1 -1
- {mbxai-0.5.3 → mbxai-0.5.5}/setup.py +1 -1
- {mbxai-0.5.3 → mbxai-0.5.5}/src/mbxai/__init__.py +1 -1
- {mbxai-0.5.3 → mbxai-0.5.5}/src/mbxai/mcp/client.py +6 -3
- {mbxai-0.5.3 → mbxai-0.5.5}/src/mbxai/mcp/server.py +1 -1
- {mbxai-0.5.3 → mbxai-0.5.5}/src/mbxai/tools/client.py +14 -10
- {mbxai-0.5.3 → mbxai-0.5.5}/src/mbxai/tools/types.py +8 -11
- {mbxai-0.5.3 → mbxai-0.5.5}/tests/test_tools.py +38 -5
- {mbxai-0.5.3 → mbxai-0.5.5}/uv.lock +7 -7
- {mbxai-0.5.3 → mbxai-0.5.5}/LICENSE +0 -0
- {mbxai-0.5.3 → mbxai-0.5.5}/README.md +0 -0
- {mbxai-0.5.3 → mbxai-0.5.5}/src/mbxai/core.py +0 -0
- {mbxai-0.5.3 → mbxai-0.5.5}/src/mbxai/mcp/__init__.py +0 -0
- {mbxai-0.5.3 → mbxai-0.5.5}/src/mbxai/mcp/example.py +0 -0
- {mbxai-0.5.3 → mbxai-0.5.5}/src/mbxai/openrouter/__init__.py +0 -0
- {mbxai-0.5.3 → mbxai-0.5.5}/src/mbxai/openrouter/client.py +0 -0
- {mbxai-0.5.3 → mbxai-0.5.5}/src/mbxai/openrouter/config.py +0 -0
- {mbxai-0.5.3 → mbxai-0.5.5}/src/mbxai/openrouter/models.py +0 -0
- {mbxai-0.5.3 → mbxai-0.5.5}/src/mbxai/tools/__init__.py +0 -0
- {mbxai-0.5.3 → mbxai-0.5.5}/src/mbxai/tools/example.py +0 -0
- {mbxai-0.5.3 → mbxai-0.5.5}/tests/test_core.py +0 -0
- {mbxai-0.5.3 → mbxai-0.5.5}/tests/test_mcp.py +0 -0
- {mbxai-0.5.3 → mbxai-0.5.5}/tests/test_openrouter.py +0 -0
@@ -187,22 +187,6 @@
|
|
187
187
|
"detail": "typing",
|
188
188
|
"documentation": {}
|
189
189
|
},
|
190
|
-
{
|
191
|
-
"label": "TypedDict",
|
192
|
-
"importPath": "typing",
|
193
|
-
"description": "typing",
|
194
|
-
"isExtraImport": true,
|
195
|
-
"detail": "typing",
|
196
|
-
"documentation": {}
|
197
|
-
},
|
198
|
-
{
|
199
|
-
"label": "NotRequired",
|
200
|
-
"importPath": "typing",
|
201
|
-
"description": "typing",
|
202
|
-
"isExtraImport": true,
|
203
|
-
"detail": "typing",
|
204
|
-
"documentation": {}
|
205
|
-
},
|
206
190
|
{
|
207
191
|
"label": "Any",
|
208
192
|
"importPath": "typing",
|
@@ -592,14 +576,6 @@
|
|
592
576
|
"detail": "mbxai.openrouter",
|
593
577
|
"documentation": {}
|
594
578
|
},
|
595
|
-
{
|
596
|
-
"label": "OpenRouterModel",
|
597
|
-
"importPath": "mbxai.openrouter",
|
598
|
-
"description": "mbxai.openrouter",
|
599
|
-
"isExtraImport": true,
|
600
|
-
"detail": "mbxai.openrouter",
|
601
|
-
"documentation": {}
|
602
|
-
},
|
603
579
|
{
|
604
580
|
"label": "load_dotenv",
|
605
581
|
"importPath": "dotenv",
|
@@ -632,6 +608,14 @@
|
|
632
608
|
"detail": "mbxai.tools",
|
633
609
|
"documentation": {}
|
634
610
|
},
|
611
|
+
{
|
612
|
+
"label": "ToolCall",
|
613
|
+
"importPath": "mbxai.tools",
|
614
|
+
"description": "mbxai.tools",
|
615
|
+
"isExtraImport": true,
|
616
|
+
"detail": "mbxai.tools",
|
617
|
+
"documentation": {}
|
618
|
+
},
|
635
619
|
{
|
636
620
|
"label": "setup",
|
637
621
|
"importPath": "setuptools",
|
@@ -900,6 +884,15 @@
|
|
900
884
|
"detail": "src.mbxai.tools.client",
|
901
885
|
"documentation": {}
|
902
886
|
},
|
887
|
+
{
|
888
|
+
"label": "logger",
|
889
|
+
"kind": 5,
|
890
|
+
"importPath": "src.mbxai.tools.client",
|
891
|
+
"description": "src.mbxai.tools.client",
|
892
|
+
"peekOfCode": "logger = logging.getLogger(__name__)\nT = TypeVar(\"T\", bound=BaseModel)\nclass ToolClient:\n \"\"\"Client for handling tool calls with OpenRouter.\"\"\"\n def __init__(self, openrouter_client: OpenRouterClient) -> None:\n \"\"\"Initialize the ToolClient.\n Args:\n openrouter_client: The OpenRouter client to use\n \"\"\"\n self._client = openrouter_client",
|
893
|
+
"detail": "src.mbxai.tools.client",
|
894
|
+
"documentation": {}
|
895
|
+
},
|
903
896
|
{
|
904
897
|
"label": "T",
|
905
898
|
"kind": 5,
|
@@ -936,15 +929,6 @@
|
|
936
929
|
"detail": "src.mbxai.tools.example",
|
937
930
|
"documentation": {}
|
938
931
|
},
|
939
|
-
{
|
940
|
-
"label": "ToolFunction",
|
941
|
-
"kind": 6,
|
942
|
-
"importPath": "src.mbxai.tools.types",
|
943
|
-
"description": "src.mbxai.tools.types",
|
944
|
-
"peekOfCode": "class ToolFunction(TypedDict):\n \"\"\"OpenAI function definition for a tool.\"\"\"\n name: str\n description: str\n parameters: dict[str, Any]\nclass ToolCall(BaseModel):\n \"\"\"A tool call from the model.\"\"\"\n id: str\n name: str\n arguments: dict[str, Any]",
|
945
|
-
"detail": "src.mbxai.tools.types",
|
946
|
-
"documentation": {}
|
947
|
-
},
|
948
932
|
{
|
949
933
|
"label": "ToolCall",
|
950
934
|
"kind": 6,
|
@@ -959,7 +943,7 @@
|
|
959
943
|
"kind": 6,
|
960
944
|
"importPath": "src.mbxai.tools.types",
|
961
945
|
"description": "src.mbxai.tools.types",
|
962
|
-
"peekOfCode": "class Tool(BaseModel):\n \"\"\"A tool that can be used by the model.\"\"\"\n name: str\n description: str\n function: Callable[..., Any]\n schema: dict[str, Any]\n def to_openai_function(self) ->
|
946
|
+
"peekOfCode": "class Tool(BaseModel):\n \"\"\"A tool that can be used by the model.\"\"\"\n name: str\n description: str\n function: Callable[..., Any]\n schema: dict[str, Any]\n def to_openai_function(self) -> dict[str, Any]:\n \"\"\"Convert the tool to an OpenAI function definition.\"\"\"\n return {\n \"type\": \"function\",",
|
963
947
|
"detail": "src.mbxai.tools.types",
|
964
948
|
"documentation": {}
|
965
949
|
},
|
@@ -1332,6 +1316,15 @@
|
|
1332
1316
|
"detail": "tests.test_tools",
|
1333
1317
|
"documentation": {}
|
1334
1318
|
},
|
1319
|
+
{
|
1320
|
+
"label": "test_tool_to_openai_function",
|
1321
|
+
"kind": 2,
|
1322
|
+
"importPath": "tests.test_tools",
|
1323
|
+
"description": "tests.test_tools",
|
1324
|
+
"peekOfCode": "def test_tool_to_openai_function():\n \"\"\"Test converting a tool to OpenAI function format.\"\"\"\n # Create a test tool\n def test_function(arg1: str) -> str:\n return f\"Test: {arg1}\"\n tool = Tool(\n name=\"test_tool\",\n description=\"A test tool\",\n function=test_function,\n schema={",
|
1325
|
+
"detail": "tests.test_tools",
|
1326
|
+
"documentation": {}
|
1327
|
+
},
|
1335
1328
|
{
|
1336
1329
|
"label": "test_chat_without_tools",
|
1337
1330
|
"kind": 2,
|
@@ -24,9 +24,12 @@ class MCPTool(Tool):
|
|
24
24
|
def to_openai_function(self) -> dict[str, Any]:
|
25
25
|
"""Convert the tool to an OpenAI function definition."""
|
26
26
|
return {
|
27
|
-
"
|
28
|
-
"
|
29
|
-
|
27
|
+
"type": "function",
|
28
|
+
"function": {
|
29
|
+
"name": self.name,
|
30
|
+
"description": self.description,
|
31
|
+
"parameters": self._convert_to_openai_schema(self.input_schema)
|
32
|
+
}
|
30
33
|
}
|
31
34
|
|
32
35
|
def _convert_to_openai_schema(self, mcp_schema: dict[str, Any]) -> dict[str, Any]:
|
@@ -3,10 +3,13 @@ ToolClient implementation for MBX AI.
|
|
3
3
|
"""
|
4
4
|
|
5
5
|
from typing import Any, Callable, TypeVar, cast
|
6
|
+
import logging
|
6
7
|
from pydantic import BaseModel
|
7
8
|
from ..openrouter import OpenRouterClient
|
8
9
|
from .types import Tool, ToolCall
|
9
10
|
|
11
|
+
logger = logging.getLogger(__name__)
|
12
|
+
|
10
13
|
T = TypeVar("T", bound=BaseModel)
|
11
14
|
|
12
15
|
class ToolClient:
|
@@ -43,6 +46,7 @@ class ToolClient:
|
|
43
46
|
schema=schema,
|
44
47
|
)
|
45
48
|
self._tools[name] = tool
|
49
|
+
logger.debug(f"Registered tool: {name}")
|
46
50
|
|
47
51
|
def chat(
|
48
52
|
self,
|
@@ -65,12 +69,12 @@ class ToolClient:
|
|
65
69
|
"""
|
66
70
|
tools = [tool.to_openai_function() for tool in self._tools.values()]
|
67
71
|
|
72
|
+
if tools:
|
73
|
+
logger.debug(f"Using tools: {tools}")
|
74
|
+
kwargs["tools"] = tools
|
75
|
+
kwargs["tool_choice"] = "auto"
|
76
|
+
|
68
77
|
while True:
|
69
|
-
# Add tools to the request if we have any
|
70
|
-
if tools:
|
71
|
-
kwargs["tools"] = tools
|
72
|
-
kwargs["tool_choice"] = "auto"
|
73
|
-
|
74
78
|
# Get the model's response
|
75
79
|
response = self._client.chat_completion(
|
76
80
|
messages=messages,
|
@@ -129,12 +133,12 @@ class ToolClient:
|
|
129
133
|
"""
|
130
134
|
tools = [tool.to_openai_function() for tool in self._tools.values()]
|
131
135
|
|
136
|
+
if tools:
|
137
|
+
logger.debug(f"Using tools: {tools}")
|
138
|
+
kwargs["tools"] = tools
|
139
|
+
kwargs["tool_choice"] = "auto"
|
140
|
+
|
132
141
|
while True:
|
133
|
-
# Add tools to the request if we have any
|
134
|
-
if tools:
|
135
|
-
kwargs["tools"] = tools
|
136
|
-
kwargs["tool_choice"] = "auto"
|
137
|
-
|
138
142
|
# Get the model's response
|
139
143
|
response = self._client.chat_completion_parse(
|
140
144
|
messages=messages,
|
@@ -2,15 +2,9 @@
|
|
2
2
|
Type definitions for the tools package.
|
3
3
|
"""
|
4
4
|
|
5
|
-
from typing import Any, Callable
|
5
|
+
from typing import Any, Callable
|
6
6
|
from pydantic import BaseModel
|
7
7
|
|
8
|
-
class ToolFunction(TypedDict):
|
9
|
-
"""OpenAI function definition for a tool."""
|
10
|
-
name: str
|
11
|
-
description: str
|
12
|
-
parameters: dict[str, Any]
|
13
|
-
|
14
8
|
class ToolCall(BaseModel):
|
15
9
|
"""A tool call from the model."""
|
16
10
|
id: str
|
@@ -24,10 +18,13 @@ class Tool(BaseModel):
|
|
24
18
|
function: Callable[..., Any]
|
25
19
|
schema: dict[str, Any]
|
26
20
|
|
27
|
-
def to_openai_function(self) ->
|
21
|
+
def to_openai_function(self) -> dict[str, Any]:
|
28
22
|
"""Convert the tool to an OpenAI function definition."""
|
29
23
|
return {
|
30
|
-
"
|
31
|
-
"
|
32
|
-
|
24
|
+
"type": "function",
|
25
|
+
"function": {
|
26
|
+
"name": self.name,
|
27
|
+
"description": self.description,
|
28
|
+
"parameters": self.schema
|
29
|
+
}
|
33
30
|
}
|
@@ -1,12 +1,11 @@
|
|
1
|
-
"""
|
2
|
-
Tests for the ToolClient.
|
3
|
-
"""
|
1
|
+
"""Tests for the tools module."""
|
4
2
|
|
5
3
|
import pytest
|
6
4
|
from unittest.mock import Mock, patch
|
7
5
|
from pydantic import BaseModel
|
8
|
-
|
9
|
-
from mbxai.openrouter import OpenRouterClient
|
6
|
+
|
7
|
+
from mbxai.openrouter import OpenRouterClient
|
8
|
+
from mbxai.tools import ToolClient, Tool, ToolCall
|
10
9
|
|
11
10
|
class TestOutput(BaseModel):
|
12
11
|
"""Test output model."""
|
@@ -43,11 +42,45 @@ def test_tool_registration():
|
|
43
42
|
# Verify tool was registered
|
44
43
|
assert "test_tool" in tool_client._tools
|
45
44
|
tool = tool_client._tools["test_tool"]
|
45
|
+
assert isinstance(tool, Tool)
|
46
46
|
assert tool.name == "test_tool"
|
47
47
|
assert tool.description == "A test tool"
|
48
48
|
assert tool.function == test_function
|
49
49
|
assert tool.schema["type"] == "object"
|
50
50
|
|
51
|
+
def test_tool_to_openai_function():
|
52
|
+
"""Test converting a tool to OpenAI function format."""
|
53
|
+
# Create a test tool
|
54
|
+
def test_function(arg1: str) -> str:
|
55
|
+
return f"Test: {arg1}"
|
56
|
+
|
57
|
+
tool = Tool(
|
58
|
+
name="test_tool",
|
59
|
+
description="A test tool",
|
60
|
+
function=test_function,
|
61
|
+
schema={
|
62
|
+
"type": "object",
|
63
|
+
"properties": {
|
64
|
+
"arg1": {
|
65
|
+
"type": "string",
|
66
|
+
"description": "Test argument"
|
67
|
+
}
|
68
|
+
},
|
69
|
+
"required": ["arg1"]
|
70
|
+
}
|
71
|
+
)
|
72
|
+
|
73
|
+
# Convert to OpenAI function format
|
74
|
+
function_def = tool.to_openai_function()
|
75
|
+
|
76
|
+
# Verify the format
|
77
|
+
assert function_def["type"] == "function"
|
78
|
+
assert "function" in function_def
|
79
|
+
assert function_def["function"]["name"] == "test_tool"
|
80
|
+
assert function_def["function"]["description"] == "A test tool"
|
81
|
+
assert function_def["function"]["parameters"]["type"] == "object"
|
82
|
+
assert "arg1" in function_def["function"]["parameters"]["properties"]
|
83
|
+
|
51
84
|
def test_chat_without_tools():
|
52
85
|
"""Test chat without any tools."""
|
53
86
|
# Setup
|
@@ -292,11 +292,11 @@ wheels = [
|
|
292
292
|
|
293
293
|
[[package]]
|
294
294
|
name = "httpx-sse"
|
295
|
-
version = "0.5.
|
295
|
+
version = "0.5.5"
|
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.5.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.5-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.5"
|
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.5"
|
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.5.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.5-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
|