1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
//! ```text
//! GraphBuilder -> App::compile -> AppRunner
//! | |
//! | +-> Scheduler -> Nodes -> NodePartial
//! | |
//! | +-> Reducers -> VersionedState
//! | +-> EventBus (diagnostics / LLM)
//! |
//! +-> RuntimeConfig (persistence, sinks, execution knobs)
//! ```
//!
//! Weavegraph is a graph-driven workflow framework for concurrent, stateful execution.
//! You define nodes and edges with [`graphs::GraphBuilder`], compile to an [`app::App`],
//! and run with either high-level invocation helpers or the lower-level [`runtimes::AppRunner`].
//!
//! # Quick Start
//!
//! ```rust,no_run
//! use async_trait::async_trait;
//! use weavegraph::graphs::GraphBuilder;
//! use weavegraph::message::Message;
//! use weavegraph::node::{Node, NodeContext, NodeError, NodePartial};
//! use weavegraph::state::{StateSnapshot, VersionedState};
//! use weavegraph::types::NodeKind;
//!
//! struct EchoNode;
//!
//! #[async_trait]
//! impl Node for EchoNode {
//! async fn run(
//! &self,
//! snapshot: StateSnapshot,
//! _ctx: NodeContext,
//! ) -> Result<NodePartial, NodeError> {
//! let reply = snapshot
//! .messages
//! .last()
//! .map(|m| format!("Echo: {}", m.content))
//! .unwrap_or_else(|| "Echo: (no input)".to_string());
//!
//! Ok(NodePartial::new().with_messages(vec![Message::assistant(&reply)]))
//! }
//! }
//!
//! # async fn run() -> Result<(), Box<dyn std::error::Error>> {
//! let app = GraphBuilder::new()
//! .add_node(NodeKind::Custom("echo".into()), EchoNode)
//! .add_edge(NodeKind::Start, NodeKind::Custom("echo".into()))
//! .add_edge(NodeKind::Custom("echo".into()), NodeKind::End)
//! .compile()?;
//!
//! let initial = VersionedState::new_with_user_message("hello");
//! let final_state = app.invoke(initial).await?;
//! assert!(!final_state.snapshot().messages.is_empty());
//! # Ok(())
//! # }
//! ```
//!
//! # Feature Flags
//!
//! | Feature | Default | Purpose |
//! | ------- | ------- | ------- |
//! | `sqlite-migrations` | yes | Enables SQLite persistence support via `sqlx` and migration wiring. |
//! | `sqlite` | no | Enables SQLite checkpointer APIs and runtime backend. |
//! | `postgres-migrations` | no | Enables Postgres migration support for checkpointer setup. |
//! | `postgres` | no | Enables PostgreSQL checkpointer APIs and runtime backend. |
//! | `rig` | no | Enables Rig-based LLM interop and adapters. |
//! | `diagnostics` | no | Adds `miette` diagnostic metadata to error types. |
//! | `examples` | no | Pulls additional deps used by selected examples. |
//! | `petgraph-compat` | no | Exposes petgraph conversion helpers for graph analysis and visualization. |
//!
//! # Documentation
//!
//! - `docs/QUICKSTART.md` for API-first onboarding and composition patterns.
//! - `docs/OPERATIONS.md` for runtime operations, persistence, and deployment concerns.
//! - `docs/STREAMING.md` for event streaming patterns and production guidance.
//! - `docs/ARCHITECTURE.md` for internal architecture and execution model details.
//!
//! # Common Patterns
//!
//! ## Graph lifecycle
//!
//! ```rust,no_run
//! # use weavegraph::graphs::GraphBuilder;
//! # use weavegraph::types::NodeKind;
//! # use weavegraph::state::VersionedState;
//! # use weavegraph::runtimes::RuntimeConfig;
//! # async fn example() -> Result<(), Box<dyn std::error::Error>> {
//! // 1. Build — declare nodes and edges.
//! // 2. Compile — validate topology, attach runtime config.
//! // 3. Invoke — run once or stream events to clients.
//! let app = GraphBuilder::new()
//! /* .add_node(...).add_edge(...) */
//! .compile()?;
//!
//! let state = VersionedState::new_with_user_message("hello");
//! let final_state = app.invoke(state).await?;
//! # Ok(())
//! # }
//! ```
//!
//! See `examples/graph_execution.rs` for a runnable graph lifecycle example.
//!
//! ## Streaming events via SSE
//!
//! ```rust,no_run
//! # use std::sync::Arc;
//! # use weavegraph::app::App;
//! # use weavegraph::event_bus::STREAM_END_SCOPE;
//! # use weavegraph::state::VersionedState;
//! # async fn example(app: Arc<App>) {
//! // Each call gets an isolated runner + event bus.
//! let state = VersionedState::new_with_user_message("hello");
//! let (handle, event_stream) = app.invoke_streaming(state).await;
//!
//! // Convert to an async stream and forward to your SSE layer.
//! // Terminate when STREAM_END_SCOPE is observed.
//! let _ = event_stream.into_async_stream(); // futures::Stream<Item = Event>
//! let _ = handle; // join or abort the background task
//! # }
//! ```
//!
//! See `examples/production_streaming.rs` for the full Axum + Postgres reference.
//!
//! ## Error handling in nodes
//!
//! ```rust,no_run
//! # use weavegraph::node::{NodeError, NodeResultExt};
//! // Return a domain error from any node:
//! fn validate(input: &str) -> Result<(), NodeError> {
//! if input.is_empty() {
//! return Err(NodeError::Other("input must not be empty".into()));
//! }
//! // Lift arbitrary std::error::Error with ?:
//! std::str::from_utf8(input.as_bytes()).node_err()?;
//! Ok(())
//! }
//! ```
//!
//! See `examples/errors_pretty.rs` for error display patterns.
pub use ;