plexus_substrate/
builder.rs1use std::sync::{Arc, Weak};
6
7use crate::activations::arbor::{Arbor, ArborConfig};
8use crate::activations::bash::Bash;
9use crate::activations::chaos::Chaos;
10use crate::activations::claudecode::{ClaudeCode, ClaudeCodeStorage, ClaudeCodeStorageConfig};
11use crate::activations::claudecode_loopback::{ClaudeCodeLoopback, LoopbackStorageConfig};
12use crate::activations::cone::{Cone, ConeStorageConfig};
13use crate::activations::echo::Echo;
14use crate::activations::health::Health;
15use crate::activations::interactive::Interactive;
16use crate::activations::lattice::{Lattice, LatticeStorageConfig};
17use crate::activations::changelog::{Changelog, ChangelogStorageConfig};
18use crate::activations::mustache::{Mustache, MustacheStorageConfig};
19use crate::activations::orcha::pm::{Pm, PmStorage, PmStorageConfig};
20use crate::activations::orcha::{GraphRuntime, Orcha, OrchaStorage, OrchaStorageConfig};
21use crate::activations::solar::Solar;
22use crate::plexus::DynamicHub;
23use registry::Registry;
25
26pub async fn build_plexus_rpc() -> Arc<DynamicHub> {
44 let arbor: Arbor<Weak<DynamicHub>> = Arbor::with_context_type(ArborConfig::default())
47 .await
48 .expect("Failed to initialize Arbor");
49 let arbor_storage = arbor.storage();
50
51 let cone: Cone<Weak<DynamicHub>> = Cone::with_context_type(ConeStorageConfig::default(), arbor_storage.clone())
54 .await
55 .expect("Failed to initialize Cone");
56
57 let claudecode_storage = ClaudeCodeStorage::new(
60 ClaudeCodeStorageConfig::default(),
61 arbor_storage,
62 )
63 .await
64 .expect("Failed to initialize ClaudeCode storage");
65 let claudecode: ClaudeCode<Weak<DynamicHub>> = ClaudeCode::with_context_type(Arc::new(claudecode_storage));
66
67 let mustache = Mustache::new(MustacheStorageConfig::default())
69 .await
70 .expect("Failed to initialize Mustache");
71
72 let loopback = Arc::new(
74 ClaudeCodeLoopback::new(LoopbackStorageConfig::default())
75 .await
76 .expect("Failed to initialize ClaudeCodeLoopback")
77 );
78
79 let orcha_storage = Arc::new(
81 OrchaStorage::new(OrchaStorageConfig::default())
82 .await
83 .expect("Failed to initialize Orcha storage")
84 );
85
86 let pm_storage = Arc::new(
88 PmStorage::new(PmStorageConfig::default())
89 .await
90 .expect("Failed to initialize PM storage")
91 );
92
93 let changelog = Changelog::new(ChangelogStorageConfig::default())
95 .await
96 .expect("Failed to initialize Changelog");
97
98 let arbor_storage_for_orcha = arbor.storage();
100
101 let lattice = Lattice::new(LatticeStorageConfig::default())
106 .await
107 .expect("Failed to initialize Lattice storage");
108
109 let registry = Registry::with_defaults()
111 .await
112 .expect("Failed to initialize Registry");
113
114 let orcha_for_recovery: std::cell::OnceCell<Orcha<Weak<DynamicHub>>> = std::cell::OnceCell::new();
121 let hub = Arc::new_cyclic(|weak_hub: &Weak<DynamicHub>| {
122 arbor.inject_parent(weak_hub.clone());
124 cone.inject_parent(weak_hub.clone());
125 claudecode.inject_parent(weak_hub.clone());
126
127 let graph_runtime = Arc::new(GraphRuntime::new(lattice.storage()));
129 let pm = Arc::new(Pm::new(pm_storage.clone(), lattice.storage()));
130 let orcha: Orcha<Weak<DynamicHub>> = Orcha::new(
131 orcha_storage.clone(),
132 Arc::new(claudecode.clone()),
133 loopback.clone(),
134 arbor_storage_for_orcha,
135 graph_runtime,
136 pm,
137 );
138
139 let _ = orcha_for_recovery.set(orcha.clone());
141
142 DynamicHub::new("substrate")
144 .register(Health::new())
145 .register(Echo::new())
146 .register(Bash::new())
147 .register(Chaos::new(lattice.storage()))
148 .register(arbor)
149 .register(cone)
150 .register(claudecode)
151 .register(mustache)
152 .register(changelog.clone())
153 .register((*loopback).clone())
154 .register_hub(orcha)
155 .register(registry)
157 .register(lattice)
158 .register(Interactive::new()) .register_hub(Solar::new())
160 });
161
162 let plexus_hash = hub.compute_hash();
164 match changelog.startup_check(&plexus_hash).await {
165 Ok((hash_changed, is_documented, message)) => {
166 if hash_changed && !is_documented {
167 tracing::error!("{}", message);
168 } else if hash_changed {
169 tracing::info!("{}", message);
170 } else {
171 tracing::debug!("{}", message);
172 }
173 }
174 Err(e) => {
175 tracing::error!("Changelog startup check failed: {}", e);
176 }
177 }
178
179 if let Some(orcha) = orcha_for_recovery.into_inner() {
182 orcha.recover_running_graphs().await;
183 }
184
185 hub
186}