beamlit 0.0.56rc107__py3-none-any.whl → 0.0.57__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/chain.py +0 -2
- beamlit/agents/chat.py +20 -8
- beamlit/agents/decorator.py +112 -99
- beamlit/agents/thread.py +5 -9
- beamlit/api/agents/delete_agent.py +1 -22
- beamlit/api/agents/get_agent.py +1 -22
- beamlit/api/agents/get_agent_metrics.py +13 -34
- beamlit/api/agents/get_agent_trace_ids.py +44 -14
- beamlit/api/agents/{list_agent_history.py → list_agent_revisions.py} +21 -17
- beamlit/api/agents/list_agents.py +4 -36
- beamlit/api/default/get_trace_ids.py +0 -15
- beamlit/api/default/list_mcp_hub_definitions.py +12 -12
- beamlit/api/functions/delete_function.py +1 -22
- beamlit/api/functions/get_function.py +1 -22
- beamlit/api/functions/get_function_metrics.py +13 -34
- beamlit/api/functions/get_function_trace_ids.py +44 -14
- beamlit/api/functions/{create_function_release.py → list_function_revisions.py} +26 -18
- beamlit/api/functions/list_functions.py +4 -36
- beamlit/api/knowledgebases/create_knowledgebase.py +4 -4
- beamlit/api/knowledgebases/delete_knowledgebase.py +5 -26
- beamlit/api/knowledgebases/get_knowledgebase.py +1 -22
- beamlit/api/{environments/get_environment_metrics.py → knowledgebases/list_knowledgebase_revisions.py} +34 -34
- beamlit/api/knowledgebases/list_knowledgebases.py +4 -36
- beamlit/api/models/create_model.py +4 -8
- beamlit/api/models/delete_model.py +1 -22
- beamlit/api/models/get_model.py +1 -22
- beamlit/api/models/get_model_metrics.py +13 -34
- beamlit/api/models/get_model_trace_ids.py +44 -14
- beamlit/api/models/{release_model.py → list_model_revisions.py} +26 -22
- beamlit/api/models/list_models.py +4 -36
- beamlit/api/models/update_model.py +4 -8
- beamlit/authentication/authentication.py +11 -8
- beamlit/authentication/clientcredentials.py +15 -28
- beamlit/authentication/credentials.py +2 -7
- beamlit/common/settings.py +1 -4
- beamlit/deploy/deploy.py +15 -9
- beamlit/functions/common.py +16 -16
- beamlit/functions/local/local.py +4 -5
- beamlit/functions/mcp/client.py +96 -0
- beamlit/functions/mcp/mcp.py +56 -46
- beamlit/functions/remote/remote.py +9 -11
- beamlit/models/__init__.py +8 -38
- beamlit/models/agent.py +6 -6
- beamlit/models/function.py +6 -6
- beamlit/models/knowledgebase.py +6 -6
- beamlit/models/last_n_requests_metric.py +0 -9
- beamlit/models/model.py +7 -7
- beamlit/models/{resource_environment_metrics.py → resource_metrics.py} +20 -26
- beamlit/models/{resource_environment_metrics_request_total_per_code.py → resource_metrics_request_total_per_code.py} +5 -5
- beamlit/models/{resource_environment_metrics_rps_per_code.py → resource_metrics_rps_per_code.py} +5 -5
- beamlit/models/{model_release.py → revision_metadata.py} +20 -20
- beamlit/models/runtime.py +2 -2
- beamlit/models/workspace.py +0 -9
- beamlit/run.py +3 -7
- beamlit/serve/app.py +4 -8
- {beamlit-0.0.56rc107.dist-info → beamlit-0.0.57.dist-info}/METADATA +2 -1
- {beamlit-0.0.56rc107.dist-info → beamlit-0.0.57.dist-info}/RECORD +63 -91
- beamlit/api/agents/create_agent_release.py +0 -146
- beamlit/api/agents/delete_agent_history.py +0 -155
- beamlit/api/agents/get_agent_history.py +0 -155
- beamlit/api/agents/put_agent_history.py +0 -181
- beamlit/api/environments/__init__.py +0 -0
- beamlit/api/environments/create_environment.py +0 -167
- beamlit/api/environments/delete_environment.py +0 -154
- beamlit/api/environments/get_environment.py +0 -154
- beamlit/api/environments/list_environments.py +0 -139
- beamlit/api/environments/update_environment.py +0 -180
- beamlit/api/generation/__init__.py +0 -0
- beamlit/api/generation/run_information_generation_agent.py +0 -168
- beamlit/api/history/__init__.py +0 -0
- beamlit/api/history/get_agents_history.py +0 -155
- beamlit/api/history/list_agents_history.py +0 -131
- beamlit/models/agent_history.py +0 -167
- beamlit/models/agent_history_event.py +0 -133
- beamlit/models/agent_information_request.py +0 -63
- beamlit/models/agent_information_response.py +0 -79
- beamlit/models/agent_release.py +0 -70
- beamlit/models/environment.py +0 -96
- beamlit/models/environment_metadata.py +0 -148
- beamlit/models/environment_metrics.py +0 -77
- beamlit/models/environment_spec.py +0 -63
- beamlit/models/function_release.py +0 -70
- beamlit/models/knowledgebase_release.py +0 -70
- beamlit/models/mcp_hub_artifact.py +0 -188
- beamlit/models/mcp_hub_artifact_entrypoint.py +0 -45
- beamlit/models/mcp_hub_artifact_form.py +0 -45
- /beamlit/api/agents/{get_agent_environment_logs.py → get_agent_logs.py} +0 -0
- /beamlit/api/functions/{get_function_environment_logs.py → get_function_logs.py} +0 -0
- /beamlit/api/models/{get_model_environment_logs.py → get_model_logs.py} +0 -0
- {beamlit-0.0.56rc107.dist-info → beamlit-0.0.57.dist-info}/WHEEL +0 -0
- {beamlit-0.0.56rc107.dist-info → beamlit-0.0.57.dist-info}/entry_points.txt +0 -0
- {beamlit-0.0.56rc107.dist-info → beamlit-0.0.57.dist-info}/licenses/LICENSE +0 -0
@@ -5,7 +5,7 @@ import httpx
|
|
5
5
|
|
6
6
|
from ... import errors
|
7
7
|
from ...client import AuthenticatedClient, Client
|
8
|
-
from ...models.
|
8
|
+
from ...models.revision_metadata import RevisionMetadata
|
9
9
|
from ...types import Response
|
10
10
|
|
11
11
|
|
@@ -13,16 +13,18 @@ def _get_kwargs(
|
|
13
13
|
model_name: str,
|
14
14
|
) -> dict[str, Any]:
|
15
15
|
_kwargs: dict[str, Any] = {
|
16
|
-
"method": "
|
17
|
-
"url": f"/models/{model_name}/
|
16
|
+
"method": "get",
|
17
|
+
"url": f"/models/{model_name}/revisions",
|
18
18
|
}
|
19
19
|
|
20
20
|
return _kwargs
|
21
21
|
|
22
22
|
|
23
|
-
def _parse_response(
|
23
|
+
def _parse_response(
|
24
|
+
*, client: Union[AuthenticatedClient, Client], response: httpx.Response
|
25
|
+
) -> Optional[RevisionMetadata]:
|
24
26
|
if response.status_code == 200:
|
25
|
-
response_200 =
|
27
|
+
response_200 = RevisionMetadata.from_dict(response.json())
|
26
28
|
|
27
29
|
return response_200
|
28
30
|
if client.raise_on_unexpected_status:
|
@@ -31,7 +33,9 @@ def _parse_response(*, client: Union[AuthenticatedClient, Client], response: htt
|
|
31
33
|
return None
|
32
34
|
|
33
35
|
|
34
|
-
def _build_response(
|
36
|
+
def _build_response(
|
37
|
+
*, client: Union[AuthenticatedClient, Client], response: httpx.Response
|
38
|
+
) -> Response[RevisionMetadata]:
|
35
39
|
return Response(
|
36
40
|
status_code=HTTPStatus(response.status_code),
|
37
41
|
content=response.content,
|
@@ -44,10 +48,10 @@ def sync_detailed(
|
|
44
48
|
model_name: str,
|
45
49
|
*,
|
46
50
|
client: AuthenticatedClient,
|
47
|
-
) -> Response[
|
48
|
-
"""
|
51
|
+
) -> Response[RevisionMetadata]:
|
52
|
+
"""List model revisions
|
49
53
|
|
50
|
-
|
54
|
+
Returns revisions for a model by name.
|
51
55
|
|
52
56
|
Args:
|
53
57
|
model_name (str):
|
@@ -57,7 +61,7 @@ def sync_detailed(
|
|
57
61
|
httpx.TimeoutException: If the request takes longer than Client.timeout.
|
58
62
|
|
59
63
|
Returns:
|
60
|
-
Response[
|
64
|
+
Response[RevisionMetadata]
|
61
65
|
"""
|
62
66
|
|
63
67
|
kwargs = _get_kwargs(
|
@@ -75,10 +79,10 @@ def sync(
|
|
75
79
|
model_name: str,
|
76
80
|
*,
|
77
81
|
client: AuthenticatedClient,
|
78
|
-
) -> Optional[
|
79
|
-
"""
|
82
|
+
) -> Optional[RevisionMetadata]:
|
83
|
+
"""List model revisions
|
80
84
|
|
81
|
-
|
85
|
+
Returns revisions for a model by name.
|
82
86
|
|
83
87
|
Args:
|
84
88
|
model_name (str):
|
@@ -88,7 +92,7 @@ def sync(
|
|
88
92
|
httpx.TimeoutException: If the request takes longer than Client.timeout.
|
89
93
|
|
90
94
|
Returns:
|
91
|
-
|
95
|
+
RevisionMetadata
|
92
96
|
"""
|
93
97
|
|
94
98
|
return sync_detailed(
|
@@ -101,10 +105,10 @@ async def asyncio_detailed(
|
|
101
105
|
model_name: str,
|
102
106
|
*,
|
103
107
|
client: AuthenticatedClient,
|
104
|
-
) -> Response[
|
105
|
-
"""
|
108
|
+
) -> Response[RevisionMetadata]:
|
109
|
+
"""List model revisions
|
106
110
|
|
107
|
-
|
111
|
+
Returns revisions for a model by name.
|
108
112
|
|
109
113
|
Args:
|
110
114
|
model_name (str):
|
@@ -114,7 +118,7 @@ async def asyncio_detailed(
|
|
114
118
|
httpx.TimeoutException: If the request takes longer than Client.timeout.
|
115
119
|
|
116
120
|
Returns:
|
117
|
-
Response[
|
121
|
+
Response[RevisionMetadata]
|
118
122
|
"""
|
119
123
|
|
120
124
|
kwargs = _get_kwargs(
|
@@ -130,10 +134,10 @@ async def asyncio(
|
|
130
134
|
model_name: str,
|
131
135
|
*,
|
132
136
|
client: AuthenticatedClient,
|
133
|
-
) -> Optional[
|
134
|
-
"""
|
137
|
+
) -> Optional[RevisionMetadata]:
|
138
|
+
"""List model revisions
|
135
139
|
|
136
|
-
|
140
|
+
Returns revisions for a model by name.
|
137
141
|
|
138
142
|
Args:
|
139
143
|
model_name (str):
|
@@ -143,7 +147,7 @@ async def asyncio(
|
|
143
147
|
httpx.TimeoutException: If the request takes longer than Client.timeout.
|
144
148
|
|
145
149
|
Returns:
|
146
|
-
|
150
|
+
RevisionMetadata
|
147
151
|
"""
|
148
152
|
|
149
153
|
return (
|
@@ -6,23 +6,13 @@ import httpx
|
|
6
6
|
from ... import errors
|
7
7
|
from ...client import AuthenticatedClient, Client
|
8
8
|
from ...models.model import Model
|
9
|
-
from ...types import
|
9
|
+
from ...types import Response
|
10
10
|
|
11
11
|
|
12
|
-
def _get_kwargs(
|
13
|
-
*,
|
14
|
-
environment: Union[Unset, str] = UNSET,
|
15
|
-
) -> dict[str, Any]:
|
16
|
-
params: dict[str, Any] = {}
|
17
|
-
|
18
|
-
params["environment"] = environment
|
19
|
-
|
20
|
-
params = {k: v for k, v in params.items() if v is not UNSET and v is not None}
|
21
|
-
|
12
|
+
def _get_kwargs() -> dict[str, Any]:
|
22
13
|
_kwargs: dict[str, Any] = {
|
23
14
|
"method": "get",
|
24
15
|
"url": "/models",
|
25
|
-
"params": params,
|
26
16
|
}
|
27
17
|
|
28
18
|
return _kwargs
|
@@ -56,15 +46,11 @@ def _build_response(*, client: Union[AuthenticatedClient, Client], response: htt
|
|
56
46
|
def sync_detailed(
|
57
47
|
*,
|
58
48
|
client: AuthenticatedClient,
|
59
|
-
environment: Union[Unset, str] = UNSET,
|
60
49
|
) -> Response[list["Model"]]:
|
61
50
|
"""List models
|
62
51
|
|
63
52
|
Returns a list of all models in the workspace.
|
64
53
|
|
65
|
-
Args:
|
66
|
-
environment (Union[Unset, str]):
|
67
|
-
|
68
54
|
Raises:
|
69
55
|
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
|
70
56
|
httpx.TimeoutException: If the request takes longer than Client.timeout.
|
@@ -73,9 +59,7 @@ def sync_detailed(
|
|
73
59
|
Response[list['Model']]
|
74
60
|
"""
|
75
61
|
|
76
|
-
kwargs = _get_kwargs(
|
77
|
-
environment=environment,
|
78
|
-
)
|
62
|
+
kwargs = _get_kwargs()
|
79
63
|
|
80
64
|
response = client.get_httpx_client().request(
|
81
65
|
**kwargs,
|
@@ -87,15 +71,11 @@ def sync_detailed(
|
|
87
71
|
def sync(
|
88
72
|
*,
|
89
73
|
client: AuthenticatedClient,
|
90
|
-
environment: Union[Unset, str] = UNSET,
|
91
74
|
) -> Optional[list["Model"]]:
|
92
75
|
"""List models
|
93
76
|
|
94
77
|
Returns a list of all models in the workspace.
|
95
78
|
|
96
|
-
Args:
|
97
|
-
environment (Union[Unset, str]):
|
98
|
-
|
99
79
|
Raises:
|
100
80
|
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
|
101
81
|
httpx.TimeoutException: If the request takes longer than Client.timeout.
|
@@ -106,22 +86,17 @@ def sync(
|
|
106
86
|
|
107
87
|
return sync_detailed(
|
108
88
|
client=client,
|
109
|
-
environment=environment,
|
110
89
|
).parsed
|
111
90
|
|
112
91
|
|
113
92
|
async def asyncio_detailed(
|
114
93
|
*,
|
115
94
|
client: AuthenticatedClient,
|
116
|
-
environment: Union[Unset, str] = UNSET,
|
117
95
|
) -> Response[list["Model"]]:
|
118
96
|
"""List models
|
119
97
|
|
120
98
|
Returns a list of all models in the workspace.
|
121
99
|
|
122
|
-
Args:
|
123
|
-
environment (Union[Unset, str]):
|
124
|
-
|
125
100
|
Raises:
|
126
101
|
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
|
127
102
|
httpx.TimeoutException: If the request takes longer than Client.timeout.
|
@@ -130,9 +105,7 @@ async def asyncio_detailed(
|
|
130
105
|
Response[list['Model']]
|
131
106
|
"""
|
132
107
|
|
133
|
-
kwargs = _get_kwargs(
|
134
|
-
environment=environment,
|
135
|
-
)
|
108
|
+
kwargs = _get_kwargs()
|
136
109
|
|
137
110
|
response = await client.get_async_httpx_client().request(**kwargs)
|
138
111
|
|
@@ -142,15 +115,11 @@ async def asyncio_detailed(
|
|
142
115
|
async def asyncio(
|
143
116
|
*,
|
144
117
|
client: AuthenticatedClient,
|
145
|
-
environment: Union[Unset, str] = UNSET,
|
146
118
|
) -> Optional[list["Model"]]:
|
147
119
|
"""List models
|
148
120
|
|
149
121
|
Returns a list of all models in the workspace.
|
150
122
|
|
151
|
-
Args:
|
152
|
-
environment (Union[Unset, str]):
|
153
|
-
|
154
123
|
Raises:
|
155
124
|
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
|
156
125
|
httpx.TimeoutException: If the request takes longer than Client.timeout.
|
@@ -162,6 +131,5 @@ async def asyncio(
|
|
162
131
|
return (
|
163
132
|
await asyncio_detailed(
|
164
133
|
client=client,
|
165
|
-
environment=environment,
|
166
134
|
)
|
167
135
|
).parsed
|
@@ -62,8 +62,7 @@ def sync_detailed(
|
|
62
62
|
|
63
63
|
Args:
|
64
64
|
model_name (str):
|
65
|
-
body (Model): Logical object representing a model
|
66
|
-
environments as model deployments
|
65
|
+
body (Model): Logical object representing a model
|
67
66
|
|
68
67
|
Raises:
|
69
68
|
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
|
@@ -97,8 +96,7 @@ def sync(
|
|
97
96
|
|
98
97
|
Args:
|
99
98
|
model_name (str):
|
100
|
-
body (Model): Logical object representing a model
|
101
|
-
environments as model deployments
|
99
|
+
body (Model): Logical object representing a model
|
102
100
|
|
103
101
|
Raises:
|
104
102
|
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
|
@@ -127,8 +125,7 @@ async def asyncio_detailed(
|
|
127
125
|
|
128
126
|
Args:
|
129
127
|
model_name (str):
|
130
|
-
body (Model): Logical object representing a model
|
131
|
-
environments as model deployments
|
128
|
+
body (Model): Logical object representing a model
|
132
129
|
|
133
130
|
Raises:
|
134
131
|
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
|
@@ -160,8 +157,7 @@ async def asyncio(
|
|
160
157
|
|
161
158
|
Args:
|
162
159
|
model_name (str):
|
163
|
-
body (Model): Logical object representing a model
|
164
|
-
environments as model deployments
|
160
|
+
body (Model): Logical object representing a model
|
165
161
|
|
166
162
|
Raises:
|
167
163
|
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
|
@@ -7,21 +7,18 @@ It also includes utilities for creating authenticated clients and managing authe
|
|
7
7
|
from dataclasses import dataclass
|
8
8
|
from typing import Dict, Generator
|
9
9
|
|
10
|
-
from httpx import Auth, Request, Response
|
11
|
-
|
12
10
|
from beamlit.common.settings import Settings, get_settings
|
11
|
+
from httpx import Auth, Request, Response
|
13
12
|
|
14
13
|
from ..client import AuthenticatedClient
|
15
14
|
from .apikey import ApiKeyProvider
|
16
15
|
from .clientcredentials import ClientCredentials
|
17
|
-
from .credentials import (
|
18
|
-
|
19
|
-
current_context,
|
20
|
-
load_credentials,
|
21
|
-
load_credentials_from_settings,
|
22
|
-
)
|
16
|
+
from .credentials import (Credentials, current_context, load_credentials,
|
17
|
+
load_credentials_from_settings)
|
23
18
|
from .device_mode import BearerToken
|
24
19
|
|
20
|
+
global provider_singleton
|
21
|
+
provider_singleton = None
|
25
22
|
|
26
23
|
class PublicProvider(Auth):
|
27
24
|
"""
|
@@ -144,6 +141,11 @@ def get_authentication_headers(settings: Settings) -> Dict[str, str]:
|
|
144
141
|
Returns:
|
145
142
|
Dict[str, str]: A dictionary of authentication headers.
|
146
143
|
"""
|
144
|
+
global provider_singleton
|
145
|
+
|
146
|
+
if provider_singleton:
|
147
|
+
return provider_singleton.get_headers()
|
148
|
+
|
147
149
|
context = current_context()
|
148
150
|
if context.workspace and not settings.authentication.client.credentials:
|
149
151
|
credentials = load_credentials(context.workspace)
|
@@ -165,4 +167,5 @@ def get_authentication_headers(settings: Settings) -> Dict[str, str]:
|
|
165
167
|
|
166
168
|
if provider is None:
|
167
169
|
return None
|
170
|
+
provider_singleton = provider
|
168
171
|
return provider.get_headers()
|
@@ -4,16 +4,13 @@ authentication for Beamlit. It manages token refreshing and authentication flows
|
|
4
4
|
client credentials and refresh tokens.
|
5
5
|
"""
|
6
6
|
|
7
|
-
import base64
|
8
|
-
import json
|
9
7
|
from dataclasses import dataclass
|
10
8
|
from datetime import datetime, timedelta
|
11
9
|
from typing import Generator, Optional
|
12
10
|
|
13
11
|
import requests
|
14
|
-
from httpx import Auth, Request, Response, post
|
15
|
-
|
16
12
|
from beamlit.common.settings import get_settings
|
13
|
+
from httpx import Auth, Request, Response, post
|
17
14
|
|
18
15
|
|
19
16
|
@dataclass
|
@@ -39,6 +36,7 @@ class ClientCredentials(Auth):
|
|
39
36
|
base_url (str): The base URL for authentication.
|
40
37
|
"""
|
41
38
|
self.credentials = credentials
|
39
|
+
self.expires_at = None
|
42
40
|
self.workspace_name = workspace_name
|
43
41
|
self.base_url = base_url
|
44
42
|
|
@@ -52,16 +50,15 @@ class ClientCredentials(Auth):
|
|
52
50
|
Raises:
|
53
51
|
Exception: If token refresh fails.
|
54
52
|
"""
|
55
|
-
err = self.
|
53
|
+
err = self.get_token()
|
56
54
|
if err:
|
57
55
|
raise err
|
58
|
-
|
59
56
|
return {
|
60
57
|
"X-Beamlit-Authorization": f"Bearer {self.credentials.access_token}",
|
61
58
|
"X-Beamlit-Workspace": self.workspace_name,
|
62
59
|
}
|
63
60
|
|
64
|
-
def
|
61
|
+
def get_token(self) -> Optional[Exception]:
|
65
62
|
"""
|
66
63
|
Checks if the access token needs to be refreshed and performs the refresh if necessary.
|
67
64
|
|
@@ -69,33 +66,23 @@ class ClientCredentials(Auth):
|
|
69
66
|
Optional[Exception]: An exception if refreshing fails, otherwise None.
|
70
67
|
"""
|
71
68
|
settings = get_settings()
|
72
|
-
if self.
|
69
|
+
if self.need_token():
|
73
70
|
headers = {"Authorization": f"Basic {self.credentials.client_credentials}", "Content-Type": "application/json"}
|
74
71
|
body = {"grant_type": "client_credentials"}
|
75
72
|
response = requests.post(f"{settings.base_url}/oauth/token", headers=headers, json=body)
|
76
73
|
response.raise_for_status()
|
77
|
-
|
78
|
-
self.credentials.
|
79
|
-
self.credentials.
|
80
|
-
|
81
|
-
|
82
|
-
parts = self.credentials.access_token.split(".")
|
83
|
-
if len(parts) != 3:
|
84
|
-
return Exception("Invalid JWT token format")
|
85
|
-
try:
|
86
|
-
claims_bytes = base64.urlsafe_b64decode(parts[1] + "=" * (-len(parts[1]) % 4))
|
87
|
-
claims = json.loads(claims_bytes)
|
88
|
-
except Exception as e:
|
89
|
-
return Exception(f"Failed to decode/parse JWT claims: {str(e)}")
|
90
|
-
|
91
|
-
exp_time = datetime.fromtimestamp(claims["exp"])
|
92
|
-
current_time = datetime.now()
|
93
|
-
# Refresh if token expires in less than 10 minutes
|
94
|
-
if current_time + timedelta(minutes=10) > exp_time:
|
95
|
-
return self.do_refresh()
|
96
|
-
|
74
|
+
creds = response.json()
|
75
|
+
self.credentials.access_token = creds["access_token"]
|
76
|
+
self.credentials.refresh_token = creds["refresh_token"]
|
77
|
+
self.credentials.expires_in = creds["expires_in"]
|
78
|
+
self.expires_at = datetime.now() + timedelta(seconds=self.credentials.expires_in)
|
97
79
|
return None
|
98
80
|
|
81
|
+
def need_token(self):
|
82
|
+
if not self.expires_at:
|
83
|
+
return True
|
84
|
+
return datetime.now() > self.expires_at - timedelta(minutes=10)
|
85
|
+
|
99
86
|
def auth_flow(self, request: Request) -> Generator[Request, Response, None]:
|
100
87
|
"""
|
101
88
|
Processes the authentication flow by ensuring tokens are valid and adding necessary headers.
|
@@ -57,10 +57,8 @@ class ContextConfig:
|
|
57
57
|
|
58
58
|
Attributes:
|
59
59
|
workspace (str): The name of the current workspace.
|
60
|
-
environment (str): The current environment (e.g., development, production).
|
61
60
|
"""
|
62
61
|
workspace: str = ""
|
63
|
-
environment: str = ""
|
64
62
|
|
65
63
|
|
66
64
|
@dataclass
|
@@ -108,7 +106,6 @@ class Config:
|
|
108
106
|
],
|
109
107
|
"context": {
|
110
108
|
"workspace": self.context.workspace,
|
111
|
-
"environment": self.context.environment,
|
112
109
|
},
|
113
110
|
}
|
114
111
|
|
@@ -186,17 +183,15 @@ def current_context() -> ContextConfig:
|
|
186
183
|
return config.context
|
187
184
|
|
188
185
|
|
189
|
-
def set_current_workspace(workspace_name: str
|
186
|
+
def set_current_workspace(workspace_name: str):
|
190
187
|
"""
|
191
|
-
Sets the current workspace
|
188
|
+
Sets the current workspace in the configuration.
|
192
189
|
|
193
190
|
Parameters:
|
194
191
|
workspace_name (str): The name of the workspace to set as current.
|
195
|
-
environment (str): The environment to set for the workspace.
|
196
192
|
"""
|
197
193
|
config = load_config()
|
198
194
|
config.context.workspace = workspace_name
|
199
|
-
config.context.environment = environment
|
200
195
|
save_config(config)
|
201
196
|
|
202
197
|
|
beamlit/common/settings.py
CHANGED
@@ -76,7 +76,6 @@ class Settings(BaseSettings):
|
|
76
76
|
)
|
77
77
|
|
78
78
|
workspace: str
|
79
|
-
environment: str = Field(default="production")
|
80
79
|
remote: bool = Field(default=False)
|
81
80
|
type: str = Field(default="agent")
|
82
81
|
name: str = Field(default="beamlit-agent")
|
@@ -130,7 +129,7 @@ def init() -> Settings:
|
|
130
129
|
"""
|
131
130
|
Initializes the settings by parsing the `beamlit.yaml` file and setting up logging.
|
132
131
|
|
133
|
-
This function reads workspace
|
132
|
+
This function reads workspace configuration from the current context,
|
134
133
|
initializes the global SETTINGS variable, and configures the logger based on the log level.
|
135
134
|
|
136
135
|
Returns:
|
@@ -144,8 +143,6 @@ def init() -> Settings:
|
|
144
143
|
kwargs = {}
|
145
144
|
if context.workspace:
|
146
145
|
kwargs["workspace"] = context.workspace
|
147
|
-
if context.environment:
|
148
|
-
kwargs["environment"] = context.environment
|
149
146
|
|
150
147
|
SETTINGS = Settings(**kwargs)
|
151
148
|
init_logger(SETTINGS.log_level)
|
beamlit/deploy/deploy.py
CHANGED
@@ -23,10 +23,10 @@ from beamlit.common.settings import Settings, get_settings, init
|
|
23
23
|
from beamlit.models import (
|
24
24
|
Agent,
|
25
25
|
AgentSpec,
|
26
|
-
EnvironmentMetadata,
|
27
26
|
Flavor,
|
28
27
|
Function,
|
29
28
|
FunctionSpec,
|
29
|
+
Metadata,
|
30
30
|
MetadataLabels,
|
31
31
|
)
|
32
32
|
|
@@ -49,13 +49,20 @@ def set_default_values(resource: Resource, deployment: Agent | Function):
|
|
49
49
|
"""
|
50
50
|
settings = get_settings()
|
51
51
|
deployment.metadata.workspace = settings.workspace
|
52
|
-
deployment.metadata.environment = settings.environment
|
53
52
|
if not deployment.metadata.name:
|
54
53
|
deployment.metadata.name = slugify(resource.name)
|
55
54
|
if not deployment.metadata.display_name:
|
56
55
|
deployment.metadata.display_name = deployment.metadata.name
|
57
56
|
if not deployment.spec.description:
|
58
57
|
deployment.spec.description = get_description(None, resource)
|
58
|
+
if isinstance(deployment, Agent):
|
59
|
+
deployment.spec.functions = []
|
60
|
+
for arg in resource.decorator.keywords:
|
61
|
+
if arg.arg == "remote_functions":
|
62
|
+
if isinstance(arg.value, ast.List):
|
63
|
+
for value in arg.value.elts:
|
64
|
+
if isinstance(value, ast.Constant):
|
65
|
+
deployment.spec.functions.append(slugify(value.value))
|
59
66
|
return deployment
|
60
67
|
|
61
68
|
def get_beamlit_deployment_from_resource(
|
@@ -75,8 +82,7 @@ def get_beamlit_deployment_from_resource(
|
|
75
82
|
if arg.arg == "agent":
|
76
83
|
if isinstance(arg.value, ast.Dict):
|
77
84
|
value = arg_to_dict(arg.value)
|
78
|
-
metadata =
|
79
|
-
metadata.environment = settings.environment
|
85
|
+
metadata = Metadata(**value.get("metadata", {}))
|
80
86
|
spec = AgentSpec(**value.get("spec", {}))
|
81
87
|
agent = Agent(metadata=metadata, spec=spec)
|
82
88
|
if not agent.spec.prompt:
|
@@ -85,18 +91,17 @@ def get_beamlit_deployment_from_resource(
|
|
85
91
|
if arg.arg == "function":
|
86
92
|
if isinstance(arg.value, ast.Dict):
|
87
93
|
value = arg_to_dict(arg.value)
|
88
|
-
metadata =
|
89
|
-
metadata.environment = settings.environment
|
94
|
+
metadata = Metadata(**value.get("metadata", {}))
|
90
95
|
spec = FunctionSpec(**value.get("spec", {}))
|
91
96
|
func = Function(metadata=metadata, spec=spec)
|
92
97
|
if not func.spec.parameters:
|
93
98
|
func.spec.parameters = get_parameters(resource)
|
94
99
|
return set_default_values(resource, func)
|
95
100
|
if resource.type == "agent":
|
96
|
-
agent = Agent(metadata=
|
101
|
+
agent = Agent(metadata=Metadata(), spec=AgentSpec())
|
97
102
|
return set_default_values(resource, agent)
|
98
103
|
if resource.type == "function":
|
99
|
-
func = Function(metadata=
|
104
|
+
func = Function(metadata=Metadata(), spec=FunctionSpec())
|
100
105
|
func.spec.parameters = get_parameters(resource)
|
101
106
|
return set_default_values(resource, func)
|
102
107
|
return None
|
@@ -134,7 +139,8 @@ def get_agent_yaml(
|
|
134
139
|
agent.spec.repository = agent_response.spec.repository
|
135
140
|
except Exception:
|
136
141
|
pass
|
137
|
-
agent.spec.functions =
|
142
|
+
agent.spec.functions = agent.spec.functions or []
|
143
|
+
agent.spec.functions = agent.spec.functions + [slugify(function.metadata.name) for (_, function) in functions]
|
138
144
|
agent.metadata.labels = agent.metadata.labels and MetadataLabels.from_dict(agent.metadata.labels) or MetadataLabels()
|
139
145
|
agent.metadata.labels["x-beamlit-auto-generated"] = "true"
|
140
146
|
agent_yaml = yaml.dump(agent.to_dict())
|
beamlit/functions/common.py
CHANGED
@@ -34,7 +34,7 @@ from beamlit.models import AgentChain
|
|
34
34
|
|
35
35
|
logger = getLogger(__name__)
|
36
36
|
|
37
|
-
def get_functions(
|
37
|
+
async def get_functions(
|
38
38
|
remote_functions: Union[list[str], None] = None,
|
39
39
|
local_functions: Union[list[dict], None] = None,
|
40
40
|
client: Union[AuthenticatedClient, None] = None,
|
@@ -139,7 +139,7 @@ def get_functions(
|
|
139
139
|
):
|
140
140
|
is_kit = keyword.value.value
|
141
141
|
if is_kit and not settings.remote:
|
142
|
-
kit_functions = get_functions(
|
142
|
+
kit_functions = await get_functions(
|
143
143
|
client=client,
|
144
144
|
dir=os.path.join(root),
|
145
145
|
remote_functions_empty=remote_functions_empty,
|
@@ -153,8 +153,8 @@ def get_functions(
|
|
153
153
|
func = getattr(module, func_name)
|
154
154
|
if settings.remote:
|
155
155
|
toolkit = RemoteToolkit(client, slugify(func.__name__))
|
156
|
-
toolkit.initialize()
|
157
|
-
functions.extend(toolkit.get_tools())
|
156
|
+
await toolkit.initialize()
|
157
|
+
functions.extend(await toolkit.get_tools())
|
158
158
|
else:
|
159
159
|
if asyncio.iscoroutinefunction(func):
|
160
160
|
functions.append(
|
@@ -183,20 +183,21 @@ def get_functions(
|
|
183
183
|
for function in remote_functions:
|
184
184
|
try:
|
185
185
|
toolkit = RemoteToolkit(client, function)
|
186
|
-
toolkit.initialize()
|
187
|
-
functions.extend(toolkit.get_tools())
|
186
|
+
await toolkit.initialize()
|
187
|
+
functions.extend(await toolkit.get_tools())
|
188
188
|
except Exception as e:
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
189
|
+
if not isinstance(e, RuntimeError):
|
190
|
+
logger.debug(
|
191
|
+
f"Failed to initialize remote function {function}: {e!s}\n"
|
192
|
+
f"Traceback:\n{traceback.format_exc()}"
|
193
|
+
)
|
194
|
+
logger.warn(f"Failed to initialize remote function {function}: {e!s}")
|
194
195
|
if local_functions:
|
195
196
|
for function in local_functions:
|
196
197
|
try:
|
197
198
|
toolkit = LocalToolKit(client, function)
|
198
|
-
toolkit.initialize()
|
199
|
-
functions.extend(toolkit.get_tools())
|
199
|
+
await toolkit.initialize()
|
200
|
+
functions.extend(await toolkit.get_tools())
|
200
201
|
except Exception as e:
|
201
202
|
logger.debug(
|
202
203
|
f"Failed to initialize local function {function}: {e!s}\n"
|
@@ -206,8 +207,7 @@ def get_functions(
|
|
206
207
|
|
207
208
|
if chain:
|
208
209
|
toolkit = ChainToolkit(client, chain)
|
209
|
-
toolkit.initialize()
|
210
|
-
functions.extend(toolkit.get_tools())
|
211
|
-
|
210
|
+
await toolkit.initialize()
|
211
|
+
functions.extend(await toolkit.get_tools())
|
212
212
|
return functions
|
213
213
|
|
beamlit/functions/local/local.py
CHANGED
@@ -23,7 +23,7 @@ class LocalToolKit:
|
|
23
23
|
_function: Function | None = None
|
24
24
|
model_config = pydantic.ConfigDict(arbitrary_types_allowed=True)
|
25
25
|
|
26
|
-
def initialize(self) -> None:
|
26
|
+
async def initialize(self) -> None:
|
27
27
|
"""Initialize the session and retrieve the local function details."""
|
28
28
|
if self._function is None:
|
29
29
|
try:
|
@@ -34,7 +34,6 @@ class LocalToolKit:
|
|
34
34
|
spec={
|
35
35
|
"configurations": {
|
36
36
|
"url": self.local_function['url'],
|
37
|
-
"sse": self.local_function['sse'],
|
38
37
|
},
|
39
38
|
"description": self.local_function['description'] or "",
|
40
39
|
}
|
@@ -42,8 +41,8 @@ class LocalToolKit:
|
|
42
41
|
except Exception as e:
|
43
42
|
raise RuntimeError(f"Failed to initialize local function: {e}")
|
44
43
|
|
45
|
-
def get_tools(self) -> list[BaseTool]:
|
44
|
+
async def get_tools(self) -> list[BaseTool]:
|
46
45
|
mcp_client = MCPClient(self.client, self._function.spec["configurations"]["url"], sse=self._function.spec["configurations"]["sse"])
|
47
46
|
mcp_toolkit = MCPToolkit(client=mcp_client)
|
48
|
-
mcp_toolkit.initialize()
|
49
|
-
return mcp_toolkit.get_tools()
|
47
|
+
await mcp_toolkit.initialize()
|
48
|
+
return await mcp_toolkit.get_tools()
|