agent_block_core/bridge/sql.rs
1//! `std.sql` thin adapter.
2//!
3//! Bridge implementation lives in the `mlua-batteries-sqlite` crate
4//! (`mlua_batteries_sqlite::sql`), which since 0.5 is where `std.sql` and
5//! `std.kv` moved out of `mlua-batteries` itself. This module only resolves
6//! the host's environment-driven SQL configuration into a
7//! [`mlua_batteries_sqlite::sql::SqlConfig`] before delegating to
8//! [`mlua_batteries_sqlite::sql::register_with`], then layers the agent-block
9//! Lua tool helpers (`sql_tools.lua`) on top.
10//!
11//! What the batteries take is the connection the host opened
12//! ([`crate::host::HostContext::sql_conn`]) — shared as `Arc<Mutex<_>>` with
13//! its `InterruptHandle` beside it. Opening the database, the busy timeout
14//! and `journal_mode` are still the host's, applied before the VM exists (see
15//! `host.rs`), and the ENV → config mapping is in `bridge/config.rs`.
16//!
17//! The VM thread does not wait on SQLite here either: a statement goes to
18//! `tokio::task::spawn_blocking` and the mutex is taken *inside* that closure,
19//! so the Lua VM yields for the whole round trip and no guard is held across
20//! an `.await`. A cancelled `std.task` scope or an expired query timeout
21//! interrupts the statement through the handle. (`std.ts` and the kernel
22//! store reach the same end by the other route — a connection thread of their
23//! own; see `bridge/ts.rs`.)
24
25use mlua::prelude::*;
26use mlua_batteries_sqlite::sql::SqlConfig;
27
28use crate::host::HostContext;
29
30pub fn register(lua: &Lua, ctx: &HostContext) -> LuaResult<()> {
31 let cfg = SqlConfig {
32 query_timeout: super::config::sql_query_timeout(),
33 };
34 mlua_batteries_sqlite::sql::register_with(
35 lua,
36 ctx.sql_conn.conn.clone(),
37 ctx.sql_conn.interrupt.clone(),
38 cfg,
39 )?;
40
41 // Load std.sql.register_tools (LLM-facing helper; requires `tool` global).
42 lua.load(include_str!("sql_tools.lua"))
43 .set_name("std.sql.register_tools")
44 .exec()?;
45
46 Ok(())
47}