tawasuyu

tawasuyu/brahman

Rust 332TOML 127JSON 17Markdown 154710 Definiciones

⎇ 595f68e2526c8dae4e8bc2a810f671bcdcc9f018 crates/apps/yahweh-shell/src/brahman_client.rs Rust · 121 líneas · 3.5 KB Historia Quién tocó qué crudo

feat(yahweh-shell): primer módulo brahman vivo 595f68e25 · Sergio ·

1//! Sidecar brahman: yahweh se presenta al Init como módulo `Widget`.
2//!
3//! Vive en un thread aparte con tokio runtime current_thread, desacoplado
4//! de GPUI. Si el Init no está disponible, loggea y termina — yahweh
5//! sigue funcionando standalone. Si conecta, mantiene la sesión viva
6//! con pings periódicos hasta que la GUI termine o el server caiga.
7//!
8//! Card declarada:
9//! - label: `brahman.ui_engine`
10//! - lifecycle: `Widget`
11//! - flow.input: `render-data` (json)
12//! - flow.output: `user-intent` (json)
13//! - permissions: filesystem read-write (yahweh persiste `layout.json`),
14//!   IPC `wit-v1`.
15
16use std::collections::BTreeSet;
17use std::time::Duration;
18
19use brahman_card::{
20    Card, Flow, Flows, FsPolicy, IpcPolicy, Lifecycle, Payload, Permissions, Priority, Supervision,
21    TypeRef, CARD_SCHEMA_VERSION,
22};
23use brahman_handshake::{client::Client, transport};
24use ulid::Ulid;
25
26/// Período entre pings al Init.
27const PING_INTERVAL: Duration = Duration::from_secs(30);
28
29/// Spawn del sidecar brahman. No-op si el thread no se puede crear.
30/// Devuelve inmediatamente; la conexión se establece en background.
31pub fn spawn() {
32    let result = std::thread::Builder::new()
33        .name("brahman-client".into())
34        .spawn(run_thread);
35    if let Err(e) = result {
36        eprintln!("[brahman] no se pudo spawnear el sidecar: {e}");
37    }
38}
39
40fn run_thread() {
41    let rt = match tokio::runtime::Builder::new_current_thread()
42        .enable_io()
43        .enable_time()
44        .build()
45    {
46        Ok(rt) => rt,
47        Err(e) => {
48            eprintln!("[brahman] tokio runtime falló: {e}");
49            return;
50        }
51    };
52    rt.block_on(run_client());
53}
54
55async fn run_client() {
56    let path = transport::default_socket_path();
57    let card = build_card();
58
59    let mut client = match Client::connect(&path, card).await {
60        Ok(c) => {
61            eprintln!(
62                "[brahman] attached: session={} init_attached={} server={}",
63                c.session(),
64                c.server_info().init_attached,
65                c.server_info().server_version
66            );
67            c
68        }
69        Err(e) => {
70            eprintln!("[brahman] no conectado a {} ({e})", path.display());
71            return;
72        }
73    };
74
75    loop {
76        tokio::time::sleep(PING_INTERVAL).await;
77        if let Err(e) = client.ping().await {
78            eprintln!("[brahman] ping falló: {e}");
79            return;
80        }
81    }
82}
83
84fn build_card() -> Card {
85    Card {
86        schema_version: CARD_SCHEMA_VERSION,
87        id: Ulid::new(),
88        lineage: None,
89        label: "brahman.ui_engine".into(),
90        provides: BTreeSet::new(),
91        requires: BTreeSet::new(),
92        payload: Payload::Virtual,
93        supervision: Supervision::Delegate,
94        lifecycle: Lifecycle::Widget,
95        priority: Priority::Normal,
96        permissions: Permissions {
97            filesystem: FsPolicy::ReadWrite,
98            ipc: IpcPolicy {
99                allow: vec!["wit-v1".into()],
100            },
101            ..Default::default()
102        },
103        flow: Flows {
104            input: vec![Flow {
105                name: "render-data".into(),
106                ty: TypeRef::Primitive {
107                    name: "json".into(),
108                },
109                pin_to: None,
110            }],
111            output: vec![Flow {
112                name: "user-intent".into(),
113                ty: TypeRef::Primitive {
114                    name: "json".into(),
115                },
116                pin_to: None,
117            }],
118        },
119        ..Default::default()
120    }
121}