Skip to content

Commit d2a821e

Browse files
committed
[WIP] API updates, documentation
1 parent 895fc86 commit d2a821e

File tree

25 files changed

+273
-240
lines changed

25 files changed

+273
-240
lines changed

rust-sdk/Cargo.lock

Lines changed: 2 additions & 14 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

rust-sdk/Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,6 @@ serde = { version = "^1", features = ["derive"] }
88
serde_json = "^1"
99
uuid = { version = "1.17.0", features = ["v4", "serde"] }
1010

11+
[patch.crates-io]
12+
ag-ui-core = { path = "crates/ag-ui-core" }
13+
ag-ui-client = { path = "crates/ag-ui-client" }

rust-sdk/TODO

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
1-
- [ ] Agent "state" handling
2-
- [ ] Run parameters DX improvements
1+
- [ ] Agent "state" handling (possibly with actor model)
2+
- [X] Run parameters DX improvements
33
- [ ] More elaborate error handling (especially for deserialization errors)
44
- [ ] Retries?
55
- [ ] Documentation
66
- [ ] JSON Patch types in `ag-ui-core`
77
- [ ] Builder patterns on most-used structs
88
- [ ] Review EventHandler & Mutations
99
- [ ] Subscriber + mutations DX improvement
10+
- [ ] Not all messages are being saved?
11+
- [ ] SSE review
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
fn main() {
2-
println!("Hello, world!");
2+
todo!()
33
}

rust-sdk/crates/ag-ui-client/Cargo.toml

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,6 @@ tokio = "1.36.0"
2424
env_logger = "0.11.8"
2525
tokio = { version = "1.36.0", features = ["full"] }
2626

27-
[patch.crates-io]
28-
ag-ui-core = { path = "../ag-ui-core" }
29-
3027
[[example]]
3128
name = "http-agent"
3229
path = "examples/basic_agent.rs"
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,36 @@
11
# AG-UI Rust Client
2+
3+
Rust client for working with the AG-UI protocol. The client API has been designed to mimic the Typescript client as
4+
close as possible. However, a key difference is that state & messages are not yet an attribute of an implementation of
5+
[`Agent`](src/agent.rs) because it would require `&mut self` for straightforward implementations. This is a work in
6+
progress.
7+
8+
## Example
9+
10+
For each example make sure to read the instructions on starting the associated AG-UI server.
11+
12+
### Basic
13+
14+
```rust
15+
use std::error::Error;
16+
use ag_ui_client::{core::types::Message, Agent, HttpAgent, RunAgentParams};
17+
18+
#[tokio::main]
19+
async fn main() -> Result<(), Box<dyn Error>>{
20+
let agent = HttpAgent::builder()
21+
.with_url_str("http://127.0.0.1:3001/")?
22+
.build()?;
23+
24+
let message = Message::new_user("Can you give me the current temperature in New York?");
25+
// Create run parameters
26+
let params = RunAgentParams::new().add_message(message);
27+
28+
// Run the agent with the subscriber
29+
let result = agent.run_agent(&params, ()).await?;
30+
31+
println!("{:#?}", result);
32+
Ok(())
33+
}
34+
```
35+
36+
For more examples check the [examples folder](examples).
Lines changed: 9 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,48 +1,19 @@
1-
use ag_ui_client::Agent;
2-
use ag_ui_client::agent::{AgentError, RunAgentParams};
3-
use ag_ui_client::http::HttpAgent;
4-
5-
use ag_ui_core::JsonValue;
6-
use ag_ui_core::types::ids::MessageId;
7-
use ag_ui_core::types::message::Message;
8-
use log::info;
9-
use reqwest::Url;
1+
use ag_ui_client::{Agent, HttpAgent, RunAgentParams, core::types::Message};
2+
use std::error::Error;
103

114
#[tokio::main]
12-
async fn main() -> Result<(), AgentError> {
13-
env_logger::Builder::from_default_env().init();
14-
15-
// Base URL for the mock server
16-
// Run the following command to start the mock server:
17-
// `uv run rust-sdk/crates/ag-ui-client/scripts/basic_agent.py`
18-
let base_url = Url::parse("http://127.0.0.1:3001/").map_err(|e| AgentError::ConfigError {
19-
message: e.to_string(),
20-
})?;
21-
22-
// Create agent
23-
let agent = HttpAgent::builder().with_url(base_url).build()?;
5+
async fn main() -> Result<(), Box<dyn Error>> {
6+
let agent = HttpAgent::builder()
7+
.with_url_str("http://127.0.0.1:3001/")?
8+
.build()?;
249

10+
let message = Message::new_user("Can you give me the current temperature in New York?");
2511
// Create run parameters
26-
let params = RunAgentParams::<JsonValue, _> {
27-
forwarded_props: Some(serde_json::json!({})),
28-
messages: vec![Message::User {
29-
id: MessageId::random(),
30-
content: "Can you give me the current temperature in New York?".into(),
31-
name: None,
32-
}],
33-
..Default::default()
34-
};
35-
36-
info!("Running agent...");
12+
let params = RunAgentParams::new().add_message(message);
3713

3814
// Run the agent with the subscriber
3915
let result = agent.run_agent(&params, ()).await?;
4016

41-
info!(
42-
"Agent run completed with {} new messages",
43-
result.new_messages.len()
44-
);
45-
info!("Result: {:#?}", result);
46-
17+
println!("{:#?}", result);
4718
Ok(())
4819
}

rust-sdk/crates/ag-ui-client/examples/generative_ui.rs

Lines changed: 16 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,25 @@
11
use std::error::Error;
2-
use std::fmt::{Debug, Display, Formatter};
2+
use std::fmt::Debug;
33

44
use async_trait::async_trait;
55
use log::info;
66
use reqwest::Url;
7-
use reqwest::header::HeaderMap;
87
use serde::{Deserialize, Serialize};
98

109
use ag_ui_client::agent::{AgentError, AgentStateMutation, RunAgentParams};
10+
use ag_ui_client::core::AgentState;
11+
use ag_ui_client::core::event::{StateDeltaEvent, StateSnapshotEvent};
12+
use ag_ui_client::core::types::Message;
1113
use ag_ui_client::subscriber::{AgentSubscriber, AgentSubscriberParams};
1214
use ag_ui_client::{Agent, HttpAgent};
13-
use ag_ui_core::event::{StateDeltaEvent, StateSnapshotEvent};
14-
use ag_ui_core::types::ids::MessageId;
15-
use ag_ui_core::types::message::Message;
16-
use ag_ui_core::{AgentState, FwdProps, JsonValue};
1715

1816
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, Hash)]
17+
#[serde(rename_all = "lowercase")]
1918
pub enum StepStatus {
20-
#[serde(rename = "pending")]
2119
Pending,
22-
#[serde(rename = "completed")]
2320
Completed,
2421
}
2522

26-
impl Display for StepStatus {
27-
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
28-
match self {
29-
StepStatus::Pending => write!(f, "pending"),
30-
StepStatus::Completed => write!(f, "completed"),
31-
}
32-
}
33-
}
34-
3523
impl Default for StepStatus {
3624
fn default() -> Self {
3725
StepStatus::Pending
@@ -71,14 +59,11 @@ impl GenerativeUiSubscriber {
7159
}
7260

7361
#[async_trait]
74-
impl<FwdPropsT> AgentSubscriber<Plan, FwdPropsT> for GenerativeUiSubscriber
75-
where
76-
FwdPropsT: FwdProps + Debug,
77-
{
62+
impl AgentSubscriber<Plan, ()> for GenerativeUiSubscriber {
7863
async fn on_state_snapshot_event(
7964
&self,
8065
event: &StateSnapshotEvent<Plan>,
81-
_params: AgentSubscriberParams<'async_trait, Plan, FwdPropsT>,
66+
_params: AgentSubscriberParams<'async_trait, Plan, ()>,
8267
) -> Result<AgentStateMutation<Plan>, AgentError> {
8368
info!("State snapshot received:");
8469
let plan = &event.snapshot;
@@ -96,7 +81,7 @@ where
9681
async fn on_state_delta_event(
9782
&self,
9883
event: &StateDeltaEvent,
99-
_params: AgentSubscriberParams<'async_trait, Plan, FwdPropsT>,
84+
_params: AgentSubscriberParams<'async_trait, Plan, ()>,
10085
) -> Result<AgentStateMutation<Plan>, AgentError> {
10186
info!("State delta received:");
10287
for patch in &event.delta {
@@ -131,7 +116,7 @@ where
131116

132117
async fn on_state_changed(
133118
&self,
134-
params: AgentSubscriberParams<'async_trait, Plan, FwdPropsT>,
119+
params: AgentSubscriberParams<'async_trait, Plan, ()>,
135120
) -> Result<(), AgentError> {
136121
info!("Overall state changed");
137122
let completed_steps = params
@@ -162,20 +147,16 @@ async fn main() -> Result<(), Box<dyn Error>> {
162147
// Create the HTTP agent
163148
let agent = HttpAgent::builder().with_url(base_url).build()?;
164149

150+
let message = Message::new_user(
151+
"I need to organize a birthday party for my friend. Can you help me \
152+
create a plan? When you have created the plan, please fully execute it.",
153+
);
154+
165155
let subscriber = GenerativeUiSubscriber::new();
166156

167157
// Create run parameters for testing generative UI with planning
168-
let params = RunAgentParams {
169-
messages: vec![Message::User {
170-
id: MessageId::random(),
171-
content: "I need to organize a birthday party for my friend. Can you help me \
172-
create a plan? When you have created the plan, please fully execute it."
173-
.into(),
174-
name: None,
175-
}],
176-
forwarded_props: Some(JsonValue::Null),
177-
..Default::default()
178-
};
158+
// State & FwdProps types are defined by GenerativeUiSubscriber
159+
let params = RunAgentParams::new_typed().add_message(message);
179160

180161
info!("Starting generative UI agent run...");
181162
info!("Testing planning functionality with state snapshots and deltas");

rust-sdk/crates/ag-ui-client/examples/logging_subscriber.rs

Lines changed: 9 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,23 @@
11
use ag_ui_client::agent::{AgentError, AgentStateMutation, RunAgentParams};
2-
use ag_ui_client::http::HttpAgent;
3-
use ag_ui_client::subscriber::{AgentSubscriber, AgentSubscriberParams};
4-
use ag_ui_core::event::{
2+
use ag_ui_client::core::JsonValue;
3+
use ag_ui_client::core::event::{
54
CustomEvent, Event, MessagesSnapshotEvent, RawEvent, RunErrorEvent, RunFinishedEvent,
65
RunStartedEvent, StateDeltaEvent, StateSnapshotEvent, StepFinishedEvent, StepStartedEvent,
76
TextMessageChunkEvent, TextMessageContentEvent, TextMessageEndEvent, TextMessageStartEvent,
87
ThinkingEndEvent, ThinkingStartEvent, ThinkingTextMessageContentEvent,
98
ThinkingTextMessageEndEvent, ThinkingTextMessageStartEvent, ToolCallArgsEvent,
109
ToolCallChunkEvent, ToolCallEndEvent, ToolCallResultEvent, ToolCallStartEvent,
1110
};
12-
use ag_ui_core::{AgentState, FwdProps, JsonValue};
11+
use ag_ui_client::http::HttpAgent;
12+
use ag_ui_client::subscriber::{AgentSubscriber, AgentSubscriberParams};
1313
use async_trait::async_trait;
1414
use reqwest::Url;
15-
use reqwest::header::{HeaderMap, HeaderValue};
1615
use std::error::Error;
1716

1817
// Import our simple subscriber implementation
1918
use ag_ui_client::Agent;
20-
use ag_ui_core::types::ids::MessageId;
21-
use ag_ui_core::types::message::Message;
22-
use ag_ui_core::types::tool::ToolCall;
19+
use ag_ui_client::core::types::{Message, ToolCall};
20+
use ag_ui_client::core::{AgentState, FwdProps};
2321
use log::info;
2422
use std::collections::HashMap;
2523
use std::fmt::Debug;
@@ -40,18 +38,9 @@ async fn main() -> Result<(), Box<dyn Error>> {
4038
let subscriber = LoggingSubscriber::new(true);
4139

4240
// Create run parameters
43-
let params = RunAgentParams {
44-
run_id: None,
45-
tools: None,
46-
context: None,
47-
forwarded_props: Some(serde_json::json!({})),
48-
messages: vec![Message::User {
49-
id: MessageId::random(),
50-
content: "Can you give me the current temperature in New York?".into(),
51-
name: None,
52-
}],
53-
state: serde_json::json!({}),
54-
};
41+
let params = RunAgentParams::new().add_message(Message::new_user(
42+
"Can you give me the current temperature in New York?",
43+
));
5544

5645
info!("Running agent with simple subscriber...");
5746

0 commit comments

Comments
 (0)