Skip to main content

mlua_swarm/worker/
baseline.rs

1//! Baseline agent — the canonical `RustFn` worker for bootstrap and
2//! smoke tests.
3//!
4//! The library-layer source of truth that structurally removes the
5//! pattern of each binary (server / MCP adapter / one-shot runner) inlining
6//! its own "let's just wire up a quick echo" duplicate. Same shape as
7//! `enhance/blueprint.rs`:
8//!
9//! - Export the agent name as a **role-literal const** ([`AG_IDENTITY`]).
10//!   The naming reflects the function itself — an identity /
11//!   passthrough of `ctx` — and deliberately avoids demo / echo
12//!   framing.
13//! - Bake **the real implementation** ([`extend_with_baseline`]). Not a
14//!   false-positive fake — a straightforward passthrough that returns
15//!   the input prompt in the value field, so callers can build smoke
16//!   tests around "the baseline agent exists".
17//! - **A builder** ([`extend_with_baseline`]) that adds the RustFn to
18//!   an existing `RustFnInProcessSpawnerFactory`. Same shape as
19//!   `enhance::blueprint::extend_factory`.
20//!
21//! ## Usage
22//!
23//! ```ignore
24//! use mlua_swarm_engine_core::baseline::{extend_with_baseline, AG_IDENTITY};
25//! use mlua_swarm_engine_core::RustFnInProcessSpawnerFactory;
26//!
27//! let factory = extend_with_baseline(RustFnInProcessSpawnerFactory::new());
28//! // The factory now has a RustFn registered under fn_id = AG_IDENTITY ("identity").
29//! ```
30//!
31//! Blueprint flows reference it as `spec: {"fn_id": baseline::AG_IDENTITY}`
32//! (or the literal `"identity"`).
33
34use crate::blueprint::compiler::RustFnInProcessSpawnerFactory;
35use crate::worker::adapter::WorkerResult;
36use serde_json::json;
37
38/// The baseline `RustFn` agent name — `"identity"`.
39///
40/// Role: a passthrough worker that echoes the input prompt into
41/// `value`. The logical id referenced from both the flow's `Step.ref`
42/// and the agent spec's `fn_id`.
43pub const AG_IDENTITY: &str = "identity";
44
45/// Builder that adds the baseline `RustFn` to a base factory.
46///
47/// Only one worker exists today ([`AG_IDENTITY`]); if additional
48/// baseline axes appear, they will be collected here.
49pub fn extend_with_baseline(base: RustFnInProcessSpawnerFactory) -> RustFnInProcessSpawnerFactory {
50    base.register_fn(AG_IDENTITY, |inv| async move {
51        Ok(WorkerResult {
52            value: json!({
53                "by": "baseline-identity",
54                "agent": inv.agent,
55                "echoed": inv.prompt,
56            }),
57            ok: true,
58        })
59    })
60}
61
62#[cfg(test)]
63mod tests {
64    use super::*;
65    use crate::blueprint::compiler::{SpawnerFactory, SpawnerFactoryKind};
66    use crate::blueprint::{AgentDef, AgentKind};
67    use serde_json::json;
68
69    #[test]
70    fn ag_identity_is_stable_literal() {
71        assert_eq!(AG_IDENTITY, "identity");
72    }
73
74    #[test]
75    fn extend_with_baseline_builds_identity_adapter() {
76        let factory = extend_with_baseline(RustFnInProcessSpawnerFactory::new());
77        assert_eq!(
78            <RustFnInProcessSpawnerFactory as SpawnerFactoryKind>::KIND,
79            AgentKind::RustFn
80        );
81        let agent_def = AgentDef {
82            name: "id".into(),
83            kind: AgentKind::RustFn,
84            spec: json!({ "fn_id": AG_IDENTITY }),
85            profile: None,
86            meta: None,
87        };
88        factory
89            .build(&agent_def, None)
90            .expect("AG_IDENTITY fn must be registered for AgentDef build");
91    }
92}