Skip to main content

agent_block_core/bridge/
mod.rs

1//! Lua Stdlib Bridge — injects all `*.*` global APIs into the Lua VM.
2//!
3//! Each submodule registers one namespace:
4//!
5//! | Module | Lua namespace | Purpose |
6//! |--------|--------------|---------|
7//! | `mesh` | `mesh.*`     | Agent-to-agent mesh communication |
8//! | `mcp`  | `mcp.*`      | MCP server management |
9//! | `sh`   | `sh.*`       | Shell command execution |
10//! | `tool` | `tool.*`     | Tool registry (define and call tools from Lua) |
11//! | `http` | `http.*`     | Async HTTP client |
12//! | `log`  | `log.*`, `env.*` | Logging and environment access |
13//! | `ts`   | `std.ts.*`   | SQLite-backed time-series primitive (in-tree) |
14//! | `knl`  | `knl.*`      | Kernel syscall layer (session / append-only history / budget) |
15
16pub mod bus;
17pub mod config;
18pub mod fs;
19pub mod http;
20pub mod knl;
21#[cfg(feature = "sqlite")]
22pub mod kv;
23pub mod llm;
24pub mod log;
25pub mod mcp;
26#[cfg(feature = "mesh")]
27pub mod mesh;
28pub mod sh;
29#[cfg(feature = "sqlite")]
30pub mod sql;
31pub mod task;
32pub mod tool;
33#[cfg(feature = "sqlite")]
34pub mod ts;
35
36use mlua::prelude::*;
37
38use crate::host::HostContext;
39
40// Re-export `obs` from agent-block-types so that existing
41// `crate::bridge::obs::*` paths inside core keep compiling without
42// duplicating the module body.
43pub use agent_block_types::obs;
44
45// Re-export the Lua ↔ JSON converters from agent-block-mcp.  They live in
46// the MCP crate because the rmcp handler depends on them; core only needs
47// to forward `lua_to_json` / `json_to_lua` for the in-process bridges
48// (llm / mesh / mcp.lua) that historically reached `crate::bridge::*`.
49pub use agent_block_mcp::lua_json::{json_to_lua, lua_to_json};
50
51/// Register bridge APIs shared between main VM and handler VM.
52///
53/// Registers everything except `bus::*`.  Split out from `register_all` so
54/// the handler-side Isle can re-use the same set of bridges without
55/// installing the main-VM-only `bus` global.
56///
57/// `is_handler_side` is forwarded to `mesh::register` so the handler Isle
58/// can skip the `mesh.on` alias (which depends on `bus.on` and would fail
59/// because the handler Isle does not expose a `bus` global).
60fn register_non_bus_bridges(lua: &Lua, ctx: &HostContext, is_handler_side: bool) -> LuaResult<()> {
61    #[cfg(feature = "mesh")]
62    mesh::register(lua, ctx, is_handler_side)?;
63    #[cfg(not(feature = "mesh"))]
64    let _ = is_handler_side;
65    sh::register(lua, ctx)?;
66    tool::register(lua)?;
67    // After tool::register — fs_tools.lua needs the `tool` global.
68    fs::register(lua, std::sync::Arc::clone(&ctx.fs_snapshots))?;
69    log::register(lua, ctx)?;
70    mcp::register(lua, ctx)?;
71    http::register(lua, ctx)?;
72    llm::register(lua)?;
73    knl::register(lua, ctx.knl_drivers.clone(), ctx.knl_store.clone())?;
74    #[cfg(feature = "sqlite")]
75    kv::register(lua, ctx)?;
76    #[cfg(feature = "sqlite")]
77    sql::register(lua, ctx)?;
78    #[cfg(feature = "sqlite")]
79    ts::register(lua, ctx.ts_isle.clone())?;
80    task::register(lua)?;
81    Ok(())
82}
83
84/// Register all bridge APIs into the Lua state (main Isle).
85///
86/// Note: `fs`, `env`, `json`, `path`, `time` are provided by mlua-batteries
87/// (registered as `std.*` in host.rs). This function registers only
88/// agent-block-specific APIs.
89pub fn register_all(lua: &Lua, ctx: &HostContext) -> LuaResult<()> {
90    // bus must register before mesh — the mesh.on alias (see
91    // bridge/mesh.rs) reads the `bus` global produced here.
92    bus::register(lua, ctx)?;
93    register_non_bus_bridges(lua, ctx, false)
94}
95
96/// Register bridge APIs for the handler Isle.
97///
98/// The handler Isle runs Lua handlers forwarded from the main Isle's
99/// `bus.on` / `bus.on_any` via bytecode transfer. It therefore needs the
100/// dispatcher-side globals (`__bus_handlers`, `__bus_on_any`,
101/// `__bus_dispatch`) installed by
102/// [`bus::install_bus_dispatcher_on_handler_isle`], but does **not** expose
103/// the `bus.*` Lua table — nested `bus.on(...)` from inside a handler is
104/// intentionally unsupported.
105pub fn register_all_handler_side(lua: &Lua, ctx: &HostContext) -> LuaResult<()> {
106    bus::install_bus_dispatcher_on_handler_isle(lua)?;
107    agent_block_mcp::handler::install_mcp_dispatcher_on_handler_isle(lua)?;
108    register_non_bus_bridges(lua, ctx, true)
109}