casual-llm 0.4.2__tar.gz → 0.4.3__tar.gz
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.
- {casual_llm-0.4.2/src/casual_llm.egg-info → casual_llm-0.4.3}/PKG-INFO +1 -1
- {casual_llm-0.4.2 → casual_llm-0.4.3}/pyproject.toml +1 -1
- {casual_llm-0.4.2 → casual_llm-0.4.3}/src/casual_llm/__init__.py +1 -1
- {casual_llm-0.4.2 → casual_llm-0.4.3}/src/casual_llm/tools.py +8 -2
- {casual_llm-0.4.2 → casual_llm-0.4.3/src/casual_llm.egg-info}/PKG-INFO +1 -1
- {casual_llm-0.4.2 → casual_llm-0.4.3}/tests/test_tools.py +64 -0
- {casual_llm-0.4.2 → casual_llm-0.4.3}/LICENSE +0 -0
- {casual_llm-0.4.2 → casual_llm-0.4.3}/README.md +0 -0
- {casual_llm-0.4.2 → casual_llm-0.4.3}/setup.cfg +0 -0
- {casual_llm-0.4.2 → casual_llm-0.4.3}/src/casual_llm/config.py +0 -0
- {casual_llm-0.4.2 → casual_llm-0.4.3}/src/casual_llm/message_converters/__init__.py +0 -0
- {casual_llm-0.4.2 → casual_llm-0.4.3}/src/casual_llm/message_converters/anthropic.py +0 -0
- {casual_llm-0.4.2 → casual_llm-0.4.3}/src/casual_llm/message_converters/ollama.py +0 -0
- {casual_llm-0.4.2 → casual_llm-0.4.3}/src/casual_llm/message_converters/openai.py +0 -0
- {casual_llm-0.4.2 → casual_llm-0.4.3}/src/casual_llm/messages.py +0 -0
- {casual_llm-0.4.2 → casual_llm-0.4.3}/src/casual_llm/providers/__init__.py +0 -0
- {casual_llm-0.4.2 → casual_llm-0.4.3}/src/casual_llm/providers/anthropic.py +0 -0
- {casual_llm-0.4.2 → casual_llm-0.4.3}/src/casual_llm/providers/base.py +0 -0
- {casual_llm-0.4.2 → casual_llm-0.4.3}/src/casual_llm/providers/ollama.py +0 -0
- {casual_llm-0.4.2 → casual_llm-0.4.3}/src/casual_llm/providers/openai.py +0 -0
- {casual_llm-0.4.2 → casual_llm-0.4.3}/src/casual_llm/py.typed +0 -0
- {casual_llm-0.4.2 → casual_llm-0.4.3}/src/casual_llm/tool_converters/__init__.py +0 -0
- {casual_llm-0.4.2 → casual_llm-0.4.3}/src/casual_llm/tool_converters/anthropic.py +0 -0
- {casual_llm-0.4.2 → casual_llm-0.4.3}/src/casual_llm/tool_converters/ollama.py +0 -0
- {casual_llm-0.4.2 → casual_llm-0.4.3}/src/casual_llm/tool_converters/openai.py +0 -0
- {casual_llm-0.4.2 → casual_llm-0.4.3}/src/casual_llm/usage.py +0 -0
- {casual_llm-0.4.2 → casual_llm-0.4.3}/src/casual_llm/utils/__init__.py +0 -0
- {casual_llm-0.4.2 → casual_llm-0.4.3}/src/casual_llm/utils/image.py +0 -0
- {casual_llm-0.4.2 → casual_llm-0.4.3}/src/casual_llm.egg-info/SOURCES.txt +0 -0
- {casual_llm-0.4.2 → casual_llm-0.4.3}/src/casual_llm.egg-info/dependency_links.txt +0 -0
- {casual_llm-0.4.2 → casual_llm-0.4.3}/src/casual_llm.egg-info/requires.txt +0 -0
- {casual_llm-0.4.2 → casual_llm-0.4.3}/src/casual_llm.egg-info/top_level.txt +0 -0
- {casual_llm-0.4.2 → casual_llm-0.4.3}/tests/test_anthropic_provider.py +0 -0
- {casual_llm-0.4.2 → casual_llm-0.4.3}/tests/test_backward_compatibility.py +0 -0
- {casual_llm-0.4.2 → casual_llm-0.4.3}/tests/test_image_utils.py +0 -0
- {casual_llm-0.4.2 → casual_llm-0.4.3}/tests/test_messages.py +0 -0
- {casual_llm-0.4.2 → casual_llm-0.4.3}/tests/test_providers.py +0 -0
- {casual_llm-0.4.2 → casual_llm-0.4.3}/tests/test_vision_integration.py +0 -0
- {casual_llm-0.4.2 → casual_llm-0.4.3}/tests/test_vision_ollama.py +0 -0
- {casual_llm-0.4.2 → casual_llm-0.4.3}/tests/test_vision_openai.py +0 -0
|
@@ -7,7 +7,7 @@ A simple, protocol-based library for working with different LLM providers
|
|
|
7
7
|
Part of the casual-* ecosystem of lightweight AI tools.
|
|
8
8
|
"""
|
|
9
9
|
|
|
10
|
-
__version__ = "0.4.
|
|
10
|
+
__version__ = "0.4.3"
|
|
11
11
|
|
|
12
12
|
# Model configuration
|
|
13
13
|
from casual_llm.config import ModelConfig, Provider
|
|
@@ -7,6 +7,7 @@ Provides unified tool models compatible with Ollama, OpenAI, and MCP.
|
|
|
7
7
|
from __future__ import annotations
|
|
8
8
|
|
|
9
9
|
from typing import Any
|
|
10
|
+
|
|
10
11
|
from pydantic import BaseModel, Field
|
|
11
12
|
|
|
12
13
|
|
|
@@ -14,10 +15,13 @@ class ToolParameter(BaseModel):
|
|
|
14
15
|
"""
|
|
15
16
|
A single tool parameter definition following JSON Schema.
|
|
16
17
|
|
|
17
|
-
Supports common JSON Schema fields for describing function parameters
|
|
18
|
+
Supports common JSON Schema fields for describing function parameters,
|
|
19
|
+
including union types via anyOf/oneOf schemas.
|
|
18
20
|
"""
|
|
19
21
|
|
|
20
|
-
type: str
|
|
22
|
+
type: str | None = Field(
|
|
23
|
+
None, description="JSON Schema type (string, number, object, array, etc.)"
|
|
24
|
+
)
|
|
21
25
|
description: str | None = Field(None, description="Parameter description")
|
|
22
26
|
enum: list[Any] | None = Field(None, description="Allowed values for enum types")
|
|
23
27
|
items: dict[str, Any] | None = Field(None, description="Array item schema")
|
|
@@ -26,6 +30,8 @@ class ToolParameter(BaseModel):
|
|
|
26
30
|
)
|
|
27
31
|
required: list[str] | None = Field(None, description="Required properties for nested objects")
|
|
28
32
|
default: Any | None = Field(None, description="Default value")
|
|
33
|
+
anyOf: list[dict[str, Any]] | None = Field(None, description="Union type schemas")
|
|
34
|
+
oneOf: list[dict[str, Any]] | None = Field(None, description="Exclusive union type schemas")
|
|
29
35
|
|
|
30
36
|
model_config = {"extra": "allow"} # Allow additional JSON Schema fields
|
|
31
37
|
|
|
@@ -71,6 +71,35 @@ class TestToolParameter:
|
|
|
71
71
|
assert dumped["maxLength"] == 100
|
|
72
72
|
assert dumped["pattern"] == "^[a-z]+$"
|
|
73
73
|
|
|
74
|
+
def test_anyof_parameter(self):
|
|
75
|
+
"""Test parameter with anyOf union type."""
|
|
76
|
+
param = ToolParameter(
|
|
77
|
+
anyOf=[{"type": "string"}, {"type": "null"}],
|
|
78
|
+
description="Optional string",
|
|
79
|
+
)
|
|
80
|
+
assert param.type is None
|
|
81
|
+
assert param.anyOf is not None
|
|
82
|
+
|
|
83
|
+
def test_oneof_parameter(self):
|
|
84
|
+
"""Test parameter with oneOf exclusive union type."""
|
|
85
|
+
param = ToolParameter(
|
|
86
|
+
oneOf=[{"type": "string"}, {"type": "number"}],
|
|
87
|
+
description="String or number",
|
|
88
|
+
)
|
|
89
|
+
assert param.type is None
|
|
90
|
+
assert param.oneOf is not None
|
|
91
|
+
|
|
92
|
+
def test_anyof_serialization(self):
|
|
93
|
+
"""Test that anyOf is properly serialized."""
|
|
94
|
+
param = ToolParameter(
|
|
95
|
+
anyOf=[{"type": "string"}, {"type": "null"}],
|
|
96
|
+
description="Optional",
|
|
97
|
+
)
|
|
98
|
+
dumped = param.model_dump(exclude_none=True)
|
|
99
|
+
assert "anyOf" in dumped
|
|
100
|
+
assert len(dumped["anyOf"]) == 2
|
|
101
|
+
assert "type" not in dumped # type is None, excluded
|
|
102
|
+
|
|
74
103
|
|
|
75
104
|
class TestTool:
|
|
76
105
|
"""Tests for Tool model."""
|
|
@@ -188,6 +217,41 @@ class TestTool:
|
|
|
188
217
|
assert reconstructed.required == original_tool.required
|
|
189
218
|
assert len(reconstructed.parameters) == len(original_tool.parameters)
|
|
190
219
|
|
|
220
|
+
def test_input_schema_with_anyof(self):
|
|
221
|
+
"""Test that input_schema preserves anyOf without injecting type."""
|
|
222
|
+
tool = Tool(
|
|
223
|
+
name="test",
|
|
224
|
+
description="Test",
|
|
225
|
+
parameters={
|
|
226
|
+
"optional_field": ToolParameter(
|
|
227
|
+
anyOf=[{"type": "string"}, {"type": "null"}],
|
|
228
|
+
description="An optional string",
|
|
229
|
+
)
|
|
230
|
+
},
|
|
231
|
+
)
|
|
232
|
+
schema = tool.input_schema
|
|
233
|
+
# anyOf should be preserved as-is
|
|
234
|
+
assert "anyOf" in schema["properties"]["optional_field"]
|
|
235
|
+
# type should NOT be injected (anyOf is valid JSON Schema)
|
|
236
|
+
assert "type" not in schema["properties"]["optional_field"]
|
|
237
|
+
|
|
238
|
+
def test_input_schema_with_oneof(self):
|
|
239
|
+
"""Test that input_schema preserves oneOf without injecting type."""
|
|
240
|
+
tool = Tool(
|
|
241
|
+
name="test",
|
|
242
|
+
description="Test",
|
|
243
|
+
parameters={
|
|
244
|
+
"mixed_field": ToolParameter(
|
|
245
|
+
oneOf=[{"type": "number"}, {"type": "string"}],
|
|
246
|
+
)
|
|
247
|
+
},
|
|
248
|
+
)
|
|
249
|
+
schema = tool.input_schema
|
|
250
|
+
# oneOf should be preserved as-is
|
|
251
|
+
assert "oneOf" in schema["properties"]["mixed_field"]
|
|
252
|
+
# type should NOT be injected
|
|
253
|
+
assert "type" not in schema["properties"]["mixed_field"]
|
|
254
|
+
|
|
191
255
|
|
|
192
256
|
class TestOllamaConverters:
|
|
193
257
|
"""Tests for Ollama format converters."""
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|