Ir al contenido

Componentes

Un componente es un bloque portátil de WebAssembly (WASM) que implementa la interfaz WIT de Greentic. Los componentes son:

  • Aislados - Se ejecutan en un entorno WASM aislado
  • Portátiles - Se ejecutan en cualquier plataforma con Wasmtime
  • Componibles - Se combinan para crear flujos de trabajo complejos
  • Independientes del lenguaje - Se escriben en Rust, Go o cualquier lenguaje compatible con WASM
TipoPropósitoEjemplo
NodePaso de procesamiento de un flowLlamada a LLM, renderizador de plantillas
ProviderPuente hacia un servicio externoTelegram, Slack, SendGrid
ToolImplementación de una herramienta MCPConsulta a base de datos, llamada a API
OperatorTransformación de mensajesManejo de botones, renderizado de cards

Usa la CLI de creación de componentes:

Ventana de terminal
# Create new component project
greentic-component new my-processor
cd my-processor

Esto genera:

my-processor/
├── Cargo.toml
├── src/
│ └── lib.rs
├── wit/
│ └── component.wit
└── build.sh
Cargo.toml
[package]
name = "my-processor"
version = "0.1.0"
edition = "2024"
[lib]
crate-type = ["cdylib"]
[dependencies]
wit-bindgen = "0.53"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
[profile.release]
opt-level = "s"
lto = true

Define la interfaz de tu componente:

wit/component.wit
package greentic:my-processor;
interface types {
record input {
message: string,
context: option<string>,
}
record output {
result: string,
success: bool,
}
}
world processor {
import types;
export process: func(input: types.input) -> types.output;
}
src/lib.rs
use wit_bindgen::generate;
generate!({
world: "processor",
path: "wit",
});
struct MyProcessor;
impl Guest for MyProcessor {
fn process(input: Input) -> Output {
// Your processing logic here
let result = format!("Processed: {}", input.message);
Output {
result,
success: true,
}
}
}
export!(MyProcessor);
target/wasm32-wasip2/release/my_processor.wasm
# Build for WASM target
cargo build --target wasm32-wasip2 --release

Los componentes pueden realizar operaciones asíncronas usando interfaces WASI:

use wit_bindgen::generate;
generate!({
world: "async-processor",
path: "wit",
async: true,
});
impl Guest for AsyncProcessor {
async fn process(input: Input) -> Output {
// Async HTTP call
let response = http_fetch(&input.url).await;
Output {
result: response.body,
success: response.status == 200,
}
}
}

Accede al estado de la sesión dentro de los componentes:

impl Guest for StatefulProcessor {
fn process(input: Input, state: &mut State) -> Output {
// Read from state
let counter = state.get("counter").unwrap_or(0);
// Update state
state.set("counter", counter + 1);
Output {
result: format!("Processed {} times", counter + 1),
success: true,
}
}
}

Usa el tipo Result para manejar errores:

impl Guest for SafeProcessor {
fn process(input: Input) -> Result<Output, Error> {
if input.message.is_empty() {
return Err(Error::InvalidInput("Message cannot be empty".into()));
}
Ok(Output {
result: process_message(&input.message)?,
success: true,
})
}
}

Greentic proporciona varios componentes integrados:

Llama a LLM compatibles con OpenAI:

- id: analyze
type: llm
config:
model: "gpt-4"
system_prompt: "You are a helpful assistant."
prompt: "{{message}}"

Renderiza plantillas Handlebars:

- id: format
type: template
config:
template: "Hello, {{name}}! Your order #{{order_id}} is ready."

Ejecuta scripts Rhai:

- id: calculate
type: script
config:
script: |
let total = 0;
for item in items {
total += item.price * item.quantity;
}
total

Renderiza y valida Adaptive Cards:

- id: show_card
type: adaptive-card
config:
card: "cards/welcome.json"
data:
user_name: "{{user_name}}"
src/lib.rs
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_process() {
let input = Input {
message: "Hello".into(),
context: None,
};
let output = MyProcessor::process(input);
assert!(output.success);
assert!(output.result.contains("Processed"));
}
}
Ventana de terminal
# Run with test harness
greentic-component test ./my-processor
# Test with sample input
echo '{"message": "test"}' | greentic-component run ./my-processor.wasm
  1. Mantén los componentes enfocados - Responsabilidad única
  2. Maneja todos los errores - Nunca hagas panic en producción
  3. Minimiza las dependencias - Binarios WASM más pequeños
  4. Usa tipos sólidos - Aprovecha WIT para seguridad de tipos
  5. Documenta las interfaces - Definiciones WIT claras
  6. Prueba a fondo - Pruebas unitarias y de integración
  7. Optimiza el tamaño - Usa LTO y optimización de tamaño
Ventana de terminal
# Inspect component exports
wasm-tools component wit ./my-processor.wasm
# Validate component
wasm-tools validate ./my-processor.wasm

Usa la interfaz de logging de WASI:

use greentic_interfaces::log;
impl Guest for DebugProcessor {
fn process(input: Input) -> Output {
log::debug(&format!("Processing: {:?}", input));
// ... processing ...
log::info("Processing complete");
output
}
}