agentic-data-contracts 0.2.2__tar.gz → 0.2.4__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.
- {agentic_data_contracts-0.2.2 → agentic_data_contracts-0.2.4}/CHANGELOG.md +19 -0
- {agentic_data_contracts-0.2.2 → agentic_data_contracts-0.2.4}/PKG-INFO +11 -12
- {agentic_data_contracts-0.2.2 → agentic_data_contracts-0.2.4}/README.md +8 -9
- {agentic_data_contracts-0.2.2 → agentic_data_contracts-0.2.4}/pyproject.toml +2 -2
- {agentic_data_contracts-0.2.2 → agentic_data_contracts-0.2.4}/src/agentic_data_contracts/__init__.py +7 -1
- {agentic_data_contracts-0.2.2 → agentic_data_contracts-0.2.4}/src/agentic_data_contracts/adapters/base.py +1 -0
- {agentic_data_contracts-0.2.2 → agentic_data_contracts-0.2.4}/src/agentic_data_contracts/adapters/duckdb.py +12 -0
- {agentic_data_contracts-0.2.2 → agentic_data_contracts-0.2.4}/src/agentic_data_contracts/core/contract.py +18 -0
- {agentic_data_contracts-0.2.2 → agentic_data_contracts-0.2.4}/src/agentic_data_contracts/tools/factory.py +9 -0
- agentic_data_contracts-0.2.4/src/agentic_data_contracts/tools/sdk.py +71 -0
- agentic_data_contracts-0.2.4/tests/test_core/test_wildcard_tables.py +106 -0
- agentic_data_contracts-0.2.4/tests/test_tools/test_sdk.py +116 -0
- agentic_data_contracts-0.2.4/tests/test_tools/test_wildcard_tools.py +76 -0
- {agentic_data_contracts-0.2.2 → agentic_data_contracts-0.2.4}/uv.lock +9 -9
- {agentic_data_contracts-0.2.2 → agentic_data_contracts-0.2.4}/.github/dependabot.yml +0 -0
- {agentic_data_contracts-0.2.2 → agentic_data_contracts-0.2.4}/.github/workflows/ci.yml +0 -0
- {agentic_data_contracts-0.2.2 → agentic_data_contracts-0.2.4}/.gitignore +0 -0
- {agentic_data_contracts-0.2.2 → agentic_data_contracts-0.2.4}/.pre-commit-config.yaml +0 -0
- {agentic_data_contracts-0.2.2 → agentic_data_contracts-0.2.4}/.python-version +0 -0
- {agentic_data_contracts-0.2.2 → agentic_data_contracts-0.2.4}/CLAUDE.md +0 -0
- {agentic_data_contracts-0.2.2 → agentic_data_contracts-0.2.4}/LICENSE +0 -0
- {agentic_data_contracts-0.2.2 → agentic_data_contracts-0.2.4}/docs/architecture.md +0 -0
- {agentic_data_contracts-0.2.2 → agentic_data_contracts-0.2.4}/examples/revenue_agent/agent.py +0 -0
- {agentic_data_contracts-0.2.2 → agentic_data_contracts-0.2.4}/examples/revenue_agent/contract.yml +0 -0
- {agentic_data_contracts-0.2.2 → agentic_data_contracts-0.2.4}/examples/revenue_agent/semantic.yml +0 -0
- {agentic_data_contracts-0.2.2 → agentic_data_contracts-0.2.4}/examples/revenue_agent/setup_db.py +0 -0
- {agentic_data_contracts-0.2.2 → agentic_data_contracts-0.2.4}/src/agentic_data_contracts/adapters/__init__.py +0 -0
- {agentic_data_contracts-0.2.2 → agentic_data_contracts-0.2.4}/src/agentic_data_contracts/bridge/__init__.py +0 -0
- {agentic_data_contracts-0.2.2 → agentic_data_contracts-0.2.4}/src/agentic_data_contracts/bridge/compiler.py +0 -0
- {agentic_data_contracts-0.2.2 → agentic_data_contracts-0.2.4}/src/agentic_data_contracts/core/__init__.py +0 -0
- {agentic_data_contracts-0.2.2 → agentic_data_contracts-0.2.4}/src/agentic_data_contracts/core/schema.py +0 -0
- {agentic_data_contracts-0.2.2 → agentic_data_contracts-0.2.4}/src/agentic_data_contracts/core/session.py +0 -0
- {agentic_data_contracts-0.2.2 → agentic_data_contracts-0.2.4}/src/agentic_data_contracts/py.typed +0 -0
- {agentic_data_contracts-0.2.2 → agentic_data_contracts-0.2.4}/src/agentic_data_contracts/semantic/__init__.py +0 -0
- {agentic_data_contracts-0.2.2 → agentic_data_contracts-0.2.4}/src/agentic_data_contracts/semantic/base.py +0 -0
- {agentic_data_contracts-0.2.2 → agentic_data_contracts-0.2.4}/src/agentic_data_contracts/semantic/cube.py +0 -0
- {agentic_data_contracts-0.2.2 → agentic_data_contracts-0.2.4}/src/agentic_data_contracts/semantic/dbt.py +0 -0
- {agentic_data_contracts-0.2.2 → agentic_data_contracts-0.2.4}/src/agentic_data_contracts/semantic/yaml_source.py +0 -0
- {agentic_data_contracts-0.2.2 → agentic_data_contracts-0.2.4}/src/agentic_data_contracts/tools/__init__.py +0 -0
- {agentic_data_contracts-0.2.2 → agentic_data_contracts-0.2.4}/src/agentic_data_contracts/tools/middleware.py +0 -0
- {agentic_data_contracts-0.2.2 → agentic_data_contracts-0.2.4}/src/agentic_data_contracts/validation/__init__.py +0 -0
- {agentic_data_contracts-0.2.2 → agentic_data_contracts-0.2.4}/src/agentic_data_contracts/validation/checkers.py +0 -0
- {agentic_data_contracts-0.2.2 → agentic_data_contracts-0.2.4}/src/agentic_data_contracts/validation/explain.py +0 -0
- {agentic_data_contracts-0.2.2 → agentic_data_contracts-0.2.4}/src/agentic_data_contracts/validation/validator.py +0 -0
- {agentic_data_contracts-0.2.2 → agentic_data_contracts-0.2.4}/tests/__init__.py +0 -0
- {agentic_data_contracts-0.2.2 → agentic_data_contracts-0.2.4}/tests/conftest.py +0 -0
- {agentic_data_contracts-0.2.2 → agentic_data_contracts-0.2.4}/tests/fixtures/minimal_contract.yml +0 -0
- {agentic_data_contracts-0.2.2 → agentic_data_contracts-0.2.4}/tests/fixtures/sample_cube_schema.yml +0 -0
- {agentic_data_contracts-0.2.2 → agentic_data_contracts-0.2.4}/tests/fixtures/sample_dbt_manifest.json +0 -0
- {agentic_data_contracts-0.2.2 → agentic_data_contracts-0.2.4}/tests/fixtures/semantic_source.yml +0 -0
- {agentic_data_contracts-0.2.2 → agentic_data_contracts-0.2.4}/tests/fixtures/valid_contract.yml +0 -0
- {agentic_data_contracts-0.2.2 → agentic_data_contracts-0.2.4}/tests/test_adapters/__init__.py +0 -0
- {agentic_data_contracts-0.2.2 → agentic_data_contracts-0.2.4}/tests/test_adapters/test_duckdb.py +0 -0
- {agentic_data_contracts-0.2.2 → agentic_data_contracts-0.2.4}/tests/test_bridge/__init__.py +0 -0
- {agentic_data_contracts-0.2.2 → agentic_data_contracts-0.2.4}/tests/test_bridge/test_compiler.py +0 -0
- {agentic_data_contracts-0.2.2 → agentic_data_contracts-0.2.4}/tests/test_core/__init__.py +0 -0
- {agentic_data_contracts-0.2.2 → agentic_data_contracts-0.2.4}/tests/test_core/test_contract.py +0 -0
- {agentic_data_contracts-0.2.2 → agentic_data_contracts-0.2.4}/tests/test_core/test_load_semantic_source.py +0 -0
- {agentic_data_contracts-0.2.2 → agentic_data_contracts-0.2.4}/tests/test_core/test_schema.py +0 -0
- {agentic_data_contracts-0.2.2 → agentic_data_contracts-0.2.4}/tests/test_core/test_sdk_config.py +0 -0
- {agentic_data_contracts-0.2.2 → agentic_data_contracts-0.2.4}/tests/test_core/test_session.py +0 -0
- {agentic_data_contracts-0.2.2 → agentic_data_contracts-0.2.4}/tests/test_core/test_system_prompt_metrics.py +0 -0
- {agentic_data_contracts-0.2.2 → agentic_data_contracts-0.2.4}/tests/test_public_api.py +0 -0
- {agentic_data_contracts-0.2.2 → agentic_data_contracts-0.2.4}/tests/test_semantic/__init__.py +0 -0
- {agentic_data_contracts-0.2.2 → agentic_data_contracts-0.2.4}/tests/test_semantic/test_cube.py +0 -0
- {agentic_data_contracts-0.2.2 → agentic_data_contracts-0.2.4}/tests/test_semantic/test_dbt.py +0 -0
- {agentic_data_contracts-0.2.2 → agentic_data_contracts-0.2.4}/tests/test_semantic/test_search.py +0 -0
- {agentic_data_contracts-0.2.2 → agentic_data_contracts-0.2.4}/tests/test_semantic/test_yaml_source.py +0 -0
- {agentic_data_contracts-0.2.2 → agentic_data_contracts-0.2.4}/tests/test_tools/__init__.py +0 -0
- {agentic_data_contracts-0.2.2 → agentic_data_contracts-0.2.4}/tests/test_tools/test_auto_load.py +0 -0
- {agentic_data_contracts-0.2.2 → agentic_data_contracts-0.2.4}/tests/test_tools/test_factory.py +0 -0
- {agentic_data_contracts-0.2.2 → agentic_data_contracts-0.2.4}/tests/test_tools/test_middleware.py +0 -0
- {agentic_data_contracts-0.2.2 → agentic_data_contracts-0.2.4}/tests/test_tools/test_semantic_tools.py +0 -0
- {agentic_data_contracts-0.2.2 → agentic_data_contracts-0.2.4}/tests/test_validation/__init__.py +0 -0
- {agentic_data_contracts-0.2.2 → agentic_data_contracts-0.2.4}/tests/test_validation/test_checkers.py +0 -0
- {agentic_data_contracts-0.2.2 → agentic_data_contracts-0.2.4}/tests/test_validation/test_explain.py +0 -0
- {agentic_data_contracts-0.2.2 → agentic_data_contracts-0.2.4}/tests/test_validation/test_validator.py +0 -0
|
@@ -2,6 +2,25 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
|
|
5
|
+
## [0.2.4] - 2026-03-29
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
|
|
9
|
+
- **Wildcard table support**: Use `tables: ["*"]` in `allowed_tables` to allow all tables in a schema, discovered from the database at runtime via `adapter.list_tables()`
|
|
10
|
+
- **`DataContract.resolve_tables(adapter)`**: Expands wildcard entries using the database adapter; called automatically by `create_tools()` when an adapter is provided
|
|
11
|
+
- **`DatabaseAdapter.list_tables(schema)`**: New protocol method for listing tables in a schema; implemented in `DuckDBAdapter` via `information_schema.tables`
|
|
12
|
+
|
|
13
|
+
## [0.2.3] - 2026-03-29
|
|
14
|
+
|
|
15
|
+
### Added
|
|
16
|
+
|
|
17
|
+
- **SDK MCP server convenience method**: `create_sdk_mcp_server(contract, adapter=...)` wraps all 10 tools with the SDK's `@tool` decorator and bundles them into a ready-to-use MCP server for `ClaudeAgentOptions.mcp_servers`
|
|
18
|
+
- **Top-level export**: `from agentic_data_contracts import create_sdk_mcp_server`
|
|
19
|
+
|
|
20
|
+
### Changed
|
|
21
|
+
|
|
22
|
+
- **SDK dependency**: Bumped `claude-agent-sdk` minimum to `>=0.1.52`
|
|
23
|
+
|
|
5
24
|
## [0.2.2] - 2026-03-28
|
|
6
25
|
|
|
7
26
|
### Added
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: agentic-data-contracts
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.4
|
|
4
4
|
Summary: YAML-first data contract governance for AI agents
|
|
5
5
|
Project-URL: Homepage, https://github.com/flyersworder/agentic-data-contracts
|
|
6
6
|
Project-URL: Repository, https://github.com/flyersworder/agentic-data-contracts
|
|
@@ -27,10 +27,10 @@ Requires-Dist: thefuzz>=0.22.1
|
|
|
27
27
|
Provides-Extra: agent-contracts
|
|
28
28
|
Requires-Dist: ai-agent-contracts>=0.2.0; extra == 'agent-contracts'
|
|
29
29
|
Provides-Extra: agent-sdk
|
|
30
|
-
Requires-Dist: claude-agent-sdk; extra == 'agent-sdk'
|
|
30
|
+
Requires-Dist: claude-agent-sdk>=0.1.52; extra == 'agent-sdk'
|
|
31
31
|
Provides-Extra: all
|
|
32
32
|
Requires-Dist: ai-agent-contracts>=0.2.0; extra == 'all'
|
|
33
|
-
Requires-Dist: claude-agent-sdk; extra == 'all'
|
|
33
|
+
Requires-Dist: claude-agent-sdk>=0.1.52; extra == 'all'
|
|
34
34
|
Requires-Dist: duckdb; extra == 'all'
|
|
35
35
|
Requires-Dist: google-cloud-bigquery; extra == 'all'
|
|
36
36
|
Requires-Dist: psycopg2-binary; extra == 'all'
|
|
@@ -117,7 +117,9 @@ semantic:
|
|
|
117
117
|
path: "./semantic.yml"
|
|
118
118
|
allowed_tables:
|
|
119
119
|
- schema: analytics
|
|
120
|
-
tables: [
|
|
120
|
+
tables: ["*"] # all tables in schema (discovered from database)
|
|
121
|
+
- schema: marketing
|
|
122
|
+
tables: [campaigns] # or list specific tables
|
|
121
123
|
forbidden_operations: [DELETE, DROP, TRUNCATE, UPDATE, INSERT]
|
|
122
124
|
rules:
|
|
123
125
|
- name: tenant_isolation
|
|
@@ -150,29 +152,26 @@ adapter = DuckDBAdapter("analytics.duckdb")
|
|
|
150
152
|
tools = create_tools(dc, adapter=adapter)
|
|
151
153
|
```
|
|
152
154
|
|
|
153
|
-
### 3. Use with the Claude Agent SDK
|
|
155
|
+
### 3. Use with the Claude Agent SDK (requires `claude-agent-sdk>=0.1.52`)
|
|
154
156
|
|
|
155
157
|
```python
|
|
156
158
|
import asyncio
|
|
159
|
+
from agentic_data_contracts import create_sdk_mcp_server
|
|
157
160
|
from claude_agent_sdk import (
|
|
158
161
|
ClaudeAgentOptions,
|
|
159
162
|
AssistantMessage,
|
|
160
163
|
TextBlock,
|
|
161
|
-
create_sdk_mcp_server,
|
|
162
164
|
query,
|
|
163
165
|
)
|
|
164
166
|
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
# Contract limits map to SDK options (token_budget → task_budget, max_retries → max_turns)
|
|
168
|
-
sdk_config = dc.to_sdk_config()
|
|
167
|
+
# One-liner: wraps all 10 tools and bundles into an SDK MCP server
|
|
168
|
+
server = create_sdk_mcp_server(dc, adapter=adapter)
|
|
169
169
|
|
|
170
170
|
options = ClaudeAgentOptions(
|
|
171
171
|
model="claude-sonnet-4-6",
|
|
172
172
|
system_prompt=f"You are a revenue analytics assistant.\n\n{dc.to_system_prompt()}",
|
|
173
173
|
mcp_servers={"dc": server},
|
|
174
|
-
|
|
175
|
-
**sdk_config,
|
|
174
|
+
**dc.to_sdk_config(), # token_budget → task_budget, max_retries → max_turns
|
|
176
175
|
)
|
|
177
176
|
|
|
178
177
|
async def run(prompt: str) -> None:
|
|
@@ -64,7 +64,9 @@ semantic:
|
|
|
64
64
|
path: "./semantic.yml"
|
|
65
65
|
allowed_tables:
|
|
66
66
|
- schema: analytics
|
|
67
|
-
tables: [
|
|
67
|
+
tables: ["*"] # all tables in schema (discovered from database)
|
|
68
|
+
- schema: marketing
|
|
69
|
+
tables: [campaigns] # or list specific tables
|
|
68
70
|
forbidden_operations: [DELETE, DROP, TRUNCATE, UPDATE, INSERT]
|
|
69
71
|
rules:
|
|
70
72
|
- name: tenant_isolation
|
|
@@ -97,29 +99,26 @@ adapter = DuckDBAdapter("analytics.duckdb")
|
|
|
97
99
|
tools = create_tools(dc, adapter=adapter)
|
|
98
100
|
```
|
|
99
101
|
|
|
100
|
-
### 3. Use with the Claude Agent SDK
|
|
102
|
+
### 3. Use with the Claude Agent SDK (requires `claude-agent-sdk>=0.1.52`)
|
|
101
103
|
|
|
102
104
|
```python
|
|
103
105
|
import asyncio
|
|
106
|
+
from agentic_data_contracts import create_sdk_mcp_server
|
|
104
107
|
from claude_agent_sdk import (
|
|
105
108
|
ClaudeAgentOptions,
|
|
106
109
|
AssistantMessage,
|
|
107
110
|
TextBlock,
|
|
108
|
-
create_sdk_mcp_server,
|
|
109
111
|
query,
|
|
110
112
|
)
|
|
111
113
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
# Contract limits map to SDK options (token_budget → task_budget, max_retries → max_turns)
|
|
115
|
-
sdk_config = dc.to_sdk_config()
|
|
114
|
+
# One-liner: wraps all 10 tools and bundles into an SDK MCP server
|
|
115
|
+
server = create_sdk_mcp_server(dc, adapter=adapter)
|
|
116
116
|
|
|
117
117
|
options = ClaudeAgentOptions(
|
|
118
118
|
model="claude-sonnet-4-6",
|
|
119
119
|
system_prompt=f"You are a revenue analytics assistant.\n\n{dc.to_system_prompt()}",
|
|
120
120
|
mcp_servers={"dc": server},
|
|
121
|
-
|
|
122
|
-
**sdk_config,
|
|
121
|
+
**dc.to_sdk_config(), # token_budget → task_budget, max_retries → max_turns
|
|
123
122
|
)
|
|
124
123
|
|
|
125
124
|
async def run(prompt: str) -> None:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "agentic-data-contracts"
|
|
3
|
-
version = "0.2.
|
|
3
|
+
version = "0.2.4"
|
|
4
4
|
description = "YAML-first data contract governance for AI agents"
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
requires-python = ">=3.12"
|
|
@@ -41,7 +41,7 @@ Issues = "https://github.com/flyersworder/agentic-data-contracts/issues"
|
|
|
41
41
|
Documentation = "https://github.com/flyersworder/agentic-data-contracts/blob/main/docs/architecture.md"
|
|
42
42
|
|
|
43
43
|
[project.optional-dependencies]
|
|
44
|
-
agent-sdk = ["claude-agent-sdk"]
|
|
44
|
+
agent-sdk = ["claude-agent-sdk>=0.1.52"]
|
|
45
45
|
agent-contracts = ["ai-agent-contracts>=0.2.0"]
|
|
46
46
|
bigquery = ["google-cloud-bigquery"]
|
|
47
47
|
snowflake = ["snowflake-connector-python"]
|
{agentic_data_contracts-0.2.2 → agentic_data_contracts-0.2.4}/src/agentic_data_contracts/__init__.py
RENAMED
|
@@ -3,5 +3,11 @@
|
|
|
3
3
|
from agentic_data_contracts.core.contract import DataContract
|
|
4
4
|
from agentic_data_contracts.tools.factory import create_tools
|
|
5
5
|
from agentic_data_contracts.tools.middleware import contract_middleware
|
|
6
|
+
from agentic_data_contracts.tools.sdk import create_sdk_mcp_server
|
|
6
7
|
|
|
7
|
-
__all__ = [
|
|
8
|
+
__all__ = [
|
|
9
|
+
"DataContract",
|
|
10
|
+
"create_tools",
|
|
11
|
+
"contract_middleware",
|
|
12
|
+
"create_sdk_mcp_server",
|
|
13
|
+
]
|
|
@@ -37,6 +37,7 @@ class DatabaseAdapter(Protocol):
|
|
|
37
37
|
def execute(self, sql: str) -> QueryResult: ...
|
|
38
38
|
def explain(self, sql: str) -> ExplainResult: ...
|
|
39
39
|
def describe_table(self, schema: str, table: str) -> TableSchema: ...
|
|
40
|
+
def list_tables(self, schema: str) -> list[str]: ...
|
|
40
41
|
|
|
41
42
|
@property
|
|
42
43
|
def dialect(self) -> str: ...
|
|
@@ -59,6 +59,18 @@ class DuckDBAdapter:
|
|
|
59
59
|
last_estimate = int(match.group(1))
|
|
60
60
|
return last_estimate
|
|
61
61
|
|
|
62
|
+
def list_tables(self, schema: str) -> list[str]:
|
|
63
|
+
rows = self.connection.execute(
|
|
64
|
+
"""
|
|
65
|
+
SELECT table_name
|
|
66
|
+
FROM information_schema.tables
|
|
67
|
+
WHERE table_schema = ?
|
|
68
|
+
ORDER BY table_name
|
|
69
|
+
""",
|
|
70
|
+
[schema],
|
|
71
|
+
).fetchall()
|
|
72
|
+
return [row[0] for row in rows]
|
|
73
|
+
|
|
62
74
|
def describe_table(self, schema: str, table: str) -> TableSchema:
|
|
63
75
|
rows = self.connection.execute(
|
|
64
76
|
"""
|
|
@@ -14,6 +14,7 @@ from agentic_data_contracts.core.schema import (
|
|
|
14
14
|
)
|
|
15
15
|
|
|
16
16
|
if TYPE_CHECKING:
|
|
17
|
+
from agentic_data_contracts.adapters.base import DatabaseAdapter
|
|
17
18
|
from agentic_data_contracts.semantic.base import SemanticSource
|
|
18
19
|
|
|
19
20
|
|
|
@@ -38,10 +39,27 @@ class DataContract:
|
|
|
38
39
|
schema = DataContractSchema.model_validate(raw)
|
|
39
40
|
return cls(schema=schema)
|
|
40
41
|
|
|
42
|
+
def has_wildcard_tables(self) -> bool:
|
|
43
|
+
"""Check if any schema uses wildcard ('*') for tables."""
|
|
44
|
+
return any("*" in entry.tables for entry in self.schema.semantic.allowed_tables)
|
|
45
|
+
|
|
46
|
+
def resolve_tables(self, adapter: DatabaseAdapter) -> None:
|
|
47
|
+
"""Expand wildcard tables using the database adapter.
|
|
48
|
+
|
|
49
|
+
Replaces ["*"] entries with actual table names from the database.
|
|
50
|
+
Call this once after creating the adapter. Results are cached
|
|
51
|
+
on the schema object.
|
|
52
|
+
"""
|
|
53
|
+
for entry in self.schema.semantic.allowed_tables:
|
|
54
|
+
if "*" in entry.tables:
|
|
55
|
+
entry.tables = adapter.list_tables(entry.schema_)
|
|
56
|
+
|
|
41
57
|
def allowed_table_names(self) -> list[str]:
|
|
42
58
|
names: list[str] = []
|
|
43
59
|
for entry in self.schema.semantic.allowed_tables:
|
|
44
60
|
for table in entry.tables:
|
|
61
|
+
if table == "*":
|
|
62
|
+
continue # unresolved wildcard — skip
|
|
45
63
|
names.append(f"{entry.schema_}.{table}")
|
|
46
64
|
return names
|
|
47
65
|
|
|
@@ -41,6 +41,10 @@ def create_tools(
|
|
|
41
41
|
if semantic_source is None:
|
|
42
42
|
semantic_source = contract.load_semantic_source()
|
|
43
43
|
|
|
44
|
+
# Resolve wildcard tables if adapter is available
|
|
45
|
+
if adapter is not None and contract.has_wildcard_tables():
|
|
46
|
+
contract.resolve_tables(adapter)
|
|
47
|
+
|
|
44
48
|
dialect = adapter.dialect if adapter else None
|
|
45
49
|
validator = Validator(contract, dialect=dialect, explain_adapter=adapter)
|
|
46
50
|
|
|
@@ -60,6 +64,11 @@ def create_tools(
|
|
|
60
64
|
for entry in contract.schema.semantic.allowed_tables:
|
|
61
65
|
if schema_filter and entry.schema_ != schema_filter:
|
|
62
66
|
continue
|
|
67
|
+
if "*" in entry.tables:
|
|
68
|
+
return _text_response(
|
|
69
|
+
f"Schema '{entry.schema_}' uses wildcard tables"
|
|
70
|
+
" but no database adapter is available to resolve them."
|
|
71
|
+
)
|
|
63
72
|
for table in entry.tables:
|
|
64
73
|
info: dict[str, Any] = {
|
|
65
74
|
"schema": entry.schema_,
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
"""Claude Agent SDK integration — wraps ToolDefs into an SDK MCP server."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from typing import Any
|
|
6
|
+
|
|
7
|
+
from agentic_data_contracts.adapters.base import DatabaseAdapter
|
|
8
|
+
from agentic_data_contracts.core.contract import DataContract
|
|
9
|
+
from agentic_data_contracts.core.session import ContractSession
|
|
10
|
+
from agentic_data_contracts.semantic.base import SemanticSource
|
|
11
|
+
from agentic_data_contracts.tools.factory import ToolDef, create_tools
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def create_sdk_mcp_server(
|
|
15
|
+
contract: DataContract,
|
|
16
|
+
*,
|
|
17
|
+
adapter: DatabaseAdapter | None = None,
|
|
18
|
+
semantic_source: SemanticSource | None = None,
|
|
19
|
+
session: ContractSession | None = None,
|
|
20
|
+
tools: list[ToolDef] | None = None,
|
|
21
|
+
server_name: str = "data-contracts",
|
|
22
|
+
server_version: str = "1.0.0",
|
|
23
|
+
) -> Any:
|
|
24
|
+
"""Create a Claude Agent SDK MCP server from a DataContract.
|
|
25
|
+
|
|
26
|
+
Wraps all 10 contract tools with the SDK's @tool decorator and
|
|
27
|
+
bundles them into an MCP server ready for ClaudeAgentOptions.mcp_servers.
|
|
28
|
+
|
|
29
|
+
Args:
|
|
30
|
+
contract: The data contract to enforce.
|
|
31
|
+
adapter: Optional database adapter for query execution.
|
|
32
|
+
semantic_source: Optional semantic source (auto-loaded if not given).
|
|
33
|
+
session: Optional session for tracking enforcement state.
|
|
34
|
+
tools: Pre-built ToolDefs (if None, created via create_tools).
|
|
35
|
+
server_name: Name for the MCP server.
|
|
36
|
+
server_version: Version for the MCP server.
|
|
37
|
+
|
|
38
|
+
Returns:
|
|
39
|
+
McpSdkServerConfig ready for ClaudeAgentOptions.mcp_servers.
|
|
40
|
+
|
|
41
|
+
Raises:
|
|
42
|
+
ImportError: If claude-agent-sdk is not installed.
|
|
43
|
+
"""
|
|
44
|
+
try:
|
|
45
|
+
from claude_agent_sdk import create_sdk_mcp_server as _create_server
|
|
46
|
+
from claude_agent_sdk import tool as sdk_tool
|
|
47
|
+
except ImportError:
|
|
48
|
+
msg = (
|
|
49
|
+
"claude-agent-sdk is required for SDK integration. "
|
|
50
|
+
"Install with: pip install agentic-data-contracts[agent-sdk]"
|
|
51
|
+
)
|
|
52
|
+
raise ImportError(msg) from None
|
|
53
|
+
|
|
54
|
+
if tools is None:
|
|
55
|
+
tools = create_tools(
|
|
56
|
+
contract,
|
|
57
|
+
adapter=adapter,
|
|
58
|
+
semantic_source=semantic_source,
|
|
59
|
+
session=session,
|
|
60
|
+
)
|
|
61
|
+
|
|
62
|
+
sdk_tools = []
|
|
63
|
+
for t in tools:
|
|
64
|
+
decorated = sdk_tool(t.name, t.description, t.input_schema)(t.callable)
|
|
65
|
+
sdk_tools.append(decorated)
|
|
66
|
+
|
|
67
|
+
return _create_server(
|
|
68
|
+
name=server_name,
|
|
69
|
+
version=server_version,
|
|
70
|
+
tools=sdk_tools,
|
|
71
|
+
)
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
"""Tests for wildcard table support in allowed_tables."""
|
|
2
|
+
|
|
3
|
+
from agentic_data_contracts.adapters.duckdb import DuckDBAdapter
|
|
4
|
+
from agentic_data_contracts.core.contract import DataContract
|
|
5
|
+
from agentic_data_contracts.core.schema import (
|
|
6
|
+
AllowedTable,
|
|
7
|
+
DataContractSchema,
|
|
8
|
+
SemanticConfig,
|
|
9
|
+
)
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def _make_contract(tables_config: list[dict]) -> DataContract:
|
|
13
|
+
allowed = [AllowedTable.model_validate(t) for t in tables_config]
|
|
14
|
+
schema = DataContractSchema(
|
|
15
|
+
name="test",
|
|
16
|
+
semantic=SemanticConfig(allowed_tables=allowed),
|
|
17
|
+
)
|
|
18
|
+
return DataContract(schema)
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def _make_adapter() -> DuckDBAdapter:
|
|
22
|
+
db = DuckDBAdapter(":memory:")
|
|
23
|
+
db.connection.execute("""
|
|
24
|
+
CREATE SCHEMA IF NOT EXISTS analytics;
|
|
25
|
+
CREATE TABLE analytics.orders (id INTEGER);
|
|
26
|
+
CREATE TABLE analytics.customers (id INTEGER);
|
|
27
|
+
CREATE TABLE analytics.products (id INTEGER);
|
|
28
|
+
CREATE SCHEMA IF NOT EXISTS raw;
|
|
29
|
+
CREATE TABLE raw.events (id INTEGER);
|
|
30
|
+
""")
|
|
31
|
+
return db
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def test_has_wildcard_tables_true() -> None:
|
|
35
|
+
dc = _make_contract([{"schema": "analytics", "tables": ["*"]}])
|
|
36
|
+
assert dc.has_wildcard_tables()
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def test_has_wildcard_tables_false() -> None:
|
|
40
|
+
dc = _make_contract(
|
|
41
|
+
[
|
|
42
|
+
{"schema": "analytics", "tables": ["orders"]},
|
|
43
|
+
]
|
|
44
|
+
)
|
|
45
|
+
assert not dc.has_wildcard_tables()
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def test_resolve_tables_expands_wildcard() -> None:
|
|
49
|
+
dc = _make_contract([{"schema": "analytics", "tables": ["*"]}])
|
|
50
|
+
adapter = _make_adapter()
|
|
51
|
+
dc.resolve_tables(adapter)
|
|
52
|
+
|
|
53
|
+
names = dc.allowed_table_names()
|
|
54
|
+
assert "analytics.orders" in names
|
|
55
|
+
assert "analytics.customers" in names
|
|
56
|
+
assert "analytics.products" in names
|
|
57
|
+
assert not any(n.startswith("raw.") for n in names)
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def test_resolve_tables_mixed() -> None:
|
|
61
|
+
dc = _make_contract(
|
|
62
|
+
[
|
|
63
|
+
{"schema": "analytics", "tables": ["*"]},
|
|
64
|
+
{"schema": "raw", "tables": []},
|
|
65
|
+
]
|
|
66
|
+
)
|
|
67
|
+
adapter = _make_adapter()
|
|
68
|
+
dc.resolve_tables(adapter)
|
|
69
|
+
|
|
70
|
+
names = dc.allowed_table_names()
|
|
71
|
+
assert "analytics.orders" in names
|
|
72
|
+
assert not any(n.startswith("raw.") for n in names)
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
def test_resolve_tables_preserves_explicit() -> None:
|
|
76
|
+
dc = _make_contract(
|
|
77
|
+
[
|
|
78
|
+
{"schema": "analytics", "tables": ["orders"]},
|
|
79
|
+
]
|
|
80
|
+
)
|
|
81
|
+
adapter = _make_adapter()
|
|
82
|
+
dc.resolve_tables(adapter)
|
|
83
|
+
|
|
84
|
+
names = dc.allowed_table_names()
|
|
85
|
+
assert names == ["analytics.orders"]
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
def test_unresolved_wildcard_skipped() -> None:
|
|
89
|
+
dc = _make_contract([{"schema": "analytics", "tables": ["*"]}])
|
|
90
|
+
# Without calling resolve_tables, wildcard is skipped
|
|
91
|
+
names = dc.allowed_table_names()
|
|
92
|
+
assert names == []
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
def test_adapter_list_tables() -> None:
|
|
96
|
+
adapter = _make_adapter()
|
|
97
|
+
tables = adapter.list_tables("analytics")
|
|
98
|
+
assert "orders" in tables
|
|
99
|
+
assert "customers" in tables
|
|
100
|
+
assert "products" in tables
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
def test_adapter_list_tables_empty_schema() -> None:
|
|
104
|
+
adapter = _make_adapter()
|
|
105
|
+
tables = adapter.list_tables("nonexistent")
|
|
106
|
+
assert tables == []
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
"""Tests for Claude Agent SDK MCP server integration."""
|
|
2
|
+
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
|
|
5
|
+
import pytest
|
|
6
|
+
|
|
7
|
+
from agentic_data_contracts.adapters.duckdb import DuckDBAdapter
|
|
8
|
+
from agentic_data_contracts.core.contract import DataContract
|
|
9
|
+
from agentic_data_contracts.core.schema import (
|
|
10
|
+
AllowedTable,
|
|
11
|
+
DataContractSchema,
|
|
12
|
+
SemanticConfig,
|
|
13
|
+
)
|
|
14
|
+
from agentic_data_contracts.tools.factory import create_tools
|
|
15
|
+
from agentic_data_contracts.tools.sdk import create_sdk_mcp_server
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
@pytest.fixture
|
|
19
|
+
def contract_no_source() -> DataContract:
|
|
20
|
+
"""Contract without a semantic source — avoids file path issues."""
|
|
21
|
+
schema = DataContractSchema(
|
|
22
|
+
name="test",
|
|
23
|
+
semantic=SemanticConfig(
|
|
24
|
+
allowed_tables=[
|
|
25
|
+
AllowedTable.model_validate(
|
|
26
|
+
{"schema": "analytics", "tables": ["orders"]}
|
|
27
|
+
),
|
|
28
|
+
],
|
|
29
|
+
),
|
|
30
|
+
)
|
|
31
|
+
return DataContract(schema)
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
@pytest.fixture
|
|
35
|
+
def contract_with_source(fixtures_dir: Path) -> DataContract:
|
|
36
|
+
"""Contract with semantic source pointing to real fixture."""
|
|
37
|
+
from agentic_data_contracts.core.schema import (
|
|
38
|
+
SemanticSource as SemanticSourceConfig,
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
schema = DataContractSchema(
|
|
42
|
+
name="test",
|
|
43
|
+
semantic=SemanticConfig(
|
|
44
|
+
source=SemanticSourceConfig(
|
|
45
|
+
type="yaml",
|
|
46
|
+
path=str(fixtures_dir / "semantic_source.yml"),
|
|
47
|
+
),
|
|
48
|
+
allowed_tables=[
|
|
49
|
+
AllowedTable.model_validate(
|
|
50
|
+
{"schema": "analytics", "tables": ["orders"]}
|
|
51
|
+
),
|
|
52
|
+
],
|
|
53
|
+
),
|
|
54
|
+
)
|
|
55
|
+
return DataContract(schema)
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
@pytest.fixture
|
|
59
|
+
def adapter() -> DuckDBAdapter:
|
|
60
|
+
db = DuckDBAdapter(":memory:")
|
|
61
|
+
db.connection.execute(
|
|
62
|
+
"""
|
|
63
|
+
CREATE SCHEMA IF NOT EXISTS analytics;
|
|
64
|
+
CREATE TABLE analytics.orders (
|
|
65
|
+
id INTEGER, amount DECIMAL(10,2), tenant_id VARCHAR
|
|
66
|
+
);
|
|
67
|
+
INSERT INTO analytics.orders VALUES (1, 100.00, 'acme');
|
|
68
|
+
"""
|
|
69
|
+
)
|
|
70
|
+
return db
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def test_create_sdk_mcp_server_returns_config(
|
|
74
|
+
contract_no_source: DataContract, adapter: DuckDBAdapter
|
|
75
|
+
) -> None:
|
|
76
|
+
server = create_sdk_mcp_server(contract_no_source, adapter=adapter)
|
|
77
|
+
assert server is not None
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
def test_create_sdk_mcp_server_with_prebuilt_tools(
|
|
81
|
+
contract_no_source: DataContract, adapter: DuckDBAdapter
|
|
82
|
+
) -> None:
|
|
83
|
+
tools = create_tools(contract_no_source, adapter=adapter)
|
|
84
|
+
server = create_sdk_mcp_server(contract_no_source, tools=tools)
|
|
85
|
+
assert server is not None
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
def test_create_sdk_mcp_server_with_semantic_source(
|
|
89
|
+
contract_with_source: DataContract, adapter: DuckDBAdapter
|
|
90
|
+
) -> None:
|
|
91
|
+
server = create_sdk_mcp_server(contract_with_source, adapter=adapter)
|
|
92
|
+
assert server is not None
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
def test_create_sdk_mcp_server_auto_creates_tools(
|
|
96
|
+
contract_no_source: DataContract,
|
|
97
|
+
) -> None:
|
|
98
|
+
server = create_sdk_mcp_server(contract_no_source)
|
|
99
|
+
assert server is not None
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
def test_create_sdk_mcp_server_custom_name(
|
|
103
|
+
contract_no_source: DataContract,
|
|
104
|
+
) -> None:
|
|
105
|
+
server = create_sdk_mcp_server(
|
|
106
|
+
contract_no_source,
|
|
107
|
+
server_name="my-server",
|
|
108
|
+
server_version="2.0.0",
|
|
109
|
+
)
|
|
110
|
+
assert server is not None
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
def test_top_level_import() -> None:
|
|
114
|
+
from agentic_data_contracts import create_sdk_mcp_server as fn
|
|
115
|
+
|
|
116
|
+
assert fn is not None
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
"""Tests for tools with wildcard table resolution."""
|
|
2
|
+
|
|
3
|
+
import json
|
|
4
|
+
|
|
5
|
+
import pytest
|
|
6
|
+
|
|
7
|
+
from agentic_data_contracts.adapters.duckdb import DuckDBAdapter
|
|
8
|
+
from agentic_data_contracts.core.contract import DataContract
|
|
9
|
+
from agentic_data_contracts.core.schema import (
|
|
10
|
+
AllowedTable,
|
|
11
|
+
DataContractSchema,
|
|
12
|
+
SemanticConfig,
|
|
13
|
+
)
|
|
14
|
+
from agentic_data_contracts.tools.factory import create_tools
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
@pytest.fixture
|
|
18
|
+
def adapter() -> DuckDBAdapter:
|
|
19
|
+
db = DuckDBAdapter(":memory:")
|
|
20
|
+
db.connection.execute("""
|
|
21
|
+
CREATE SCHEMA IF NOT EXISTS analytics;
|
|
22
|
+
CREATE TABLE analytics.orders (id INTEGER, amount DECIMAL);
|
|
23
|
+
CREATE TABLE analytics.customers (id INTEGER, name VARCHAR);
|
|
24
|
+
INSERT INTO analytics.orders VALUES (1, 100.00);
|
|
25
|
+
""")
|
|
26
|
+
return db
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
@pytest.fixture
|
|
30
|
+
def wildcard_contract() -> DataContract:
|
|
31
|
+
schema = DataContractSchema(
|
|
32
|
+
name="test",
|
|
33
|
+
semantic=SemanticConfig(
|
|
34
|
+
allowed_tables=[
|
|
35
|
+
AllowedTable.model_validate({"schema": "analytics", "tables": ["*"]}),
|
|
36
|
+
],
|
|
37
|
+
),
|
|
38
|
+
)
|
|
39
|
+
return DataContract(schema)
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
@pytest.mark.asyncio
|
|
43
|
+
async def test_list_tables_after_wildcard_resolve(
|
|
44
|
+
wildcard_contract: DataContract, adapter: DuckDBAdapter
|
|
45
|
+
) -> None:
|
|
46
|
+
tools = create_tools(wildcard_contract, adapter=adapter)
|
|
47
|
+
tool = next(t for t in tools if t.name == "list_tables")
|
|
48
|
+
result = await tool.callable({})
|
|
49
|
+
text = result["content"][0]["text"]
|
|
50
|
+
data = json.loads(text)
|
|
51
|
+
table_names = [t["table"] for t in data["tables"]]
|
|
52
|
+
assert "orders" in table_names
|
|
53
|
+
assert "customers" in table_names
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
@pytest.mark.asyncio
|
|
57
|
+
async def test_run_query_with_wildcard_tables(
|
|
58
|
+
wildcard_contract: DataContract, adapter: DuckDBAdapter
|
|
59
|
+
) -> None:
|
|
60
|
+
tools = create_tools(wildcard_contract, adapter=adapter)
|
|
61
|
+
tool = next(t for t in tools if t.name == "run_query")
|
|
62
|
+
result = await tool.callable({"sql": "SELECT id, amount FROM analytics.orders"})
|
|
63
|
+
text = result["content"][0]["text"]
|
|
64
|
+
assert "100" in text
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
@pytest.mark.asyncio
|
|
68
|
+
async def test_validate_query_with_wildcard_tables(
|
|
69
|
+
wildcard_contract: DataContract, adapter: DuckDBAdapter
|
|
70
|
+
) -> None:
|
|
71
|
+
tools = create_tools(wildcard_contract, adapter=adapter)
|
|
72
|
+
tool = next(t for t in tools if t.name == "validate_query")
|
|
73
|
+
# analytics.orders should be allowed after wildcard resolution
|
|
74
|
+
result = await tool.callable({"sql": "SELECT id FROM analytics.orders"})
|
|
75
|
+
text = result["content"][0]["text"]
|
|
76
|
+
assert "valid" in text.lower()
|
|
@@ -9,7 +9,7 @@ resolution-markers = [
|
|
|
9
9
|
|
|
10
10
|
[[package]]
|
|
11
11
|
name = "agentic-data-contracts"
|
|
12
|
-
version = "0.2.
|
|
12
|
+
version = "0.2.4"
|
|
13
13
|
source = { editable = "." }
|
|
14
14
|
dependencies = [
|
|
15
15
|
{ name = "pydantic" },
|
|
@@ -57,7 +57,7 @@ snowflake = [
|
|
|
57
57
|
requires-dist = [
|
|
58
58
|
{ name = "agentic-data-contracts", extras = ["agent-sdk", "agent-contracts", "bigquery", "snowflake", "postgres", "duckdb"], marker = "extra == 'all'" },
|
|
59
59
|
{ name = "ai-agent-contracts", marker = "extra == 'agent-contracts'", specifier = ">=0.2.0" },
|
|
60
|
-
{ name = "claude-agent-sdk", marker = "extra == 'agent-sdk'" },
|
|
60
|
+
{ name = "claude-agent-sdk", marker = "extra == 'agent-sdk'", specifier = ">=0.1.52" },
|
|
61
61
|
{ name = "duckdb", marker = "extra == 'dev'" },
|
|
62
62
|
{ name = "duckdb", marker = "extra == 'duckdb'" },
|
|
63
63
|
{ name = "google-cloud-bigquery", marker = "extra == 'bigquery'" },
|
|
@@ -412,19 +412,19 @@ wheels = [
|
|
|
412
412
|
|
|
413
413
|
[[package]]
|
|
414
414
|
name = "claude-agent-sdk"
|
|
415
|
-
version = "0.1.
|
|
415
|
+
version = "0.1.52"
|
|
416
416
|
source = { registry = "https://pypi.org/simple" }
|
|
417
417
|
dependencies = [
|
|
418
418
|
{ name = "anyio" },
|
|
419
419
|
{ name = "mcp" },
|
|
420
420
|
]
|
|
421
|
-
sdist = { url = "https://files.pythonhosted.org/packages/
|
|
421
|
+
sdist = { url = "https://files.pythonhosted.org/packages/b1/d7/a56b7ba793918e5cc557447b25f2d428e11d6f025b6c0c7b1e6e3fa373c0/claude_agent_sdk-0.1.52.tar.gz", hash = "sha256:c27f35d850521c7cff18448b38ff0dd5e899a4aeb6de9d28c0b2a66863eaf134", size = 116267, upload-time = "2026-03-29T02:40:25.554Z" }
|
|
422
422
|
wheels = [
|
|
423
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
424
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
425
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
426
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
427
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
423
|
+
{ url = "https://files.pythonhosted.org/packages/31/e0/6759f98c699ef5da84750b93de543a839f3e3b905b5ce20424a5033c58fa/claude_agent_sdk-0.1.52-py3-none-macosx_11_0_arm64.whl", hash = "sha256:0f15c91319c20831f881fd4b6bcec1772a3599d66da5e7c057d79945bf603e1a", size = 57872944, upload-time = "2026-03-29T02:40:28.742Z" },
|
|
424
|
+
{ url = "https://files.pythonhosted.org/packages/cd/e8/d3c3ef7cb104d3ebb6348a82eab7574b8c0eaddb683efd3f606f3c22bc21/claude_agent_sdk-0.1.52-py3-none-macosx_11_0_x86_64.whl", hash = "sha256:f32ca2ca95e312678af63ee60a5fb1b765f98ed47825ea3ba90322ceb26736ff", size = 59615855, upload-time = "2026-03-29T02:40:31.765Z" },
|
|
425
|
+
{ url = "https://files.pythonhosted.org/packages/f0/b7/2c4def1c5c67b9bad8966b8839d6d9da812a6458050650dbaba3526d3824/claude_agent_sdk-0.1.52-py3-none-manylinux_2_17_aarch64.whl", hash = "sha256:97c238fda13f0bea057e546895a3dc67468fc1acdbbc00d0b53a46cb3ba588dc", size = 71217617, upload-time = "2026-03-29T02:40:35.127Z" },
|
|
426
|
+
{ url = "https://files.pythonhosted.org/packages/44/9e/4be542b58610bd74056dfed37dbdc5a12224a2fbde41a333ddbcd8255a8a/claude_agent_sdk-0.1.52-py3-none-manylinux_2_17_x86_64.whl", hash = "sha256:4cd3f2e6fd5b272b16114fbc8dcd4348cbe8615dcc1b3bea251a7d489bf83a5d", size = 71292911, upload-time = "2026-03-29T02:40:38.919Z" },
|
|
427
|
+
{ url = "https://files.pythonhosted.org/packages/93/73/4601d43d57354bd6e664444970bd5c1de8003542745a4388cf84611c9f26/claude_agent_sdk-0.1.52-py3-none-win_amd64.whl", hash = "sha256:a8a5455d248b76c17126abee0f69d0f9870cbc0d52cb2f8ad5eb3deddb05af39", size = 73447753, upload-time = "2026-03-29T02:40:42.786Z" },
|
|
428
428
|
]
|
|
429
429
|
|
|
430
430
|
[[package]]
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{agentic_data_contracts-0.2.2 → agentic_data_contracts-0.2.4}/examples/revenue_agent/agent.py
RENAMED
|
File without changes
|
{agentic_data_contracts-0.2.2 → agentic_data_contracts-0.2.4}/examples/revenue_agent/contract.yml
RENAMED
|
File without changes
|
{agentic_data_contracts-0.2.2 → agentic_data_contracts-0.2.4}/examples/revenue_agent/semantic.yml
RENAMED
|
File without changes
|
{agentic_data_contracts-0.2.2 → agentic_data_contracts-0.2.4}/examples/revenue_agent/setup_db.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{agentic_data_contracts-0.2.2 → agentic_data_contracts-0.2.4}/src/agentic_data_contracts/py.typed
RENAMED
|
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
|
{agentic_data_contracts-0.2.2 → agentic_data_contracts-0.2.4}/tests/fixtures/minimal_contract.yml
RENAMED
|
File without changes
|
{agentic_data_contracts-0.2.2 → agentic_data_contracts-0.2.4}/tests/fixtures/sample_cube_schema.yml
RENAMED
|
File without changes
|
|
File without changes
|
{agentic_data_contracts-0.2.2 → agentic_data_contracts-0.2.4}/tests/fixtures/semantic_source.yml
RENAMED
|
File without changes
|
{agentic_data_contracts-0.2.2 → agentic_data_contracts-0.2.4}/tests/fixtures/valid_contract.yml
RENAMED
|
File without changes
|
{agentic_data_contracts-0.2.2 → agentic_data_contracts-0.2.4}/tests/test_adapters/__init__.py
RENAMED
|
File without changes
|
{agentic_data_contracts-0.2.2 → agentic_data_contracts-0.2.4}/tests/test_adapters/test_duckdb.py
RENAMED
|
File without changes
|
|
File without changes
|
{agentic_data_contracts-0.2.2 → agentic_data_contracts-0.2.4}/tests/test_bridge/test_compiler.py
RENAMED
|
File without changes
|
|
File without changes
|
{agentic_data_contracts-0.2.2 → agentic_data_contracts-0.2.4}/tests/test_core/test_contract.py
RENAMED
|
File without changes
|
|
File without changes
|
{agentic_data_contracts-0.2.2 → agentic_data_contracts-0.2.4}/tests/test_core/test_schema.py
RENAMED
|
File without changes
|
{agentic_data_contracts-0.2.2 → agentic_data_contracts-0.2.4}/tests/test_core/test_sdk_config.py
RENAMED
|
File without changes
|
{agentic_data_contracts-0.2.2 → agentic_data_contracts-0.2.4}/tests/test_core/test_session.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{agentic_data_contracts-0.2.2 → agentic_data_contracts-0.2.4}/tests/test_semantic/__init__.py
RENAMED
|
File without changes
|
{agentic_data_contracts-0.2.2 → agentic_data_contracts-0.2.4}/tests/test_semantic/test_cube.py
RENAMED
|
File without changes
|
{agentic_data_contracts-0.2.2 → agentic_data_contracts-0.2.4}/tests/test_semantic/test_dbt.py
RENAMED
|
File without changes
|
{agentic_data_contracts-0.2.2 → agentic_data_contracts-0.2.4}/tests/test_semantic/test_search.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{agentic_data_contracts-0.2.2 → agentic_data_contracts-0.2.4}/tests/test_tools/test_auto_load.py
RENAMED
|
File without changes
|
{agentic_data_contracts-0.2.2 → agentic_data_contracts-0.2.4}/tests/test_tools/test_factory.py
RENAMED
|
File without changes
|
{agentic_data_contracts-0.2.2 → agentic_data_contracts-0.2.4}/tests/test_tools/test_middleware.py
RENAMED
|
File without changes
|
|
File without changes
|
{agentic_data_contracts-0.2.2 → agentic_data_contracts-0.2.4}/tests/test_validation/__init__.py
RENAMED
|
File without changes
|
{agentic_data_contracts-0.2.2 → agentic_data_contracts-0.2.4}/tests/test_validation/test_checkers.py
RENAMED
|
File without changes
|
{agentic_data_contracts-0.2.2 → agentic_data_contracts-0.2.4}/tests/test_validation/test_explain.py
RENAMED
|
File without changes
|
|
File without changes
|