beamlit 0.0.29rc26__py3-none-any.whl → 0.0.29rc28__py3-none-any.whl
Sign up to get free protection for your applications and to get access to all the features.
- beamlit/agents/decorator.py +10 -4
- beamlit/authentication/authentication.py +1 -1
- beamlit/functions/mcp/mcp.py +26 -18
- beamlit/functions/remote/remote.py +39 -37
- {beamlit-0.0.29rc26.dist-info → beamlit-0.0.29rc28.dist-info}/METADATA +1 -1
- {beamlit-0.0.29rc26.dist-info → beamlit-0.0.29rc28.dist-info}/RECORD +7 -7
- {beamlit-0.0.29rc26.dist-info → beamlit-0.0.29rc28.dist-info}/WHEEL +0 -0
beamlit/agents/decorator.py
CHANGED
@@ -17,16 +17,18 @@ from langchain_core.tools import Tool
|
|
17
17
|
from langgraph.checkpoint.memory import MemorySaver
|
18
18
|
from langgraph.prebuilt import create_react_agent
|
19
19
|
|
20
|
-
from .chat import get_chat_model
|
21
20
|
from .chain import ChainToolkit
|
21
|
+
from .chat import get_chat_model
|
22
|
+
|
22
23
|
|
23
|
-
def get_functions(dir="src/functions", from_decorator="function"):
|
24
|
+
def get_functions(dir="src/functions", from_decorator="function", remote_functions_empty=True):
|
24
25
|
functions = []
|
25
26
|
logger = getLogger(__name__)
|
26
27
|
|
27
28
|
# Walk through all Python files in functions directory and subdirectories
|
28
29
|
if not os.path.exists(dir):
|
29
|
-
|
30
|
+
if remote_functions_empty:
|
31
|
+
logger.warn(f"Functions directory {dir} not found")
|
30
32
|
return []
|
31
33
|
for root, _, files in os.walk(dir):
|
32
34
|
for file in files:
|
@@ -74,6 +76,7 @@ def get_functions(dir="src/functions", from_decorator="function"):
|
|
74
76
|
kit_functions = get_functions(
|
75
77
|
dir=os.path.join(root),
|
76
78
|
from_decorator="kit",
|
79
|
+
remote_functions_empty=remote_functions_empty,
|
77
80
|
)
|
78
81
|
functions.extend(kit_functions)
|
79
82
|
|
@@ -134,7 +137,10 @@ def agent(
|
|
134
137
|
return wrapped
|
135
138
|
|
136
139
|
# Initialize functions array to store decorated functions
|
137
|
-
functions = get_functions(
|
140
|
+
functions = get_functions(
|
141
|
+
dir=settings.agent.functions_directory,
|
142
|
+
remote_functions_empty=not remote_functions,
|
143
|
+
)
|
138
144
|
settings.agent.functions = functions
|
139
145
|
|
140
146
|
if agent is not None:
|
@@ -80,7 +80,7 @@ def new_client_with_credentials(config: RunClientWithCredentials):
|
|
80
80
|
|
81
81
|
def get_authentication_headers(settings: Settings) -> Dict[str, str]:
|
82
82
|
context = current_context()
|
83
|
-
if context.workspace:
|
83
|
+
if context.workspace and not settings.authentication.client.credentials:
|
84
84
|
credentials = load_credentials(context.workspace)
|
85
85
|
else:
|
86
86
|
settings = get_settings()
|
beamlit/functions/mcp/mcp.py
CHANGED
@@ -11,26 +11,35 @@ from beamlit.authentication.authentication import AuthenticatedClient
|
|
11
11
|
from beamlit.common.settings import get_settings
|
12
12
|
from langchain_core.tools.base import BaseTool, BaseToolkit, ToolException
|
13
13
|
from mcp import ListToolsResult
|
14
|
-
from pydantic.json_schema import JsonSchemaValue
|
15
|
-
from pydantic_core import core_schema as cs
|
16
14
|
|
17
15
|
settings = get_settings()
|
18
16
|
|
17
|
+
def create_dynamic_schema(name: str, schema: dict[str, t.Any]) -> type[pydantic.BaseModel]:
|
18
|
+
field_definitions = {}
|
19
|
+
for k, v in schema["properties"].items():
|
20
|
+
field_type = str
|
21
|
+
if v["type"] == "number":
|
22
|
+
field_type = float
|
23
|
+
elif v["type"] == "integer":
|
24
|
+
field_type = int
|
25
|
+
elif v["type"] == "boolean":
|
26
|
+
field_type = bool
|
27
|
+
description = v.get("description") or ""
|
28
|
+
default_ = v.get("default")
|
29
|
+
fields = {}
|
30
|
+
if default_ is not None:
|
31
|
+
fields["default"] = default_
|
32
|
+
if description is not None:
|
33
|
+
fields["description"] = description
|
34
|
+
field_definitions[k] = (
|
35
|
+
field_type,
|
36
|
+
pydantic.Field(**fields)
|
37
|
+
)
|
38
|
+
return pydantic.create_model(
|
39
|
+
f"{name}Schema",
|
40
|
+
**field_definitions
|
41
|
+
)
|
19
42
|
|
20
|
-
def create_schema_model(schema: dict[str, t.Any]) -> type[pydantic.BaseModel]:
|
21
|
-
# Create a new model class that returns our JSON schema.
|
22
|
-
# LangChain requires a BaseModel class.
|
23
|
-
class Schema(pydantic.BaseModel):
|
24
|
-
model_config = pydantic.ConfigDict(extra="allow")
|
25
|
-
|
26
|
-
@t.override
|
27
|
-
@classmethod
|
28
|
-
def __get_pydantic_json_schema__(
|
29
|
-
cls, core_schema: cs.CoreSchema, handler: pydantic.GetJsonSchemaHandler
|
30
|
-
) -> JsonSchemaValue:
|
31
|
-
return schema
|
32
|
-
|
33
|
-
return Schema
|
34
43
|
|
35
44
|
|
36
45
|
class MCPClient:
|
@@ -42,7 +51,6 @@ class MCPClient:
|
|
42
51
|
def list_tools(self) -> requests.Response:
|
43
52
|
client = self.client.get_httpx_client()
|
44
53
|
url = urllib.parse.urljoin(settings.mcp_hub_url, f"{self.server_name}/tools/list")
|
45
|
-
|
46
54
|
response = client.request("GET", url, headers=self.headers)
|
47
55
|
response.raise_for_status()
|
48
56
|
return response
|
@@ -118,7 +126,7 @@ class MCPToolkit(BaseToolkit):
|
|
118
126
|
client=self.client,
|
119
127
|
name=tool.name,
|
120
128
|
description=tool.description or "",
|
121
|
-
args_schema=
|
129
|
+
args_schema=create_dynamic_schema(tool.name, tool.inputSchema),
|
122
130
|
)
|
123
131
|
# list_tools returns a PaginatedResult, but I don't see a way to pass the cursor to retrieve more tools
|
124
132
|
for tool in self._tools.tools
|
@@ -1,46 +1,37 @@
|
|
1
1
|
import asyncio
|
2
2
|
import warnings
|
3
|
-
from
|
3
|
+
from dataclasses import dataclass
|
4
|
+
from typing import Callable, Literal
|
4
5
|
|
5
6
|
import pydantic
|
6
7
|
import typing_extensions as t
|
7
|
-
from dataclasses import dataclass
|
8
8
|
from beamlit.api.functions import get_function
|
9
9
|
from beamlit.authentication.authentication import AuthenticatedClient
|
10
|
-
from beamlit.run import RunClient
|
11
10
|
from beamlit.common.settings import get_settings
|
12
11
|
from beamlit.models import Function, StoreFunctionParameter
|
12
|
+
from beamlit.run import RunClient
|
13
13
|
from langchain_core.tools.base import BaseTool, ToolException
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
schema["properties"][parameter.name] = {
|
36
|
-
"type": parameter.type_,
|
37
|
-
"description": parameter.description,
|
38
|
-
}
|
39
|
-
if parameter.required:
|
40
|
-
schema["required"].append(parameter.name)
|
41
|
-
return schema
|
42
|
-
|
43
|
-
return Schema
|
14
|
+
|
15
|
+
|
16
|
+
def create_dynamic_schema(name: str, parameters: list[StoreFunctionParameter]) -> type[pydantic.BaseModel]:
|
17
|
+
field_definitions = {}
|
18
|
+
for param in parameters:
|
19
|
+
field_type = str
|
20
|
+
if param.type_ == "number":
|
21
|
+
field_type = float
|
22
|
+
elif param.type_ == "integer":
|
23
|
+
field_type = int
|
24
|
+
elif param.type_ == "boolean":
|
25
|
+
field_type = bool
|
26
|
+
|
27
|
+
field_definitions[param.name] = (
|
28
|
+
field_type,
|
29
|
+
pydantic.Field(description=param.description or "")
|
30
|
+
)
|
31
|
+
return pydantic.create_model(
|
32
|
+
f"{name}Schema",
|
33
|
+
**field_definitions
|
34
|
+
)
|
44
35
|
|
45
36
|
|
46
37
|
class RemoteTool(BaseTool):
|
@@ -49,6 +40,8 @@ class RemoteTool(BaseTool):
|
|
49
40
|
"""
|
50
41
|
|
51
42
|
client: RunClient
|
43
|
+
resource_name: str
|
44
|
+
kit: bool = False
|
52
45
|
handle_tool_error: bool | str | Callable[[ToolException], str] | None = True
|
53
46
|
|
54
47
|
@t.override
|
@@ -62,12 +55,15 @@ class RemoteTool(BaseTool):
|
|
62
55
|
@t.override
|
63
56
|
async def _arun(self, *args: t.Any, **kwargs: t.Any) -> t.Any:
|
64
57
|
settings = get_settings()
|
58
|
+
body = {**kwargs}
|
59
|
+
if self.kit:
|
60
|
+
body["name"] = self.name
|
65
61
|
result = self.client.run(
|
66
62
|
"function",
|
67
|
-
self.
|
63
|
+
self.resource_name,
|
68
64
|
settings.environment,
|
69
65
|
"POST",
|
70
|
-
|
66
|
+
json=body
|
71
67
|
)
|
72
68
|
return result.text
|
73
69
|
|
@@ -104,8 +100,10 @@ class RemoteToolkit:
|
|
104
100
|
RemoteTool(
|
105
101
|
client=RunClient(self.client),
|
106
102
|
name=func.name,
|
103
|
+
resource_name=self._function.metadata.name,
|
104
|
+
kit=True,
|
107
105
|
description=func.description or "",
|
108
|
-
args_schema=
|
106
|
+
args_schema=create_dynamic_schema(func.name, func.parameters),
|
109
107
|
)
|
110
108
|
for func in self._function.spec.kit
|
111
109
|
]
|
@@ -114,7 +112,11 @@ class RemoteToolkit:
|
|
114
112
|
RemoteTool(
|
115
113
|
client=RunClient(self.client),
|
116
114
|
name=self._function.metadata.name,
|
115
|
+
resource_name=self._function.metadata.name,
|
117
116
|
description=self._function.spec.description or "",
|
118
|
-
args_schema=
|
117
|
+
args_schema=create_dynamic_schema(
|
118
|
+
self._function.metadata.name,
|
119
|
+
self._function.spec.parameters
|
120
|
+
),
|
119
121
|
)
|
120
122
|
]
|
@@ -7,7 +7,7 @@ beamlit/types.py,sha256=E1hhDh_zXfsSQ0NCt9-uw90_Mr5iIlsdfnfvxv5HarU,1005
|
|
7
7
|
beamlit/agents/__init__.py,sha256=nf1iwQwGtCG6nDqyVhxfWoqR6dv6X3bvSpCeqkTCFaM,101
|
8
8
|
beamlit/agents/chain.py,sha256=HzBs3nI4xaH86I_r-M-HGGp6roXsJxMx-qXl_GrJaY0,2831
|
9
9
|
beamlit/agents/chat.py,sha256=gVyv4FGBdQTDhdutX8l64OUNa6Fdqaw4eCfEDRH0IPQ,3558
|
10
|
-
beamlit/agents/decorator.py,sha256=
|
10
|
+
beamlit/agents/decorator.py,sha256=4KxPcu6hPoB__1OdzpEJVD5N3QVa_syKd_Y6n6lVEjQ,9715
|
11
11
|
beamlit/api/__init__.py,sha256=zTSiG_ujSjAqWPyc435YXaX9XTlpMjiJWBbV-f-YtdA,45
|
12
12
|
beamlit/api/agents/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
13
13
|
beamlit/api/agents/create_agent.py,sha256=t5Pr62My2EhQlcIY71MrI73-0_q5Djr3a_Ybt9MIiQQ,3587
|
@@ -124,7 +124,7 @@ beamlit/api/workspaces/update_workspace.py,sha256=qa5DV2UJSUYuB_ibALb4E9ghKpT1Ha
|
|
124
124
|
beamlit/api/workspaces/update_workspace_user_role.py,sha256=Yn9iuJ4tKtauzBiJyU4-wYUMS9g98X2Om8zs7UkzrY8,4917
|
125
125
|
beamlit/authentication/__init__.py,sha256=wiXqRbc7E-ulrH_ueA9duOGFvXeo7-RvhSD1XbFogMo,1020
|
126
126
|
beamlit/authentication/apikey.py,sha256=KNBTgdi0VBzBAAmSwU2X1QoB58vRbg8wkXb8-GTZCQo,657
|
127
|
-
beamlit/authentication/authentication.py,sha256=
|
127
|
+
beamlit/authentication/authentication.py,sha256=ZH3zS7PVa9kw8szZTplwZvCbhBJ-oXHsxEtnAhKjxzM,3409
|
128
128
|
beamlit/authentication/clientcredentials.py,sha256=cxZPPu--CgizwqX0pdfFQ91gJt1EFKwyy-aBB_dXX7I,3990
|
129
129
|
beamlit/authentication/credentials.py,sha256=p_1xenabCbQuRz7BiFk7oTK4uCxAt_zoyku5o-jcKGE,5343
|
130
130
|
beamlit/authentication/device_mode.py,sha256=tmr22gllKOZwBRub_QjF5pYa425x-nE8tQNpZ_EGR6g,3644
|
@@ -147,8 +147,8 @@ beamlit/functions/github/kit/__init__.py,sha256=jBwPqZv6C23_utukohxqXZwrlicNlI7P
|
|
147
147
|
beamlit/functions/github/kit/pull_request.py,sha256=wQVeRBakiqu-2ouflO8p1z7D5u07KNsitwyNRrp0KjM,1357
|
148
148
|
beamlit/functions/math/__init__.py,sha256=wie4WME8jT-WpFRrtu-lDlHW31Mg6K2cwstjkUdLF3o,43
|
149
149
|
beamlit/functions/math/math.py,sha256=CpoLJGwuvwCPGnVC8k9GYuIyvfUYPDQHKlZg3cx-z-A,1049
|
150
|
-
beamlit/functions/mcp/mcp.py,sha256=
|
151
|
-
beamlit/functions/remote/remote.py,sha256=
|
150
|
+
beamlit/functions/mcp/mcp.py,sha256=gXzvUPAKmvGQPHUKTVzMiINukxpw1BV6H8M2iOWvIGU,4348
|
151
|
+
beamlit/functions/remote/remote.py,sha256=x2eHh4oYkWwHuZWwg5XeylY-E9Opa6SzfN_0396ePZw,3775
|
152
152
|
beamlit/functions/search/__init__.py,sha256=5NAthQ9PBwrkNg1FpLRx4flauvv0HyWuwaVS589c1Pw,49
|
153
153
|
beamlit/functions/search/search.py,sha256=8s9ECltq7YE17j6rTxb12uY2EQY4_eTLHmwlIMThI0w,515
|
154
154
|
beamlit/models/__init__.py,sha256=O16oX1-oBJqB5LZEHAfu_hZZZh6_PX2LqZpVl4fNQRs,7730
|
@@ -254,6 +254,6 @@ beamlit/serve/app.py,sha256=OpwPjRdyHZK6J-ziPwhiRDGGa2mvCrFVcBFE6alJVOM,3071
|
|
254
254
|
beamlit/serve/middlewares/__init__.py,sha256=1dVmnOmhAQWvWktqHkKSIX-YoF6fmMU8xkUQuhg_rJU,148
|
255
255
|
beamlit/serve/middlewares/accesslog.py,sha256=Mu4T4_9OvHybjA0ApzZFpgi2C8f3X1NbUk-76v634XM,631
|
256
256
|
beamlit/serve/middlewares/processtime.py,sha256=lDAaIasZ4bwvN-HKHvZpaD9r-yrkVNZYx4abvbjbrCg,411
|
257
|
-
beamlit-0.0.
|
258
|
-
beamlit-0.0.
|
259
|
-
beamlit-0.0.
|
257
|
+
beamlit-0.0.29rc28.dist-info/METADATA,sha256=UVbjc-yv-ZhbPjwVM9Ngq4A0igVBwugwKpP-EoZVodQ,2405
|
258
|
+
beamlit-0.0.29rc28.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
259
|
+
beamlit-0.0.29rc28.dist-info/RECORD,,
|
File without changes
|