blaxel 0.1.13__py3-none-any.whl → 0.1.14.dev3__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.
- blaxel/authentication/clientcredentials.py +25 -4
- blaxel/common/internal.py +19 -15
- blaxel/common/logger.py +54 -2
- blaxel/common/settings.py +8 -3
- blaxel/instrumentation/manager.py +10 -8
- blaxel/jobs/__init__.py +187 -0
- {blaxel-0.1.13.dist-info → blaxel-0.1.14.dev3.dist-info}/METADATA +2 -2
- {blaxel-0.1.13.dist-info → blaxel-0.1.14.dev3.dist-info}/RECORD +10 -9
- {blaxel-0.1.13.dist-info → blaxel-0.1.14.dev3.dist-info}/WHEEL +0 -0
- {blaxel-0.1.13.dist-info → blaxel-0.1.14.dev3.dist-info}/licenses/LICENSE +0 -0
@@ -7,6 +7,7 @@ client credentials and refresh tokens.
|
|
7
7
|
from dataclasses import dataclass
|
8
8
|
from datetime import datetime, timedelta
|
9
9
|
from typing import Generator, Optional
|
10
|
+
import time
|
10
11
|
|
11
12
|
import requests
|
12
13
|
from httpx import Request, Response
|
@@ -46,14 +47,17 @@ class ClientCredentials(BlaxelAuth):
|
|
46
47
|
"X-Blaxel-Workspace": self.workspace_name,
|
47
48
|
}
|
48
49
|
|
49
|
-
def
|
50
|
+
def _request_token(self, remaining_retries: int = 3) -> Optional[Exception]:
|
50
51
|
"""
|
51
|
-
|
52
|
+
Makes the token request with recursive retry logic.
|
53
|
+
|
54
|
+
Args:
|
55
|
+
remaining_retries (int): Number of retry attempts remaining.
|
52
56
|
|
53
57
|
Returns:
|
54
|
-
Optional[Exception]: An exception if refreshing fails, otherwise None.
|
58
|
+
Optional[Exception]: An exception if refreshing fails after all retries, otherwise None.
|
55
59
|
"""
|
56
|
-
|
60
|
+
try:
|
57
61
|
headers = {"Authorization": f"Basic {self.credentials.client_credentials}", "Content-Type": "application/json"}
|
58
62
|
body = {"grant_type": "client_credentials"}
|
59
63
|
response = requests.post(f"{self.base_url}/oauth/token", headers=headers, json=body)
|
@@ -63,6 +67,23 @@ class ClientCredentials(BlaxelAuth):
|
|
63
67
|
self.credentials.refresh_token = creds["refresh_token"]
|
64
68
|
self.credentials.expires_in = creds["expires_in"]
|
65
69
|
self.expires_at = datetime.now() + timedelta(seconds=self.credentials.expires_in)
|
70
|
+
return None
|
71
|
+
except Exception as e:
|
72
|
+
if remaining_retries > 0:
|
73
|
+
time.sleep(1)
|
74
|
+
return self._request_token(remaining_retries - 1)
|
75
|
+
return e
|
76
|
+
|
77
|
+
def get_token(self) -> Optional[Exception]:
|
78
|
+
"""
|
79
|
+
Checks if the access token needs to be refreshed and performs the refresh if necessary.
|
80
|
+
Uses recursive retry logic for up to 3 attempts.
|
81
|
+
|
82
|
+
Returns:
|
83
|
+
Optional[Exception]: An exception if refreshing fails after all retries, otherwise None.
|
84
|
+
"""
|
85
|
+
if self.need_token():
|
86
|
+
return self._request_token()
|
66
87
|
return None
|
67
88
|
|
68
89
|
def need_token(self):
|
blaxel/common/internal.py
CHANGED
@@ -7,21 +7,25 @@ from typing import Optional
|
|
7
7
|
|
8
8
|
logger = getLogger(__name__)
|
9
9
|
|
10
|
-
def get_alphanumeric_limited_hash(input_str, max_size):
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
10
|
+
def get_alphanumeric_limited_hash(input_str, max_size=48):
|
11
|
+
"""
|
12
|
+
Create an alphanumeric hash using MD5 that can be reproduced in Go, TypeScript, and Python.
|
13
|
+
|
14
|
+
Args:
|
15
|
+
input_str (str): The input string to hash
|
16
|
+
max_size (int): The maximum length of the returned hash
|
17
|
+
|
18
|
+
Returns:
|
19
|
+
str: An alphanumeric hash of the input string, limited to max_size
|
20
|
+
"""
|
21
|
+
# Calculate MD5 hash and convert to hexadecimal
|
22
|
+
hash_hex = hashlib.md5(input_str.encode('utf-8')).hexdigest()
|
23
|
+
|
24
|
+
# Limit to max_size
|
25
|
+
if len(hash_hex) > max_size:
|
26
|
+
return hash_hex[:max_size]
|
27
|
+
|
28
|
+
return hash_hex
|
25
29
|
|
26
30
|
|
27
31
|
def get_global_unique_hash(workspace: str, type: str, name: str) -> str:
|
blaxel/common/logger.py
CHANGED
@@ -2,8 +2,55 @@
|
|
2
2
|
This module provides a custom colored formatter for logging and an initialization function
|
3
3
|
to set up logging configurations for Blaxel applications.
|
4
4
|
"""
|
5
|
-
|
5
|
+
import json
|
6
6
|
import logging
|
7
|
+
import os
|
8
|
+
from opentelemetry import trace
|
9
|
+
|
10
|
+
class JsonFormatter(logging.Formatter):
|
11
|
+
"""
|
12
|
+
A logger compatible with standard json logging.
|
13
|
+
"""
|
14
|
+
def __init__(self):
|
15
|
+
super().__init__()
|
16
|
+
self.trace_id_name = os.environ.get('BL_LOGGER_TRACE_ID', 'trace_id')
|
17
|
+
self.span_id_name = os.environ.get('BL_LOGGER_SPAN_ID', 'span_id')
|
18
|
+
self.labels_name = os.environ.get('BL_LOGGER_LABELS', 'labels')
|
19
|
+
self.trace_id_prefix = os.environ.get('BL_LOGGER_TRACE_ID_PREFIX', '')
|
20
|
+
self.span_id_prefix = os.environ.get('BL_LOGGER_SPAN_ID_PREFIX', '')
|
21
|
+
self.task_index = os.environ.get('BL_TASK_KEY', 'TASK_INDEX')
|
22
|
+
self.task_prefix = os.environ.get('BL_TASK_PREFIX', '')
|
23
|
+
self.execution_key = os.environ.get('BL_EXECUTION_KEY', 'BL_EXECUTION_ID')
|
24
|
+
self.execution_prefix = os.environ.get('BL_EXECUTION_PREFIX', '')
|
25
|
+
|
26
|
+
def format(self, record):
|
27
|
+
"""
|
28
|
+
Formats the log record by converting it to a JSON object with trace context and environment variables.
|
29
|
+
"""
|
30
|
+
log_entry = {
|
31
|
+
'message': record.getMessage(),
|
32
|
+
'severity': record.levelname,
|
33
|
+
self.labels_name: {}
|
34
|
+
}
|
35
|
+
|
36
|
+
# Add trace context if available
|
37
|
+
current_span = trace.get_current_span()
|
38
|
+
if current_span.is_recording():
|
39
|
+
span_context = current_span.get_span_context()
|
40
|
+
log_entry[self.trace_id_name] = f"{self.trace_id_prefix}{span_context.trace_id}"
|
41
|
+
log_entry[self.span_id_name] = f"{self.span_id_prefix}{span_context.span_id}"
|
42
|
+
|
43
|
+
# Add task ID if available
|
44
|
+
task_id = os.environ.get(self.task_index)
|
45
|
+
if task_id:
|
46
|
+
log_entry[self.labels_name]['blaxel-task'] = f"{self.task_prefix}{task_id}"
|
47
|
+
|
48
|
+
# Add execution ID if available
|
49
|
+
execution_id = os.environ.get(self.execution_key)
|
50
|
+
if execution_id:
|
51
|
+
log_entry[self.labels_name]['blaxel-execution'] = f"{self.execution_prefix}{execution_id.split('-')[-1]}"
|
52
|
+
|
53
|
+
return json.dumps(log_entry)
|
7
54
|
|
8
55
|
|
9
56
|
class ColoredFormatter(logging.Formatter):
|
@@ -51,5 +98,10 @@ def init_logger(log_level: str):
|
|
51
98
|
logging.getLogger('urllib3').setLevel(logging.CRITICAL)
|
52
99
|
logging.getLogger("httpx").setLevel(logging.CRITICAL)
|
53
100
|
handler = logging.StreamHandler()
|
54
|
-
|
101
|
+
|
102
|
+
logger_type = os.environ.get("BL_LOGGER", "http")
|
103
|
+
if logger_type == "json":
|
104
|
+
handler.setFormatter(JsonFormatter())
|
105
|
+
else:
|
106
|
+
handler.setFormatter(ColoredFormatter("%(levelname)s %(name)s - %(message)s"))
|
55
107
|
logging.basicConfig(level=log_level, handlers=[handler])
|
blaxel/common/settings.py
CHANGED
@@ -62,9 +62,14 @@ class Settings:
|
|
62
62
|
@property
|
63
63
|
def run_internal_hostname(self) -> str:
|
64
64
|
"""Get the run internal hostname."""
|
65
|
-
|
66
|
-
|
67
|
-
|
65
|
+
if self.generation == "":
|
66
|
+
return ""
|
67
|
+
return os.environ.get("BL_RUN_INTERNAL_HOST", "")
|
68
|
+
|
69
|
+
@property
|
70
|
+
def generation(self) -> str:
|
71
|
+
"""Get the generation."""
|
72
|
+
return os.environ.get("BL_GENERATION", "")
|
68
73
|
|
69
74
|
@property
|
70
75
|
def bl_cloud(self) -> bool:
|
@@ -7,6 +7,7 @@ import importlib
|
|
7
7
|
import logging
|
8
8
|
import signal
|
9
9
|
import time
|
10
|
+
import os
|
10
11
|
from typing import Any, Dict, List, Optional, Type
|
11
12
|
|
12
13
|
from opentelemetry import metrics, trace
|
@@ -164,14 +165,15 @@ class TelemetryManager:
|
|
164
165
|
metrics.set_meter_provider(meter_provider)
|
165
166
|
self.meter = meter_provider.get_meter(__name__)
|
166
167
|
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
168
|
+
logger_type = os.environ.get("BL_LOGGER", "http")
|
169
|
+
if logger_type == "http":
|
170
|
+
self.logger_provider = LoggerProvider(resource=resource)
|
171
|
+
set_logger_provider(self.logger_provider)
|
172
|
+
self.logger_provider.add_log_record_processor(
|
173
|
+
AsyncLogRecordProcessor(self.get_log_exporter())
|
174
|
+
)
|
175
|
+
handler = LoggingHandler(level=logging.NOTSET, logger_provider=self.logger_provider)
|
176
|
+
logging.getLogger().addHandler(handler)
|
175
177
|
|
176
178
|
# Load and enable instrumentations
|
177
179
|
for name, mapping in MAPPINGS.items():
|
blaxel/jobs/__init__.py
ADDED
@@ -0,0 +1,187 @@
|
|
1
|
+
import argparse
|
2
|
+
import os
|
3
|
+
import sys
|
4
|
+
import asyncio
|
5
|
+
import json
|
6
|
+
import requests
|
7
|
+
|
8
|
+
|
9
|
+
from typing import Any, Dict, Callable, Awaitable
|
10
|
+
from logging import getLogger
|
11
|
+
from ..client import client
|
12
|
+
from ..common.env import env
|
13
|
+
from ..common.internal import get_global_unique_hash
|
14
|
+
from ..common.settings import settings
|
15
|
+
from ..instrumentation.span import SpanManager
|
16
|
+
|
17
|
+
|
18
|
+
|
19
|
+
class BlJobWrapper:
|
20
|
+
def get_arguments(self) -> Dict[str, Any]:
|
21
|
+
if not os.getenv('BL_EXECUTION_DATA_URL'):
|
22
|
+
parser = argparse.ArgumentParser()
|
23
|
+
# Parse known args, ignore unknown
|
24
|
+
args, unknown = parser.parse_known_args()
|
25
|
+
# Convert to dict and include unknown args
|
26
|
+
args_dict = vars(args)
|
27
|
+
# Add unknown args to dict
|
28
|
+
for i in range(0, len(unknown), 2):
|
29
|
+
if i + 1 < len(unknown):
|
30
|
+
key = unknown[i].lstrip('-')
|
31
|
+
args_dict[key] = unknown[i + 1]
|
32
|
+
return args_dict
|
33
|
+
|
34
|
+
response = requests.get(os.getenv('BL_EXECUTION_DATA_URL'))
|
35
|
+
data = response.json()
|
36
|
+
tasks = data.get('tasks', [])
|
37
|
+
return tasks[self.index] if self.index < len(tasks) else {}
|
38
|
+
|
39
|
+
@property
|
40
|
+
def index_key(self) -> str:
|
41
|
+
return os.getenv('BL_TASK_KEY', 'TASK_INDEX')
|
42
|
+
|
43
|
+
@property
|
44
|
+
def index(self) -> int:
|
45
|
+
index_value = os.getenv(self.index_key)
|
46
|
+
return int(index_value) if index_value else 0
|
47
|
+
|
48
|
+
def start(self, func: Callable):
|
49
|
+
"""
|
50
|
+
Run a job defined in a function, it's run in the current process.
|
51
|
+
Handles both async and sync functions.
|
52
|
+
Arguments are passed as keyword arguments to the function.
|
53
|
+
"""
|
54
|
+
try:
|
55
|
+
parsed_args = self.get_arguments()
|
56
|
+
if asyncio.iscoroutinefunction(func):
|
57
|
+
asyncio.run(func(**parsed_args))
|
58
|
+
else:
|
59
|
+
func(**parsed_args)
|
60
|
+
sys.exit(0)
|
61
|
+
except Exception as error:
|
62
|
+
print('Job execution failed:', error, file=sys.stderr)
|
63
|
+
sys.exit(1)
|
64
|
+
|
65
|
+
|
66
|
+
|
67
|
+
|
68
|
+
logger = getLogger(__name__)
|
69
|
+
|
70
|
+
class BlJob:
|
71
|
+
def __init__(self, name: str):
|
72
|
+
self.name = name
|
73
|
+
|
74
|
+
@property
|
75
|
+
def internal_url(self):
|
76
|
+
"""Get the internal URL for the job using a hash of workspace and job name."""
|
77
|
+
hash = get_global_unique_hash(settings.workspace, "job", self.name)
|
78
|
+
return f"{settings.run_internal_protocol}://bl-{settings.env}-{hash}.{settings.run_internal_hostname}"
|
79
|
+
|
80
|
+
@property
|
81
|
+
def forced_url(self):
|
82
|
+
"""Get the forced URL from environment variables if set."""
|
83
|
+
env_var = self.name.replace("-", "_").upper()
|
84
|
+
if env[f"BL_JOB_{env_var}_URL"]:
|
85
|
+
return env[f"BL_JOB_{env_var}_URL"]
|
86
|
+
return None
|
87
|
+
|
88
|
+
@property
|
89
|
+
def external_url(self):
|
90
|
+
return f"{settings.run_url}/{settings.workspace}/jobs/{self.name}"
|
91
|
+
|
92
|
+
@property
|
93
|
+
def fallback_url(self):
|
94
|
+
if self.external_url != self.url:
|
95
|
+
return self.external_url
|
96
|
+
return None
|
97
|
+
|
98
|
+
@property
|
99
|
+
def url(self):
|
100
|
+
if self.forced_url:
|
101
|
+
return self.forced_url
|
102
|
+
if settings.run_internal_hostname:
|
103
|
+
return self.internal_url
|
104
|
+
return self.external_url
|
105
|
+
|
106
|
+
def call(self, url, input_data, headers: dict = {}, params: dict = {}):
|
107
|
+
body = {
|
108
|
+
"tasks": input_data
|
109
|
+
}
|
110
|
+
|
111
|
+
return client.get_httpx_client().post(
|
112
|
+
url+"/executions",
|
113
|
+
headers={
|
114
|
+
'Content-Type': 'application/json',
|
115
|
+
**headers
|
116
|
+
},
|
117
|
+
json=body,
|
118
|
+
params=params
|
119
|
+
)
|
120
|
+
|
121
|
+
async def acall(self, url, input_data, headers: dict = {}, params: dict = {}):
|
122
|
+
logger.debug(f"Job Calling: {self.name}")
|
123
|
+
body = {
|
124
|
+
"tasks": input_data
|
125
|
+
}
|
126
|
+
|
127
|
+
return await client.get_async_httpx_client().post(
|
128
|
+
url+"/executions",
|
129
|
+
headers={
|
130
|
+
'Content-Type': 'application/json',
|
131
|
+
**headers
|
132
|
+
},
|
133
|
+
json=body,
|
134
|
+
params=params
|
135
|
+
)
|
136
|
+
|
137
|
+
def run(self, input: Any, headers: dict = {}, params: dict = {}) -> str:
|
138
|
+
attributes = {
|
139
|
+
"job.name": self.name,
|
140
|
+
"span.type": "job.run",
|
141
|
+
}
|
142
|
+
with SpanManager("blaxel-tracer").create_active_span(self.name, attributes) as span:
|
143
|
+
logger.debug(f"Job Calling: {self.name}")
|
144
|
+
response = self.call(self.url, input, headers, params)
|
145
|
+
if response.status_code >= 400:
|
146
|
+
if not self.fallback_url:
|
147
|
+
span.set_attribute("job.run.error", response.text)
|
148
|
+
raise Exception(f"Job {self.name} returned status code {response.status_code} with body {response.text}")
|
149
|
+
response = self.call(self.fallback_url, input, headers, params)
|
150
|
+
if response.status_code >= 400:
|
151
|
+
span.set_attribute("job.run.error", response.text)
|
152
|
+
raise Exception(f"Job {self.name} returned status code {response.status_code} with body {response.text}")
|
153
|
+
span.set_attribute("job.run.result", response.text)
|
154
|
+
return response.text
|
155
|
+
|
156
|
+
async def arun(self, input: Any, headers: dict = {}, params: dict = {}) -> Awaitable[str]:
|
157
|
+
attributes = {
|
158
|
+
"job.name": self.name,
|
159
|
+
"span.type": "job.run",
|
160
|
+
}
|
161
|
+
with SpanManager("blaxel-tracer").create_active_span(self.name, attributes) as span:
|
162
|
+
logger.debug(f"Job Calling: {self.name}")
|
163
|
+
response = await self.acall(self.url, input, headers, params)
|
164
|
+
if response.status_code >= 400:
|
165
|
+
if not self.fallback_url:
|
166
|
+
span.set_attribute("job.run.error", response.text)
|
167
|
+
raise Exception(f"Job {self.name} returned status code {response.status_code} with body {response.text}")
|
168
|
+
response = await self.acall(self.fallback_url, input, headers, params)
|
169
|
+
if response.status_code >= 400:
|
170
|
+
span.set_attribute("job.run.error", response.text)
|
171
|
+
raise Exception(f"Job {self.name} returned status code {response.status_code} with body {response.text}")
|
172
|
+
span.set_attribute("job.run.result", response.text)
|
173
|
+
return response.text
|
174
|
+
|
175
|
+
def __str__(self):
|
176
|
+
return f"Job {self.name}"
|
177
|
+
|
178
|
+
def __repr__(self):
|
179
|
+
return self.__str__()
|
180
|
+
|
181
|
+
|
182
|
+
|
183
|
+
def bl_job(name: str):
|
184
|
+
return BlJob(name)
|
185
|
+
|
186
|
+
# Create a singleton instance
|
187
|
+
bl_start_job = BlJobWrapper()
|
@@ -1,13 +1,13 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: blaxel
|
3
|
-
Version: 0.1.
|
3
|
+
Version: 0.1.14.dev3
|
4
4
|
Summary: Add your description here
|
5
5
|
Author-email: cploujoux <cploujoux@blaxel.ai>
|
6
6
|
License-File: LICENSE
|
7
7
|
Requires-Python: >=3.10
|
8
8
|
Requires-Dist: attrs>=21.3.0
|
9
9
|
Requires-Dist: httpx>=0.27.0
|
10
|
-
Requires-Dist: mcp
|
10
|
+
Requires-Dist: mcp<=1.7.1
|
11
11
|
Requires-Dist: opentelemetry-api>=1.28.0
|
12
12
|
Requires-Dist: opentelemetry-exporter-otlp>=1.28.0
|
13
13
|
Requires-Dist: opentelemetry-instrumentation-anthropic==0.35.0
|
@@ -2,7 +2,7 @@ blaxel/__init__.py,sha256=qmuJKjl5oGnjj4TbqHcJqUkKoxk4PvCsMb6-8rp67pE,159
|
|
2
2
|
blaxel/agents/__init__.py,sha256=RDWkvfICIXXaQxJuuSu63jsFj_F8NBAL4U752hfN4AE,5262
|
3
3
|
blaxel/authentication/__init__.py,sha256=tL9XKNCek5ixszTqjlKRBvidXMg4Nj6ODlBKlxxA9uk,3283
|
4
4
|
blaxel/authentication/apikey.py,sha256=nOgLVba7EfVk3V-qm7cj-30LAL-BT7NOMIlGL9Ni1jY,1249
|
5
|
-
blaxel/authentication/clientcredentials.py,sha256=
|
5
|
+
blaxel/authentication/clientcredentials.py,sha256=7ZrqsXTQTBmCzzrWWUl9qRqq7ZPjucBWQ6dzFCB7JT4,3804
|
6
6
|
blaxel/authentication/devicemode.py,sha256=kWbArs4okIIDqW-ql5oV2eQRE_LpRwfadCB6LG83irw,5986
|
7
7
|
blaxel/authentication/oauth.py,sha256=Q5J0taIK1JrvGB6BC-zz3hM77HPCNu01DPGf4l7xjPQ,1417
|
8
8
|
blaxel/authentication/types.py,sha256=E3lmfbmZuJ4Bc_kGA0Kc0GZC02Sjha1_2CbabP7z6oo,1603
|
@@ -262,14 +262,15 @@ blaxel/client/models/workspace_runtime.py,sha256=dxEpmwCFPOCRKHRKhY-iW7j6TbtL5qU
|
|
262
262
|
blaxel/client/models/workspace_user.py,sha256=70CcifQWYbeWG7TDui4pblTzUe5sVK0AS19vNCzKE8g,3423
|
263
263
|
blaxel/common/autoload.py,sha256=NFuK71-IHOY2JQyEBSjDCVfUaQ8D8PJsEUEryIdG4AU,263
|
264
264
|
blaxel/common/env.py,sha256=wTbzPDdNgz4HMJiS2NCZmQlN0qpxy1PQEYBaZgtvhoc,1247
|
265
|
-
blaxel/common/internal.py,sha256=
|
266
|
-
blaxel/common/logger.py,sha256=
|
267
|
-
blaxel/common/settings.py,sha256=
|
265
|
+
blaxel/common/internal.py,sha256=PExgeKfJEmjINKreNb3r2nB5GAfG7uJhbfqHxuxBED8,2395
|
266
|
+
blaxel/common/logger.py,sha256=7oWvrZ4fg7qUfrXe7oFAeH-1pTxadrvWQmPDn7bvbmQ,4111
|
267
|
+
blaxel/common/settings.py,sha256=7KTryuBdud0IfHqykX7xEEtpgq5M5h1Z8YEzYKsHB-Q,2327
|
268
268
|
blaxel/instrumentation/exporters.py,sha256=EoX3uaBVku1Rg49pSNXKFyHhgY5OV3Ih6UlqgjF5epw,1670
|
269
269
|
blaxel/instrumentation/log.py,sha256=4tGyvLg6r4DbjqJfajYbbZ1toUzF4Q4H7kHVqYWFAEA,2537
|
270
|
-
blaxel/instrumentation/manager.py,sha256=
|
270
|
+
blaxel/instrumentation/manager.py,sha256=vX8RT84upjzgCUeiULp9QpDSSNVnPNFxLq0sMVz4Pjs,8974
|
271
271
|
blaxel/instrumentation/map.py,sha256=zZoiUiQHmik5WQZ4VCWNARSa6ppMi0r7D6hlb41N-Mg,1589
|
272
272
|
blaxel/instrumentation/span.py,sha256=X2lwfu_dyxwQTMQJT2vbXOrbVSChEhjRLc413QOxQJM,3244
|
273
|
+
blaxel/jobs/__init__.py,sha256=4Mk-S_eT-bV-bI9Y_TOfisv_rxme9O1Z69AgmDoAKTY,6510
|
273
274
|
blaxel/mcp/__init__.py,sha256=KednMrtuc4Y0O3lv7u1Lla54FCk8UX9c1k0USjL3Ahk,69
|
274
275
|
blaxel/mcp/client.py,sha256=cFFXfpKXoMu8qTUly2ejF0pX2iBQkSNAxqwvDV1V6xY,4979
|
275
276
|
blaxel/mcp/server.py,sha256=GIldtA_NgIc2dzd7ZpPvpbhpIt_7AfKu5yS_YJ0bDGg,7310
|
@@ -340,7 +341,7 @@ blaxel/tools/llamaindex.py,sha256=-gQ-C9V_h9a11J4ItsbWjXrCJOg0lRKsb98v9rVsNak,71
|
|
340
341
|
blaxel/tools/openai.py,sha256=GuFXkj6bXEwldyVr89jEsRAi5ihZUVEVe327QuWiGNs,653
|
341
342
|
blaxel/tools/pydantic.py,sha256=CvnNbAG_J4yBtA-XFI4lQrq3FYKjNd39hu841vZT004,1801
|
342
343
|
blaxel/tools/types.py,sha256=YPCGJ4vZDhqR0X2H_TWtc5chQScsC32nGTQdRKJlO8Y,707
|
343
|
-
blaxel-0.1.
|
344
|
-
blaxel-0.1.
|
345
|
-
blaxel-0.1.
|
346
|
-
blaxel-0.1.
|
344
|
+
blaxel-0.1.14.dev3.dist-info/METADATA,sha256=wwb37Z03Dg-wMo0jN0MhdZUf-uA5lLlKrdbywdH8hMM,11777
|
345
|
+
blaxel-0.1.14.dev3.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
346
|
+
blaxel-0.1.14.dev3.dist-info/licenses/LICENSE,sha256=p5PNQvpvyDT_0aYBDgmV1fFI_vAD2aSV0wWG7VTgRis,1069
|
347
|
+
blaxel-0.1.14.dev3.dist-info/RECORD,,
|
File without changes
|
File without changes
|