blaxel 0.2.36__py3-none-any.whl → 0.2.38__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.
Files changed (55) hide show
  1. blaxel/__init__.py +2 -2
  2. blaxel/core/client/models/create_job_execution_request_env.py +3 -3
  3. blaxel/core/client/models/preview.py +48 -1
  4. blaxel/core/client/models/sandbox.py +10 -0
  5. blaxel/core/jobs/__init__.py +2 -2
  6. blaxel/core/sandbox/__init__.py +12 -0
  7. blaxel/core/sandbox/client/api/system/__init__.py +0 -0
  8. blaxel/core/sandbox/client/api/system/get_health.py +134 -0
  9. blaxel/core/sandbox/client/api/system/post_upgrade.py +196 -0
  10. blaxel/core/sandbox/client/models/__init__.py +8 -0
  11. blaxel/core/sandbox/client/models/content_search_match.py +24 -25
  12. blaxel/core/sandbox/client/models/content_search_response.py +25 -29
  13. blaxel/core/sandbox/client/models/find_match.py +13 -14
  14. blaxel/core/sandbox/client/models/find_response.py +21 -24
  15. blaxel/core/sandbox/client/models/fuzzy_search_match.py +17 -19
  16. blaxel/core/sandbox/client/models/fuzzy_search_response.py +21 -24
  17. blaxel/core/sandbox/client/models/health_response.py +159 -0
  18. blaxel/core/sandbox/client/models/process_upgrade_state.py +20 -0
  19. blaxel/core/sandbox/client/models/upgrade_request.py +71 -0
  20. blaxel/core/sandbox/client/models/upgrade_status.py +125 -0
  21. blaxel/core/sandbox/default/__init__.py +2 -0
  22. blaxel/core/sandbox/default/filesystem.py +20 -6
  23. blaxel/core/sandbox/default/preview.py +48 -1
  24. blaxel/core/sandbox/default/process.py +66 -21
  25. blaxel/core/sandbox/default/sandbox.py +36 -5
  26. blaxel/core/sandbox/default/system.py +71 -0
  27. blaxel/core/sandbox/sync/__init__.py +2 -0
  28. blaxel/core/sandbox/sync/filesystem.py +19 -2
  29. blaxel/core/sandbox/sync/preview.py +50 -3
  30. blaxel/core/sandbox/sync/process.py +38 -15
  31. blaxel/core/sandbox/sync/sandbox.py +29 -4
  32. blaxel/core/sandbox/sync/system.py +71 -0
  33. blaxel/core/sandbox/types.py +212 -5
  34. blaxel/core/tools/__init__.py +4 -0
  35. blaxel/core/volume/volume.py +10 -0
  36. blaxel/crewai/model.py +81 -44
  37. blaxel/crewai/tools.py +85 -2
  38. blaxel/googleadk/model.py +22 -3
  39. blaxel/googleadk/tools.py +25 -6
  40. blaxel/langgraph/custom/gemini.py +19 -12
  41. blaxel/langgraph/model.py +26 -18
  42. blaxel/langgraph/tools.py +6 -12
  43. blaxel/livekit/model.py +7 -2
  44. blaxel/livekit/tools.py +3 -1
  45. blaxel/llamaindex/model.py +145 -84
  46. blaxel/llamaindex/tools.py +6 -4
  47. blaxel/openai/model.py +7 -1
  48. blaxel/openai/tools.py +13 -3
  49. blaxel/pydantic/model.py +38 -24
  50. blaxel/pydantic/tools.py +37 -4
  51. blaxel-0.2.38.dist-info/METADATA +528 -0
  52. {blaxel-0.2.36.dist-info → blaxel-0.2.38.dist-info}/RECORD +54 -45
  53. blaxel-0.2.36.dist-info/METADATA +0 -228
  54. {blaxel-0.2.36.dist-info → blaxel-0.2.38.dist-info}/WHEEL +0 -0
  55. {blaxel-0.2.36.dist-info → blaxel-0.2.38.dist-info}/licenses/LICENSE +0 -0
blaxel/openai/tools.py CHANGED
@@ -1,7 +1,8 @@
1
1
  import json
2
2
  from typing import Any
3
3
 
4
- from agents import FunctionTool, RunContextWrapper
4
+ from agents import FunctionTool # type: ignore[import-not-found]
5
+ from agents.tool_context import ToolContext # type: ignore[import-not-found]
5
6
 
6
7
  from blaxel.core.tools import bl_tools as bl_tools_core
7
8
  from blaxel.core.tools.types import Tool
@@ -24,6 +25,13 @@ def _clean_schema_for_openai(schema: dict) -> dict:
24
25
  if "additionalProperties" in cleaned_schema:
25
26
  del cleaned_schema["additionalProperties"]
26
27
 
28
+ # Ensure object type schemas have properties
29
+ if cleaned_schema.get("type") == "object":
30
+ if "properties" not in cleaned_schema:
31
+ cleaned_schema["properties"] = {}
32
+ if "required" not in cleaned_schema:
33
+ cleaned_schema["required"] = []
34
+
27
35
  # Recursively clean properties if they exist
28
36
  if "properties" in cleaned_schema:
29
37
  cleaned_schema["properties"] = {
@@ -39,9 +47,11 @@ def _clean_schema_for_openai(schema: dict) -> dict:
39
47
 
40
48
  def get_openai_tool(tool: Tool) -> FunctionTool:
41
49
  async def openai_coroutine(
42
- _: RunContextWrapper,
43
- arguments: dict[str, Any],
50
+ _: ToolContext[Any],
51
+ arguments: str,
44
52
  ) -> Any:
53
+ if not tool.coroutine:
54
+ raise ValueError(f"Tool {tool.name} does not have a coroutine defined")
45
55
  result = await tool.coroutine(**json.loads(arguments))
46
56
  return result
47
57
 
blaxel/pydantic/model.py CHANGED
@@ -1,7 +1,7 @@
1
1
  import logging
2
2
  from typing import Any
3
3
 
4
- from pydantic_ai.models import Model
4
+ from pydantic_ai.models import Model # type: ignore[import-not-found]
5
5
 
6
6
  from blaxel.core import bl_model as bl_model_core
7
7
  from blaxel.core import settings
@@ -30,8 +30,12 @@ class TokenRefreshingModel(Model):
30
30
 
31
31
  if type == "mistral":
32
32
  from mistralai.sdk import Mistral
33
- from pydantic_ai.models.mistral import MistralModel
34
- from pydantic_ai.providers.mistral import MistralProvider
33
+ from pydantic_ai.models.mistral import ( # type: ignore[import-not-found]
34
+ MistralModel,
35
+ )
36
+ from pydantic_ai.providers.mistral import ( # type: ignore[import-not-found]
37
+ MistralProvider,
38
+ )
35
39
 
36
40
  return MistralModel(
37
41
  model_name=model,
@@ -45,8 +49,12 @@ class TokenRefreshingModel(Model):
45
49
  )
46
50
  elif type == "cohere":
47
51
  from cohere import AsyncClientV2
48
- from pydantic_ai.models.cohere import CohereModel
49
- from pydantic_ai.providers.cohere import CohereProvider
52
+ from pydantic_ai.models.cohere import ( # type: ignore[import-not-found]
53
+ CohereModel,
54
+ )
55
+ from pydantic_ai.providers.cohere import ( # type: ignore[import-not-found]
56
+ CohereProvider,
57
+ )
50
58
 
51
59
  return CohereModel(
52
60
  model_name=model,
@@ -58,30 +66,42 @@ class TokenRefreshingModel(Model):
58
66
  ),
59
67
  )
60
68
  elif type == "xai":
61
- from pydantic_ai.models.openai import OpenAIModel
62
- from pydantic_ai.providers.openai import OpenAIProvider
69
+ from pydantic_ai.models.openai import ( # type: ignore[import-not-found]
70
+ OpenAIChatModel,
71
+ )
72
+ from pydantic_ai.providers.openai import ( # type: ignore[import-not-found]
73
+ OpenAIProvider,
74
+ )
63
75
 
64
- return OpenAIModel(
76
+ return OpenAIChatModel(
65
77
  model_name=model,
66
78
  provider=OpenAIProvider(
67
79
  base_url=f"{url}/v1", api_key=settings.auth.token, **kwargs
68
80
  ),
69
81
  )
70
82
  elif type == "deepseek":
71
- from pydantic_ai.models.openai import OpenAIModel
72
- from pydantic_ai.providers.openai import OpenAIProvider
83
+ from pydantic_ai.models.openai import ( # type: ignore[import-not-found]
84
+ OpenAIChatModel,
85
+ )
86
+ from pydantic_ai.providers.openai import ( # type: ignore[import-not-found]
87
+ OpenAIProvider,
88
+ )
73
89
 
74
- return OpenAIModel(
90
+ return OpenAIChatModel(
75
91
  model_name=model,
76
92
  provider=OpenAIProvider(
77
93
  base_url=f"{url}/v1", api_key=settings.auth.token, **kwargs
78
94
  ),
79
95
  )
80
96
  elif type == "cerebras":
81
- from pydantic_ai.models.openai import OpenAIModel
82
- from pydantic_ai.providers.openai import OpenAIProvider
97
+ from pydantic_ai.models.openai import ( # type: ignore[import-not-found]
98
+ OpenAIChatModel,
99
+ )
100
+ from pydantic_ai.providers.openai import ( # type: ignore[import-not-found]
101
+ OpenAIProvider,
102
+ )
83
103
 
84
- return OpenAIModel(
104
+ return OpenAIChatModel(
85
105
  model_name=model,
86
106
  provider=OpenAIProvider(
87
107
  base_url=f"{url}/v1", api_key=settings.auth.token, **kwargs
@@ -116,12 +136,12 @@ class TokenRefreshingModel(Model):
116
136
  ),
117
137
  )
118
138
  else:
119
- from pydantic_ai.models.openai import OpenAIModel
139
+ from pydantic_ai.models.openai import OpenAIChatModel
120
140
  from pydantic_ai.providers.openai import OpenAIProvider
121
141
 
122
142
  if type != "openai":
123
143
  logger.warning(f"Model {model} is not supported by Pydantic, defaulting to OpenAI")
124
- return OpenAIModel(
144
+ return OpenAIChatModel(
125
145
  model_name=model,
126
146
  provider=OpenAIProvider(
127
147
  base_url=f"{url}/v1", api_key=settings.auth.token, **kwargs
@@ -130,12 +150,6 @@ class TokenRefreshingModel(Model):
130
150
 
131
151
  def _get_fresh_model(self) -> Model:
132
152
  """Get or create a model with fresh token if needed."""
133
- # Only refresh if using ClientCredentials (which has get_token method)
134
- if hasattr(settings.auth, "get_token"):
135
- # This will trigger token refresh if needed
136
- logger.debug(f"Calling get_token for {self.model_config['type']} model")
137
- settings.auth.get_token()
138
-
139
153
  new_token = settings.auth.token
140
154
 
141
155
  # If token changed or no cached model, create new one
@@ -152,10 +166,10 @@ class TokenRefreshingModel(Model):
152
166
  return model.model_name
153
167
 
154
168
  @property
155
- def system(self) -> Any | None:
169
+ def system(self) -> str:
156
170
  """Return the system property from the wrapped model."""
157
171
  model = self._get_fresh_model()
158
- return model.system if hasattr(model, "system") else None
172
+ return model.system if hasattr(model, "system") else ""
159
173
 
160
174
  async def request(self, *args, **kwargs):
161
175
  """Make a request to the model with token refresh."""
blaxel/pydantic/tools.py CHANGED
@@ -1,11 +1,44 @@
1
- from pydantic_ai import RunContext
2
- from pydantic_ai.tools import Tool as PydanticTool
3
- from pydantic_ai.tools import ToolDefinition
1
+ from typing import Any
2
+
3
+ from pydantic_ai import RunContext # type: ignore[import-not-found]
4
+ from pydantic_ai.tools import Tool as PydanticTool # type: ignore[import-not-found]
5
+ from pydantic_ai.tools import ToolDefinition # type: ignore[import-not-found]
4
6
 
5
7
  from blaxel.core.tools import Tool
6
8
  from blaxel.core.tools import bl_tools as bl_tools_core
7
9
 
8
10
 
11
+ def _clean_schema_for_openai(schema: dict[str, Any]) -> dict[str, Any]:
12
+ """Clean JSON schema to be compatible with OpenAI function calling.
13
+
14
+ OpenAI requires object schemas to have a 'properties' field, even if empty.
15
+ """
16
+ if not isinstance(schema, dict):
17
+ return schema
18
+
19
+ cleaned = schema.copy()
20
+
21
+ if cleaned.get("type") == "object":
22
+ if "properties" not in cleaned:
23
+ cleaned["properties"] = {}
24
+ if "required" not in cleaned:
25
+ cleaned["required"] = []
26
+
27
+ if "additionalProperties" in cleaned:
28
+ del cleaned["additionalProperties"]
29
+ if "$schema" in cleaned:
30
+ del cleaned["$schema"]
31
+
32
+ if "properties" in cleaned:
33
+ cleaned["properties"] = {
34
+ k: _clean_schema_for_openai(v) for k, v in cleaned["properties"].items()
35
+ }
36
+ if "items" in cleaned and isinstance(cleaned["items"], dict):
37
+ cleaned["items"] = _clean_schema_for_openai(cleaned["items"])
38
+
39
+ return cleaned
40
+
41
+
9
42
  def get_pydantic_tool(tool: Tool) -> PydanticTool:
10
43
  """
11
44
  Converts a custom Tool object into a Pydantic AI Tool object.
@@ -27,7 +60,7 @@ def get_pydantic_tool(tool: Tool) -> PydanticTool:
27
60
  """Dynamically prepares the ToolDefinition using the custom Tool's attributes."""
28
61
  tool_def.name = tool.name # Override inferred name
29
62
  tool_def.description = tool.description # Override inferred description
30
- tool_def.parameters_json_schema = tool.input_schema
63
+ tool_def.parameters_json_schema = _clean_schema_for_openai(tool.input_schema)
31
64
  return tool_def
32
65
 
33
66
  async def pydantic_function(**kwargs):