Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions crates/aingle/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "aingle"
version = "0.4.2"
version = "0.6.0"
description = "AIngle, a framework for distributed applications"
license = "Apache-2.0 OR LicenseRef-Commercial"
homepage = "https://apilium.com"
Expand All @@ -26,14 +26,14 @@ ghost_actor = "0.3.0-alpha.1"
ai_hash = { version = ">=0.0.1", path = "../ai_hash", features = ["full"] }
aingle_cascade = { version = "0.0.1", path = "../aingle_cascade" }
aingle_conductor_api = { version = "0.0.1", path = "../aingle_conductor_api" }
aingle_ai = { version = "0.4", path = "../aingle_ai", optional = true }
aingle_ai = { version = "0.6", path = "../aingle_ai", optional = true }
aingle_keystore = { version = "0.0.1", path = "../aingle_keystore" }
aingle_p2p = { version = "0.0.1", path = "../aingle_p2p" }
aingle_sqlite = { version = "0.0.1", path = "../aingle_sqlite" }
aingle_middleware_bytes = "=0.0.3"
aingle_state = { version = "0.0.1", path = "../aingle_state" }
aingle_types = { version = "0.0.1", path = "../aingle_types" }
aingle_cortex = { version = "0.4", path = "../aingle_cortex", default-features = false, features = ["rest"] }
aingle_cortex = { version = "0.6", path = "../aingle_cortex", default-features = false, features = ["rest"] }
aingle_wasmer_host = "0.0.1"
aingle_websocket = { version = "0.0.1", path = "../aingle_websocket" }
wasmer = "=7.0.1"
Expand Down
2 changes: 1 addition & 1 deletion crates/aingle_ai/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "aingle_ai"
version = "0.5.0"
version = "0.6.0"
description = "AI integration layer for AIngle - Ineru, Nested Learning, Kaneru"
license = "Apache-2.0 OR LicenseRef-Commercial"
repository = "https://github.com/ApiliumCode/aingle"
Expand Down
2 changes: 1 addition & 1 deletion crates/aingle_contracts/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "aingle_contracts"
version = "0.5.0"
version = "0.6.0"
description = "Smart Contracts DSL and WASM Runtime for AIngle"
license = "Apache-2.0 OR LicenseRef-Commercial"
repository = "https://github.com/ApiliumCode/aingle"
Expand Down
15 changes: 8 additions & 7 deletions crates/aingle_cortex/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "aingle_cortex"
version = "0.5.0"
version = "0.6.0"
description = "Córtex API - REST/GraphQL/SPARQL interface for AIngle semantic graphs"
license = "Apache-2.0 OR LicenseRef-Commercial"
repository = "https://github.com/ApiliumCode/aingle"
Expand All @@ -21,6 +21,7 @@ auth = ["dep:jsonwebtoken", "dep:argon2"]
p2p = ["dep:quinn", "dep:rustls", "dep:rcgen", "dep:ed25519-dalek", "dep:hex"]
p2p-mdns = ["p2p", "dep:mdns-sd", "dep:if-addrs"]
cluster = ["p2p", "dep:aingle_wal", "dep:aingle_raft", "dep:openraft", "dep:tokio-rustls", "dep:rustls-pemfile"]
dag = ["cluster", "aingle_graph/dag", "aingle_graph/dag-sign", "aingle_raft/dag"]
full = ["rest", "graphql", "sparql", "auth"]

[[bin]]
Expand All @@ -29,10 +30,10 @@ path = "src/main.rs"

[dependencies]
# Core AIngle crates
aingle_graph = { version = "0.5", path = "../aingle_graph", features = ["sled-backend"] }
aingle_logic = { version = "0.5", path = "../aingle_logic" }
aingle_zk = { version = "0.5", path = "../aingle_zk" }
ineru = { version = "0.5", path = "../ineru" }
aingle_graph = { version = "0.6", path = "../aingle_graph", features = ["sled-backend"] }
aingle_logic = { version = "0.6", path = "../aingle_logic" }
aingle_zk = { version = "0.6", path = "../aingle_zk" }
ineru = { version = "0.6", path = "../ineru" }

# Web framework
axum = { version = "0.8", features = ["ws", "macros"] }
Expand Down Expand Up @@ -95,8 +96,8 @@ rcgen = { version = "0.13", optional = true }
ed25519-dalek = { version = "2", features = ["rand_core"], optional = true }
hex = { version = "0.4", optional = true }
# Clustering (optional)
aingle_wal = { version = "0.5", path = "../aingle_wal", optional = true }
aingle_raft = { version = "0.5", path = "../aingle_raft", optional = true }
aingle_wal = { version = "0.6", path = "../aingle_wal", optional = true }
aingle_raft = { version = "0.6", path = "../aingle_raft", optional = true }
openraft = { version = "0.10.0-alpha.17", features = ["serde", "type-alias"], optional = true }
tokio-rustls = { version = "0.26", default-features = false, features = ["ring"], optional = true }
rustls-pemfile = { version = "2", optional = true }
Expand Down
116 changes: 115 additions & 1 deletion crates/aingle_cortex/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -104,11 +104,13 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
cfg
};

// Capture bind address before config is moved (used by cluster bootstrap)
// Capture bind address and db_path before config is moved
#[allow(unused_variables)]
let bind_host = config.host.clone();
#[allow(unused_variables)]
let bind_port = config.port;
#[allow(unused_variables)]
let db_path = config.db_path.clone();

// Create and run server
#[allow(unused_mut)]
Expand Down Expand Up @@ -142,6 +144,118 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
);
}

// Initialize DAG if enabled: enable DAG on the graph, create genesis if needed
#[cfg(feature = "dag")]
{
let state = server.state_mut();

// Enable DAG on the GraphDB (persistent for Sled, in-memory otherwise)
{
let mut graph = state.graph.write().await;
match &db_path {
Some(p) if p != ":memory:" => {
if let Err(e) = graph.enable_dag_persistent(p) {
tracing::error!(
"Failed to enable persistent DAG: {e}. \
Falling back to in-memory DAG — data will NOT survive restarts!"
);
graph.enable_dag();
} else {
tracing::info!("DAG persistence enabled (Sled)");
}
}
_ => {
tracing::warn!("DAG using in-memory backend — data will NOT survive restarts");
graph.enable_dag();
}
}
let triple_count = graph.count();
if let Some(dag_store) = graph.dag_store() {
match dag_store.init_or_migrate(triple_count) {
Ok(genesis_hash) => {
tracing::info!(
hash = %genesis_hash,
triples = triple_count,
"DAG initialized (genesis)"
);
}
Err(e) => {
tracing::error!("DAG initialization failed: {e}");
}
}
}
}

// Set DAG author from cluster node ID
#[cfg(feature = "cluster")]
if let Some(node_id) = state.cluster_node_id {
state.dag_author = Some(aingle_graph::NodeId::named(&format!("node:{}", node_id)));
}

// Initialize Ed25519 signing key for DAG actions.
// Reuses the same node.key seed as P2P identity (deterministic).
{
let key = match &db_path {
Some(p) if p != ":memory:" => {
let key_path = std::path::Path::new(p)
.parent()
.unwrap_or(std::path::Path::new("."))
.join("node.key");
if key_path.exists() {
match std::fs::read(&key_path) {
Ok(seed) if seed.len() == 32 => {
let mut arr = [0u8; 32];
arr.copy_from_slice(&seed);
Some(aingle_graph::dag::DagSigningKey::from_seed(&arr))
}
_ => None,
}
} else {
// Generate new key and persist
let key = aingle_graph::dag::DagSigningKey::generate();
let seed = key.seed();
if let Some(parent) = key_path.parent() {
std::fs::create_dir_all(parent).ok();
}
#[cfg(unix)]
{
use std::io::Write;
use std::os::unix::fs::OpenOptionsExt;
if let Ok(mut f) = std::fs::OpenOptions::new()
.create(true)
.write(true)
.truncate(true)
.mode(0o600)
.open(&key_path)
{
let _ = f.write_all(&seed);
}
}
#[cfg(not(unix))]
{
let _ = std::fs::write(&key_path, &seed);
}
Some(key)
}
}
_ => {
// In-memory mode: generate ephemeral key
Some(aingle_graph::dag::DagSigningKey::generate())
}
};

if let Some(ref k) = key {
tracing::info!(
public_key = %k.public_key_hex(),
"DAG signing key loaded (Ed25519)"
);
}
state.dag_signing_key = key.map(std::sync::Arc::new);
}

tracing::info!("Semantic DAG v0.6.0 enabled");
}

// Keep a reference to the state for shutdown flush
let state_for_shutdown = server.state().clone();
let snapshot_dir_for_shutdown = snapshot_dir.clone();
Expand Down
Loading
Loading