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