chore: refresco desde el monorepo (pin tawasuyu.git v0.2.0)
Regenerado con scripts/actualizar-standalone.py: código del dominio al día,
git-deps repineadas a v0.2.0 y doble-fuente resuelta con [patch] al source git.
cargo check --workspace verde.
bb86cfaeae474682bae8a1b3349ac82932fb39e1 · por Sergio · 2026-07-25T21:03:54Z (hace 3 meses) · padre 958e62665 · ver el árbol en este commit
Delta semántico · 141
02_ruway/chasqui/card-handshake/src/health.rs
02_ruway/chasqui/card-handshake/src/lib.rs
02_ruway/chasqui/card-handshake/tests/handshake.rs
02_ruway/chasqui/chasqui-broker-explorer-llimphi/examples/chasqui_showreel.rs
02_ruway/chasqui/chasqui-broker-explorer-llimphi/src/main.rs
02_ruway/chasqui/chasqui-card/src/intension.rs
02_ruway/chasqui/chasqui-card/src/lib.rs
02_ruway/chasqui/chasqui-core/src/bin/nouser.rs
02_ruway/chasqui/chasqui-core/src/cluster.rs
02_ruway/chasqui/chasqui-core/src/db.rs
02_ruway/chasqui/chasqui-core/src/edit.rs
02_ruway/chasqui/chasqui-core/src/grafo.rs
02_ruway/chasqui/chasqui-core/src/lib.rs
02_ruway/chasqui/chasqui-core/src/resolve.rs
02_ruway/chasqui/chasqui-explorer-llimphi/src/main.rs
02_ruway/chasqui/chasqui-nous-real/src/cache.rs
02_ruway/chasqui/chasqui-nous-real/src/embeddings.rs
02_ruway/chasqui/chasqui-nous-real/src/main.rs
cambió por dentro fn main
39 archivos · +4681 −1120
diff --git a/02_ruway/chasqui/ARQUITECTURA.md b/02_ruway/chasqui/ARQUITECTURA.md
index bddc6a5..b7f21d3 100644
--- a/02_ruway/chasqui/ARQUITECTURA.md
+++ b/02_ruway/chasqui/ARQUITECTURA.md
@@ -185,7 +185,7 @@ DEUDA / ASPIRA_A:
#5 COHERENCIA cross-dominio: rimay/shuma/arje aún no integrados a fondo con nouser.
NORTE_ARQUITECTÓNICO:
- Dos planos que convergen. PLANO DE TIPOS (Brahman): "decláme qué consumís y te encuentro quién lo produce,
+ Dos planos que convergen. PLANO DE TIPOS (Brahman): "decláme qué consumes y te encuentro quién lo produce,
determinista y observable, sin acoplar módulos". PLANO DE DATOS (Nouser): "dame una carpeta y te devuelvo su
estructura semántica latente (Mónadas) con embeddings intercambiables".
El destino es que el broker deje de ser local (Unix socket) y, sobre transporte minga/libp2p, haga discovery
diff --git a/02_ruway/chasqui/LEEME.md b/02_ruway/chasqui/LEEME.md
index e86434b..08c3daa 100644
--- a/02_ruway/chasqui/LEEME.md
+++ b/02_ruway/chasqui/LEEME.md
@@ -1,41 +1,43 @@
# chasqui
-> `chasqui` (quechua: *mensajero del camino del inca*). Broker de mensajería + bus tipado.
+> `chasqui` (quechua: *mensajero del camino del inca*). Broker de tipos + Mónadas semánticas.
-Sistema nervioso del monorepo. Apps publican y se suscriben a topics tipados; el broker rutea y persiste. Backend `nous` con dos implementaciones: `mock` (in-process para tests) y `real` (TCP + binary). Cada mensaje lleva su schema, fail-closed si el receptor no lo conoce.
+Dominio dual (ver `ARQUITECTURA.md`, el doc técnico autoritativo). **Brahman**: broker de tipos determinista — los módulos (Cards) declaran flujos tipados de entrada/salida y el broker matchea consumer↔producer (matching exact + structural, prioridades, sesgos por contexto) sin mover datos. **Nouser**: inteligencia de datos — escanea directorios en Mónadas (clusters semánticos de archivos) enriquecidas por proveedores de embeddings intercambiables tras el contrato `nous`: `mock` (32d determinista) y `real` (ONNX 384d). El discovery de consumidores es local-first con fallback DHT (`card-sidecar::discovery::resolve_provider`), más connect-and-consume remoto por libp2p (`consume_remote`).
## Instalación
```sh
-# arrancar el broker
-cargo run --release -p chasqui-broker
-
-# explorer (ver topics + mensajes en vivo)
-cargo run --release -p chasqui-broker-explorer-llimphi
-cargo run --release -p chasqui-explorer-llimphi
+cargo run --release -p chasqui-core --bin chasqui # CLI Nouser: scan|show|json|daemon|attract
+cargo run --release -p chasqui-broker-explorer-llimphi # UI probe del broker
+cargo run --release -p chasqui-explorer-llimphi # UI explorador de Mónadas
```
+El broker Brahman es una librería hospedada por el init de arje (`arje-zero`), no un binario standalone.
+
## Compatibilidad
-- **Linux / macOS / Windows** — broker + clientes en Rust nativo.
-- **Wawa** — broker corre como app del kernel (`apps/`).
-- TCP localhost por default; sockets Unix opcionales.
+- **Linux / macOS** — Rust nativo; handshake sobre sockets Unix.
+- **Remoto** — handshake sobre stream libp2p (`card-net`): relay + dcutr + autonat, el NAT ya no bloquea.
+- El broker vive en la memoria del Init — efímero por diseño, sin snapshot/recover.
## Crates
| Crate | Rol |
|---|---|
-| [`chasqui-core`](chasqui-core/README.md) | Tipos: Topic, Message, Schema, Subscription. |
-| [`chasqui-broker`](chasqui-broker/README.md) | Binario del broker. |
-| [`chasqui-nous`](chasqui-nous/README.md) | Trait del transport. |
-| [`chasqui-nous-mock`](chasqui-nous-mock/README.md) | Transport in-process para tests. |
-| [`chasqui-nous-real`](chasqui-nous-real/README.md) | Transport TCP/Unix binario. |
-| [`chasqui-card`](chasqui-card/README.md) | Card escritorio (estado del broker). |
-| [`chasqui-broker-explorer-llimphi`](chasqui-broker-explorer-llimphi/README.md) | UI: topics + suscriptores activos. |
-| [`chasqui-explorer-llimphi`](chasqui-explorer-llimphi/README.md) | UI: log de mensajes en vivo. |
+| [`chasqui-broker`](chasqui-broker/README.md) | Brahman: librería de matching de tipos (Exact/Structural, prioridades, contextos). |
+| [`card-handshake`](card-handshake/) | Handshake Init↔módulo: Unix socket local, stream libp2p remoto. |
+| [`card-sidecar`](card-sidecar/) | Mantiene viva la sesión + discovery (`resolve_provider`, `consume_remote`). |
+| [`card-admin`](card-admin/) | Snapshot del estado del broker (sesiones + matches) — `brahman-status`. |
+| [`chasqui-core`](chasqui-core/README.md) | Nouser: scanner, clustering determinista, MonadDb, CLI `chasqui`. |
+| [`chasqui-card`](chasqui-card/README.md) | Manifiesto de Mónada + cliente de query (`resolve_monad`). |
+| [`chasqui-nous`](chasqui-nous/README.md) | Contrato Nous: JSON line-delimited sobre Unix socket. |
+| [`chasqui-nous-mock`](chasqui-nous-mock/README.md) | Proveedor de pseudo-embeddings 32d determinista. |
+| [`chasqui-nous-real`](chasqui-nous-real/README.md) | Proveedor de embeddings 384d ONNX (feature `embeddings`). |
+| [`chasqui-broker-explorer-llimphi`](chasqui-broker-explorer-llimphi/README.md) | UI probe del broker: estado + timeline de matches. |
+| [`chasqui-explorer-llimphi`](chasqui-explorer-llimphi/README.md) | UI exploradora de Mónadas con búsqueda semántica. |
## Consideraciones
-- **Schema-first.** Sin schema declarado, ningún mensaje pasa.
-- **Persistencia opt-in** por topic; los topics efímeros viven sólo en memoria.
-- **No es Kafka.** Diseñado para el monorepo, no para volumen de producción interplanetaria.
+- **El broker matchea tipos, no mueve datos.** Cada módulo abre su propio data plane (`service_socket`).
+- **Efímero por diseño.** El broker es el registro en memoria del Init de qué está vivo *ahora* — no es deuda de persistencia.
+- **No es un bus pub/sub.** Esa aspiración original migró al dominio Ayni; chasqui no transporta mensajes app↔app en tiempo real.
diff --git a/02_ruway/chasqui/README.md b/02_ruway/chasqui/README.md
index 2366596..524ca75 100644
--- a/02_ruway/chasqui/README.md
+++ b/02_ruway/chasqui/README.md
@@ -1,38 +1,43 @@
# chasqui
-> `chasqui` (Quechua: *messenger of the Inca road*). Message broker + typed bus.
+> `chasqui` (Quechua: *messenger of the Inca road*). Type broker + semantic Monads.
-Nervous system of the monorepo. Apps publish and subscribe to typed topics; the broker routes and persists. `nous` backend with two impls: `mock` (in-process for tests) and `real` (binary TCP). Every message carries its schema, fail-closed if the receiver doesn't know it.
+Dual domain (see `ARQUITECTURA.md`, the authoritative technical doc). **Brahman**: a deterministic type broker — modules (Cards) declare typed input/output flows and the broker matches consumer↔producer (exact + structural matching, priorities, per-context biases) without moving any data. **Nouser**: data intelligence — scans directories into Monads (semantic file clusters) enriched by swappable embedding providers behind the `nous` contract: `mock` (deterministic 32d) and `real` (ONNX 384d). Consumer discovery is local-first with DHT fallback (`card-sidecar::discovery::resolve_provider`), plus remote connect-and-consume over libp2p (`consume_remote`).
## Install
```sh
-cargo run --release -p chasqui-broker
-cargo run --release -p chasqui-broker-explorer-llimphi
-cargo run --release -p chasqui-explorer-llimphi
+cargo run --release -p chasqui-core --bin chasqui # Nouser CLI: scan|show|json|daemon|attract
+cargo run --release -p chasqui-broker-explorer-llimphi # broker probe UI
+cargo run --release -p chasqui-explorer-llimphi # Monad explorer UI
```
+The Brahman broker is a library hosted by arje's init (`arje-zero`), not a standalone binary.
+
## Compatibility
-- **Linux / macOS / Windows** — broker + clients in native Rust.
-- **Wawa** — broker runs as a kernel app.
-- TCP localhost by default; Unix sockets optional.
+- **Linux / macOS** — native Rust; handshake over Unix sockets.
+- **Remote** — handshake over libp2p stream (`card-net`): relay + dcutr + autonat, NAT no longer blocks.
+- The broker lives in the Init's memory — ephemeral by design, no snapshot/recover.
## Crates
| Crate | Role |
|---|---|
-| [`chasqui-core`](chasqui-core/README.md) | Topic, Message, Schema, Subscription. |
-| [`chasqui-broker`](chasqui-broker/README.md) | Broker binary. |
-| [`chasqui-nous`](chasqui-nous/README.md) | Transport trait. |
-| [`chasqui-nous-mock`](chasqui-nous-mock/README.md) | In-process transport. |
-| [`chasqui-nous-real`](chasqui-nous-real/README.md) | Binary TCP/Unix transport. |
-| [`chasqui-card`](chasqui-card/README.md) | Desktop card. |
-| [`chasqui-broker-explorer-llimphi`](chasqui-broker-explorer-llimphi/README.md) | Topics + active subscribers UI. |
-| [`chasqui-explorer-llimphi`](chasqui-explorer-llimphi/README.md) | Live message log UI. |
+| [`chasqui-broker`](chasqui-broker/README.md) | Brahman: type-matching library (Exact/Structural, priorities, contexts). |
+| [`card-handshake`](card-handshake/) | Init↔module handshake: Unix socket local, libp2p stream remote. |
+| [`card-sidecar`](card-sidecar/) | Keeps the session alive + discovery (`resolve_provider`, `consume_remote`). |
+| [`card-admin`](card-admin/) | Broker state snapshot (sessions + matches) — `brahman-status`. |
+| [`chasqui-core`](chasqui-core/README.md) | Nouser: scanner, deterministic clustering, MonadDb, `chasqui` CLI. |
+| [`chasqui-card`](chasqui-card/README.md) | Monad manifest + query client (`resolve_monad`). |
+| [`chasqui-nous`](chasqui-nous/README.md) | Nous contract: JSON line-delimited over Unix socket. |
+| [`chasqui-nous-mock`](chasqui-nous-mock/README.md) | Deterministic 32d pseudo-embeddings provider. |
+| [`chasqui-nous-real`](chasqui-nous-real/README.md) | 384d ONNX embeddings provider (`embeddings` feature). |
+| [`chasqui-broker-explorer-llimphi`](chasqui-broker-explorer-llimphi/README.md) | Broker probe UI: status + match timeline. |
+| [`chasqui-explorer-llimphi`](chasqui-explorer-llimphi/README.md) | Monad explorer UI with semantic search. |
## Considerations
-- **Schema-first.** No schema declared, no message through.
-- **Persistence opt-in** per topic; ephemeral topics live in memory only.
-- **Not Kafka.** Designed for the monorepo, not interplanetary production volume.
+- **The broker matches types, it does not move data.** Each module opens its own data plane (`service_socket`).
+- **Ephemeral by design.** The broker is the Init's in-memory registry of what's alive *now* — no persistence debt.
+- **Not a pub/sub bus.** That original aspiration migrated to the Ayni domain; chasqui carries no app↔app messages in real time.
diff --git a/02_ruway/chasqui/card-admin/LEEME.md b/02_ruway/chasqui/card-admin/LEEME.md
new file mode 100644
index 0000000..8976b05
--- /dev/null
+++ b/02_ruway/chasqui/card-admin/LEEME.md
@@ -0,0 +1,18 @@
+# card-admin
+
+*Read this in English: [README.md](README.md).*
+
+`brahman-admin` — observabilidad del broker.
+
+Expone un Unix socket separado (no se mezcla con el handshake) en el
+que cada conexión recibe un `StatusSnapshot` JSON y se cierra. Es
+single-shot por conexión: pensado para herramientas como
+`brahman-status`, dashboards y health-checks.
+
+Wire format: una línea JSON por conexión, terminada en `\n`. Esto
+hace trivial inspeccionar con `nc` o `socat` además del cliente
+tipado de este crate.
+
+---
+
+Parte de **chasqui** — ver [chasqui](../LEEME.md).
diff --git a/02_ruway/chasqui/card-admin/README.md b/02_ruway/chasqui/card-admin/README.md
new file mode 100644
index 0000000..3081696
--- /dev/null
+++ b/02_ruway/chasqui/card-admin/README.md
@@ -0,0 +1,11 @@
+# card-admin
+
+`brahman-admin` — the broker's observability.
+
+It exposes a separate Unix socket (not mixed with the handshake) where each
+connection receives a JSON `StatusSnapshot` and is closed. It is single-shot per
+connection: meant for tools that poll.
+
+---
+
+Part of **chasqui** — see [chasqui](../README.md).
diff --git a/02_ruway/chasqui/card-handshake/LEEME.md b/02_ruway/chasqui/card-handshake/LEEME.md
new file mode 100644
index 0000000..aa4da68
--- /dev/null
+++ b/02_ruway/chasqui/card-handshake/LEEME.md
@@ -0,0 +1,23 @@
+# card-handshake
+
+*Read this in English: [README.md](README.md).*
+
+`brahman-handshake` — protocolo runtime Init↔módulo sobre Unix socket.
+
+Implementa la versión concreta de `shared_wit/protocol.wit` (handshake +
+lifecycle): un servidor que vive en el Init (o un Admin proxy) y clientes
+que son los módulos Brahman. Cada conexión arranca con un `Hello` que
+lleva una `card_core::Card`; el servidor valida la Card, deriva el
+`TrustLevel`, emite un `HelloAck` con `session-id` ULID, y a partir de
+ahí acepta `Ping`/`Farewell`.
+
+Wire format: frames length-prefixed (4 bytes LE) con cuerpo
+`postcard`-codificado. Compacto, rápido y reversible.
+
+Esto NO es la implementación WIT/WASM (que generaría wit-bindgen). Es la
+implementación nativa Rust↔Rust que cubre el caso común antes de que los
+módulos WASM consuman el mismo contrato vía ABI generada.
+
+---
+
+Parte de **chasqui** — ver [chasqui](../LEEME.md).
diff --git a/02_ruway/chasqui/card-handshake/README.md b/02_ruway/chasqui/card-handshake/README.md
new file mode 100644
index 0000000..ec26a86
--- /dev/null
+++ b/02_ruway/chasqui/card-handshake/README.md
@@ -0,0 +1,11 @@
+# card-handshake
+
+`brahman-handshake` — the runtime Init↔module protocol over a Unix socket.
+
+It implements the concrete version of `shared_wit/protocol.wit` (handshake +
+lifecycle): a server living in the Init (or an Admin proxy) and clients that are the
+Brahman modules. Every connection starts with a `Hello`.
+
+---
+
+Part of **chasqui** — see [chasqui](../README.md).
diff --git a/02_ruway/chasqui/card-handshake/src/client.rs b/02_ruway/chasqui/card-handshake/src/client.rs
index d93dd33..941c7f3 100644
--- a/02_ruway/chasqui/card-handshake/src/client.rs
+++ b/02_ruway/chasqui/card-handshake/src/client.rs
@@ -82,7 +82,7 @@ where
{
/// Constructor genérico sobre un stream ya abierto, **sin firma**.
/// Apto para path Unix (donde SO_PEERCRED del kernel ya autentica)
- /// o tests in-memory. Para libp2p remoto usá
+ /// o tests in-memory. Para libp2p remoto usa
/// [`connect_with_stream_signed`](Self::connect_with_stream_signed) —
/// el server libp2p rechaza Hello sin firma.
pub async fn connect_with_stream(
diff --git a/02_ruway/chasqui/card-handshake/src/health.rs b/02_ruway/chasqui/card-handshake/src/health.rs
new file mode 100644
index 0000000..18318ee
--- /dev/null
+++ b/02_ruway/chasqui/card-handshake/src/health.rs
@@ -0,0 +1,91 @@
+//! Observación de la **salud del broker por polling**: diff entre snapshots de
+//! matches tomados en ticks sucesivos.
+//!
+//! A diferencia de [`crate::messages::MatchEvent`] (push del server al consumer,
+//! tipo de protocolo serializable), esto es la observación que arma un monitor
+//! que **consulta** la `MatchList` cada N segundos y deriva qué apareció
+//! (`Available`) y qué desapareció (`Lost`) entre ticks. Vivía atrapado en el
+//! frontend `chasqui-broker-explorer-llimphi`; baja aquí —junto a `MatchList` y
+//! `MatchEventKind`— para que cualquier monitor (UI, CLI) lo reuse (Regla 2).
+
+use std::collections::HashSet;
+
+use chasqui_broker::MatchStrategy;
+
+use crate::messages::{MatchEventKind, MatchList, SessionId};
+
+/// Clave estable de un match: `(sesión_consumer, flow_consumer, sesión_producer,
+/// flow_producer)`. Identifica un match entre ticks para detectar altas y bajas.
+pub type MatchKey = (SessionId, String, SessionId, String);
+
+/// Una entrada del timeline de salud: un alta/baja observada al diferenciar dos
+/// snapshots, con el momento en que el monitor la vio.
+#[derive(Clone, Debug)]
+pub struct TimelineEntry {
+ pub at: std::time::SystemTime,
+ pub kind: MatchEventKind,
+ pub consumer_label: String,
+ pub consumer_flow: String,
+ pub producer_label: String,
+ pub producer_flow: String,
+ pub via: MatchStrategy,
+ pub pinned: bool,
+}
+
+/// Diff puro entre snapshots de matches. Devuelve la lista de entries nuevas
+/// (Available + Lost) en orden Available-primero, y el set actualizado de keys.
+pub fn diff_matches(
+ last_keys: &HashSet<MatchKey>,
+ list: &MatchList,
+) -> (Vec<TimelineEntry>, HashSet<MatchKey>) {
+ let now = std::time::SystemTime::now();
+ let current_keys: HashSet<MatchKey> = list
+ .matches
+ .iter()
+ .map(|m| {
+ (
+ m.consumer.session,
+ m.consumer.flow_name.clone(),
+ m.producer.session,
+ m.producer.flow_name.clone(),
+ )
+ })
+ .collect();
+
+ let mut entries = Vec::new();
+ for m in &list.matches {
+ let key = (
+ m.consumer.session,
+ m.consumer.flow_name.clone(),
+ m.producer.session,
+ m.producer.flow_name.clone(),
+ );
+ if !last_keys.contains(&key) {
+ entries.push(TimelineEntry {
+ at: now,
+ kind: MatchEventKind::Available,
+ consumer_label: m.consumer_label.clone(),
+ consumer_flow: m.consumer.flow_name.clone(),
+ producer_label: m.producer_label.clone(),
+ producer_flow: m.producer.flow_name.clone(),
+ via: m.via,
+ pinned: m.pinned,
+ });
+ }
+ }
+ for key in last_keys.iter() {
+ if !current_keys.contains(key) {
+ entries.push(TimelineEntry {
+ at: now,
+ kind: MatchEventKind::Lost,
+ consumer_label: String::new(),
+ consumer_flow: key.1.clone(),
+ producer_label: String::new(),
+ producer_flow: key.3.clone(),
+ via: MatchStrategy::Exact,
+ pinned: false,
+ });
+ }
+ }
+ (entries, current_keys)
+}
diff --git a/02_ruway/chasqui/card-handshake/src/identity.rs b/02_ruway/chasqui/card-handshake/src/identity.rs
index ac2a46c..a51e396 100644
--- a/02_ruway/chasqui/card-handshake/src/identity.rs
+++ b/02_ruway/chasqui/card-handshake/src/identity.rs
@@ -131,7 +131,7 @@ pub struct SessionCert {
/// format libp2p protobuf.
pub session_pubkey: Vec<u8>,
/// Public key de la master identity, en format libp2p protobuf.
- /// El verificador deriva el `master_peer_id` desde acá.
+ /// El verificador deriva el `master_peer_id` desde aquí.
pub master_pubkey: Vec<u8>,
/// Expiración en milisegundos desde UNIX_EPOCH. Tras esto, el
/// cert no es válido y el nodo debe re-emitirse uno nuevo
diff --git a/02_ruway/chasqui/card-handshake/src/lib.rs b/02_ruway/chasqui/card-handshake/src/lib.rs
index c744925..28191e3 100644
--- a/02_ruway/chasqui/card-handshake/src/lib.rs
+++ b/02_ruway/chasqui/card-handshake/src/lib.rs
@@ -18,6 +18,7 @@
#![warn(rust_2018_idioms)]
pub mod codec;
+pub mod health;
pub mod identity;
pub mod messages;
pub mod server;
diff --git a/02_ruway/chasqui/card-handshake/tests/handshake.rs b/02_ruway/chasqui/card-handshake/tests/handshake.rs
index 3c716b6..240590f 100644
--- a/02_ruway/chasqui/card-handshake/tests/handshake.rs
+++ b/02_ruway/chasqui/card-handshake/tests/handshake.rs
@@ -37,6 +37,8 @@ fn sample_card(label: &str) -> Card {
namespaces: NamespaceSet::default(),
rlimits: ResourceLimits::default(),
cpu_affinity: None,
+ run_as: None,
+ mounts: card_core::MountPlan::default(),
},
payload: Payload::Virtual,
supervision: Supervision::OneShot,
@@ -224,6 +226,8 @@ fn card_with_flows(label: &str, input: Vec<Flow>, output: Vec<Flow>) -> Card {
namespaces: NamespaceSet::default(),
rlimits: ResourceLimits::default(),
cpu_affinity: None,
+ run_as: None,
+ mounts: card_core::MountPlan::default(),
},
payload: Payload::Virtual,
supervision: Supervision::OneShot,
diff --git a/02_ruway/chasqui/card-sidecar/LEEME.md b/02_ruway/chasqui/card-sidecar/LEEME.md
new file mode 100644
index 0000000..6b73ff2
--- /dev/null
+++ b/02_ruway/chasqui/card-sidecar/LEEME.md
@@ -0,0 +1,22 @@
+# card-sidecar
+
+*Read this in English: [README.md](README.md).*
+
+`brahman-sidecar` — boilerplate del cliente brahman extraído.
+
+Cualquier módulo que quiera presentarse al Init brahman pero que tenga
+su propio runtime (GPUI, current_thread tokio, std-thread loop, etc.)
+puede llamar `spawn` con su `card_core::Card`. Eso arma un
+thread aparte con un runtime tokio current_thread, conecta al Init,
+y mantiene la sesión viva con pings periódicos.
+
+Si el Init no está disponible, el thread loggea y termina — el módulo
+sigue funcionando standalone.
+
+Errores de conexión / ping se loggean vía `tracing::warn!`. Si quieres
+capturar la salida del thread (por ejemplo para test), usa
+`spawn_with_handle` que devuelve un `JoinHandle`.
+
+---
+
+Parte de **chasqui** — ver [chasqui](../LEEME.md).
diff --git a/02_ruway/chasqui/card-sidecar/README.md b/02_ruway/chasqui/card-sidecar/README.md
new file mode 100644
index 0000000..d0b7391
--- /dev/null
+++ b/02_ruway/chasqui/card-sidecar/README.md
@@ -0,0 +1,11 @@
+# card-sidecar
+
+`brahman-sidecar` — the brahman client's boilerplate, extracted.
+
+Any module that wants to present itself to the brahman Init but has its own runtime
+(a current_thread tokio, an std-thread loop, and so on) can call `spawn` with its
+`card_core::Card`.
+
+---
+
+Part of **chasqui** — see [chasqui](../README.md).
diff --git a/02_ruway/chasqui/card-sidecar/src/discovery.rs b/02_ruway/chasqui/card-sidecar/src/discovery.rs
index 6f9fb1b..ae4c873 100644
--- a/02_ruway/chasqui/card-sidecar/src/discovery.rs
+++ b/02_ruway/chasqui/card-sidecar/src/discovery.rs
@@ -3,7 +3,7 @@
//! sockets ni reimplementar el patrón a mano.
//!
//! Es la generalización de `discover_producer_socket` del CLI
-//! `chasqui attract --remote`: declarás el `TypeRef` que querés
+//! `chasqui attract --remote`: declaras el `TypeRef` que quieres
//! consumir y el broker te empuja un `MatchEvent::Available` con el
//! `producer_service_socket` del primer proveedor matched.
//!
@@ -18,7 +18,7 @@
//! `current_thread`.
//!
//! Quién elige al proveedor es el broker, no este módulo. Si el
-//! broker tiene `priority_contexts` activo, podés cambiar de
+//! broker tiene `priority_contexts` activo, puedes cambiar de
//! proveedor sin tocar el consumer; el matching dinámico se respeta.
use std::path::PathBuf;
@@ -70,8 +70,8 @@ pub enum ConsumerError {
}
/// Construye una Card mínima de consumer que declara un input flow
-/// con el `TypeRef::Primitive { name }` solicitado. Usá esto para
-/// el caso común; si necesitás algo más rico (output flows,
+/// con el `TypeRef::Primitive { name }` solicitado. Usa esto para
+/// el caso común; si necesitas algo más rico (output flows,
/// permissions, references) construí la Card a mano y pasala a
/// [`await_provider`] directamente.
pub fn build_consumer_card(
diff --git a/02_ruway/chasqui/card-sidecar/src/lib.rs b/02_ruway/chasqui/card-sidecar/src/lib.rs
index 1c86df8..5644527 100644
--- a/02_ruway/chasqui/card-sidecar/src/lib.rs
+++ b/02_ruway/chasqui/card-sidecar/src/lib.rs
@@ -9,8 +9,8 @@
//! Si el Init no está disponible, el thread loggea y termina — el módulo
//! sigue funcionando standalone.
//!
-//! Errores de conexión / ping se loggean vía `tracing::warn!`. Si querés
-//! capturar la salida del thread (por ejemplo para test), usá
+//! Errores de conexión / ping se loggean vía `tracing::warn!`. Si quieres
+//! capturar la salida del thread (por ejemplo para test), usa
//! [`spawn_with_handle`] que devuelve un `JoinHandle`.
#![forbid(unsafe_code)]
@@ -65,7 +65,7 @@ impl SidecarConfig {
}
}
-/// Spawn fire-and-forget agnóstico. Para módulos conscientes usá
+/// Spawn fire-and-forget agnóstico. Para módulos conscientes usa
/// [`spawn_conscious`] o [`spawn_with_handle`] con un `SidecarConfig`
/// personalizado.
pub fn spawn(card: Card) {
diff --git a/02_ruway/chasqui/chasqui-broker-explorer-llimphi/Cargo.toml b/02_ruway/chasqui/chasqui-broker-explorer-llimphi/Cargo.toml
index a49c7d5..f727dea 100644
--- a/02_ruway/chasqui/chasqui-broker-explorer-llimphi/Cargo.toml
+++ b/02_ruway/chasqui/chasqui-broker-explorer-llimphi/Cargo.toml
@@ -20,9 +20,19 @@ llimphi-widget-banner = { workspace = true }
llimphi-widget-stat-card = { workspace = true }
llimphi-widget-menubar = { workspace = true }
llimphi-widget-context-menu = { workspace = true }
+llimphi-widget-skeleton = { workspace = true }
+llimphi-widget-empty = { workspace = true }
+llimphi-widget-toast = { workspace = true }
+llimphi-icons = { workspace = true }
llimphi-motion = { workspace = true }
app-bus = { workspace = true }
+rimay-localize = { workspace = true }
[[bin]]
name = "chasqui-broker-explorer-llimphi"
path = "src/main.rs"
+
+[dev-dependencies]
+# Sólo para el example `chasqui_showreel` (volcado headless a PNG, sin winit).
+pollster = { workspace = true }
+png = { workspace = true }
diff --git a/02_ruway/chasqui/chasqui-broker-explorer-llimphi/examples/chasqui_showreel.rs b/02_ruway/chasqui/chasqui-broker-explorer-llimphi/examples/chasqui_showreel.rs
new file mode 100644
index 0000000..cff68d2
--- /dev/null
+++ b/02_ruway/chasqui/chasqui-broker-explorer-llimphi/examples/chasqui_showreel.rs
@@ -0,0 +1,841 @@
+//! **Showreel** de `chasqui` — la capa de red / broker P2P soberano sobre
+//! Cards (brahman). NO es eye-candy abstracto: cada frame reconstruye el
+//! **chrome real** del probe del broker (`chasqui-broker-explorer-llimphi`):
+//! menubar + app-header con la línea de probe + banner de salud + tres
+//! `stat_card` (Estado · Sesiones activas · Timeline de matches) + las filas
+//! del timeline formateadas con `format_timeline_entry` REAL — todo con los
+//! MISMOS widgets que pinta la app en producción (`menubar_view`,
+//! `app_header`, `banner_view`, `stat_card_view`).
+//!
+//! El **estado** se deriva del tiempo normalizado `t∈[0,1]`: el chrome hace
+//! slide-in; la salud del broker recorre DOWN → UP/NO PROVIDER → UP/PROVIDER;
+//! las sesiones (peers) entran con stagger en la card de sesiones; y el
+//! timeline de matches se llena fila a fila — consumidor ← productor
+//! apareciendo en vivo, que es la imagen de "peers que se enganchan por flow".
+//! Cierra con el wordmark **chasqui**.
+//!
+//! Render headless y determinista (sin reloj, sin runtime, sin winit): frame
+//! `i` de `N` → `t = i/(N-1)` → View → layout (taffy + parley) → vello::Scene
+//! → wgpu → PNG. Idéntico al eventloop.
+//!
+//! ```text
+//! cargo run -p chasqui-broker-explorer-llimphi --example chasqui_showreel \
+//! --release -- [out_dir] [n_frames] [W] [H]
+//! ```
+//! Defaults: `out_dir=showreel_frames_chasqui`, `n_frames=300`, `W=1600`, `H=900`.
+#![allow(dead_code)]
+
+use std::fs::{create_dir_all, File};
+use std::io::BufWriter;
+use std::sync::Arc;
+use std::time::{Duration, SystemTime, UNIX_EPOCH};
+
+use app_bus::{AppMenu, Menu, MenuItem};
+use card_handshake::health::TimelineEntry;
+use card_handshake::messages::MatchEventKind;
+use chasqui_broker::MatchStrategy;
+use llimphi_motion::motion;
+use llimphi_theme::Theme;
+use llimphi_ui::llimphi_hal::{wgpu, Hal};
+use llimphi_ui::llimphi_layout::taffy::{
+ self,
+ prelude::{length, percent, Dimension, FlexDirection, Size, Style},
+ style::Position,
+ AlignItems, Rect,
+};
+use llimphi_ui::llimphi_layout::LayoutTree;
+use llimphi_ui::llimphi_raster::peniko::{self, Color};
+use llimphi_ui::llimphi_raster::vello::kurbo::{Affine, BezPath, Circle, Point, Stroke};
+use llimphi_ui::llimphi_raster::{vello, Renderer};
+use llimphi_ui::llimphi_text::{draw_layout_brush_xf, measurement, Alignment, Typesetter};
+use llimphi_ui::{measure_text_node, mount, paint, Mounted, PaintRect, View};
+
+use llimphi_widget_app_header::{app_header, AppHeaderPalette};
+use llimphi_widget_banner::{banner_view, BannerKind};
+use llimphi_widget_menubar::{menubar_view, MenuBarSpec, DEFAULT_HEIGHT as MENU_H};
+use llimphi_widget_stat_card::{stat_card_view, StatCardPalette};
+
+const FMT: wgpu::TextureFormat = wgpu::TextureFormat::Rgba8Unorm;
+
+/// Msg fantasma: el showreel no despacha eventos, pero los widgets reales
+/// exigen un Msg `Clone + 'static`.
+#[derive(Clone)]
+enum Msg {
+ Nada,
+}
+
+// ───────────────────────── utilidades ─────────────────────────
+
+fn with_alpha(c: Color, a: f32) -> Color {
+ let [r, g, b, _] = c.components;
+ Color::new([r, g, b, a.clamp(0.0, 1.0)])
+}
+
+fn lerp(a: f64, b: f64, t: f64) -> f64 {
+ a + (b - a) * t
+}
+
+/// Reescala `t` desde el subintervalo `[lo,hi]` a `[0,1]`, clampado.
+fn seg(t: f32, lo: f32, hi: f32) -> f32 {
+ ((t - lo) / (hi - lo)).clamp(0.0, 1.0)
+}
+
+// ───────────────────────── skin ─────────────────────────
+
+#[derive(Clone)]
+struct Skin {
+ theme: Theme,
+ accent: Color,
+ bg: Color,
+ fg: Color,
+ fg_muted: Color,
+ // Acentos por estado del probe (espejo de la app real).
+ accent_up: Color,
+ accent_partial: Color,
+ accent_down: Color,
+ accent_pending: Color,
+}
+
+// ───────────────────────── datos sintéticos (forma real) ─────────────────────────
+
+/// Una "sesión" (peer) registrada en el broker, con sus flows in/out — la
+/// misma forma que `SessionEntry` produce en la card de sesiones real.
+struct Peer {
+ label: &'static str,
+ inputs: &'static [&'static str],
+ outputs: &'static [&'static str],
+ conscious: bool,
+}
+
+const PEERS: &[Peer] = &[
+ Peer {
+ label: "chasqui-nous",
+ inputs: &["doc-ingest:json"],
+ outputs: &["monad-list:json", "event-log:tail"],
+ conscious: true,
+ },
+ Peer {
+ label: "pluma-app",
+ inputs: &["monad-list:json"],
+ outputs: &["doc-ingest:json"],
+ conscious: false,
+ },
+ Peer {
+ label: "nahual-shell",
+ inputs: &["monad-list:json", "thumb:png"],
+ outputs: &[],
+ conscious: false,
+ },
+ Peer {
+ label: "shuma-term",
+ inputs: &["event-log:tail"],
+ outputs: &["cmd-run:json"],
+ conscious: false,
+ },
+ Peer {
+ label: "khipu",
+ inputs: &[],
+ outputs: &["thumb:png"],
+ conscious: true,
+ },
+];
+
+/// Formatea una entrada de sesión igual que la app real (label · in/out · wit).
+fn fmt_peer(p: &Peer) -> String {
+ format!(
+ "{} · in:[{}] out:[{}]{}",
+ p.label,
+ p.inputs.join(","),
+ p.outputs.join(","),
+ if p.conscious { " (wit)" } else { "" }
+ )
+}
+
+/// Matches que el broker va "descubriendo" — consumidor ← productor por flow.
+/// `(consumer_label, flow, producer_label, flow, via, pinned)`.
+struct MatchSeed {
+ consumer_label: &'static str,
+ flow: &'static str,
+ producer_label: &'static str,
+ via: MatchStrategy,
+ pinned: bool,
+}
+
+const MATCHES: &[MatchSeed] = &[
+ MatchSeed {
+ consumer_label: "pluma-app",
+ flow: "monad-list:json",
+ producer_label: "chasqui-nous",
+ via: MatchStrategy::Exact,
+ pinned: true,
+ },
+ MatchSeed {
+ consumer_label: "nahual-shell",
+ flow: "monad-list:json",
+ producer_label: "chasqui-nous",
+ via: MatchStrategy::Exact,
+ pinned: false,
+ },
+ MatchSeed {
+ consumer_label: "chasqui-nous",
+ flow: "doc-ingest:json",
+ producer_label: "pluma-app",
+ via: MatchStrategy::Exact,
+ pinned: false,
+ },
+ MatchSeed {
+ consumer_label: "nahual-shell",
+ flow: "thumb:png",
+ producer_label: "khipu",
+ via: MatchStrategy::Structural,
+ pinned: false,
+ },
+ MatchSeed {
+ consumer_label: "shuma-term",
+ flow: "event-log:tail",
+ producer_label: "chasqui-nous",
+ via: MatchStrategy::Exact,
+ pinned: false,
+ },
+];
+
+/// Convierte un seed en `TimelineEntry` real (kind=Available) con un `at`
+/// determinista escalonado, para reusar el formateo idéntico al de la app.
+fn timeline_entry(seed: &MatchSeed, idx: usize) -> TimelineEntry {
+ // Base fija (no usa el reloj real → determinista): 14:32:10 + idx*7s.
+ let base = UNIX_EPOCH + Duration::from_secs(52_330 + idx as u64 * 7);
+ TimelineEntry {
+ at: base,
+ kind: MatchEventKind::Available,
+ consumer_label: seed.consumer_label.to_string(),
+ consumer_flow: seed.flow.to_string(),
+ producer_label: seed.producer_label.to_string(),
+ producer_flow: seed.flow.to_string(),
+ via: seed.via,
+ pinned: seed.pinned,
+ }
+}
+
+/// Espejo EXACTO de `format_timeline_entry` del binario `src/main.rs` —
+/// no podemos importarlo (es un binario sin lib), así que lo replicamos
+/// carácter a carácter para que las filas se vean idénticas a la app.
+fn format_timeline_entry(e: &TimelineEntry) -> String {
+ let secs_today = e
+ .at
+ .duration_since(SystemTime::UNIX_EPOCH)
+ .map(|d| d.as_secs() % 86_400)
+ .unwrap_or(0);
+ let h = secs_today / 3600;
+ let m = (secs_today % 3600) / 60;
+ let s = secs_today % 60;
+ let kind = match e.kind {
+ MatchEventKind::Available => "+",
+ MatchEventKind::Lost => "-",
+ };
+ let pinned = if e.pinned { " (pinned)" } else { "" };
+ match e.kind {
+ MatchEventKind::Available => format!(
+ "{:02}:{:02}:{:02} {} {}.{} ← {}.{} [{:?}]{}",
+ h,
+ m,
+ s,
+ kind,
+ e.consumer_label,
+ e.consumer_flow,
+ e.producer_label,
+ e.producer_flow,
+ e.via,
+ pinned,
+ ),
+ MatchEventKind::Lost => format!(
+ "{:02}:{:02}:{:02} {} ?.{} ← ?.{} (lost)",
+ h, m, s, kind, e.consumer_flow, e.producer_flow,
+ ),
+ }
+}
+
+// ───────────────────────── chrome real ─────────────────────────
+
+/// Menú real del probe (espejo de `app_menu` del binario).
+fn app_menu() -> AppMenu {
+ AppMenu::new()
+ .menu(
+ Menu::new("Archivo")
+ .item(MenuItem::new("Refrescar probe", "file.refresh").shortcut("Ctrl+R"))
+ .item(MenuItem::new("Limpiar timeline", "file.clear"))
+ .item(MenuItem::new("Salir", "file.quit").shortcut("Ctrl+Q").separated()),
+ )
+ .menu(
+ Menu::new("Ver")
+ .item(MenuItem::new("Reconectar", "view.reconnect"))
+ .item(MenuItem::new("Cambiar tema", "view.theme").separated()),
+ )
+ .menu(Menu::new("Ayuda").item(MenuItem::new("Acerca de", "help.about")))
+}
+
+fn menubar(cw: f64, ch: f64, s: &Skin) -> View<Msg> {
+ let menu = app_menu();
+ menubar_view(&MenuBarSpec {
+ menu: &menu,
+ open: None,
+ theme: &s.theme,
+ viewport: (cw as f32, ch as f32),
+ height: MENU_H,
+ on_open: Arc::new(|_| Msg::Nada),
+ on_command: Arc::new(|_: &str| Msg::Nada),
+ })
+}
+
+/// Fase de salud del broker derivada de `t` — recorre los tres estados
+/// reales que el probe reporta.
+#[derive(Clone, Copy, PartialEq)]
+enum Health {
+ Pending,
+ Down,
+ UpNoProvider,
+ UpProvider,
+}
+
+fn health_at(t: f32) -> Health {
+ if t < 0.20 {
+ Health::Pending
+ } else if t < 0.34 {
+ Health::Down
+ } else if t < 0.46 {
+ Health::UpNoProvider
+ } else {
+ Health::UpProvider
+ }
+}
+
+fn health_banner(h: Health) -> Option<View<Msg>> {
+ match h {
+ Health::Pending => None,
+ Health::Down => Some(banner_view::<Msg>(
+ BannerKind::Error,
+ "Broker DOWN — connect failed (init socket no escucha)".to_string(),
+ )),
+ Health::UpNoProvider => Some(banner_view::<Msg>(
+ BannerKind::Warning,
+ "Broker UP, sin provider para el flow".to_string(),
+ )),
+ Health::UpProvider => Some(banner_view::<Msg>(
+ BannerKind::Success,
+ "Broker UP, provider matcheado".to_string(),
+ )),
+ }
+}
+
+fn state_card_params(h: Health, s: &Skin) -> (Color, String, String) {
+ match h {
+ Health::Pending => (
+ s.accent_pending,
+ "PENDING".into(),
+ "esperando primer probe…".into(),
+ ),
+ Health::Down => (
+ s.accent_down,
+ "DOWN".into(),
+ "connect failed: init socket no responde".into(),
+ ),
+ Health::UpNoProvider => (
+ s.accent_partial,
+ "UP / NO PROVIDER".into(),
+ "broker reachable; sin productor para flow `monad-list:json`".into(),
+ ),
+ Health::UpProvider => (
+ s.accent_up,
+ "UP / PROVIDER".into(),
+ "flow `monad-list:json` matcheado en chasqui-nous.sock".into(),
+ ),
+ }
+}
+
+/// Fila del timeline (espejo de la fila real en `view()`): texto monoespaciado
+/// con la entry formateada, la última resaltada como "recién llegada".
+fn timeline_row(text: String, selected: bool, s: &Skin) -> View<Msg> {
+ let mut row = View::new(Style {
+ size: Size {
+ width: percent(1.0_f32),
+ height: length(20.0_f32),
+ },
+ padding: Rect {
+ left: length(10.0_f32),
+ right: length(8.0_f32),
+ top: length(0.0_f32),
+ bottom: length(0.0_f32),
+ },
+ align_items: Some(AlignItems::Center),
+ flex_shrink: 0.0,
+ ..Default::default()
+ })
+ .text_aligned(text, 12.0, s.theme.fg_text, Alignment::Start);
+ if selected {
+ row = row.fill(s.theme.bg_selected);
+ }
+ row
+}
+
+// ───────────────────────── overlays vector (cold-open + wordmark) ─────────────────────────
+
+fn signature_path(cw: f64, ch: f64) -> BezPath {
+ let cx = cw / 2.0;
+ let cy = ch / 2.0;
+ let mut p = BezPath::new();
+ p.move_to((cx - 360.0, cy + 40.0));
+ p.curve_to(
+ (cx - 150.0, cy - 220.0),
+ (cx + 150.0, cy + 220.0),
+ (cx + 360.0, cy - 40.0),
+ );
+ p
+}
+
+fn trim_path(full: &BezPath, prog: f64) -> (BezPath, Point) {
+ use vello::kurbo::ParamCurve;
+ let prog = prog.clamp(0.0, 1.0);
+ let mut cubic = None;
+ let mut start = Point::ZERO;
+ for el in full.elements() {
+ match el {
+ vello::kurbo::PathEl::MoveTo(p) => start = *p,
+ vello::kurbo::PathEl::CurveTo(c1, c2, p) => {
+ cubic = Some(vello::kurbo::CubicBez::new(start, *c1, *c2, *p));
+ }
+ _ => {}
+ }
+ }
+ let mut out = BezPath::new();
+ let mut head = start;
+ if let Some(cb) = cubic {
+ out.move_to(cb.p0);
+ let steps = 96;
+ for i in 1..=steps {
+ let u = (i as f64 / steps as f64) * prog;
+ let pt = cb.eval(u);
+ out.line_to(pt);
+ head = pt;
+ }
+ }
+ (out, head)
+}
+
+fn draw_overlays(scene: &mut vello::Scene, ts: &mut Typesetter, t: f32, cw: f64, ch: f64, s: &Skin) {
+ // ── COLD OPEN (0–11%) ──────────────────────────────────────────
+ let b1 = seg(t, 0.0, 0.10);
+ let line_vis = 1.0 - seg(t, 0.10, 0.17);
+ if line_vis > 0.001 {
+ let path = signature_path(cw, ch);
+ let draw_on = motion::ease_out_cubic(seg(t, 0.01, 0.11)) as f64;
+ let (trimmed, head) = trim_path(&path, draw_on);
+ let line_col = with_alpha(s.accent, 0.9 * line_vis);
+ scene.stroke(&Stroke::new(2.0), Affine::IDENTITY, line_col, None, &trimmed);
+ let pop = motion::ease_out_back(b1);
+ let r = (4.0 + 7.0 * pop as f64).max(0.0);
+ let dot_a = (b1 * line_vis).clamp(0.0, 1.0);
+ scene.fill(
+ peniko::Fill::NonZero,
+ Affine::IDENTITY,
+ with_alpha(s.accent, 0.18 * dot_a),
+ None,
+ &Circle::new(head, r * 3.2),
+ );
+ scene.fill(
+ peniko::Fill::NonZero,
+ Affine::IDENTITY,
+ with_alpha(s.accent, dot_a),
+ None,
+ &Circle::new(head, r),
+ );
+ }
+
+ // ── WORDMARK (84–100%) ─────────────────────────────────────────
+ let word_in = seg(t, 0.86, 0.96);
+ let word_a = motion::ease_out_cubic(word_in);
+ if word_a > 0.001 {
+ let size = 140.0_f32;
+ let layout = ts.layout(
+ "chasqui", size, None, Alignment::Start, 1.0, false, None, 800.0, false, false, 0.0, 0.0,
+ );
+ let m = measurement(&layout);
+ let rise = lerp(24.0, 0.0, word_a as f64);
+ let ox = (cw - m.width as f64) / 2.0;
+ let oy = (ch - m.height as f64) / 2.0 - 18.0 + rise;
+ let brush = peniko::Brush::Solid(with_alpha(s.fg, word_a));
+ draw_layout_brush_xf(scene, &layout, &brush, Affine::translate((ox, oy)));
+
+ let sub_a = motion::ease_out_cubic(seg(t, 0.90, 1.0));
+ if sub_a > 0.001 {
+ let ssz = 26.0_f32;
+ let sub = ts.layout(
+ "sovereign P2P networking, in Rust",
+ ssz,
+ None,
+ Alignment::Start,
+ 1.0,
+ false,
+ None,
+ 400.0,
+ false,
+ false, 0.0, 0.0,
+ );
+ let sm = measurement(&sub);
+ let dot_r = 6.0;
+ let block_w = sm.width as f64 + dot_r * 2.0 + 14.0;
+ let sx = (cw - block_w) / 2.0;
+ let sy = oy + m.height as f64 + 18.0;
+ scene.fill(
+ peniko::Fill::NonZero,
+ Affine::IDENTITY,
+ with_alpha(s.accent, sub_a),
+ None,
+ &Circle::new(Point::new(sx + dot_r, sy + ssz as f64 * 0.42), dot_r as f64),
+ );
+ let sbrush = peniko::Brush::Solid(with_alpha(s.fg_muted, sub_a));
+ draw_layout_brush_xf(
+ scene,
+ &sub,
+ &sbrush,
+ Affine::translate((sx + dot_r * 2.0 + 14.0, sy)),
+ );
+ }
+ }
+
+ // ── punto teal de firma (esquina inf-der) ───────
+ let corner_a = seg(t, 0.04, 0.12) * (1.0 - seg(t, 0.82, 0.88));
+ if corner_a > 0.001 {
+ let cx = cw - 54.0;
+ let cy = ch - 54.0;
+ scene.fill(
+ peniko::Fill::NonZero,
+ Affine::IDENTITY,
+ with_alpha(s.accent, 0.16 * corner_a),
+ None,
+ &Circle::new(Point::new(cx, cy), 18.0),
+ );
+ scene.fill(
+ peniko::Fill::NonZero,
+ Affine::IDENTITY,
+ with_alpha(s.accent, 0.9 * corner_a),
+ None,
+ &Circle::new(Point::new(cx, cy), 6.0),
+ );
+ }
+}
+
+// ───────────────────────── la escena por frame ─────────────────────────
+
+fn build_view(t: f32, cw: f64, ch: f64, s: &Skin) -> View<Msg> {
+ // ── timeline de animación ──
+ // chrome slide-in (11–22%): menubar + header.
+ let chrome = motion::ease_out_cubic(seg(t, 0.11, 0.22));
+ // salud del broker (derivada por umbrales).
+ let health = health_at(t);
+ // sesiones (peers) entran con stagger una vez que el broker está UP (34–58%).
+ let peers_reveal = motion::ease_out_cubic(seg(t, 0.34, 0.58));
+ // matches del timeline aparecen fila a fila (46–80%) — sólo con provider.
+ let matches_reveal = motion::ease_out_cubic(seg(t, 0.46, 0.80));
+ // fade del chrome antes del wordmark (82–88%).
+ let chrome_fade = 1.0 - seg(t, 0.82, 0.88);
+
+ let mut children: Vec<View<Msg>> = Vec::new();
+
+ if chrome_fade > 0.001 {
+ let menubar = menubar(cw, ch, s);
+
+ // header con la línea de probe real.
+ let header_palette = AppHeaderPalette::from_theme(&s.theme);
+ let reload_ms = 4 + ((t * 90.0) as u32 % 9);
+ let header_text = format!(
+ "Probe: {}/init.sock · flow: broker-health/ping · reload {} ms",
+ "$XDG_RUNTIME_DIR", reload_ms
+ );
+ let header = app_header::<Msg>(header_text, vec![], &header_palette);
+
+ // ── cuerpo ──
+ let stat_palette = StatCardPalette::from_theme(&s.theme);
+ let mut body_children: Vec<View<Msg>> = Vec::new();
+
+ // banner permanente con la salud actual.
+ if let Some(b) = health_banner(health) {
+ body_children.push(b);
+ }
+
+ // card de Estado.
+ let (state_accent, state_value, state_descr) = state_card_params(health, s);
+ body_children.push(stat_card_view::<Msg>(
+ "Estado",
+ state_value,
+ &state_descr,
+ state_accent,
+ &[],
+ &stat_palette,
+ ));
+
+ // card de Sesiones activas (peers) — los items entran con stagger.
+ let n_peers_up = matches!(
+ health,
+ Health::UpNoProvider | Health::UpProvider
+ )
+ .then(|| ((PEERS.len() as f32) * peers_reveal).ceil() as usize)
+ .unwrap_or(0)
+ .min(PEERS.len());
+ // Listamos hasta 3 peers (los "recientes") para dejar aire al
+ // timeline de matches debajo — el contador refleja el total real.
+ let shown = n_peers_up.min(3);
+ let peer_items: Vec<String> = PEERS[..shown].iter().map(fmt_peer).collect();
+ let sessions_value = if n_peers_up == 0 {
+ "—".to_string()
+ } else {
+ n_peers_up.to_string()
+ };
+ let sessions_descr = if n_peers_up == 0 {
+ "lista no disponible (broker DOWN o pendiente)".to_string()
+ } else {
+ "labels visibles + flows in/out · (wit) = consciente".to_string()
+ };
+ body_children.push(stat_card_view::<Msg>(
+ "Sesiones activas",
+ sessions_value,
+ &sessions_descr,
+ s.accent_up,
+ &peer_items,
+ &stat_palette,
+ ));
+
+ // card de Timeline de matches (cabecera contador) — sólo con provider.
+ let n_matches = if health == Health::UpProvider {
+ (((MATCHES.len()) as f32) * matches_reveal).ceil() as usize
+ } else {
+ 0
+ }
+ .min(MATCHES.len());
+ let timeline_value = n_matches.to_string();
+ let timeline_descr = if n_matches == 0 {
+ "esperando primer match…".to_string()
+ } else {
+ "click selecciona · right-click = menú · cap 50 entries".to_string()
+ };
+ body_children.push(stat_card_view::<Msg>(
+ "Timeline de matches",
+ timeline_value,
+ &timeline_descr,
+ s.accent_partial,
+ &[],
+ &stat_palette,
+ ));
+
+ // filas del timeline: consumidor ← productor, la última resaltada.
+ for i in 0..n_matches {
+ let entry = timeline_entry(&MATCHES[i], i);
+ let txt = format_timeline_entry(&entry);
+ let is_last = i + 1 == n_matches && matches_reveal < 1.0;
+ body_children.push(timeline_row(txt, is_last, s));
+ }
+
+ let body = View::new(Style {
+ flex_direction: FlexDirection::Column,
+ size: Size {
+ width: percent(1.0_f32),
+ height: Dimension::auto(),
+ },
+ flex_grow: 1.0,
+ padding: Rect {
+ left: length(16.0_f32),
+ right: length(16.0_f32),
+ top: length(12.0_f32),
+ bottom: length(16.0_f32),
+ },
+ gap: Size {
+ width: length(0.0_f32),
+ height: length(8.0_f32),
+ },
+ ..Default::default()
+ })
+ .fill(s.theme.bg_app)
+ .children(body_children);
+
+ // slide-in vertical del chrome completo.
+ let dy = lerp(-22.0, 0.0, chrome as f64);
+ let chrome_view = View::new(Style {
+ flex_direction: FlexDirection::Column,
+ size: Size {
+ width: percent(1.0_f32),
+ height: percent(1.0_f32),
+ },
+ ..Default::default()
+ })
+ .fill(s.theme.bg_app)
+ .alpha((chrome * chrome_fade).clamp(0.0, 1.0))
+ .transform(Affine::translate((0.0, dy)))
+ .children(vec![menubar, header, body]);
+ children.push(chrome_view);
+ }
+
+ // overlay full-screen del vector (cold-open + wordmark).
+ let overlay = View::new(Style {
+ position: Position::Absolute,
+ inset: Rect {
+ left: length(0.0),
+ top: length(0.0),
+ right: length(0.0),
+ bottom: length(0.0),
+ },
+ size: Size {
+ width: percent(1.0_f32),
+ height: percent(1.0_f32),
+ },
+ ..Default::default()
+ })
+ .paint_with({
+ let s = s.clone();
+ move |scene, ts, _rect: PaintRect| {
+ draw_overlays(scene, ts, t, cw, ch, &s);
+ }
+ });
+ children.push(overlay);
+
+ View::new(Style {
+ size: Size {
+ width: percent(1.0_f32),
+ height: percent(1.0_f32),
+ },
+ position: Position::Relative,
+ ..Default::default()
+ })
+ .fill(s.bg)
+ .children(children)
+}
+
+fn main() {
+ let mut args = std::env::args().skip(1);
+ let out_dir = args.next().unwrap_or_else(|| "showreel_frames_chasqui".to_string());
+ let n: usize = args.next().and_then(|v| v.parse().ok()).unwrap_or(300);
+ let w: u32 = args.next().and_then(|v| v.parse().ok()).unwrap_or(1600);
+ let h: u32 = args.next().and_then(|v| v.parse().ok()).unwrap_or(900);
+ create_dir_all(&out_dir).expect("mkdir out_dir");
+
+ let theme = Theme::dark();
+ let accent = Color::from_rgba8(0x2B, 0xD9, 0xA6, 0xFF); // teal firma
+ let skin = Skin {
+ accent,
+ bg: theme.bg_app,
+ fg: theme.fg_text,
+ fg_muted: theme.fg_muted,
+ // mismos acentos por estado que la app real.
+ accent_up: Color::from_rgba8(0xa3, 0xbe, 0x8c, 0xff),
+ accent_partial: Color::from_rgba8(0xeb, 0xcb, 0x8b, 0xff),
+ accent_down: Color::from_rgba8(0xbf, 0x61, 0x6a, 0xff),
+ accent_pending: Color::from_rgba8(0x6a, 0x72, 0x80, 0xff),
+ theme,
+ };
+
+ let [br, bg, bb, _] = skin.bg.components;
+ let base = Color::from_rgba8((br * 255.0) as u8, (bg * 255.0) as u8, (bb * 255.0) as u8, 255);
+
+ // GPU una sola vez; reusar device/renderer/target para los N frames.
+ let hal = pollster::block_on(Hal::new(None)).expect("hal");
+ let mut renderer = Renderer::new(&hal).expect("renderer");
+ let target = hal.device.create_texture(&wgpu::TextureDescriptor {
+ label: Some("showreel-chasqui"),
+ size: wgpu::Extent3d { width: w, height: h, depth_or_array_layers: 1 },
+ mip_level_count: 1,
+ sample_count: 1,
+ dimension: wgpu::TextureDimension::D2,
+ format: FMT,
+ usage: wgpu::TextureUsages::STORAGE_BINDING
+ | wgpu::TextureUsages::RENDER_ATTACHMENT
+ | wgpu::TextureUsages::COPY_SRC,
+ view_formats: &[],
+ });
+ let view = target.create_view(&wgpu::TextureViewDescriptor::default());
+
+ let mut ts = Typesetter::new();
+ let cw = w as f64;
+ let ch = h as f64;
+
+ for i in 0..n {
+ let t = if n <= 1 { 0.0 } else { i as f32 / (n as f32 - 1.0) };
+ let root = build_view(t, cw, ch, &skin);
+
+ let mut layout = LayoutTree::new();
+ let mounted: Mounted<Msg> = mount(&mut layout, root);
+ let computed = {
+ let tmap = &mounted.text_measures;
+ layout
+ .compute_with_measure(mounted.root, (w as f32, h as f32), |nid, known, avail| {
+ match tmap.get(&nid) {
+ Some(tm) => measure_text_node(&mut ts, tm, known, avail),
+ None => taffy::Size::ZERO,
+ }
+ })
+ .expect("layout")
+ };
+ let mut scene = vello::Scene::new();
+ paint(&mut scene, &mounted, &computed, &mut ts, None, None);
+
+ renderer
+ .render_to_view(&hal, &scene, &view, w, h, base)
+ .expect("render_to_view");
+ let path = format!("{out_dir}/frame_{i:04}.png");
+ write_png(&hal, &target, &path, w, h);
+ if i % 30 == 0 || i == n - 1 {
+ eprintln!("showreel-chasqui: frame {}/{} (t={:.3})", i + 1, n, t);
+ }
+ }
+ eprintln!("showreel-chasqui: {n} frames en {out_dir}/ ({w}x{h})");
+}
+
+fn write_png(hal: &Hal, target: &wgpu::Texture, path: &str, w: u32, h: u32) {
+ let unpadded = (w * 4) as usize;
+ let align = wgpu::COPY_BYTES_PER_ROW_ALIGNMENT as usize;
+ let padded = unpadded.div_ceil(align) * align;
+ let buf = hal.device.create_buffer(&wgpu::BufferDescriptor {
+ label: Some("readback"),
+ size: (padded * h as usize) as u64,
+ usage: wgpu::BufferUsages::MAP_READ | wgpu::BufferUsages::COPY_DST,
+ mapped_at_creation: false,
+ });
+ let mut enc = hal
+ .device
+ .create_command_encoder(&wgpu::CommandEncoderDescriptor { label: None });
+ enc.copy_texture_to_buffer(
+ wgpu::TexelCopyTextureInfo {
+ texture: target,
+ mip_level: 0,
+ origin: wgpu::Origin3d::ZERO,
+ aspect: wgpu::TextureAspect::All,
+ },
+ wgpu::TexelCopyBufferInfo {
+ buffer: &buf,
+ layout: wgpu::TexelCopyBufferLayout {
+ offset: 0,
+ bytes_per_row: Some(padded as u32),
+ rows_per_image: Some(h),
+ },
+ },
+ wgpu::Extent3d { width: w, height: h, depth_or_array_layers: 1 },
+ );
+ hal.queue.submit(std::iter::once(enc.finish()));
+ let slice = buf.slice(..);
+ let (tx, rx) = std::sync::mpsc::channel();
+ slice.map_async(wgpu::MapMode::Read, move |r| {
+ let _ = tx.send(r);
+ });
+ let _ = hal.device.poll(wgpu::PollType::wait_indefinitely());
+ rx.recv().unwrap().unwrap();
+ let data = slice.get_mapped_range();
+ let mut pixels = Vec::with_capacity((w * h * 4) as usize);
+ for r in 0..h as usize {
+ let sidx = r * padded;
+ pixels.extend_from_slice(&data[sidx..sidx + unpadded]);
+ }
+ drop(data);
+ buf.unmap();
+ let file = File::create(path).expect("png");
+ let mut enc = png::Encoder::new(BufWriter::new(file), w, h);
+ enc.set_color(png::ColorType::Rgba);
+ enc.set_depth(png::BitDepth::Eight);
+ let mut wr = enc.write_header().unwrap();
+ wr.write_image_data(&pixels).unwrap();
+}
diff --git a/02_ruway/chasqui/chasqui-broker-explorer-llimphi/src/main.rs b/02_ruway/chasqui/chasqui-broker-explorer-llimphi/src/main.rs
index 0229101..38d1a6d 100644
--- a/02_ruway/chasqui/chasqui-broker-explorer-llimphi/src/main.rs
+++ b/02_ruway/chasqui/chasqui-broker-explorer-llimphi/src/main.rs
@@ -20,13 +20,14 @@
//! - `BRAHMAN_BROKER_PROBE_TYPE` — type name del flow probe
//! (default `ping`).
//!
-//! Usá un type name probable (ej. `monad-list:json`,
+//! Usa un type name probable (ej. `monad-list:json`,
//! `event-log:tail`) para detectar productores específicos del
//! ecosistema.
#![forbid(unsafe_code)]
use std::collections::{HashSet, VecDeque};
+use std::hash::{Hash, Hasher};
use std::path::PathBuf;
use std::sync::Arc;
use std::time::{Duration, Instant};
@@ -56,9 +57,15 @@ use llimphi_widget_menubar::{
DEFAULT_HEIGHT as MENU_H,
};
use llimphi_widget_stat_card::{stat_card_view, StatCardPalette};
+use llimphi_widget_skeleton::{skeleton_view, SkeletonPalette};
+use llimphi_widget_empty::{empty_view, EmptyPalette};
+use llimphi_widget_toast::{toast_stack_view, Toast};
+use llimphi_icons::Icon;
+#[cfg(test)]
use ulid::Ulid;
use app_bus::{AppMenu, Menu, MenuItem};
+use rimay_localize::{t, t_args};
const POLL_INTERVAL: Duration = Duration::from_secs(5);
const PROBE_TIMEOUT: Duration = Duration::from_secs(1);
@@ -67,6 +74,18 @@ const PROBE_TIMEOUT: Duration = Duration::from_secs(1);
/// más viejo se descarta. 50 cubre ~4 minutos de actividad densa.
const TIMELINE_CAP: usize = 50;
+/// Cuánto vive un toast efímero antes de auto-descartarse.
+const TOAST_TTL: Duration = Duration::from_secs(4);
+
+/// Hash estable de una cadena → `key` para animaciones implícitas
+/// (la misma entry produce siempre la misma key entre rebuilds, así el
+/// pop-in sólo anima la primera aparición).
+fn key_of(s: &str) -> u64 {
+ let mut h = std::collections::hash_map::DefaultHasher::new();
+ s.hash(&mut h);
+ h.finish()
+}
+
#[derive(Clone, Debug)]
enum ProbeState {
Pending,
@@ -75,19 +94,10 @@ enum ProbeState {
UpWithProvider { flow: String, producer_socket: PathBuf },
}
-#[derive(Clone, Debug)]
-struct TimelineEntry {
- at: std::time::SystemTime,
- kind: card_handshake::messages::MatchEventKind,
- consumer_label: String,
- consumer_flow: String,
- producer_label: String,
- producer_flow: String,
- via: chasqui_broker::MatchStrategy,
- pinned: bool,
-}
-
-type MatchKey = (Ulid, String, Ulid, String);
+// El diff de salud del broker (TimelineEntry/MatchKey/diff_matches) vive en el
+// core agnóstico `card_handshake::health` (Regla 2): observar la diff de matches
+// entre ticks es lógica reusable, no exclusiva de este frontend.
+use card_handshake::health::{diff_matches, MatchKey, TimelineEntry};
struct Model {
theme: Theme,
@@ -113,6 +123,14 @@ struct Model {
/// Menú contextual sobre una entry: `(idx, x, y)` ancla en ventana.
/// `None` cerrado.
context_menu: Option<(usize, f32, f32)>,
+ /// Toasts efímeros vivos (errores del probe, confirmaciones de
+ /// acciones del usuario).
+ toasts: Vec<Toast>,
+ /// Id incremental para correlacionar toast ↔ `Msg` de expiración.
+ next_toast: u64,
+ /// Hay una cadena de `Msg::Shimmer` en vuelo (evita rearmar dos);
+ /// sólo corre mientras el probe está en estado `Pending`.
+ shimmering: bool,
}
#[derive(Clone)]
@@ -146,6 +164,12 @@ enum Msg {
ContextMenuOpen(f32, f32),
/// Limpia el timeline acumulado.
ClearTimeline,
+ /// Un toast cumplió su `duration`: se descarta del stack.
+ ToastExpire(u64),
+ /// Tick de animación del shimmer del skeleton — fuerza repaint
+ /// mientras el probe está `Pending`. Se auto-rearma sólo si sigue
+ /// cargando, así no queda un loop de repaint ocioso.
+ Shimmer,
}
struct Explorer;
@@ -163,6 +187,7 @@ impl App for Explorer {
}
fn init(handle: &Handle<Msg>) -> Model {
+ rimay_localize::init();
let flow = std::env::var("BRAHMAN_BROKER_PROBE_FLOW")
.unwrap_or_else(|_| "broker-health".to_string());
let type_name = std::env::var("BRAHMAN_BROKER_PROBE_TYPE")
@@ -171,7 +196,7 @@ impl App for Explorer {
handle.dispatch(Msg::Tick);
handle.spawn_periodic(POLL_INTERVAL, || Msg::Tick);
- Model {
+ let mut m = Model {
theme: Theme::dark(),
socket_path: transport::default_socket_path(),
flow,
@@ -186,7 +211,14 @@ impl App for Explorer {
menu_anim: Tween::idle(1.0),
selected: None,
context_menu: None,
- }
+ toasts: Vec::new(),
+ next_toast: 0,
+ shimmering: false,
+ };
+ // Mientras esperamos el primer probe (estado `Pending`) corre el
+ // shimmer del skeleton del timeline.
+ ensure_shimmer(&mut m, handle);
+ m
}
fn on_key(model: &Model, event: &KeyEvent) -> Option<Msg> {
@@ -217,7 +249,30 @@ impl App for Explorer {
handle.spawn(move || run_probe(flow, type_name));
}
Msg::ProbeResult { state, sessions, matches, elapsed_ms } => {
+ // Toast sólo en la transición de estado (no en cada tick de
+ // 5 s con el mismo estado), para no spamear.
+ let changed =
+ std::mem::discriminant(&m.state) != std::mem::discriminant(&state);
m.state = state;
+ if changed {
+ let toast = match &m.state {
+ ProbeState::Down { reason } => Some(Toast::error(
+ m.next_toast,
+ t_args("chasqui-broker-down", &[("reason", reason.clone().into())]),
+ TOAST_TTL,
+ )),
+ ProbeState::UpWithProvider { .. } => Some(Toast::success(
+ m.next_toast,
+ t("chasqui-toast-provider-matched"),
+ TOAST_TTL,
+ )),
+ _ => None,
+ };
+ if let Some(toast) = toast {
+ m.next_toast += 1;
+ push_toast(&mut m, handle, toast);
+ }
+ }
m.sessions = sessions;
if let Some(list) = matches {
m.diff_matches_into_timeline(&list);
@@ -268,6 +323,14 @@ impl App for Explorer {
}
Msg::CycleTheme => {
m.theme = Theme::next_after(m.theme.name);
+ let id = m.next_toast;
+ m.next_toast += 1;
+ let toast = Toast::info(
+ id,
+ t_args("chasqui-toast-theme", &[("name", m.theme.name.to_string().into())]),
+ TOAST_TTL,
+ );
+ push_toast(&mut m, handle, toast);
}
Msg::SelectEntry(i) => {
m.selected = Some(i);
@@ -284,8 +347,24 @@ impl App for Explorer {
m.timeline.clear();
m.selected = None;
m.context_menu = None;
+ let id = m.next_toast;
+ m.next_toast += 1;
+ push_toast(
+ &mut m,
+ handle,
+ Toast::info(id, t("chasqui-toast-timeline-cleared"), TOAST_TTL),
+ );
+ }
+ Msg::ToastExpire(id) => {
+ m.toasts.retain(|t| t.id != id);
+ }
+ Msg::Shimmer => {
+ // El thread durmió 50 ms; `ensure_shimmer` reabre la cadena
+ // sólo si seguimos en `Pending`.
+ m.shimmering = false;
}
}
+ ensure_shimmer(&mut m, handle);
m
}
@@ -319,15 +398,15 @@ impl App for Explorer {
ProbeState::Pending => {}
ProbeState::Down { reason } => body_children.push(banner_view::<Msg>(
BannerKind::Error,
- format!("Broker DOWN — {reason}"),
+ t_args("chasqui-broker-down", &[("reason", reason.clone().into())]),
)),
ProbeState::UpNoProvider { .. } => body_children.push(banner_view::<Msg>(
BannerKind::Warning,
- "Broker UP, sin provider para el flow".to_string(),
+ t("chasqui-banner-no-provider"),
)),
ProbeState::UpWithProvider { .. } => body_children.push(banner_view::<Msg>(
BannerKind::Success,
- "Broker UP, provider matcheado".to_string(),
+ t("chasqui-banner-provider-matched"),
)),
}
@@ -339,8 +418,9 @@ impl App for Explorer {
accent_down,
accent_pending,
);
+ let label_state = t("chasqui-card-state");
body_children.push(stat_card_view::<Msg>(
- "Estado",
+ &label_state,
state_value,
&state_descr,
state_accent,
@@ -375,14 +455,13 @@ impl App for Explorer {
.map(|l| l.entries.len().to_string())
.unwrap_or_else(|| "—".into());
let sessions_descr = match &model.sessions {
- None => "lista no disponible (broker DOWN o pendiente)".to_string(),
- Some(l) if l.entries.is_empty() => {
- "sin sesiones registradas en el broker".into()
- }
- Some(_) => "labels visibles + flows in/out · (wit) = consciente".into(),
+ None => t("chasqui-sessions-unavailable"),
+ Some(l) if l.entries.is_empty() => t("chasqui-sessions-empty"),
+ Some(_) => t("chasqui-sessions-some"),
};
+ let label_sessions = t("chasqui-card-sessions");
body_children.push(stat_card_view::<Msg>(
- "Sesiones activas",
+ &label_sessions,
sessions_count_value,
&sessions_descr,
accent_up,
@@ -395,12 +474,13 @@ impl App for Explorer {
// right-click en la raíz abre el contextual).
let timeline_value = model.timeline.len().to_string();
let timeline_descr = if model.timeline.is_empty() {
- "esperando primer match…".to_string()
+ t("chasqui-timeline-waiting")
} else {
- "click selecciona · right-click = menú · cap 50 entries".to_string()
+ t("chasqui-timeline-help")
};
+ let label_timeline = t("chasqui-card-timeline");
body_children.push(stat_card_view::<Msg>(
- "Timeline de matches",
+ &label_timeline,
timeline_value,
&timeline_descr,
accent_partial,
@@ -408,32 +488,78 @@ impl App for Explorer {
&stat_palette,
));
- for (i, e) in model.timeline.iter().take(20).enumerate() {
- let selected = model.selected == Some(i);
- let mut row = View::new(Style {
- size: Size {
- width: percent(1.0_f32),
- height: length(18.0_f32),
- },
- padding: Rect {
- left: length(8.0_f32),
- right: length(8.0_f32),
- top: length(0.0_f32),
- bottom: length(0.0_f32),
- },
- ..Default::default()
- })
- .text_aligned(
- format_timeline_entry(e),
- 11.0,
- theme.fg_text,
- Alignment::Start,
- )
- .on_click(Msg::SelectEntry(i));
- if selected {
- row = row.fill(theme.bg_selected);
+ // Timeline tri-estado:
+ // 1) Pending y vacío → filas skeleton con shimmer (esperando 1er probe).
+ // 2) vacío pero ya sondeado → empty-state con orientación.
+ // 3) con entries → filas reales, cada una entra con pop-in la
+ // primera vez que aparece su key.
+ if model.timeline.is_empty() {
+ if matches!(model.state, ProbeState::Pending) {
+ let skel = SkeletonPalette::from_theme(theme);
+ for _ in 0..5 {
+ body_children.push(
+ View::new(Style {
+ size: Size {
+ width: percent(1.0_f32),
+ height: length(18.0_f32),
+ },
+ flex_shrink: 0.0,
+ ..Default::default()
+ })
+ .radius(4.0)
+ .clip(true)
+ .children(vec![skeleton_view::<Msg>(&skel)]),
+ );
+ }
+ } else {
+ let empty_pal = EmptyPalette::from_theme(theme);
+ let empty_descr = t("chasqui-empty-descr");
+ body_children.push(
+ View::new(Style {
+ size: Size {
+ width: percent(1.0_f32),
+ height: length(160.0_f32),
+ },
+ flex_shrink: 0.0,
+ ..Default::default()
+ })
+ .children(vec![empty_view::<Msg>(
+ Icon::Bell,
+ t("chasqui-empty-title"),
+ Some(empty_descr.as_str()),
+ &empty_pal,
+ )]),
+ );
+ }
+ } else {
+ for (i, e) in model.timeline.iter().take(20).enumerate() {
+ let selected = model.selected == Some(i);
+ let mut row = View::new(Style {
+ size: Size {
+ width: percent(1.0_f32),
+ height: length(18.0_f32),
+ },
+ padding: Rect {
+ left: length(8.0_f32),
+ right: length(8.0_f32),
+ top: length(0.0_f32),
+ bottom: length(0.0_f32),
+ },
+ ..Default::default()
+ })
+ .text_aligned(
+ format_timeline_entry(e),
+ 11.0,
+ theme.fg_text,
+ Alignment::Start,
+ )
+ .on_click(Msg::SelectEntry(i))
+ .animated_pop_in(key_of(&format_timeline_entry(e)), motion::NORMAL);
+ if selected {
+ row = row.fill(theme.bg_selected);
+ }
+ body_children.push(row);
}
- body_children.push(row);
}
let body = View::new(Style {
@@ -458,7 +584,7 @@ impl App for Explorer {
.fill(theme.bg_app)
.children(body_children);
- View::new(Style {
+ let root = View::new(Style {
flex_direction: FlexDirection::Column,
size: Size {
width: percent(1.0_f32),
@@ -470,7 +596,26 @@ impl App for Explorer {
// Right-click en la raíz (origen 0,0 ⇒ local == ventana) abre el
// menú contextual sobre la entry seleccionada.
.on_right_click_at(|x, y, _w, _h| Some(Msg::ContextMenuOpen(x, y)))
- .children(vec![menubar, header, body])
+ .children(vec![menubar, header, body]);
+
+ // Overlay de toasts efímeros (bottom-right). Click en uno = descartarlo.
+ let now = Instant::now();
+ let alive: Vec<Toast> = model.toasts.iter().filter(|t| t.is_alive(now)).cloned().collect();
+ if alive.is_empty() {
+ root
+ } else {
+ View::new(Style {
+ size: Size {
+ width: percent(1.0_f32),
+ height: percent(1.0_f32),
+ },
+ ..Default::default()
+ })
+ .children(vec![
+ root,
+ toast_stack_view(&alive, viewport_of(model), Msg::ToastExpire),
+ ])
+ }
}
fn view_overlay(model: &Model) -> Option<View<Msg>> {
@@ -480,13 +625,13 @@ impl App for Explorer {
.timeline
.get(idx)
.map(format_timeline_entry)
- .unwrap_or_else(|| "Entry".to_string());
+ .unwrap_or_else(|| t("chasqui-entry-fallback"));
let viewport = viewport_of(model);
// Acciones reales del probe (sólo lectura): refrescar el
// probe y limpiar el timeline. No inventamos edición.
let items = vec![
- ContextMenuItem::action("Refrescar probe"),
- ContextMenuItem::action("Limpiar timeline"),
+ ContextMenuItem::action(t("chasqui-refresh-probe")),
+ ContextMenuItem::action(t("chasqui-clear-timeline")),
];
let on_pick: Arc<dyn Fn(usize) -> Msg + Send + Sync> =
Arc::new(move |i: usize| match i {
@@ -545,26 +690,57 @@ fn menubar_spec<'a>(
fn app_menu() -> AppMenu {
AppMenu::new()
.menu(
- Menu::new("Archivo")
- .item(MenuItem::new("Refrescar probe", "file.refresh").shortcut("Ctrl+R"))
- .item(MenuItem::new("Limpiar timeline", "file.clear"))
- .item(MenuItem::new("Salir", "file.quit").shortcut("Ctrl+Q").separated()),
+ Menu::new(t("chasqui-menu-file"))
+ .item(MenuItem::new(t("chasqui-refresh-probe"), "file.refresh").shortcut("Ctrl+R"))
+ .item(MenuItem::new(t("chasqui-clear-timeline"), "file.clear"))
+ .item(MenuItem::new(t("exit"), "file.quit").shortcut("Ctrl+Q").separated()),
)
.menu(
- Menu::new("Ver")
- .item(MenuItem::new("Reconectar", "view.reconnect"))
- .item(MenuItem::new("Cambiar tema", "view.theme").separated()),
+ Menu::new(t("chasqui-menu-view"))
+ .item(MenuItem::new(t("chasqui-menu-reconnect"), "view.reconnect"))
+ .item(MenuItem::new(t("cycle-theme"), "view.theme").separated()),
)
- .menu(Menu::new("Ayuda").item(MenuItem::new("Acerca de", "help.about")))
+ .menu(Menu::new(t("help")).item(MenuItem::new(t("about"), "help.about")))
+}
+
+/// Empuja un toast al stack y programa su expiración (acción real del
+/// usuario o evento del probe, no ruido de cada tick).
+fn push_toast(m: &mut Model, handle: &Handle<Msg>, toast: Toast) {
+ let id = toast.id;
+ m.toasts.push(toast);
+ handle.spawn(move || {
+ std::thread::sleep(TOAST_TTL);
+ Msg::ToastExpire(id)
+ });
+}
+
+/// Arranca la cadena de ticks del shimmer si el probe sigue `Pending` y no
+/// hay ya una corriendo. Se auto-detiene cuando el primer probe responde.
+fn ensure_shimmer(m: &mut Model, handle: &Handle<Msg>) {
+ if m.shimmering || !matches!(m.state, ProbeState::Pending) {
+ return;
+ }
+ m.shimmering = true;
+ handle.spawn(move || {
+ std::thread::sleep(Duration::from_millis(50));
+ Msg::Shimmer
+ });
}
/// Traduce un command id del menú principal al `Msg`/efecto real.
-fn handle_menu_command(model: Model, cmd: &str, handle: &Handle<Msg>) -> Model {
+fn handle_menu_command(mut model: Model, cmd: &str, handle: &Handle<Msg>) -> Model {
match cmd {
// Reconectar == re-disparar el probe; el ProbeResult refresca
// estado/sesiones/matches.
"file.refresh" | "view.reconnect" => {
handle.dispatch(Msg::Tick);
+ let id = model.next_toast;
+ model.next_toast += 1;
+ push_toast(
+ &mut model,
+ handle,
+ Toast::info(id, t("chasqui-toast-refreshing"), TOAST_TTL),
+ );
model
}
"file.clear" => {
@@ -612,24 +788,27 @@ fn state_card_params(
ProbeState::Pending => (
accent_pending,
"PENDING".into(),
- "esperando primer probe…".into(),
+ t("chasqui-state-pending"),
),
ProbeState::Down { reason } => (
accent_down,
"DOWN".into(),
- format!("connect failed: {reason}"),
+ t_args("chasqui-state-down", &[("reason", reason.clone().into())]),
),
ProbeState::UpNoProvider { flow } => (
accent_partial,
"UP / NO PROVIDER".into(),
- format!("broker reachable; sin productor para flow `{flow}`"),
+ t_args("chasqui-state-no-provider", &[("flow", flow.clone().into())]),
),
ProbeState::UpWithProvider { flow, producer_socket } => (
accent_up,
"UP / PROVIDER".into(),
- format!(
- "flow `{flow}` matcheado en producer socket: {}",
- producer_socket.display()
+ t_args(
+ "chasqui-state-provider",
+ &[
+ ("flow", flow.clone().into()),
+ ("socket", producer_socket.display().to_string().into()),
+ ],
),
),
}
@@ -667,66 +846,6 @@ fn run_probe(flow: String, type_name: String) -> Msg {
}
}
-/// Diff puro entre snapshots de matches. Devuelve la lista de
-/// entries nuevas (Available + Lost) en orden Available-primero, y
-/// el set actualizado de keys.
-fn diff_matches(
- last_keys: &HashSet<MatchKey>,
- list: &card_handshake::messages::MatchList,
-) -> (Vec<TimelineEntry>, HashSet<MatchKey>) {
- use card_handshake::messages::MatchEventKind;
- let now = std::time::SystemTime::now();
- let current_keys: HashSet<MatchKey> = list
- .matches
- .iter()
- .map(|m| {
- (
- m.consumer.session,
- m.consumer.flow_name.clone(),
- m.producer.session,
- m.producer.flow_name.clone(),
- )
- })
- .collect();
-
- let mut entries = Vec::new();
- for m in &list.matches {
- let key = (
- m.consumer.session,
- m.consumer.flow_name.clone(),
- m.producer.session,
- m.producer.flow_name.clone(),
- );
- if !last_keys.contains(&key) {
- entries.push(TimelineEntry {
- at: now,
- kind: MatchEventKind::Available,
- consumer_label: m.consumer_label.clone(),
- consumer_flow: m.consumer.flow_name.clone(),
- producer_label: m.producer_label.clone(),
- producer_flow: m.producer.flow_name.clone(),
- via: m.via,
- pinned: m.pinned,
- });
- }
- }
- for key in last_keys.iter() {
- if !current_keys.contains(key) {
- entries.push(TimelineEntry {
- at: now,
- kind: MatchEventKind::Lost,
- consumer_label: String::new(),
- consumer_flow: key.1.clone(),
- producer_label: String::new(),
- producer_flow: key.3.clone(),
- via: chasqui_broker::MatchStrategy::Exact,
- pinned: false,
- });
- }
- }
- (entries, current_keys)
-}
-
fn format_timeline_entry(e: &TimelineEntry) -> String {
use card_handshake::messages::MatchEventKind;
let secs_today = e
diff --git a/02_ruway/chasqui/chasqui-broker/Cargo.toml b/02_ruway/chasqui/chasqui-broker/Cargo.toml
index 05eac74..b46a315 100644
--- a/02_ruway/chasqui/chasqui-broker/Cargo.toml
+++ b/02_ruway/chasqui/chasqui-broker/Cargo.toml
@@ -11,5 +11,4 @@ description = "Brahman — broker de tipos: empareja productores↔consumidores
[dependencies]
card-core = { workspace = true }
serde = { workspace = true }
-thiserror = { workspace = true }
ulid = { workspace = true }
diff --git a/02_ruway/chasqui/chasqui-card/src/intension.rs b/02_ruway/chasqui/chasqui-card/src/intension.rs
new file mode 100644
index 0000000..83cb8d1
--- /dev/null
+++ b/02_ruway/chasqui/chasqui-card/src/intension.rs
@@ -0,0 +1,154 @@
+//! Cuerpo **intensional** de una Mónada: la regla que (re)deriva sus
+//! miembros en cada scan, en vez de curarlos a mano.
+//!
+//! Una Mónada **extensional** lista sus miembros explícitamente (un
+//! álbum: estas 40 fotos). Una Mónada **intensional** no guarda la
+//! lista: guarda un *predicado* ([`MonadQuery`]) que el motor evalúa
+//! contra el corpus para producir los miembros ("Fotos" = todo lo que
+//! sea imagen, en cualquier parte). Es la misma idea que una
+//! smart-playlist o un saved-search: la membresía es una consulta, no
+//! una colección.
+//!
+//! Este crate sólo define el **tipo** de la regla (dato puro,
+//! serializable). La **evaluación** —que necesita leer el corpus y, para
+//! [`MonadQuery::Near`], los embeddings— vive en `chasqui-core::resolve`,
+//! igual que el resto de la lógica de scan/cluster/attraction.
+
+use std::collections::BTreeSet;
+
+use serde::{Deserialize, Serialize};
+
+use crate::Lens;
+
+/// Predicado que define los miembros de una Mónada intensional.
+///
+/// Es un álgebra chica y cerrada bajo composición ([`All`](Self::All) /
+/// [`Any`](Self::Any) / [`Not`](Self::Not)), de modo que casos reales se
+/// expresan combinando hojas simples:
+///
+/// - `"Fotos"` = `Lens { lens: Gallery }` (o `Extension` de los formatos
+/// de imagen, si se prefiere por extensión).
+/// - `"Código Rust grande"` = `All { of: [Extension{rs}, ...] }`.
+/// - `"Cerca de este viaje"` = `Near { min_similarity }`, comparando el
+/// embedding de cada archivo contra el `centroid` de la propia Mónada
+/// (que vive en el manifiesto, no aquí — la query es agnóstica del
+/// centroide concreto).
+///
+/// Las hojas [`Extension`](Self::Extension) y [`Lens`](Self::Lens) son
+/// deterministas y baratas (no requieren embeddings); [`Near`](Self::Near)
+/// es la hoja semántica que apoya en el modelo vectorial de `chasqui`.
+#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
+#[serde(tag = "op", rename_all = "snake_case")]
+pub enum MonadQuery {
+ /// Verdadero si la extensión del archivo (lowercase, sin punto) está
+ /// en el conjunto. `{"png","jpg","jpeg",...}` = "imágenes por formato".
+ Extension {
+ /// Extensiones aceptadas, ya normalizadas a lowercase sin punto.
+ exts: BTreeSet<String>,
+ },
+ /// Verdadero si el lente discernido del archivo coincide. Es el modo
+ /// natural de "todo lo que se ve con tal vista" (Gallery, Code, …).
+ Lens {
+ /// Lente exigido.
+ lens: Lens,
+ },
+ /// Verdadero si el embedding del archivo está a coseno ≥
+ /// `min_similarity` del centroide de la Mónada. La hoja semántica:
+ /// "lo que se parece a esto".
+ Near {
+ /// Umbral de similitud coseno en `[-1, 1]`. Típico ≈ 0.7.
+ min_similarity: f32,
+ },
+ /// Conjunción: el archivo entra si satisface **todas** las
+ /// subconsultas. `of` vacío ⇒ verdadero (neutro del AND).
+ All {
+ /// Subconsultas que deben cumplirse todas.
+ of: Vec<MonadQuery>,
+ },
+ /// Disyunción: el archivo entra si satisface **alguna**. `of` vacío
+ /// ⇒ falso (neutro del OR).
+ Any {
+ /// Subconsultas, basta una.
+ of: Vec<MonadQuery>,
+ },
+ /// Negación: invierte la subconsulta.
+ Not {
+ /// Subconsulta a negar.
+ inner: Box<MonadQuery>,
+ },
+}
+
+impl MonadQuery {
+ /// Atajo: una query de imágenes por las extensiones más comunes.
+ /// Útil para sembrar la Mónada intensional canónica "Fotos".
+ pub fn imagenes() -> Self {
+ MonadQuery::Lens { lens: Lens::Gallery }
+ }
+
+ /// Atajo: una query por un único formato de archivo.
+ pub fn extension(ext: impl Into<String>) -> Self {
+ let mut exts = BTreeSet::new();
+ exts.insert(ext.into().to_lowercase());
+ MonadQuery::Extension { exts }
+ }
+
+ /// `true` si la query es puramente léxica (Extension/composición de
+ /// Extension) y por lo tanto evaluable **sin** leer el contenido ni
+ /// los embeddings — sólo mirando la ruta/extensión. Le sirve al
+ /// motor para decidir si puede resolverla en frío.
+ pub fn es_lexica(&self) -> bool {
+ match self {
+ MonadQuery::Extension { .. } => true,
+ MonadQuery::Lens { .. } | MonadQuery::Near { .. } => false,
+ MonadQuery::All { of } | MonadQuery::Any { of } => of.iter().all(Self::es_lexica),
+ MonadQuery::Not { inner } => inner.es_lexica(),
+ }
+ }
+
+ /// `true` si la query usa la hoja semántica [`Near`](Self::Near) en
+ /// algún lugar — es decir, su evaluación necesita un centroide y los
+ /// embeddings del corpus.
+ pub fn usa_embeddings(&self) -> bool {
+ match self {
+ MonadQuery::Near { .. } => true,
+ MonadQuery::Extension { .. } | MonadQuery::Lens { .. } => false,
+ MonadQuery::All { of } | MonadQuery::Any { of } => of.iter().any(Self::usa_embeddings),
+ MonadQuery::Not { inner } => inner.usa_embeddings(),
+ }
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+
+ #[test]
+ fn roundtrip_json_con_tag_op() {
+ let q = MonadQuery::All {
+ of: vec![
+ MonadQuery::extension("rs"),
+ MonadQuery::Not {
+ inner: Box::new(MonadQuery::Near { min_similarity: 0.8 }),
+ },
+ ],
+ };
+ let s = serde_json::to_string(&q).unwrap();
+ assert!(s.contains(r#""op":"all""#), "{s}");
+ let back: MonadQuery = serde_json::from_str(&s).unwrap();
+ assert_eq!(back, q);
+ }
+
+ #[test]
+ fn lexica_vs_semantica() {
+ assert!(MonadQuery::extension("png").es_lexica());
+ assert!(!MonadQuery::imagenes().es_lexica()); // Lens necesita discernir
+ assert!(!MonadQuery::Near { min_similarity: 0.7 }.es_lexica());
+
+ let mixta = MonadQuery::Any {
+ of: vec![MonadQuery::extension("png"), MonadQuery::Near { min_similarity: 0.7 }],
+ };
+ assert!(!mixta.es_lexica());
+ assert!(mixta.usa_embeddings());
+ assert!(!MonadQuery::extension("png").usa_embeddings());
+ }
+}
diff --git a/02_ruway/chasqui/chasqui-card/src/lib.rs b/02_ruway/chasqui/chasqui-card/src/lib.rs
index 3712b80..0d9deb6 100644
--- a/02_ruway/chasqui/chasqui-card/src/lib.rs
+++ b/02_ruway/chasqui/chasqui-card/src/lib.rs
@@ -33,10 +33,20 @@ use ulid::Ulid;
// Re-export para consumidores
pub use ::ulid;
+pub mod intension;
pub mod query;
+pub use intension::MonadQuery;
+
/// Versión del esquema del manifiesto. Bump al cambiar el schema.
-pub const MONAD_SCHEMA_VERSION: u16 = 1;
+///
+/// v2 (grafo de Mónadas): `MonadManifest` gana `submonads` (contención
+/// DAG: una Mónada puede contener otras) y `query` (cuerpo intensional:
+/// los miembros se derivan de un [`MonadQuery`] en vez de curarse a
+/// mano). Ambos campos son aditivos con `serde default`, así que un
+/// manifiesto v1 deserializa sin pérdida; `validate` acepta esquemas
+/// **iguales o anteriores** (sólo rechaza los más nuevos que no entiende).
+pub const MONAD_SCHEMA_VERSION: u16 = 2;
/// Identificador opaco de un archivo registrado en la DB.
pub type FileId = Ulid;
@@ -176,6 +186,26 @@ pub struct MonadManifest {
/// IDs de archivos miembros (incluye pins).
pub members: BTreeSet<FileId>,
+ /// **Sub-Mónadas contenidas** (contención DAG). Una Mónada puede
+ /// contener otras además de archivos: "Fotos" contiene el álbum
+ /// "Viaje", que contiene las fotos. Como una sub-Mónada se referencia
+ /// por su `MonadId`, la *misma* sub-Mónada puede aparecer bajo varios
+ /// padres — multi-pertenencia sin duplicar el objeto. Es el eje de
+ /// **contención**, ortogonal a `lineage` (que es *derivación*:
+ /// split/merge histórico, no quién-contiene-a-quién).
+ #[serde(default)]
+ pub submonads: BTreeSet<MonadId>,
+
+ /// Cuerpo **intensional**, si la Mónada es una consulta. `None` =
+ /// Mónada extensional (los `members` se curan a mano o por
+ /// clustering). `Some(q)` = los miembros se (re)derivan evaluando `q`
+ /// contra el corpus en cada scan; `members` queda como la
+ /// materialización cacheada de esa evaluación (más los `pins`, que el
+ /// usuario fija aunque la query no los capture). Ver
+ /// [`intension::MonadQuery`].
+ #[serde(default)]
+ pub query: Option<MonadQuery>,
+
/// Unix ms de creación de la Mónada.
pub created_at_ms: u64,
@@ -232,6 +262,8 @@ impl MonadManifest {
dominant_lens: Lens::default(),
pins: BTreeSet::new(),
members: BTreeSet::new(),
+ submonads: BTreeSet::new(),
+ query: None,
created_at_ms: now_ms,
updated_at_ms: now_ms,
extensions: BTreeMap::new(),
@@ -240,7 +272,11 @@ impl MonadManifest {
/// Validación semántica.
pub fn validate(&self) -> Result<(), MonadError> {
- if self.schema_version != MONAD_SCHEMA_VERSION {
+ // Aceptamos esquemas iguales o anteriores (los campos nuevos son
+ // aditivos con default). Sólo rechazamos uno MÁS nuevo que el que
+ // este binario entiende: ahí sí podrían venir invariantes que no
+ // sabemos verificar.
+ if self.schema_version > MONAD_SCHEMA_VERSION {
return Err(MonadError::SchemaMismatch {
got: self.schema_version,
expected: MONAD_SCHEMA_VERSION,
@@ -255,7 +291,15 @@ impl MonadManifest {
if !(0.0..=1.0).contains(&self.entropy) {
return Err(MonadError::InvalidEntropy(self.entropy));
}
- if self.members.is_empty() && self.pins.is_empty() {
+ // Una Mónada es no-vacía si tiene algo que mostrar o una regla que
+ // la define: archivos, pines, sub-Mónadas, o un cuerpo intensional
+ // (que puede resolver a cero miembros hoy y a muchos tras el
+ // próximo scan — sigue siendo una Mónada legítima).
+ if self.members.is_empty()
+ && self.pins.is_empty()
+ && self.submonads.is_empty()
+ && self.query.is_none()
+ {
return Err(MonadError::Empty);
}
let actual = self.members.len() as u32;
@@ -412,6 +456,58 @@ mod tests {
assert_eq!(data.presentation_hint, "code");
}
+ #[test]
+ fn submonads_solo_es_no_vacia() {
+ // Una Mónada-contenedor que sólo agrupa otras Mónadas (sin
+ // archivos propios) es válida — es el caso de "Fotos" conteniendo
+ // álbumes.
+ let mut m = MonadManifest::new("Fotos");
+ m.submonads.insert(Ulid::new());
+ m.touch();
+ m.validate().expect("submonads-only debe validar");
+ }
+
+ #[test]
+ fn query_sola_es_no_vacia() {
+ // Una Mónada intensional recién creada puede no tener miembros
+ // materializados todavía y aun así ser válida: su cuerpo es la
+ // query.
+ let mut m = MonadManifest::new("Imágenes");
+ m.query = Some(MonadQuery::imagenes());
+ m.touch();
+ assert_eq!(m.cardinality, 0);
+ m.validate().expect("query-only debe validar");
+ }
+
+ #[test]
+ fn schema_anterior_se_acepta() {
+ // Un manifiesto de un esquema previo (v1) sigue siendo legible:
+ // validate sólo rechaza esquemas MÁS nuevos.
+ let mut m = MonadManifest::new("legacy");
+ m.members.insert(Ulid::new());
+ m.touch();
+ m.schema_version = 1;
+ m.validate().expect("v1 debe validar contra un binario v2");
+
+ m.schema_version = MONAD_SCHEMA_VERSION + 1;
+ assert!(matches!(m.validate(), Err(MonadError::SchemaMismatch { .. })));
+ }
+
+ #[test]
+ fn json_roundtrip_preserva_grafo() {
+ let mut m = MonadManifest::new("Fotos");
+ m.submonads.insert(Ulid::new());
+ m.submonads.insert(Ulid::new());
+ m.query = Some(MonadQuery::Any {
+ of: vec![MonadQuery::extension("png"), MonadQuery::extension("jpg")],
+ });
+ m.touch();
+ let s = m.to_json_pretty().unwrap();
+ let m2 = MonadManifest::from_json(&s).unwrap();
+ assert_eq!(m2.submonads, m.submonads);
+ assert_eq!(m2.query, m.query);
+ }
+
#[test]
fn json_roundtrip() {
let mut m = MonadManifest::new("test-monad");
diff --git a/02_ruway/chasqui/chasqui-core/Cargo.toml b/02_ruway/chasqui/chasqui-core/Cargo.toml
index 1827a00..c09f842 100644
--- a/02_ruway/chasqui/chasqui-core/Cargo.toml
+++ b/02_ruway/chasqui/chasqui-core/Cargo.toml
@@ -13,17 +13,18 @@ chasqui-card = { path = "../chasqui-card" }
chasqui-nous = { path = "../chasqui-nous" }
shuma-discern = { workspace = true }
card-core = { workspace = true }
-card-handshake = { path = "../card-handshake" }
card-sidecar = { path = "../card-sidecar" }
blake3 = { workspace = true }
-serde = { workspace = true }
serde_json = { workspace = true }
sled = { workspace = true }
thiserror = { workspace = true }
-tokio = { workspace = true }
ulid = { workspace = true }
walkdir = "2"
notify = { workspace = true }
+# El contrato del DAG navegable compartido (PLAN-GRAFO): el adaptador
+# `grafo::GrafoMonadas` ve el grafo de contención de Mónadas como GrafoNavegable
+# para el cockpit universal (visor de DAGs en nahual).
+grafo-nav = { workspace = true }
[dev-dependencies]
tempfile = { workspace = true }
diff --git a/02_ruway/chasqui/chasqui-core/src/bin/nouser.rs b/02_ruway/chasqui/chasqui-core/src/bin/nouser.rs
index f47087f..65e19f3 100644
--- a/02_ruway/chasqui/chasqui-core/src/bin/nouser.rs
+++ b/02_ruway/chasqui/chasqui-core/src/bin/nouser.rs
@@ -118,7 +118,7 @@ fn cmd_scan(args: &[String]) -> Cmd {
min_files()
);
if db.monad_count() == 0 {
- println!(" (ninguna Mónada — bajá NOUSER_MIN_FILES o apuntá a un dir con más archivos)");
+ println!(" (ninguna Mónada — baja NOUSER_MIN_FILES o apunta a un dir con más archivos)");
return Ok(());
}
println!();
diff --git a/02_ruway/chasqui/chasqui-core/src/cluster.rs b/02_ruway/chasqui/chasqui-core/src/cluster.rs
index 85af5b5..5bcb1c9 100644
--- a/02_ruway/chasqui/chasqui-core/src/cluster.rs
+++ b/02_ruway/chasqui/chasqui-core/src/cluster.rs
@@ -155,9 +155,13 @@ fn top_extensions(files: &[&FileEntry], n: usize) -> Vec<String> {
/// Elige el lente dominante según la extensión más frecuente, con
/// fallback a `shuma-discern` sobre el head del archivo más
/// representativo cuando la extensión no da hint claro (Lens::Grid).
-fn pick_lens(files: &[&FileEntry]) -> Lens {
- let dominant = top_extensions(files, 1).into_iter().next();
- let by_ext = match dominant.as_deref() {
+/// Mapea una extensión (lowercase, sin punto) a su lente determinista,
+/// o [`Lens::Grid`] si la extensión no da hint claro. Determinista y sin
+/// disco — la fuente de verdad del "lente por formato", compartida entre
+/// el clustering ([`pick_lens`]) y la evaluación de queries intensionales
+/// ([`crate::resolve`]).
+pub fn lens_from_ext(ext: Option<&str>) -> Lens {
+ match ext {
Some("rs" | "py" | "ts" | "tsx" | "js" | "jsx" | "go" | "java" | "kt" | "c" | "cpp"
| "cc" | "h" | "hpp" | "rb" | "swift" | "zig") => Lens::Code,
Some("png" | "jpg" | "jpeg" | "gif" | "webp" | "svg" | "bmp" | "tiff" | "heic") => {
@@ -166,7 +170,12 @@ fn pick_lens(files: &[&FileEntry]) -> Lens {
Some("md" | "markdown" | "rst" | "txt" | "org" | "tex") => Lens::Markdown,
Some("db" | "sqlite" | "sqlite3" | "csv" | "tsv" | "parquet") => Lens::Database,
_ => Lens::Grid,
- };
+ }
+}
+
+fn pick_lens(files: &[&FileEntry]) -> Lens {
+ let dominant = top_extensions(files, 1).into_iter().next();
+ let by_ext = lens_from_ext(dominant.as_deref());
if by_ext != Lens::Grid {
return by_ext;
}
diff --git a/02_ruway/chasqui/chasqui-core/src/db.rs b/02_ruway/chasqui/chasqui-core/src/db.rs
index 6674015..941965e 100644
--- a/02_ruway/chasqui/chasqui-core/src/db.rs
+++ b/02_ruway/chasqui/chasqui-core/src/db.rs
@@ -146,6 +146,19 @@ impl MonadDb {
self.monads.get(&id)
}
+ /// Elimina una Mónada del store (cache + persistencia). Devuelve el
+ /// manifiesto removido, o `None` si no existía. No toca a quién la
+ /// referenciaba como sub-Mónada — eso es responsabilidad de la capa
+ /// de edición (`crate::edit`), que mantiene la coherencia del grafo.
+ pub fn remove_monad(&mut self, id: MonadId) -> Option<MonadManifest> {
+ if let Some(db) = &self.persistence {
+ if let Ok(tree) = db.open_tree(TREE_MONADS) {
+ let _ = tree.remove(id.to_string().as_bytes());
+ }
+ }
+ self.monads.remove(&id)
+ }
+
pub fn monads(&self) -> impl Iterator<Item = &MonadManifest> + '_ {
self.monads.values()
}
diff --git a/02_ruway/chasqui/chasqui-core/src/edit.rs b/02_ruway/chasqui/chasqui-core/src/edit.rs
new file mode 100644
index 0000000..f4d8d48
--- /dev/null
+++ b/02_ruway/chasqui/chasqui-core/src/edit.rs
@@ -0,0 +1,442 @@
+//! Edición del **grafo de Mónadas**: las mutaciones que convierten a
+//! nahual en un *file manager* (no un mero visor).
+//!
+//! "Para manejar mis datos los voy a querer modificar, y submonadizar": el
+//! usuario edita la **organización** (el grafo), no necesariamente los
+//! bytes de los archivos. Estas operaciones reorganizan Mónadas y su
+//! pertenencia sin mover un solo archivo en disco — el archivo físico es
+//! agnóstico a en cuántas Mónadas vive.
+//!
+//! Todas las mutaciones siguen el patrón **clonar→mutar→reinsertar** sobre
+//! [`MonadDb`], para que la escritura pase por `insert_monad` y herede el
+//! write-through a sled cuando el store es persistente.
+//!
+//! Invariantes que esta capa mantiene:
+//! - El grafo de contención es un **DAG**: [`add_submonad`] /
+//! [`submonadize`] rechazan cualquier arista que cierre un ciclo.
+//! - Al cambiar los miembros de una Mónada, su `centroid` se recalcula
+//! (vía [`crate::embed`]) para que la atracción y las queries `Near`
+//! sigan siendo significativas.
+//! - [`delete_monad`] y [`merge`] dejan el grafo coherente: ningún padre
+//! queda apuntando a una sub-Mónada que ya no existe.
+
+use chasqui_card::{FileId, Lens, MonadId, MonadManifest, MonadQuery};
+use thiserror::Error;
+
+use crate::db::MonadDb;
+use crate::embed;
+
+/// Error de una operación de edición del grafo.
+#[derive(Debug, Error, PartialEq, Eq)]
+pub enum EditError {
+ #[error("Mónada inexistente: {0}")]
+ NotFound(MonadId),
+ /// Agregar `child` bajo `parent` cerraría un ciclo, porque `parent` ya
+ /// es alcanzable desde `child` (o son la misma).
+ #[error("ciclo: {child} ya contiene (transitivamente) a {parent}")]
+ Cycle { parent: MonadId, child: MonadId },
+}
+
+/// `true` si `target` es alcanzable desde `from` bajando por sub-Mónadas
+/// (incluye el caso `from == target`). Sirve para detectar ciclos antes de
+/// agregar una arista de contención.
+fn reachable(db: &MonadDb, from: MonadId, target: MonadId) -> bool {
+ if from == target {
+ return true;
+ }
+ let mut stack = vec![from];
+ let mut visto = std::collections::BTreeSet::new();
+ while let Some(id) = stack.pop() {
+ if !visto.insert(id) {
+ continue;
+ }
+ if let Some(m) = db.monad(id) {
+ for sub in &m.submonads {
+ if *sub == target {
+ return true;
+ }
+ stack.push(*sub);
+ }
+ }
+ }
+ false
+}
+
+/// Recalcula el centroide de una Mónada desde los embeddings de sus
+/// miembros actuales. Sin miembros, el centroide queda vacío (y `Near`
+/// deja de matchear, como corresponde).
+fn recompute_centroid(db: &mut MonadDb, id: MonadId) {
+ let Some(m) = db.monad(id) else { return };
+ let mut m = m.clone();
+ let vecs: Vec<Vec<f32>> = m
+ .members
+ .iter()
+ .filter_map(|fid| db.file(*fid))
+ .map(|f| embed::embed(f).to_vec())
+ .collect();
+ m.centroid = embed::centroid(&vecs);
+ m.centroid_model = if m.centroid.is_empty() {
+ None
+ } else {
+ Some(embed::MODEL_ID.to_string())
+ };
+ m.touch();
+ db.insert_monad(m);
+}
+
+/// Crea una Mónada vacía con un label y un lente, y la inserta. Devuelve
+/// su id. Queda sin miembros hasta que se le agreguen (o se le ponga una
+/// query); recién ahí valida como no-vacía.
+pub fn create_monad(db: &mut MonadDb, label: impl Into<String>, lens: Lens) -> MonadId {
+ let mut m = MonadManifest::new(label);
+ m.dominant_lens = lens;
+ m.touch();
+ let id = m.id;
+ db.insert_monad(m);
+ id
+}
+
+/// Renombra una Mónada.
+pub fn rename(db: &mut MonadDb, id: MonadId, label: impl Into<String>) -> Result<(), EditError> {
+ let mut m = db.monad(id).ok_or(EditError::NotFound(id))?.clone();
+ m.label = label.into();
+ m.touch();
+ db.insert_monad(m);
+ Ok(())
+}
+
+/// Cambia el lente dominante (la "vista" que el shell elige para la
+/// Mónada).
+pub fn set_lens(db: &mut MonadDb, id: MonadId, lens: Lens) -> Result<(), EditError> {
+ let mut m = db.monad(id).ok_or(EditError::NotFound(id))?.clone();
+ m.dominant_lens = lens;
+ m.touch();
+ db.insert_monad(m);
+ Ok(())
+}
+
+/// Fija (o quita, con `None`) el cuerpo intensional. Convertir una Mónada
+/// extensional en intensional no borra sus `members` curados: la query
+/// *suma* (ver `resolve::effective_members`).
+pub fn set_query(
+ db: &mut MonadDb,
+ id: MonadId,
+ query: Option<MonadQuery>,
+) -> Result<(), EditError> {
+ let mut m = db.monad(id).ok_or(EditError::NotFound(id))?.clone();
+ m.query = query;
+ m.touch();
+ db.insert_monad(m);
+ Ok(())
+}
+
+/// Agrega un archivo como miembro curado de la Mónada y recalcula el
+/// centroide.
+pub fn add_member(db: &mut MonadDb, id: MonadId, file: FileId) -> Result<(), EditError> {
+ let mut m = db.monad(id).ok_or(EditError::NotFound(id))?.clone();
+ m.members.insert(file);
+ m.touch();
+ db.insert_monad(m);
+ recompute_centroid(db, id);
+ Ok(())
+}
+
+/// Quita un archivo de los miembros curados (y de los pines). Recalcula el
+/// centroide.
+pub fn remove_member(db: &mut MonadDb, id: MonadId, file: FileId) -> Result<(), EditError> {
+ let mut m = db.monad(id).ok_or(EditError::NotFound(id))?.clone();
+ m.members.remove(&file);
+ m.pins.remove(&file);
+ m.touch();
+ db.insert_monad(m);
+ recompute_centroid(db, id);
+ Ok(())
+}
+
+/// Agrega `child` como sub-Mónada de `parent`. Rechaza la arista si
+/// cerraría un ciclo (si `parent` ya es alcanzable desde `child`).
+pub fn add_submonad(db: &mut MonadDb, parent: MonadId, child: MonadId) -> Result<(), EditError> {
+ if db.monad(parent).is_none() {
+ return Err(EditError::NotFound(parent));
+ }
+ if db.monad(child).is_none() {
+ return Err(EditError::NotFound(child));
+ }
+ if reachable(db, child, parent) {
+ return Err(EditError::Cycle { parent, child });
+ }
+ let mut m = db.monad(parent).unwrap().clone();
+ m.submonads.insert(child);
+ m.touch();
+ db.insert_monad(m);
+ Ok(())
+}
+
+/// Quita la arista de contención `parent → child`. No borra la sub-Mónada,
+/// sólo la desvincula de ese padre (puede seguir colgando de otros).
+pub fn remove_submonad(
+ db: &mut MonadDb,
+ parent: MonadId,
+ child: MonadId,
+) -> Result<(), EditError> {
+ let mut m = db.monad(parent).ok_or(EditError::NotFound(parent))?.clone();
+ m.submonads.remove(&child);
+ m.touch();
+ db.insert_monad(m);
+ Ok(())
+}
+
+/// **Submonadizar**: crea una nueva Mónada hija de `parent` y le *traslada*
+/// la selección de archivos y sub-Mónadas indicada (la saca de `parent` y
+/// la mete en la hija). Es la operación canónica de "tomar un puñado de
+/// cosas dentro de una Mónada y agruparlas en una sub-Mónada propia".
+///
+/// La hija hereda el lente de `parent` por defecto; su centroide se calcula
+/// de los archivos trasladados. Devuelve el id de la hija.
+pub fn submonadize(
+ db: &mut MonadDb,
+ parent: MonadId,
+ label: impl Into<String>,
+ members: &[FileId],
+ submonads: &[MonadId],
+) -> Result<MonadId, EditError> {
+ let padre = db.monad(parent).ok_or(EditError::NotFound(parent))?.clone();
+
+ // La hija nace con la selección y el lente del padre.
+ let mut hija = MonadManifest::new(label);
+ hija.dominant_lens = padre.dominant_lens;
+ hija.lineage = Some(parent);
+ for f in members {
+ hija.members.insert(*f);
+ }
+ for s in submonads {
+ hija.submonads.insert(*s);
+ }
+ hija.touch();
+ let hija_id = hija.id;
+ db.insert_monad(hija);
+ recompute_centroid(db, hija_id);
+
+ // El padre suelta la selección y adopta a la hija.
+ let mut padre = padre;
+ for f in members {
+ padre.members.remove(f);
+ padre.pins.remove(f);
+ }
+ for s in submonads {
+ padre.submonads.remove(s);
+ }
+ padre.submonads.insert(hija_id);
+ padre.touch();
+ db.insert_monad(padre);
+ recompute_centroid(db, parent);
+
+ Ok(hija_id)
+}
+
+/// **Fusionar** `from` en `into`: traslada todos los miembros y
+/// sub-Mónadas de `from` a `into`, repunta a todo padre que apuntaba a
+/// `from` para que ahora apunte a `into`, y borra `from`. El grafo queda
+/// sin referencias colgadas.
+pub fn merge(db: &mut MonadDb, into: MonadId, from: MonadId) -> Result<(), EditError> {
+ if into == from {
+ return Ok(());
+ }
+ let origen = db.monad(from).ok_or(EditError::NotFound(from))?.clone();
+ let mut destino = db.monad(into).ok_or(EditError::NotFound(into))?.clone();
+
+ for f in &origen.members {
+ destino.members.insert(*f);
+ }
+ for p in &origen.pins {
+ destino.pins.insert(*p);
+ }
+ for s in &origen.submonads {
+ if *s != into {
+ destino.submonads.insert(*s);
+ }
+ }
+ destino.submonads.remove(&from);
+ destino.touch();
+ db.insert_monad(destino);
+
+ // Repuntar padres de `from` → `into`.
+ let padres: Vec<MonadId> = db
+ .monads()
+ .filter(|m| m.submonads.contains(&from))
+ .map(|m| m.id)
+ .collect();
+ for pid in padres {
+ if pid == into {
+ continue;
+ }
+ let mut p = db.monad(pid).unwrap().clone();
+ p.submonads.remove(&from);
+ if pid != into {
+ p.submonads.insert(into);
+ }
+ p.touch();
+ db.insert_monad(p);
+ }
+
+ db.remove_monad(from);
+ recompute_centroid(db, into);
+ Ok(())
+}
+
+/// Borra una Mónada y la desvincula de todo padre que la contenía. Los
+/// archivos y sub-Mónadas que contenía NO se borran — sólo se disuelve el
+/// agrupamiento.
+pub fn delete_monad(db: &mut MonadDb, id: MonadId) {
+ let padres: Vec<MonadId> = db
+ .monads()
+ .filter(|m| m.submonads.contains(&id))
+ .map(|m| m.id)
+ .collect();
+ for pid in padres {
+ if let Some(p) = db.monad(pid) {
+ let mut p = p.clone();
+ p.submonads.remove(&id);
+ p.touch();
+ db.insert_monad(p);
+ }
+ }
+ db.remove_monad(id);
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+ use crate::resolve;
+ use chasqui_card::FileEntry;
+ use std::path::PathBuf;
+ use ulid::Ulid;
+
+ fn mk(path: &str, ext: &str) -> FileEntry {
+ FileEntry {
+ id: FileId::from(Ulid::new()),
+ path: PathBuf::from(path),
+ content_hash: None,
+ size: 100,
+ mtime_ms: 1_700_000_000_000,
+ extension: Some(ext.into()),
+ }
+ }
+
+ fn db_con_archivos(n: usize) -> (MonadDb, Vec<FileId>) {
+ let mut db = MonadDb::new();
+ let mut ids = Vec::new();
+ for i in 0..n {
+ let f = mk(&format!("/proj/src/f{i}.rs"), "rs");
+ ids.push(f.id);
+ db.insert_file(f);
+ }
+ (db, ids)
+ }
+
+ #[test]
+ fn crear_agregar_y_recalcular_centroide() {
+ let (mut db, files) = db_con_archivos(2);
+ let m = create_monad(&mut db, "src", Lens::Code);
+ assert!(db.monad(m).unwrap().centroid.is_empty());
+
+ add_member(&mut db, m, files[0]).unwrap();
+ add_member(&mut db, m, files[1]).unwrap();
+ let mon = db.monad(m).unwrap();
+ assert_eq!(mon.cardinality, 2);
+ assert!(!mon.centroid.is_empty(), "el centroide se recalcula al agregar");
+ assert_eq!(mon.centroid_model.as_deref(), Some(embed::MODEL_ID));
+
+ remove_member(&mut db, m, files[0]).unwrap();
+ assert_eq!(db.monad(m).unwrap().cardinality, 1);
+ }
+
+ #[test]
+ fn add_submonad_rechaza_ciclo() {
+ let mut db = MonadDb::new();
+ let a = create_monad(&mut db, "A", Lens::Grid);
+ let b = create_monad(&mut db, "B", Lens::Grid);
+ add_submonad(&mut db, a, b).unwrap(); // A ⊃ B
+ // B ⊃ A cerraría el ciclo.
+ assert_eq!(add_submonad(&mut db, b, a), Err(EditError::Cycle { parent: b, child: a }));
+ // A ⊃ A también.
+ assert_eq!(add_submonad(&mut db, a, a), Err(EditError::Cycle { parent: a, child: a }));
+ }
+
+ #[test]
+ fn submonadizar_traslada_la_seleccion() {
+ let (mut db, files) = db_con_archivos(3);
+ let padre = create_monad(&mut db, "todo", Lens::Code);
+ for f in &files {
+ add_member(&mut db, padre, *f).unwrap();
+ }
+ assert_eq!(db.monad(padre).unwrap().cardinality, 3);
+
+ // Submonadizar dos de los tres archivos a una hija "sub".
+ let hija = submonadize(&mut db, padre, "sub", &files[0..2], &[]).unwrap();
+
+ // El padre queda con 1 archivo + la hija como sub-Mónada.
+ let p = db.monad(padre).unwrap();
+ assert_eq!(p.cardinality, 1, "el padre soltó 2 archivos");
+ assert!(p.submonads.contains(&hija));
+
+ // La hija tiene los 2 archivos y lineage al padre.
+ let h = db.monad(hija).unwrap();
+ assert_eq!(h.cardinality, 2);
+ assert_eq!(h.lineage, Some(padre));
+
+ // Los 3 archivos siguen alcanzables transitivamente desde el padre.
+ assert_eq!(resolve::transitive_files(&db, padre).len(), 3);
+ }
+
+ #[test]
+ fn fusionar_repunta_padres_y_borra_origen() {
+ let (mut db, files) = db_con_archivos(2);
+ let raiz = create_monad(&mut db, "raíz", Lens::Grid);
+ let a = create_monad(&mut db, "A", Lens::Code);
+ let b = create_monad(&mut db, "B", Lens::Code);
+ add_member(&mut db, a, files[0]).unwrap();
+ add_member(&mut db, b, files[1]).unwrap();
+ add_submonad(&mut db, raiz, a).unwrap();
+ add_submonad(&mut db, raiz, b).unwrap();
+
+ // Fusionar B en A: A se queda con ambos archivos, B desaparece, y
+ // raíz deja de apuntar a B.
+ merge(&mut db, a, b).unwrap();
+ assert!(db.monad(b).is_none(), "B se borró");
+ assert_eq!(db.monad(a).unwrap().cardinality, 2);
+ let raiz = db.monad(raiz).unwrap();
+ assert!(raiz.submonads.contains(&a));
+ assert!(!raiz.submonads.contains(&b), "raíz no apunta a una Mónada borrada");
+ }
+
+ #[test]
+ fn borrar_desvincula_de_padres() {
+ let mut db = MonadDb::new();
+ let raiz = create_monad(&mut db, "raíz", Lens::Grid);
+ let hija = create_monad(&mut db, "hija", Lens::Grid);
+ add_submonad(&mut db, raiz, hija).unwrap();
+
+ delete_monad(&mut db, hija);
+ assert!(db.monad(hija).is_none());
+ assert!(!db.monad(raiz).unwrap().submonads.contains(&hija), "sin referencia colgada");
+ }
+
+ #[test]
+ fn set_query_convierte_a_intensional_sin_perder_curados() {
+ let (mut db, files) = db_con_archivos(1);
+ let png = mk("/a/foto.png", "png");
+ let png_id = png.id;
+ db.insert_file(png);
+
+ let m = create_monad(&mut db, "mix", Lens::Grid);
+ add_member(&mut db, m, files[0]).unwrap(); // un .rs curado
+ set_query(&mut db, m, Some(MonadQuery::imagenes())).unwrap();
+
+ // effective_members = el .rs curado + el .png por la query.
+ let eff = resolve::effective_members(&db, m);
+ assert!(eff.contains(&files[0]));
+ assert!(eff.contains(&png_id));
+ assert_eq!(eff.len(), 2);
+ }
+}
diff --git a/02_ruway/chasqui/chasqui-core/src/engine_socket.rs b/02_ruway/chasqui/chasqui-core/src/engine_socket.rs
index 5aa38fb..8369f68 100644
--- a/02_ruway/chasqui/chasqui-core/src/engine_socket.rs
+++ b/02_ruway/chasqui/chasqui-core/src/engine_socket.rs
@@ -10,7 +10,7 @@
//! que `chasqui-nous` (mock/real ↔ chasqui-core), reutilizado.
//!
//! Threading: un thread dedicado, blocking I/O. No vale la pena traer
-//! tokio acá — la frecuencia esperada es muy baja (UI poll cada 2s)
+//! tokio aquí — la frecuencia esperada es muy baja (UI poll cada 2s)
//! y el handler es trivial (lock db → snapshot → write).
use std::io::{BufRead, BufReader, Write};
diff --git a/02_ruway/chasqui/chasqui-core/src/grafo.rs b/02_ruway/chasqui/chasqui-core/src/grafo.rs
new file mode 100644
index 0000000..4fc908a
--- /dev/null
+++ b/02_ruway/chasqui/chasqui-core/src/grafo.rs
@@ -0,0 +1,191 @@
+//! Adaptador: el **grafo de contención de Mónadas** como [`GrafoNavegable`]
+//! (PLAN-GRAFO). Es el DAG que nahual muestra en su file-manager: una Mónada
+//! («Fotos») contiene sub-Mónadas («Viaje») y archivos; una misma sub-Mónada
+//! puede colgar de varios padres (multi-pertenencia). El eje es `submonads`
+//! (contención), no `lineage` (derivación histórica split/merge).
+//!
+//! Verbos del dominio (ver [`nahual_source_core::MonadGraphMut`]): **Saltar**
+//! (abrir la Mónada) y, sobre una selección, **Cercenar** (disolver el
+//! agrupamiento — `delete_monad`; no borra los archivos). No hay *Restablecer*
+//! ni *Conciliar* por nodo: el merge de Mónadas (`merge_monads`) es entre dos y
+//! no encaja en el menú de un solo nodo.
+//!
+//! `MonadId` es un `Ulid` (128 bits) y no cabe en `NodoId = u64`, así que el
+//! adaptador mantiene la tabla `ids` para traducir de vuelta.
+
+use grafo_nav::{GrafoNavegable, Nodo, NodoId, Rol, Verbo};
+
+use chasqui_card::MonadId;
+
+use crate::db::MonadDb;
+
+/// Un **snapshot owned** del DAG de contención de Mónadas de una [`MonadDb`]. No
+/// retiene el borrow de la DB (copia label/entropy/aristas), así puede cruzar la
+/// frontera `dyn Source` de nahual —construido dentro de `with_db(...)` y
+/// devuelto— sin pelear con el `RwLock`.
+pub struct GrafoMonadas {
+ /// `(id, label, entropy)` por nodo, en orden de la DB (índice = `NodoId`).
+ nodos: Vec<(MonadId, String, f32)>,
+ /// Aristas `(contenedora, contenida)` por `MonadId`.
+ aristas: Vec<(MonadId, MonadId)>,
+ /// Mónada en foco (se pinta [`Rol::Activo`]).
+ activo: Option<MonadId>,
+}
+
+impl GrafoMonadas {
+ /// Toma el snapshot desde la DB: nodos + aristas de contención (`submonads`
+ /// hacia Mónadas presentes).
+ pub fn from_db(db: &MonadDb) -> Self {
+ let nodos: Vec<(MonadId, String, f32)> = db
+ .monads()
+ .map(|m| (m.id, m.label.clone(), m.entropy))
+ .collect();
+ let presentes = alloc_set(&nodos);
+ let mut aristas = Vec::new();
+ for m in db.monads() {
+ for sub in &m.submonads {
+ if presentes.contains(sub) {
+ aristas.push((m.id, *sub));
+ }
+ }
+ }
+ Self { nodos, aristas, activo: None }
+ }
+
+ /// Marca la Mónada en foco (se pinta [`Rol::Activo`]).
+ pub fn con_activo(mut self, activo: Option<MonadId>) -> Self {
+ self.activo = activo;
+ self
+ }
+
+ /// Traduce el id compacto del visor al `MonadId` real (para abrir/seleccionar
+ /// la Mónada al clickear un nodo).
+ pub fn monad_id_de(&self, id: NodoId) -> Option<MonadId> {
+ self.nodos.get(id as usize).map(|(m, _, _)| *m)
+ }
+
+ /// Traduce un `MonadId` al id compacto del visor.
+ pub fn id_de(&self, m: &MonadId) -> Option<NodoId> {
+ self.nodos.iter().position(|(x, _, _)| x == m).map(|i| i as NodoId)
+ }
+}
+
+impl GrafoNavegable for GrafoMonadas {
+ fn nodos(&self) -> Vec<Nodo> {
+ self.nodos
+ .iter()
+ .enumerate()
+ .map(|(i, (mid, label, entropy))| {
+ let rol = if self.activo == Some(*mid) {
+ Rol::Activo
+ } else if *entropy > 0.66 {
+ // Mónada dispersa: el manifiesto sugiere bifurcarla.
+ Rol::Stale
+ } else {
+ Rol::Normal
+ };
+ let etiqueta = if label.is_empty() {
+ String::from("(sin nombre)")
+ } else {
+ label.clone()
+ };
+ Nodo::new(i as NodoId, etiqueta, rol)
+ })
+ .collect()
+ }
+
+ fn aristas(&self) -> Vec<(NodoId, NodoId)> {
+ // Contención: `(contenedora → contenida)` = `(ancestro → descendiente)`.
+ self.aristas
+ .iter()
+ .filter_map(|(f, t)| Some((self.id_de(f)?, self.id_de(t)?)))
+ .collect()
+ }
+
+ fn acciones(&self, seleccion: Option<NodoId>) -> Vec<Verbo> {
+ let mut v = vec![Verbo::Saltar];
+ if seleccion.is_some() {
+ // Cercenar = disolver el agrupamiento (delete_monad); no toca archivos.
+ v.push(Verbo::Cercenar);
+ }
+ v
+ }
+}
+
+/// Conjunto de los `MonadId` presentes en el snapshot (para descartar aristas a
+/// sub-Mónadas ausentes).
+fn alloc_set(nodos: &[(MonadId, String, f32)]) -> std::collections::BTreeSet<MonadId> {
+ nodos.iter().map(|(id, _, _)| *id).collect()
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+ use chasqui_card::MonadManifest;
+
+ /// DB en contención: raíz «Fotos» contiene «Viaje» y «Familia»; «Viaje»
+ /// contiene «Cusco». Devuelve (db, id_fotos, id_viaje, id_cusco).
+ fn db_contencion() -> (MonadDb, MonadId, MonadId, MonadId) {
+ let mut cusco = MonadManifest::new("Cusco");
+ let mut viaje = MonadManifest::new("Viaje");
+ let mut familia = MonadManifest::new("Familia");
+ let mut fotos = MonadManifest::new("Fotos");
+ viaje.submonads.insert(cusco.id);
+ fotos.submonads.insert(viaje.id);
+ fotos.submonads.insert(familia.id);
+ // Marcar una dispersa para el test de rol.
+ familia.entropy = 0.9;
+ let (fid, vid, cid) = (fotos.id, viaje.id, cusco.id);
+ let mut db = MonadDb::new();
+ for m in [cusco, viaje, familia, fotos] {
+ db.insert_monad(m);
+ }
+ (db, fid, vid, cid)
+ }
+
+ #[test]
+ fn estructura_de_contencion() {
+ let (db, fotos, viaje, cusco) = db_contencion();
+ let g = GrafoMonadas::from_db(&db);
+ assert_eq!(g.nodos().len(), 4);
+ // Aristas: fotos→viaje, fotos→familia, viaje→cusco = 3.
+ assert_eq!(g.aristas().len(), 3);
+ // «Fotos» es raíz (nadie la contiene); «Cusco»/«Familia» son cabezas.
+ let raices: Vec<MonadId> =
+ g.raices().iter().filter_map(|id| g.monad_id_de(*id)).collect();
+ assert_eq!(raices, vec![fotos]);
+ // El cono descendente de «Fotos» es todo (4).
+ let cono = g.cono_descendente(g.id_de(&fotos).unwrap());
+ assert_eq!(cono.len(), 4);
+ // «Cusco» es una hoja: su cono descendente es sólo él.
+ assert_eq!(g.cono_descendente(g.id_de(&cusco).unwrap()).len(), 1);
+ assert!(g.cabezas().contains(&g.id_de(&cusco).unwrap()));
+ let _ = viaje;
+ }
+
+ #[test]
+ fn rol_activo_y_dispersa() {
+ let (db, fotos, _viaje, _cusco) = db_contencion();
+ let g = GrafoMonadas::from_db(&db).con_activo(Some(fotos));
+ let nodos = g.nodos();
+ let rol = |mid: &MonadId| {
+ let nid = g.id_de(mid).unwrap();
+ nodos.iter().find(|n| n.id == nid).unwrap().rol
+ };
+ assert_eq!(rol(&fotos), Rol::Activo, "el foco gana");
+ // «Familia» tiene entropy 0.9 → Stale (sugerencia de bifurcar).
+ assert!(nodos.iter().any(|n| n.rol == Rol::Stale));
+ }
+
+ #[test]
+ fn verbos_saltar_y_cercenar() {
+ let (db, _f, _v, _c) = db_contencion();
+ let g = GrafoMonadas::from_db(&db);
+ assert_eq!(g.acciones(None), vec![Verbo::Saltar]);
+ let sel = g.acciones(Some(0));
+ assert!(sel.contains(&Verbo::Saltar));
+ assert!(sel.contains(&Verbo::Cercenar));
+ assert!(!sel.contains(&Verbo::Conciliar));
+ assert!(!sel.contains(&Verbo::Restablecer));
+ }
+}
diff --git a/02_ruway/chasqui/chasqui-core/src/lib.rs b/02_ruway/chasqui/chasqui-core/src/lib.rs
index e0ce4f1..247cb51 100644
--- a/02_ruway/chasqui/chasqui-core/src/lib.rs
+++ b/02_ruway/chasqui/chasqui-core/src/lib.rs
@@ -27,8 +27,12 @@
pub mod cluster;
pub mod db;
+pub mod edit;
pub mod embed;
pub mod engine_socket;
+pub mod grafo;
+pub mod resolve;
pub mod scanner;
pub use chasqui_card::*;
+pub use grafo::GrafoMonadas;
diff --git a/02_ruway/chasqui/chasqui-core/src/resolve.rs b/02_ruway/chasqui/chasqui-core/src/resolve.rs
new file mode 100644
index 0000000..7101683
--- /dev/null
+++ b/02_ruway/chasqui/chasqui-core/src/resolve.rs
@@ -0,0 +1,303 @@
+//! Resolución del **grafo de Mónadas**: contención (sub-Mónadas) +
+//! cuerpo intensional (queries).
+//!
+//! El modelo (`chasqui-card`) ahora describe un DAG: una Mónada contiene
+//! archivos (`members`) y/o otras Mónadas (`submonads`), y puede definir
+//! su membresía por una regla ([`MonadQuery`]) en vez de a mano. Este
+//! módulo es la lógica que *recorre* ese grafo:
+//!
+//! - [`resolve_query`] evalúa un predicado contra un corpus de archivos.
+//! - [`effective_members`] da los archivos directos de una Mónada
+//! (curados + intensional + pines).
+//! - [`transitive_files`] baja por las sub-Mónadas (guardando ciclos y
+//! diamantes) y junta todos los archivos alcanzables.
+//! - [`child_monads`] resuelve las sub-Mónadas a sus manifiestos.
+//!
+//! Determinista y sin red. La hoja semántica [`MonadQuery::Near`] usa los
+//! pseudo-embeddings de [`crate::embed`]; el resto es puramente léxico.
+
+use std::collections::BTreeSet;
+
+use chasqui_card::{FileEntry, FileId, MonadId, MonadManifest, MonadQuery};
+
+use crate::cluster::lens_from_ext;
+use crate::db::MonadDb;
+use crate::embed;
+
+/// Evalúa una [`MonadQuery`] contra un corpus y devuelve los IDs de los
+/// archivos que la satisfacen.
+///
+/// `centroid` es el centroide de la Mónada dueña de la query — lo que la
+/// hoja [`MonadQuery::Near`] usa como referencia de "cerca de esto". Si
+/// la query no usa `Near`, `centroid` se ignora (pasa `&[]`).
+pub fn resolve_query<'a, I>(query: &MonadQuery, files: I, centroid: &[f32]) -> BTreeSet<FileId>
+where
+ I: IntoIterator<Item = &'a FileEntry>,
+{
+ files
+ .into_iter()
+ .filter(|f| matches(query, f, centroid))
+ .map(|f| f.id)
+ .collect()
+}
+
+/// Decide si un archivo satisface la query. Recursivo sobre el álgebra.
+fn matches(query: &MonadQuery, file: &FileEntry, centroid: &[f32]) -> bool {
+ match query {
+ MonadQuery::Extension { exts } => file
+ .extension
+ .as_deref()
+ .is_some_and(|e| exts.contains(e)),
+ // Lente determinista por extensión. Refinamiento futuro: discernir
+ // por contenido (shuma-discern) cuando la extensión miente; hoy nos
+ // quedamos en el mapeo barato y sin disco, coherente con el lente
+ // que el clustering asigna.
+ MonadQuery::Lens { lens } => lens_from_ext(file.extension.as_deref()) == *lens,
+ MonadQuery::Near { min_similarity } => {
+ if centroid.is_empty() {
+ return false;
+ }
+ // Recalcula el embedding por nodo Near; las queries reales
+ // tienen ≤1, así que no vale la pena cachear todavía.
+ let v = embed::embed(file);
+ embed::cosine_similarity(&v, centroid) >= *min_similarity
+ }
+ MonadQuery::All { of } => of.iter().all(|sub| matches(sub, file, centroid)),
+ MonadQuery::Any { of } => of.iter().any(|sub| matches(sub, file, centroid)),
+ MonadQuery::Not { inner } => !matches(inner, file, centroid),
+ }
+}
+
+/// Archivos **directos** de una Mónada: la unión de sus miembros curados,
+/// los miembros derivados de su cuerpo intensional (si tiene `query`), y
+/// sus pines. No baja por las sub-Mónadas (para eso, [`transitive_files`]).
+///
+/// Mónada inexistente ⇒ conjunto vacío.
+pub fn effective_members(db: &MonadDb, id: MonadId) -> BTreeSet<FileId> {
+ let Some(m) = db.monad(id) else {
+ return BTreeSet::new();
+ };
+ let mut out: BTreeSet<FileId> = m.members.iter().copied().collect();
+ out.extend(m.pins.iter().copied());
+ if let Some(query) = &m.query {
+ out.extend(resolve_query(query, db.files(), &m.centroid));
+ }
+ out
+}
+
+/// Sub-Mónadas directas de una Mónada, resueltas a sus manifiestos.
+/// Skipea silenciosamente IDs colgados (sub-Mónada borrada).
+pub fn child_monads(db: &MonadDb, id: MonadId) -> Vec<&MonadManifest> {
+ match db.monad(id) {
+ Some(m) => m.submonads.iter().filter_map(|sid| db.monad(*sid)).collect(),
+ None => Vec::new(),
+ }
+}
+
+/// Todos los archivos alcanzables desde una Mónada bajando por el DAG de
+/// sub-Mónadas. Cuenta cada archivo una sola vez aunque sea alcanzable por
+/// varios caminos (es un `BTreeSet`), y termina aunque el grafo tenga
+/// ciclos o diamantes gracias al set de visitados.
+pub fn transitive_files(db: &MonadDb, root: MonadId) -> BTreeSet<FileId> {
+ let mut visited: BTreeSet<MonadId> = BTreeSet::new();
+ let mut files: BTreeSet<FileId> = BTreeSet::new();
+ collect_files(db, root, &mut visited, &mut files);
+ files
+}
+
+fn collect_files(
+ db: &MonadDb,
+ id: MonadId,
+ visited: &mut BTreeSet<MonadId>,
+ files: &mut BTreeSet<FileId>,
+) {
+ // Guarda de ciclos/diamantes: cada Mónada se visita una vez.
+ if !visited.insert(id) {
+ return;
+ }
+ let Some(m) = db.monad(id) else {
+ return;
+ };
+ files.extend(effective_members(db, id));
+ for sub in &m.submonads {
+ collect_files(db, *sub, visited, files);
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+ use chasqui_card::{FileId, Lens};
+ use std::collections::BTreeSet;
+ use std::path::PathBuf;
+ use ulid::Ulid;
+
+ fn mk(path: &str, ext: Option<&str>, size: u64) -> FileEntry {
+ FileEntry {
+ id: FileId::from(Ulid::new()),
+ path: PathBuf::from(path),
+ content_hash: None,
+ size,
+ mtime_ms: 1_700_000_000_000,
+ extension: ext.map(String::from),
+ }
+ }
+
+ fn exts(list: &[&str]) -> MonadQuery {
+ MonadQuery::Extension {
+ exts: list.iter().map(|s| s.to_string()).collect(),
+ }
+ }
+
+ #[test]
+ fn query_extension_selecciona_por_formato() {
+ let corpus = vec![
+ mk("/a/1.png", Some("png"), 100),
+ mk("/a/2.jpg", Some("jpg"), 100),
+ mk("/a/3.rs", Some("rs"), 100),
+ ];
+ let hit = resolve_query(&exts(&["png", "jpg"]), &corpus, &[]);
+ assert_eq!(hit.len(), 2);
+ assert!(hit.contains(&corpus[0].id));
+ assert!(hit.contains(&corpus[1].id));
+ assert!(!hit.contains(&corpus[2].id));
+ }
+
+ #[test]
+ fn query_lens_gallery_capta_imagenes() {
+ let corpus = vec![
+ mk("/a/1.png", Some("png"), 100),
+ mk("/a/2.heic", Some("heic"), 100),
+ mk("/a/3.rs", Some("rs"), 100),
+ ];
+ let hit = resolve_query(&MonadQuery::imagenes(), &corpus, &[]);
+ assert_eq!(hit.len(), 2, "png + heic son Gallery, rs no");
+ }
+
+ #[test]
+ fn query_not_y_all_componen() {
+ let corpus = vec![
+ mk("/a/1.png", Some("png"), 100),
+ mk("/a/2.rs", Some("rs"), 100),
+ ];
+ // "imágenes que NO sean png" → vacío (sólo hay png entre imágenes).
+ let q = MonadQuery::All {
+ of: vec![
+ MonadQuery::imagenes(),
+ MonadQuery::Not { inner: Box::new(exts(&["png"])) },
+ ],
+ };
+ assert!(resolve_query(&q, &corpus, &[]).is_empty());
+ }
+
+ #[test]
+ fn query_near_usa_centroide() {
+ // Centroide de un cluster de .rs en /proj/src.
+ let rust = vec![
+ embed::embed(&mk("/proj/src/a.rs", Some("rs"), 1000)).to_vec(),
+ embed::embed(&mk("/proj/src/b.rs", Some("rs"), 1100)).to_vec(),
+ ];
+ let centroid = embed::centroid(&rust);
+
+ let corpus = vec![
+ mk("/proj/src/c.rs", Some("rs"), 1200), // cerca
+ mk("/photos/x.jpg", Some("jpg"), 5_000_000), // lejos
+ ];
+ let hit = resolve_query(&MonadQuery::Near { min_similarity: 0.7 }, &corpus, ¢roid);
+ assert!(hit.contains(&corpus[0].id), "el .rs debe caer cerca del centroide");
+ assert!(!hit.contains(&corpus[1].id), "la foto debe quedar lejos");
+ }
+
+ #[test]
+ fn near_sin_centroide_no_matchea() {
+ let corpus = vec![mk("/a/x.rs", Some("rs"), 100)];
+ let hit = resolve_query(&MonadQuery::Near { min_similarity: 0.0 }, &corpus, &[]);
+ assert!(hit.is_empty(), "sin centroide, Near no puede decidir");
+ }
+
+ #[test]
+ fn effective_members_une_curados_y_query() {
+ let mut db = MonadDb::new();
+ let png = mk("/a/1.png", Some("png"), 100);
+ let rs = mk("/a/2.rs", Some("rs"), 100);
+ let png_id = png.id;
+ let rs_id = rs.id;
+ db.insert_file(png.clone());
+ db.insert_file(rs.clone());
+
+ // Mónada intensional "imágenes" + un .rs fijado a mano como miembro.
+ let mut m = MonadManifest::new("mixta");
+ m.query = Some(MonadQuery::imagenes());
+ m.members.insert(rs_id);
+ m.touch();
+ let mid = m.id;
+ db.insert_monad(m);
+
+ let eff = effective_members(&db, mid);
+ assert!(eff.contains(&png_id), "el png entra por la query");
+ assert!(eff.contains(&rs_id), "el rs entra por miembro curado");
+ assert_eq!(eff.len(), 2);
+ }
+
+ #[test]
+ fn transitive_baja_por_submonadas_y_dedup() {
+ let mut db = MonadDb::new();
+ let f1 = mk("/album/1.jpg", Some("jpg"), 100);
+ let f2 = mk("/album/2.jpg", Some("jpg"), 100);
+ let f1_id = f1.id;
+ let f2_id = f2.id;
+ db.insert_file(f1);
+ db.insert_file(f2);
+
+ // Álbum extensional con dos fotos.
+ let mut album = MonadManifest::new("Viaje");
+ album.members.insert(f1_id);
+ album.members.insert(f2_id);
+ album.touch();
+ let album_id = album.id;
+ db.insert_monad(album);
+
+ // "Fotos" contiene al álbum (sub-Mónada) y además una de las fotos
+ // directamente — el mismo archivo alcanzable por dos caminos.
+ let mut fotos = MonadManifest::new("Fotos");
+ fotos.submonads.insert(album_id);
+ fotos.members.insert(f1_id);
+ fotos.touch();
+ let fotos_id = fotos.id;
+ db.insert_monad(fotos);
+
+ let all = transitive_files(&db, fotos_id);
+ assert_eq!(all.len(), 2, "f1 contado una sola vez pese a dos caminos");
+ assert!(all.contains(&f1_id) && all.contains(&f2_id));
+
+ let kids = child_monads(&db, fotos_id);
+ assert_eq!(kids.len(), 1);
+ assert_eq!(kids[0].label, "Viaje");
+ }
+
+ #[test]
+ fn transitive_termina_con_ciclo() {
+ let mut db = MonadDb::new();
+ let f = mk("/x/a.rs", Some("rs"), 100);
+ let f_id = f.id;
+ db.insert_file(f);
+
+ let mut a = MonadManifest::new("A");
+ a.members.insert(f_id);
+ let a_id = a.id;
+ let mut b = MonadManifest::new("B");
+ b.members.insert(f_id);
+ let b_id = b.id;
+ // Ciclo: A contiene B, B contiene A.
+ a.submonads.insert(b_id);
+ b.submonads.insert(a_id);
+ a.touch();
+ b.touch();
+ db.insert_monad(a);
+ db.insert_monad(b);
+
+ // No debe colgarse; junta el único archivo.
+ let all = transitive_files(&db, a_id);
+ assert_eq!(all, BTreeSet::from([f_id]));
+ }
+}
diff --git a/02_ruway/chasqui/chasqui-explorer-llimphi/Cargo.toml b/02_ruway/chasqui/chasqui-explorer-llimphi/Cargo.toml
index 2f0ecd1..8bd450c 100644
--- a/02_ruway/chasqui/chasqui-explorer-llimphi/Cargo.toml
+++ b/02_ruway/chasqui/chasqui-explorer-llimphi/Cargo.toml
@@ -8,7 +8,6 @@ publish.workspace = true
description = "Explorador Llimphi de Mónadas: panel que descubre al daemon chasqui vía broker brahman y consulta sus Mónadas dinámicamente. Reemplazo del `chasqui-explorer` GPUI; el discovery (card-sidecar) y el cliente de query no cambian, sólo el frontend."
[dependencies]
-card-core = { workspace = true }
card-sidecar = { path = "../card-sidecar" }
chasqui-card = { path = "../chasqui-card" }
llimphi-ui = { workspace = true }
@@ -18,6 +17,10 @@ llimphi-widget-banner = { workspace = true }
llimphi-widget-card = { workspace = true }
llimphi-widget-menubar = { workspace = true }
llimphi-widget-context-menu = { workspace = true }
+llimphi-widget-skeleton = { workspace = true }
+llimphi-widget-empty = { workspace = true }
+llimphi-widget-toast = { workspace = true }
+llimphi-icons = { workspace = true }
llimphi-motion = { workspace = true }
app-bus = { workspace = true }
rimay-localize = { workspace = true }
diff --git a/02_ruway/chasqui/chasqui-explorer-llimphi/src/main.rs b/02_ruway/chasqui/chasqui-explorer-llimphi/src/main.rs
index 155a4e8..e46aee0 100644
--- a/02_ruway/chasqui/chasqui-explorer-llimphi/src/main.rs
+++ b/02_ruway/chasqui/chasqui-explorer-llimphi/src/main.rs
@@ -20,8 +20,9 @@
#![forbid(unsafe_code)]
+use std::hash::{Hash, Hasher};
use std::path::PathBuf;
-use std::time::Duration;
+use std::time::{Duration, Instant};
use card_sidecar::{await_provider_blocking, build_consumer_card, ConsumerError};
use chasqui_card::query::client as query_client;
@@ -32,13 +33,18 @@ use llimphi_ui::llimphi_layout::taffy::{
prelude::{length, percent, AlignItems, Dimension, FlexDirection, Size, Style},
Rect,
};
+use llimphi_ui::llimphi_raster::kurbo::Affine;
use llimphi_ui::llimphi_raster::peniko::Color;
use llimphi_ui::llimphi_text::Alignment;
use llimphi_ui::{App, Handle, Key, KeyEvent, KeyState, NamedKey, View};
use llimphi_motion::{animate, motion, Tween};
+use llimphi_icons::Icon;
use llimphi_widget_app_header::{app_header, AppHeaderPalette};
use llimphi_widget_banner::{banner_view, BannerKind};
use llimphi_widget_card::{card_view, CardOptions, CardPalette};
+use llimphi_widget_empty::{empty_view, EmptyPalette};
+use llimphi_widget_skeleton::{skeleton_view, SkeletonPalette};
+use llimphi_widget_toast::{toast_stack_view, Toast};
use llimphi_widget_context_menu::{
context_menu_view, ContextMenuItem, ContextMenuPalette, ContextMenuSpec,
};
@@ -53,6 +59,18 @@ use std::sync::Arc;
const REFRESH_INTERVAL: Duration = Duration::from_secs(2);
const DISCOVERY_TIMEOUT: Duration = Duration::from_secs(3);
const QUERY_TIMEOUT: Duration = Duration::from_secs(2);
+/// Cuánto vive un toast antes de auto-descartarse.
+const TOAST_TTL: Duration = Duration::from_secs(4);
+/// Cadencia del repaint que anima el shimmer del skeleton mientras carga.
+const SHIMMER_MS: u64 = 50;
+
+/// Hash estable de una cadena → `key` para animaciones implícitas (la misma
+/// Mónada produce siempre la misma key entre rebuilds).
+fn key_of(s: &str) -> u64 {
+ let mut h = std::collections::hash_map::DefaultHasher::new();
+ s.hash(&mut h);
+ h.finish()
+}
struct Model {
theme: Theme,
@@ -76,6 +94,15 @@ struct Model {
/// Menú contextual sobre una Mónada: `(idx, x, y)` ancla en ventana.
/// `None` cerrado.
context_menu: Option<(usize, f32, f32)>,
+ /// Esperando la primera respuesta del daemon (muestra skeleton en vez de
+ /// hueco vacío). Baja al primer `Refresh`, sea Ok o fallo.
+ loading: bool,
+ /// Toasts vivos (errores de conexión, acciones del usuario).
+ toasts: Vec<Toast>,
+ /// Id incremental para correlacionar toast ↔ Msg de expiración.
+ next_toast: u64,
+ /// Hay una cadena de `Msg::Anim` en vuelo (evita rearmar dos).
+ ticking: bool,
}
#[derive(Clone)]
@@ -105,6 +132,11 @@ enum Msg {
/// `(x, y)` de ventana sobre la Mónada seleccionada. Sin selección
/// es no-op.
ContextMenuOpen(f32, f32),
+ /// Tick de animación — fuerza repaint para el shimmer del skeleton mientras
+ /// esperamos la primera respuesta. Se auto-rearma sólo si sigue cargando.
+ Anim,
+ /// Un toast cumplió su `duration`: se descarta del stack.
+ ToastExpire(u64),
}
#[derive(Clone)]
@@ -143,7 +175,7 @@ impl App for Explorer {
handle.dispatch(Msg::Tick);
handle.spawn_periodic(REFRESH_INTERVAL, || Msg::Tick);
- Model {
+ let mut m = Model {
theme: Theme::dark(),
socket: None,
snapshot: None,
@@ -154,7 +186,14 @@ impl App for Explorer {
menu_anim: Tween::idle(1.0),
selected: None,
context_menu: None,
- }
+ loading: true,
+ toasts: Vec::new(),
+ next_toast: 0,
+ ticking: false,
+ };
+ // Shimmer del skeleton mientras llega la primera respuesta.
+ ensure_anim(&mut m, handle);
+ m
}
fn on_key(model: &Model, event: &KeyEvent) -> Option<Msg> {
@@ -185,33 +224,47 @@ impl App for Explorer {
let prior_socket = m.socket.clone();
handle.spawn(move || Msg::Refresh(tick(prior_socket)));
}
- Msg::Refresh(outcome) => match outcome {
- TickOutcome::Ok { socket, source, snapshot } => {
- m.socket = Some(socket);
- m.socket_source = Some(source);
- m.snapshot = Some(*snapshot);
- m.error = None;
- // Si la selección quedó fuera de rango tras el
- // refresh, la descartamos.
- let count = m.snapshot.as_ref().map(|s| s.monads.len()).unwrap_or(0);
- if m.selected.map(|i| i >= count).unwrap_or(false) {
- m.selected = None;
- m.context_menu = None;
+ Msg::Refresh(outcome) => {
+ // Primera respuesta recibida: apaga el skeleton.
+ m.loading = false;
+ // Toast de error sólo en la *transición* a fallo (None→Some);
+ // si el daemon sigue caído el error persiste y no spammeamos.
+ let tenia_error = m.error.is_some();
+ match outcome {
+ TickOutcome::Ok { socket, source, snapshot } => {
+ m.socket = Some(socket);
+ m.socket_source = Some(source);
+ m.snapshot = Some(*snapshot);
+ m.error = None;
+ // Si la selección quedó fuera de rango tras el
+ // refresh, la descartamos.
+ let count = m.snapshot.as_ref().map(|s| s.monads.len()).unwrap_or(0);
+ if m.selected.map(|i| i >= count).unwrap_or(false) {
+ m.selected = None;
+ m.context_menu = None;
+ }
+ }
+ TickOutcome::DiscoveryFailed(msg) => {
+ m.socket = None;
+ m.socket_source = None;
+ m.error = Some(msg);
+ }
+ TickOutcome::QueryFailed(msg) => {
+ // Invalida el socket cacheado: la próxima iteración
+ // re-descubre.
+ m.socket = None;
+ m.socket_source = None;
+ m.error = Some(msg);
}
}
- TickOutcome::DiscoveryFailed(msg) => {
- m.socket = None;
- m.socket_source = None;
- m.error = Some(msg);
- }
- TickOutcome::QueryFailed(msg) => {
- // Invalida el socket cacheado: la próxima iteración
- // re-descubre.
- m.socket = None;
- m.socket_source = None;
- m.error = Some(msg);
+ if !tenia_error {
+ if let Some(e) = m.error.clone() {
+ let id = m.next_toast;
+ m.next_toast += 1;
+ push_toast(&mut m, handle, Toast::error(id, e, TOAST_TTL));
+ }
}
- },
+ }
Msg::MenuOpen(which) => {
m.menu_open = which;
// Abrir un menú raíz cierra cualquier contextual.
@@ -256,6 +309,11 @@ impl App for Explorer {
m.socket = None;
m.socket_source = None;
m.error = None;
+ m.loading = true;
+ ensure_anim(&mut m, handle);
+ let id = m.next_toast;
+ m.next_toast += 1;
+ push_toast(&mut m, handle, Toast::info(id, "Reconectando…", TOAST_TTL));
handle.dispatch(Msg::Tick);
}
Msg::SelectMonad(i) => {
@@ -270,7 +328,16 @@ impl App for Explorer {
m.context_menu = Some((i, x, y));
}
}
+ Msg::Anim => {
+ // El thread durmió; sólo rearmamos si seguimos cargando (abajo).
+ m.ticking = false;
+ }
+ Msg::ToastExpire(id) => {
+ m.toasts.retain(|t| t.id != id);
+ }
}
+ // Si quedó una carga en vuelo, mantén el shimmer animado.
+ ensure_anim(&mut m, handle);
m
}
@@ -321,8 +388,32 @@ impl App for Explorer {
body_children.push(banner_view::<Msg>(BannerKind::Error, e.clone()));
}
- if let Some(snap) = &model.snapshot {
+ if model.loading && model.snapshot.is_none() {
+ // Esperando la primera respuesta: cards-placeholder con shimmer en
+ // vez de un hueco vacío. Requiere los ticks de `Msg::Anim`.
+ body_children.extend(skeleton_cards(theme));
+ } else if let Some(snap) = &model.snapshot {
body_children.push(engine_card(snap, accent_engine, theme, &card_palette));
+ if snap.monads.is_empty() {
+ // Engine vivo pero sin Mónadas todavía: estado vacío con
+ // orientación, no un hueco.
+ body_children.push(
+ View::new(Style {
+ size: Size {
+ width: percent(1.0_f32),
+ height: length(220.0_f32),
+ },
+ flex_grow: 1.0,
+ ..Default::default()
+ })
+ .children(vec![empty_view(
+ Icon::Search,
+ "Sin Mónadas",
+ Some("El engine está vivo pero todavía no expone Mónadas. Aparecerán aquí en cuanto el daemon las indexe."),
+ &EmptyPalette::from_theme(theme),
+ )]),
+ );
+ }
for (i, m) in snap.monads.iter().enumerate() {
let selected = model.selected == Some(i);
let card = monad_card(m, accent_data, theme, &card_palette);
@@ -336,6 +427,9 @@ impl App for Explorer {
} else {
card
};
+ // Pop-in: cada Mónada entra con un fade la primera vez que
+ // aparece su key (estable por id).
+ let card = card.animated_enter(key_of(&m.id.to_string()), motion::NORMAL);
body_children.push(card);
}
}
@@ -360,9 +454,13 @@ impl App for Explorer {
..Default::default()
})
.fill(theme.bg_app)
- .children(body_children);
+ .children(body_children)
+ // Transición de escena: al pasar entre cargando / error / conectado la
+ // `scene_key` cambia y el cuerpo entra con fade + slide-up en vez de
+ // saltar.
+ .animated_enter_from(scene_key(model), motion::SLOW, Affine::translate((0.0, 24.0)));
- View::new(Style {
+ let root = View::new(Style {
flex_direction: FlexDirection::Column,
size: Size {
width: percent(1.0_f32),
@@ -374,7 +472,24 @@ impl App for Explorer {
// Right-click en la raíz (origen 0,0 ⇒ local == ventana) abre el
// menú contextual sobre la Mónada seleccionada.
.on_right_click_at(|x, y, _w, _h| Some(Msg::ContextMenuOpen(x, y)))
- .children(vec![menubar, header, body])
+ .children(vec![menubar, header, body]);
+
+ // Overlay de toasts (bottom-right). Click en uno = descartarlo.
+ let now = Instant::now();
+ let alive: Vec<Toast> = model.toasts.iter().filter(|t| t.is_alive(now)).cloned().collect();
+ if alive.is_empty() {
+ root
+ } else {
+ let viewport = viewport_of(model);
+ View::new(Style {
+ size: Size {
+ width: percent(1.0_f32),
+ height: percent(1.0_f32),
+ },
+ ..Default::default()
+ })
+ .children(vec![root, toast_stack_view(&alive, viewport, Msg::ToastExpire)])
+ }
}
fn view_overlay(model: &Model) -> Option<View<Msg>> {
@@ -419,6 +534,43 @@ impl App for Explorer {
}
}
+/// Empuja un toast al stack y programa su expiración.
+fn push_toast(m: &mut Model, handle: &Handle<Msg>, toast: Toast) {
+ let id = toast.id;
+ m.toasts.push(toast);
+ handle.spawn(move || {
+ std::thread::sleep(TOAST_TTL);
+ Msg::ToastExpire(id)
+ });
+}
+
+/// Arranca la cadena de ticks de shimmer si seguimos esperando la primera
+/// respuesta y no hay ya una corriendo. La cadena se auto-detiene cuando
+/// `loading` baja (ver `Msg::Anim`), así no queda un repaint ocioso.
+fn ensure_anim(m: &mut Model, handle: &Handle<Msg>) {
+ if m.ticking || !m.loading {
+ return;
+ }
+ m.ticking = true;
+ handle.spawn(move || {
+ std::thread::sleep(Duration::from_millis(SHIMMER_MS));
+ Msg::Anim
+ });
+}
+
+/// `key` estable de la escena del cuerpo. Cambia al pasar entre cargando /
+/// error / conectado → dispara la transición de entrada del cuerpo; estable
+/// mientras la escena no cambia.
+fn scene_key(m: &Model) -> u64 {
+ if m.loading && m.snapshot.is_none() {
+ key_of("cargando")
+ } else if m.error.is_some() && m.snapshot.is_none() {
+ key_of("error")
+ } else {
+ key_of("conectado")
+ }
+}
+
/// Viewport para clampear overlays: tamaño de ventana del Model si lo
/// llevara; como el explorer no lo trackea, usamos `initial_size()`.
fn viewport_of(_model: &Model) -> (f32, f32) {
@@ -704,6 +856,51 @@ fn text_line(text: &str, color: Color, _theme: &Theme) -> View<Msg> {
.text_aligned(text.to_string(), 11.0, color, Alignment::Start)
}
+/// Cards-placeholder con shimmer mientras llega la primera respuesta del
+/// daemon — el usuario ve la forma de lo que viene, no un hueco. Requiere los
+/// repaints periódicos de `Msg::Anim` mientras `loading`.
+fn skeleton_cards(theme: &Theme) -> Vec<View<Msg>> {
+ let pal = SkeletonPalette::from_theme(theme);
+ // Un bloque lleno y clipeado para que el `skeleton_view` (absolute) pinte
+ // dentro de su caja.
+ let bloque = move |w: Dimension, h: f32| -> View<Msg> {
+ View::new(Style {
+ size: Size { width: w, height: length(h) },
+ flex_shrink: 0.0,
+ ..Default::default()
+ })
+ .radius(4.0_f64)
+ .clip(true)
+ .children(vec![skeleton_view::<Msg>(&pal)])
+ };
+ (0..4)
+ .map(|_| {
+ let titulo = bloque(percent(0.45_f32), 16.0);
+ let l1 = bloque(percent(0.7_f32), 11.0);
+ let l2 = bloque(percent(0.55_f32), 11.0);
+ View::new(Style {
+ flex_direction: FlexDirection::Column,
+ size: Size {
+ width: percent(1.0_f32),
+ height: Dimension::auto(),
+ },
+ padding: Rect {
+ left: length(12.0_f32),
+ right: length(12.0_f32),
+ top: length(12.0_f32),
+ bottom: length(12.0_f32),
+ },
+ gap: Size { width: length(0.0_f32), height: length(8.0_f32) },
+ flex_shrink: 0.0,
+ ..Default::default()
+ })
+ .fill(theme.bg_panel)
+ .radius(8.0_f64)
+ .children(vec![titulo, l1, l2])
+ })
+ .collect()
+}
+
fn tick(prior_socket: Option<PathBuf>) -> TickOutcome {
let (socket, source) = match prior_socket {
Some(p) => (p, "cache"),
diff --git a/02_ruway/chasqui/chasqui-nous-real/src/cache.rs b/02_ruway/chasqui/chasqui-nous-real/src/cache.rs
index cd1cde6..8662e7e 100644
--- a/02_ruway/chasqui/chasqui-nous-real/src/cache.rs
+++ b/02_ruway/chasqui/chasqui-nous-real/src/cache.rs
@@ -70,7 +70,7 @@ impl EmbedCache {
}
/// Almacena. Errores se loggean pero no propagan — cache miss es
- /// recuperable, no querés tirar el embed válido por fallo de I/O
+ /// recuperable, no quieres tirar el embed válido por fallo de I/O
/// de cache.
pub fn put(&self, file_sha: &[u8; 32], model_id: &str, embedding: &[f32]) {
let key = build_key(file_sha, model_id);
@@ -139,7 +139,7 @@ mod tests {
use super::*;
fn sha(s: &[u8]) -> [u8; 32] {
- arje_cas::sha256_of(s)
+ arje_cas::blake3_of(s)
}
#[test]
diff --git a/02_ruway/chasqui/chasqui-nous-real/src/embeddings.rs b/02_ruway/chasqui/chasqui-nous-real/src/embeddings.rs
index 28b0078..775c6fb 100644
--- a/02_ruway/chasqui/chasqui-nous-real/src/embeddings.rs
+++ b/02_ruway/chasqui/chasqui-nous-real/src/embeddings.rs
@@ -135,7 +135,7 @@ fn handle_file(
// bajo la semántica del proveedor (el modelo nunca vio los bytes
// adicionales). Si la cabeza cambia, el hash cambia y caemos a
// re-embed naturalmente.
- let file_sha = arje_cas::sha256_of(&buf);
+ let file_sha = arje_cas::blake3_of(&buf);
if let Some(cache) = cache {
if let Some(cached) = cache.get(&file_sha, model_id) {
diff --git a/02_ruway/chasqui/chasqui-nous-real/src/main.rs b/02_ruway/chasqui/chasqui-nous-real/src/main.rs
index 5ba8570..6813a2a 100644
--- a/02_ruway/chasqui/chasqui-nous-real/src/main.rs
+++ b/02_ruway/chasqui/chasqui-nous-real/src/main.rs
@@ -63,7 +63,7 @@ async fn main() -> std::io::Result<()> {
#[cfg(not(feature = "embeddings"))]
info!(
- "chasqui-nous-real corriendo en modo STUB (compilá con \
+ "chasqui-nous-real corriendo en modo STUB (compila con \
--features embeddings para activar el modelo)"
);
diff --git a/02_ruway/chasqui/chasqui-nous/src/lib.rs b/02_ruway/chasqui/chasqui-nous/src/lib.rs
index d85e37d..3c5f725 100644
--- a/02_ruway/chasqui/chasqui-nous/src/lib.rs
+++ b/02_ruway/chasqui/chasqui-nous/src/lib.rs
@@ -24,7 +24,7 @@
//! El consumidor (chasqui-core) y el proveedor (chasqui-nous-mock,
//! chasqui-nous-real) deben acordar en types EXACTOS. Tener el contrato
//! en su crate evita que cada lado declare structs paralelos que se
-//! desincronizan. Si bumpeás el wire, bumpeás aquí.
+//! desincronizan. Si bumpeas el wire, bumpeas aquí.
//!
//! ## Swap por priority_contexts
//!
diff --git a/Cargo.lock b/Cargo.lock
index 4adedba..9e3eb73 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -18,6 +18,114 @@ version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "366ffbaa4442f4684d91e2cd7c5ea7c4ed8add41959a31447066e279e432b618"
+[[package]]
+name = "accesskit"
+version = "0.24.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d3b7f7f85a7e5f68090000ed7622545829afd484d210358702ae4cb97dd0c320"
+dependencies = [
+ "uuid",
+]
+
+[[package]]
+name = "accesskit_atspi_common"
+version = "0.19.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "023da0e5097f46df7092d5280b02efb9bbf8d93298daeced42652463e357d636"
+dependencies = [
+ "accesskit",
+ "accesskit_consumer",
+ "atspi-common",
+ "phf",
+ "serde",
+ "zvariant",
+]
+
+[[package]]
+name = "accesskit_consumer"
+version = "0.38.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5d10a236f96f87d70732e44520046785431ef01d5bcd6b041317bfadd2f88245"
+dependencies = [
+ "accesskit",
+ "hashbrown 0.16.1",
+]
+
+[[package]]
+name = "accesskit_ios"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "750c4e9f6ce888dfe8a10c0f1b5ceb646a7854fd46579d74919219d1bb314083"
+dependencies = [
+ "accesskit",
+ "accesskit_consumer",
+ "hashbrown 0.16.1",
+ "objc2 0.5.2",
+ "objc2-foundation 0.2.2",
+ "objc2-ui-kit",
+]
+
+[[package]]
+name = "accesskit_macos"
+version = "0.26.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ce02dc63b43f0c9296af9ac946312a2dc8814427d7a64d2d600971dac55b6076"
+dependencies = [
+ "accesskit",
+ "accesskit_consumer",
+ "hashbrown 0.16.1",
+ "objc2 0.5.2",
+ "objc2-app-kit 0.2.2",
+ "objc2-foundation 0.2.2",
+]
+
+[[package]]
+name = "accesskit_unix"
+version = "0.22.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "03e156ed3802e35eefe894ef2671bc6c889303d8a7e110b5e1b48f504b91362f"
+dependencies = [
+ "accesskit",
+ "accesskit_atspi_common",
+ "async-channel",
+ "async-executor",
+ "async-task",
+ "atspi",
+ "futures-lite",
+ "futures-util",
+ "serde",
+ "zbus",
+]
+
+[[package]]
+name = "accesskit_windows"
+version = "0.34.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "106c2b961215864d1c2e703ee63269c25c4e80a577ffb2c1017b9c17dcdf83a1"
+dependencies = [
+ "accesskit",
+ "accesskit_consumer",
+ "hashbrown 0.16.1",
+ "static_assertions",
+ "windows 0.62.2",
+ "windows-core 0.62.2",
+]
+
+[[package]]
+name = "accesskit_winit"
+version = "0.33.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d5b41e63a69f36d9f1f41e70464c7e5f72eee485ef26aab19f0b4f86e6c0a84c"
+dependencies = [
+ "accesskit",
+ "accesskit_ios",
+ "accesskit_macos",
+ "accesskit_unix",
+ "accesskit_windows",
+ "raw-window-handle",
+ "winit",
+]
+
[[package]]
name = "adler2"
version = "2.0.1"
@@ -113,16 +221,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0f2a1bb052857d5dd49572219344a7332b31b76405648eabac5bc68978251bcd"
dependencies = [
"android-properties",
- "bitflags 2.12.1",
+ "bitflags 2.13.1",
"cc",
"jni",
"libc",
"log",
"ndk",
"ndk-context",
- "ndk-sys 0.6.0+11769913",
+ "ndk-sys",
"num_enum",
- "thiserror 2.0.18",
+ "thiserror 2.0.19",
]
[[package]]
@@ -142,14 +250,14 @@ dependencies = [
[[package]]
name = "anyhow"
-version = "1.0.102"
+version = "1.0.104"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c"
+checksum = "330a5ed07fa54e4702c9d6c4174f74427fc0ef6e214bbd677ae50a5099946470"
[[package]]
name = "app-bus"
version = "0.1.0"
-source = "git+https://gitea.tawasuyu.net/sergio/gioser.git?tag=v0.1.0#692b40336c1e9cb12ab561764d6943cb65905ab3"
+source = "git+https://git.tawasuyu.net/tawasuyu/tawasuyu.git?tag=v0.2.0#a446bb3a73a0e022158cc0ec7deb65173859644b"
dependencies = [
"directories",
"serde",
@@ -162,6 +270,27 @@ version = "1.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c3d036a3c4ab069c7b410a2ce876bd74808d2d0888a82667669f8e783a898bf1"
+[[package]]
+name = "arboard"
+version = "3.6.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0348a1c054491f4bfe6ab86a7b6ab1e44e45d899005de92f58b3df180b36ddaf"
+dependencies = [
+ "clipboard-win",
+ "image",
+ "log",
+ "objc2 0.6.4",
+ "objc2-app-kit 0.3.2",
+ "objc2-core-foundation",
+ "objc2-core-graphics",
+ "objc2-foundation 0.3.2",
+ "parking_lot 0.12.5",
+ "percent-encoding",
+ "windows-sys 0.60.2",
+ "wl-clipboard-rs",
+ "x11rb",
+]
+
[[package]]
name = "arg_enum_proc_macro"
version = "0.3.4"
@@ -170,16 +299,16 @@ checksum = "0ae92a5119aa49cdbcf6b9f893fe4e1d98b04ccbf82ee0584ad948a44a734dea"
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.119",
]
[[package]]
name = "arje-cas"
version = "0.0.1"
-source = "git+https://gitea.tawasuyu.net/sergio/gioser.git?tag=v0.1.0#692b40336c1e9cb12ab561764d6943cb65905ab3"
+source = "git+https://git.tawasuyu.net/tawasuyu/tawasuyu.git?tag=v0.2.0#a446bb3a73a0e022158cc0ec7deb65173859644b"
dependencies = [
"anyhow",
- "sha2",
+ "blake3",
"tracing",
]
@@ -191,9 +320,9 @@ checksum = "76a2e8124351fda1ef8aaaa3bbd7ebbcb486bbcd4225aca0aa0d84bb2db8fecb"
[[package]]
name = "arrayvec"
-version = "0.7.6"
+version = "0.7.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50"
+checksum = "d3fb67a6e08acf24fdeccbac2cb6ac4305825bd1f117462e0e6f2f193345ad56"
[[package]]
name = "as-raw-xcb-connection"
@@ -231,7 +360,7 @@ dependencies = [
"nom 7.1.3",
"num-traits",
"rusticata-macros",
- "thiserror 2.0.18",
+ "thiserror 2.0.19",
"time",
]
@@ -243,7 +372,7 @@ checksum = "3109e49b1e4909e9db6515a30c633684d68cdeaa252f215214cb4fa1a5bfee2c"
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.119",
"synstructure",
]
@@ -255,7 +384,45 @@ checksum = "7b18050c2cd6fe86c3a76584ef5e0baf286d038cda203eb6223df2cc413565f7"
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.119",
+]
+
+[[package]]
+name = "async-broadcast"
+version = "0.7.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "435a87a52755b8f27fcf321ac4f04b2802e337c8c4872923137471ec39c37532"
+dependencies = [
+ "event-listener",
+ "event-listener-strategy",
+ "futures-core",
+ "pin-project-lite",
+]
+
+[[package]]
+name = "async-channel"
+version = "2.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "924ed96dd52d1b75e9c1a3e6275715fd320f5f9439fb5a4a11fa51f4221158d2"
+dependencies = [
+ "concurrent-queue",
+ "event-listener-strategy",
+ "futures-core",
+ "pin-project-lite",
+]
+
+[[package]]
+name = "async-executor"
+version = "1.14.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c96bf972d85afc50bf5ab8fe2d54d1586b4e0b46c97c50a0c9e71e2f7bcd812a"
+dependencies = [
+ "async-task",
+ "concurrent-queue",
+ "fastrand",
+ "futures-lite",
+ "pin-project-lite",
+ "slab",
]
[[package]]
@@ -276,15 +443,79 @@ dependencies = [
"windows-sys 0.61.2",
]
+[[package]]
+name = "async-lock"
+version = "3.4.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "290f7f2596bd5b78a9fec8088ccd89180d7f9f55b94b0576823bbbdc72ee8311"
+dependencies = [
+ "event-listener",
+ "event-listener-strategy",
+ "pin-project-lite",
+]
+
+[[package]]
+name = "async-process"
+version = "2.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fc50921ec0055cdd8a16de48773bfeec5c972598674347252c0399676be7da75"
+dependencies = [
+ "async-channel",
+ "async-io",
+ "async-lock",
+ "async-signal",
+ "async-task",
+ "blocking",
+ "cfg-if",
+ "event-listener",
+ "futures-lite",
+ "rustix 1.1.4",
+]
+
+[[package]]
+name = "async-recursion"
+version = "1.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3b43422f69d8ff38f95f1b2bb76517c91589a924d1559a0e935d7c8ce0274c11"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.119",
+]
+
+[[package]]
+name = "async-signal"
+version = "0.2.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "52b5aaafa020cf5053a01f2a60e8ff5dccf550f0f77ec54a4e47285ac2bab485"
+dependencies = [
+ "async-io",
+ "async-lock",
+ "atomic-waker",
+ "cfg-if",
+ "futures-core",
+ "futures-io",
+ "rustix 1.1.4",
+ "signal-hook-registry",
+ "slab",
+ "windows-sys 0.61.2",
+]
+
+[[package]]
+name = "async-task"
+version = "4.7.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8b75356056920673b02621b35afd0f7dda9306d03c79a30f5c56c44cf256e3de"
+
[[package]]
name = "async-trait"
-version = "0.1.89"
+version = "0.1.91"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb"
+checksum = "ae36dc4177970ef04fde5178d3e2429882def40e57a451f919c098f72baa6cec"
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 3.0.3",
]
[[package]]
@@ -315,6 +546,43 @@ version = "1.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0"
+[[package]]
+name = "atspi"
+version = "0.29.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c77886257be21c9cd89a4ae7e64860c6f0eefca799bb79127913052bd0eefb3d"
+dependencies = [
+ "atspi-common",
+ "atspi-proxies",
+]
+
+[[package]]
+name = "atspi-common"
+version = "0.13.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "20c5617155740c98003016429ad13fe43ce7a77b007479350a9f8bf95a29f63d"
+dependencies = [
+ "enumflags2",
+ "serde",
+ "static_assertions",
+ "zbus",
+ "zbus-lockstep",
+ "zbus-lockstep-macros",
+ "zbus_names",
+ "zvariant",
+]
+
+[[package]]
+name = "atspi-proxies"
+version = "0.13.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2230e48787ed3eb4088996eab66a32ca20c0b67bbd4fd6cdfe79f04f1f04c9fc"
+dependencies = [
+ "atspi-common",
+ "serde",
+ "zbus",
+]
+
[[package]]
name = "attohttpc"
version = "0.30.1"
@@ -348,7 +616,7 @@ dependencies = [
"num-traits",
"pastey",
"rayon",
- "thiserror 2.0.18",
+ "thiserror 2.0.19",
"v_frame",
"y4m",
]
@@ -392,6 +660,12 @@ dependencies = [
"match-lookup",
]
+[[package]]
+name = "base45"
+version = "3.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "240e56f4d3c453c36faacb695c535a4d5f8c7d23dac175014f32eb0a71012a03"
+
[[package]]
name = "base64"
version = "0.13.1"
@@ -439,12 +713,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "bitflags"
-version = "2.12.1"
+version = "2.13.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "84d7ced0ae9557296835c32bf1b1e02b44c746701f898460fb000d7eaa84f00a"
-dependencies = [
- "serde_core",
-]
+checksum = "b588b76d00fde79687d7646a9b5bdf3cc0f655e0bbd080335a95d7e96f3587da"
[[package]]
name = "bitstream-io"
@@ -502,6 +773,19 @@ dependencies = [
"objc2 0.5.2",
]
+[[package]]
+name = "blocking"
+version = "1.6.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e83f8d02be6967315521be875afa792a316e28d57b5a2d401897e2a7921b7f21"
+dependencies = [
+ "async-channel",
+ "async-task",
+ "futures-io",
+ "futures-lite",
+ "piper",
+]
+
[[package]]
name = "bs58"
version = "0.5.1"
@@ -525,22 +809,22 @@ checksum = "72f5acc6cb2ba439de613abc23857ec3d78374d8ed5ac84e9d11336e87da8649"
[[package]]
name = "bytemuck"
-version = "1.25.0"
+version = "1.25.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c8efb64bd706a16a1bdde310ae86b351e4d21550d98d056f22f8a7f7a2183fec"
+checksum = "95832e849adfb21180ccb6826a99da14e5d266ae5c2e668e1602cf234f153797"
dependencies = [
"bytemuck_derive",
]
[[package]]
name = "bytemuck_derive"
-version = "1.10.2"
+version = "1.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f9abbd1bc6865053c427f7198e6af43bfdedc55ab791faed4fbd361d789575ff"
+checksum = "f65693059b6b9c588b9f62fed1cedbf0a8b805631457ea162d68f0de186f3de5"
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.119",
]
[[package]]
@@ -557,9 +841,9 @@ checksum = "8f1fe948ff07f4bd06c30984e69f5b4899c516a3ef74f34df92a2df2ab535495"
[[package]]
name = "bytes"
-version = "1.11.1"
+version = "1.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1e748733b7cbc798e1434b6ac524f0c1ff2ab456fe201501e6497c8417a4fc33"
+checksum = "fc652a48c352aef3ea3aed32080501cf3ef6ed5da78602a020c991775b0aff04"
[[package]]
name = "calloop"
@@ -567,7 +851,7 @@ version = "0.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b99da2f8558ca23c71f4fd15dc57c906239752dd27ff3c00a1d56b685b7cbfec"
dependencies = [
- "bitflags 2.12.1",
+ "bitflags 2.13.1",
"log",
"polling",
"rustix 0.38.44",
@@ -597,7 +881,7 @@ dependencies = [
"serde",
"serde_json",
"tempfile",
- "thiserror 2.0.18",
+ "thiserror 2.0.19",
"tokio",
"tracing",
"ulid",
@@ -606,11 +890,12 @@ dependencies = [
[[package]]
name = "card-core"
version = "0.1.0"
-source = "git+https://gitea.tawasuyu.net/sergio/gioser.git?tag=v0.1.0#692b40336c1e9cb12ab561764d6943cb65905ab3"
+source = "git+https://git.tawasuyu.net/tawasuyu/tawasuyu.git?tag=v0.2.0#a446bb3a73a0e022158cc0ec7deb65173859644b"
dependencies = [
+ "format",
"serde",
"serde_json",
- "thiserror 2.0.18",
+ "thiserror 2.0.19",
"toml",
"ulid",
]
@@ -629,7 +914,7 @@ dependencies = [
"postcard",
"serde",
"tempfile",
- "thiserror 2.0.18",
+ "thiserror 2.0.19",
"tokio",
"tokio-util",
"tracing",
@@ -639,7 +924,7 @@ dependencies = [
[[package]]
name = "card-net"
version = "0.1.0"
-source = "git+https://gitea.tawasuyu.net/sergio/gioser.git?tag=v0.1.0#692b40336c1e9cb12ab561764d6943cb65905ab3"
+source = "git+https://git.tawasuyu.net/tawasuyu/tawasuyu.git?tag=v0.2.0#a446bb3a73a0e022158cc0ec7deb65173859644b"
dependencies = [
"blake3",
"futures",
@@ -647,7 +932,7 @@ dependencies = [
"libp2p-allow-block-list",
"libp2p-stream",
"serde",
- "thiserror 2.0.18",
+ "thiserror 2.0.19",
"tokio",
]
@@ -661,7 +946,7 @@ dependencies = [
"card-wit",
"chasqui-broker",
"tempfile",
- "thiserror 2.0.18",
+ "thiserror 2.0.19",
"tokio",
"tracing",
"tracing-subscriber",
@@ -670,11 +955,11 @@ dependencies = [
[[package]]
name = "card-wit"
version = "0.1.0"
-source = "git+https://gitea.tawasuyu.net/sergio/gioser.git?tag=v0.1.0#692b40336c1e9cb12ab561764d6943cb65905ab3"
+source = "git+https://git.tawasuyu.net/tawasuyu/tawasuyu.git?tag=v0.2.0#a446bb3a73a0e022158cc0ec7deb65173859644b"
dependencies = [
"card-core",
- "thiserror 2.0.18",
- "wit-parser 0.230.0",
+ "thiserror 2.0.19",
+ "wit-parser",
]
[[package]]
@@ -688,9 +973,9 @@ dependencies = [
[[package]]
name = "cc"
-version = "1.2.63"
+version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "556e016178bb5662a08681bbe0f00f8e17631781a4dfc8c45e466e4b185ec27f"
+checksum = "5add81bb678e6cb321aff7fa0dc7689ad82b112dbc032cea19f91d6b8e3582b9"
dependencies = [
"find-msvc-tools",
"jobserver",
@@ -706,9 +991,9 @@ checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801"
[[package]]
name = "cfg_aliases"
-version = "0.2.1"
+version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724"
+checksum = "f079e83a288787bcd14a6aea84cee5c87a67c5a3e660c30f557a3d24761b3527"
[[package]]
name = "chacha20"
@@ -721,6 +1006,17 @@ dependencies = [
"cpufeatures 0.2.17",
]
+[[package]]
+name = "chacha20"
+version = "0.10.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d524456ba66e72eb8b115ff89e01e497f8e6d11d78b70b1aa13c0fbd97540a81"
+dependencies = [
+ "cfg-if",
+ "cpufeatures 0.3.0",
+ "rand_core 0.10.1",
+]
+
[[package]]
name = "chacha20poly1305"
version = "0.10.1"
@@ -728,7 +1024,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "10cd79432192d1c0f4e1a0fef9527696cc039165d729fb41b3f4f4f354c2dc35"
dependencies = [
"aead",
- "chacha20",
+ "chacha20 0.9.1",
"cipher",
"poly1305",
"zeroize",
@@ -740,7 +1036,6 @@ version = "0.1.0"
dependencies = [
"card-core",
"serde",
- "thiserror 2.0.18",
"ulid",
]
@@ -753,14 +1048,21 @@ dependencies = [
"card-handshake",
"card-sidecar",
"chasqui-broker",
+ "llimphi-icons",
"llimphi-motion",
"llimphi-theme",
"llimphi-ui",
"llimphi-widget-app-header",
"llimphi-widget-banner",
"llimphi-widget-context-menu",
+ "llimphi-widget-empty",
"llimphi-widget-menubar",
+ "llimphi-widget-skeleton",
"llimphi-widget-stat-card",
+ "llimphi-widget-toast",
+ "png 0.18.1",
+ "pollster",
+ "rimay-localize",
"ulid",
]
@@ -771,7 +1073,7 @@ dependencies = [
"card-core",
"serde",
"serde_json",
- "thiserror 2.0.18",
+ "thiserror 2.0.19",
"ulid",
]
@@ -781,18 +1083,16 @@ version = "0.1.0"
dependencies = [
"blake3",
"card-core",
- "card-handshake",
"card-sidecar",
"chasqui-card",
"chasqui-nous",
+ "grafo-nav",
"notify",
- "serde",
"serde_json",
"shuma-discern",
"sled",
"tempfile",
- "thiserror 2.0.18",
- "tokio",
+ "thiserror 2.0.19",
"ulid",
"walkdir",
]
@@ -802,9 +1102,9 @@ name = "chasqui-explorer-llimphi"
version = "0.1.0"
dependencies = [
"app-bus",
- "card-core",
"card-sidecar",
"chasqui-card",
+ "llimphi-icons",
"llimphi-motion",
"llimphi-theme",
"llimphi-ui",
@@ -812,7 +1112,10 @@ dependencies = [
"llimphi-widget-banner",
"llimphi-widget-card",
"llimphi-widget-context-menu",
+ "llimphi-widget-empty",
"llimphi-widget-menubar",
+ "llimphi-widget-skeleton",
+ "llimphi-widget-toast",
"rimay-localize",
"wawa-config",
]
@@ -823,7 +1126,7 @@ version = "0.1.0"
dependencies = [
"serde",
"serde_json",
- "thiserror 2.0.18",
+ "thiserror 2.0.19",
]
[[package]]
@@ -871,23 +1174,33 @@ dependencies = [
"zeroize",
]
+[[package]]
+name = "clipboard-win"
+version = "5.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bde03770d3df201d4fb868f2c9c59e66a3e4e2bd06692a0fe701e7103c7e84d4"
+dependencies = [
+ "error-code",
+]
+
[[package]]
name = "cobs"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0fa961b519f0b462e3a3b4a34b64d119eeaca1d59af726fe450bbba07a9fc0a1"
dependencies = [
- "thiserror 2.0.18",
+ "thiserror 2.0.19",
]
[[package]]
name = "codespan-reporting"
-version = "0.11.1"
+version = "0.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3538270d33cc669650c4b093848450d380def10c331d38c768e34cac80576e6e"
+checksum = "fe6d2e5af09e8c8ad56c969f2157a3d4238cebc7c55f0a517728c38f7b200f81"
dependencies = [
+ "serde",
"termcolor",
- "unicode-width 0.1.14",
+ "unicode-width",
]
[[package]]
@@ -945,7 +1258,7 @@ dependencies = [
"encode_unicode",
"libc",
"once_cell",
- "unicode-width 0.2.2",
+ "unicode-width",
"windows-sys 0.59.0",
]
@@ -1001,7 +1314,7 @@ checksum = "c07782be35f9e1140080c6b96f0d44b739e2278479f64e02fdab4e32dfd8b081"
dependencies = [
"bitflags 1.3.2",
"core-foundation 0.9.4",
- "core-graphics-types",
+ "core-graphics-types 0.1.3",
"foreign-types 0.5.0",
"libc",
]
@@ -1017,6 +1330,26 @@ dependencies = [
"libc",
]
+[[package]]
+name = "core-graphics-types"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3d44a101f213f6c4cdc1853d4b78aef6db6bdfa3468798cc1d9912f4735013eb"
+dependencies = [
+ "bitflags 2.13.1",
+ "core-foundation 0.10.1",
+ "libc",
+]
+
+[[package]]
+name = "core_maths"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "77745e017f5edba1a9c1d854f6f3a52dac8a12dd5af5d2f54aecf61e43d80d30"
+dependencies = [
+ "libm",
+]
+
[[package]]
name = "cpufeatures"
version = "0.2.17"
@@ -1052,18 +1385,18 @@ checksum = "790eea4361631c5e7d22598ecd5723ff611904e3344ce8720784c93e3d83d40b"
[[package]]
name = "crossbeam-channel"
-version = "0.5.15"
+version = "0.5.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "82b8f8f868b36967f9606790d1903570de9ceaf870a7bf9fbbd3016d636a2cb2"
+checksum = "d85363c37faeca707aef026efa9f3b34d077bce547e48f770770625c6013679e"
dependencies = [
"crossbeam-utils",
]
[[package]]
name = "crossbeam-deque"
-version = "0.8.6"
+version = "0.8.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51"
+checksum = "5181e0de7b61eb03a81e347d6dd8797bae9da5146707b51077e2d71a54ec0ceb"
dependencies = [
"crossbeam-epoch",
"crossbeam-utils",
@@ -1071,18 +1404,18 @@ dependencies = [
[[package]]
name = "crossbeam-epoch"
-version = "0.9.18"
+version = "0.9.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e"
+checksum = "2d6914041f254d6e9176c01941b21115dcfb7089e55135a35411081bd106ef3f"
dependencies = [
"crossbeam-utils",
]
[[package]]
name = "crossbeam-utils"
-version = "0.8.21"
+version = "0.8.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28"
+checksum = "61803da095bee82a81bb1a452ecc25d3b2f1416d1897eb86430c6159ef717c17"
[[package]]
name = "crunchy"
@@ -1140,7 +1473,7 @@ checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3"
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.119",
]
[[package]]
@@ -1164,7 +1497,7 @@ dependencies = [
"proc-macro2",
"quote",
"strsim",
- "syn",
+ "syn 2.0.119",
]
[[package]]
@@ -1175,7 +1508,7 @@ checksum = "fc34b93ccb385b40dc71c6fceac4b2ad23662c7eeb248cf10d529b7e055b6ead"
dependencies = [
"darling_core",
"quote",
- "syn",
+ "syn 2.0.119",
]
[[package]]
@@ -1210,7 +1543,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ccc2776f0c61eca1ca32528f85548abd1a4be8fb53d1b21c013e4f18da1e7090"
dependencies = [
"data-encoding",
- "syn",
+ "syn 2.0.119",
]
[[package]]
@@ -1242,9 +1575,6 @@ name = "deranged"
version = "0.5.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7cd812cc2bc1d69d4764bd80df88b4317eaef9e773c75226407d9bc0876b211c"
-dependencies = [
- "powerfmt",
-]
[[package]]
name = "derive_builder"
@@ -1264,7 +1594,7 @@ dependencies = [
"darling",
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.119",
]
[[package]]
@@ -1274,7 +1604,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ab63b0e2bf4d5928aff72e83a7dace85d7bba5fe12dcc3c5a572d78caffd3f3c"
dependencies = [
"derive_builder_core",
- "syn",
+ "syn 2.0.119",
]
[[package]]
@@ -1336,6 +1666,16 @@ version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bd0c93bb4b0c6d9b77f4435b0ae98c24d17f1c45b2ff844c6151a07256ca923b"
+[[package]]
+name = "dispatch2"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1e0e367e4e7da84520dedcac1901e4da967309406d1e51017ae1abfb97adbd38"
+dependencies = [
+ "bitflags 2.13.1",
+ "objc2 0.6.4",
+]
+
[[package]]
name = "displaydoc"
version = "0.2.6"
@@ -1344,7 +1684,7 @@ checksum = "1ac70aa55017e108007fbaf5aa0f54b021c98f92ff8af59d42eda9da96e3dd4f"
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.119",
]
[[package]]
@@ -1409,9 +1749,9 @@ dependencies = [
[[package]]
name = "either"
-version = "1.16.0"
+version = "1.17.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "91622ff5e7162018101f2fea40d6ebf4a78bbe5a49736a2020649edf9693679e"
+checksum = "9e5e8f6c15a24b9a3ee5efec809ccd006d3b30e8b3bb63c39af737c7f87daa1d"
[[package]]
name = "embedded-io"
@@ -1440,6 +1780,12 @@ dependencies = [
"cfg-if",
]
+[[package]]
+name = "endi"
+version = "1.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "66b7e2430c6dff6a955451e2cfc438f09cea1965a9d6f87f7e3b90decc014099"
+
[[package]]
name = "enum-as-inner"
version = "0.6.1"
@@ -1449,7 +1795,28 @@ dependencies = [
"heck",
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.119",
+]
+
+[[package]]
+name = "enumflags2"
+version = "0.7.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1027f7680c853e056ebcec683615fb6fbbc07dbaa13b4d5d9442b146ded4ecef"
+dependencies = [
+ "enumflags2_derive",
+ "serde",
+]
+
+[[package]]
+name = "enumflags2_derive"
+version = "0.7.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "67c78a4d8fdf9953a5c9d458f9efe940fd97a0cab0941c075a813ac594733827"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.119",
]
[[package]]
@@ -1469,7 +1836,7 @@ checksum = "44f23cf4b44bfce11a86ace86f8a73ffdec849c9fd00a386a53d278bd9e81fb3"
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.119",
]
[[package]]
@@ -1488,6 +1855,12 @@ dependencies = [
"windows-sys 0.61.2",
]
+[[package]]
+name = "error-code"
+version = "3.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dea2df4cf52843e0452895c455a1a2cfbb842a1e7329671acf418fdc53ed4c59"
+
[[package]]
name = "esaxx-rs"
version = "0.1.10"
@@ -1503,21 +1876,56 @@ dependencies = [
"num-traits",
]
+[[package]]
+name = "event-listener"
+version = "5.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e13b66accf52311f30a0db42147dadea9850cb48cd070028831ae5f5d4b856ab"
+dependencies = [
+ "concurrent-queue",
+ "parking",
+ "pin-project-lite",
+]
+
+[[package]]
+name = "event-listener-strategy"
+version = "0.5.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8be9f3dfaaffdae2972880079a491a1a8bb7cbed0b8dd7a347f668b4150a3b93"
+dependencies = [
+ "event-listener",
+ "pin-project-lite",
+]
+
[[package]]
name = "exr"
-version = "1.74.0"
+version = "1.74.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4300e043a56aa2cb633c01af81ca8f699a321879a7854d3896a0ba89056363be"
+checksum = "711fe42c9964295e01ee3fba3f9fe0e1d24b98886950d68efe81b1c76e21adf3"
dependencies = [
"bit_field",
"half",
"lebe",
"miniz_oxide",
+ "num-complex",
+ "pulp",
"rayon-core",
"smallvec",
"zune-inflate",
]
+[[package]]
+name = "fastbloom"
+version = "0.17.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ef975e30683b2d965054bb0a836f8973857c4ebf6acf274fe46617cd285060d8"
+dependencies = [
+ "foldhash 0.2.0",
+ "libm",
+ "portable-atomic",
+ "siphasher",
+]
+
[[package]]
name = "fastembed"
version = "4.9.1"
@@ -1537,9 +1945,9 @@ dependencies = [
[[package]]
name = "fastrand"
-version = "2.4.1"
+version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9f1f227452a390804cdb637b74a86990f2a7d7ba4b7d5693aac9b4dd6defd8d6"
+checksum = "da7c62ceae207dd37ea5b845da6a0696c799f85e97da1ab5b7910be3c1c80223"
[[package]]
name = "fax"
@@ -1578,6 +1986,12 @@ version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582"
+[[package]]
+name = "fixedbitset"
+version = "0.5.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1d674e81391d1e1ab681a28d99df07927c6d4aa5b027d7da16ba32d1d21ecd99"
+
[[package]]
name = "flate2"
version = "1.1.9"
@@ -1634,11 +2048,17 @@ version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2"
+[[package]]
+name = "foldhash"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "77ce24cb58228fbb8aa041425bb1050850ac19177686ea6e0f41a70416f56fdb"
+
[[package]]
name = "font-types"
-version = "0.9.0"
+version = "0.10.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "02a596f5713680923a2080d86de50fe472fb290693cf0f701187a1c8b36996b7"
+checksum = "39a654f404bbcbd48ea58c617c2993ee91d1cb63727a37bf2323a4edeed1b8c5"
dependencies = [
"bytemuck",
]
@@ -1653,36 +2073,35 @@ dependencies = [
]
[[package]]
-name = "fontconfig-cache-parser"
-version = "0.2.0"
+name = "font-types"
+version = "0.12.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a7f8afb20c8069fd676d27b214559a337cc619a605d25a87baa90b49a06f3b18"
+checksum = "0a7299a780854a6d391be2ae1c8521c9368471b559dbfd6a8dbd9f407eaff100"
dependencies = [
"bytemuck",
- "thiserror 1.0.69",
]
[[package]]
name = "fontique"
-version = "0.4.0"
+version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "64763d1f274c8383333851435b6cdf071c31cfcdb39fd5860d20943205a007a7"
+checksum = "ff3336bc0b87fe42305047263fa60d2eabd650d29cbe62fdeb2a66c7a0a595f9"
dependencies = [
"bytemuck",
- "fontconfig-cache-parser",
"hashbrown 0.15.5",
- "icu_locid",
+ "icu_locale_core",
+ "linebender_resource_handle",
"memmap2",
"objc2 0.6.4",
"objc2-core-foundation",
"objc2-core-text",
"objc2-foundation 0.3.2",
- "peniko",
- "read-fonts 0.29.3",
+ "read-fonts 0.35.0",
"roxmltree",
"smallvec",
"windows 0.58.0",
"windows-core 0.58.0",
+ "yeslogic-fontconfig-sys",
]
[[package]]
@@ -1706,13 +2125,13 @@ dependencies = [
[[package]]
name = "foreign-types-macros"
-version = "0.2.3"
+version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1a5c6c585bc94aaf2c7b51dd4c2ba22680844aba4c687be581871a6f518c5742"
+checksum = "ea5190182e6915eb873ddbc16e23b711b6eb1f9c00a0d0a3a91b5f6228475225"
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 3.0.3",
]
[[package]]
@@ -1736,6 +2155,17 @@ dependencies = [
"percent-encoding",
]
+[[package]]
+name = "format"
+version = "0.1.0"
+source = "git+https://git.tawasuyu.net/tawasuyu/tawasuyu.git?tag=v0.2.0#a446bb3a73a0e022158cc0ec7deb65173859644b"
+dependencies = [
+ "blake3",
+ "postcard",
+ "serde",
+ "serde-big-array",
+]
+
[[package]]
name = "fs2"
version = "0.4.3"
@@ -1757,9 +2187,9 @@ dependencies = [
[[package]]
name = "futures"
-version = "0.3.32"
+version = "0.3.33"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8b147ee9d1f6d097cef9ce628cd2ee62288d963e16fb287bd9286455b241382d"
+checksum = "a88cf1f829d945f548cf8fec32c61b1f202b6d93b45848602fc02af4b12ad218"
dependencies = [
"futures-channel",
"futures-core",
@@ -1782,9 +2212,9 @@ dependencies = [
[[package]]
name = "futures-channel"
-version = "0.3.32"
+version = "0.3.33"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "07bbe89c50d7a535e539b8c17bc0b49bdb77747034daa8087407d655f3f7cc1d"
+checksum = "262590f4fe6afeb0bc83be1daa64e52657fe185690a958af7f3ad0e92085c5ae"
dependencies = [
"futures-core",
"futures-sink",
@@ -1792,15 +2222,15 @@ dependencies = [
[[package]]
name = "futures-core"
-version = "0.3.32"
+version = "0.3.33"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7e3450815272ef58cec6d564423f6e755e25379b217b0bc688e295ba24df6b1d"
+checksum = "2cd50c473c80f6d7c3670a752354b8e569b1a7cbfdc0419ec88e5edad85e0dc7"
[[package]]
name = "futures-executor"
-version = "0.3.32"
+version = "0.3.33"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "baf29c38818342a3b26b5b923639e7b1f4a61fc5e76102d4b1981c6dc7a7579d"
+checksum = "6754879cc9f2c66f88c6e5c35344bb0bdb0708b0352b1201815667c7eabc7458"
dependencies = [
"futures-core",
"futures-task",
@@ -1820,9 +2250,9 @@ dependencies = [
[[package]]
name = "futures-io"
-version = "0.3.32"
+version = "0.3.33"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cecba35d7ad927e23624b22ad55235f2239cfa44fd10428eecbeba6d6a717718"
+checksum = "4577ecaa3c4f96589d473f679a71b596316f6641bc350038b962a5daf0085d7a"
[[package]]
name = "futures-lite"
@@ -1830,19 +2260,22 @@ version = "2.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f78e10609fe0e0b3f4157ffab1876319b5b0db102a2c60dc4626306dc46b44ad"
dependencies = [
+ "fastrand",
"futures-core",
+ "futures-io",
+ "parking",
"pin-project-lite",
]
[[package]]
name = "futures-macro"
-version = "0.3.32"
+version = "0.3.33"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e835b70203e41293343137df5c0664546da5745f82ec9b84d40be8336958447b"
+checksum = "2d6d3cde68c518367be28956066ddfef33813991b77a55005a69dae04bf3b10b"
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.119",
]
[[package]]
@@ -1858,15 +2291,15 @@ dependencies = [
[[package]]
name = "futures-sink"
-version = "0.3.32"
+version = "0.3.33"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c39754e157331b013978ec91992bde1ac089843443c49cbc7f46150b0fad0893"
+checksum = "e34418ac499d6305c2fb5ad0ed2f6ac998c5f8ca209b4510f7f94242c647e307"
[[package]]
name = "futures-task"
-version = "0.3.32"
+version = "0.3.33"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "037711b3d59c33004d3856fbdc83b99d4ff37a24768fa1be9ce3538a1cde4393"
+checksum = "b231ed28831efb4a61a08580c4bc233ec56bc009f4cd8f52da2c3cb97df0c109"
[[package]]
name = "futures-timer"
@@ -1876,9 +2309,9 @@ checksum = "af43fadb8a98512d547e37b4e92e0ced13e205c061b87b4623eff01d918d6968"
[[package]]
name = "futures-util"
-version = "0.3.32"
+version = "0.3.33"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "389ca41296e6190b48053de0321d02a77f32f8a5d2461dd38762c0593805c6d6"
+checksum = "a77a90a256fce34da66415271e30f94ee91c57b04b8a2c042d9cf3220179deaa"
dependencies = [
"futures-channel",
"futures-core",
@@ -1940,24 +2373,23 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd"
dependencies = [
"cfg-if",
- "js-sys",
"libc",
"r-efi 5.3.0",
"wasip2",
- "wasm-bindgen",
]
[[package]]
name = "getrandom"
-version = "0.4.2"
+version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0de51e6874e94e7bf76d726fc5d13ba782deca734ff60d5bb2fb2607c7406555"
+checksum = "300e883d756b2e4ec94e02791f39b04b522276138852cfc41d9fb7e904106099"
dependencies = [
"cfg-if",
+ "js-sys",
"libc",
"r-efi 6.0.0",
- "wasip2",
- "wasip3",
+ "rand_core 0.10.1",
+ "wasm-bindgen",
]
[[package]]
@@ -2014,21 +2446,21 @@ dependencies = [
[[package]]
name = "gpu-alloc"
-version = "0.6.0"
+version = "0.6.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fbcd2dba93594b227a1f57ee09b8b9da8892c34d55aa332e034a228d0fe6a171"
+checksum = "45cf04b2726f02df5508c6de726acdc90cdf97ac771a9a0ffd8ba10a6e696bf9"
dependencies = [
- "bitflags 2.12.1",
+ "bitflags 2.13.1",
"gpu-alloc-types",
]
[[package]]
name = "gpu-alloc-types"
-version = "0.3.0"
+version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "98ff03b468aa837d70984d55f5d3f846f6ec31fe34bbb97c4f85219caeee1ca4"
+checksum = "b2bbed164dd10ed526c2e4fe3e721ca4a71c61730e5aafac6844b417b3227058"
dependencies = [
- "bitflags 2.12.1",
+ "bitflags 2.13.1",
]
[[package]]
@@ -2049,7 +2481,7 @@ version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b89c83349105e3732062a895becfc71a8f921bb71ecbbdd8ff99263e3b53a0ca"
dependencies = [
- "bitflags 2.12.1",
+ "bitflags 2.13.1",
"gpu-descriptor-types",
"hashbrown 0.15.5",
]
@@ -2060,9 +2492,14 @@ version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fdf242682df893b86f33a73828fb09ca4b2d3bb6cc95249707fc684d27484b91"
dependencies = [
- "bitflags 2.12.1",
+ "bitflags 2.13.1",
]
+[[package]]
+name = "grafo-nav"
+version = "0.1.0"
+source = "git+https://git.tawasuyu.net/tawasuyu/tawasuyu.git?tag=v0.2.0#a446bb3a73a0e022158cc0ec7deb65173859644b"
+
[[package]]
name = "grid"
version = "1.0.1"
@@ -2081,9 +2518,9 @@ dependencies = [
[[package]]
name = "h2"
-version = "0.4.14"
+version = "0.4.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "171fefbc92fe4a4de27e0698d6a5b392d6a0e333506bc49133760b3bcf948733"
+checksum = "6cb093c84e8bd9b188d4c4a8cb6579fc016968d14c99882163cd3ff402a4f155"
dependencies = [
"atomic-waker",
"bytes",
@@ -2106,9 +2543,23 @@ checksum = "6ea2d84b969582b4b1864a92dc5d27cd2b77b622a8d79306834f1be5ba20d84b"
dependencies = [
"cfg-if",
"crunchy",
+ "num-traits",
"zerocopy",
]
+[[package]]
+name = "harfrust"
+version = "0.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "92c020db12c71d8a12a3fe7607873cade3a01a6287e29d540c8723276221b9d8"
+dependencies = [
+ "bitflags 2.13.1",
+ "bytemuck",
+ "core_maths",
+ "read-fonts 0.35.0",
+ "smallvec",
+]
+
[[package]]
name = "hash32"
version = "0.2.1"
@@ -2126,7 +2577,16 @@ checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1"
dependencies = [
"allocator-api2",
"equivalent",
- "foldhash",
+ "foldhash 0.1.5",
+]
+
+[[package]]
+name = "hashbrown"
+version = "0.16.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100"
+dependencies = [
+ "foldhash 0.2.0",
]
[[package]]
@@ -2194,11 +2654,11 @@ dependencies = [
"libc",
"log",
"native-tls",
- "rand 0.9.4",
+ "rand 0.9.5",
"reqwest",
"serde",
"serde_json",
- "thiserror 2.0.18",
+ "thiserror 2.0.19",
"ureq",
"windows-sys 0.60.2",
]
@@ -2219,10 +2679,10 @@ dependencies = [
"idna",
"ipnet",
"once_cell",
- "rand 0.9.4",
+ "rand 0.9.5",
"ring",
"socket2 0.5.10",
- "thiserror 2.0.18",
+ "thiserror 2.0.19",
"tinyvec",
"tokio",
"tracing",
@@ -2242,10 +2702,10 @@ dependencies = [
"moka",
"once_cell",
"parking_lot 0.12.5",
- "rand 0.9.4",
+ "rand 0.9.5",
"resolv-conf",
"smallvec",
- "thiserror 2.0.18",
+ "thiserror 2.0.19",
"tokio",
"tracing",
]
@@ -2270,9 +2730,9 @@ dependencies = [
[[package]]
name = "http"
-version = "1.4.1"
+version = "1.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8be7462df143984c4598a256ef469b251d7d7f9e271135073e78fc535414f3d0"
+checksum = "6970f50e31d6fc17d3fa27329444bfa74e196cf62e95052a3f6fee181dba6425"
dependencies = [
"bytes",
"itoa",
@@ -2280,9 +2740,9 @@ dependencies = [
[[package]]
name = "http-body"
-version = "1.0.1"
+version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184"
+checksum = "ca2a8f2913ee65f60facd6a5905613afaa448497a0230cc41ce022d93290bc2c"
dependencies = [
"bytes",
"http",
@@ -2290,9 +2750,9 @@ dependencies = [
[[package]]
name = "http-body-util"
-version = "0.1.3"
+version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b021d93e26becf5dc7e1b75b1bed1fd93124b374ceb73f43d4d4eafec896a64a"
+checksum = "e9f41fd6a08e4d4ec69df65976da761afd5ad5e58a9d4acb46bd1c953a9e3ff2"
dependencies = [
"bytes",
"futures-core",
@@ -2309,9 +2769,9 @@ checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87"
[[package]]
name = "hyper"
-version = "1.10.1"
+version = "1.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "55281c53a1894c864990125767da440a4e630446785086f52523b20033b74498"
+checksum = "d22053281f852e11534f5198498373cbb59295120a20771d90f7ed1897490a72"
dependencies = [
"atomic-waker",
"bytes",
@@ -2376,7 +2836,7 @@ dependencies = [
"libc",
"percent-encoding",
"pin-project-lite",
- "socket2 0.6.4",
+ "socket2 0.6.5",
"system-configuration",
"tokio",
"tower-service",
@@ -2405,24 +2865,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "92219b62b3e2b4d88ac5119f8904c10f8f61bf7e95b640d25ba3075e6cac2c29"
dependencies = [
"displaydoc",
- "litemap 0.8.2",
- "tinystr 0.8.3",
- "writeable 0.6.3",
+ "litemap",
+ "serde",
+ "tinystr",
+ "writeable",
"zerovec",
]
-[[package]]
-name = "icu_locid"
-version = "1.5.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "13acbb8371917fc971be86fc8057c41a64b521c184808a698c02acc242dbf637"
-dependencies = [
- "displaydoc",
- "litemap 0.7.5",
- "tinystr 0.7.6",
- "writeable 0.5.5",
-]
-
[[package]]
name = "icu_normalizer"
version = "2.2.0"
@@ -2471,7 +2920,7 @@ checksum = "139c4cf31c8b5f33d7e199446eff9c1e02decfc2f0eec2c8d71f65befa45b421"
dependencies = [
"displaydoc",
"icu_locale_core",
- "writeable 0.6.3",
+ "writeable",
"yoke",
"zerofrom",
"zerotrie",
@@ -2559,7 +3008,7 @@ dependencies = [
"hyper",
"hyper-util",
"log",
- "rand 0.9.4",
+ "rand 0.9.5",
"tokio",
"url",
"xmltree",
@@ -2601,9 +3050,9 @@ dependencies = [
[[package]]
name = "imgref"
-version = "1.12.1"
+version = "1.12.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "40fac9d56ed6437b198fddba683305e8e2d651aa42647f00f5ae542e7f5c94a2"
+checksum = "89194689a993ab15268672e99e7b0e19da2da3268ac682e8f02d29d4d1434cd7"
[[package]]
name = "indexmap"
@@ -2626,7 +3075,7 @@ dependencies = [
"console",
"number_prefix",
"portable-atomic",
- "unicode-width 0.2.2",
+ "unicode-width",
"web-time",
]
@@ -2643,9 +3092,9 @@ dependencies = [
[[package]]
name = "inotify-sys"
-version = "0.1.5"
+version = "0.1.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e05c02b5e89bff3b946cedeca278abc628fe811e604f027c45a8aa3cf793d0eb"
+checksum = "c033f80b2c113cdf91ab7a33faa9cbc014726dcad99880c8609af2a370edf37d"
dependencies = [
"libc",
]
@@ -2676,7 +3125,7 @@ checksum = "c34819042dc3d3971c46c2190835914dfbe0c3c13f61449b2997f4e9722dfa60"
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.119",
]
[[package]]
@@ -2704,7 +3153,7 @@ version = "0.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4d40460c0ce33d6ce4b0630ad68ff63d6661961c48b6dba35e5a4d81cfb48222"
dependencies = [
- "socket2 0.6.4",
+ "socket2 0.6.5",
"widestring",
"windows-registry",
"windows-result 0.4.1",
@@ -2744,7 +3193,7 @@ dependencies = [
"jni-sys 0.4.1",
"log",
"simd_cesu8",
- "thiserror 2.0.18",
+ "thiserror 2.0.19",
"walkdir",
"windows-link",
]
@@ -2759,7 +3208,7 @@ dependencies = [
"quote",
"rustc_version",
"simd_cesu8",
- "syn",
+ "syn 2.0.119",
]
[[package]]
@@ -2787,28 +3236,27 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "38c0b942f458fe50cdac086d2f946512305e5631e720728f2a61aabcd47a6264"
dependencies = [
"quote",
- "syn",
+ "syn 2.0.119",
]
[[package]]
name = "jobserver"
-version = "0.1.34"
+version = "0.1.35"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9afb3de4395d6b3e67a780b6de64b51c978ecf11cb9a462c66be7d4ca9039d33"
+checksum = "1c00acbd29eabad4a2392fa0e921c874934dbbf4194312ad20f04a0ed67a3cb3"
dependencies = [
- "getrandom 0.3.4",
+ "getrandom 0.4.3",
"libc",
]
[[package]]
name = "js-sys"
-version = "0.3.99"
+version = "0.3.103"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "142bc4740e452c1e57ade0cbc129f139c9093e354346f0872ef985f4f5cf5f11"
+checksum = "53b44bfcdb3f8d5837a46dae1ca9660a837176eee74a28b229bc626816589102"
dependencies = [
"cfg-if",
"futures-util",
- "once_cell",
"wasm-bindgen",
]
@@ -2845,18 +3293,19 @@ version = "1.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "07293a4e297ac234359b510362495713f75ea345d5307140414f20c69ffeb087"
dependencies = [
- "bitflags 2.12.1",
+ "bitflags 2.13.1",
"libc",
]
[[package]]
name = "kurbo"
-version = "0.11.3"
+version = "0.13.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c62026ae44756f8a599ba21140f350303d4f08dcdcc71b5ad9c9bb8128c13c62"
+checksum = "4b60dfc32f652b926df6192e55525b16d186c69d47876c3ead4da5cc9f8450e2"
dependencies = [
"arrayvec",
"euclid",
+ "polycool",
"smallvec",
]
@@ -2866,12 +3315,6 @@ version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
-[[package]]
-name = "leb128fmt"
-version = "0.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2"
-
[[package]]
name = "lebe"
version = "0.5.3"
@@ -2880,15 +3323,15 @@ checksum = "7a79a3332a6609480d7d0c9eab957bca6b455b91bb84e66d19f5ff66294b85b8"
[[package]]
name = "libc"
-version = "0.2.186"
+version = "0.2.189"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66"
+checksum = "3eaf3ede3fee6db1a4c2ee091bf8a8b4dccdc6d17f656fb07896ee72867612f2"
[[package]]
name = "libfuzzer-sys"
-version = "0.4.12"
+version = "0.4.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f12a681b7dd8ce12bff52488013ba614b869148d54dd79836ab85aafdd53f08d"
+checksum = "a9fd2f41a1cba099f79a0b6b6c35656cf7c03351a7bae8ff0f28f25270f929d2"
dependencies = [
"arbitrary",
"cc",
@@ -2904,6 +3347,12 @@ dependencies = [
"windows-link",
]
+[[package]]
+name = "libm"
+version = "0.2.16"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b6d2cec3eae94f9f509c767b45932f1ada8350c4bdb85af2fcab4a3c14807981"
+
[[package]]
name = "libp2p"
version = "0.56.0"
@@ -2936,7 +3385,7 @@ dependencies = [
"multiaddr",
"pin-project",
"rw-stream-sink",
- "thiserror 2.0.18",
+ "thiserror 2.0.19",
]
[[package]]
@@ -2968,9 +3417,9 @@ dependencies = [
"libp2p-swarm",
"quick-protobuf",
"quick-protobuf-codec",
- "rand 0.8.6",
+ "rand 0.8.7",
"rand_core 0.6.4",
- "thiserror 2.0.18",
+ "thiserror 2.0.19",
"tracing",
"web-time",
]
@@ -3003,9 +3452,9 @@ dependencies = [
"parking_lot 0.12.5",
"pin-project",
"quick-protobuf",
- "rand 0.8.6",
+ "rand 0.8.7",
"rw-stream-sink",
- "thiserror 2.0.18",
+ "thiserror 2.0.19",
"tracing",
"unsigned-varint 0.8.0",
"web-time",
@@ -3028,7 +3477,7 @@ dependencies = [
"libp2p-swarm",
"quick-protobuf",
"quick-protobuf-codec",
- "thiserror 2.0.18",
+ "thiserror 2.0.19",
"tracing",
"web-time",
]
@@ -3066,7 +3515,7 @@ dependencies = [
"quick-protobuf",
"quick-protobuf-codec",
"smallvec",
- "thiserror 2.0.18",
+ "thiserror 2.0.19",
"tracing",
]
@@ -3081,9 +3530,9 @@ dependencies = [
"hkdf",
"multihash",
"prost",
- "rand 0.8.6",
+ "rand 0.8.7",
"sha2",
- "thiserror 2.0.18",
+ "thiserror 2.0.19",
"tracing",
"zeroize",
]
@@ -3106,10 +3555,10 @@ dependencies = [
"libp2p-swarm",
"quick-protobuf",
"quick-protobuf-codec",
- "rand 0.8.6",
+ "rand 0.8.7",
"sha2",
"smallvec",
- "thiserror 2.0.18",
+ "thiserror 2.0.19",
"tracing",
"uint",
"web-time",
@@ -3127,7 +3576,7 @@ dependencies = [
"libp2p-core",
"libp2p-identity",
"libp2p-swarm",
- "rand 0.8.6",
+ "rand 0.8.7",
"smallvec",
"socket2 0.5.10",
"tokio",
@@ -3167,10 +3616,10 @@ dependencies = [
"multiaddr",
"multihash",
"quick-protobuf",
- "rand 0.8.6",
+ "rand 0.8.7",
"snow",
"static_assertions",
- "thiserror 2.0.18",
+ "thiserror 2.0.19",
"tracing",
"x25519-dalek",
"zeroize",
@@ -3178,9 +3627,9 @@ dependencies = [
[[package]]
name = "libp2p-quic"
-version = "0.13.0"
+version = "0.13.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8dc448b2de9f4745784e3751fe8bc6c473d01b8317edd5ababcb0dec803d843f"
+checksum = "9dcc597d70bf7f6f30cbe07081802c836184e48416e89e9ce73a0ba2c56a319e"
dependencies = [
"futures",
"futures-timer",
@@ -3189,11 +3638,12 @@ dependencies = [
"libp2p-identity",
"libp2p-tls",
"quinn",
- "rand 0.8.6",
+ "quinn-proto",
+ "rand 0.8.7",
"ring",
"rustls",
"socket2 0.5.10",
- "thiserror 2.0.18",
+ "thiserror 2.0.19",
"tokio",
"tracing",
]
@@ -3215,9 +3665,9 @@ dependencies = [
"libp2p-swarm",
"quick-protobuf",
"quick-protobuf-codec",
- "rand 0.8.6",
+ "rand 0.8.7",
"static_assertions",
- "thiserror 2.0.18",
+ "thiserror 2.0.19",
"tracing",
"web-time",
]
@@ -3234,7 +3684,7 @@ dependencies = [
"libp2p-core",
"libp2p-identity",
"libp2p-swarm",
- "rand 0.8.6",
+ "rand 0.8.7",
"smallvec",
"tracing",
]
@@ -3249,7 +3699,7 @@ dependencies = [
"libp2p-core",
"libp2p-identity",
"libp2p-swarm",
- "rand 0.8.6",
+ "rand 0.8.7",
"tracing",
]
@@ -3268,7 +3718,7 @@ dependencies = [
"libp2p-identity",
"libp2p-swarm-derive",
"multistream-select",
- "rand 0.8.6",
+ "rand 0.8.7",
"smallvec",
"tokio",
"tracing",
@@ -3283,7 +3733,7 @@ checksum = "dd297cf53f0cb3dee4d2620bb319ae47ef27c702684309f682bdb7e55a18ae9c"
dependencies = [
"heck",
"quote",
- "syn",
+ "syn 2.0.119",
]
[[package]]
@@ -3297,7 +3747,7 @@ dependencies = [
"if-watch",
"libc",
"libp2p-core",
- "socket2 0.6.4",
+ "socket2 0.6.5",
"tokio",
"tracing",
]
@@ -3316,7 +3766,7 @@ dependencies = [
"ring",
"rustls",
"rustls-webpki",
- "thiserror 2.0.18",
+ "thiserror 2.0.19",
"x509-parser",
"yasna",
]
@@ -3345,7 +3795,7 @@ dependencies = [
"either",
"futures",
"libp2p-core",
- "thiserror 2.0.18",
+ "thiserror 2.0.19",
"tracing",
"yamux 0.12.1",
"yamux 0.13.10",
@@ -3353,14 +3803,14 @@ dependencies = [
[[package]]
name = "libredox"
-version = "0.1.17"
+version = "0.1.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f02ab6bace2054fb888a3c16f990117b579d14a3088e472d63c6011fa185c9d3"
+checksum = "c943259e342f1e06ff2da7a83eabdfe7f92ce10262688dbf1895ff0b3e6e4652"
dependencies = [
- "bitflags 2.12.1",
+ "bitflags 2.13.1",
"libc",
"plain",
- "redox_syscall 0.8.1",
+ "redox_syscall 0.9.0",
]
[[package]]
@@ -3381,12 +3831,6 @@ version = "0.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "32a66949e030da00e8c7d4434b251670a91556f4144941d37452769c25d58a53"
-[[package]]
-name = "litemap"
-version = "0.7.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "23fb14cb19457329c82206317a5663005a4d404783dc74f4252769b0d5f42856"
-
[[package]]
name = "litemap"
version = "0.8.2"
@@ -3402,7 +3846,7 @@ checksum = "11d3d7f243d5c5a8b9bb5d6dd2b1602c0cb0b9db1621bafc7ed66e35ff9fe092"
[[package]]
name = "llimphi-compositor"
version = "0.1.0"
-source = "git+https://gitea.tawasuyu.net/sergio/gioser.git?tag=v0.1.0#692b40336c1e9cb12ab561764d6943cb65905ab3"
+source = "git+https://git.tawasuyu.net/tawasuyu/tawasuyu.git?tag=v0.2.0#a446bb3a73a0e022158cc0ec7deb65173859644b"
dependencies = [
"llimphi-layout",
"llimphi-text",
@@ -3413,7 +3857,7 @@ dependencies = [
[[package]]
name = "llimphi-hal"
version = "0.1.0"
-source = "git+https://gitea.tawasuyu.net/sergio/gioser.git?tag=v0.1.0#692b40336c1e9cb12ab561764d6943cb65905ab3"
+source = "git+https://git.tawasuyu.net/tawasuyu/tawasuyu.git?tag=v0.2.0#a446bb3a73a0e022158cc0ec7deb65173859644b"
dependencies = [
"pollster",
"raw-window-handle",
@@ -3421,10 +3865,18 @@ dependencies = [
"winit",
]
+[[package]]
+name = "llimphi-icons"
+version = "0.1.0"
+source = "git+https://git.tawasuyu.net/tawasuyu/tawasuyu.git?tag=v0.2.0#a446bb3a73a0e022158cc0ec7deb65173859644b"
+dependencies = [
+ "llimphi-ui",
+]
+
[[package]]
name = "llimphi-layout"
version = "0.1.0"
-source = "git+https://gitea.tawasuyu.net/sergio/gioser.git?tag=v0.1.0#692b40336c1e9cb12ab561764d6943cb65905ab3"
+source = "git+https://git.tawasuyu.net/tawasuyu/tawasuyu.git?tag=v0.2.0#a446bb3a73a0e022158cc0ec7deb65173859644b"
dependencies = [
"taffy",
]
@@ -3432,7 +3884,7 @@ dependencies = [
[[package]]
name = "llimphi-motion"
version = "0.1.0"
-source = "git+https://gitea.tawasuyu.net/sergio/gioser.git?tag=v0.1.0#692b40336c1e9cb12ab561764d6943cb65905ab3"
+source = "git+https://git.tawasuyu.net/tawasuyu/tawasuyu.git?tag=v0.2.0#a446bb3a73a0e022158cc0ec7deb65173859644b"
dependencies = [
"llimphi-theme",
"llimphi-ui",
@@ -3441,7 +3893,7 @@ dependencies = [
[[package]]
name = "llimphi-raster"
version = "0.1.0"
-source = "git+https://gitea.tawasuyu.net/sergio/gioser.git?tag=v0.1.0#692b40336c1e9cb12ab561764d6943cb65905ab3"
+source = "git+https://git.tawasuyu.net/tawasuyu/tawasuyu.git?tag=v0.2.0#a446bb3a73a0e022158cc0ec7deb65173859644b"
dependencies = [
"llimphi-hal",
"pollster",
@@ -3451,7 +3903,7 @@ dependencies = [
[[package]]
name = "llimphi-text"
version = "0.1.0"
-source = "git+https://gitea.tawasuyu.net/sergio/gioser.git?tag=v0.1.0#692b40336c1e9cb12ab561764d6943cb65905ab3"
+source = "git+https://git.tawasuyu.net/tawasuyu/tawasuyu.git?tag=v0.2.0#a446bb3a73a0e022158cc0ec7deb65173859644b"
dependencies = [
"parley",
"vello",
@@ -3460,7 +3912,7 @@ dependencies = [
[[package]]
name = "llimphi-theme"
version = "0.1.0"
-source = "git+https://gitea.tawasuyu.net/sergio/gioser.git?tag=v0.1.0#692b40336c1e9cb12ab561764d6943cb65905ab3"
+source = "git+https://git.tawasuyu.net/tawasuyu/tawasuyu.git?tag=v0.2.0#a446bb3a73a0e022158cc0ec7deb65173859644b"
dependencies = [
"llimphi-raster",
]
@@ -3468,21 +3920,27 @@ dependencies = [
[[package]]
name = "llimphi-ui"
version = "0.1.0"
-source = "git+https://gitea.tawasuyu.net/sergio/gioser.git?tag=v0.1.0#692b40336c1e9cb12ab561764d6943cb65905ab3"
+source = "git+https://git.tawasuyu.net/tawasuyu/tawasuyu.git?tag=v0.2.0#a446bb3a73a0e022158cc0ec7deb65173859644b"
dependencies = [
+ "accesskit",
+ "accesskit_winit",
+ "arboard",
"llimphi-compositor",
"llimphi-hal",
"llimphi-layout",
"llimphi-raster",
"llimphi-text",
+ "log",
"pollster",
+ "uuid",
]
[[package]]
name = "llimphi-widget-app-header"
version = "0.1.0"
-source = "git+https://gitea.tawasuyu.net/sergio/gioser.git?tag=v0.1.0#692b40336c1e9cb12ab561764d6943cb65905ab3"
+source = "git+https://git.tawasuyu.net/tawasuyu/tawasuyu.git?tag=v0.2.0#a446bb3a73a0e022158cc0ec7deb65173859644b"
dependencies = [
+ "llimphi-icons",
"llimphi-theme",
"llimphi-ui",
"llimphi-widget-panel",
@@ -3491,7 +3949,7 @@ dependencies = [
[[package]]
name = "llimphi-widget-banner"
version = "0.1.0"
-source = "git+https://gitea.tawasuyu.net/sergio/gioser.git?tag=v0.1.0#692b40336c1e9cb12ab561764d6943cb65905ab3"
+source = "git+https://git.tawasuyu.net/tawasuyu/tawasuyu.git?tag=v0.2.0#a446bb3a73a0e022158cc0ec7deb65173859644b"
dependencies = [
"llimphi-ui",
]
@@ -3499,7 +3957,7 @@ dependencies = [
[[package]]
name = "llimphi-widget-button"
version = "0.1.0"
-source = "git+https://gitea.tawasuyu.net/sergio/gioser.git?tag=v0.1.0#692b40336c1e9cb12ab561764d6943cb65905ab3"
+source = "git+https://git.tawasuyu.net/tawasuyu/tawasuyu.git?tag=v0.2.0#a446bb3a73a0e022158cc0ec7deb65173859644b"
dependencies = [
"llimphi-theme",
"llimphi-ui",
@@ -3508,7 +3966,7 @@ dependencies = [
[[package]]
name = "llimphi-widget-card"
version = "0.1.0"
-source = "git+https://gitea.tawasuyu.net/sergio/gioser.git?tag=v0.1.0#692b40336c1e9cb12ab561764d6943cb65905ab3"
+source = "git+https://git.tawasuyu.net/tawasuyu/tawasuyu.git?tag=v0.2.0#a446bb3a73a0e022158cc0ec7deb65173859644b"
dependencies = [
"llimphi-theme",
"llimphi-ui",
@@ -3518,17 +3976,28 @@ dependencies = [
[[package]]
name = "llimphi-widget-context-menu"
version = "0.1.0"
-source = "git+https://gitea.tawasuyu.net/sergio/gioser.git?tag=v0.1.0#692b40336c1e9cb12ab561764d6943cb65905ab3"
+source = "git+https://git.tawasuyu.net/tawasuyu/tawasuyu.git?tag=v0.2.0#a446bb3a73a0e022158cc0ec7deb65173859644b"
dependencies = [
+ "llimphi-icons",
"llimphi-theme",
"llimphi-ui",
"llimphi-widget-panel",
]
+[[package]]
+name = "llimphi-widget-empty"
+version = "0.1.0"
+source = "git+https://git.tawasuyu.net/tawasuyu/tawasuyu.git?tag=v0.2.0#a446bb3a73a0e022158cc0ec7deb65173859644b"
+dependencies = [
+ "llimphi-icons",
+ "llimphi-theme",
+ "llimphi-ui",
+]
+
[[package]]
name = "llimphi-widget-menubar"
version = "0.1.0"
-source = "git+https://gitea.tawasuyu.net/sergio/gioser.git?tag=v0.1.0#692b40336c1e9cb12ab561764d6943cb65905ab3"
+source = "git+https://git.tawasuyu.net/tawasuyu/tawasuyu.git?tag=v0.2.0#a446bb3a73a0e022158cc0ec7deb65173859644b"
dependencies = [
"app-bus",
"llimphi-theme",
@@ -3540,7 +4009,16 @@ dependencies = [
[[package]]
name = "llimphi-widget-panel"
version = "0.1.0"
-source = "git+https://gitea.tawasuyu.net/sergio/gioser.git?tag=v0.1.0#692b40336c1e9cb12ab561764d6943cb65905ab3"
+source = "git+https://git.tawasuyu.net/tawasuyu/tawasuyu.git?tag=v0.2.0#a446bb3a73a0e022158cc0ec7deb65173859644b"
+dependencies = [
+ "llimphi-theme",
+ "llimphi-ui",
+]
+
+[[package]]
+name = "llimphi-widget-skeleton"
+version = "0.1.0"
+source = "git+https://git.tawasuyu.net/tawasuyu/tawasuyu.git?tag=v0.2.0#a446bb3a73a0e022158cc0ec7deb65173859644b"
dependencies = [
"llimphi-theme",
"llimphi-ui",
@@ -3549,13 +4027,23 @@ dependencies = [
[[package]]
name = "llimphi-widget-stat-card"
version = "0.1.0"
-source = "git+https://gitea.tawasuyu.net/sergio/gioser.git?tag=v0.1.0#692b40336c1e9cb12ab561764d6943cb65905ab3"
+source = "git+https://git.tawasuyu.net/tawasuyu/tawasuyu.git?tag=v0.2.0#a446bb3a73a0e022158cc0ec7deb65173859644b"
dependencies = [
"llimphi-theme",
"llimphi-ui",
"llimphi-widget-card",
]
+[[package]]
+name = "llimphi-widget-toast"
+version = "0.1.0"
+source = "git+https://git.tawasuyu.net/tawasuyu/tawasuyu.git?tag=v0.2.0#a446bb3a73a0e022158cc0ec7deb65173859644b"
+dependencies = [
+ "llimphi-icons",
+ "llimphi-theme",
+ "llimphi-ui",
+]
+
[[package]]
name = "lock_api"
version = "0.4.14"
@@ -3567,9 +4055,9 @@ dependencies = [
[[package]]
name = "log"
-version = "0.4.32"
+version = "0.4.33"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "953f07c43838f8e6f9758cab68bf5bed85465e7587ebe0b823f1bcd81978ad3a"
+checksum = "0ceec5bc11778974d1bcb055b18002eba7f4b3518b6a0081b3af5f21666da9ad"
[[package]]
name = "loop9"
@@ -3619,7 +4107,7 @@ checksum = "757aee279b8bdbb9f9e676796fd459e4207a1f986e87886700abf589f5abf771"
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.119",
]
[[package]]
@@ -3633,9 +4121,9 @@ dependencies = [
[[package]]
name = "matrixmultiply"
-version = "0.3.10"
+version = "0.3.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a06de3016e9fae57a36fd14dba131fccf49f74b40b7fbdb472f96e361ec71a08"
+checksum = "3f607c237553f086e7043417a51df26b2eb899d3caff94e6a67592ff992fedc7"
dependencies = [
"autocfg",
"rawpointer",
@@ -3653,28 +4141,37 @@ dependencies = [
[[package]]
name = "memchr"
-version = "2.8.1"
+version = "2.8.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6b947ae49db0d222b1dbc6b113ce7248a3fc3a6ca21b696717bfc000ba4484d8"
+checksum = "cf8baf1c55e62ffcace7a9f06f4bd9cd3f0c4beb022d3b367256b91b87513d98"
[[package]]
name = "memmap2"
-version = "0.9.10"
+version = "0.9.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "714098028fe011992e1c3962653c96b2d578c4b4bce9036e15ff220319b1e0e3"
+checksum = "d1219ed1b7f229ee7104d281dd01d6802fe28bb6e95d292942c4daacdeb798c0"
dependencies = [
"libc",
]
+[[package]]
+name = "memoffset"
+version = "0.9.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a"
+dependencies = [
+ "autocfg",
+]
+
[[package]]
name = "metal"
-version = "0.31.0"
+version = "0.32.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f569fb946490b5743ad69813cb19629130ce9374034abe31614a36402d18f99e"
+checksum = "00c15a6f673ff72ddcc22394663290f870fb224c1bfce55734a75c414150e605"
dependencies = [
- "bitflags 2.12.1",
+ "bitflags 2.13.1",
"block",
- "core-graphics-types",
+ "core-graphics-types 0.2.0",
"foreign-types 0.5.0",
"log",
"objc",
@@ -3717,9 +4214,9 @@ dependencies = [
[[package]]
name = "mio"
-version = "1.2.1"
+version = "1.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "02bd0af71c67b473010cbbc60715ee815645a4dc942899111f494b4b737d6fda"
+checksum = "30d65c71f1ce40ab09135ce117d742b9f8a19ff91a41a8b57ed50bc2de59c427"
dependencies = [
"libc",
"wasi",
@@ -3762,7 +4259,7 @@ checksum = "e4db6d5580af57bf992f59068d4ea26fd518574ff48d7639b255a36f9de6e7e9"
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.119",
]
[[package]]
@@ -3796,12 +4293,13 @@ dependencies = [
[[package]]
name = "multibase"
-version = "0.9.2"
+version = "0.9.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8694bb4835f452b0e3bb06dbebb1d6fc5385b6ca1caf2e55fd165c042390ec77"
+checksum = "7e0e4a371cbf1dfd666b658ba137763edb23c45beb43cfe369b5593cd6b437b6"
dependencies = [
"base-x",
"base256emoji",
+ "base45",
"data-encoding",
"data-encoding-macro",
]
@@ -3831,24 +4329,28 @@ dependencies = [
[[package]]
name = "naga"
-version = "24.0.0"
+version = "27.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e380993072e52eef724eddfcde0ed013b0c023c3f0417336ed041aa9f076994e"
+checksum = "066cf25f0e8b11ee0df221219010f213ad429855f57c494f995590c861a9a7d8"
dependencies = [
"arrayvec",
"bit-set",
- "bitflags 2.12.1",
+ "bitflags 2.13.1",
+ "cfg-if",
"cfg_aliases",
"codespan-reporting",
+ "half",
+ "hashbrown 0.16.1",
"hexf-parse",
"indexmap",
+ "libm",
"log",
+ "num-traits",
+ "once_cell",
"rustc-hash 1.1.0",
"spirv",
- "strum",
- "termcolor",
- "thiserror 2.0.18",
- "unicode-xid",
+ "thiserror 2.0.19",
+ "unicode-ident",
]
[[package]]
@@ -3889,10 +4391,10 @@ version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c3f42e7bbe13d351b6bead8286a43aac9534b82bd3cc43e47037f012ebfd62d4"
dependencies = [
- "bitflags 2.12.1",
+ "bitflags 2.13.1",
"jni-sys 0.3.1",
"log",
- "ndk-sys 0.6.0+11769913",
+ "ndk-sys",
"num_enum",
"raw-window-handle",
"thiserror 1.0.69",
@@ -3904,15 +4406,6 @@ version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "27b02d87554356db9e9a873add8782d4ea6e3e58ea071a9adb9a2e8ddb884a8b"
-[[package]]
-name = "ndk-sys"
-version = "0.5.0+25.2.9519653"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8c196769dd60fd4f363e11d948139556a344e79d451aeb2fa2fd040738ef7691"
-dependencies = [
- "jni-sys 0.3.1",
-]
-
[[package]]
name = "ndk-sys"
version = "0.6.0+11769913"
@@ -3937,7 +4430,7 @@ version = "0.28.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4ce3636fa715e988114552619582b530481fd5ef176a1e5c1bf024077c2c9445"
dependencies = [
- "bitflags 2.12.1",
+ "bitflags 2.13.1",
"libc",
"log",
"netlink-packet-core",
@@ -3945,16 +4438,17 @@ dependencies = [
[[package]]
name = "netlink-proto"
-version = "0.12.0"
+version = "0.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b65d130ee111430e47eed7896ea43ca693c387f097dd97376bffafbf25812128"
+checksum = "e6f7398dddf5f152d2a91a2921a134c6097056e292c0d4b9906007855e7cece6"
dependencies = [
"bytes",
- "futures",
+ "futures-channel",
+ "futures-util",
"log",
"netlink-packet-core",
"netlink-sys",
- "thiserror 2.0.18",
+ "thiserror 2.0.19",
]
[[package]]
@@ -3982,7 +4476,7 @@ version = "0.30.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "74523f3a35e05aba87a1d978330aef40f67b0304ac79c1c00b294c9830543db6"
dependencies = [
- "bitflags 2.12.1",
+ "bitflags 2.13.1",
"cfg-if",
"cfg_aliases",
"libc",
@@ -4034,7 +4528,7 @@ version = "6.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6205bd8bb1e454ad2e27422015fb5e4f2bcc7e08fa8f27058670d208324a4d2d"
dependencies = [
- "bitflags 2.12.1",
+ "bitflags 2.13.1",
"crossbeam-channel",
"filetime",
"fsevent-sys",
@@ -4058,9 +4552,9 @@ dependencies = [
[[package]]
name = "num-bigint"
-version = "0.4.6"
+version = "0.4.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9"
+checksum = "c89e69e7e0f03bea5ef08013795c25018e101932225a656383bd384495ecc367"
dependencies = [
"num-integer",
"num-traits",
@@ -4072,6 +4566,7 @@ version = "0.4.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495"
dependencies = [
+ "bytemuck",
"num-traits",
]
@@ -4089,7 +4584,7 @@ checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202"
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.119",
]
[[package]]
@@ -4119,6 +4614,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841"
dependencies = [
"autocfg",
+ "libm",
]
[[package]]
@@ -4140,7 +4636,7 @@ dependencies = [
"proc-macro-crate",
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.119",
]
[[package]]
@@ -4189,7 +4685,7 @@ version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e4e89ad9e3d7d297152b17d39ed92cd50ca8063a89a9fa569046d41568891eff"
dependencies = [
- "bitflags 2.12.1",
+ "bitflags 2.13.1",
"block2",
"libc",
"objc2 0.5.2",
@@ -4199,13 +4695,25 @@ dependencies = [
"objc2-quartz-core",
]
+[[package]]
+name = "objc2-app-kit"
+version = "0.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d49e936b501e5c5bf01fda3a9452ff86dc3ea98ad5f283e1455153142d97518c"
+dependencies = [
+ "bitflags 2.13.1",
+ "objc2 0.6.4",
+ "objc2-core-graphics",
+ "objc2-foundation 0.3.2",
+]
+
[[package]]
name = "objc2-cloud-kit"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "74dd3b56391c7a0596a295029734d3c1c5e7e510a4cb30245f8221ccea96b009"
dependencies = [
- "bitflags 2.12.1",
+ "bitflags 2.13.1",
"block2",
"objc2 0.5.2",
"objc2-core-location",
@@ -4229,7 +4737,7 @@ version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "617fbf49e071c178c0b24c080767db52958f716d9eabdf0890523aeae54773ef"
dependencies = [
- "bitflags 2.12.1",
+ "bitflags 2.13.1",
"block2",
"objc2 0.5.2",
"objc2-foundation 0.2.2",
@@ -4241,7 +4749,22 @@ version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2a180dd8642fa45cdb7dd721cd4c11b1cadd4929ce112ebd8b9f5803cc79d536"
dependencies = [
- "bitflags 2.12.1",
+ "bitflags 2.13.1",
+ "dispatch2",
+ "objc2 0.6.4",
+]
+
+[[package]]
+name = "objc2-core-graphics"
+version = "0.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e022c9d066895efa1345f8e33e584b9f958da2fd4cd116792e15e07e4720a807"
+dependencies = [
+ "bitflags 2.13.1",
+ "dispatch2",
+ "objc2 0.6.4",
+ "objc2-core-foundation",
+ "objc2-io-surface",
]
[[package]]
@@ -4274,7 +4797,7 @@ version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0cde0dfb48d25d2b4862161a4d5fcc0e3c24367869ad306b0c9ec0073bfed92d"
dependencies = [
- "bitflags 2.12.1",
+ "bitflags 2.13.1",
"objc2-core-foundation",
]
@@ -4290,7 +4813,7 @@ version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0ee638a5da3799329310ad4cfa62fbf045d5f56e3ef5ba4149e7452dcf89d5a8"
dependencies = [
- "bitflags 2.12.1",
+ "bitflags 2.13.1",
"block2",
"dispatch",
"libc",
@@ -4303,8 +4826,20 @@ version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e3e0adef53c21f888deb4fa59fc59f7eb17404926ee8a6f59f5df0fd7f9f3272"
dependencies = [
- "bitflags 2.12.1",
+ "bitflags 2.13.1",
+ "objc2 0.6.4",
+ "objc2-core-foundation",
+]
+
+[[package]]
+name = "objc2-io-surface"
+version = "0.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "180788110936d59bab6bd83b6060ffdfffb3b922ba1396b312ae795e1de9d81d"
+dependencies = [
+ "bitflags 2.13.1",
"objc2 0.6.4",
+ "objc2-core-foundation",
]
[[package]]
@@ -4315,7 +4850,7 @@ checksum = "a1a1ae721c5e35be65f01a03b6d2ac13a54cb4fa70d8a5da293d7b0020261398"
dependencies = [
"block2",
"objc2 0.5.2",
- "objc2-app-kit",
+ "objc2-app-kit 0.2.2",
"objc2-foundation 0.2.2",
]
@@ -4325,7 +4860,7 @@ version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dd0cba1276f6023976a406a14ffa85e1fdd19df6b0f737b063b95f6c8c7aadd6"
dependencies = [
- "bitflags 2.12.1",
+ "bitflags 2.13.1",
"block2",
"objc2 0.5.2",
"objc2-foundation 0.2.2",
@@ -4337,7 +4872,7 @@ version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e42bee7bff906b14b167da2bac5efe6b6a07e6f7c0a21a7308d40c960242dc7a"
dependencies = [
- "bitflags 2.12.1",
+ "bitflags 2.13.1",
"block2",
"objc2 0.5.2",
"objc2-foundation 0.2.2",
@@ -4360,7 +4895,7 @@ version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b8bb46798b20cd6b91cbd113524c490f1686f4c4e8f49502431415f3512e2b6f"
dependencies = [
- "bitflags 2.12.1",
+ "bitflags 2.13.1",
"block2",
"objc2 0.5.2",
"objc2-cloud-kit",
@@ -4392,7 +4927,7 @@ version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "76cfcbf642358e8689af64cee815d139339f3ed8ad05103ed5eaf73db8d84cb3"
dependencies = [
- "bitflags 2.12.1",
+ "bitflags 2.13.1",
"block2",
"objc2 0.5.2",
"objc2-core-location",
@@ -4424,7 +4959,7 @@ version = "6.5.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0cc3cbf698f9438986c11a880c90a6d04b9de27575afd28bbf45b154b6c709e2"
dependencies = [
- "bitflags 2.12.1",
+ "bitflags 2.13.1",
"libc",
"once_cell",
"onig_sys",
@@ -4448,11 +4983,11 @@ checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381"
[[package]]
name = "openssl"
-version = "0.10.80"
+version = "0.10.81"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a45fa2aa886c42762255da344f0a0d313e254066c46aad76f300c3d3da62d967"
+checksum = "77823a27f0babb03091cb9ed9ef80af3b39dbc82f97e8fa530374b7dafd87a45"
dependencies = [
- "bitflags 2.12.1",
+ "bitflags 2.13.1",
"cfg-if",
"foreign-types 0.3.2",
"libc",
@@ -4468,7 +5003,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c"
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.119",
]
[[package]]
@@ -4479,9 +5014,9 @@ checksum = "7c87def4c32ab89d880effc9e097653c8da5d6ef28e6b539d313baaacfbafcbe"
[[package]]
name = "openssl-sys"
-version = "0.9.116"
+version = "0.9.117"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f28a22dc7140cda5f096e5e7724a6962ca81a7f8bfd2979f9b18c11af56318c4"
+checksum = "b47e7e6bb2c38cd930d25a23b40fa52e068c10e85f3e03a7f5ba5aaca5713695"
dependencies = [
"cc",
"libc",
@@ -4507,13 +5042,23 @@ dependencies = [
[[package]]
name = "ordered-float"
-version = "4.6.0"
+version = "5.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7bb71e1b3fa6ca1c61f383464aaf2bb0e2f8e772a1f01d486832464de363b951"
+checksum = "b7d950ca161dc355eaf28f82b11345ed76c6e1f6eb1f4f4479e0323b9e2fbd0e"
dependencies = [
"num-traits",
]
+[[package]]
+name = "ordered-stream"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9aa2b01e1d916879f73a53d01d1d6cee68adbb31d6d9177a8cfce093cced1d50"
+dependencies = [
+ "futures-core",
+ "pin-project-lite",
+]
+
[[package]]
name = "ort"
version = "2.0.0-rc.9"
@@ -4538,6 +5083,16 @@ dependencies = [
"ureq",
]
+[[package]]
+name = "os_pipe"
+version = "1.2.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7d8fae84b431384b68627d0f9b3b1245fcf9f46f6c0e3dc902e9dce64edd1967"
+dependencies = [
+ "libc",
+ "windows-sys 0.61.2",
+]
+
[[package]]
name = "owned_ttf_parser"
version = "0.25.1"
@@ -4603,14 +5158,15 @@ dependencies = [
[[package]]
name = "parley"
-version = "0.4.0"
+version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e28dadbe655332fd7d996794ec8d0c376695f6ca47bc75aa01e0967c7f28e42a"
+checksum = "26746861bb76dbc9bcd5ed1b0b55d2fedf291100961251702a031ab2abd2ce52"
dependencies = [
"fontique",
+ "harfrust",
"hashbrown 0.15.5",
- "peniko",
- "skrifa 0.31.3",
+ "linebender_resource_handle",
+ "skrifa 0.37.0",
"swash",
]
@@ -4638,9 +5194,9 @@ dependencies = [
[[package]]
name = "peniko"
-version = "0.4.1"
+version = "0.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9b44f9ddd2f480176b34278eb653ec1c8062f3b143a4e16eeff5ffac3334e288"
+checksum = "839c8299360d2e998bdb106dc0a6cd71dcc5f4df51df1b620361bf50e283cca6"
dependencies = [
"color",
"kurbo",
@@ -4654,6 +5210,60 @@ version = "2.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220"
+[[package]]
+name = "petgraph"
+version = "0.8.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8701b58ea97060d5e5b155d383a69952a60943f0e6dfe30b04c287beb0b27455"
+dependencies = [
+ "fixedbitset",
+ "hashbrown 0.15.5",
+ "indexmap",
+]
+
+[[package]]
+name = "phf"
+version = "0.13.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c1562dc717473dbaa4c1f85a36410e03c047b2e7df7f45ee938fbef64ae7fadf"
+dependencies = [
+ "phf_macros",
+ "phf_shared",
+ "serde",
+]
+
+[[package]]
+name = "phf_generator"
+version = "0.13.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "135ace3a761e564ec88c03a77317a7c6b80bb7f7135ef2544dbe054243b89737"
+dependencies = [
+ "fastrand",
+ "phf_shared",
+]
+
+[[package]]
+name = "phf_macros"
+version = "0.13.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "812f032b54b1e759ccd5f8b6677695d5268c588701effba24601f6932f8269ef"
+dependencies = [
+ "phf_generator",
+ "phf_shared",
+ "proc-macro2",
+ "quote",
+ "syn 2.0.119",
+]
+
+[[package]]
+name = "phf_shared"
+version = "0.13.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e57fef6bc5981e38c2ce2d63bfa546861309f875b8a75f092d1d54ae2d64f266"
+dependencies = [
+ "siphasher",
+]
+
[[package]]
name = "pin-project"
version = "1.1.13"
@@ -4671,7 +5281,7 @@ checksum = "c96395f0a926bc13b1c17622aaddda1ecb55d49c8f1bf9777e4d877800a43f8b"
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.119",
]
[[package]]
@@ -4680,6 +5290,17 @@ version = "0.2.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd"
+[[package]]
+name = "piper"
+version = "0.2.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c835479a4443ded371d6c535cbfd8d31ad92c5d23ae9770a61bc155e4992a3c1"
+dependencies = [
+ "atomic-waker",
+ "fastrand",
+ "futures-io",
+]
+
[[package]]
name = "pkcs8"
version = "0.10.2"
@@ -4721,7 +5342,7 @@ version = "0.18.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "60769b8b31b2a9f263dae2776c37b1b28ae246943cf719eb6946a1db05128a61"
dependencies = [
- "bitflags 2.12.1",
+ "bitflags 2.13.1",
"crc32fast",
"fdeflate",
"flate2",
@@ -4759,6 +5380,15 @@ dependencies = [
"universal-hash",
]
+[[package]]
+name = "polycool"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "50596ddc09eb5ad5f75cacd40209568e66df71baf86e1499a0e99c4cff12a5a6"
+dependencies = [
+ "arrayvec",
+]
+
[[package]]
name = "polyval"
version = "0.6.2"
@@ -4773,9 +5403,9 @@ dependencies = [
[[package]]
name = "portable-atomic"
-version = "1.13.1"
+version = "1.14.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c33a9471896f1c69cecef8d20cbe2f7accd12527ce60845ff44c153bb2a21b49"
+checksum = "3d20d5497ef88037a52ff98267d066e7f11fcc5e99bbfbd58a42336193aacec3"
[[package]]
name = "portable-atomic-util"
@@ -4829,23 +5459,13 @@ version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e8cf8e6a8aa66ce33f63993ffc4ea4271eb5b0530a9002db8455ea6050c77bfa"
-[[package]]
-name = "prettyplease"
-version = "0.2.37"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b"
-dependencies = [
- "proc-macro2",
- "syn",
-]
-
[[package]]
name = "proc-macro-crate"
version = "3.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e67ba7e9b2b56446f1d419b1d807906278ffa1a658a8a5d8a39dcb1f5a78614f"
dependencies = [
- "toml_edit 0.25.12+spec-1.1.0",
+ "toml_edit 0.25.13+spec-1.1.0",
]
[[package]]
@@ -4856,9 +5476,9 @@ checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068"
[[package]]
name = "proc-macro2"
-version = "1.0.106"
+version = "1.0.107"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934"
+checksum = "985e7ec9bb745e6ce6535b544d84d6cd6f7ad8bd711c398938ae983b91a766d9"
dependencies = [
"unicode-ident",
]
@@ -4879,7 +5499,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4488a4a36b9a4ba6b9334a32a39971f77c1436ec82c38707bce707699cc3bbcb"
dependencies = [
"quote",
- "syn",
+ "syn 2.0.119",
]
[[package]]
@@ -4902,14 +5522,14 @@ checksum = "440f724eba9f6996b75d63681b0a92b06947f1457076d503a4d2e2c8f56442b8"
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.119",
]
[[package]]
name = "prost"
-version = "0.14.3"
+version = "0.14.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d2ea70524a2f82d518bce41317d0fae74151505651af45faf1ffbd6fd33f0568"
+checksum = "528ac67416ff8646872a3c02cad9cc4ee5dc9f9540c9b10771855c95cb2e5ae1"
dependencies = [
"bytes",
"prost-derive",
@@ -4917,22 +5537,45 @@ dependencies = [
[[package]]
name = "prost-derive"
-version = "0.14.3"
+version = "0.14.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "27c6023962132f4b30eb4c172c91ce92d933da334c59c23cddee82358ddafb0b"
+checksum = "b570b25f7617e43d59005d0990ccb79e950a423952cea19671b7a876da390adf"
dependencies = [
"anyhow",
"itertools",
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.119",
+]
+
+[[package]]
+name = "pulp"
+version = "0.22.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "046aa45b989642ec2e4717c8e72d677b13edd831a4d3b6cf37d9a3e54912496a"
+dependencies = [
+ "bytemuck",
+ "cfg-if",
+ "libm",
+ "num-complex",
+ "paste",
+ "pulp-wasm-simd-flag",
+ "raw-cpuid",
+ "reborrow",
+ "version_check",
]
+[[package]]
+name = "pulp-wasm-simd-flag"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1d8f70e07b9c3962945a74e59ca1c511bba65b6419468acc217c457d93f3c740"
+
[[package]]
name = "pxfm"
-version = "0.1.29"
+version = "0.1.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e0c5ccf5294c6ccd63a74f1565028353830a9c2f5eb0c682c355c471726a6e3f"
+checksum = "d55d956fa96f5ec02be2e13af0e20391a5aa83d6a074e3ad368959d0fab299ea"
[[package]]
name = "qoi"
@@ -4973,18 +5616,18 @@ dependencies = [
[[package]]
name = "quick-xml"
-version = "0.39.4"
+version = "0.41.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cdcc8dd4e2f670d309a5f0e83fe36dfdc05af317008fea29144da1a2ac858e5e"
+checksum = "e660451e55124f798a69a5af3f49ccfbefbd41910eefd25caf2393e1f3473ec1"
dependencies = [
"memchr",
]
[[package]]
name = "quinn"
-version = "0.11.9"
+version = "0.11.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b9e20a958963c291dc322d98411f541009df2ced7b5a4f2bd52337638cfccf20"
+checksum = "0c1a41e437b6bbd489372cd4971de128e85c855f56c57f283d20ff016cf7c0a8"
dependencies = [
"bytes",
"cfg_aliases",
@@ -4992,10 +5635,10 @@ dependencies = [
"pin-project-lite",
"quinn-proto",
"quinn-udp",
- "rustc-hash 2.1.2",
+ "rustc-hash 2.1.3",
"rustls",
- "socket2 0.6.4",
- "thiserror 2.0.18",
+ "socket2 0.6.5",
+ "thiserror 2.0.19",
"tokio",
"tracing",
"web-time",
@@ -5003,20 +5646,22 @@ dependencies = [
[[package]]
name = "quinn-proto"
-version = "0.11.14"
+version = "0.11.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "434b42fec591c96ef50e21e886936e66d3cc3f737104fdb9b737c40ffb94c098"
+checksum = "2f4bfc015262b9df63c8845072ce59068853ff5872180c2ce2f13038b970e560"
dependencies = [
"bytes",
- "getrandom 0.3.4",
+ "fastbloom",
+ "getrandom 0.4.3",
"lru-slab",
- "rand 0.9.4",
+ "rand 0.10.2",
+ "rand_pcg",
"ring",
- "rustc-hash 2.1.2",
+ "rustc-hash 2.1.3",
"rustls",
"rustls-pki-types",
"slab",
- "thiserror 2.0.18",
+ "thiserror 2.0.19",
"tinyvec",
"tracing",
"web-time",
@@ -5024,23 +5669,23 @@ dependencies = [
[[package]]
name = "quinn-udp"
-version = "0.5.14"
+version = "0.5.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "addec6a0dcad8a8d96a771f815f0eaf55f9d1805756410b39f5fa81332574cbd"
+checksum = "35a133f956daabe89a61a685c2649f13d82d5aa4bd5d12d1277e1072a21c0694"
dependencies = [
"cfg_aliases",
"libc",
"once_cell",
- "socket2 0.6.4",
+ "socket2 0.6.5",
"tracing",
- "windows-sys 0.60.2",
+ "windows-sys 0.61.2",
]
[[package]]
name = "quote"
-version = "1.0.45"
+version = "1.0.47"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924"
+checksum = "1fbf4db142a473a8d80c26bbf18454ed458bf8d26c8219c331daecfdbd079001"
dependencies = [
"proc-macro2",
]
@@ -5059,9 +5704,9 @@ checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf"
[[package]]
name = "rand"
-version = "0.8.6"
+version = "0.8.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5ca0ecfa931c29007047d1bc58e623ab12e5590e8c7cc53200d5202b69266d8a"
+checksum = "22f6172bdec972074665ed81ed53b71da00bfc44b65a753cfde883ec4c702a1a"
dependencies = [
"libc",
"rand_chacha 0.3.1",
@@ -5070,14 +5715,25 @@ dependencies = [
[[package]]
name = "rand"
-version = "0.9.4"
+version = "0.9.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "44c5af06bb1b7d3216d91932aed5265164bf384dc89cd6ba05cf59a35f5f76ea"
+checksum = "b9ef1d0d795eb7d84685bca4f72f3649f064e6641543d3a8c415898726a57b41"
dependencies = [
"rand_chacha 0.9.0",
"rand_core 0.9.5",
]
+[[package]]
+name = "rand"
+version = "0.10.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c7f5fa3a058cd35567ef9bfa5e75732bee0f9e4c55fa90477bef2dfcdbc4be80"
+dependencies = [
+ "chacha20 0.10.1",
+ "getrandom 0.4.3",
+ "rand_core 0.10.1",
+]
+
[[package]]
name = "rand_chacha"
version = "0.3.1"
@@ -5116,6 +5772,21 @@ dependencies = [
"getrandom 0.3.4",
]
+[[package]]
+name = "rand_core"
+version = "0.10.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "63b8176103e19a2643978565ca18b50549f6101881c443590420e4dc998a3c69"
+
+[[package]]
+name = "rand_pcg"
+version = "0.10.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "caa0f4137e1c0a72f4c651489402276c8e8e1cf081f3b0ba156d2cbeef09e86a"
+dependencies = [
+ "rand_core 0.10.1",
+]
+
[[package]]
name = "range-alloc"
version = "0.1.5"
@@ -5149,10 +5820,10 @@ dependencies = [
"num-traits",
"paste",
"profiling",
- "rand 0.9.4",
+ "rand 0.9.5",
"rand_chacha 0.9.0",
"simd_helpers",
- "thiserror 2.0.18",
+ "thiserror 2.0.19",
"v_frame",
"wasm-bindgen",
]
@@ -5172,6 +5843,15 @@ dependencies = [
"rgb",
]
+[[package]]
+name = "raw-cpuid"
+version = "11.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "498cd0dc59d73224351ee52a95fee0f1a617a2eae0e7d9d720cc622c73a54186"
+dependencies = [
+ "bitflags 2.13.1",
+]
+
[[package]]
name = "raw-window-handle"
version = "0.6.2"
@@ -5230,34 +5910,42 @@ dependencies = [
[[package]]
name = "read-fonts"
-version = "0.29.3"
+version = "0.35.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "04ca636dac446b5664bd16c069c00a9621806895b8bb02c2dc68542b23b8f25d"
+checksum = "6717cf23b488adf64b9d711329542ba34de147df262370221940dfabc2c91358"
dependencies = [
"bytemuck",
- "font-types 0.9.0",
+ "core_maths",
+ "font-types 0.10.1",
]
[[package]]
name = "read-fonts"
-version = "0.33.1"
+version = "0.37.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "50ea612a55c08586a1d15134be8a776186c440c312ebda3b9e8efbfe4255b7f4"
+checksum = "7b634fabf032fab15307ffd272149b622260f55974d9fad689292a5d33df02e5"
dependencies = [
"bytemuck",
- "font-types 0.9.0",
+ "font-types 0.11.3",
]
[[package]]
name = "read-fonts"
-version = "0.37.0"
+version = "0.41.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7b634fabf032fab15307ffd272149b622260f55974d9fad689292a5d33df02e5"
+checksum = "046a7d674daf459825b32f5062056d6882db0d2f5a479fbd76ccfc870ac18709"
dependencies = [
"bytemuck",
- "font-types 0.11.3",
+ "font-types 0.12.2",
+ "once_cell",
]
+[[package]]
+name = "reborrow"
+version = "0.5.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "03251193000f4bd3b042892be858ee50e8b3719f2b08e5833ac4353724632430"
+
[[package]]
name = "redox_syscall"
version = "0.2.16"
@@ -5282,16 +5970,16 @@ version = "0.5.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d"
dependencies = [
- "bitflags 2.12.1",
+ "bitflags 2.13.1",
]
[[package]]
name = "redox_syscall"
-version = "0.8.1"
+version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5b44b894f2a6e36457d665d1e08c3866add6ed5e70050c1b4ba8a8ddedb02ce7"
+checksum = "c5102a6aaa05aa011a238e178e6bca86d2cb56fc9f586d37cb80f5bca6e07759"
dependencies = [
- "bitflags 2.12.1",
+ "bitflags 2.13.1",
]
[[package]]
@@ -5313,14 +6001,14 @@ checksum = "a4e608c6638b9c18977b00b475ac1f28d14e84b27d8d42f70e0bf1e3dec127ac"
dependencies = [
"getrandom 0.2.17",
"libredox",
- "thiserror 2.0.18",
+ "thiserror 2.0.19",
]
[[package]]
name = "regex"
-version = "1.12.3"
+version = "1.13.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e10754a14b9137dd7b1e3e5b0493cc9171fdd105e0ab477f51b72e7f3ac0e276"
+checksum = "f020237b6c8eed93db2e2cb53c00c60a8e1bc73da7d073199a1180401450218d"
dependencies = [
"aho-corasick",
"memchr",
@@ -5330,9 +6018,9 @@ dependencies = [
[[package]]
name = "regex-automata"
-version = "0.4.14"
+version = "0.4.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6e1dd4122fc1595e8162618945476892eefca7b88c52820e74af6262213cae8f"
+checksum = "8fcfdb36bda0c880c5931cdc7a2bcdc8ba4556847b9d912bca70bc94708711ad"
dependencies = [
"aho-corasick",
"memchr",
@@ -5341,9 +6029,9 @@ dependencies = [
[[package]]
name = "regex-syntax"
-version = "0.8.10"
+version = "0.8.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dc897dd8d9e8bd1ed8cdad82b5966c3e0ecae09fb1907d58efaa013543185d0a"
+checksum = "d6f6ff9a378485b298a5286656da665ba74413d36db0979633275d2e708145d4"
[[package]]
name = "renderdoc-sys"
@@ -5409,13 +6097,14 @@ checksum = "47b34b781b31e5d73e9fbc8689c70551fd1ade9a19e3e28cfec8580a79290cc4"
[[package]]
name = "rimay-localize"
version = "0.1.0"
-source = "git+https://gitea.tawasuyu.net/sergio/gioser.git?tag=v0.1.0#692b40336c1e9cb12ab561764d6943cb65905ab3"
+source = "git+https://git.tawasuyu.net/tawasuyu/tawasuyu.git?tag=v0.2.0#a446bb3a73a0e022158cc0ec7deb65173859644b"
dependencies = [
+ "directories",
"fluent-bundle",
"once_cell",
"parking_lot 0.12.5",
"sys-locale",
- "thiserror 2.0.18",
+ "thiserror 2.0.19",
"tracing",
"unic-langid",
]
@@ -5466,9 +6155,9 @@ checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
[[package]]
name = "rustc-hash"
-version = "2.1.2"
+version = "2.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "94300abf3f1ae2e2b8ffb7b58043de3d399c73fa6f4b73826402a5c457614dbe"
+checksum = "6b1e7f9a428571be2dc5bc0505c13fb6bf936822b894ec87abf8a08a4e51742d"
[[package]]
name = "rustc_version"
@@ -5494,7 +6183,7 @@ version = "0.38.44"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154"
dependencies = [
- "bitflags 2.12.1",
+ "bitflags 2.13.1",
"errno",
"libc",
"linux-raw-sys 0.4.15",
@@ -5507,7 +6196,7 @@ version = "1.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b6fe4565b9518b83ef4f91bb47ce29620ca828bd32cb7e408f0062e9930ba190"
dependencies = [
- "bitflags 2.12.1",
+ "bitflags 2.13.1",
"errno",
"libc",
"linux-raw-sys 0.12.1",
@@ -5516,9 +6205,9 @@ dependencies = [
[[package]]
name = "rustls"
-version = "0.23.40"
+version = "0.23.42"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ef86cd5876211988985292b91c96a8f2d298df24e75989a43a3c73f2d4d8168b"
+checksum = "3c54fcab019b409d04215d3a17cb438fd7fbf192ee61461f20f4fe18704bc138"
dependencies = [
"log",
"once_cell",
@@ -5531,9 +6220,9 @@ dependencies = [
[[package]]
name = "rustls-pki-types"
-version = "1.14.1"
+version = "1.15.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "30a7197ae7eb376e574fe940d068c30fe0462554a3ddbe4eca7838e049c937a9"
+checksum = "2f4925028c7eb5d1fcdaf196971378ed9d2c1c4efc7dc5d011256f76c99c0a96"
dependencies = [
"web-time",
"zeroize",
@@ -5552,9 +6241,9 @@ dependencies = [
[[package]]
name = "rustversion"
-version = "1.0.22"
+version = "1.0.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d"
+checksum = "cf54715a573b99ac80df0bc206da022bcd442c974952c7b9720069370852e21f"
[[package]]
name = "rw-stream-sink"
@@ -5622,7 +6311,7 @@ version = "3.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b7f4bc775c73d9a02cde8bf7b2ec4c9d12743edf609006c7facc23998404cd1d"
dependencies = [
- "bitflags 2.12.1",
+ "bitflags 2.13.1",
"core-foundation 0.10.1",
"core-foundation-sys",
"libc",
@@ -5645,14 +6334,14 @@ version = "0.10.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e14e4d63b804dc0c7ec4a1e52bcb63f02c7ac94476755aa579edac21e01f915d"
dependencies = [
- "self_cell 1.2.2",
+ "self_cell 1.3.0",
]
[[package]]
name = "self_cell"
-version = "1.2.2"
+version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b12e76d157a900eb52e81bc6e9f3069344290341720e9178cde2407113ac8d89"
+checksum = "2ab42ca02749e120097e328d91d415325bdf43b1c72c4c8badf37375fe40a813"
[[package]]
name = "semver"
@@ -5662,39 +6351,48 @@ checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd"
[[package]]
name = "serde"
-version = "1.0.228"
+version = "1.0.229"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e"
+checksum = "4148590afebada386688f18773da617792bf2ef03ffc1e4cbd2b1d45b023e0ba"
dependencies = [
"serde_core",
"serde_derive",
]
+[[package]]
+name = "serde-big-array"
+version = "0.5.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "11fc7cc2c76d73e0f27ee52abbd64eec84d46f370c88371120433196934e4b7f"
+dependencies = [
+ "serde",
+]
+
[[package]]
name = "serde_core"
-version = "1.0.228"
+version = "1.0.229"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad"
+checksum = "67dca2c9c51e58a4791a4b1ed58308b39c64224d349a935ab5039aa360942a48"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
-version = "1.0.228"
+version = "1.0.229"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79"
+checksum = "e7a5d71263a5a7d47b41f6b3f06ba276f10cc18b0931f1799f710578e2309348"
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 3.0.3",
]
[[package]]
name = "serde_json"
-version = "1.0.150"
+version = "1.0.151"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e8014e44b4736ed0538adeecded0fce2a272f22dc9578a7eb6b2d9993c74cfb9"
+checksum = "c841b55ecdae098c80dcae9cf767f6f8a0c2cdb3416bbef72181df4d0fe73f14"
dependencies = [
"itoa",
"memchr",
@@ -5703,6 +6401,17 @@ dependencies = [
"zmij",
]
+[[package]]
+name = "serde_repr"
+version = "0.1.21"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8d3b1629de253c70a0508c3899572da79ca359fdab27c7920ff00406df418906"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 3.0.3",
+]
+
[[package]]
name = "serde_spanned"
version = "0.6.9"
@@ -5753,7 +6462,7 @@ checksum = "f8fadd59c855ef2080decdef8ff161eb6661b86933c9d82e5ba29dc602a55aba"
[[package]]
name = "shuma-discern"
version = "0.1.0"
-source = "git+https://gitea.tawasuyu.net/sergio/gioser.git?tag=v0.1.0#692b40336c1e9cb12ab561764d6943cb65905ab3"
+source = "git+https://git.tawasuyu.net/tawasuyu/tawasuyu.git?tag=v0.2.0#a446bb3a73a0e022158cc0ec7deb65173859644b"
dependencies = [
"card-core",
"serde_json",
@@ -5781,15 +6490,15 @@ dependencies = [
[[package]]
name = "simd-adler32"
-version = "0.3.9"
+version = "0.3.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "703d5c7ef118737c72f1af64ad2f6f8c5e1921f818cdcb97b8fe6fc69bf66214"
+checksum = "3a219298ac11a56ea9a6d2120044824d6f01aeb034955e7af7bc16858527deea"
[[package]]
name = "simd_cesu8"
-version = "1.1.1"
+version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "94f90157bb87cddf702797c5dadfa0be7d266cdf49e22da2fcaa32eff75b2c33"
+checksum = "11031e251abf8611c80f460e19dbdeb54a66db918e49c65a7065b46ac7aec520"
dependencies = [
"rustc_version",
"simdutf8",
@@ -5810,34 +6519,40 @@ version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e3a9fe34e3e7a50316060351f37187a3f546bce95496156754b601a5fa71b76e"
+[[package]]
+name = "siphasher"
+version = "1.0.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8ee5873ec9cce0195efcb7a4e9507a04cd49aec9c83d0389df45b1ef7ba2e649"
+
[[package]]
name = "skrifa"
-version = "0.31.3"
+version = "0.37.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dbeb4ca4399663735553a09dd17ce7e49a0a0203f03b706b39628c4d913a8607"
+checksum = "8c31071dedf532758ecf3fed987cdb4bd9509f900e026ab684b4ecb81ea49841"
dependencies = [
"bytemuck",
- "read-fonts 0.29.3",
+ "read-fonts 0.35.0",
]
[[package]]
name = "skrifa"
-version = "0.35.0"
+version = "0.40.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "576e60c7de4bb6a803a0312f9bef17e78cf1e8d25a80e1ade76770d7a0237955"
+checksum = "7fbdfe3d2475fbd7ddd1f3e5cf8288a30eb3e5f95832829570cd88115a7434ac"
dependencies = [
"bytemuck",
- "read-fonts 0.33.1",
+ "read-fonts 0.37.0",
]
[[package]]
name = "skrifa"
-version = "0.40.0"
+version = "0.44.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7fbdfe3d2475fbd7ddd1f3e5cf8288a30eb3e5f95832829570cd88115a7434ac"
+checksum = "819ab7d62b1d3e72d9d9dea5650bac30424f9111364bb94928dbf5ecad1baa68"
dependencies = [
"bytemuck",
- "read-fonts 0.37.0",
+ "read-fonts 0.41.0",
]
[[package]]
@@ -5873,9 +6588,9 @@ dependencies = [
[[package]]
name = "smallvec"
-version = "1.15.1"
+version = "1.15.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03"
+checksum = "8ed6a63f02c8539c91a8685a86f4099661ba3da017932f6ebbea6de3f0fa7c90"
[[package]]
name = "smithay-client-toolkit"
@@ -5883,7 +6598,7 @@ version = "0.19.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3457dea1f0eb631b4034d61d4d8c32074caa6cd1ab2d59f2327bd8461e2c0016"
dependencies = [
- "bitflags 2.12.1",
+ "bitflags 2.13.1",
"calloop",
"calloop-wayland-source",
"cursor-icon",
@@ -5940,9 +6655,9 @@ dependencies = [
[[package]]
name = "socket2"
-version = "0.6.4"
+version = "0.6.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "52d1cfed4120b4d927bf7c0f86d2087a4a7d6027c906d9f9d525a80573b9be51"
+checksum = "c3d1e2c7f27f8d4cb10542a02c49005dbd6e93095799d6f3be745fae9f8fedd4"
dependencies = [
"libc",
"windows-sys 0.61.2",
@@ -5961,9 +6676,9 @@ dependencies = [
[[package]]
name = "spin"
-version = "0.9.8"
+version = "0.9.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67"
+checksum = "3763264f6b73151db08c50ff20d7d8a0b8796e021cdea7ceedad07b80155fa0e"
dependencies = [
"lock_api",
]
@@ -5974,7 +6689,7 @@ version = "0.3.0+sdk-1.3.268.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eda41003dc44290527a59b13432d4a0379379fa074b70174882adfbdfd917844"
dependencies = [
- "bitflags 2.12.1",
+ "bitflags 2.13.1",
]
[[package]]
@@ -6023,28 +6738,6 @@ version = "0.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
-[[package]]
-name = "strum"
-version = "0.26.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8fec0f0aef304996cf250b31b5a10dee7980c85da9d759361292b8bca5a18f06"
-dependencies = [
- "strum_macros",
-]
-
-[[package]]
-name = "strum_macros"
-version = "0.26.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4c6bee85a5a24955dc440386795aa378cd9cf82acd5f764469152d2270e581be"
-dependencies = [
- "heck",
- "proc-macro2",
- "quote",
- "rustversion",
- "syn",
-]
-
[[package]]
name = "subtle"
version = "2.6.1"
@@ -6059,20 +6752,31 @@ checksum = "0193cc4331cfd2f3d2011ef287590868599a2f33c3e69bc22c1a3d3acf9e02fb"
[[package]]
name = "swash"
-version = "0.2.7"
+version = "0.2.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6c2499c2d826531388872b2268718aed907a39bd785ab0dcfe57fab26283f92e"
+dependencies = [
+ "skrifa 0.44.0",
+ "yazi",
+ "zeno",
+]
+
+[[package]]
+name = "syn"
+version = "2.0.119"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "842f3cd369c2ba38966204f983eaa5e54a8e84a7d7159ed36ade2b6c335aae64"
+checksum = "872831b642d1a07999a962a351ed35b955ea2cfc8f3862091e2a240a84f17297"
dependencies = [
- "skrifa 0.40.0",
- "yazi",
- "zeno",
+ "proc-macro2",
+ "quote",
+ "unicode-ident",
]
[[package]]
name = "syn"
-version = "2.0.117"
+version = "3.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99"
+checksum = "53e9bae58849f64dfa4f5d5ae372c8341f7305f82a3868709269343628b659a3"
dependencies = [
"proc-macro2",
"quote",
@@ -6096,7 +6800,7 @@ checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2"
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.119",
]
[[package]]
@@ -6114,7 +6818,7 @@ version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a13f3d0daba03132c0aa9767f98351b3488edc2c100cda2d2ec2b04f3d8d3c8b"
dependencies = [
- "bitflags 2.12.1",
+ "bitflags 2.13.1",
"core-foundation 0.9.4",
"system-configuration-sys",
]
@@ -6165,7 +6869,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bd"
dependencies = [
"fastrand",
- "getrandom 0.4.2",
+ "getrandom 0.4.3",
"once_cell",
"rustix 1.1.4",
"windows-sys 0.61.2",
@@ -6191,11 +6895,11 @@ dependencies = [
[[package]]
name = "thiserror"
-version = "2.0.18"
+version = "2.0.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4288b5bcbc7920c07a1149a35cf9590a2aa808e0bc1eafaade0b80947865fbc4"
+checksum = "09a43598840e33d5b0331f38c5e30d13bb11c11210a4b58f0d9b18a5a5eefcd9"
dependencies = [
- "thiserror-impl 2.0.18",
+ "thiserror-impl 2.0.19",
]
[[package]]
@@ -6206,25 +6910,25 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1"
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.119",
]
[[package]]
name = "thiserror-impl"
-version = "2.0.18"
+version = "2.0.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5"
+checksum = "43cbfe0cf76104d42a574802844187e84a305e531ed54455f11fbde0f10541cd"
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 3.0.3",
]
[[package]]
name = "thread_local"
-version = "1.1.9"
+version = "1.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f60246a4944f24f6e018aa17cdeffb7818b76356965d03b07d6a9886e8962185"
+checksum = "1ad99c4c6d32803332c548b1af0540b357b3f5fc0be8f6c6bfe8b2e6ae784070"
dependencies = [
"cfg-if",
]
@@ -6245,12 +6949,11 @@ dependencies = [
[[package]]
name = "time"
-version = "0.3.47"
+version = "0.3.54"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "743bd48c283afc0388f9b8827b976905fb217ad9e647fae3a379a9283c4def2c"
+checksum = "3e1d5e639ff6bab73cb6885cc7e7b1de96c3f32c68ec55f3952614bec1092244"
dependencies = [
"deranged",
- "itoa",
"num-conv",
"powerfmt",
"serde_core",
@@ -6260,15 +6963,15 @@ dependencies = [
[[package]]
name = "time-core"
-version = "0.1.8"
+version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7694e1cfe791f8d31026952abf09c69ca6f6fa4e1a1229e18988f06a04a12dca"
+checksum = "9e1c906769ad99c88eaa54e728060edef082f8e358ff32030cb7c7d315e81109"
[[package]]
name = "time-macros"
-version = "0.2.27"
+version = "0.2.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2e70e4c5a0e0a8a4823ad65dfe1a6930e4f4d756dcd9dd7939022b5e8c501215"
+checksum = "7e689342a48d2ea927c87ea50cabf8594854bf940e9310208848d680d668ed85"
dependencies = [
"num-conv",
"time-core",
@@ -6299,15 +7002,6 @@ dependencies = [
"strict-num",
]
-[[package]]
-name = "tinystr"
-version = "0.7.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9117f5d4db391c1cf6927e7bea3db74b9a1c1add8f7eda9ffd5364f40f57b82f"
-dependencies = [
- "displaydoc",
-]
-
[[package]]
name = "tinystr"
version = "0.8.3"
@@ -6321,9 +7015,9 @@ dependencies = [
[[package]]
name = "tinyvec"
-version = "1.11.0"
+version = "1.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3e61e67053d25a4e82c844e8424039d9745781b3fc4f32b8d55ed50f5f667ef3"
+checksum = "bb4ebadaa0af04fab11ae01eb5f9fdb5f9c5b875506e210e71c07873528baa7f"
dependencies = [
"tinyvec_macros",
]
@@ -6353,7 +7047,7 @@ dependencies = [
"monostate",
"onig",
"paste",
- "rand 0.9.4",
+ "rand 0.9.5",
"rayon",
"rayon-cond",
"regex",
@@ -6361,7 +7055,7 @@ dependencies = [
"serde",
"serde_json",
"spm_precompiled",
- "thiserror 2.0.18",
+ "thiserror 2.0.19",
"unicode-normalization-alignments",
"unicode-segmentation",
"unicode_categories",
@@ -6369,30 +7063,30 @@ dependencies = [
[[package]]
name = "tokio"
-version = "1.52.3"
+version = "1.53.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8fc7f01b389ac15039e4dc9531aa973a135d7a4135281b12d7c1bc79fd57fffe"
+checksum = "202caea871b69668250d242070849eb495be178ed697a3e98aebce5bc81a0bed"
dependencies = [
"bytes",
"libc",
- "mio 1.2.1",
+ "mio 1.2.2",
"parking_lot 0.12.5",
"pin-project-lite",
"signal-hook-registry",
- "socket2 0.6.4",
+ "socket2 0.6.5",
"tokio-macros",
"windows-sys 0.61.2",
]
[[package]]
name = "tokio-macros"
-version = "2.7.0"
+version = "2.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "385a6cb71ab9ab790c5fe8d67f1645e6c450a7ce006a33de03daa956cf70a496"
+checksum = "6328af13490e73a9b4694030fafd93f8c8c6a9dede33e821c3fc63eddf8042ba"
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.119",
]
[[package]]
@@ -6417,14 +7111,15 @@ dependencies = [
[[package]]
name = "tokio-util"
-version = "0.7.18"
+version = "0.7.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9ae9cec805b01e8fc3fd2fe289f89149a9b66dd16786abd8b19cfa7b48cb0098"
+checksum = "494815d09bf52b5548659851081238f0ca39ff638363907596da739561c62c52"
dependencies = [
"bytes",
"futures-core",
"futures-io",
"futures-sink",
+ "libc",
"pin-project-lite",
"tokio",
]
@@ -6475,14 +7170,14 @@ dependencies = [
[[package]]
name = "toml_edit"
-version = "0.25.12+spec-1.1.0"
+version = "0.25.13+spec-1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d2153edc6955a6c354fad8f5efd38b6a8769bdccf9fe50f8e1329f81b0baa5d7"
+checksum = "6975367e4d2ef766d86af01ffad14b622fecc8d4357a998fbc4deb6e9bacaf9b"
dependencies = [
"indexmap",
"toml_datetime 1.1.1+spec-1.1.0",
"toml_parser",
- "winnow 1.0.3",
+ "winnow 1.0.4",
]
[[package]]
@@ -6491,7 +7186,7 @@ version = "1.1.2+spec-1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a2abe9b86193656635d2411dc43050282ca48aa31c2451210f4202550afb7526"
dependencies = [
- "winnow 1.0.3",
+ "winnow 1.0.4",
]
[[package]]
@@ -6521,7 +7216,7 @@ version = "0.6.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4cfcf7e2740e6fc6d4d688b4ef00650406bb94adf4731e43c096c3a19fe40840"
dependencies = [
- "bitflags 2.12.1",
+ "bitflags 2.13.1",
"bytes",
"futures-util",
"http",
@@ -6551,6 +7246,7 @@ version = "0.1.44"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "63e71662fa4b2a2c3a26f570f037eb95bb1f85397f3cd8076caed2f026a6d100"
dependencies = [
+ "log",
"pin-project-lite",
"tracing-attributes",
"tracing-core",
@@ -6564,7 +7260,7 @@ checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da"
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.119",
]
[[package]]
@@ -6606,6 +7302,17 @@ dependencies = [
"tracing-log",
]
+[[package]]
+name = "tree_magic_mini"
+version = "3.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b8765b90061cba6c22b5831f675da109ae5561588290f9fa2317adab2714d5a6"
+dependencies = [
+ "memchr",
+ "nom 8.0.0",
+ "petgraph",
+]
+
[[package]]
name = "try-lock"
version = "0.2.5"
@@ -6624,7 +7331,7 @@ version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cb30dbbd9036155e74adad6812e9898d03ec374946234fbcebd5dfc7b9187b90"
dependencies = [
- "rustc-hash 2.1.2",
+ "rustc-hash 2.1.3",
]
[[package]]
@@ -6633,6 +7340,17 @@ version = "1.20.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b6f5e870be6c3b371b77fe0ee0bafb859fa4964b4404c27de1d380043c4dda20"
+[[package]]
+name = "uds_windows"
+version = "1.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f2f6fb2847f6742cd76af783a2a2c49e9375d0a111c7bef6f71cd9e738c72d6e"
+dependencies = [
+ "memoffset",
+ "tempfile",
+ "windows-sys 0.61.2",
+]
+
[[package]]
name = "uint"
version = "0.10.0"
@@ -6651,7 +7369,7 @@ version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "470dbf6591da1b39d43c14523b2b469c86879a53e8b758c8e090a470fe7b1fbe"
dependencies = [
- "rand 0.9.4",
+ "rand 0.9.5",
"serde",
"web-time",
]
@@ -6672,7 +7390,7 @@ version = "0.9.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dce1bf08044d4b7a94028c93786f8566047edc11110595914de93362559bc658"
dependencies = [
- "tinystr 0.8.3",
+ "tinystr",
]
[[package]]
@@ -6682,7 +7400,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d5957eb82e346d7add14182a3315a7e298f04e1ba4baac36f7f0dbfedba5fc25"
dependencies = [
"proc-macro-hack",
- "tinystr 0.8.3",
+ "tinystr",
"unic-langid-impl",
"unic-langid-macros-impl",
]
@@ -6695,7 +7413,7 @@ checksum = "a1249a628de3ad34b821ecb1001355bca3940bcb2f88558f1a8bd82e977f75b5"
dependencies = [
"proc-macro-hack",
"quote",
- "syn",
+ "syn 2.0.119",
"unic-langid-impl",
]
@@ -6720,12 +7438,6 @@ version = "1.13.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c6f5d3c3b1bf09027a88a6bc961fc00497d651009560b5463668dc81b0fa87a8"
-[[package]]
-name = "unicode-width"
-version = "0.1.14"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af"
-
[[package]]
name = "unicode-width"
version = "0.2.2"
@@ -6812,12 +7524,13 @@ checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be"
[[package]]
name = "uuid"
-version = "1.23.2"
+version = "1.24.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d258b83ceec21034727ecee8c382cfa6c3e133699b0742c64571814fb420c9f7"
+checksum = "bf3923a6f5c4c6382e0b653c4117f48d631ea17f38ed86e2a828e6f7412f5239"
dependencies = [
- "getrandom 0.4.2",
+ "getrandom 0.4.3",
"js-sys",
+ "serde_core",
"wasm-bindgen",
]
@@ -6846,18 +7559,18 @@ checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426"
[[package]]
name = "vello"
-version = "0.5.1"
+version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fa3f8a53870a2ee699ce05b738a3f9974c92c35ed4874de86052ac68d214811c"
+checksum = "72fef40773530322d5c2ffe3c1107e9874bd8239ac137d1c2b6c1edad695146e"
dependencies = [
"bytemuck",
"futures-intrusive",
"log",
"peniko",
"png 0.17.16",
- "skrifa 0.35.0",
+ "skrifa 0.40.0",
"static_assertions",
- "thiserror 2.0.18",
+ "thiserror 2.0.19",
"vello_encoding",
"vello_shaders",
"wgpu",
@@ -6865,26 +7578,27 @@ dependencies = [
[[package]]
name = "vello_encoding"
-version = "0.5.1"
+version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c69b0fe94b0ac7e47619c504ee2c377355174f5c46353c46d03fa5f7e435922b"
+checksum = "24c91203ec4b483440614a9a5c7c2d991932af72c5349659a63ec49476f0b79c"
dependencies = [
"bytemuck",
"guillotiere",
"peniko",
- "skrifa 0.35.0",
+ "skrifa 0.40.0",
"smallvec",
]
[[package]]
name = "vello_shaders"
-version = "0.5.1"
+version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b2ebea426bb2f95b7610bca09178b03d809ede1d3c500a9acf6eca43e8f200be"
+checksum = "7a765d44d4bd354146e44f9a860f4e92effd91a97302549be9e47f0a18d8128c"
dependencies = [
"bytemuck",
+ "log",
"naga",
- "thiserror 2.0.18",
+ "thiserror 2.0.19",
"vello_encoding",
]
@@ -6921,27 +7635,18 @@ checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b"
[[package]]
name = "wasip2"
-version = "1.0.3+wasi-0.2.9"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "20064672db26d7cdc89c7798c48a0fdfac8213434a1186e5ef29fd560ae223d6"
-dependencies = [
- "wit-bindgen 0.57.1",
-]
-
-[[package]]
-name = "wasip3"
-version = "0.4.0+wasi-0.3.0-rc-2026-01-06"
+version = "1.0.4+wasi-0.2.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5428f8bf88ea5ddc08faddef2ac4a67e390b88186c703ce6dbd955e1c145aca5"
+checksum = "b67efb37e106e55ce722a510d6b5f9c17f083e5fc79afc2badeb12cc313d9487"
dependencies = [
- "wit-bindgen 0.51.0",
+ "wit-bindgen",
]
[[package]]
name = "wasm-bindgen"
-version = "0.2.122"
+version = "0.2.126"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3ed04576f974d2b2fba0f38c51dbc5518011e38c36bf1143164be765528fd409"
+checksum = "4b067c0c11094aef6b7a801c1e34a26affafdf3d051dba08456b868789aaf9a4"
dependencies = [
"cfg-if",
"once_cell",
@@ -6952,9 +7657,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-futures"
-version = "0.4.72"
+version = "0.4.76"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9473dbd2991ae90b6291c3c32c30c6187ac49aa32f9905d1cce280ec1e110b0f"
+checksum = "c62df1340f32221cb9c54d6a27b030e3dba64361d4a95bed55f9aacb44da291d"
dependencies = [
"js-sys",
"wasm-bindgen",
@@ -6962,9 +7667,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-macro"
-version = "0.2.122"
+version = "0.2.126"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "916151b09da36bd82f6615cbf3a419e2f0ba23a03c6160e8e92eb6bd4aa1dec6"
+checksum = "167ce5e579f6bcf889c4f7175a8a5a585de84e8ff93976ce393efa5f2837aab1"
dependencies = [
"quote",
"wasm-bindgen-macro-support",
@@ -6972,48 +7677,26 @@ dependencies = [
[[package]]
name = "wasm-bindgen-macro-support"
-version = "0.2.122"
+version = "0.2.126"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "299047362ccbfce148b67ab7e73349f77748e00c8296f9542adfad2ad82c5c5e"
+checksum = "f3997c7839262f4ef12cf90b818d6340c18e80f263f1a94bf157d0ec4420380e"
dependencies = [
"bumpalo",
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.119",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-shared"
-version = "0.2.122"
+version = "0.2.126"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9a929b2c61f11ba3e9bc35b50c1f25cb38e0e892c0c231ae2b8cf78d5dad4437"
+checksum = "dc1b4cb0cc549fcf58d7dfc081778139b3d283a081644e833e84682ad71cea24"
dependencies = [
"unicode-ident",
]
-[[package]]
-name = "wasm-encoder"
-version = "0.244.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "990065f2fe63003fe337b932cfb5e3b80e0b4d0f5ff650e6985b1048f62c8319"
-dependencies = [
- "leb128fmt",
- "wasmparser 0.244.0",
-]
-
-[[package]]
-name = "wasm-metadata"
-version = "0.244.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bb0e353e6a2fbdc176932bbaab493762eb1255a7900fe0fea1a2f96c296cc909"
-dependencies = [
- "anyhow",
- "indexmap",
- "wasm-encoder",
- "wasmparser 0.244.0",
-]
-
[[package]]
name = "wasm-streams"
version = "0.4.2"
@@ -7033,19 +7716,7 @@ version = "0.230.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "808198a69b5a0535583370a51d459baa14261dfab04800c4864ee9e1a14346ed"
dependencies = [
- "bitflags 2.12.1",
- "indexmap",
- "semver",
-]
-
-[[package]]
-name = "wasmparser"
-version = "0.244.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "47b807c72e1bac69382b3a6fb3dbe8ea4c0ed87ff5629b8685ae6b9a611028fe"
-dependencies = [
- "bitflags 2.12.1",
- "hashbrown 0.15.5",
+ "bitflags 2.13.1",
"indexmap",
"semver",
]
@@ -7053,21 +7724,21 @@ dependencies = [
[[package]]
name = "wawa-config"
version = "0.1.0"
-source = "git+https://gitea.tawasuyu.net/sergio/gioser.git?tag=v0.1.0#692b40336c1e9cb12ab561764d6943cb65905ab3"
+source = "git+https://git.tawasuyu.net/tawasuyu/tawasuyu.git?tag=v0.2.0#a446bb3a73a0e022158cc0ec7deb65173859644b"
dependencies = [
"directories",
"notify",
"serde",
"serde_json",
- "thiserror 2.0.18",
+ "thiserror 2.0.19",
"tracing",
]
[[package]]
name = "wayland-backend"
-version = "0.3.15"
+version = "0.3.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2857dd20b54e916ec7253b3d6b4d5c4d7d4ca2c33c2e11c6c76a99bd8744755d"
+checksum = "016ccf01d1c58b6f8999612813e17c9b2390f7d70671428869913310f83f54b8"
dependencies = [
"cc",
"downcast-rs",
@@ -7079,11 +7750,11 @@ dependencies = [
[[package]]
name = "wayland-client"
-version = "0.31.14"
+version = "0.31.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "645c7c96bb74690c3189b5c9cb4ca1627062bb23693a4fad9d8c3de958260144"
+checksum = "e3c36a0f861ad76d0901f2800b46321410d9f73f2ea88aac0650d86c32688073"
dependencies = [
- "bitflags 2.12.1",
+ "bitflags 2.13.1",
"rustix 1.1.4",
"wayland-backend",
"wayland-scanner",
@@ -7095,7 +7766,7 @@ version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "625c5029dbd43d25e6aa9615e88b829a5cad13b2819c4ae129fdbb7c31ab4c7e"
dependencies = [
- "bitflags 2.12.1",
+ "bitflags 2.13.1",
"cursor-icon",
"wayland-backend",
]
@@ -7113,11 +7784,11 @@ dependencies = [
[[package]]
name = "wayland-protocols"
-version = "0.32.12"
+version = "0.32.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "563a85523cade2429938e790815fd7319062103b9f4a2dc806e9b53b95982d8f"
+checksum = "23d0c813de3daa2ed6520af85a3bd49b0e722a3078506899aa9686fea58dc4b6"
dependencies = [
- "bitflags 2.12.1",
+ "bitflags 2.13.1",
"wayland-backend",
"wayland-client",
"wayland-scanner",
@@ -7129,7 +7800,7 @@ version = "0.3.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2b6d8cf1eb2c1c31ed1f5643c88a6e53538129d4af80030c8cabd1f9fa884d91"
dependencies = [
- "bitflags 2.12.1",
+ "bitflags 2.13.1",
"wayland-backend",
"wayland-client",
"wayland-protocols",
@@ -7142,7 +7813,7 @@ version = "0.3.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eb04e52f7836d7c7976c78ca0250d61e33873c34156a2a1fc9474828ec268234"
dependencies = [
- "bitflags 2.12.1",
+ "bitflags 2.13.1",
"wayland-backend",
"wayland-client",
"wayland-protocols",
@@ -7151,9 +7822,9 @@ dependencies = [
[[package]]
name = "wayland-scanner"
-version = "0.31.10"
+version = "0.31.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9c324a910fd86ebdc364a3e61ec1f11737d3b1d6c273c0239ee8ff4bc0d24b4a"
+checksum = "338e30461b3a2b67d70eb30a6d89f8e0c93a833e07d2ae89085cd070c4a00ac0"
dependencies = [
"proc-macro2",
"quick-xml",
@@ -7174,9 +7845,9 @@ dependencies = [
[[package]]
name = "web-sys"
-version = "0.3.99"
+version = "0.3.103"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6d621441cfc37b84979402712047321980c178f299193a3589d05b99e8763436"
+checksum = "8622dcb61c0bcc9fffa6938bed81210af2da9a7e4a1a834b2e37a59b6dfb6141"
dependencies = [
"js-sys",
"wasm-bindgen",
@@ -7198,14 +7869,14 @@ version = "0.26.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "521bc38abb08001b01866da9f51eb7c5d647a19260e00054a8c7fd5f9e57f7a9"
dependencies = [
- "webpki-roots 1.0.7",
+ "webpki-roots 1.0.9",
]
[[package]]
name = "webpki-roots"
-version = "1.0.7"
+version = "1.0.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "52f5ee44c96cf55f1b349600768e3ece3a8f26010c05265ab73f945bb1a2eb9d"
+checksum = "7dcd9d09a39985f5344844e66b0c530a33843579125f23e21e9f0f220850f22a"
dependencies = [
"rustls-pki-types",
]
@@ -7218,18 +7889,21 @@ checksum = "a28ac98ddc8b9274cb41bb4d9d4d5c425b6020c50c46f25559911905610b4a88"
[[package]]
name = "wgpu"
-version = "24.0.5"
+version = "27.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6b0b3436f0729f6cdf2e6e9201f3d39dc95813fad61d826c1ed07918b4539353"
+checksum = "bfe68bac7cde125de7a731c3400723cadaaf1703795ad3f4805f187459cd7a77"
dependencies = [
"arrayvec",
- "bitflags 2.12.1",
+ "bitflags 2.13.1",
+ "cfg-if",
"cfg_aliases",
"document-features",
+ "hashbrown 0.16.1",
"js-sys",
"log",
"naga",
"parking_lot 0.12.5",
+ "portable-atomic",
"profiling",
"raw-window-handle",
"smallvec",
@@ -7244,49 +7918,85 @@ dependencies = [
[[package]]
name = "wgpu-core"
-version = "24.0.5"
+version = "27.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7f0aa306497a238d169b9dc70659105b4a096859a34894544ca81719242e1499"
+checksum = "27a75de515543b1897b26119f93731b385a19aea165a1ec5f0e3acecc229cae7"
dependencies = [
"arrayvec",
+ "bit-set",
"bit-vec",
- "bitflags 2.12.1",
+ "bitflags 2.13.1",
+ "bytemuck",
"cfg_aliases",
"document-features",
+ "hashbrown 0.16.1",
"indexmap",
"log",
"naga",
"once_cell",
"parking_lot 0.12.5",
+ "portable-atomic",
"profiling",
"raw-window-handle",
"rustc-hash 1.1.0",
"smallvec",
- "thiserror 2.0.18",
+ "thiserror 2.0.19",
+ "wgpu-core-deps-apple",
+ "wgpu-core-deps-emscripten",
+ "wgpu-core-deps-windows-linux-android",
"wgpu-hal",
"wgpu-types",
]
+[[package]]
+name = "wgpu-core-deps-apple"
+version = "27.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0772ae958e9be0c729561d5e3fd9a19679bcdfb945b8b1a1969d9bfe8056d233"
+dependencies = [
+ "wgpu-hal",
+]
+
+[[package]]
+name = "wgpu-core-deps-emscripten"
+version = "27.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b06ac3444a95b0813ecfd81ddb2774b66220b264b3e2031152a4a29fda4da6b5"
+dependencies = [
+ "wgpu-hal",
+]
+
+[[package]]
+name = "wgpu-core-deps-windows-linux-android"
+version = "27.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "71197027d61a71748e4120f05a9242b2ad142e3c01f8c1b47707945a879a03c3"
+dependencies = [
+ "wgpu-hal",
+]
+
[[package]]
name = "wgpu-hal"
-version = "24.0.4"
+version = "27.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f112f464674ca69f3533248508ee30cb84c67cf06c25ff6800685f5e0294e259"
+checksum = "5b21cb61c57ee198bc4aff71aeadff4cbb80b927beb912506af9c780d64313ce"
dependencies = [
"android_system_properties",
"arrayvec",
"ash",
"bit-set",
- "bitflags 2.12.1",
+ "bitflags 2.13.1",
"block",
"bytemuck",
+ "cfg-if",
"cfg_aliases",
- "core-graphics-types",
+ "core-graphics-types 0.2.0",
"glow",
"glutin_wgl_sys",
"gpu-alloc",
"gpu-allocator",
"gpu-descriptor",
+ "hashbrown 0.16.1",
"js-sys",
"khronos-egl",
"libc",
@@ -7294,18 +8004,19 @@ dependencies = [
"log",
"metal",
"naga",
- "ndk-sys 0.5.0+25.2.9519653",
+ "ndk-sys",
"objc",
"once_cell",
"ordered-float",
"parking_lot 0.12.5",
+ "portable-atomic",
+ "portable-atomic-util",
"profiling",
"range-alloc",
"raw-window-handle",
"renderdoc-sys",
- "rustc-hash 1.1.0",
"smallvec",
- "thiserror 2.0.18",
+ "thiserror 2.0.19",
"wasm-bindgen",
"web-sys",
"wgpu-types",
@@ -7315,13 +8026,15 @@ dependencies = [
[[package]]
name = "wgpu-types"
-version = "24.0.0"
+version = "27.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "50ac044c0e76c03a0378e7786ac505d010a873665e2d51383dcff8dd227dc69c"
+checksum = "afdcf84c395990db737f2dd91628706cb31e86d72e53482320d368e52b5da5eb"
dependencies = [
- "bitflags 2.12.1",
+ "bitflags 2.13.1",
+ "bytemuck",
"js-sys",
"log",
+ "thiserror 2.0.19",
"web-sys",
]
@@ -7438,7 +8151,7 @@ checksum = "2bbd5b46c938e506ecbce286b6628a02171d56153ba733b6c741fc627ec9579b"
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.119",
]
[[package]]
@@ -7449,7 +8162,7 @@ checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf"
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.119",
]
[[package]]
@@ -7460,7 +8173,7 @@ checksum = "053c4c462dc91d3b1504c6fe5a726dd15e216ba718e84a0e46a88fbe5ded3515"
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.119",
]
[[package]]
@@ -7471,7 +8184,7 @@ checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358"
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.119",
]
[[package]]
@@ -7787,7 +8500,7 @@ dependencies = [
"ahash",
"android-activity",
"atomic-waker",
- "bitflags 2.12.1",
+ "bitflags 2.13.1",
"block2",
"bytemuck",
"calloop",
@@ -7802,7 +8515,7 @@ dependencies = [
"memmap2",
"ndk",
"objc2 0.5.2",
- "objc2-app-kit",
+ "objc2-app-kit 0.2.2",
"objc2-foundation 0.2.2",
"objc2-ui-kit",
"orbclient",
@@ -7841,89 +8554,19 @@ dependencies = [
[[package]]
name = "winnow"
-version = "1.0.3"
+version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0592e1c9d151f854e6fd382574c3a0855250e1d9b2f99d9281c6e6391af352f1"
+checksum = "23b97319f7b8343df12cc98938e5c3eb436064524c8d2b4e30a1d3a36eecdf81"
dependencies = [
"memchr",
]
-[[package]]
-name = "wit-bindgen"
-version = "0.51.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d7249219f66ced02969388cf2bb044a09756a083d0fab1e566056b04d9fbcaa5"
-dependencies = [
- "wit-bindgen-rust-macro",
-]
-
[[package]]
name = "wit-bindgen"
version = "0.57.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1ebf944e87a7c253233ad6766e082e3cd714b5d03812acc24c318f549614536e"
-[[package]]
-name = "wit-bindgen-core"
-version = "0.51.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ea61de684c3ea68cb082b7a88508a8b27fcc8b797d738bfc99a82facf1d752dc"
-dependencies = [
- "anyhow",
- "heck",
- "wit-parser 0.244.0",
-]
-
-[[package]]
-name = "wit-bindgen-rust"
-version = "0.51.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b7c566e0f4b284dd6561c786d9cb0142da491f46a9fbed79ea69cdad5db17f21"
-dependencies = [
- "anyhow",
- "heck",
- "indexmap",
- "prettyplease",
- "syn",
- "wasm-metadata",
- "wit-bindgen-core",
- "wit-component",
-]
-
-[[package]]
-name = "wit-bindgen-rust-macro"
-version = "0.51.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0c0f9bfd77e6a48eccf51359e3ae77140a7f50b1e2ebfe62422d8afdaffab17a"
-dependencies = [
- "anyhow",
- "prettyplease",
- "proc-macro2",
- "quote",
- "syn",
- "wit-bindgen-core",
- "wit-bindgen-rust",
-]
-
-[[package]]
-name = "wit-component"
-version = "0.244.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9d66ea20e9553b30172b5e831994e35fbde2d165325bec84fc43dbf6f4eb9cb2"
-dependencies = [
- "anyhow",
- "bitflags 2.12.1",
- "indexmap",
- "log",
- "serde",
- "serde_derive",
- "serde_json",
- "wasm-encoder",
- "wasm-metadata",
- "wasmparser 0.244.0",
- "wit-parser 0.244.0",
-]
-
[[package]]
name = "wit-parser"
version = "0.230.0"
@@ -7939,33 +8582,27 @@ dependencies = [
"serde_derive",
"serde_json",
"unicode-xid",
- "wasmparser 0.230.0",
+ "wasmparser",
]
[[package]]
-name = "wit-parser"
-version = "0.244.0"
+name = "wl-clipboard-rs"
+version = "0.9.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ecc8ac4bc1dc3381b7f59c34f00b67e18f910c2c0f50015669dde7def656a736"
+checksum = "e9651471a32e87d96ef3a127715382b2d11cc7c8bb9822ded8a7cc94072eb0a3"
dependencies = [
- "anyhow",
- "id-arena",
- "indexmap",
+ "libc",
"log",
- "semver",
- "serde",
- "serde_derive",
- "serde_json",
- "unicode-xid",
- "wasmparser 0.244.0",
+ "os_pipe",
+ "rustix 1.1.4",
+ "thiserror 2.0.19",
+ "tree_magic_mini",
+ "wayland-backend",
+ "wayland-client",
+ "wayland-protocols",
+ "wayland-protocols-wlr",
]
-[[package]]
-name = "writeable"
-version = "0.5.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51"
-
[[package]]
name = "writeable"
version = "0.6.3"
@@ -8029,7 +8666,7 @@ dependencies = [
"nom 7.1.3",
"oid-registry",
"rusticata-macros",
- "thiserror 2.0.18",
+ "thiserror 2.0.19",
"time",
]
@@ -8055,7 +8692,7 @@ version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d039de8032a9a8856a6be89cea3e5d12fdd82306ab7c94d74e6deab2460651c5"
dependencies = [
- "bitflags 2.12.1",
+ "bitflags 2.13.1",
"dlib",
"log",
"once_cell",
@@ -8100,7 +8737,7 @@ dependencies = [
"nohash-hasher",
"parking_lot 0.12.5",
"pin-project",
- "rand 0.8.6",
+ "rand 0.8.7",
"static_assertions",
]
@@ -8115,7 +8752,7 @@ dependencies = [
"nohash-hasher",
"parking_lot 0.12.5",
"pin-project",
- "rand 0.9.4",
+ "rand 0.9.5",
"static_assertions",
"web-time",
]
@@ -8135,6 +8772,17 @@ version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e01738255b5a16e78bbb83e7fbba0a1e7dd506905cfc53f4622d89015a03fbb5"
+[[package]]
+name = "yeslogic-fontconfig-sys"
+version = "6.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1d8b8abf912b9a29ff112e1671c97c33636903d13a69712037190e6805af4f76"
+dependencies = [
+ "dlib",
+ "once_cell",
+ "pkg-config",
+]
+
[[package]]
name = "yoke"
version = "0.8.3"
@@ -8154,10 +8802,107 @@ checksum = "de844c262c8848816172cef550288e7dc6c7b7814b4ee56b3e1553f275f1858e"
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.119",
"synstructure",
]
+[[package]]
+name = "zbus"
+version = "5.18.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fe18fb60dc696039e738717b76eaea21e7a4489bbb1885020b43c94236d7e98a"
+dependencies = [
+ "async-broadcast",
+ "async-executor",
+ "async-io",
+ "async-lock",
+ "async-process",
+ "async-recursion",
+ "async-task",
+ "async-trait",
+ "blocking",
+ "enumflags2",
+ "event-listener",
+ "futures-core",
+ "futures-lite",
+ "hex",
+ "libc",
+ "ordered-stream",
+ "rustix 1.1.4",
+ "serde",
+ "serde_repr",
+ "tracing",
+ "uds_windows",
+ "uuid",
+ "windows-sys 0.61.2",
+ "winnow 1.0.4",
+ "zbus_macros",
+ "zbus_names",
+ "zvariant",
+]
+
+[[package]]
+name = "zbus-lockstep"
+version = "0.5.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6998de05217a084b7578728a9443d04ea4cd80f2a0839b8d78770b76ccd45863"
+dependencies = [
+ "zbus_xml",
+ "zvariant",
+]
+
+[[package]]
+name = "zbus-lockstep-macros"
+version = "0.5.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "10da05367f3a7b7553c8cdf8fa91aee6b64afebe32b51c95177957efc47ca3a0"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.119",
+ "zbus-lockstep",
+ "zbus_xml",
+ "zvariant",
+]
+
+[[package]]
+name = "zbus_macros"
+version = "5.18.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fe96480bed92df2b442a1a30df364e12d08eed03aeb061f2b8dc6afb2be91119"
+dependencies = [
+ "proc-macro-crate",
+ "proc-macro2",
+ "quote",
+ "syn 2.0.119",
+ "zbus_names",
+ "zvariant",
+ "zvariant_utils",
+]
+
+[[package]]
+name = "zbus_names"
+version = "4.3.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d8bf88b4a3ff53e883001e0e0115b297a9d53c31b9c1edd2bfdd853e3428624e"
+dependencies = [
+ "serde",
+ "winnow 1.0.4",
+ "zvariant",
+]
+
+[[package]]
+name = "zbus_xml"
+version = "5.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d1586c021a01ca0a9216dcd874e546382e156a5cbab5fab6cb5f10087e22682a"
+dependencies = [
+ "serde",
+ "winnow 1.0.4",
+ "zbus_names",
+ "zvariant",
+]
+
[[package]]
name = "zeno"
version = "0.3.3"
@@ -8166,22 +8911,22 @@ checksum = "6df3dc4292935e51816d896edcd52aa30bc297907c26167fec31e2b0c6a32524"
[[package]]
name = "zerocopy"
-version = "0.8.50"
+version = "0.8.55"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3b065d4f0e55f82fae73202e189638116a87c55ab6b8e6c2721e13dd9d854ad1"
+checksum = "b5a105cd7b140f6eeec8acff2ea38135d3cab283ada58540f629fe51e46696eb"
dependencies = [
"zerocopy-derive",
]
[[package]]
name = "zerocopy-derive"
-version = "0.8.50"
+version = "0.8.55"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0b631b19d36a892ab55420c92dbc83ccd79274f25be714855d3074aa71cab639"
+checksum = "0fe976fb70c78cd64cccfe3a6fc142244e8a77b70959b30faf9d0ac37ee228eb"
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.119",
]
[[package]]
@@ -8201,28 +8946,28 @@ checksum = "11532158c46691caf0f2593ea8358fed6bbf68a0315e80aae9bd41fbade684a1"
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.119",
"synstructure",
]
[[package]]
name = "zeroize"
-version = "1.8.2"
+version = "1.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b97154e67e32c85465826e8bcc1c59429aaaf107c1e4a9e53c8d8ccd5eff88d0"
+checksum = "e13c156562582aa81c60cb29407084cdb54c4164760106ab78e6c5b0858cf64e"
dependencies = [
"zeroize_derive",
]
[[package]]
name = "zeroize_derive"
-version = "1.4.3"
+version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "85a5b4158499876c763cb03bc4e49185d3cccbabb15b33c627f7884f43db852e"
+checksum = "3c50655cbb0fe3fc43170059e702f1ce5e19b84cec58dc87b037a09935c2f328"
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.119",
]
[[package]]
@@ -8256,14 +9001,14 @@ checksum = "625dc425cab0dca6dc3c3319506e6593dcb08a9f387ea3b284dbd52a92c40555"
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.119",
]
[[package]]
name = "zmij"
-version = "1.0.21"
+version = "1.0.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa"
+checksum = "29666d0abbfad1e3dc4dcf6144730dd3a3ab225bbbdac83319345b1b44ccfc1b"
[[package]]
name = "zune-core"
@@ -8288,3 +9033,43 @@ checksum = "27bc9d5b815bc103f142aa054f561d9187d191692ec7c2d1e2b4737f8dbd7296"
dependencies = [
"zune-core",
]
+
+[[package]]
+name = "zvariant"
+version = "5.13.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bee2a0bcd2a907786a456fff45aaaaf54c9ba5f50b71ae9ec1a4edd200c94911"
+dependencies = [
+ "endi",
+ "enumflags2",
+ "serde",
+ "winnow 1.0.4",
+ "zvariant_derive",
+ "zvariant_utils",
+]
+
+[[package]]
+name = "zvariant_derive"
+version = "5.13.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "38a708216a18780796770bfe3f4739c7c83a3e8f789b755534bbbc06e4e23e12"
+dependencies = [
+ "proc-macro-crate",
+ "proc-macro2",
+ "quote",
+ "syn 2.0.119",
+ "zvariant_utils",
+]
+
+[[package]]
+name = "zvariant_utils"
+version = "3.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "90cb9383f9b45290407a1258b202d3f8f01db719eb60b4e4055c6375af4fc7c7"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "serde",
+ "syn 2.0.119",
+ "winnow 1.0.4",
+]
diff --git a/Cargo.toml b/Cargo.toml
index fbef7f2..60acebf 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,7 +1,13 @@
-# Cargo.toml raíz STANDALONE de chasqui — front-door sobre Llimphi.
-# Solo el código de chasqui; Llimphi y lo fundacional por git-dep del monorepo gioser.git.
+# Cargo.toml raíz STANDALONE de chasqui — front-door público.
+# GENERADO por scripts/actualizar-standalone.py desde el monorepo tawasuyu.git
+# (v0.2.0). No editar a mano: se regenera. Lo fundacional se consume por
+# git-dep al tag; sólo el código del dominio vive en este repo.
[workspace]
resolver = "2"
+
+# ============================================================
+# Cuadrantes — agregar a medida que se migran
+# ============================================================
members = [
"02_ruway/chasqui/card-admin",
"02_ruway/chasqui/card-handshake",
@@ -16,6 +22,11 @@ members = [
"02_ruway/chasqui/chasqui-nous-real",
]
+# `wawa/` se excluye del workspace global porque corre en target
+# `x86_64-unknown-none` y `panic = "abort"`, incompatibles con los
+# perfiles globales. Los crates compartidos se referencian por `path`
+# cruzando la frontera.
+
[workspace.package]
version = "0.1.0"
edition = "2021"
@@ -26,9 +37,32 @@ publish = false
repository = "https://git.tawasuyu.net/tawasuyu/chasqui"
[workspace.dependencies]
-
+# === Configuración declarativa (vocabulario de esquemas) ===
+allichay = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+marca = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+# Telemetría local de desarrollo (stderr+panics+tracing → $XDG_STATE_HOME/tawasuyu/<dominio>/<bin>.log)
+bitacora = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+# default = [] (núcleo liviano sin vello); `bake` es opt-in. Declaramos
+# default-features = false aquí para que el `default-features = false` de los
+# consumidores (splash/greeter/compositor) se honre y no quede el warning.
+mirada-fondo = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+mirada-teclado-core = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+mirada-teclado-widget = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
# === Registro de apps / menú global ===
-app-bus = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.1.0" }
+app-bus = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+app-iconset = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+# === Centro de eventos (notificaciones + capturas + clipboard + …) ===
+willay-core = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+willay-checkpoint = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+willay-hilo = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+willay-store = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+willay-emit = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+rag-motor = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+churay-core = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+churay-welcome = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+churay-welcome-runner = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+# === Puente de drag-and-drop compositor → app (suple winit en Wayland) ===
+drop-bridge = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
# === Serialización ===
serde = { version = "1", features = ["derive"] }
serde_json = "1"
@@ -55,8 +89,12 @@ tracing = "0.1"
tracing-subscriber = { version = "0.3", features = ["env-filter", "fmt"] }
# === Linux primitives (arje) ===
-nix = { version = "0.29", features = ["signal", "process", "sched", "mount", "fs", "socket", "net", "user"] }
+nix = { version = "0.29", features = ["signal", "process", "sched", "mount", "fs", "socket", "net", "user", "reboot"] }
libc = "0.2"
+# DRM/KMS legacy (dumb buffer) para el splash nativo del arranque sin parpadeo.
+# Misma versión que reexporta smithay (mirada-compositor) — el lock ya la fija.
+drm = "0.14"
+font8x8 = { version = "0.3", default-features = false }
# === IDs / Hash / Crypto ===
ulid = { version = "1", features = ["serde"] }
@@ -70,10 +108,15 @@ argon2 = "0.5"
rand = "0.8"
# === WASM (arje) ===
-# wasmi 1.0: unifica la versión con renaser (su kernel ya corre 1.0), para
+# wasmi 1.0: unifica la versión con wawa (su kernel ya corre 1.0), para
# que el ABI WASM del host sea idéntico en Linux y en bare-metal.
wasmi = "1.0"
wat = "1"
+# wasmtime 46 (Fase 1 del pipeline JS): tier 0 de puriy-js pasa de wasmi
+# (intérprete) a Wasmtime AOT (Cranelift → nativo) en Linux — quita la doble
+# interpretación de QuickJS.wasm. En wawa bare-metal el runtime es Pulley (spike
+# Q1 cerrado); mismo crate, distinto backend.
+wasmtime = "46"
# === Storage / DB ===
sled = "0.34"
@@ -88,6 +131,10 @@ bzip2 = "0.4"
# === Compresión (minga multi-bundle) ===
zstd = "0.13"
+xz2 = "0.1"
+# Contenedores adicionales del visor Archive de nahual (sólo listado).
+sevenz-rust = "0.6"
+unrar = "0.5"
# === HTTP server (iniy-server) ===
axum = "0.7"
@@ -97,7 +144,7 @@ tower = "0.5"
instant-distance = "0.6"
# === P2P (minga) ===
-libp2p = { version = "0.56", features = ["tokio", "tcp", "noise", "yamux", "macros", "kad", "identify", "relay", "dcutr", "autonat", "mdns"] }
+libp2p = { version = "0.56", features = ["tokio", "tcp", "dns", "noise", "yamux", "macros", "kad", "identify", "relay", "dcutr", "autonat", "mdns"] }
libp2p-stream = "=0.4.0-alpha"
libp2p-allow-block-list = "0.6"
@@ -112,7 +159,11 @@ libm = "0.2"
midly = "0.5"
# === Code parsing (minga) ===
-arboard = "3"
+# `wayland-data-control` trae el backend wl-clipboard-rs: bajo mirada (Wayland
+# propio, sin Xwayland para apps nativas) arboard-x11 fallaba a no-op silencioso
+# y el clipboard de los text-editor quedaba muerto. Con la feature habla
+# zwlr_data_control_manager_v1 (que mirada expone) y cae a X11 si no hay Wayland.
+arboard = { version = "3", features = ["wayland-data-control"] }
ropey = "1.6"
tree-sitter = "0.24"
tree-sitter-rust = "0.23"
@@ -131,7 +182,19 @@ petgraph = "0.6"
# default-features = false: nos quedamos con PNG + JPEG + WebP (lossless).
# tullpu-render exporta a las tres; AVIF/TIFF/… los habilitamos si una app
# los pide específicamente.
-image = { version = "0.25", default-features = false, features = ["png", "jpeg", "webp"] }
+# Decoders puro-Rust baratos; avif queda fuera (arrastra dav1d/rav1e).
+image = { version = "0.25", default-features = false, features = ["png", "jpeg", "webp", "gif", "bmp", "ico", "tiff", "tga", "qoi"] }
+# ONNX Runtime para los proveedores de píxel reales (pixel-verbo-onnx: segmentación
+# u2net/isnet, inpaint, restyle…). `download-binaries` (default) baja el runtime nativo
+# solo; ya lo arrastraba fastembed (rimay-verbo) transitivo — aquí lo declaramos directo.
+ort = "2.0.0-rc.9"
+
+# Rasterizador vectorial CPU (relleno/trazo anti-aliased) para capas vectoriales de tullpu.
+tiny-skia = "0.11"
+# Booleanos de polígonos robustos (union/intersection/difference/xor) para el
+# clipper vectorial de tullpu — restar/intersecar paths que se solapan
+# parcialmente, que la regla de relleno no expresa. Ya estaba en el lock.
+geo = "0.28"
# === FUSE (minga-vfs) ===
# default-features = false: prescinde de pkg-config/libfuse-dev en build.
@@ -153,91 +216,164 @@ tempfile = "3"
# === Llimphi (motor gráfico soberano) ===
# wgpu sobre Vulkan/Metal/DX12, winit para ventana en dev Linux.
-# raw-window-handle 0.6 alinea winit 0.30 con wgpu 24.
-# vello 0.5 = rasterizador vectorial sobre wgpu 24.
+# raw-window-handle 0.6 alinea winit 0.30 con wgpu 27.
+# vello 0.7 = rasterizador vectorial sobre wgpu 27 (renderer GPU "wgpu" + opt-in "hybrid" CPU+GPU).
# taffy 0.9 = motor Flexbox/Grid puro Rust (ya pulled por transitivos, lo alineamos).
-# parley 0.2 = shaping/layout de texto compatible con peniko 0.4 (que vello 0.5 expone).
-wgpu = "24"
+# parley 0.6 = shaping/layout de texto compatible con peniko 0.6 (que vello 0.7 expone).
+wgpu = "27"
winit = "0.30"
raw-window-handle = "0.6"
pollster = "0.4"
-vello = "0.5"
+vello = "0.7"
+# Renderer hybrid CPU+GPU sin compute shaders (mejor compat WebGL2/Adreno viejas).
+# Opt-in; el renderer "wgpu" sigue siendo el default.
+vello_hybrid = "0.0.9"
+# foreign-lottie = fork vendorizado de velato 0.9 (Lottie → vello::Scene),
+# completado para no paniquear ante features no soportadas. Lo consume
+# llimphi-lottie. Ver shared/foreign-lottie.
+foreign-lottie = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+# Árbol de accesibilidad para lectores de pantalla (NVDA/VoiceOver/Orca/TalkBack).
+# Lo consume el runtime de Llimphi (iter 2/3 del plan AccessKit); el modelo
+# `SemanticsSpec` del compositor es independiente de estas crates.
+accesskit = "0.24"
+accesskit_winit = "0.33"
taffy = "0.9"
# parley = shaping completo (bidi, ligatures, fallback CJK/emoji vía fontique, line break).
-parley = "0.4"
+parley = "0.6"
# Bucle Elm (input→update→view→layout→raster→present). Lo consumen las apps.
-llimphi-ui = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.1.0" }
+llimphi-ui = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+# Tier 3 — apps WASM con UI Llimphi real. El guest pinta un WireNode (IR
+# serializable), el host (runner) lo materializa en View<Msg> y rebota los
+# eventos al update del guest. SDK = lado guest, runner = lado host.
+llimphi-wire-view = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+llimphi-wasm-app-sdk = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+llimphi-wasm-runner = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+# Núcleo puro de distribución (CAS + verificación + resolve), SIN runner/GPU.
+llimphi-wasm-core = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+# Cara con baterías: re-exporta core + puente al runner para correr la app.
+llimphi-wasm-dist = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+llimphi-wasm-open = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+llimphi-wasm-registry = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+llimphi-wasm-wasi = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+# Transporte P2P del bytecode por hash sobre BrahmanNet (card-net).
+llimphi-wasm-net = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+llimphi-3d = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+# Runner wlr-layer-shell: corre un `App` de Llimphi como barra anclada a un
+# borde (no como ventana), reusando la plumbing sctk+wgpu que pata probó.
+llimphi-layer = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
# Paleta semántica compartida por las apps y los widgets.
-llimphi-theme = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.1.0" }
+llimphi-theme = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
# Tweens y helpers de animación sobre el bucle Elm.
-llimphi-motion = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.1.0" }
+llimphi-motion = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+# Máquina de estados de animación (estilo Rive) clip-agnóstica. Núcleo puro;
+# el render lo cablea el consumidor (llimphi-lottie). Escalón sobre el playback.
+llimphi-anim = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+# Studio de animación «rive»: además del editor (bin), expone como lib los
+# documentos serializables (Doc + RigDoc + Project) que carga mirada-fondo.
+llimphi-anim-studio = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+# Render de mallas deformables (skel::Mesh) a vello Scene: vectorial y texturizada.
+llimphi-mesh = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
# Iconos vectoriales (BezPath en grid 24×24) compartidos por todas las apps.
-llimphi-icons = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.1.0" }
+llimphi-icons = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+# Puente fino vello_svg → Llimphi para SVG arbitrario (íconos .desktop, logos).
+llimphi-svg = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+# Puente fino velato (Lottie) → Llimphi para animación vectorial autorada (.json).
+llimphi-lottie = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+llimphi-image = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+# Decodificador de protocolos de gráficos de terminal (kitty/sixel) → RGBA.
+llimphi-term-graphics = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
# Widgets reusables sobre llimphi-ui — uno por crate.
-llimphi-widget-app-header = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.1.0" }
-llimphi-widget-banner = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.1.0" }
-llimphi-widget-button = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.1.0" }
-llimphi-widget-card = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.1.0" }
-llimphi-clipboard = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.1.0" }
-llimphi-widget-context-menu = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.1.0" }
-llimphi-widget-edit-menu = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.1.0" }
-llimphi-widget-menubar = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.1.0" }
-llimphi-widget-list = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.1.0" }
-llimphi-widget-grid = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.1.0" }
-llimphi-widget-slider = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.1.0" }
-llimphi-widget-scroll = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.1.0" }
-llimphi-widget-splitter = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.1.0" }
-llimphi-widget-stat-card = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.1.0" }
-llimphi-widget-tabs = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.1.0" }
-llimphi-module-command-palette = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.1.0" }
-llimphi-module-diff-viewer = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.1.0" }
-llimphi-module-fif = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.1.0" }
-llimphi-module-file-picker = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.1.0" }
-llimphi-module-bookmarks = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.1.0" }
-llimphi-module-mini-map = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.1.0" }
-llimphi-module-shuma-term = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.1.0" }
-llimphi-module-symbol-outline = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.1.0" }
-llimphi-plugin-host = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.1.0" }
-llimphi-widget-theme-switcher = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.1.0" }
-llimphi-widget-text-area = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.1.0" }
-llimphi-widget-text-editor-core = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.1.0" }
-llimphi-widget-text-editor = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.1.0" }
-llimphi-widget-text-editor-lsp = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.1.0" }
-llimphi-widget-text-input = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.1.0" }
-llimphi-widget-tiled = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.1.0" }
-llimphi-widget-nodegraph = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.1.0" }
-llimphi-widget-tree = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.1.0" }
-llimphi-widget-navigator = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.1.0" }
+llimphi-widget-app-header = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+llimphi-widget-banner = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+llimphi-widget-button = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+llimphi-widget-rive-button = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+llimphi-widget-card = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+llimphi-clipboard = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+llimphi-widget-context-menu = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+llimphi-widget-edit-menu = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+llimphi-widget-menubar = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+llimphi-widget-list = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+llimphi-widget-grid = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+llimphi-widget-table = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+llimphi-widget-color-picker = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+llimphi-widget-slider = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+llimphi-widget-scroll = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+llimphi-widget-lazy-list = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+llimphi-widget-splitter = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+llimphi-widget-stat-card = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+llimphi-widget-tabs = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+llimphi-module-allichay = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+llimphi-module-command-palette = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+llimphi-module-diff-viewer = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+llimphi-module-fif = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+llimphi-module-file-picker = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+llimphi-module-bookmarks = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+llimphi-module-mini-map = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+llimphi-module-shuma-term = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+llimphi-module-symbol-outline = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+llimphi-plugin-host = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+llimphi-widget-theme-switcher = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+llimphi-widget-text-area = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+llimphi-widget-text-editor-core = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+llimphi-widget-text-editor = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+llimphi-widget-text-editor-lsp = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+llimphi-widget-text-input = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+llimphi-widget-tiled = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+llimphi-widget-nodegraph = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+llimphi-widget-tree = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+grafo-nav = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+llimphi-widget-navigator = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+llimphi-widget-detail-table = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+llimphi-widget-select = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+llimphi-widget-terminal = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
# Sello vectorial wawa (rombo + W implícita + Merkle Core).
-llimphi-widget-wawa-mark = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.1.0" }
+llimphi-widget-wawa-mark = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
# Widgets de elegancia transversal (tooltip, spinner, progress, toast,
# modal, empty, status-bar, shortcuts-help, splash).
-llimphi-widget-tooltip = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.1.0" }
-llimphi-widget-spinner = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.1.0" }
-llimphi-widget-progress = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.1.0" }
-llimphi-widget-toast = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.1.0" }
-llimphi-widget-modal = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.1.0" }
-llimphi-widget-empty = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.1.0" }
-llimphi-widget-status-bar = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.1.0" }
-llimphi-widget-shortcuts-help = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.1.0" }
-llimphi-widget-timeline = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.1.0" }
-llimphi-widget-splash = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.1.0" }
+llimphi-widget-tooltip = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+llimphi-widget-spinner = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+llimphi-widget-progress = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+llimphi-widget-toast = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+llimphi-widget-modal = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+llimphi-widget-empty = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+llimphi-widget-status-bar = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+llimphi-widget-shortcuts-help = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+llimphi-widget-timeline = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+llimphi-widget-transport = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+llimphi-widget-waveform = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+llimphi-widget-splash = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
# Controles de formulario y signaling (switch, segmented, breadcrumb,
# badge, avatar, skeleton, field).
-llimphi-widget-switch = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.1.0" }
-llimphi-widget-segmented = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.1.0" }
-llimphi-widget-dock-rail = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.1.0" }
-llimphi-widget-breadcrumb = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.1.0" }
-llimphi-widget-badge = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.1.0" }
-llimphi-widget-avatar = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.1.0" }
-llimphi-widget-skeleton = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.1.0" }
-llimphi-widget-field = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.1.0" }
+llimphi-widget-switch = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+llimphi-widget-segmented = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+llimphi-widget-rag-sidebar = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+llimphi-widget-dock-rail = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+llimphi-widget-toolbar = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+llimphi-widget-breadcrumb = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+llimphi-widget-badge = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+llimphi-widget-avatar = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+llimphi-widget-skeleton = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+llimphi-widget-field = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
# Firma visual transversal (gradient sutil + hairline accent).
-llimphi-widget-panel = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.1.0" }
-llimphi-widget-panes = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.1.0" }
-llimphi-workspace = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.1.0" }
+llimphi-widget-panel = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+llimphi-widget-panes = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+# Widgets Flutter-like — composición sobre primitivas Tier 1/3 ya
+# expuestas (sombra, gradient, animated, ripple).
+llimphi-widget-chip = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+llimphi-widget-fab = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+llimphi-widget-wrap = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+llimphi-widget-range-slider = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+llimphi-widget-calendar = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+llimphi-widget-fitted-box = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+llimphi-widget-carousel = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+llimphi-widget-rating = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+llimphi-widget-gauge = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+llimphi-widget-scaffold = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+llimphi-widget-hero = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+llimphi-widget-router = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+llimphi-workspace = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
# Abstracción Selector — host (paths) + wawa (khipus).
-llimphi-module-selector = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.1.0" }
+llimphi-module-selector = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
# === Filesystem helpers ===
directories = "5"
@@ -271,7 +407,7 @@ hex = "0.4"
portable-pty = "0.9"
vt100 = "0.16"
-# === WASM web (gioser) ===
+# === WASM web (tawasuyu) ===
wasm-bindgen = "0.2"
wasm-bindgen-futures = "0.4"
js-sys = "0.3"
@@ -296,61 +432,92 @@ ttf-parser = "0.25"
# ============================================================
# Intra-workspace deps de nahual (referenciadas por workspace = true)
# ============================================================
-nahual-text-viewer-llimphi = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.1.0" }
-nahual-image-viewer-llimphi = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.1.0" }
-nahual-thumb-core = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.1.0" }
-nahual-gallery-llimphi = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.1.0" }
-nahual-video-viewer-llimphi = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.1.0" }
-nahual-card-viewer-llimphi = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.1.0" }
-nahual-audio-viewer-llimphi = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.1.0" }
-nahual-tree-viewer-llimphi = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.1.0" }
-nahual-hex-viewer-llimphi = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.1.0" }
-nahual-table-viewer-llimphi = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.1.0" }
-nahual-markdown-viewer-llimphi = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.1.0" }
-nahual-archive-viewer-llimphi = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.1.0" }
-nahual-font-viewer-llimphi = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.1.0" }
-nahual-map-viewer-llimphi = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.1.0" }
-nahual-geo-core = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.1.0" }
-nahual-viewer-core = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.1.0" }
-nahual-file-explorer-llimphi = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.1.0" }
+nahual-text-viewer-llimphi = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+nahual-image-viewer-llimphi = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+nahual-pdf-viewer-llimphi = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+nahual-cbz-viewer-llimphi = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+nahual-thumb-core = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+nahual-gallery-llimphi = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+nahual-video-viewer-llimphi = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+nahual-card-viewer-llimphi = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+nahual-audio-viewer-llimphi = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+media-module = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+tullpu-module = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+tullpu-core = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+tullpu-icon-core = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+tullpu-icon-cli = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+tullpu-icon-llimphi = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+tullpu-icon-llm = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+foreign-svg = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+foreign-pdf = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+tullpu-render = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+tullpu-render-gpu = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+tullpu-ops = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+tullpu-paint = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+nahual-tree-viewer-llimphi = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+nahual-hex-viewer-llimphi = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+nahual-svg-viewer-llimphi = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+nahual-sheet-viewer-llimphi = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+nahual-dbf-viewer-llimphi = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+nahual-table-viewer-llimphi = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+nahual-markdown-viewer-llimphi = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+nahual-pluma-viewer-llimphi = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+nahual-cotejo-llimphi = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+nahual-deck-viewer-llimphi = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+nahual-archive-viewer-llimphi = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+nahual-font-viewer-llimphi = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+nahual-map-viewer-llimphi = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+nahual-geo-core = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+nahual-geo-voxel = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+nahual-iconos = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+nahual-viewer-core = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+nahual-file-explorer-llimphi = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
# ============================================================
# Intra-workspace deps de pineal (módulo de gráficos)
# ============================================================
-pineal-core = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.1.0" }
-pineal-render = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.1.0" }
-pineal-cartesian = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.1.0" }
-pineal-stream = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.1.0" }
-pineal-mesh = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.1.0" }
-pineal-financial = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.1.0" }
-pineal-polar = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.1.0" }
-pineal-heatmap = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.1.0" }
-pineal-treemap = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.1.0" }
-pineal-flow = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.1.0" }
-pineal-phosphor = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.1.0" }
-pineal-export = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.1.0" }
-pineal-hexbin = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.1.0" }
-pineal-contour = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.1.0" }
-pineal-bars = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.1.0" }
-pineal = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.1.0" }
+pineal-core = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+pineal-render = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+pineal-cartesian = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+pineal-stream = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+pineal-mesh = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+pineal-financial = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+pineal-polar = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+pineal-heatmap = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+pineal-treemap = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+pineal-flow = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+pineal-phosphor = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+pineal-export = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+pineal-hexbin = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+pineal-contour = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+pineal-bars = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+pineal = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
# ============================================================
# Intra-workspace deps de iniy (laboratorio semántico de creencias)
# ============================================================
-iniy-core = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.1.0" }
-iniy-ingest = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.1.0" }
-iniy-extract = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.1.0" }
-iniy-nli = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.1.0" }
-iniy-nli-llm = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.1.0" }
-iniy-graph = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.1.0" }
-iniy-store = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.1.0" }
+iniy-core = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+iniy-evidencia = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+iniy-derive = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+iniy-emisores = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+iniy-cache = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+iniy-daemon = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+iniy-ingest = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+iniy-extract = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+iniy-nli = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+iniy-nli-llm = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+iniy-graph = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+iniy-store = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+# la física de decaimiento de khipu la importa iniy-derive (SDD iniy §3)
+khipu-gravity = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
# === auto: declarados por crates internos faltantes ===
-cosmos-coords = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.1.0" }
-cosmos-core = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.1.0" }
-cosmos-ephemeris = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.1.0" }
-cosmos-time = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.1.0" }
-cosmos-wcs = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.1.0" }
+cosmos-coords = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+cosmos-cities = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+cosmos-core = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+cosmos-ephemeris = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+cosmos-time = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+cosmos-wcs = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
# === auto: externas de eternal ===
celestial-eop-data = { version = "0.1"}
@@ -358,6 +525,7 @@ approx = "0.5"
byteorder = "1.5"
cc = "1.0"
chrono = "0.4"
+chrono-tz = "0.10"
crc32fast = "1.4"
criterion = "0.5"
csv = "1.4"
@@ -366,6 +534,11 @@ glob = "0.3"
indicatif = "0.18"
lz4_flex = "0.11"
memmap2 = "0.9"
+# Cliente Wayland (lado cliente) — lo usa hapiy para hablar zwlr_screencopy
+# contra mirada (u otro compositor wlroots) y capturar la pantalla.
+wayland-client = "0.31"
+wayland-protocols-wlr = { version = "0.3", features = ["client"] }
+wayland-protocols-misc = { version = "0.3", features = ["client"] }
mockito = "1.0"
ndarray = "0.15"
num-traits = "0.2"
@@ -399,6 +572,9 @@ markup5ever_rcdom = "0.39"
cssparser = "0.35"
url = "2"
ureq = { version = "2", default-features = false, features = ["tls"] }
+# Charset de la web real: no todo es UTF-8 (google.com sirve ISO-8859-1).
+# Ya venía transitivo por el stack de Servo — aquí se hace explícito.
+encoding_rs = "0.8"
# === takiy-synth (SoundFont MIDI) ===
# rustysynth = sintetizador SF2 puro Rust, MIT. Reemplaza el oscilador
@@ -427,7 +603,7 @@ hound = "3.5"
symphonia = { version = "0.5", default-features = false, features = ["mp3", "flac", "vorbis", "ogg"] }
# === media-source-opus (decoder Opus NATIVO puro-Rust) ===
-# Opus es el formato de audio nativo de gioser (par del video AV1). ogg
+# Opus es el formato de audio nativo de tawasuyu (par del video AV1). ogg
# demuxea las páginas Ogg; opus-wave es un port puro-Rust de libopus
# (SILK+CELT, sin C ni FFI) — par del rav1d del lado video.
ogg = "0.9"
@@ -438,11 +614,30 @@ opus-wave = "3"
# paquetes de los tracks V_AV1 y A_OPUS para alimentar a media-source-av1
# y media-source-opus — un .webm AV1+Opus se reproduce 100% nativo.
matroska-demuxer = "0.7"
-# === git-deps al monorepo (agregados por la extracción) ===
-arje-cas = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.1.0" }
-card-core = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.1.0" }
-card-net = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.1.0" }
-card-wit = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.1.0" }
-rimay-localize = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.1.0" }
-shuma-discern = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.1.0" }
-wawa-config = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.1.0" }
+
+# === Perfil `dist`: binarios de reparto livianos (equipos chicos / poca RAM) ===
+# Hereda de `release` pero prioriza HUELLA sobre tiempo de compilación: LTO thin
+# (poda código muerto entre crates), un solo codegen-unit (mejor inlining/DCE) y
+# `strip` de símbolos. Reduce el tamaño en disco Y el segmento de código mapeado
+# en RAM de cada binario (mirada, pata, apps Llimphi). No toca `cargo build
+# --release` de iteración diaria; se usa sólo al empaquetar:
+# cargo build --profile dist -p mirada-compositor -p pata-host …
+# `panic = "unwind"` se mantiene a propósito: mirada-plugin-host aísla plugins
+# con `catch_unwind`, así que `abort` rompería el sandbox.
+# === Crates del monorepo consumidos por git-dep (pin del tag) ===
+arje-cas = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+card-core = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+card-net = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+card-wit = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+rimay-localize = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+shuma-discern = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+wawa-config = { git = "https://git.tawasuyu.net/tawasuyu/tawasuyu.git", tag = "v0.2.0" }
+
+[profile.dist]
+inherits = "release"
+lto = "thin"
+codegen-units = 1
+strip = "symbols"
+panic = "unwind"
+
+