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
15pub mod bus;
16pub mod config;
17pub mod http;
18#[cfg(feature = "sqlite")]
19pub mod kv;
20pub mod llm;
21pub mod log;
22pub mod mcp;
23#[cfg(feature = "mesh")]
24pub mod mesh;
25pub mod sh;
26#[cfg(feature = "sqlite")]
27pub mod sql;
28pub mod task;
29pub mod tool;
30#[cfg(feature = "sqlite")]
31pub mod ts;
32
33use mlua::prelude::*;
34
35use crate::host::HostContext;
36
37// Re-export `obs` from agent-block-types so that existing
38// `crate::bridge::obs::*` paths inside core keep compiling without
39// duplicating the module body.
40pub use agent_block_types::obs;
41
42// Re-export the Lua ↔ JSON converters from agent-block-mcp. They live in
43// the MCP crate because the rmcp handler depends on them; core only needs
44// to forward `lua_to_json` / `json_to_lua` for the in-process bridges
45// (llm / mesh / mcp.lua) that historically reached `crate::bridge::*`.
46pub use agent_block_mcp::lua_json::{json_to_lua, lua_to_json};
47
48/// Register bridge APIs shared between main VM and handler VM.
49///
50/// Registers everything except `bus::*`. Split out from `register_all` so
51/// the handler-side Isle can re-use the same set of bridges without
52/// installing the main-VM-only `bus` global.
53///
54/// `is_handler_side` is forwarded to `mesh::register` so the handler Isle
55/// can skip the `mesh.on` alias (which depends on `bus.on` and would fail
56/// because the handler Isle does not expose a `bus` global).
57fn register_non_bus_bridges(lua: &Lua, ctx: &HostContext, is_handler_side: bool) -> LuaResult<()> {
58 #[cfg(feature = "mesh")]
59 mesh::register(lua, ctx, is_handler_side)?;
60 #[cfg(not(feature = "mesh"))]
61 let _ = is_handler_side;
62 sh::register(lua, ctx)?;
63 tool::register(lua)?;
64 log::register(lua, ctx)?;
65 mcp::register(lua, ctx)?;
66 http::register(lua, ctx)?;
67 llm::register(lua)?;
68 #[cfg(feature = "sqlite")]
69 kv::register(lua, ctx)?;
70 #[cfg(feature = "sqlite")]
71 sql::register(lua, ctx)?;
72 #[cfg(feature = "sqlite")]
73 ts::register(lua, ctx)?;
74 task::register(lua)?;
75 Ok(())
76}
77
78/// Register all bridge APIs into the Lua state (main Isle).
79///
80/// Note: `fs`, `env`, `json`, `path`, `time` are provided by mlua-batteries
81/// (registered as `std.*` in host.rs). This function registers only
82/// agent-block-specific APIs.
83pub fn register_all(lua: &Lua, ctx: &HostContext) -> LuaResult<()> {
84 // bus must register before mesh — the mesh.on alias (see
85 // bridge/mesh.rs) reads the `bus` global produced here.
86 bus::register(lua, ctx)?;
87 register_non_bus_bridges(lua, ctx, false)
88}
89
90/// Register bridge APIs for the handler Isle.
91///
92/// The handler Isle runs Lua handlers forwarded from the main Isle's
93/// `bus.on` / `bus.on_any` via bytecode transfer. It therefore needs the
94/// dispatcher-side globals (`__bus_handlers`, `__bus_on_any`,
95/// `__bus_dispatch`) installed by
96/// [`bus::install_bus_dispatcher_on_handler_isle`], but does **not** expose
97/// the `bus.*` Lua table — nested `bus.on(...)` from inside a handler is
98/// intentionally unsupported.
99pub fn register_all_handler_side(lua: &Lua, ctx: &HostContext) -> LuaResult<()> {
100 bus::install_bus_dispatcher_on_handler_isle(lua)?;
101 agent_block_mcp::handler::install_mcp_dispatcher_on_handler_isle(lua)?;
102 register_non_bus_bridges(lua, ctx, true)
103}