beamlit 0.0.34rc60__py3-none-any.whl → 0.0.34rc62__py3-none-any.whl

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.
beamlit/agents/chat.py CHANGED
@@ -1,4 +1,7 @@
1
1
  from logging import getLogger
2
+ from typing import Tuple
3
+
4
+ from langchain_core.language_models import BaseChatModel
2
5
 
3
6
  from beamlit.authentication import get_authentication_headers, new_client
4
7
  from beamlit.common.settings import get_settings
@@ -39,7 +42,7 @@ def get_cohere_chat_model(**kwargs):
39
42
 
40
43
  return ChatCohere(**kwargs)
41
44
 
42
- def get_chat_model(name: str, agent_model: Model):
45
+ def get_chat_model(name: str, agent_model: Model) -> Tuple[BaseChatModel, str, str]:
43
46
  settings = get_settings()
44
47
  client = new_client()
45
48
 
@@ -1,122 +1,20 @@
1
1
  # Import necessary modules
2
- import ast
3
- import asyncio
4
2
  import functools
5
- import importlib
6
- import os
7
3
  from logging import getLogger
8
4
 
9
- from langchain_core.tools import StructuredTool
10
5
  from langgraph.checkpoint.memory import MemorySaver
11
6
  from langgraph.prebuilt import create_react_agent
12
- from langchain_core.tools.base import create_schema_from_function
13
7
 
14
8
  from beamlit.api.models import get_model
15
9
  from beamlit.authentication import new_client
16
- from beamlit.common import slugify
17
- from beamlit.common.settings import get_settings, init
10
+ from beamlit.common.settings import init
18
11
  from beamlit.errors import UnexpectedStatus
19
- from beamlit.functions.mcp.mcp import MCPClient, MCPToolkit
20
- from beamlit.functions.remote.remote import RemoteToolkit
12
+ from beamlit.functions import get_functions
21
13
  from beamlit.models import Agent, AgentMetadata, AgentSpec
22
14
 
23
- from .chain import ChainToolkit
24
15
  from .chat import get_chat_model
25
16
 
26
17
 
27
- def get_functions(client, dir="src/functions", from_decorator="function", remote_functions_empty=True):
28
- functions = []
29
- logger = getLogger(__name__)
30
- settings = get_settings()
31
-
32
- # Walk through all Python files in functions directory and subdirectories
33
- if not os.path.exists(dir):
34
- if remote_functions_empty:
35
- logger.warn(f"Functions directory {dir} not found")
36
- return []
37
- for root, _, files in os.walk(dir):
38
- for file in files:
39
- if file.endswith(".py"):
40
- file_path = os.path.join(root, file)
41
- # Read and compile the file content
42
- with open(file_path) as f:
43
- try:
44
- file_content = f.read()
45
- # Parse the file content to find decorated functions
46
- tree = ast.parse(file_content)
47
-
48
- # Look for function definitions with decorators
49
- for node in ast.walk(tree):
50
- if (
51
- not isinstance(node, ast.FunctionDef)
52
- and not isinstance(node, ast.AsyncFunctionDef)
53
- ) or len(node.decorator_list) == 0:
54
- continue
55
- decorator = node.decorator_list[0]
56
-
57
- decorator_name = ""
58
- if isinstance(decorator, ast.Call):
59
- decorator_name = decorator.func.id
60
- if isinstance(decorator, ast.Name):
61
- decorator_name = decorator.id
62
-
63
- if decorator_name == from_decorator:
64
- # Get the function name and decorator name
65
- func_name = node.name
66
-
67
- # Import the module to get the actual function
68
- spec = importlib.util.spec_from_file_location(func_name, file_path)
69
- module = importlib.util.module_from_spec(spec)
70
- spec.loader.exec_module(module)
71
- # Check if kit=True in the decorator arguments
72
- is_kit = False
73
- if isinstance(decorator, ast.Call):
74
- for keyword in decorator.keywords:
75
- if keyword.arg == "kit" and isinstance(
76
- keyword.value, ast.Constant
77
- ):
78
- is_kit = keyword.value.value
79
- if is_kit and not settings.remote:
80
- kit_functions = get_functions(
81
- client,
82
- dir=os.path.join(root),
83
- from_decorator="kit",
84
- remote_functions_empty=remote_functions_empty,
85
- )
86
- functions.extend(kit_functions)
87
-
88
- # Get the decorated function
89
- if not is_kit and hasattr(module, func_name):
90
- func = getattr(module, func_name)
91
- if settings.remote:
92
- toolkit = RemoteToolkit(client, slugify(func.__name__))
93
- toolkit.initialize()
94
- functions.extend(toolkit.get_tools())
95
- else:
96
- if asyncio.iscoroutinefunction(func):
97
- functions.append(
98
- StructuredTool(
99
- name=func.__name__,
100
- description=func.__doc__,
101
- func=func,
102
- coroutine=func,
103
- args_schema=create_schema_from_function(func.__name__, func)
104
- )
105
- )
106
- else:
107
- functions.append(
108
- StructuredTool(
109
- name=func.__name__,
110
- description=func.__doc__,
111
- func=func,
112
- args_schema=create_schema_from_function(func.__name__, func)
113
- )
114
- )
115
- except Exception as e:
116
- logger.warning(f"Error processing {file_path}: {e!s}")
117
- return functions
118
-
119
-
120
18
  def agent(
121
19
  agent: Agent | dict = None,
122
20
  override_model=None,
@@ -148,15 +46,6 @@ def agent(
148
46
 
149
47
  return wrapped
150
48
 
151
- # Initialize functions array to store decorated functions
152
- functions = get_functions(
153
- client,
154
- dir=settings.agent.functions_directory,
155
- remote_functions_empty=not remote_functions,
156
- )
157
-
158
-
159
-
160
49
  if agent is not None:
161
50
  metadata = AgentMetadata(**agent.get("metadata", {}))
162
51
  spec = AgentSpec(**agent.get("spec", {}))
@@ -187,32 +76,16 @@ def agent(
187
76
  settings.agent.chat_model = chat_model
188
77
  logger.info(f"Chat model configured, using: {provider}:{model}")
189
78
 
190
- if mcp_hub:
191
- for server in mcp_hub:
192
- try:
193
- mcp_client = MCPClient(client, server)
194
- toolkit = MCPToolkit(client=mcp_client)
195
- toolkit.initialize()
196
- functions.extend(toolkit.get_tools())
197
- except Exception as e:
198
- logger.warn(f"Failed to initialize MCP server {server}: {e!s}")
199
-
200
- if remote_functions:
201
- for function in remote_functions:
202
- try:
203
- toolkit = RemoteToolkit(client, function)
204
- toolkit.initialize()
205
- functions.extend(toolkit.get_tools())
206
- except Exception as e:
207
- logger.warn(f"Failed to initialize remote function {function}: {e!s}")
208
-
209
- if agent.spec.agent_chain:
210
- toolkit = ChainToolkit(client, agent.spec.agent_chain)
211
- toolkit.initialize()
212
- functions.extend(toolkit.get_tools())
213
-
79
+ functions = get_functions(
80
+ client=client,
81
+ dir=settings.agent.functions_directory,
82
+ mcp_hub=mcp_hub,
83
+ remote_functions=remote_functions,
84
+ chain=agent.spec.agent_chain,
85
+ remote_functions_empty=not remote_functions,
86
+ )
214
87
  settings.agent.functions = functions
215
-
88
+
216
89
  if override_agent is None and len(functions) == 0:
217
90
  raise ValueError(
218
91
  "You must define at least one function, you can define this function in directory "
@@ -225,8 +98,8 @@ def agent(
225
98
 
226
99
  if override_agent is None and chat_model is not None:
227
100
  memory = MemorySaver()
228
- agent = create_react_agent(chat_model, functions, checkpointer=memory)
229
- settings.agent.agent = agent
101
+ _agent = create_react_agent(chat_model, functions, checkpointer=memory)
102
+ settings.agent.agent = _agent
230
103
  else:
231
104
  settings.agent.agent = override_agent
232
105
  return wrapper
@@ -6,7 +6,9 @@ import httpx
6
6
  from ... import errors
7
7
  from ...client import AuthenticatedClient, Client
8
8
  from ...models.create_workspace_service_account_body import CreateWorkspaceServiceAccountBody
9
- from ...models.create_workspace_service_account_response_200 import CreateWorkspaceServiceAccountResponse200
9
+ from ...models.create_workspace_service_account_response_200 import (
10
+ CreateWorkspaceServiceAccountResponse200,
11
+ )
10
12
  from ...types import Response
11
13
 
12
14
 
@@ -5,7 +5,9 @@ import httpx
5
5
 
6
6
  from ... import errors
7
7
  from ...client import AuthenticatedClient, Client
8
- from ...models.delete_workspace_service_account_response_200 import DeleteWorkspaceServiceAccountResponse200
8
+ from ...models.delete_workspace_service_account_response_200 import (
9
+ DeleteWorkspaceServiceAccountResponse200,
10
+ )
9
11
  from ...types import Response
10
12
 
11
13
 
@@ -5,7 +5,9 @@ import httpx
5
5
 
6
6
  from ... import errors
7
7
  from ...client import AuthenticatedClient, Client
8
- from ...models.get_workspace_service_accounts_response_200_item import GetWorkspaceServiceAccountsResponse200Item
8
+ from ...models.get_workspace_service_accounts_response_200_item import (
9
+ GetWorkspaceServiceAccountsResponse200Item,
10
+ )
9
11
  from ...types import Response
10
12
 
11
13
 
@@ -6,7 +6,9 @@ import httpx
6
6
  from ... import errors
7
7
  from ...client import AuthenticatedClient, Client
8
8
  from ...models.update_workspace_service_account_body import UpdateWorkspaceServiceAccountBody
9
- from ...models.update_workspace_service_account_response_200 import UpdateWorkspaceServiceAccountResponse200
9
+ from ...models.update_workspace_service_account_response_200 import (
10
+ UpdateWorkspaceServiceAccountResponse200,
11
+ )
10
12
  from ...types import Response
11
13
 
12
14
 
beamlit/deploy/deploy.py CHANGED
@@ -1,11 +1,17 @@
1
1
  import ast
2
2
  import json
3
3
  import os
4
+ import shutil
4
5
  import sys
5
- import uuid
6
6
  from logging import getLogger
7
+ from pathlib import Path
7
8
  from typing import Literal
8
9
 
10
+ import yaml
11
+
12
+ from beamlit.api.agents import get_agent
13
+ from beamlit.authentication import new_client
14
+ from beamlit.client import AuthenticatedClient
9
15
  from beamlit.common import slugify
10
16
  from beamlit.common.settings import Settings, get_settings, init
11
17
  from beamlit.models import (
@@ -15,26 +21,15 @@ from beamlit.models import (
15
21
  Flavor,
16
22
  Function,
17
23
  FunctionSpec,
18
- Runtime,
24
+ MetadataLabels,
19
25
  )
20
26
 
21
- from .format import arg_to_dict, format_agent_chain, format_parameters
27
+ from .format import arg_to_dict
22
28
  from .parser import Resource, get_description, get_parameters, get_resources
23
29
 
24
30
  sys.path.insert(0, os.getcwd())
25
31
  sys.path.insert(0, os.path.join(os.getcwd(), "src"))
26
32
 
27
- random_id = str(uuid.uuid4())[:8]
28
-
29
- def get_runtime_image(type: str, name: str) -> str:
30
- settings = get_settings()
31
- registry_url = settings.registry_url.replace("https://", "").replace("http://", "")
32
- image = f"{registry_url}/{settings.workspace}/{type}s/{name}"
33
- # Generate a random ID to ensure unique image tags
34
- image = f"{image}:{random_id}"
35
- return image
36
-
37
-
38
33
  def set_default_values(resource: Resource, deployment: Agent | Function):
39
34
  settings = get_settings()
40
35
  deployment.metadata.workspace = settings.workspace
@@ -45,10 +40,6 @@ def set_default_values(resource: Resource, deployment: Agent | Function):
45
40
  deployment.metadata.display_name = deployment.metadata.name
46
41
  if not deployment.spec.description:
47
42
  deployment.spec.description = get_description(None, resource)
48
- if not deployment.spec.runtime:
49
- deployment.spec.runtime = Runtime()
50
- if not deployment.spec.runtime.image:
51
- deployment.spec.runtime.image = get_runtime_image(resource.type, deployment.metadata.name)
52
43
  return deployment
53
44
 
54
45
  def get_beamlit_deployment_from_resource(
@@ -105,7 +96,7 @@ def get_flavors(flavors: list[Flavor]) -> str:
105
96
  return json.dumps([flavor.to_dict() for flavor in flavors])
106
97
 
107
98
  def get_agent_yaml(
108
- agent: Agent, functions: list[tuple[Resource, Function]], settings: Settings
99
+ agent: Agent, functions: list[tuple[Resource, Function]], settings: Settings, client: AuthenticatedClient
109
100
  ) -> str:
110
101
  """
111
102
  Generates YAML configuration for an agent deployment.
@@ -118,30 +109,24 @@ def get_agent_yaml(
118
109
  Returns:
119
110
  str: YAML configuration string
120
111
  """
112
+ try:
113
+ agent_response = get_agent.sync(agent.metadata.name, client=client)
114
+ agent.spec.repository = agent_response.spec.repository
115
+ except Exception:
116
+ pass
117
+ agent.spec.functions = [slugify(function.metadata.name) for (_, function) in functions]
118
+ agent.metadata.labels = agent.metadata.labels and MetadataLabels.from_dict(agent.metadata.labels) or MetadataLabels()
119
+ agent.metadata.labels["x-beamlit-auto-generated"] = "true"
120
+ agent_yaml = yaml.dump(agent.to_dict())
121
121
  template = f"""
122
122
  apiVersion: beamlit.com/v1alpha1
123
123
  kind: Agent
124
- metadata:
125
- name: {slugify(agent.metadata.name)}
126
- displayName: {agent.metadata.display_name or agent.metadata.name}
127
- environment: {settings.environment}
128
- workspace: {settings.workspace}
129
- labels:
130
- x-beamlit-auto-generated: "true"
131
- spec:
132
- enabled: true
133
- policies: [{", ".join(agent.spec.policies or [])}]
134
- functions: [{", ".join([f"{slugify(function.metadata.name)}" for (_, function) in functions])}]
135
- agentChain: {format_agent_chain(agent.spec.agent_chain)}
136
- model: {agent.spec.model}
124
+ {agent_yaml}
137
125
  """
138
- if agent.spec.description:
139
- template += f""" description: |
140
- {agent.spec.description}"""
141
126
  return template
142
127
 
143
128
 
144
- def get_function_yaml(function: Function, settings: Settings) -> str:
129
+ def get_function_yaml(function: Function, settings: Settings, client: AuthenticatedClient) -> str:
145
130
  """
146
131
  Generates YAML configuration for a function deployment.
147
132
 
@@ -152,21 +137,13 @@ def get_function_yaml(function: Function, settings: Settings) -> str:
152
137
  Returns:
153
138
  str: YAML configuration string
154
139
  """
140
+ function.metadata.labels = function.metadata.labels and MetadataLabels.from_dict(function.metadata.labels) or MetadataLabels()
141
+ function.metadata.labels["x-beamlit-auto-generated"] = "true"
142
+ function_yaml = yaml.dump(function.to_dict())
155
143
  return f"""
156
144
  apiVersion: beamlit.com/v1alpha1
157
145
  kind: Function
158
- metadata:
159
- name: {slugify(function.metadata.name)}
160
- displayName: {function.metadata.display_name or function.metadata.name}
161
- environment: {settings.environment}
162
- labels:
163
- x-beamlit-auto-generated: "true"
164
- spec:
165
- enabled: true
166
- policies: [{", ".join(function.spec.policies or [])}]
167
- description: |
168
- {function.spec.description}
169
- parameters: {format_parameters(function.spec.parameters)}
146
+ {function_yaml}
170
147
  """
171
148
 
172
149
 
@@ -220,6 +197,35 @@ ENV PATH="/beamlit/.venv/bin:$PATH"
220
197
  ENTRYPOINT [{cmd_str}]
221
198
  """
222
199
 
200
+ def clean_auto_generated(
201
+ directory: str,
202
+ type: Literal["agent", "function"],
203
+ deployments: list[tuple[Resource, Agent | Function]]
204
+ ):
205
+ """
206
+ Cleans up auto-generated deployments of a specific type.
207
+
208
+ Args:
209
+ directory (str): Base directory containing deployments
210
+ type (str): Type of deployment ("agent" or "function")
211
+ deployments (list[tuple[Resource, Agent | Function]]): List of deployment resources and configurations
212
+ """
213
+
214
+ deploy_dir = Path(directory) / f"{type}s"
215
+ deploy_names = [d.metadata.name for (_, d) in deployments]
216
+
217
+ if deploy_dir.exists():
218
+ for item_dir in deploy_dir.iterdir():
219
+ if item_dir.is_dir() and item_dir.name not in deploy_names:
220
+ yaml_file = item_dir / f"{type}.yaml"
221
+ if yaml_file.exists():
222
+ with open(yaml_file) as f:
223
+ try:
224
+ content = yaml.safe_load(f)
225
+ if content.get("metadata", {}).get("labels", {}).get("x-beamlit-auto-generated") == "true":
226
+ shutil.rmtree(item_dir)
227
+ except yaml.YAMLError:
228
+ continue
223
229
 
224
230
  def generate_beamlit_deployment(directory: str):
225
231
  """
@@ -234,6 +240,7 @@ def generate_beamlit_deployment(directory: str):
234
240
  - Directory structure for agents and functions
235
241
  """
236
242
  settings = init()
243
+ client = new_client()
237
244
  logger = getLogger(__name__)
238
245
  logger.info(f"Importing server module: {settings.server.module}")
239
246
  functions: list[tuple[Resource, Function]] = []
@@ -257,28 +264,23 @@ def generate_beamlit_deployment(directory: str):
257
264
  agent_dir = os.path.join(agents_dir, agent.metadata.name)
258
265
  os.makedirs(agent_dir, exist_ok=True)
259
266
  with open(os.path.join(agent_dir, "agent.yaml"), "w") as f:
260
- content = get_agent_yaml(agent, functions, settings)
267
+ content = get_agent_yaml(agent, functions, settings, client)
261
268
  f.write(content)
262
269
  # write dockerfile for build
263
270
  with open(os.path.join(agent_dir, "Dockerfile"), "w") as f:
264
271
  content = dockerfile("agent", resource, agent)
265
272
  f.write(content)
266
- # write destination docker
267
- with open(os.path.join(agent_dir, "destination.txt"), "w") as f:
268
- content = agent.spec.runtime.image
269
- f.write(content)
270
273
  for resource, function in functions:
271
274
  # write deployment file
272
275
  function_dir = os.path.join(functions_dir, function.metadata.name)
273
276
  os.makedirs(function_dir, exist_ok=True)
274
277
  with open(os.path.join(function_dir, "function.yaml"), "w") as f:
275
- content = get_function_yaml(function, settings)
278
+ content = get_function_yaml(function, settings, client)
276
279
  f.write(content)
277
280
  # write dockerfile for build
278
281
  with open(os.path.join(function_dir, "Dockerfile"), "w") as f:
279
282
  content = dockerfile("function", resource, function)
280
283
  f.write(content)
281
- # write destination docker
282
- with open(os.path.join(function_dir, "destination.txt"), "w") as f:
283
- content = function.spec.runtime.image
284
- f.write(content)
284
+
285
+ clean_auto_generated(directory, "agent", agents)
286
+ clean_auto_generated(directory, "function", functions)
beamlit/deploy/format.py CHANGED
@@ -48,6 +48,16 @@ def format_parameters(parameters: list[StoreFunctionParameter]) -> str:
48
48
 
49
49
  return "\n".join(formatted)
50
50
 
51
+ def format_dict(obj: dict) -> str:
52
+ if not obj:
53
+ return "null"
54
+ ret = ""
55
+ for k, v in obj.items():
56
+ if not v:
57
+ ret += f"{k}: null\n"
58
+ else:
59
+ ret += f"{k}: {v}\n"
60
+ return ret
51
61
 
52
62
  def format_agent_chain(agentChain: list[AgentChain]) -> str:
53
63
  """
@@ -1,5 +1,5 @@
1
1
  """Functions package providing function decorators and utilities."""
2
2
 
3
- from .decorator import function, kit
3
+ from .decorator import function, get_functions, kit
4
4
 
5
- __all__ = ["function", "kit"]
5
+ __all__ = ["function", "kit", "get_functions"]
@@ -1,15 +1,161 @@
1
1
  """Decorators for creating function tools with Beamlit and LangChain integration."""
2
+ import ast
2
3
  import asyncio
3
4
  import functools
5
+ import importlib.util
6
+ import os
4
7
  from collections.abc import Callable
5
8
  from logging import getLogger
9
+ from typing import Union
6
10
 
7
11
  from fastapi import Request
12
+ from langchain_core.tools import StructuredTool
13
+ from langchain_core.tools.base import create_schema_from_function
8
14
 
9
- from beamlit.models import Function, FunctionKit
15
+ from beamlit.agents.chain import ChainToolkit
16
+ from beamlit.authentication import new_client
17
+ from beamlit.client import AuthenticatedClient
18
+ from beamlit.common import slugify
19
+ from beamlit.common.settings import get_settings
20
+ from beamlit.functions.mcp.mcp import MCPClient, MCPToolkit
21
+ from beamlit.functions.remote.remote import RemoteToolkit
22
+ from beamlit.models import AgentChain, Function, FunctionKit
10
23
 
11
24
  logger = getLogger(__name__)
12
25
 
26
+ def get_functions(
27
+ client:Union[AuthenticatedClient, None]=None,
28
+ dir:Union[str, None]=None,
29
+ mcp_hub:Union[list[str], None]=None,
30
+ remote_functions:Union[list[str], None]=None,
31
+ chain:Union[list[AgentChain], None]=None,
32
+ remote_functions_empty:bool=True,
33
+ from_decorator:str="function",
34
+ ):
35
+ settings = get_settings()
36
+ if client is None:
37
+ client = new_client()
38
+ if dir is None:
39
+ dir = settings.agent.functions_directory
40
+
41
+ functions = []
42
+ logger = getLogger(__name__)
43
+ settings = get_settings()
44
+
45
+ # Walk through all Python files in functions directory and subdirectories
46
+ if not os.path.exists(dir):
47
+ if remote_functions_empty:
48
+ logger.warn(f"Functions directory {dir} not found")
49
+ return []
50
+ for root, _, files in os.walk(dir):
51
+ for file in files:
52
+ if file.endswith(".py"):
53
+ file_path = os.path.join(root, file)
54
+ # Read and compile the file content
55
+ with open(file_path) as f:
56
+ try:
57
+ file_content = f.read()
58
+ # Parse the file content to find decorated functions
59
+ tree = ast.parse(file_content)
60
+
61
+ # Look for function definitions with decorators
62
+ for node in ast.walk(tree):
63
+ if (
64
+ not isinstance(node, ast.FunctionDef)
65
+ and not isinstance(node, ast.AsyncFunctionDef)
66
+ ) or len(node.decorator_list) == 0:
67
+ continue
68
+ decorator = node.decorator_list[0]
69
+
70
+ decorator_name = ""
71
+ if isinstance(decorator, ast.Call):
72
+ decorator_name = decorator.func.id
73
+ if isinstance(decorator, ast.Name):
74
+ decorator_name = decorator.id
75
+ if decorator_name == from_decorator:
76
+ # Get the function name and decorator name
77
+ func_name = node.name
78
+
79
+ # Import the module to get the actual function
80
+ spec = importlib.util.spec_from_file_location(func_name, file_path)
81
+ module = importlib.util.module_from_spec(spec)
82
+ spec.loader.exec_module(module)
83
+ # Check if kit=True in the decorator arguments
84
+ is_kit = False
85
+ if isinstance(decorator, ast.Call):
86
+ for keyword in decorator.keywords:
87
+ if keyword.arg == "kit" and isinstance(
88
+ keyword.value, ast.Constant
89
+ ):
90
+ is_kit = keyword.value.value
91
+ if is_kit and not settings.remote:
92
+ kit_functions = get_functions(
93
+ client=client,
94
+ dir=os.path.join(root),
95
+ remote_functions_empty=remote_functions_empty,
96
+ from_decorator="kit",
97
+ )
98
+ functions.extend(kit_functions)
99
+
100
+ # Get the decorated function
101
+ if not is_kit and hasattr(module, func_name):
102
+ func = getattr(module, func_name)
103
+ if settings.remote:
104
+ toolkit = RemoteToolkit(client, slugify(func.__name__))
105
+ toolkit.initialize()
106
+ functions.extend(toolkit.get_tools())
107
+ else:
108
+ if asyncio.iscoroutinefunction(func):
109
+ functions.append(
110
+ StructuredTool(
111
+ name=func.__name__,
112
+ description=func.__doc__,
113
+ func=func,
114
+ coroutine=func,
115
+ args_schema=create_schema_from_function(func.__name__, func)
116
+ )
117
+ )
118
+ else:
119
+
120
+ functions.append(
121
+ StructuredTool(
122
+ name=func.__name__,
123
+ description=func.__doc__,
124
+ func=func,
125
+ args_schema=create_schema_from_function(func.__name__, func)
126
+ )
127
+ )
128
+ except Exception as e:
129
+ logger.warning(f"Error processing {file_path}: {e!s}")
130
+
131
+ if mcp_hub:
132
+ for server in mcp_hub:
133
+ try:
134
+ mcp_client = MCPClient(client, server)
135
+ toolkit = MCPToolkit(client=mcp_client)
136
+ toolkit.initialize()
137
+ functions.extend(toolkit.get_tools())
138
+ except Exception as e:
139
+ logger.warn(f"Failed to initialize MCP server {server}: {e!s}")
140
+
141
+ if remote_functions:
142
+ for function in remote_functions:
143
+ try:
144
+ toolkit = RemoteToolkit(client, function)
145
+ toolkit.initialize()
146
+ functions.extend(toolkit.get_tools())
147
+ except Exception as e:
148
+ logger.warn(f"Failed to initialize remote function {function}: {e!s}")
149
+
150
+ if chain:
151
+ toolkit = ChainToolkit(client, chain)
152
+ toolkit.initialize()
153
+ functions.extend(toolkit.get_tools())
154
+
155
+ return functions
156
+
157
+
158
+
13
159
  def kit(bl_kit: FunctionKit = None, **kwargs: dict) -> Callable:
14
160
  """Create function tools with Beamlit and LangChain integration."""
15
161
 
@@ -33,7 +33,9 @@ from .function_spec import FunctionSpec
33
33
  from .get_trace_ids_response_200 import GetTraceIdsResponse200
34
34
  from .get_trace_logs_response_200 import GetTraceLogsResponse200
35
35
  from .get_trace_response_200 import GetTraceResponse200
36
- from .get_workspace_service_accounts_response_200_item import GetWorkspaceServiceAccountsResponse200Item
36
+ from .get_workspace_service_accounts_response_200_item import (
37
+ GetWorkspaceServiceAccountsResponse200Item,
38
+ )
37
39
  from .increase_and_rate_metric import IncreaseAndRateMetric
38
40
  from .integration_config import IntegrationConfig
39
41
  from .integration_connection import IntegrationConnection
beamlit/serve/app.py CHANGED
@@ -16,8 +16,8 @@ from beamlit.common import HTTPError, get_settings, init
16
16
  from beamlit.common.instrumentation import (
17
17
  get_resource_attributes,
18
18
  get_span_exporter,
19
- shutdown_instrumentation,
20
19
  instrument_app,
20
+ shutdown_instrumentation,
21
21
  )
22
22
 
23
23
  from .middlewares import AccessLogMiddleware, AddProcessTimeHeader
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: beamlit
3
- Version: 0.0.34rc60
3
+ Version: 0.0.34rc62
4
4
  Summary: Add your description here
5
5
  Author-email: cploujoux <ch.ploujoux@gmail.com>
6
6
  Requires-Python: >=3.12
@@ -6,8 +6,8 @@ beamlit/run.py,sha256=HtDYDjD7oVfQ8r3T5_t4qN5UDJOJfsQILi45Z21ArAg,1446
6
6
  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=vfCjiFHuu02uTTGicxMlFzjyICQkIjpXrBGs-7uJEsg,2826
9
- beamlit/agents/chat.py,sha256=gVyv4FGBdQTDhdutX8l64OUNa6Fdqaw4eCfEDRH0IPQ,3558
10
- beamlit/agents/decorator.py,sha256=yY3tObddiFjzLah_eQoecaXORShIrF0qvvF8sYR8r84,10619
9
+ beamlit/agents/chat.py,sha256=eSpLhZkfL8Llf7TZeDnRT7HH70buBJO1DOwKm9UNeHs,3675
10
+ beamlit/agents/decorator.py,sha256=YU8FHrn9bYfgKuGtt42iPzOqiVvWC9GzbFLmhTacIsU,4183
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
@@ -98,12 +98,12 @@ beamlit/api/privateclusters/update_private_cluster.py,sha256=Urb5GGuVcSwQy2WBlru
98
98
  beamlit/api/privateclusters/update_private_cluster_health.py,sha256=PxCyl5ZEIqpQ_PKIr9ErqjZcoTSKlTZS1YgTT1JwhCg,2572
99
99
  beamlit/api/service_accounts/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
100
100
  beamlit/api/service_accounts/create_api_key_for_service_account.py,sha256=Ee9CXzYqVh9OTJeai8bKaclznuWpJiPd74aPHZYZdeQ,4525
101
- beamlit/api/service_accounts/create_workspace_service_account.py,sha256=XFAvmmjrwaenuWEPw0YBe7QeiYmXNX8WmcsYj6VYHa4,4639
101
+ beamlit/api/service_accounts/create_workspace_service_account.py,sha256=D3NkGoPZyMi6ibj29F7xbJd5aLI2jw2vLSl1qDRGhW4,4648
102
102
  beamlit/api/service_accounts/delete_api_key_for_service_account.py,sha256=bS2OWtO7Dn8FU2uaTe9h7VCxiobti8Ka2NtTUKBd31Q,2621
103
- beamlit/api/service_accounts/delete_workspace_service_account.py,sha256=_FVYHH29JKQGZqCFSih2-gU92OR-6Am1CIQX6VJ_goo,4127
104
- beamlit/api/service_accounts/get_workspace_service_accounts.py,sha256=R67By_FV4Nv8tVT2b8mgsC_Dnwy0hla353-EOupBizY,4142
103
+ beamlit/api/service_accounts/delete_workspace_service_account.py,sha256=XEz6-DkWZTmuaTOMooaywKvBsGilBYR-xG32RsXP5Mw,4136
104
+ beamlit/api/service_accounts/get_workspace_service_accounts.py,sha256=6c7T_WsXCuotQomm4zkAkAkhdLEcgVyvon9aYHPiEiI,4151
105
105
  beamlit/api/service_accounts/list_api_keys_for_service_account.py,sha256=skp0PmjxfW7EGAyRcVAye_SKfryKjvsTuhSRxeIaXDo,4066
106
- beamlit/api/service_accounts/update_workspace_service_account.py,sha256=IWVMnChlL27mOCH44GYSA6ep5AJuLXzW2oDsqs7mYIQ,4903
106
+ beamlit/api/service_accounts/update_workspace_service_account.py,sha256=Y4rQL8Yx8yRZSzTJz5-ESP5zQ0juVhuoX6xwpg5ZM00,4912
107
107
  beamlit/api/store/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
108
108
  beamlit/api/store/get_store_agent.py,sha256=UjvsRXyFsXZLf4utQjpiOiPM7KxlRj4C-x_ac5EXoLk,3624
109
109
  beamlit/api/store/get_store_function.py,sha256=kEbg91jJh0XAXmipjzwg931mxkMCZ820PxiJ89zYbso,3756
@@ -137,11 +137,11 @@ beamlit/common/settings.py,sha256=b2rvby-ufG3M0AB1ReoWFM-1EzF1LaE-gbokO9HvQDI,38
137
137
  beamlit/common/slugify.py,sha256=nR29r37IdWS2i44ZC6ZsXRgqKPYmvMGtFQ7BuIQUTlc,90
138
138
  beamlit/common/utils.py,sha256=jouz5igBvT37Xn_e94-foCHyQczVim-UzVcoIF6RWJ4,657
139
139
  beamlit/deploy/__init__.py,sha256=GS7l7Jtm2yKs7iNLKcfjYO-rAhUzggQ3xiYSf3oxLBY,91
140
- beamlit/deploy/deploy.py,sha256=FyDqSYpm_YKG8IapaFhI0EN5m71d7wkWLjfBuitxsOU,9884
141
- beamlit/deploy/format.py,sha256=PJ8kU7Y1pwiS3tqqyvFaag9LO3jju-4ua574163VPk4,1820
140
+ beamlit/deploy/deploy.py,sha256=h8ugvkSGcMKLqM-_uD5BZUzng5tJRp-Gea1Jup6QzTE,10257
141
+ beamlit/deploy/format.py,sha256=U6UZEFAYLnGJJ7O2YmSdlUUFhnWNGAv6NZ-DW4KTgvI,2049
142
142
  beamlit/deploy/parser.py,sha256=Ga0poCZkoRnuTw082QnTcNGCBJncoRAnVsn8-1FsaJE,6907
143
- beamlit/functions/__init__.py,sha256=_RPG1Bfg54JGdIPnViAU6n9zD7E1cDNsdXi8oYGskzE,138
144
- beamlit/functions/decorator.py,sha256=ZtSQsPLI70WKwi2jPhA7DaqREQUINpqt9BDVugeV_sg,1714
143
+ beamlit/functions/__init__.py,sha256=NcQPZZNfWhAJ1T1F6Xn21LFPMbZ7aMR2Sve3uZOkBCQ,170
144
+ beamlit/functions/decorator.py,sha256=6Sc-ZX5g-p8GlmdI2MmTW-XhVa8eeMawmwSQlndTLCE,8718
145
145
  beamlit/functions/github/__init__.py,sha256=gYnUkeegukOfbymdabuuJkScvH-_ZJygX05BoqkPn0o,49
146
146
  beamlit/functions/github/github.py,sha256=FajzLCNkpXcwfgnC0l9rOGT2eSPLCz8-qrMzK9N_ZNc,598
147
147
  beamlit/functions/github/kit/__init__.py,sha256=jBwPqZv6C23_utukohxqXZwrlicNlI7PYPUj0Den7Cw,136
@@ -152,7 +152,7 @@ beamlit/functions/mcp/mcp.py,sha256=-LL7O35vTlcYfF1MSlEY83rBKKShJTaHB-y9MRPAEiU,
152
152
  beamlit/functions/remote/remote.py,sha256=AL8WhD7yXZ18h3iU4vE9E4JtJt0n_i-ZwlbBDoolnEs,3767
153
153
  beamlit/functions/search/__init__.py,sha256=5NAthQ9PBwrkNg1FpLRx4flauvv0HyWuwaVS589c1Pw,49
154
154
  beamlit/functions/search/search.py,sha256=8s9ECltq7YE17j6rTxb12uY2EQY4_eTLHmwlIMThI0w,515
155
- beamlit/models/__init__.py,sha256=JivNHOlMd3eGSmg18BKQfTVEwOR730cBsUi64v4LwA0,7888
155
+ beamlit/models/__init__.py,sha256=YMCHuYVLqV03yE_D8TB15I07F7wS1DYV022owTeMRYA,7897
156
156
  beamlit/models/acl.py,sha256=tH67gsl_BMaviSbTaaIkO1g9cWZgJ6VgAnYVjQSzGZY,3952
157
157
  beamlit/models/agent.py,sha256=nGRGNghN5RID5q8oikPVzj1_Aahh9GmDhVPMIA901zc,4372
158
158
  beamlit/models/agent_chain.py,sha256=8PN8wVSayS-LoBN2nahZsOmr6r3t62H_LPDK_8fnkM8,2255
@@ -258,10 +258,10 @@ beamlit/models/websocket_channel.py,sha256=jg3vN7yS_oOIwGtndtIUr1LsyEA58RXLXahqS
258
258
  beamlit/models/workspace.py,sha256=7G3Q9_D9n7_AczznYOToAsEGjWgMJwhnFb3flYNg2ro,4245
259
259
  beamlit/models/workspace_labels.py,sha256=WbnUY6eCTkUNdY7hhhSF-KQCl8fWFfkCf7hzCTiNp4A,1246
260
260
  beamlit/models/workspace_user.py,sha256=70CcifQWYbeWG7TDui4pblTzUe5sVK0AS19vNCzKE8g,3423
261
- beamlit/serve/app.py,sha256=gYQvUK_S7g0Em-idND8HrVDqgg5LlIemheSGlX2Jj8U,3638
261
+ beamlit/serve/app.py,sha256=_aG2UVQ3Y85rUW3ehu9TlzLnowkfh54IIz558ftqOMw,3638
262
262
  beamlit/serve/middlewares/__init__.py,sha256=1dVmnOmhAQWvWktqHkKSIX-YoF6fmMU8xkUQuhg_rJU,148
263
263
  beamlit/serve/middlewares/accesslog.py,sha256=Mu4T4_9OvHybjA0ApzZFpgi2C8f3X1NbUk-76v634XM,631
264
264
  beamlit/serve/middlewares/processtime.py,sha256=lDAaIasZ4bwvN-HKHvZpaD9r-yrkVNZYx4abvbjbrCg,411
265
- beamlit-0.0.34rc60.dist-info/METADATA,sha256=KQjOGNRhgwRUfHsM1l1e4DQzZsI_wEIMYQq__j1LxZo,2412
266
- beamlit-0.0.34rc60.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
267
- beamlit-0.0.34rc60.dist-info/RECORD,,
265
+ beamlit-0.0.34rc62.dist-info/METADATA,sha256=a5Vc8440X2LFgBPnIwx0SqImcwaKO3_OaUVLfTl7K7M,2412
266
+ beamlit-0.0.34rc62.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
267
+ beamlit-0.0.34rc62.dist-info/RECORD,,