sqlrite 0.1.17__tar.gz → 0.1.19__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.
- {sqlrite-0.1.17 → sqlrite-0.1.19}/Cargo.lock +7 -7
- {sqlrite-0.1.17 → sqlrite-0.1.19}/Cargo.toml +32 -5
- {sqlrite-0.1.17 → sqlrite-0.1.19}/PKG-INFO +1 -1
- {sqlrite-0.1.17 → sqlrite-0.1.19}/README.md +8 -6
- {sqlrite-0.1.17 → sqlrite-0.1.19}/desktop/package.json +1 -1
- {sqlrite-0.1.17 → sqlrite-0.1.19}/docs/embedding.md +17 -13
- {sqlrite-0.1.17 → sqlrite-0.1.19}/docs/phase-7-plan.md +1 -1
- {sqlrite-0.1.17 → sqlrite-0.1.19}/docs/roadmap.md +5 -1
- {sqlrite-0.1.17 → sqlrite-0.1.19}/pyproject.toml +1 -1
- {sqlrite-0.1.17 → sqlrite-0.1.19}/sdk/python/Cargo.toml +1 -1
- sqlrite-0.1.19/sqlrite-ask/Cargo.toml +63 -0
- sqlrite-0.1.19/sqlrite-ask/src/lib.rs +572 -0
- sqlrite-0.1.19/sqlrite-ask/src/prompt.rs +230 -0
- sqlrite-0.1.19/sqlrite-ask/src/provider/anthropic.rs +232 -0
- sqlrite-0.1.19/sqlrite-ask/src/provider/mock.rs +68 -0
- sqlrite-0.1.19/sqlrite-ask/src/provider/mod.rs +68 -0
- sqlrite-0.1.19/sqlrite-ask/tests/anthropic_http.rs +244 -0
- sqlrite-0.1.19/src/ask/mod.rs +121 -0
- sqlrite-0.1.19/src/ask/schema.rs +223 -0
- {sqlrite-0.1.17 → sqlrite-0.1.19}/src/lib.rs +9 -0
- {sqlrite-0.1.17 → sqlrite-0.1.19}/src/meta_command/mod.rs +160 -3
- {sqlrite-0.1.17 → sqlrite-0.1.19}/.github/workflows/ci.yml +0 -0
- {sqlrite-0.1.17 → sqlrite-0.1.19}/.github/workflows/release-pr.yml +0 -0
- {sqlrite-0.1.17 → sqlrite-0.1.19}/.github/workflows/release.yml +0 -0
- {sqlrite-0.1.17 → sqlrite-0.1.19}/.github/workflows/rust.yml +0 -0
- {sqlrite-0.1.17 → sqlrite-0.1.19}/.gitignore +0 -0
- {sqlrite-0.1.17 → sqlrite-0.1.19}/CODE_OF_CONDUCT.md +0 -0
- {sqlrite-0.1.17 → sqlrite-0.1.19}/LICENSE +0 -0
- {sqlrite-0.1.17 → sqlrite-0.1.19}/MAINTAINERS +0 -0
- {sqlrite-0.1.17 → sqlrite-0.1.19}/Makefile +0 -0
- {sqlrite-0.1.17 → sqlrite-0.1.19}/desktop/index.html +0 -0
- {sqlrite-0.1.17 → sqlrite-0.1.19}/desktop/package-lock.json +0 -0
- {sqlrite-0.1.17 → sqlrite-0.1.19}/desktop/src/App.svelte +0 -0
- {sqlrite-0.1.17 → sqlrite-0.1.19}/desktop/src/app.css +0 -0
- {sqlrite-0.1.17 → sqlrite-0.1.19}/desktop/src/main.ts +0 -0
- {sqlrite-0.1.17 → sqlrite-0.1.19}/desktop/src/vite-env.d.ts +0 -0
- {sqlrite-0.1.17 → sqlrite-0.1.19}/desktop/svelte.config.js +0 -0
- {sqlrite-0.1.17 → sqlrite-0.1.19}/desktop/tsconfig.json +0 -0
- {sqlrite-0.1.17 → sqlrite-0.1.19}/desktop/vite.config.ts +0 -0
- {sqlrite-0.1.17 → sqlrite-0.1.19}/docs/_index.md +0 -0
- {sqlrite-0.1.17 → sqlrite-0.1.19}/docs/architecture.md +0 -0
- {sqlrite-0.1.17 → sqlrite-0.1.19}/docs/design-decisions.md +0 -0
- {sqlrite-0.1.17 → sqlrite-0.1.19}/docs/desktop.md +0 -0
- {sqlrite-0.1.17 → sqlrite-0.1.19}/docs/file-format.md +0 -0
- {sqlrite-0.1.17 → sqlrite-0.1.19}/docs/getting-started.md +0 -0
- {sqlrite-0.1.17 → sqlrite-0.1.19}/docs/pager.md +0 -0
- {sqlrite-0.1.17 → sqlrite-0.1.19}/docs/release-plan.md +0 -0
- {sqlrite-0.1.17 → sqlrite-0.1.19}/docs/release-secrets.md +0 -0
- {sqlrite-0.1.17 → sqlrite-0.1.19}/docs/smoke-test.md +0 -0
- {sqlrite-0.1.17 → sqlrite-0.1.19}/docs/sql-engine.md +0 -0
- {sqlrite-0.1.17 → sqlrite-0.1.19}/docs/storage-model.md +0 -0
- {sqlrite-0.1.17 → sqlrite-0.1.19}/docs/supported-sql.md +0 -0
- {sqlrite-0.1.17 → sqlrite-0.1.19}/docs/usage.md +0 -0
- {sqlrite-0.1.17 → sqlrite-0.1.19}/examples/README.md +0 -0
- {sqlrite-0.1.17 → sqlrite-0.1.19}/examples/c/Makefile +0 -0
- {sqlrite-0.1.17 → sqlrite-0.1.19}/examples/c/hello.c +0 -0
- {sqlrite-0.1.17 → sqlrite-0.1.19}/examples/go/go.mod +0 -0
- {sqlrite-0.1.17 → sqlrite-0.1.19}/examples/go/hello.go +0 -0
- {sqlrite-0.1.17 → sqlrite-0.1.19}/examples/nodejs/hello.mjs +0 -0
- {sqlrite-0.1.17 → sqlrite-0.1.19}/examples/python/hello.py +0 -0
- {sqlrite-0.1.17 → sqlrite-0.1.19}/examples/rust/quickstart.rs +0 -0
- {sqlrite-0.1.17 → sqlrite-0.1.19}/examples/wasm/Makefile +0 -0
- {sqlrite-0.1.17 → sqlrite-0.1.19}/examples/wasm/index.html +0 -0
- {sqlrite-0.1.17 → sqlrite-0.1.19}/images/SQLRite - Desktop.png +0 -0
- {sqlrite-0.1.17 → sqlrite-0.1.19}/images/SQLRite Data Structures.png +0 -0
- {sqlrite-0.1.17 → sqlrite-0.1.19}/images/SQLRite Simple SQL Execution High Level Diagram.png +0 -0
- {sqlrite-0.1.17 → sqlrite-0.1.19}/images/SQLRite Simple SQL INSERT Execution High Level Diagram (Insert Row).png +0 -0
- {sqlrite-0.1.17 → sqlrite-0.1.19}/images/SQLRite Simple SQL INSERT Execution High Level Diagram.png +0 -0
- {sqlrite-0.1.17 → sqlrite-0.1.19}/images/SQLRite_logo.png +0 -0
- {sqlrite-0.1.17 → sqlrite-0.1.19}/images/architecture.png +0 -0
- {sqlrite-0.1.17 → sqlrite-0.1.19}/rust-toolchain.toml +0 -0
- {sqlrite-0.1.17 → sqlrite-0.1.19}/samples/AST.delete.example +0 -0
- {sqlrite-0.1.17 → sqlrite-0.1.19}/samples/AST.insert.exemple +0 -0
- {sqlrite-0.1.17 → sqlrite-0.1.19}/samples/AST.select.example +0 -0
- {sqlrite-0.1.17 → sqlrite-0.1.19}/samples/AST.update.example +0 -0
- {sqlrite-0.1.17 → sqlrite-0.1.19}/samples/CREATE TABLE sqlrite_schema.sql +0 -0
- {sqlrite-0.1.17 → sqlrite-0.1.19}/samples/CREATE_TABLE with duplicate.sql +0 -0
- {sqlrite-0.1.17 → sqlrite-0.1.19}/samples/CREATE_TABLE.sql +0 -0
- {sqlrite-0.1.17 → sqlrite-0.1.19}/samples/INSERT.sql +0 -0
- {sqlrite-0.1.17 → sqlrite-0.1.19}/scripts/bump-version.sh +0 -0
- {sqlrite-0.1.17 → sqlrite-0.1.19}/sdk/go/README.md +0 -0
- {sqlrite-0.1.17 → sqlrite-0.1.19}/sdk/go/conn.go +0 -0
- {sqlrite-0.1.17 → sqlrite-0.1.19}/sdk/go/go.mod +0 -0
- {sqlrite-0.1.17 → sqlrite-0.1.19}/sdk/go/rows.go +0 -0
- {sqlrite-0.1.17 → sqlrite-0.1.19}/sdk/go/sqlrite.go +0 -0
- {sqlrite-0.1.17 → sqlrite-0.1.19}/sdk/go/sqlrite_test.go +0 -0
- {sqlrite-0.1.17 → sqlrite-0.1.19}/sdk/go/stmt.go +0 -0
- {sqlrite-0.1.17 → sqlrite-0.1.19}/sdk/python/README.md +0 -0
- {sqlrite-0.1.17 → sqlrite-0.1.19}/sdk/python/src/lib.rs +0 -0
- {sqlrite-0.1.17 → sqlrite-0.1.19}/sdk/python/tests/test_sqlrite.py +0 -0
- {sqlrite-0.1.17 → sqlrite-0.1.19}/src/connection.rs +0 -0
- {sqlrite-0.1.17 → sqlrite-0.1.19}/src/error.rs +0 -0
- {sqlrite-0.1.17 → sqlrite-0.1.19}/src/main.rs +0 -0
- {sqlrite-0.1.17 → sqlrite-0.1.19}/src/repl/mod.rs +0 -0
- {sqlrite-0.1.17 → sqlrite-0.1.19}/src/sql/db/database.rs +0 -0
- {sqlrite-0.1.17 → sqlrite-0.1.19}/src/sql/db/mod.rs +0 -0
- {sqlrite-0.1.17 → sqlrite-0.1.19}/src/sql/db/secondary_index.rs +0 -0
- {sqlrite-0.1.17 → sqlrite-0.1.19}/src/sql/db/table.rs +0 -0
- {sqlrite-0.1.17 → sqlrite-0.1.19}/src/sql/executor.rs +0 -0
- {sqlrite-0.1.17 → sqlrite-0.1.19}/src/sql/hnsw.rs +0 -0
- {sqlrite-0.1.17 → sqlrite-0.1.19}/src/sql/mod.rs +0 -0
- {sqlrite-0.1.17 → sqlrite-0.1.19}/src/sql/pager/cell.rs +0 -0
- {sqlrite-0.1.17 → sqlrite-0.1.19}/src/sql/pager/file.rs +0 -0
- {sqlrite-0.1.17 → sqlrite-0.1.19}/src/sql/pager/header.rs +0 -0
- {sqlrite-0.1.17 → sqlrite-0.1.19}/src/sql/pager/hnsw_cell.rs +0 -0
- {sqlrite-0.1.17 → sqlrite-0.1.19}/src/sql/pager/index_cell.rs +0 -0
- {sqlrite-0.1.17 → sqlrite-0.1.19}/src/sql/pager/interior_page.rs +0 -0
- {sqlrite-0.1.17 → sqlrite-0.1.19}/src/sql/pager/mod.rs +0 -0
- {sqlrite-0.1.17 → sqlrite-0.1.19}/src/sql/pager/overflow.rs +0 -0
- {sqlrite-0.1.17 → sqlrite-0.1.19}/src/sql/pager/page.rs +0 -0
- {sqlrite-0.1.17 → sqlrite-0.1.19}/src/sql/pager/pager.rs +0 -0
- {sqlrite-0.1.17 → sqlrite-0.1.19}/src/sql/pager/table_page.rs +0 -0
- {sqlrite-0.1.17 → sqlrite-0.1.19}/src/sql/pager/varint.rs +0 -0
- {sqlrite-0.1.17 → sqlrite-0.1.19}/src/sql/pager/wal.rs +0 -0
- {sqlrite-0.1.17 → sqlrite-0.1.19}/src/sql/parser/create.rs +0 -0
- {sqlrite-0.1.17 → sqlrite-0.1.19}/src/sql/parser/insert.rs +0 -0
- {sqlrite-0.1.17 → sqlrite-0.1.19}/src/sql/parser/mod.rs +0 -0
- {sqlrite-0.1.17 → sqlrite-0.1.19}/src/sql/parser/select.rs +0 -0
- {sqlrite-0.1.17 → sqlrite-0.1.19}/src/sql/tokenizer.rs +0 -0
|
@@ -3804,11 +3804,10 @@ dependencies = [
|
|
|
3804
3804
|
|
|
3805
3805
|
[[package]]
|
|
3806
3806
|
name = "sqlrite-ask"
|
|
3807
|
-
version = "0.1.
|
|
3807
|
+
version = "0.1.19"
|
|
3808
3808
|
dependencies = [
|
|
3809
3809
|
"serde",
|
|
3810
3810
|
"serde_json",
|
|
3811
|
-
"sqlrite-engine",
|
|
3812
3811
|
"thiserror 2.0.18",
|
|
3813
3812
|
"tiny_http",
|
|
3814
3813
|
"ureq",
|
|
@@ -3816,7 +3815,7 @@ dependencies = [
|
|
|
3816
3815
|
|
|
3817
3816
|
[[package]]
|
|
3818
3817
|
name = "sqlrite-desktop"
|
|
3819
|
-
version = "0.1.
|
|
3818
|
+
version = "0.1.19"
|
|
3820
3819
|
dependencies = [
|
|
3821
3820
|
"serde",
|
|
3822
3821
|
"serde_json",
|
|
@@ -3828,7 +3827,7 @@ dependencies = [
|
|
|
3828
3827
|
|
|
3829
3828
|
[[package]]
|
|
3830
3829
|
name = "sqlrite-engine"
|
|
3831
|
-
version = "0.1.
|
|
3830
|
+
version = "0.1.19"
|
|
3832
3831
|
dependencies = [
|
|
3833
3832
|
"clap",
|
|
3834
3833
|
"env_logger",
|
|
@@ -3839,12 +3838,13 @@ dependencies = [
|
|
|
3839
3838
|
"rustyline-derive",
|
|
3840
3839
|
"serde_json",
|
|
3841
3840
|
"sqlparser",
|
|
3841
|
+
"sqlrite-ask",
|
|
3842
3842
|
"thiserror 2.0.18",
|
|
3843
3843
|
]
|
|
3844
3844
|
|
|
3845
3845
|
[[package]]
|
|
3846
3846
|
name = "sqlrite-ffi"
|
|
3847
|
-
version = "0.1.
|
|
3847
|
+
version = "0.1.19"
|
|
3848
3848
|
dependencies = [
|
|
3849
3849
|
"cbindgen",
|
|
3850
3850
|
"sqlrite-engine",
|
|
@@ -3852,7 +3852,7 @@ dependencies = [
|
|
|
3852
3852
|
|
|
3853
3853
|
[[package]]
|
|
3854
3854
|
name = "sqlrite-nodejs"
|
|
3855
|
-
version = "0.1.
|
|
3855
|
+
version = "0.1.19"
|
|
3856
3856
|
dependencies = [
|
|
3857
3857
|
"napi",
|
|
3858
3858
|
"napi-build",
|
|
@@ -3862,7 +3862,7 @@ dependencies = [
|
|
|
3862
3862
|
|
|
3863
3863
|
[[package]]
|
|
3864
3864
|
name = "sqlrite-python"
|
|
3865
|
-
version = "0.1.
|
|
3865
|
+
version = "0.1.19"
|
|
3866
3866
|
dependencies = [
|
|
3867
3867
|
"pyo3",
|
|
3868
3868
|
"sqlrite-engine",
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
# wasm32-unknown-unknown. `cargo build --workspace` on a native host
|
|
10
10
|
# would fail on a wasm-only crate; wasm-pack drives that build
|
|
11
11
|
# separately.
|
|
12
|
-
members = [".", "sdk/python"]
|
|
12
|
+
members = [".", "sqlrite-ask", "sdk/python"]
|
|
13
13
|
resolver = "3"
|
|
14
14
|
|
|
15
15
|
[package]
|
|
@@ -27,7 +27,7 @@ resolver = "3"
|
|
|
27
27
|
# `package =` key so the import name stays `sqlrite` internally:
|
|
28
28
|
# sqlrite = { package = "sqlrite-engine", path = "…" }
|
|
29
29
|
name = "sqlrite-engine"
|
|
30
|
-
version = "0.1.
|
|
30
|
+
version = "0.1.19"
|
|
31
31
|
authors = ["Joao Henrique Machado Silva <joaoh82@gmail.com>"]
|
|
32
32
|
edition = "2024"
|
|
33
33
|
rust-version = "1.85"
|
|
@@ -47,13 +47,14 @@ name = "sqlrite"
|
|
|
47
47
|
path = "src/lib.rs"
|
|
48
48
|
|
|
49
49
|
# Binary target — the interactive REPL. Needs the `cli` feature
|
|
50
|
-
# (
|
|
50
|
+
# (rustyline/clap/env_logger) AND the `ask` feature (sqlrite-ask
|
|
51
|
+
# integration for the `.ask` meta-command). Both are default-on; a
|
|
51
52
|
# `--no-default-features` build (e.g. for WASM or a minimal
|
|
52
53
|
# embedding) skips the bin entirely via `required-features`.
|
|
53
54
|
[[bin]]
|
|
54
55
|
name = "sqlrite"
|
|
55
56
|
path = "src/main.rs"
|
|
56
|
-
required-features = ["cli"]
|
|
57
|
+
required-features = ["cli", "ask"]
|
|
57
58
|
|
|
58
59
|
# Phase 5a quickstart — the canonical "how do I use this as a library?"
|
|
59
60
|
# walkthrough. Run with `cargo run --example quickstart`. Lives under
|
|
@@ -72,8 +73,21 @@ path = "examples/rust/quickstart.rs"
|
|
|
72
73
|
# `default-features = false` so rustyline, clap, env_logger, and
|
|
73
74
|
# fs2 don't try to compile against wasm32-unknown-unknown (none of
|
|
74
75
|
# them support that target).
|
|
75
|
-
default = ["cli", "file-locks"]
|
|
76
|
+
default = ["cli", "ask", "file-locks"]
|
|
76
77
|
cli = ["dep:rustyline", "dep:rustyline-derive", "dep:env_logger", "dep:clap"]
|
|
78
|
+
# Phase 7g.2: optional engine integration with the `sqlrite-ask`
|
|
79
|
+
# natural-language → SQL crate. Adds `sqlrite::ConnectionAskExt::ask`
|
|
80
|
+
# (and the schema-introspection helper that powers it) when enabled.
|
|
81
|
+
# The core LLM/HTTP machinery still lives in `sqlrite-ask` itself —
|
|
82
|
+
# this feature is just the thin engine-side glue (extension trait +
|
|
83
|
+
# schema dump). Exists as a feature so library-only embedders
|
|
84
|
+
# (Tauri without ask, the WASM SDK, lean SDK builds) don't pay the
|
|
85
|
+
# `sqlrite-ask` weight by default.
|
|
86
|
+
#
|
|
87
|
+
# The CLI binary requires both `cli` and `ask` (see required-features
|
|
88
|
+
# on the `[[bin]]` section) — `.ask` is part of the standard REPL
|
|
89
|
+
# surface as of Phase 7g.2.
|
|
90
|
+
ask = ["dep:sqlrite-ask"]
|
|
77
91
|
file-locks = ["dep:fs2"]
|
|
78
92
|
|
|
79
93
|
[dependencies]
|
|
@@ -104,3 +118,16 @@ clap = { version = "4.6", features = ["cargo"], optional = true }
|
|
|
104
118
|
# fs2 wraps POSIX flock / Windows LockFileEx — neither exists on
|
|
105
119
|
# wasm32-unknown-unknown.
|
|
106
120
|
fs2 = { version = "0.4", optional = true }
|
|
121
|
+
|
|
122
|
+
# Phase 7g.2: REPL `.ask` command. Optional + gated under the `cli`
|
|
123
|
+
# feature because library-only embedders shouldn't have to pull in
|
|
124
|
+
# the LLM stack (HTTP / TLS / extra serde derives) just to use the
|
|
125
|
+
# engine. WASM builds skip it via `default-features = false` per
|
|
126
|
+
# Q9's JS-callback shape — they do prompt construction in-page but
|
|
127
|
+
# never make the HTTP call themselves.
|
|
128
|
+
#
|
|
129
|
+
# `version = "0.1"` is required for `cargo publish` — the engine
|
|
130
|
+
# crate publishes to crates.io, and a path-only dep without a
|
|
131
|
+
# version field fails the manifest verification step. See PR #58
|
|
132
|
+
# retrospective in docs/roadmap.md.
|
|
133
|
+
sqlrite-ask = { version = "0.1", path = "sqlrite-ask", optional = true }
|
|
@@ -155,12 +155,13 @@ Expressions in `WHERE` and `UPDATE`'s `SET` RHS:
|
|
|
155
155
|
| `.open FILENAME` | working — opens an existing `.sqlrite` file or creates a fresh one; **auto-save is enabled from this point on** |
|
|
156
156
|
| `.save FILENAME` | working — explicit flush (rarely needed once `.open` is in play) |
|
|
157
157
|
| `.tables` | working |
|
|
158
|
+
| `.ask <QUESTION>` | working — natural-language → SQL via the configured LLM (Anthropic by default). Prints generated SQL + rationale, prompts `Run? [Y/n]`, runs through the same pipeline as a typed statement on confirm. Requires `SQLRITE_LLM_API_KEY` in the environment. *Phase 7g.2.* |
|
|
158
159
|
| `.read FILENAME` | later |
|
|
159
160
|
| `.ast QUERY` | later |
|
|
160
161
|
|
|
161
162
|
#### Natural-language → SQL (`sqlrite-ask`)
|
|
162
163
|
|
|
163
|
-
*Phase 7g.1.* The companion crate [`sqlrite-ask`](sqlrite-ask/)
|
|
164
|
+
*Phase 7g.1 / 7g.2.* The companion crate [`sqlrite-ask`](sqlrite-ask/) — pure-Rust over `&str` schemas + questions — provides the LLM-talking machinery. The engine integrates it via the `ask` feature (default-on), exposing `Connection::ask` for ergonomic library use:
|
|
164
165
|
|
|
165
166
|
```toml
|
|
166
167
|
[dependencies]
|
|
@@ -169,8 +170,8 @@ sqlrite-ask = "0.1"
|
|
|
169
170
|
```
|
|
170
171
|
|
|
171
172
|
```rust
|
|
172
|
-
use sqlrite::Connection;
|
|
173
|
-
use sqlrite_ask::
|
|
173
|
+
use sqlrite::{Connection, ConnectionAskExt};
|
|
174
|
+
use sqlrite_ask::AskConfig;
|
|
174
175
|
|
|
175
176
|
let conn = Connection::open("foo.sqlrite")?;
|
|
176
177
|
let cfg = AskConfig::from_env()?; // SQLRITE_LLM_API_KEY etc.
|
|
@@ -182,7 +183,7 @@ println!("Why: {}", resp.explanation);
|
|
|
182
183
|
|
|
183
184
|
**Defaults:** `claude-sonnet-4-6`, `max_tokens: 1024`, schema dump cached for 5 minutes via Anthropic prompt caching (configurable to 1h or off via `AskConfig::cache_ttl`). Bring your own API key — set `SQLRITE_LLM_API_KEY` or pass it on `AskConfig`.
|
|
184
185
|
|
|
185
|
-
|
|
186
|
+
In the REPL: `.ask <question>`. From an open `Connection` (this section). Per-product wrappers — desktop "Ask" button, `conn.ask()` in the Python / Node / Go SDKs, MCP `ask` tool, WASM with a JS-callback shape so the API key never enters the browser — ship in **7g.3-7g.8** as follow-up sub-phases. See [`docs/phase-7-plan.md`](docs/phase-7-plan.md) §7g for the full surface plan.
|
|
186
187
|
|
|
187
188
|
### Roadmap
|
|
188
189
|
|
|
@@ -268,8 +269,9 @@ Lockstep versioning — one dispatch bumps every product to the same `vX.Y.Z`. T
|
|
|
268
269
|
- [x] **7c — Bounded-heap top-k optimization** *(v0.1.12)*
|
|
269
270
|
- [x] **7d — HNSW ANN index** *(v0.1.13–15)*: `CREATE INDEX … USING hnsw (col)`; recall@10 ≥ 0.95 at default `M=16, ef_construction=200, ef_search=50`; persisted as a `KIND_HNSW` cell tree
|
|
270
271
|
- [x] **7e — JSON column type + path queries** *(v0.1.16)*: `JSON` / `JSONB` columns stored as canonical text; `json_extract` / `json_type` / `json_array_length` / `json_object_keys`; `$.key`, `[N]`, chained JSONPath subset
|
|
271
|
-
- [x] **7g.1 — `sqlrite-ask` crate** *(
|
|
272
|
-
- [
|
|
272
|
+
- [x] **7g.1 — `sqlrite-ask` crate** *(v0.1.18)*: foundational natural-language → SQL via the [Anthropic API](https://docs.anthropic.com/) (Sonnet 4.6 by default), prompt-cached schema dump, sync `ureq` HTTP.
|
|
273
|
+
- [x] **7g.2 — REPL `.ask` + dep-direction flip** *(this wave)*: `.ask <question>` meta-command with `Run? [Y/n]` confirmation. The wiring required dropping the engine dep from `sqlrite-ask` (cargo cycle) — `sqlrite-ask` is now pure over `&str` schemas; the `Connection`/`Database` integration moved to the engine's new `ask` feature. Public surface for callers: `use sqlrite::{Connection, ConnectionAskExt}`.
|
|
274
|
+
- [ ] **7g.3-7g.8** — per-product `ask()` adapters: desktop "Ask" button, Python/Node/Go/WASM SDKs, MCP `ask` tool
|
|
273
275
|
- [ ] **7h** — MCP server adapter (`sqlrite-mcp` binary)
|
|
274
276
|
- [ ] *(deferred to Phase 8)* Full-text search with BM25 + hybrid retrieval
|
|
275
277
|
|
|
@@ -71,19 +71,21 @@ See [Phase 4f notes in roadmap.md](roadmap.md) for the snapshot semantics and th
|
|
|
71
71
|
- **Parameter binding.** `stmt.query(&[&"alice"])` is the intended shape but the current implementation takes no arguments — use string interpolation for now. Parameter binding lands with the cursor refactor.
|
|
72
72
|
- **Cursor abstraction.** The Pager still eagerly loads every row at open time; `Rows` today wraps an in-memory `Vec`. Phase 5a's follow-up refactor streams rows through the B-Tree on demand — same public API, much lower memory for big SELECTs.
|
|
73
73
|
|
|
74
|
-
### Natural-language → SQL
|
|
74
|
+
### Natural-language → SQL — `sqlrite::ask` + `sqlrite-ask`
|
|
75
75
|
|
|
76
|
-
The companion crate [`sqlrite-ask`](../sqlrite-ask/)
|
|
76
|
+
*Phases 7g.1 + 7g.2.* The companion crate [`sqlrite-ask`](../sqlrite-ask/) provides the LLM-talking machinery (provider adapters, prompt construction, response parsing) over a deliberately small surface — `&str` schema in, generated SQL out. The engine wraps it under a new `ask` feature (default-on) so library users get the ergonomic `Connection::ask` form without composing the schema dump themselves.
|
|
77
77
|
|
|
78
78
|
```toml
|
|
79
79
|
[dependencies]
|
|
80
|
+
# `ask` is a default feature on sqlrite-engine; opt out with
|
|
81
|
+
# default-features = false if you don't want the LLM stack pulled in.
|
|
80
82
|
sqlrite-engine = "0.1"
|
|
81
83
|
sqlrite-ask = "0.1"
|
|
82
84
|
```
|
|
83
85
|
|
|
84
86
|
```rust
|
|
85
|
-
use sqlrite::Connection;
|
|
86
|
-
use sqlrite_ask::{AskConfig, AskResponse
|
|
87
|
+
use sqlrite::{Connection, ConnectionAskExt};
|
|
88
|
+
use sqlrite_ask::{AskConfig, AskResponse};
|
|
87
89
|
|
|
88
90
|
let conn = Connection::open("foo.sqlrite")?;
|
|
89
91
|
let cfg = AskConfig::from_env()?; // reads SQLRITE_LLM_API_KEY etc.
|
|
@@ -105,18 +107,20 @@ let mut conn = conn; // need &mut for execute
|
|
|
105
107
|
let _ = conn.execute(&resp.sql)?;
|
|
106
108
|
```
|
|
107
109
|
|
|
108
|
-
**
|
|
110
|
+
**Where what lives:**
|
|
111
|
+
|
|
112
|
+
| Crate | Provides |
|
|
113
|
+
|---|---|
|
|
114
|
+
| `sqlrite-engine` (with `ask` feature) | `sqlrite::ConnectionAskExt`, `sqlrite::ask::ask` / `ask_with_database` / `ask_with_provider` / `ask_with_database_and_provider`, `sqlrite::ask::schema::dump_schema_for_connection` / `_for_database`. Pure engine-side glue: dump schema → call into `sqlrite-ask`. |
|
|
115
|
+
| `sqlrite-ask` | `ask_with_schema` / `ask_with_schema_and_provider`, `AskConfig`, `AskResponse`, `AskError`, `Provider` trait + `AnthropicProvider`. Pure `&str` inputs, no engine dep — keeps the LLM stack independently testable + plugable. |
|
|
116
|
+
|
|
117
|
+
**Provider:** Anthropic only in 7g.1; the `Provider` trait lets OpenAI / Ollama slot in without touching consumers. `AnthropicProvider` does sync `ureq` POSTs to `/v1/messages`. **Defaults:** `claude-sonnet-4-6`, `max_tokens: 1024`, 5-minute prompt-cache TTL on the schema dump (configurable via `AskConfig::cache_ttl` / `SQLRITE_LLM_CACHE_TTL`).
|
|
109
118
|
|
|
110
|
-
- `
|
|
111
|
-
- `Connection::ask(question, config)` via the `ConnectionAskExt` trait — same flow, method syntax.
|
|
112
|
-
- `AskConfig::from_env()` — reads `SQLRITE_LLM_PROVIDER` / `_API_KEY` / `_MODEL` / `_MAX_TOKENS` / `_CACHE_TTL` with sensible defaults.
|
|
113
|
-
- `AnthropicProvider` — sync `ureq` POST to `https://api.anthropic.com/v1/messages`. The crate is provider-pluggable (a `Provider` trait + `Request` / `Response` types), with OpenAI and Ollama follow-ups planned for later 7g sub-phases.
|
|
114
|
-
- Schema-aware prompt construction — walks `Database.tables` deterministically (alphabetical) and emits a `<schema>...</schema>` block with `cache_control: ephemeral`, so the schema dump is served from Anthropic's prompt cache after the first call.
|
|
115
|
-
- Output parser tolerant to fenced JSON (`` ```json … ``` ``) or JSON-with-leading-prose, in addition to strict JSON.
|
|
119
|
+
**Why the split** (Phase 7g.2 retro): the REPL binary needed to import the LLM crate to wire up `.ask`, but `sqlrite-ask` 0.1.18 imported `sqlrite-engine` for the `Connection` integration. That's a cargo cycle (`engine[bin] → sqlrite-ask → engine[lib]`) — even with `optional = true`, the static cycle detector rejects the graph. Flipping the dep direction broke it: `sqlrite-ask` is pure now, the engine carries the integration weight behind a feature flag. See `docs/roadmap.md` for the full retrospective.
|
|
116
120
|
|
|
117
|
-
**
|
|
121
|
+
**REPL surface** *(7g.2)*: type `.ask <question>` at the prompt. Prints generated SQL + rationale, asks `Run? [Y/n]`, executes through the same `process_command` pipeline as a typed statement on confirm. Requires `SQLRITE_LLM_API_KEY`.
|
|
118
122
|
|
|
119
|
-
**Per-product wrappers ship in 7g.
|
|
123
|
+
**Per-product wrappers ship in 7g.3-7g.8** — desktop "Ask" button, Python/Node/Go SDKs `conn.ask()`, WASM SDK with a JS-callback shape (so the API key stays out of the browser tab), and the MCP `ask` tool.
|
|
120
124
|
|
|
121
125
|
## The C FFI (Phase 5b)
|
|
122
126
|
|
|
@@ -250,7 +250,7 @@ let rows = conn.execute(&resp.sql)?;
|
|
|
250
250
|
**Layered design.** The work splits into one library layer + several thin adapters:
|
|
251
251
|
|
|
252
252
|
- **✅ 7g.1 — `sqlrite-ask` crate (foundational, ~750 LOC code + tests).** New separate crate (not feature-gated on the engine) so the engine stays pure-SQL with no HTTP / async deps. Owns: provider adapters (Anthropic in 7g.1; OpenAI / Ollama follow-ups), prompt construction, schema introspection helper that walks `Database.tables` directly (typed walk — cheaper + more robust than reflecting through `sqlrite_master`), the `AskResponse` type, configuration loading from env (`SQLRITE_LLM_PROVIDER` / `_API_KEY` / `_MODEL` / `_MAX_TOKENS` / `_CACHE_TTL`) or a passed config struct. Depends on `sqlrite-engine` for the schema introspection. Public API: `ask()` free function, `ConnectionAskExt::ask` trait extension on `sqlrite::Connection`, `AskConfig::from_env()`, `AskResponse { sql, explanation, usage }`. Default model `claude-sonnet-4-6` per the cost-quality NL→SQL sweet spot. Sync `ureq` HTTP (rejected reqwest::blocking — pulls tokio in even on the blocking path); JSON request/response shapes hand-rolled in serde_json (~120 LOC) — there is no official Anthropic Rust SDK, and rolling our own matches Q5's "build it yourself" theme. Schema dump goes inside a `<schema>...</schema>` block with `cache_control: ephemeral` so repeat asks against the same DB hit Anthropic's prompt cache (5-min TTL default; 1-hour TTL via `CacheTtl::OneHour`). Output parsing is tolerant — strict JSON, fenced JSON, or JSON-with-leading-prose all parse — because real LLM output drifts even with strict prompts. 30 tests pass (26 unit + 4 integration via `tiny_http` localhost mock).
|
|
253
|
-
-
|
|
253
|
+
- **✅ 7g.2 — REPL `.ask` + structural refactor.** New `MetaCommand::Ask(String)` variant + `handle_ask` that calls `sqlrite::ask::ask_with_database`, prints the generated SQL + rationale, prompts `Run? [Y/n] ` via rustyline (Ctrl-C / EOF map to skip — paranoid default for LLM-generated SQL), and pipes through `process_command` if confirmed. The thin REPL part itself is ~120 LOC. **Required a bigger structural fix that 7g.1 didn't anticipate:** wiring the binary to call into `sqlrite-ask` created a cargo cycle (`sqlrite-engine[bin] → sqlrite-ask → sqlrite-engine[lib]`) that even `optional = true` doesn't break — cargo's static cycle detection includes all potential edges. Resolution: flipped the dep direction. `sqlrite-ask` is now pure (no engine dep, canonical API takes a `&str` schema dump + `&str` question). Schema introspection + the `Connection`/`Database` integration (`ConnectionAskExt`, `ask`, `ask_with_database`, `ask_with_provider`, `ask_with_database_and_provider`) moved into `sqlrite-engine` itself under a new `ask` feature (default-on for the CLI binary, off for `--no-default-features` / WASM). Public API for end users is unchanged in spirit: `use sqlrite::{Connection, ConnectionAskExt}` instead of `use sqlrite_ask::ConnectionAskExt`. Net effect — `sqlrite-ask` shrunk + got easier to test in isolation; the engine carries the integration weight, scoped behind a feature flag so SDK / WASM / Tauri builds opt in. 30+ tests pass on both sides (sqlrite-ask: 20 unit + 4 integration; engine ask module: 6 schema + 3 .ask parser).
|
|
254
254
|
- **7g.3 — Desktop UI (~150 LOC).** New "Ask" button + prompt input + inline SQL preview in the editor. Calls into `sqlrite-ask` from a Tauri command; the command lives in `desktop/src-tauri/`. Schema introspection runs server-side; HTTP call also server-side (so the API key stays in the app process, not the webview).
|
|
255
255
|
- **7g.4 — Python SDK (~80 LOC).** PyO3 wrapper around `sqlrite-ask`. `Connection.ask(question)` returns a Python object with `.sql` and `.explanation`. `Connection.ask_run(question)` is the convenience that calls `execute` after.
|
|
256
256
|
- **7g.5 — Node.js SDK (~80 LOC).** Same shape via napi-rs. `db.ask(question)` / `db.askRun(question)`.
|
|
@@ -476,11 +476,15 @@ Approved sub-phases (Q1–Q10 resolved):
|
|
|
476
476
|
- **✅ 7d — HNSW ANN index** — three PRs: 7d.1 (algorithm w/ recall@10 ≥ 0.95), 7d.2 (SQL integration + query optimizer), 7d.3 (persistence + DELETE/UPDATE rebuild). `CREATE INDEX … USING hnsw (col)`; fixed defaults `M=16, ef_construction=200, ef_search=50` (Q2). New `KIND_HNSW` cell tag.
|
|
477
477
|
- **✅ 7e — JSON column type + path queries** — `JSON` data type stored as canonical text (validated via `serde_json::from_str` at INSERT/UPDATE time; SQLite-JSON1-style — Q3 scope correction since bincode was removed in Phase 3c). Functions: `json_extract` / `json_type` / `json_array_length` / `json_object_keys`. Path subset supports `$`, `.key`, `[N]`, chained. `json_object_keys` returns a JSON-array text rather than a table-valued result (no set-returning functions in the executor yet).
|
|
478
478
|
- **7f — ~~Full-text search with BM25~~** — **deferred to Phase 8** (Q1).
|
|
479
|
-
- **7g — `ask()` API across the product surface** — natural-language → SQL via Anthropic API (Q4), Anthropic-first then OpenAI + Ollama follow-ups. Foundational **✅ 7g.1** introduces a new `sqlrite-ask` crate (Q10 — separate crate, not a feature flag) — `
|
|
479
|
+
- **7g — `ask()` API across the product surface** — natural-language → SQL via Anthropic API (Q4), Anthropic-first then OpenAI + Ollama follow-ups. Foundational **✅ 7g.1** introduces a new `sqlrite-ask` crate (Q10 — separate crate, not a feature flag) — `ask_with_schema()` over `&str` inputs (Phase 7g.2 made it pure — see retrospective below), sync `ureq` POST to `/v1/messages`, schema-aware prompt with prompt-caching on the schema dump (Sonnet 4.6 default; configurable). **✅ 7g.2** wires the REPL's `.ask` meta-command (`MetaCommand::Ask(String)` + confirm-and-run UX) and adds the `sqlrite::ask` module on the engine side (gated under a new `ask` feature) carrying `ConnectionAskExt` + the schema introspection helper. Per-product adapters in 7g.3-7g.8 cover desktop, Python, Node.js, Go, WASM (JS-callback shape per Q9), and the MCP `ask` tool — and fold in the SDK README catch-up for VECTOR / JSON / HNSW capabilities along the way.
|
|
480
480
|
- **7h — MCP server adapter** — new `sqlrite-mcp` binary, hand-rolled JSON-RPC + tool framework (Q5).
|
|
481
481
|
|
|
482
482
|
Total scope budget: ~3-4 kLOC of new Rust across the wave. Each sub-phase ships as its own PR + release wave through the Phase 6 pipeline. The Phase 7 wave will likely close out **v0.2.0** (first minor bump after the 0.1.x Phase 6 cycle). Two new product lines added to lockstep versioning: `sqlrite-ask` and `sqlrite-mcp`.
|
|
483
483
|
|
|
484
|
+
> **v0.1.17 partial-publish retrospective** *(2026-04-29)* — first wave to ship `sqlrite-ask` as a brand-new product line. 23/25 jobs succeeded — `sqlrite-engine 0.1.17` landed on crates.io alongside Python / Node / Go / WASM / FFI / Desktop, and the umbrella `v0.1.17` tag exists. Two jobs failed: `publish-ask` and the `finalize` step that depends on it. Root cause: `cargo publish` rejects path-deps that don't carry a `version` requirement, with `error: dependency 'sqlrite-engine' does not specify a version`. We hit it because `sqlrite-ask` is the **first crate-besides-the-engine to actually publish to crates.io** — `sqlrite-ffi` only ships GitHub Release tarballs, so it never tripped the same check. Fixed in PR #58 by adding `version = "0.1"` (caret-compatible across 0.1.x — no per-release update) to the path-dep declaration. Verified locally with `cargo publish -p sqlrite-ask --dry-run --allow-dirty`. **`sqlrite-ask 0.1.17` will not exist on crates.io** per the never-reuse-a-version policy; the next canary cuts `v0.1.18` and ships `sqlrite-ask` for the first time there. Tags `sqlrite-ask-v0.1.17` and `v0.1.17` stay on `main` per the never-reuse-a-tag policy.
|
|
485
|
+
|
|
486
|
+
> **v0.1.19 dep-direction flip retrospective** *(2026-04-30)* — Phase 7g.2 wired the REPL's `.ask` meta-command, which required the engine binary to call into `sqlrite-ask`. That created a cargo cycle: `sqlrite-engine[bin] → sqlrite-ask → sqlrite-engine[lib]` (because `sqlrite-ask` 0.1.18 imported `sqlrite::Connection` for `ConnectionAskExt`). Cargo's static cycle detection counts every edge in the graph regardless of features, so `optional = true` didn't help — the cycle is rejected even when nobody actually exercises both directions at once. The fix flipped the dep direction structurally: `sqlrite-ask` 0.1.19 dropped `sqlrite-engine` entirely and became pure over `&str` schemas (canonical API: `ask_with_schema(schema_dump, question, &cfg)`). The engine integration (`schema::dump_schema_for_database`, `ConnectionAskExt`, `ask`, `ask_with_database`) moved into a new `sqlrite::ask` module gated by a fresh `ask` feature on `sqlrite-engine`. Default-on for the CLI binary; off for the WASM SDK and any `default-features = false` lib embedding. **Breaking change for `sqlrite-ask` 0.1.18 callers:** `use sqlrite_ask::ConnectionAskExt` becomes `use sqlrite::ConnectionAskExt` (after enabling the engine's `ask` feature). API method signature unchanged. The 0.1.18 crate had been live ~30 minutes with no known adopters at the time of the flip. Lesson: when a "thin per-product wrapper" sub-phase introduces a new edge in the dep graph, sketch out the full graph BEFORE writing code — would have caught the cycle in design rather than mid-implementation.
|
|
487
|
+
|
|
484
488
|
## Phase 8 — Full-text search + hybrid retrieval *(deferred from Phase 7 per Q1)*
|
|
485
489
|
|
|
486
490
|
Adds the FTS5-style inverted-index machinery that Phase 7 deliberately skipped, plus a small hybrid-ranking convenience function (`bm25_score(...)` × `vec_distance_cosine(...)`) so RAG callers can do BM25 + vector search in a single query. Why deferred: ~600-800 LOC of its own, orthogonal to the AI-era theme, and Phase 7 was already large. Why we'll come back to it: hybrid search (lexical + semantic) is the modern standard for RAG retrieval — vector-only retrieval misses keyword-grounded queries. Will likely close out v0.3.0.
|
|
@@ -4,7 +4,7 @@ build-backend = "maturin"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "sqlrite"
|
|
7
|
-
version = "0.1.
|
|
7
|
+
version = "0.1.19"
|
|
8
8
|
description = "Python bindings for SQLRite — a small, embeddable SQLite clone written in Rust."
|
|
9
9
|
authors = [{ name = "Joao Henrique Machado Silva", email = "joaoh82@gmail.com" }]
|
|
10
10
|
license = { text = "MIT" }
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
[package]
|
|
2
|
+
# Phase 7g.1 — natural-language → SQL via an LLM provider.
|
|
3
|
+
#
|
|
4
|
+
# This crate is intentionally kept separate from `sqlrite-engine` so
|
|
5
|
+
# the engine stays pure-SQL with no HTTP / TLS / async dependencies.
|
|
6
|
+
# Anyone embedding SQLRite who doesn't need `ask()` (the WASM SDK,
|
|
7
|
+
# read-only build-time tooling, lean embeddings) can ignore this
|
|
8
|
+
# crate entirely.
|
|
9
|
+
#
|
|
10
|
+
# Published to crates.io as `sqlrite-ask`. Joins the lockstep release
|
|
11
|
+
# wave (`sqlrite-ask-vX.Y.Z` tag) — see `docs/release-plan.md`.
|
|
12
|
+
name = "sqlrite-ask"
|
|
13
|
+
version = "0.1.19"
|
|
14
|
+
authors = ["Joao Henrique Machado Silva <joaoh82@gmail.com>"]
|
|
15
|
+
edition = "2024"
|
|
16
|
+
rust-version = "1.85"
|
|
17
|
+
description = "Natural-language → SQL adapter for sqlrite-engine. Anthropic-first; OpenAI / Ollama follow-ups."
|
|
18
|
+
repository = "https://github.com/joaoh82/rust_sqlite"
|
|
19
|
+
license = "MIT"
|
|
20
|
+
|
|
21
|
+
[lib]
|
|
22
|
+
name = "sqlrite_ask"
|
|
23
|
+
path = "src/lib.rs"
|
|
24
|
+
|
|
25
|
+
[dependencies]
|
|
26
|
+
# **No engine dep as of v0.1.19 (Phase 7g.2 structural fix).**
|
|
27
|
+
# `sqlrite-ask` is now pure: takes a `&str` schema dump + a `&str`
|
|
28
|
+
# question, returns generated SQL. The `Connection` / `Database`
|
|
29
|
+
# integration moved to the engine itself, gated behind the engine's
|
|
30
|
+
# new `ask` feature. Why: cargo's static cycle detection rejected
|
|
31
|
+
# `sqlrite-engine[bin] → sqlrite-ask → sqlrite-engine[lib]` even
|
|
32
|
+
# with `optional = true` on the engine side. Pure crate breaks the
|
|
33
|
+
# cycle structurally.
|
|
34
|
+
#
|
|
35
|
+
# Migration for v0.1.18 callers: `use sqlrite_ask::ConnectionAskExt`
|
|
36
|
+
# becomes `use sqlrite::ConnectionAskExt` (after enabling the
|
|
37
|
+
# engine's `ask` feature). API signature unchanged. See PR #60
|
|
38
|
+
# retrospective in `docs/roadmap.md`.
|
|
39
|
+
|
|
40
|
+
# JSON request/response shapes for the Anthropic Messages API.
|
|
41
|
+
# Could be hand-rolled but the request body has nested arrays of
|
|
42
|
+
# tagged-enum content blocks — serde derives are worth the dep.
|
|
43
|
+
serde = { version = "1", features = ["derive"] }
|
|
44
|
+
serde_json = "1"
|
|
45
|
+
|
|
46
|
+
# Sync HTTPS client. `ureq` 2.x is pure-Rust + rustls — no system
|
|
47
|
+
# OpenSSL, no tokio, no async runtime. Per `ask()` call we make
|
|
48
|
+
# exactly one POST to api.anthropic.com, so the sync surface is a
|
|
49
|
+
# perfect fit. Rolling our own JSON types over ureq is ~120 LOC
|
|
50
|
+
# vs. ~400 LOC + tokio + reqwest::blocking via an SDK.
|
|
51
|
+
ureq = { version = "2", features = ["json", "tls"] }
|
|
52
|
+
|
|
53
|
+
# Typed errors. (Same crate the engine uses, so consumers that
|
|
54
|
+
# enable the engine's `ask` feature can layer their own thiserror
|
|
55
|
+
# wrapper without version skew.)
|
|
56
|
+
thiserror = "2"
|
|
57
|
+
|
|
58
|
+
[dev-dependencies]
|
|
59
|
+
# Throwaway tiny localhost HTTP server for the integration test
|
|
60
|
+
# that exercises the real ureq path. Avoids hitting api.anthropic.com
|
|
61
|
+
# from CI (no network egress + no API key in test runners). Stays
|
|
62
|
+
# in `dev-dependencies` so it doesn't ship to consumers.
|
|
63
|
+
tiny_http = "0.12"
|