data-flow-control 0.1.0__tar.gz → 0.1.2__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.
- {data_flow_control-0.1.0 → data_flow_control-0.1.2}/Cargo.lock +3 -3
- {data_flow_control-0.1.0 → data_flow_control-0.1.2}/Cargo.toml +1 -1
- data_flow_control-0.1.2/LICENSE +21 -0
- {data_flow_control-0.1.0 → data_flow_control-0.1.2}/PKG-INFO +7 -3
- {data_flow_control-0.1.0 → data_flow_control-0.1.2}/passant-core/src/rewrite_stats.rs +1 -1
- {data_flow_control-0.1.0 → data_flow_control-0.1.2}/pyproject.toml +15 -5
- data_flow_control-0.1.2/python/data_flow_control/__init__.py +31 -0
- data_flow_control-0.1.2/python/data_flow_control/langchain/__init__.py +8 -0
- data_flow_control-0.1.2/python/data_flow_control/langchain/agent.py +114 -0
- data_flow_control-0.1.2/python/data_flow_control/langchain/call_tool_with_dataflow.py +160 -0
- data_flow_control-0.1.2/python/data_flow_control/langchain/database.py +466 -0
- data_flow_control-0.1.2/python/data_flow_control/langchain/middleware.py +127 -0
- data_flow_control-0.1.2/python/data_flow_control/langchain/schema.py +174 -0
- data_flow_control-0.1.2/python/data_flow_control/langchain/sql_validation.py +123 -0
- data_flow_control-0.1.2/python/data_flow_control/langchain/tool_spec.py +164 -0
- data_flow_control-0.1.2/python/data_flow_control/langchain/wrapper.py +128 -0
- data_flow_control-0.1.0/python/data_flow_control/__init__.py +0 -17
- {data_flow_control-0.1.0 → data_flow_control-0.1.2}/passant-core/Cargo.toml +0 -0
- {data_flow_control-0.1.0 → data_flow_control-0.1.2}/passant-core/benches/rewrite_perf.rs +0 -0
- {data_flow_control-0.1.0 → data_flow_control-0.1.2}/passant-core/src/aggregate_registry.rs +0 -0
- {data_flow_control-0.1.0 → data_flow_control-0.1.2}/passant-core/src/catalog.rs +0 -0
- {data_flow_control-0.1.0 → data_flow_control-0.1.2}/passant-core/src/diagnostics.rs +0 -0
- {data_flow_control-0.1.0 → data_flow_control-0.1.2}/passant-core/src/explain.rs +0 -0
- {data_flow_control-0.1.0 → data_flow_control-0.1.2}/passant-core/src/full_push.rs +0 -0
- {data_flow_control-0.1.0 → data_flow_control-0.1.2}/passant-core/src/identifiers.rs +0 -0
- {data_flow_control-0.1.0 → data_flow_control-0.1.2}/passant-core/src/intern.rs +0 -0
- {data_flow_control-0.1.0 → data_flow_control-0.1.2}/passant-core/src/ir.rs +0 -0
- {data_flow_control-0.1.0 → data_flow_control-0.1.2}/passant-core/src/lib.rs +0 -0
- {data_flow_control-0.1.0 → data_flow_control-0.1.2}/passant-core/src/optimizer.rs +0 -0
- {data_flow_control-0.1.0 → data_flow_control-0.1.2}/passant-core/src/parser.rs +0 -0
- {data_flow_control-0.1.0 → data_flow_control-0.1.2}/passant-core/src/partial_push.rs +0 -0
- {data_flow_control-0.1.0 → data_flow_control-0.1.2}/passant-core/src/planner.rs +0 -0
- {data_flow_control-0.1.0 → data_flow_control-0.1.2}/passant-core/src/policy.rs +0 -0
- {data_flow_control-0.1.0 → data_flow_control-0.1.2}/passant-core/src/policy_compile.rs +0 -0
- {data_flow_control-0.1.0 → data_flow_control-0.1.2}/passant-core/src/policy_index.rs +0 -0
- {data_flow_control-0.1.0 → data_flow_control-0.1.2}/passant-core/src/policy_parser.rs +0 -0
- {data_flow_control-0.1.0 → data_flow_control-0.1.2}/passant-core/src/policy_pgn.pest +0 -0
- {data_flow_control-0.1.0 → data_flow_control-0.1.2}/passant-core/src/policy_store/branch.rs +0 -0
- {data_flow_control-0.1.0 → data_flow_control-0.1.2}/passant-core/src/policy_store/compiled.rs +0 -0
- {data_flow_control-0.1.0 → data_flow_control-0.1.2}/passant-core/src/policy_store/delete.rs +0 -0
- {data_flow_control-0.1.0 → data_flow_control-0.1.2}/passant-core/src/policy_store/indexes.rs +0 -0
- {data_flow_control-0.1.0 → data_flow_control-0.1.2}/passant-core/src/policy_store/memory.rs +0 -0
- {data_flow_control-0.1.0 → data_flow_control-0.1.2}/passant-core/src/policy_store/mod.rs +0 -0
- {data_flow_control-0.1.0 → data_flow_control-0.1.2}/passant-core/src/query_analysis.rs +0 -0
- {data_flow_control-0.1.0 → data_flow_control-0.1.2}/passant-core/src/rewrite_strategy.rs +0 -0
- {data_flow_control-0.1.0 → data_flow_control-0.1.2}/passant-core/src/rewriter/aggregates.rs +0 -0
- {data_flow_control-0.1.0 → data_flow_control-0.1.2}/passant-core/src/rewriter/columns.rs +0 -0
- {data_flow_control-0.1.0 → data_flow_control-0.1.2}/passant-core/src/rewriter/constraint_preprocess.rs +0 -0
- {data_flow_control-0.1.0 → data_flow_control-0.1.2}/passant-core/src/rewriter/derived_policy.rs +0 -0
- {data_flow_control-0.1.0 → data_flow_control-0.1.2}/passant-core/src/rewriter/dimensions.rs +0 -0
- {data_flow_control-0.1.0 → data_flow_control-0.1.2}/passant-core/src/rewriter/exists.rs +0 -0
- {data_flow_control-0.1.0 → data_flow_control-0.1.2}/passant-core/src/rewriter/expr.rs +0 -0
- {data_flow_control-0.1.0 → data_flow_control-0.1.2}/passant-core/src/rewriter/helpers.rs +0 -0
- {data_flow_control-0.1.0 → data_flow_control-0.1.2}/passant-core/src/rewriter/limit.rs +0 -0
- {data_flow_control-0.1.0 → data_flow_control-0.1.2}/passant-core/src/rewriter/mod.rs +0 -0
- {data_flow_control-0.1.0 → data_flow_control-0.1.2}/passant-core/src/rewriter/plan/actions.rs +0 -0
- {data_flow_control-0.1.0 → data_flow_control-0.1.2}/passant-core/src/rewriter/plan/applicability.rs +0 -0
- {data_flow_control-0.1.0 → data_flow_control-0.1.2}/passant-core/src/rewriter/plan/dominance.rs +0 -0
- {data_flow_control-0.1.0 → data_flow_control-0.1.2}/passant-core/src/rewriter/plan/mod.rs +0 -0
- {data_flow_control-0.1.0 → data_flow_control-0.1.2}/passant-core/src/rewriter/plan/scope_plan.rs +0 -0
- {data_flow_control-0.1.0 → data_flow_control-0.1.2}/passant-core/src/rewriter/plan/write_plan.rs +0 -0
- {data_flow_control-0.1.0 → data_flow_control-0.1.2}/passant-core/src/rewriter/policy_expr.rs +0 -0
- {data_flow_control-0.1.0 → data_flow_control-0.1.2}/passant-core/src/rewriter/projection.rs +0 -0
- {data_flow_control-0.1.0 → data_flow_control-0.1.2}/passant-core/src/rewriter/resolution.rs +0 -0
- {data_flow_control-0.1.0 → data_flow_control-0.1.2}/passant-core/src/rewriter/scope.rs +0 -0
- {data_flow_control-0.1.0 → data_flow_control-0.1.2}/passant-core/src/rewriter/select.rs +0 -0
- {data_flow_control-0.1.0 → data_flow_control-0.1.2}/passant-core/src/rewriter/types.rs +0 -0
- {data_flow_control-0.1.0 → data_flow_control-0.1.2}/passant-core/src/rewriter/write_path.rs +0 -0
- {data_flow_control-0.1.0 → data_flow_control-0.1.2}/passant-core/src/semiring.rs +0 -0
- {data_flow_control-0.1.0 → data_flow_control-0.1.2}/passant-core/src/source_set_index.rs +0 -0
- {data_flow_control-0.1.0 → data_flow_control-0.1.2}/passant-core/src/source_sets/analysis.rs +0 -0
- {data_flow_control-0.1.0 → data_flow_control-0.1.2}/passant-core/src/source_sets/annotations.rs +0 -0
- {data_flow_control-0.1.0 → data_flow_control-0.1.2}/passant-core/src/source_sets/branch.rs +0 -0
- {data_flow_control-0.1.0 → data_flow_control-0.1.2}/passant-core/src/source_sets/mod.rs +0 -0
- {data_flow_control-0.1.0 → data_flow_control-0.1.2}/passant-core/src/source_sets/rewrites.rs +0 -0
- {data_flow_control-0.1.0 → data_flow_control-0.1.2}/passant-core/src/source_sets/split.rs +0 -0
- {data_flow_control-0.1.0 → data_flow_control-0.1.2}/passant-core/src/sql/ast_stats.rs +0 -0
- {data_flow_control-0.1.0 → data_flow_control-0.1.2}/passant-core/src/sql/builders.rs +0 -0
- {data_flow_control-0.1.0 → data_flow_control-0.1.2}/passant-core/src/sql/columns.rs +0 -0
- {data_flow_control-0.1.0 → data_flow_control-0.1.2}/passant-core/src/sql/dialect.rs +0 -0
- {data_flow_control-0.1.0 → data_flow_control-0.1.2}/passant-core/src/sql/expr.rs +0 -0
- {data_flow_control-0.1.0 → data_flow_control-0.1.2}/passant-core/src/sql/expr_key.rs +0 -0
- {data_flow_control-0.1.0 → data_flow_control-0.1.2}/passant-core/src/sql/mod.rs +0 -0
- {data_flow_control-0.1.0 → data_flow_control-0.1.2}/passant-core/src/sql/parse.rs +0 -0
- {data_flow_control-0.1.0 → data_flow_control-0.1.2}/passant-core/src/sql/render.rs +0 -0
- {data_flow_control-0.1.0 → data_flow_control-0.1.2}/passant-core/src/statement_tables.rs +0 -0
- {data_flow_control-0.1.0 → data_flow_control-0.1.2}/passant-core/src/threshold.rs +0 -0
- {data_flow_control-0.1.0 → data_flow_control-0.1.2}/passant-core/tests/common/duckdb.rs +0 -0
- {data_flow_control-0.1.0 → data_flow_control-0.1.2}/passant-core/tests/common/mod.rs +0 -0
- {data_flow_control-0.1.0 → data_flow_control-0.1.2}/passant-core/tests/completion/conformance.rs +0 -0
- {data_flow_control-0.1.0 → data_flow_control-0.1.2}/passant-core/tests/completion/main.rs +0 -0
- {data_flow_control-0.1.0 → data_flow_control-0.1.2}/passant-core/tests/completion/partial_push.rs +0 -0
- {data_flow_control-0.1.0 → data_flow_control-0.1.2}/passant-core/tests/completion/pgn.rs +0 -0
- {data_flow_control-0.1.0 → data_flow_control-0.1.2}/passant-core/tests/completion/pgn_unique.rs +0 -0
- {data_flow_control-0.1.0 → data_flow_control-0.1.2}/passant-core/tests/completion/policy_storage.rs +0 -0
- {data_flow_control-0.1.0 → data_flow_control-0.1.2}/passant-core/tests/completion/rewrite_api_parity.rs +0 -0
- {data_flow_control-0.1.0 → data_flow_control-0.1.2}/passant-core/tests/completion/semiring.rs +0 -0
- {data_flow_control-0.1.0 → data_flow_control-0.1.2}/passant-core/tests/completion/source_sets.rs +0 -0
- {data_flow_control-0.1.0 → data_flow_control-0.1.2}/passant-core/tests/completion/symmetric_self_join.rs +0 -0
- {data_flow_control-0.1.0 → data_flow_control-0.1.2}/passant-core/tests/completion/threshold.rs +0 -0
- {data_flow_control-0.1.0 → data_flow_control-0.1.2}/passant-core/tests/completion/unique_not_unique.rs +0 -0
- {data_flow_control-0.1.0 → data_flow_control-0.1.2}/passant-core/tests/dialect.rs +0 -0
- {data_flow_control-0.1.0 → data_flow_control-0.1.2}/passant-core/tests/execution/insert.rs +0 -0
- {data_flow_control-0.1.0 → data_flow_control-0.1.2}/passant-core/tests/execution/kill.rs +0 -0
- {data_flow_control-0.1.0 → data_flow_control-0.1.2}/passant-core/tests/execution/main.rs +0 -0
- {data_flow_control-0.1.0 → data_flow_control-0.1.2}/passant-core/tests/execution/oracle.rs +0 -0
- {data_flow_control-0.1.0 → data_flow_control-0.1.2}/passant-core/tests/execution/remove.rs +0 -0
- {data_flow_control-0.1.0 → data_flow_control-0.1.2}/passant-core/tests/execution/update.rs +0 -0
- {data_flow_control-0.1.0 → data_flow_control-0.1.2}/passant-core/tests/expected/duckdb/remove_scan.sql +0 -0
- {data_flow_control-0.1.0 → data_flow_control-0.1.2}/passant-core/tests/expected/postgres/remove_scan.sql +0 -0
- {data_flow_control-0.1.0 → data_flow_control-0.1.2}/passant-core/tests/expected/sqlite/remove_scan.sql +0 -0
- {data_flow_control-0.1.0 → data_flow_control-0.1.2}/passant-core/tests/explain_strategy.rs +0 -0
- {data_flow_control-0.1.0 → data_flow_control-0.1.2}/passant-core/tests/gaps/column_propagation.rs +0 -0
- {data_flow_control-0.1.0 → data_flow_control-0.1.2}/passant-core/tests/gaps/dimensions.rs +0 -0
- {data_flow_control-0.1.0 → data_flow_control-0.1.2}/passant-core/tests/gaps/exists_join.rs +0 -0
- {data_flow_control-0.1.0 → data_flow_control-0.1.2}/passant-core/tests/gaps/having_where.rs +0 -0
- {data_flow_control-0.1.0 → data_flow_control-0.1.2}/passant-core/tests/gaps/identifiers.rs +0 -0
- {data_flow_control-0.1.0 → data_flow_control-0.1.2}/passant-core/tests/gaps/insert_shapes.rs +0 -0
- {data_flow_control-0.1.0 → data_flow_control-0.1.2}/passant-core/tests/gaps/main.rs +0 -0
- {data_flow_control-0.1.0 → data_flow_control-0.1.2}/passant-core/tests/gaps/multi_source.rs +0 -0
- {data_flow_control-0.1.0 → data_flow_control-0.1.2}/passant-core/tests/gaps/operators.rs +0 -0
- {data_flow_control-0.1.0 → data_flow_control-0.1.2}/passant-core/tests/gaps/query_shapes.rs +0 -0
- {data_flow_control-0.1.0 → data_flow_control-0.1.2}/passant-core/tests/gaps/scalar_subquery.rs +0 -0
- {data_flow_control-0.1.0 → data_flow_control-0.1.2}/passant-core/tests/indexed_candidate_differential.rs +0 -0
- {data_flow_control-0.1.0 → data_flow_control-0.1.2}/passant-core/tests/insert_values_body.rs +0 -0
- {data_flow_control-0.1.0 → data_flow_control-0.1.2}/passant-core/tests/paper_examples.rs +0 -0
- {data_flow_control-0.1.0 → data_flow_control-0.1.2}/passant-core/tests/parser.rs +0 -0
- {data_flow_control-0.1.0 → data_flow_control-0.1.2}/passant-core/tests/planner.rs +0 -0
- {data_flow_control-0.1.0 → data_flow_control-0.1.2}/passant-core/tests/policy.rs +0 -0
- {data_flow_control-0.1.0 → data_flow_control-0.1.2}/passant-core/tests/policy_dialect.rs +0 -0
- {data_flow_control-0.1.0 → data_flow_control-0.1.2}/passant-core/tests/policy_store_memory.rs +0 -0
- {data_flow_control-0.1.0 → data_flow_control-0.1.2}/passant-core/tests/rewrite/derived_policy.rs +0 -0
- {data_flow_control-0.1.0 → data_flow_control-0.1.2}/passant-core/tests/rewrite/in_semijoin.rs +0 -0
- {data_flow_control-0.1.0 → data_flow_control-0.1.2}/passant-core/tests/rewrite/insert.rs +0 -0
- {data_flow_control-0.1.0 → data_flow_control-0.1.2}/passant-core/tests/rewrite/joins.rs +0 -0
- {data_flow_control-0.1.0 → data_flow_control-0.1.2}/passant-core/tests/rewrite/main.rs +0 -0
- {data_flow_control-0.1.0 → data_flow_control-0.1.2}/passant-core/tests/rewrite/output.rs +0 -0
- {data_flow_control-0.1.0 → data_flow_control-0.1.2}/passant-core/tests/rewrite/recursive.rs +0 -0
- {data_flow_control-0.1.0 → data_flow_control-0.1.2}/passant-core/tests/rewrite/scan.rs +0 -0
- {data_flow_control-0.1.0 → data_flow_control-0.1.2}/passant-core/tests/rewrite/update.rs +0 -0
- {data_flow_control-0.1.0 → data_flow_control-0.1.2}/passant-core/tests/rewrite_candidate_regression.rs +0 -0
- {data_flow_control-0.1.0 → data_flow_control-0.1.2}/passant-core/tests/rewrite_fast_paths.rs +0 -0
- {data_flow_control-0.1.0 → data_flow_control-0.1.2}/passant-core/tests/rewrite_large_registry.rs +0 -0
- {data_flow_control-0.1.0 → data_flow_control-0.1.2}/passant-core/tests/rewrite_stats_timings.rs +0 -0
- {data_flow_control-0.1.0 → data_flow_control-0.1.2}/passant-core/tests/scan_ready_expr.rs +0 -0
- {data_flow_control-0.1.0 → data_flow_control-0.1.2}/passant-core/tests/source_set_split_no_parse.rs +0 -0
- {data_flow_control-0.1.0 → data_flow_control-0.1.2}/passant-core/tests/sql_builders.rs +0 -0
- {data_flow_control-0.1.0 → data_flow_control-0.1.2}/passant-core/tests/sql_columns.rs +0 -0
- {data_flow_control-0.1.0 → data_flow_control-0.1.2}/passant-core/tests/ui_resolution.rs +0 -0
- {data_flow_control-0.1.0 → data_flow_control-0.1.2}/passant-py/Cargo.toml +0 -0
- {data_flow_control-0.1.0 → data_flow_control-0.1.2}/passant-py/src/bindings/catalog.rs +0 -0
- {data_flow_control-0.1.0 → data_flow_control-0.1.2}/passant-py/src/bindings/errors.rs +0 -0
- {data_flow_control-0.1.0 → data_flow_control-0.1.2}/passant-py/src/bindings/mod.rs +0 -0
- {data_flow_control-0.1.0 → data_flow_control-0.1.2}/passant-py/src/bindings/planner.rs +0 -0
- {data_flow_control-0.1.0 → data_flow_control-0.1.2}/passant-py/src/bindings/policy.rs +0 -0
- {data_flow_control-0.1.0 → data_flow_control-0.1.2}/passant-py/src/bindings/stats.rs +0 -0
- {data_flow_control-0.1.0 → data_flow_control-0.1.2}/passant-py/src/lib.rs +0 -0
- {data_flow_control-0.1.0 → data_flow_control-0.1.2}/python/data_flow_control/_rust.py +0 -0
- {data_flow_control-0.1.0 → data_flow_control-0.1.2}/python/data_flow_control/adapters/__init__.py +0 -0
- {data_flow_control-0.1.0 → data_flow_control-0.1.2}/python/data_flow_control/adapters/base.py +0 -0
- {data_flow_control-0.1.0 → data_flow_control-0.1.2}/python/data_flow_control/adapters/clickhouse.py +0 -0
- {data_flow_control-0.1.0 → data_flow_control-0.1.2}/python/data_flow_control/adapters/datafusion.py +0 -0
- {data_flow_control-0.1.0 → data_flow_control-0.1.2}/python/data_flow_control/adapters/duckdb.py +0 -0
- {data_flow_control-0.1.0 → data_flow_control-0.1.2}/python/data_flow_control/adapters/kill.py +0 -0
- {data_flow_control-0.1.0 → data_flow_control-0.1.2}/python/data_flow_control/adapters/pg_catalog.py +0 -0
- {data_flow_control-0.1.0 → data_flow_control-0.1.2}/python/data_flow_control/adapters/postgres.py +0 -0
- {data_flow_control-0.1.0 → data_flow_control-0.1.2}/python/data_flow_control/adapters/registry.py +0 -0
- {data_flow_control-0.1.0 → data_flow_control-0.1.2}/python/data_flow_control/adapters/sqlite.py +0 -0
- {data_flow_control-0.1.0 → data_flow_control-0.1.2}/python/data_flow_control/adapters/umbra.py +0 -0
- {data_flow_control-0.1.0 → data_flow_control-0.1.2}/python/data_flow_control/aggregate_introspection.py +0 -0
- {data_flow_control-0.1.0 → data_flow_control-0.1.2}/python/data_flow_control/catalog.py +0 -0
- {data_flow_control-0.1.0 → data_flow_control-0.1.2}/python/data_flow_control/connection.py +0 -0
- {data_flow_control-0.1.0 → data_flow_control-0.1.2}/python/data_flow_control/dialect.py +0 -0
- {data_flow_control-0.1.0 → data_flow_control-0.1.2}/python/data_flow_control/options.py +0 -0
- {data_flow_control-0.1.0 → data_flow_control-0.1.2}/python/data_flow_control/planner.py +0 -0
- {data_flow_control-0.1.0 → data_flow_control-0.1.2}/python/data_flow_control/policy.py +0 -0
- {data_flow_control-0.1.0 → data_flow_control-0.1.2}/python/data_flow_control/ui.py +0 -0
|
@@ -1594,7 +1594,7 @@ dependencies = [
|
|
|
1594
1594
|
|
|
1595
1595
|
[[package]]
|
|
1596
1596
|
name = "passant-cli"
|
|
1597
|
-
version = "0.1.
|
|
1597
|
+
version = "0.1.2"
|
|
1598
1598
|
dependencies = [
|
|
1599
1599
|
"anyhow",
|
|
1600
1600
|
"assert_cmd",
|
|
@@ -1606,7 +1606,7 @@ dependencies = [
|
|
|
1606
1606
|
|
|
1607
1607
|
[[package]]
|
|
1608
1608
|
name = "passant-core"
|
|
1609
|
-
version = "0.1.
|
|
1609
|
+
version = "0.1.2"
|
|
1610
1610
|
dependencies = [
|
|
1611
1611
|
"anyhow",
|
|
1612
1612
|
"criterion",
|
|
@@ -1624,7 +1624,7 @@ dependencies = [
|
|
|
1624
1624
|
|
|
1625
1625
|
[[package]]
|
|
1626
1626
|
name = "passant-py"
|
|
1627
|
-
version = "0.1.
|
|
1627
|
+
version = "0.1.2"
|
|
1628
1628
|
dependencies = [
|
|
1629
1629
|
"passant-core",
|
|
1630
1630
|
"pyo3",
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 dataflowcontrol
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: data-flow-control
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.2
|
|
4
4
|
Requires-Dist: boto3>=1.26.0
|
|
5
5
|
Requires-Dist: duckdb>=1.3.0
|
|
6
|
+
Requires-Dist: langchain>=1.3,<2
|
|
7
|
+
Requires-Dist: langchain-core>=1.3,<2
|
|
6
8
|
Requires-Dist: numpy>=1.24.4
|
|
7
9
|
Requires-Dist: sqlglot==28.3.0
|
|
8
10
|
Requires-Dist: clickhouse-connect>=0.7.0 ; extra == 'clickhouse'
|
|
9
|
-
Requires-Dist: datafusion>=53.0.0 ;
|
|
11
|
+
Requires-Dist: datafusion>=53.0.0 ; extra == 'datafusion'
|
|
10
12
|
Requires-Dist: pyarrow>=14.0.0 ; extra == 'datafusion'
|
|
11
13
|
Requires-Dist: maturin>=1.7.0 ; extra == 'dev'
|
|
12
14
|
Requires-Dist: pytest>=8.4.2 ; extra == 'dev'
|
|
@@ -16,5 +18,7 @@ Provides-Extra: clickhouse
|
|
|
16
18
|
Provides-Extra: datafusion
|
|
17
19
|
Provides-Extra: dev
|
|
18
20
|
Provides-Extra: postgres
|
|
21
|
+
License-File: LICENSE
|
|
19
22
|
Summary: Rust-backed Data Flow Control rewrite engine
|
|
20
|
-
|
|
23
|
+
License-Expression: MIT
|
|
24
|
+
Requires-Python: >=3.10
|
|
@@ -36,7 +36,7 @@ impl From<RewriteStats> for RewriteStatsExport {
|
|
|
36
36
|
}
|
|
37
37
|
}
|
|
38
38
|
|
|
39
|
-
/// Optional rewrite instrumentation counters (see `
|
|
39
|
+
/// Optional rewrite instrumentation counters (see `developer-docs/performance.md`).
|
|
40
40
|
#[derive(Debug, Default, Clone)]
|
|
41
41
|
pub struct RewriteStats {
|
|
42
42
|
pub total_policies: usize,
|
|
@@ -1,11 +1,15 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "data-flow-control"
|
|
3
|
-
version = "0.1.
|
|
3
|
+
version = "0.1.2"
|
|
4
4
|
description = "Rust-backed Data Flow Control rewrite engine"
|
|
5
|
-
|
|
5
|
+
license = "MIT"
|
|
6
|
+
license-files = ["LICENSE"]
|
|
7
|
+
requires-python = ">=3.10"
|
|
6
8
|
dependencies = [
|
|
7
9
|
"boto3>=1.26.0",
|
|
8
10
|
"duckdb>=1.3.0",
|
|
11
|
+
"langchain>=1.3,<2",
|
|
12
|
+
"langchain-core>=1.3,<2",
|
|
9
13
|
"numpy>=1.24.4",
|
|
10
14
|
"sqlglot==28.3.0",
|
|
11
15
|
]
|
|
@@ -23,7 +27,7 @@ clickhouse = [
|
|
|
23
27
|
"clickhouse-connect>=0.7.0",
|
|
24
28
|
]
|
|
25
29
|
datafusion = [
|
|
26
|
-
"datafusion>=53.0.0
|
|
30
|
+
"datafusion>=53.0.0",
|
|
27
31
|
"pyarrow>=14.0.0",
|
|
28
32
|
]
|
|
29
33
|
|
|
@@ -45,10 +49,16 @@ markers = [
|
|
|
45
49
|
"postgres: requires psycopg and Passant docker postgres service",
|
|
46
50
|
"clickhouse: requires clickhouse-connect and Passant docker clickhouse service",
|
|
47
51
|
"umbra: requires psycopg and Passant docker umbra service",
|
|
48
|
-
"flock: optional Flock DuckDB extension tests (see
|
|
52
|
+
"flock: optional Flock DuckDB extension tests (see scripts/setup_flock.sh)",
|
|
49
53
|
"ui_extension: optional extended_duckdb UI stream union tests",
|
|
54
|
+
"langchain: LangChain tool-use integration tests",
|
|
50
55
|
]
|
|
51
56
|
|
|
57
|
+
[tool.ruff.lint.per-file-ignores]
|
|
58
|
+
"python/tests/test_langchain*.py" = ["E402"]
|
|
59
|
+
"python/tests/test_call_tool_with_dataflow.py" = ["E402"]
|
|
60
|
+
|
|
52
61
|
[tool.ruff]
|
|
53
62
|
line-length = 100
|
|
54
|
-
target-version = "
|
|
63
|
+
target-version = "py310"
|
|
64
|
+
exclude = ["extended_duckdb"]
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
from ._passant import PassantRewriteError
|
|
2
|
+
from .connection import dfc
|
|
3
|
+
from .dialect import Dialect
|
|
4
|
+
from .options import RewriteOptions, UiUpdateMode
|
|
5
|
+
from .policy import Policy, Resolution
|
|
6
|
+
from .ui import UiViolationEvent
|
|
7
|
+
|
|
8
|
+
__all__ = [
|
|
9
|
+
"create_agent",
|
|
10
|
+
"dfc",
|
|
11
|
+
"Dialect",
|
|
12
|
+
"langchain_dfc",
|
|
13
|
+
"Policy",
|
|
14
|
+
"Resolution",
|
|
15
|
+
"RewriteOptions",
|
|
16
|
+
"UiUpdateMode",
|
|
17
|
+
"PassantRewriteError",
|
|
18
|
+
"UiViolationEvent",
|
|
19
|
+
]
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def __getattr__(name: str):
|
|
23
|
+
if name == "create_agent":
|
|
24
|
+
from .langchain import create_agent as _create_agent
|
|
25
|
+
|
|
26
|
+
return _create_agent
|
|
27
|
+
if name == "langchain_dfc":
|
|
28
|
+
from .langchain import langchain_dfc as _langchain_dfc
|
|
29
|
+
|
|
30
|
+
return _langchain_dfc
|
|
31
|
+
raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
"""LangChain integration for Passant data flow control."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from .agent import create_agent, store_langchain_agent_config
|
|
6
|
+
from .wrapper import LangChainDFC, langchain_dfc
|
|
7
|
+
|
|
8
|
+
__all__ = ["LangChainDFC", "create_agent", "langchain_dfc", "store_langchain_agent_config"]
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
"""LangChain agent configuration for Passant wrapping."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from dataclasses import dataclass, field
|
|
6
|
+
from typing import Any
|
|
7
|
+
|
|
8
|
+
from langchain.agents import create_agent as _langchain_create_agent
|
|
9
|
+
|
|
10
|
+
from .middleware import CALL_TOOL_WITH_DATAFLOW_NAME
|
|
11
|
+
from .tool_spec import ToolSpec, tools_to_specs
|
|
12
|
+
|
|
13
|
+
PASSANT_CONFIG_ATTR = "_passant_langchain_config"
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class UnsupportedAgentError(ValueError):
|
|
17
|
+
"""Raised when an agent cannot be wrapped through public LangChain hooks."""
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
@dataclass
|
|
21
|
+
class AgentConfig:
|
|
22
|
+
model: Any
|
|
23
|
+
tools: list[Any]
|
|
24
|
+
middleware: list[Any] = field(default_factory=list)
|
|
25
|
+
system_prompt: str | None = None
|
|
26
|
+
create_agent_kwargs: dict[str, Any] = field(default_factory=dict)
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def create_agent(
|
|
30
|
+
model: Any,
|
|
31
|
+
tools: list[Any],
|
|
32
|
+
*,
|
|
33
|
+
middleware: list[Any] | None = None,
|
|
34
|
+
system_prompt: str | None = None,
|
|
35
|
+
**create_agent_kwargs: Any,
|
|
36
|
+
) -> Any:
|
|
37
|
+
"""Create a LangChain agent and attach Passant wrap configuration."""
|
|
38
|
+
agent = _langchain_create_agent(
|
|
39
|
+
model=model,
|
|
40
|
+
tools=tools,
|
|
41
|
+
middleware=tuple(middleware or ()),
|
|
42
|
+
system_prompt=system_prompt,
|
|
43
|
+
**create_agent_kwargs,
|
|
44
|
+
)
|
|
45
|
+
return store_langchain_agent_config(
|
|
46
|
+
agent,
|
|
47
|
+
model=model,
|
|
48
|
+
tools=tools,
|
|
49
|
+
middleware=middleware,
|
|
50
|
+
system_prompt=system_prompt,
|
|
51
|
+
**create_agent_kwargs,
|
|
52
|
+
)
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def store_langchain_agent_config(
|
|
56
|
+
agent: Any,
|
|
57
|
+
*,
|
|
58
|
+
model: Any,
|
|
59
|
+
tools: list[Any],
|
|
60
|
+
middleware: list[Any] | None = None,
|
|
61
|
+
system_prompt: str | None = None,
|
|
62
|
+
**create_agent_kwargs: Any,
|
|
63
|
+
) -> Any:
|
|
64
|
+
"""Attach Passant agent configuration using only public create_agent inputs."""
|
|
65
|
+
config = AgentConfig(
|
|
66
|
+
model=model,
|
|
67
|
+
tools=list(tools),
|
|
68
|
+
middleware=list(middleware or []),
|
|
69
|
+
system_prompt=system_prompt,
|
|
70
|
+
create_agent_kwargs=dict(create_agent_kwargs),
|
|
71
|
+
)
|
|
72
|
+
setattr(agent, PASSANT_CONFIG_ATTR, config)
|
|
73
|
+
return agent
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
def resolve_agent_config(agent: Any) -> AgentConfig:
|
|
77
|
+
stored = getattr(agent, PASSANT_CONFIG_ATTR, None)
|
|
78
|
+
if stored is not None:
|
|
79
|
+
return stored
|
|
80
|
+
|
|
81
|
+
raise UnsupportedAgentError(
|
|
82
|
+
"Could not resolve LangChain agent configuration for the provided agent. "
|
|
83
|
+
"Create the agent with data_flow_control.langchain.create_agent(...), or call "
|
|
84
|
+
"store_langchain_agent_config(agent, model=..., tools=...) after create_agent(...). "
|
|
85
|
+
"Passant does not introspect private LangGraph state."
|
|
86
|
+
)
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
def build_wrapped_agent(
|
|
90
|
+
config: AgentConfig,
|
|
91
|
+
*,
|
|
92
|
+
visible_tools: list[Any],
|
|
93
|
+
middleware: list[Any],
|
|
94
|
+
) -> Any:
|
|
95
|
+
wrapped = _langchain_create_agent(
|
|
96
|
+
model=config.model,
|
|
97
|
+
tools=visible_tools,
|
|
98
|
+
system_prompt=config.system_prompt,
|
|
99
|
+
middleware=[*config.middleware, *middleware],
|
|
100
|
+
**config.create_agent_kwargs,
|
|
101
|
+
)
|
|
102
|
+
setattr(wrapped, PASSANT_CONFIG_ATTR, config)
|
|
103
|
+
return wrapped
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
def specs_from_agent_tools(
|
|
107
|
+
tools: list[Any],
|
|
108
|
+
*,
|
|
109
|
+
output_schemas: dict[str, Any] | None,
|
|
110
|
+
) -> list[ToolSpec]:
|
|
111
|
+
filtered = [
|
|
112
|
+
tool for tool in tools if getattr(tool, "name", None) != CALL_TOOL_WITH_DATAFLOW_NAME
|
|
113
|
+
]
|
|
114
|
+
return tools_to_specs(filtered, output_schemas=output_schemas)
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
"""CallToolWithDataFlow LangChain tool implementation."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import asyncio
|
|
6
|
+
import json
|
|
7
|
+
from typing import Any
|
|
8
|
+
|
|
9
|
+
from langchain.tools import tool
|
|
10
|
+
|
|
11
|
+
from .database import ToolUseDatabase
|
|
12
|
+
from .middleware import CALL_TOOL_WITH_DATAFLOW_NAME
|
|
13
|
+
from .sql_validation import validate_call_tool_sql
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class CallToolWithDataFlowRunner:
|
|
17
|
+
"""Executes SQL over Passant tool tables and drains pending tool inputs."""
|
|
18
|
+
|
|
19
|
+
def __init__(self, db: ToolUseDatabase) -> None:
|
|
20
|
+
self.db = db
|
|
21
|
+
|
|
22
|
+
def _drain_new_rows(self, before: dict[str, set[int]]) -> list[dict[str, Any]]:
|
|
23
|
+
tool_outputs: list[dict[str, Any]] = []
|
|
24
|
+
new_rows = self.db.find_new_pending_rows(before)
|
|
25
|
+
with self.db._lock:
|
|
26
|
+
for tool_name, input_id in new_rows:
|
|
27
|
+
if not self.db.claim_input_row(tool_name, input_id):
|
|
28
|
+
continue
|
|
29
|
+
status, _result, output_id = self.db.execute_tool_for_input(tool_name, input_id)
|
|
30
|
+
tool_outputs.append(
|
|
31
|
+
{
|
|
32
|
+
"tool": tool_name,
|
|
33
|
+
"input_id": input_id,
|
|
34
|
+
"status": status,
|
|
35
|
+
"output_id": output_id,
|
|
36
|
+
}
|
|
37
|
+
)
|
|
38
|
+
return tool_outputs
|
|
39
|
+
|
|
40
|
+
async def _adrain_new_rows(self, before: dict[str, set[int]]) -> list[dict[str, Any]]:
|
|
41
|
+
tool_outputs: list[dict[str, Any]] = []
|
|
42
|
+
new_rows = self.db.find_new_pending_rows(before)
|
|
43
|
+
if self.db._async_lock is None:
|
|
44
|
+
self.db._async_lock = asyncio.Lock()
|
|
45
|
+
async with self.db._async_lock:
|
|
46
|
+
for tool_name, input_id in new_rows:
|
|
47
|
+
if not self.db.claim_input_row(tool_name, input_id):
|
|
48
|
+
continue
|
|
49
|
+
status, _result, output_id = await self.db.execute_tool_for_input_async(
|
|
50
|
+
tool_name, input_id
|
|
51
|
+
)
|
|
52
|
+
tool_outputs.append(
|
|
53
|
+
{
|
|
54
|
+
"tool": tool_name,
|
|
55
|
+
"input_id": input_id,
|
|
56
|
+
"status": status,
|
|
57
|
+
"output_id": output_id,
|
|
58
|
+
}
|
|
59
|
+
)
|
|
60
|
+
return tool_outputs
|
|
61
|
+
|
|
62
|
+
def run(self, sql: str) -> str:
|
|
63
|
+
validated = validate_call_tool_sql(
|
|
64
|
+
sql,
|
|
65
|
+
allowed_input_tables=self.db.allowed_input_tables,
|
|
66
|
+
protected_tables=self.db.protected_tables,
|
|
67
|
+
)
|
|
68
|
+
sql_call_id = self.db._next_sql_call_id()
|
|
69
|
+
before = self.db.snapshot_pending_input_ids()
|
|
70
|
+
rows: list[list[Any]] = []
|
|
71
|
+
error: str | None = None
|
|
72
|
+
tool_outputs: list[dict[str, Any]] = []
|
|
73
|
+
|
|
74
|
+
try:
|
|
75
|
+
if validated.statement_type == "select":
|
|
76
|
+
result = self.db.conn.execute(validated.sql)
|
|
77
|
+
rows = [list(row) for row in result.fetchall()]
|
|
78
|
+
else:
|
|
79
|
+
self.db.conn.execute(validated.sql)
|
|
80
|
+
|
|
81
|
+
tool_outputs = self._drain_new_rows(before)
|
|
82
|
+
except Exception as exc:
|
|
83
|
+
error = str(exc)
|
|
84
|
+
|
|
85
|
+
self.db.log_sql_call(
|
|
86
|
+
sql_call_id=sql_call_id,
|
|
87
|
+
sql=validated.sql,
|
|
88
|
+
row_count_inserted=len(tool_outputs),
|
|
89
|
+
tool_calls_executed=len(tool_outputs),
|
|
90
|
+
error=error,
|
|
91
|
+
)
|
|
92
|
+
|
|
93
|
+
if error is not None:
|
|
94
|
+
raise RuntimeError(error)
|
|
95
|
+
|
|
96
|
+
payload = {
|
|
97
|
+
"sql_call_id": sql_call_id,
|
|
98
|
+
"statement_type": validated.statement_type,
|
|
99
|
+
"inserted_input_rows": len(tool_outputs),
|
|
100
|
+
"tool_calls_executed": len(tool_outputs),
|
|
101
|
+
"tool_outputs": tool_outputs,
|
|
102
|
+
"rows": rows,
|
|
103
|
+
}
|
|
104
|
+
return json.dumps(payload, default=str)
|
|
105
|
+
|
|
106
|
+
async def arun(self, sql: str) -> str:
|
|
107
|
+
validated = validate_call_tool_sql(
|
|
108
|
+
sql,
|
|
109
|
+
allowed_input_tables=self.db.allowed_input_tables,
|
|
110
|
+
protected_tables=self.db.protected_tables,
|
|
111
|
+
)
|
|
112
|
+
sql_call_id = self.db._next_sql_call_id()
|
|
113
|
+
before = self.db.snapshot_pending_input_ids()
|
|
114
|
+
rows: list[list[Any]] = []
|
|
115
|
+
error: str | None = None
|
|
116
|
+
tool_outputs: list[dict[str, Any]] = []
|
|
117
|
+
|
|
118
|
+
try:
|
|
119
|
+
if validated.statement_type == "select":
|
|
120
|
+
result = await asyncio.to_thread(self.db.conn.execute, validated.sql)
|
|
121
|
+
rows = [list(row) for row in result.fetchall()]
|
|
122
|
+
else:
|
|
123
|
+
await asyncio.to_thread(self.db.conn.execute, validated.sql)
|
|
124
|
+
|
|
125
|
+
tool_outputs = await self._adrain_new_rows(before)
|
|
126
|
+
except Exception as exc:
|
|
127
|
+
error = str(exc)
|
|
128
|
+
|
|
129
|
+
await asyncio.to_thread(
|
|
130
|
+
self.db.log_sql_call,
|
|
131
|
+
sql_call_id=sql_call_id,
|
|
132
|
+
sql=validated.sql,
|
|
133
|
+
row_count_inserted=len(tool_outputs),
|
|
134
|
+
tool_calls_executed=len(tool_outputs),
|
|
135
|
+
error=error,
|
|
136
|
+
)
|
|
137
|
+
|
|
138
|
+
if error is not None:
|
|
139
|
+
raise RuntimeError(error)
|
|
140
|
+
|
|
141
|
+
payload = {
|
|
142
|
+
"sql_call_id": sql_call_id,
|
|
143
|
+
"statement_type": validated.statement_type,
|
|
144
|
+
"inserted_input_rows": len(tool_outputs),
|
|
145
|
+
"tool_calls_executed": len(tool_outputs),
|
|
146
|
+
"tool_outputs": tool_outputs,
|
|
147
|
+
"rows": rows,
|
|
148
|
+
}
|
|
149
|
+
return json.dumps(payload, default=str)
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
def build_call_tool_with_dataflow(db: ToolUseDatabase) -> Any:
|
|
153
|
+
runner = CallToolWithDataFlowRunner(db)
|
|
154
|
+
|
|
155
|
+
@tool(CALL_TOOL_WITH_DATAFLOW_NAME)
|
|
156
|
+
def call_tool_with_dataflow(sql: str) -> str:
|
|
157
|
+
"""Execute SQL over Passant tool input/output tables and run inserted tool inputs."""
|
|
158
|
+
return runner.run(sql)
|
|
159
|
+
|
|
160
|
+
return call_tool_with_dataflow
|