nl2sql-engine 0.1.0__tar.gz → 0.1.1__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.
Files changed (201) hide show
  1. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/PKG-INFO +1 -1
  2. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/pyproject.toml +1 -1
  3. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql/api/datasource_api.py +2 -2
  4. nl2sql_engine-0.1.1/src/nl2sql/cli/checks.py +80 -0
  5. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql/cli/commands/setup.py +16 -1
  6. nl2sql_engine-0.1.1/src/nl2sql/cli/common/prompts.py +53 -0
  7. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql/cli/demo/defaults.py +12 -8
  8. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql/cli/demo/schemas.py +12 -0
  9. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql/cli/demo/writers/docker.py +12 -0
  10. nl2sql_engine-0.1.1/src/nl2sql/common/exceptions.py +24 -0
  11. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql/configs/manager.py +4 -1
  12. nl2sql_engine-0.1.1/src/nl2sql/configs/secrets.py +23 -0
  13. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql/datasources/registry.py +52 -13
  14. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql/pipeline/routes.py +8 -5
  15. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql/pipeline/runtime.py +6 -0
  16. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql_engine.egg-info/PKG-INFO +1 -1
  17. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql_engine.egg-info/SOURCES.txt +1 -0
  18. nl2sql_engine-0.1.0/src/nl2sql/cli/checks.py +0 -53
  19. nl2sql_engine-0.1.0/src/nl2sql/common/exceptions.py +0 -3
  20. nl2sql_engine-0.1.0/src/nl2sql/configs/secrets.py +0 -11
  21. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/README.md +0 -0
  22. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/setup.cfg +0 -0
  23. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql/__init__.py +0 -0
  24. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql/adapters/__init__.py +0 -0
  25. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql/adapters/duckdb/__init__.py +0 -0
  26. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql/adapters/duckdb/adapter.py +0 -0
  27. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql/adapters/mssql/__init__.py +0 -0
  28. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql/adapters/mssql/adapter.py +0 -0
  29. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql/adapters/mysql/__init__.py +0 -0
  30. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql/adapters/mysql/adapter.py +0 -0
  31. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql/adapters/postgres/__init__.py +0 -0
  32. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql/adapters/postgres/adapter.py +0 -0
  33. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql/adapters/sqlalchemy_base/__init__.py +0 -0
  34. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql/adapters/sqlalchemy_base/adapter.py +0 -0
  35. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql/adapters/sqlalchemy_base/models.py +0 -0
  36. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql/adapters/sqlite/__init__.py +0 -0
  37. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql/adapters/sqlite/adapter.py +0 -0
  38. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql/aggregation/__init__.py +0 -0
  39. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql/aggregation/aggregator.py +0 -0
  40. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql/aggregation/engines/__init__.py +0 -0
  41. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql/aggregation/engines/polars_duckdb.py +0 -0
  42. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql/api/__init__.py +0 -0
  43. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql/api/auth_api.py +0 -0
  44. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql/api/benchmark_api.py +0 -0
  45. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql/api/indexing_api.py +0 -0
  46. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql/api/llm_api.py +0 -0
  47. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql/api/policy_api.py +0 -0
  48. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql/api/query_api.py +0 -0
  49. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql/api/result_api.py +0 -0
  50. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql/api/settings_api.py +0 -0
  51. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql/auth/__init__.py +0 -0
  52. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql/auth/models.py +0 -0
  53. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql/auth/rbac.py +0 -0
  54. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql/cli/__init__.py +0 -0
  55. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql/cli/commands/__init__.py +0 -0
  56. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql/cli/commands/benchmark.py +0 -0
  57. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql/cli/commands/doctor.py +0 -0
  58. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql/cli/commands/indexing.py +0 -0
  59. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql/cli/commands/info.py +0 -0
  60. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql/cli/commands/install.py +0 -0
  61. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql/cli/commands/policy.py +0 -0
  62. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql/cli/commands/run.py +0 -0
  63. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql/cli/commands/visualize.py +0 -0
  64. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql/cli/common/decorators.py +0 -0
  65. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql/cli/config.py +0 -0
  66. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql/cli/console.py +0 -0
  67. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql/cli/demo/__init__.py +0 -0
  68. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql/cli/demo/data.py +0 -0
  69. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql/cli/demo/factory.py +0 -0
  70. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql/cli/demo/manager.py +0 -0
  71. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql/cli/demo/writers/__init__.py +0 -0
  72. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql/cli/demo/writers/sqlite.py +0 -0
  73. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql/cli/generators/datasources/__init__.py +0 -0
  74. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql/cli/generators/datasources/generator.py +0 -0
  75. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql/cli/generators/datasources/templates.py +0 -0
  76. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql/cli/generators/env/__init__.py +0 -0
  77. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql/cli/generators/env/generator.py +0 -0
  78. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql/cli/generators/env/templates.py +0 -0
  79. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql/cli/generators/llm/__init__.py +0 -0
  80. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql/cli/generators/llm/generator.py +0 -0
  81. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql/cli/generators/llm/templates.py +0 -0
  82. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql/cli/generators/policies/__init__.py +0 -0
  83. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql/cli/generators/policies/generator.py +0 -0
  84. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql/cli/generators/policies/templates.py +0 -0
  85. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql/cli/main.py +0 -0
  86. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql/cli/reporting.py +0 -0
  87. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql/cli/types.py +0 -0
  88. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql/common/__init__.py +0 -0
  89. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql/common/cancellation.py +0 -0
  90. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql/common/context.py +0 -0
  91. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql/common/errors.py +0 -0
  92. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql/common/event_logger.py +0 -0
  93. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql/common/logger.py +0 -0
  94. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql/common/metrics.py +0 -0
  95. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql/common/resilience.py +0 -0
  96. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql/common/settings.py +0 -0
  97. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql/configs/__init__.py +0 -0
  98. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql/configs/datasources.py +0 -0
  99. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql/configs/llm.py +0 -0
  100. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql/configs/policies.py +0 -0
  101. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql/configs/sample_questions.py +0 -0
  102. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql/context.py +0 -0
  103. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql/datasources/__init__.py +0 -0
  104. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql/datasources/discovery.py +0 -0
  105. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql/datasources/models.py +0 -0
  106. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql/datasources/protocols.py +0 -0
  107. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql/evaluation/__init__.py +0 -0
  108. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql/evaluation/benchmark_runner.py +0 -0
  109. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql/evaluation/evaluator.py +0 -0
  110. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql/evaluation/types.py +0 -0
  111. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql/execution/__init__.py +0 -0
  112. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql/execution/artifacts/__init__.py +0 -0
  113. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql/execution/artifacts/parquet.py +0 -0
  114. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql/execution/artifacts/store.py +0 -0
  115. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql/execution/contracts.py +0 -0
  116. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql/execution/execution_store.py +0 -0
  117. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql/execution/executor/__init__.py +0 -0
  118. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql/execution/executor/sql_executor.py +0 -0
  119. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql/indexing/__init__.py +0 -0
  120. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql/indexing/chunk_builder.py +0 -0
  121. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql/indexing/embeddings.py +0 -0
  122. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql/indexing/enrichment_service.py +0 -0
  123. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql/indexing/models.py +0 -0
  124. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql/indexing/orchestrator.py +0 -0
  125. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql/indexing/vector_store.py +0 -0
  126. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql/llm/__init__.py +0 -0
  127. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql/llm/models.py +0 -0
  128. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql/llm/registry.py +0 -0
  129. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql/pipeline/__init__.py +0 -0
  130. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql/pipeline/graph.py +0 -0
  131. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql/pipeline/graph_utils.py +0 -0
  132. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql/pipeline/nodes/__init__.py +0 -0
  133. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql/pipeline/nodes/aggregator/__init__.py +0 -0
  134. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql/pipeline/nodes/aggregator/node.py +0 -0
  135. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql/pipeline/nodes/aggregator/prompts.py +0 -0
  136. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql/pipeline/nodes/aggregator/schemas.py +0 -0
  137. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql/pipeline/nodes/answer_synthesizer/__init__.py +0 -0
  138. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql/pipeline/nodes/answer_synthesizer/node.py +0 -0
  139. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql/pipeline/nodes/answer_synthesizer/prompts.py +0 -0
  140. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql/pipeline/nodes/answer_synthesizer/schemas.py +0 -0
  141. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql/pipeline/nodes/ast_planner/__init__.py +0 -0
  142. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql/pipeline/nodes/ast_planner/node.py +0 -0
  143. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql/pipeline/nodes/ast_planner/prompts.py +0 -0
  144. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql/pipeline/nodes/ast_planner/schemas.py +0 -0
  145. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql/pipeline/nodes/datasource_resolver/__init__.py +0 -0
  146. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql/pipeline/nodes/datasource_resolver/node.py +0 -0
  147. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql/pipeline/nodes/datasource_resolver/schemas.py +0 -0
  148. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql/pipeline/nodes/decomposer/__init__.py +0 -0
  149. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql/pipeline/nodes/decomposer/node.py +0 -0
  150. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql/pipeline/nodes/decomposer/prompts.py +0 -0
  151. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql/pipeline/nodes/decomposer/schemas.py +0 -0
  152. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql/pipeline/nodes/executor/__init__.py +0 -0
  153. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql/pipeline/nodes/executor/node.py +0 -0
  154. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql/pipeline/nodes/generator/__init__.py +0 -0
  155. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql/pipeline/nodes/generator/node.py +0 -0
  156. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql/pipeline/nodes/generator/schemas.py +0 -0
  157. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql/pipeline/nodes/global_planner/__init__.py +0 -0
  158. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql/pipeline/nodes/global_planner/node.py +0 -0
  159. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql/pipeline/nodes/global_planner/schemas.py +0 -0
  160. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql/pipeline/nodes/refiner/__init__.py +0 -0
  161. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql/pipeline/nodes/refiner/node.py +0 -0
  162. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql/pipeline/nodes/refiner/prompts.py +0 -0
  163. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql/pipeline/nodes/refiner/schemas.py +0 -0
  164. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql/pipeline/nodes/schema_retriever/__init__.py +0 -0
  165. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql/pipeline/nodes/schema_retriever/node.py +0 -0
  166. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql/pipeline/nodes/schema_retriever/schema.py +0 -0
  167. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql/pipeline/nodes/validator/__init__.py +0 -0
  168. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql/pipeline/nodes/validator/node.py +0 -0
  169. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql/pipeline/nodes/validator/schemas.py +0 -0
  170. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql/pipeline/pipeline_runner.py +0 -0
  171. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql/pipeline/state.py +0 -0
  172. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql/pipeline/subgraphs/__init__.py +0 -0
  173. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql/pipeline/subgraphs/schemas.py +0 -0
  174. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql/pipeline/subgraphs/sql_agent.py +0 -0
  175. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql/public_api.py +0 -0
  176. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql/schema/__init__.py +0 -0
  177. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql/schema/in_memory_store.py +0 -0
  178. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql/schema/protocol.py +0 -0
  179. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql/schema/sqlite_store.py +0 -0
  180. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql/schema/store.py +0 -0
  181. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql/secrets/__init__.py +0 -0
  182. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql/secrets/factory.py +0 -0
  183. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql/secrets/interfaces.py +0 -0
  184. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql/secrets/manager.py +0 -0
  185. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql/secrets/models.py +0 -0
  186. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql/secrets/providers/aws.py +0 -0
  187. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql/secrets/providers/azure.py +0 -0
  188. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql/secrets/providers/env.py +0 -0
  189. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql/secrets/providers/hashi.py +0 -0
  190. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql/services/__init__.py +0 -0
  191. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql/services/callbacks/__init__.py +0 -0
  192. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql/services/callbacks/monitor.py +0 -0
  193. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql/services/callbacks/node_context.py +0 -0
  194. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql/services/callbacks/node_handlers.py +0 -0
  195. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql/services/callbacks/node_metrics.py +0 -0
  196. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql/services/callbacks/presenter.py +0 -0
  197. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql/services/callbacks/token_handler.py +0 -0
  198. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql_engine.egg-info/dependency_links.txt +0 -0
  199. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql_engine.egg-info/entry_points.txt +0 -0
  200. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql_engine.egg-info/requires.txt +0 -0
  201. {nl2sql_engine-0.1.0 → nl2sql_engine-0.1.1}/src/nl2sql_engine.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: nl2sql-engine
3
- Version: 0.1.0
3
+ Version: 0.1.1
4
4
  Summary: Natural-language-to-SQL engine, CLI and database adapters
5
5
  Requires-Python: >=3.9
6
6
  Description-Content-Type: text/markdown
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "nl2sql-engine"
7
- version = "0.1.0" # x-release-please-version
7
+ version = "0.1.1" # x-release-please-version
8
8
  description = "Natural-language-to-SQL engine, CLI and database adapters"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.9"
@@ -10,7 +10,7 @@ import pathlib
10
10
  from typing import Union, Dict, Any, List
11
11
 
12
12
  from nl2sql.context import NL2SQLContext
13
- from nl2sql.datasources.registry import DatasourceRegistry
13
+ from nl2sql.datasources.registry import DatasourceRegistry, mask_connection_args
14
14
  from nl2sql.datasources.models import DatasourceConfig
15
15
 
16
16
 
@@ -123,7 +123,7 @@ class DatasourceAPI:
123
123
  details = {
124
124
  "datasource_id": adapter.datasource_id,
125
125
  "datasource_engine_type": adapter.datasource_engine_type,
126
- "connection_args": adapter.connection_args,
126
+ "connection_args": mask_connection_args(adapter.connection_args),
127
127
  "statement_timeout_ms": adapter.statement_timeout_ms,
128
128
  "row_limit": adapter.row_limit,
129
129
  "max_bytes": adapter.max_bytes,
@@ -0,0 +1,80 @@
1
+ import importlib.util
2
+
3
+ from rich.table import Table
4
+ from rich.text import Text
5
+
6
+ from nl2sql.cli.console import console
7
+ from nl2sql.configs import ConfigManager
8
+ from nl2sql.datasources import DatasourceRegistry
9
+ from nl2sql.secrets import SecretManager
10
+
11
+
12
+ def check_package(name: str) -> bool:
13
+ """Checks if a python package is installed."""
14
+ import_name = name.replace("-", "_")
15
+ return importlib.util.find_spec(import_name) is not None
16
+
17
+
18
+ def verify_connectivity(print_table: bool = True) -> bool:
19
+ """Checks connectivity for every configured datasource.
20
+
21
+ This backs ``nl2sql doctor``, which is what a user runs when something is
22
+ already wrong, so no failure mode may escape as an exception: a broken
23
+ config, an uninstalled driver, an unresolvable secret and a driver that
24
+ raises on connect all have to come back as a reported row or a message.
25
+
26
+ Returns:
27
+ bool: True only if every datasource connected. ``setup`` branches on
28
+ this to decide whether to warn before continuing.
29
+ """
30
+ try:
31
+ config_manager = ConfigManager()
32
+ secret_manager = SecretManager()
33
+ secret_configs = config_manager.load_secrets()
34
+ if secret_configs:
35
+ secret_manager.configure(secret_configs)
36
+ ds_configs = config_manager.load_datasources()
37
+ registry = DatasourceRegistry(secret_manager)
38
+ except Exception as e:
39
+ # Externally-sourced text (paths, parser errors): print it as Text so
40
+ # a bracket sequence in the message cannot be parsed as rich markup.
41
+ console.print(Text(f"Connectivity check failed: {e}", style="red"))
42
+ return False
43
+
44
+ if not ds_configs:
45
+ console.print("[yellow]No datasources configured.[/yellow]")
46
+ return True
47
+
48
+ results = []
49
+
50
+ with console.status("[bold green]Verifying connectivity...[/bold green]"):
51
+ for config in ds_configs:
52
+ ds_id = getattr(config, "id", None) or "<unknown>"
53
+ try:
54
+ adapter = registry.register_datasource(config)
55
+ except Exception as e:
56
+ results.append((ds_id, False, str(e)))
57
+ continue
58
+
59
+ try:
60
+ ok = bool(adapter.test_connection())
61
+ details = "" if ok else "Connection test failed."
62
+ except Exception as e:
63
+ ok, details = False, str(e)
64
+ results.append((ds_id, ok, details))
65
+
66
+ all_ok = all(ok for _, ok, _ in results)
67
+
68
+ if print_table:
69
+ conn_table = Table(show_header=True, header_style="bold cyan")
70
+ conn_table.add_column("Datasource ID")
71
+ conn_table.add_column("Status")
72
+ conn_table.add_column("Details")
73
+
74
+ for ds_id, ok, details in results:
75
+ status = "[green]OK[/green]" if ok else "[red]Failed[/red]"
76
+ conn_table.add_row(Text(str(ds_id)), status, Text(str(details)))
77
+
78
+ console.print(conn_table)
79
+
80
+ return all_ok
@@ -7,6 +7,7 @@ from InquirerPy import inquirer
7
7
  from InquirerPy.validator import NumberValidator
8
8
 
9
9
  from nl2sql.cli.common.decorators import handle_cli_errors
10
+ from nl2sql.cli.common.prompts import confirm
10
11
  from nl2sql.cli.console import console, print_success, print_step
11
12
  from nl2sql.cli.config import ADAPTER_DRIVERS, KNOWN_ADAPTERS
12
13
  from nl2sql.cli.commands.install import install_package
@@ -357,8 +358,22 @@ def setup_command(demo: bool = False, lite: bool = True, docker: bool = False, a
357
358
  demo_manager.setup_lite(api_key=api_key)
358
359
  elif docker:
359
360
  docker_dir = demo_manager.setup_docker(api_key=api_key)
360
- if inquirer.confirm(message="Start Docker containers now?", default=True).execute():
361
+ # A terminal that cannot host a prompt (Git Bash/MSYS) must not be
362
+ # read as consent to pull images and bind ports, so the fallback is
363
+ # "no": the artifacts are already on disk and the panel below tells
364
+ # the user how to start the stack themselves.
365
+ if confirm(
366
+ "Start Docker containers now?",
367
+ default=True,
368
+ when_unavailable=False,
369
+ ):
361
370
  demo_manager.start_docker_containers(docker_dir)
371
+ else:
372
+ console.print(
373
+ f"[dim]Containers not started. To start them yourself: "
374
+ f"cd {escape(str(docker_dir))} && "
375
+ f"docker compose -f docker-compose.demo.yml up -d[/dim]"
376
+ )
362
377
 
363
378
  console.print(Panel(f"""[bold yellow]Next Steps:[/bold yellow]
364
379
  1. [bold]Verify & Index[/bold]:
@@ -0,0 +1,53 @@
1
+ """Interactive prompts that survive a terminal which cannot host them.
2
+
3
+ Git Bash / MSYS on Windows present a TTY that is not a Windows console, so
4
+ ``prompt_toolkit`` -- which InquirerPy builds every prompt on -- refuses to
5
+ attach and raises ``NoConsoleScreenBufferError``. That killed
6
+ ``nl2sql setup --demo --docker`` with a traceback *after* it had already
7
+ written the demo artifacts, which is the exact flow the docs tell users to run.
8
+
9
+ The convention here: a prompt that cannot be shown is answered the way a
10
+ non-interactive run would answer it, and the caller states that answer
11
+ explicitly rather than inheriting the interactive default. The two are not the
12
+ same -- a prompt guarding an action with side effects defaults to "yes" when a
13
+ human is watching and to "no" when nobody can say otherwise.
14
+ """
15
+
16
+ from __future__ import annotations
17
+
18
+ import sys
19
+
20
+ from InquirerPy import inquirer
21
+ from rich.markup import escape
22
+
23
+ from nl2sql.cli.console import console
24
+
25
+ if sys.platform == "win32": # pragma: no cover - exercised only on Windows
26
+ from prompt_toolkit.output.win32 import NoConsoleScreenBufferError
27
+ else:
28
+ class NoConsoleScreenBufferError(Exception):
29
+ """Stand-in for the Windows-only prompt_toolkit error.
30
+
31
+ ``prompt_toolkit.output.win32`` asserts ``sys.platform == "win32"`` at
32
+ import time, so the real class cannot be imported elsewhere. This one is
33
+ never raised in production; it only keeps the ``except`` clause below
34
+ importable (and testable) on every platform.
35
+ """
36
+
37
+
38
+ def confirm(message: str, default: bool, when_unavailable: bool) -> bool:
39
+ """Ask a yes/no question, falling back when no prompt can be displayed.
40
+
41
+ ``default`` is the pre-selected answer for a human; ``when_unavailable`` is
42
+ the answer used when the terminal cannot host a prompt at all.
43
+ """
44
+ try:
45
+ return inquirer.confirm(message=message, default=default).execute()
46
+ except (NoConsoleScreenBufferError, EOFError):
47
+ answer = "yes" if when_unavailable else "no"
48
+ console.print(
49
+ f"[yellow]No usable interactive console (Git Bash/MSYS or a "
50
+ f"redirected terminal). Assuming '{answer}' for:[/yellow] "
51
+ f"{escape(message)}"
52
+ )
53
+ return when_unavailable
@@ -69,13 +69,17 @@ DEMO_LITE_DATASOURCES = [
69
69
  {"id": "manufacturing_history", "connection": {"type": "sqlite", "database": "data/demo_lite/manufacturing_history.db"}, "description": "Historical Data (Sales)"},
70
70
  ]
71
71
 
72
+ # Host and port are resolved from the environment so one config serves both
73
+ # callers: `.env.demo` defaults to localhost + the published ports for the
74
+ # host-side CLI, and the compose `app` service overrides them with the
75
+ # compose service names + internal ports.
72
76
  DEMO_DOCKER_DATASOURCES = [
73
77
  {
74
78
  "id": "manufacturing_ref",
75
79
  "connection": {
76
80
  "type": "postgres",
77
- "host": "localhost",
78
- "port": 5433,
81
+ "host": "${env:DEMO_REF_HOST}",
82
+ "port": "${env:DEMO_REF_PORT}",
79
83
  "user": "${env:DEMO_REF_USER}",
80
84
  "password": "${env:DEMO_REF_PASSWORD}",
81
85
  "database": "manufacturing_ref"
@@ -86,8 +90,8 @@ DEMO_DOCKER_DATASOURCES = [
86
90
  "id": "manufacturing_ops",
87
91
  "connection": {
88
92
  "type": "postgres",
89
- "host": "localhost",
90
- "port": 5434,
93
+ "host": "${env:DEMO_OPS_HOST}",
94
+ "port": "${env:DEMO_OPS_PORT}",
91
95
  "user": "${env:DEMO_OPS_USER}",
92
96
  "password": "${env:DEMO_OPS_PASSWORD}",
93
97
  "database": "manufacturing_ops"
@@ -98,8 +102,8 @@ DEMO_DOCKER_DATASOURCES = [
98
102
  "id": "manufacturing_supply",
99
103
  "connection": {
100
104
  "type": "mysql",
101
- "host": "localhost",
102
- "port": 3307,
105
+ "host": "${env:DEMO_SUPPLY_HOST}",
106
+ "port": "${env:DEMO_SUPPLY_PORT}",
103
107
  "user": "${env:DEMO_SUPPLY_USER}",
104
108
  "password": "${env:DEMO_SUPPLY_PASSWORD}",
105
109
  "database": "manufacturing_supply"
@@ -110,8 +114,8 @@ DEMO_DOCKER_DATASOURCES = [
110
114
  "id": "manufacturing_history",
111
115
  "connection": {
112
116
  "type": "mssql",
113
- "host": "localhost",
114
- "port": 1434,
117
+ "host": "${env:DEMO_HISTORY_HOST}",
118
+ "port": "${env:DEMO_HISTORY_PORT}",
115
119
  "user": "${env:DEMO_HISTORY_USER}",
116
120
  "password": "${env:DEMO_HISTORY_PASSWORD}",
117
121
  "database": "manufacturing_history",
@@ -323,6 +323,18 @@ services:
323
323
  - "8000:8000"
324
324
  env_file:
325
325
  - ../.env.demo
326
+ environment:
327
+ # .env.demo points at localhost + the published ports, which is correct
328
+ # from the developer's machine but not from in here -- inside the compose
329
+ # network the databases answer on their service names and internal ports.
330
+ DEMO_REF_HOST: manufacturing_ref
331
+ DEMO_REF_PORT: 5432
332
+ DEMO_OPS_HOST: manufacturing_ops
333
+ DEMO_OPS_PORT: 5432
334
+ DEMO_SUPPLY_HOST: manufacturing_supply
335
+ DEMO_SUPPLY_PORT: 3306
336
+ DEMO_HISTORY_HOST: manufacturing_history
337
+ DEMO_HISTORY_PORT: 1433
326
338
  volumes:
327
339
  - ../configs:/app/configs
328
340
  - ../data:/app/data
@@ -157,11 +157,19 @@ GO
157
157
  content = f"""# NL2SQL Demo Environment Secrets
158
158
  # Generated automatically. DO NOT COMMIT TO VERSION CONTROL.
159
159
 
160
+ # Host-side defaults: the published ports on localhost, for
161
+ # `nl2sql --env demo index` / `run` from the developer's machine. The compose
162
+ # `app` service overrides these with the service names and internal ports.
163
+
160
164
  # 1. Manufacturing Ref (Postgres)
165
+ DEMO_REF_HOST=localhost
166
+ DEMO_REF_PORT=5433
161
167
  DEMO_REF_USER=ref_admin
162
168
  DEMO_REF_PASSWORD={secrets["DEMO_REF_PASSWORD"]}
163
169
 
164
170
  # 2. Manufacturing Ops (Postgres)
171
+ DEMO_OPS_HOST=localhost
172
+ DEMO_OPS_PORT=5434
165
173
  DEMO_OPS_USER=ops_admin
166
174
  DEMO_OPS_PASSWORD={secrets["DEMO_OPS_PASSWORD"]}
167
175
 
@@ -170,11 +178,15 @@ DEMO_POSTGRES_USER=postgres
170
178
  DEMO_POSTGRES_PASSWORD={secrets["DEMO_POSTGRES_PASSWORD"]}
171
179
 
172
180
  # 3. Manufacturing Supply (MySQL)
181
+ DEMO_SUPPLY_HOST=localhost
182
+ DEMO_SUPPLY_PORT=3307
173
183
  DEMO_SUPPLY_USER=supply_admin
174
184
  DEMO_SUPPLY_PASSWORD={secrets["DEMO_SUPPLY_PASSWORD"]}
175
185
  DEMO_MYSQL_ROOT_PASSWORD={secrets["DEMO_MYSQL_ROOT_PASSWORD"]}
176
186
 
177
187
  # 4. Manufacturing History (MSSQL)
188
+ DEMO_HISTORY_HOST=localhost
189
+ DEMO_HISTORY_PORT=1434
178
190
  DEMO_HISTORY_USER=history_admin
179
191
  DEMO_HISTORY_PASSWORD={secrets["DEMO_HISTORY_PASSWORD"]}
180
192
  DEMO_MSSQL_SA_PASSWORD={secrets["DEMO_MSSQL_SA_PASSWORD"]}
@@ -0,0 +1,24 @@
1
+ from __future__ import annotations
2
+
3
+ from nl2sql.common.errors import PipelineError
4
+
5
+
6
+ class NL2SQLError(Exception):
7
+ """Base exception for all NL2SQL errors."""
8
+ pass
9
+
10
+
11
+ class PipelineExecutionError(NL2SQLError):
12
+ """Raised when a pipeline step fails where a PipelineError cannot be returned.
13
+
14
+ Most of the pipeline reports failures by putting a ``PipelineError`` into
15
+ graph state as a value. LangGraph conditional-edge routers cannot do that --
16
+ they may only return routing decisions -- so they raise this instead. The
17
+ structured payload is kept on ``error`` because ``error_code``, ``severity``
18
+ and ``is_retryable`` drive downstream handling; ``str()`` is the underlying
19
+ message so the CLI error decorator prints something readable.
20
+ """
21
+
22
+ def __init__(self, error: PipelineError):
23
+ super().__init__(error.message)
24
+ self.error = error
@@ -125,7 +125,10 @@ class ConfigManager:
125
125
 
126
126
  try:
127
127
  content = target_path.read_text(encoding="utf-8")
128
- raw = yaml.safe_load(content) or []
128
+ # An empty file parses as None. Fall back to a mapping, not a
129
+ # list: the envelope is a mapping, and `or []` made an empty file
130
+ # fail with a misleading "should be a valid dictionary".
131
+ raw = yaml.safe_load(content) or {}
129
132
 
130
133
  file_config = SecretsFileConfig.model_validate(raw)
131
134
  return file_config.providers
@@ -0,0 +1,23 @@
1
+
2
+ from typing import List
3
+
4
+ from pydantic import BaseModel, Field, field_validator
5
+ from nl2sql.secrets.models import SecretProviderConfig
6
+
7
+ class SecretsFileConfig(BaseModel):
8
+ """File-level schema for secrets.yaml."""
9
+ version: int = Field(1, description="Schema version")
10
+ providers: List[SecretProviderConfig] = Field(default_factory=list)
11
+
12
+ @field_validator("providers", mode="before")
13
+ @classmethod
14
+ def _empty_providers_means_none_configured(cls, value):
15
+ """Treat ``providers:`` with nothing under it as no providers.
16
+
17
+ Secret providers are optional, so the default alone is not enough:
18
+ pydantic applies it only when the key is absent, and a user who
19
+ comments out every example leaves the key present with a null value.
20
+ YAML parses that as ``None``, which the annotation rejects. Coerce it
21
+ here so the missing key and the empty key behave the same.
22
+ """
23
+ return [] if value is None else value
@@ -7,6 +7,32 @@ from nl2sql.datasources.protocols import DatasourceAdapterProtocol
7
7
  from nl2sql.secrets import SecretManager
8
8
  from .models import DatasourceConfig, ConnectionConfig
9
9
 
10
+ # Resolved connection args hold plaintext secrets (see ``resolved_connection``),
11
+ # so anything that renders them -- an API payload, a `doctor` row, a pydantic
12
+ # ValidationError repr -- has to mask them by name first.
13
+ SECRET_ARG_HINTS = ("password", "secret", "token", "api_key")
14
+
15
+
16
+ def _is_secret_arg(key: str) -> bool:
17
+ return any(hint in key.lower() for hint in SECRET_ARG_HINTS)
18
+
19
+
20
+ def mask_connection_args(connection_args: Dict[str, Any]) -> Dict[str, Any]:
21
+ """Returns a copy of the connection args with secret values masked."""
22
+ return {
23
+ key: ("***" if _is_secret_arg(key) and value else value)
24
+ for key, value in (connection_args or {}).items()
25
+ }
26
+
27
+
28
+ def redact_connection_secrets(text: str, connection_args: Dict[str, Any]) -> str:
29
+ """Replaces every secret value from the connection args found in ``text``."""
30
+ for key, value in (connection_args or {}).items():
31
+ if _is_secret_arg(key) and isinstance(value, str) and value:
32
+ text = text.replace(value, "***")
33
+ return text
34
+
35
+
10
36
  class DatasourceRegistry:
11
37
  """Manages a collection of active DatasourceAdapters.
12
38
 
@@ -38,19 +64,24 @@ class DatasourceRegistry:
38
64
  def resolved_connection(self, unresolved_connection: ConnectionConfig) -> ConnectionConfig:
39
65
  """Resolves all secrets in a connection dictionary.
40
66
 
67
+ Values are returned as plain strings. ``ConnectionConfig`` declares only
68
+ ``type`` and allows extras, so there is no type information here to tell
69
+ a password apart from a host, a user or a port -- wrapping every
70
+ placeholder in ``SecretStr`` broke every non-password field. Each
71
+ adapter's own config model declares which fields are secret and pydantic
72
+ coerces the plain string into ``SecretStr`` for those, so masking is
73
+ preserved exactly where it is declared.
74
+
41
75
  Args:
42
76
  unresolved_connection (ConnectionConfig): The connection dictionary with potential secrets.
43
77
 
44
78
  Returns:
45
79
  ConnectionConfig: The connection dictionary with resolved secrets.
46
80
  """
47
- from pydantic import SecretStr
48
-
49
81
  resolved_connection = unresolved_connection.model_dump()
50
- for key, value in unresolved_connection.model_dump().items():
82
+ for key, value in list(resolved_connection.items()):
51
83
  if isinstance(value, str) and value.startswith("${") and value.endswith("}"):
52
- secret_val = self.find_and_resolve_secret(value)
53
- resolved_connection[key] = SecretStr(secret_val)
84
+ resolved_connection[key] = self.find_and_resolve_secret(value)
54
85
  return ConnectionConfig(**resolved_connection)
55
86
 
56
87
  def register_datasources(self, configs: List[DatasourceConfig]):
@@ -95,14 +126,22 @@ class DatasourceRegistry:
95
126
  if conn_type in self._available_adapters:
96
127
  adapter_cls = self._available_adapters[conn_type]
97
128
 
98
- adapter = adapter_cls(
99
- datasource_id=ds_id,
100
- datasource_engine_type=conn_type,
101
- connection_args=connection_args,
102
- statement_timeout_ms=config.options.get("statement_timeout_ms"),
103
- row_limit=config.options.get("row_limit"),
104
- max_bytes=config.options.get("max_bytes"),
105
- )
129
+ try:
130
+ adapter = adapter_cls(
131
+ datasource_id=ds_id,
132
+ datasource_engine_type=conn_type,
133
+ connection_args=connection_args,
134
+ statement_timeout_ms=config.options.get("statement_timeout_ms"),
135
+ row_limit=config.options.get("row_limit"),
136
+ max_bytes=config.options.get("max_bytes"),
137
+ )
138
+ except Exception as e:
139
+ # A pydantic ValidationError renders the whole input dict, which
140
+ # now holds the plaintext password. Re-raise without the cause so
141
+ # neither the message nor the traceback carries it.
142
+ raise ValueError(
143
+ redact_connection_secrets(str(e), connection_args)
144
+ ) from None
106
145
  with self._lock:
107
146
  self._adapters[ds_id] = adapter
108
147
  if hasattr(adapter, "capabilities"):
@@ -4,6 +4,7 @@ from langgraph.graph import END
4
4
  from langgraph.types import Send
5
5
 
6
6
  from nl2sql.common.errors import PipelineError, ErrorSeverity, ErrorCode
7
+ from nl2sql.common.exceptions import PipelineExecutionError
7
8
  from nl2sql.context import NL2SQLContext
8
9
  from nl2sql.pipeline.graph_utils import (
9
10
  StateAccessor,
@@ -58,11 +59,13 @@ def build_scan_layer_router(ctx: NL2SQLContext):
58
59
 
59
60
  target = resolve_subgraph(datasource_id, ctx)
60
61
  if not target:
61
- raise PipelineError(
62
- node="layer_router",
63
- message=f"No compatible subgraph found for datasource '{datasource_id}'.",
64
- severity=ErrorSeverity.ERROR,
65
- error_code=ErrorCode.INVALID_STATE,
62
+ raise PipelineExecutionError(
63
+ PipelineError(
64
+ node="layer_router",
65
+ message=f"No compatible subgraph found for datasource '{datasource_id}'.",
66
+ severity=ErrorSeverity.ERROR,
67
+ error_code=ErrorCode.INVALID_STATE,
68
+ )
66
69
  )
67
70
  payload = build_scan_payload(state, target, node_id)
68
71
  branches.append(Send(target, payload))
@@ -10,6 +10,7 @@ from typing import Callable, Dict, List, Optional
10
10
  from nl2sql.auth import UserContext
11
11
  from nl2sql.common.cancellation import CancellationToken
12
12
  from nl2sql.common.errors import PipelineError, ErrorSeverity, ErrorCode
13
+ from nl2sql.common.exceptions import PipelineExecutionError
13
14
  from nl2sql.common.settings import settings
14
15
  from nl2sql.context import NL2SQLContext
15
16
  from nl2sql.pipeline.graph import build_graph
@@ -135,6 +136,11 @@ def run_with_graph(
135
136
  ],
136
137
  "final_answer": "I apologize, but the request timed out. Please try again with a simpler query.",
137
138
  }
139
+ except PipelineExecutionError as e:
140
+ # Raised where a PipelineError cannot be returned as a value (conditional-edge
141
+ # routers). The payload is already structured, so surface it unchanged: the
142
+ # blanket catch below would relabel it UNKNOWN_ERROR and flip is_retryable.
143
+ return {"errors": [e.error]}
138
144
  except Exception as e:
139
145
  # Fallback for other runtime crashes
140
146
  return {
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: nl2sql-engine
3
- Version: 0.1.0
3
+ Version: 0.1.1
4
4
  Summary: Natural-language-to-SQL engine, CLI and database adapters
5
5
  Requires-Python: >=3.9
6
6
  Description-Content-Type: text/markdown
@@ -52,6 +52,7 @@ src/nl2sql/cli/commands/run.py
52
52
  src/nl2sql/cli/commands/setup.py
53
53
  src/nl2sql/cli/commands/visualize.py
54
54
  src/nl2sql/cli/common/decorators.py
55
+ src/nl2sql/cli/common/prompts.py
55
56
  src/nl2sql/cli/demo/__init__.py
56
57
  src/nl2sql/cli/demo/data.py
57
58
  src/nl2sql/cli/demo/defaults.py
@@ -1,53 +0,0 @@
1
- import importlib.util
2
- from typing import Dict, Tuple
3
- import pathlib
4
- from rich.markup import escape
5
- from rich.table import Table
6
- from rich.text import Text
7
- from nl2sql.cli.console import console, print_success, print_error
8
-
9
- def check_package(name: str) -> bool:
10
- """Checks if a python package is installed."""
11
- import_name = name.replace("-", "_")
12
- return importlib.util.find_spec(import_name) is not None
13
-
14
- def verify_connectivity(print_table: bool = True) -> bool:
15
- """
16
- Checks connectivity for all profiles in the default config.
17
- Returns True if all checks passed, False otherwise.
18
- """
19
- from nl2sql.common.settings import settings
20
- from nl2sql.datasources import load_profiles
21
- from nl2sql.diagnostics import check_connectivity as core_check
22
-
23
- try:
24
- profiles = load_profiles(pathlib.Path(settings.datasource_config_path))
25
-
26
- with console.status("[bold green]Verifying connectivity...[/bold green]"):
27
- results = core_check(list(profiles.values()))
28
-
29
- all_ok = True
30
-
31
- if print_table:
32
- conn_table = Table(show_header=True, header_style="bold cyan")
33
- conn_table.add_column("Datasource ID")
34
- conn_table.add_column("Status")
35
- conn_table.add_column("Details")
36
-
37
- for ds_id, (success, msg) in results.items():
38
- if not success:
39
- all_ok = False
40
-
41
- if print_table:
42
- status = "[green]OK[/green]" if success else "[red]Failed[/red]"
43
- details = msg if not success else ""
44
- conn_table.add_row(Text(str(ds_id)), status, Text(str(details)))
45
-
46
- if print_table:
47
- console.print(conn_table)
48
-
49
- return all_ok
50
-
51
- except Exception as e:
52
- console.print(f"[red]Connectivity check failed: {escape(str(e))}[/red]")
53
- return False
@@ -1,3 +0,0 @@
1
- class NL2SQLError(Exception):
2
- """Base exception for all NL2SQL errors."""
3
- pass
@@ -1,11 +0,0 @@
1
-
2
- from typing import List
3
-
4
- from pydantic import BaseModel, Field
5
- from nl2sql.secrets.models import SecretProviderConfig
6
-
7
- class SecretsFileConfig(BaseModel):
8
- """File-level schema for secrets.yaml."""
9
- version: int = Field(1, description="Schema version")
10
- providers: List[SecretProviderConfig]
11
-
File without changes
File without changes