Skip to main content

nexo_tool_meta/
lib.rs

1//! Wire-shape types shared between the Nexo agent runtime and any
2//! third-party microapp that consumes its events.
3//!
4//! Provider-agnostic by construction: no transport layer (no
5//! `axum`, no `tokio`), no broker, no agent runtime. Pulling this
6//! crate in is a four-dependency, sub-second compile and exposes
7//! only the data shapes a downstream consumer needs to read what
8//! the daemon emits.
9//!
10//! # What lives here
11//!
12//! - [`BindingContext`] — identifies the inbound binding a tool
13//!   call originated from. Microapps read it from
14//!   `params._meta.nexo.binding`.
15//! - [`InboundMessageMeta`] — per-turn metadata about the inbound
16//!   message that triggered the agent turn (sender id, msg id,
17//!   timestamp, …). Microapps read it from
18//!   `params._meta.nexo.inbound`.
19//! - [`build_meta_value`] / [`parse_binding_from_meta`] /
20//!   [`parse_inbound_from_meta`] — the inverse trio around the
21//!   dual-write `_meta` payload.
22//! - [`WebhookEnvelope`] — JSON envelope nexo publishes to NATS
23//!   after every accepted webhook request.
24//! - [`format_webhook_source`] — turn-log marker helper.
25//!
26//! # Round-trip example
27//!
28//! ```
29//! use nexo_tool_meta::{build_meta_value, parse_binding_from_meta, BindingContext};
30//! use uuid::Uuid;
31//!
32//! // Daemon side: build the `_meta` payload for a tool call.
33//! let mut binding = BindingContext::agent_only("ana");
34//! binding.channel = Some("whatsapp".into());
35//! binding.account_id = Some("personal".into());
36//! binding.binding_id = Some("whatsapp:personal".into());
37//! let meta = build_meta_value("ana", Some(Uuid::nil()), Some(&binding), None);
38//!
39//! // Microapp side: extract the binding back.
40//! let parsed = parse_binding_from_meta(&meta).unwrap();
41//! assert_eq!(parsed.channel.as_deref(), Some("whatsapp"));
42//! assert_eq!(parsed.binding_id.as_deref(), Some("whatsapp:personal"));
43//! ```
44
45#![deny(missing_docs)]
46
47pub mod admin;
48pub mod binding;
49pub mod event_source;
50pub mod http_server;
51pub mod inbound;
52/// Locale validation. Lives here (rather than in nexo-microapp-sdk) so
53/// nexo-config can consume the closed-enum validator at YAML
54/// deserialise time. SDK still re-exports for back-compat.
55pub mod locale;
56pub mod marketing;
57pub mod meta;
58pub mod microapp_error;
59pub mod reply_kind;
60pub mod template;
61pub mod voice_addenda;
62pub mod webhook;
63
64pub use admin::audit::{AdminAuditResult, AdminAuditRow, AuditTailFilter, AuditTailPage};
65pub use binding::{binding_id_render, BindingContext};
66pub use event_source::{
67    format_dispatch_source, format_event_subscriber_source, format_rate_limit_hit, EventSourceMeta,
68};
69pub use inbound::{InboundKind, InboundMessageMeta};
70pub use locale::{LangCode, Locale, LocaleParseError, RegionCode};
71pub use meta::{
72    build_meta_value, parse_binding_from_meta, parse_inbound_from_meta, BINDING_KEY, INBOUND_KEY,
73    META_KEY, NEXO_NAMESPACE,
74};
75pub use microapp_error::{MicroappError, MicroappErrorKind, MICROAPP_ERROR_NOTIFY_METHOD};
76pub use template::{render_template, MISSING_PLACEHOLDER};
77pub use webhook::{format_webhook_source, WebhookEnvelope, ENVELOPE_SCHEMA_VERSION};
78
79// TypeScript bindings codegen: types tagged
80// `#[cfg_attr(feature = "ts-export", derive(ts_rs::TS), ts(export))]`
81// auto-generate one test per type via the `ts_rs::TS` derive macro.
82// Running `cargo test --features=ts-export -p nexo-tool-meta` triggers
83// every test, which writes per-type `.ts` files into the directory
84// pointed at by `TS_RS_EXPORT_DIR` (or `./bindings` by default). The
85// wrapper script `proyecto/scripts/regen-ts-types.sh` sets the env
86// var to point at agent-creator-microapp's frontend api/ directory
87// and concatenates the per-type files into a single `types.gen.ts`
88// with a banner header.
89//
90// Production builds (no `ts-export` feature) skip the derive
91// entirely — zero runtime impact.