Skip to content

Commit f3d1b8b

Browse files
committed
first hook test without verification
1 parent 4e7974b commit f3d1b8b

File tree

4 files changed

+100
-1
lines changed

4 files changed

+100
-1
lines changed

crates/agent/tests/common/mod.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,19 @@ impl TestCase {
164164
&self.sent_requests
165165
}
166166

167+
pub async fn wait_until_agent_initializes(&mut self, timeout: Duration) {
168+
let timeout_at = Instant::now() + timeout;
169+
loop {
170+
let evt = tokio::time::timeout_at(timeout_at.into(), self.recv_agent_event())
171+
.await
172+
.expect("timed out");
173+
match &evt {
174+
AgentEvent::Initialized => break,
175+
_ => (),
176+
}
177+
}
178+
}
179+
167180
pub async fn wait_until_agent_stop(&mut self, timeout: Duration) {
168181
let timeout_at = Instant::now() + timeout;
169182
loop {
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
{"result":"ok","messageStart":{"role":"assistant"}}
2+
{"result":"ok","contentBlockDelta":{"delta":{"text":"Hello"},"contentBlockIndex":null}}
3+
{"result":"ok","contentBlockDelta":{"delta":{"text":"! I'm Amazon"},"contentBlockIndex":null}}
4+
{"result":"ok","contentBlockDelta":{"delta":{"text":" Q"},"contentBlockIndex":null}}
5+
{"result":"ok","contentBlockDelta":{"delta":{"text":", an"},"contentBlockIndex":null}}
6+
{"result":"ok","contentBlockDelta":{"delta":{"text":" AI assistant built"},"contentBlockIndex":null}}
7+
{"result":"ok","contentBlockDelta":{"delta":{"text":" by AWS"},"contentBlockIndex":null}}
8+
{"result":"ok","contentBlockDelta":{"delta":{"text":". I'm here to"},"contentBlockIndex":null}}
9+
{"result":"ok","contentBlockDelta":{"delta":{"text":" help you with AWS"},"contentBlockIndex":null}}
10+
{"result":"ok","contentBlockDelta":{"delta":{"text":" services"},"contentBlockIndex":null}}
11+
{"result":"ok","contentBlockDelta":{"delta":{"text":", software"},"contentBlockIndex":null}}
12+
{"result":"ok","contentBlockDelta":{"delta":{"text":" development, infrastructure"},"contentBlockIndex":null}}
13+
{"result":"ok","contentBlockDelta":{"delta":{"text":", and system"},"contentBlockIndex":null}}
14+
{"result":"ok","contentBlockDelta":{"delta":{"text":" administration tasks"},"contentBlockIndex":null}}
15+
{"result":"ok","contentBlockDelta":{"delta":{"text":"."},"contentBlockIndex":null}}
16+
{"result":"ok","contentBlockDelta":{"delta":{"text":" \n\nWhat"},"contentBlockIndex":null}}
17+
{"result":"ok","contentBlockDelta":{"delta":{"text":" can I help"},"contentBlockIndex":null}}
18+
{"result":"ok","contentBlockDelta":{"delta":{"text":" you with today?"},"contentBlockIndex":null}}
19+
{"result":"ok","messageStop":{"stopReason":"endTurn"}}
20+
{"result":"ok","metadata":{"metrics":{"requestStartTime":"2025-11-04T00:44:30.186448Z","requestEndTime":"2025-11-04T00:44:32.273193Z","timeToFirstChunk":{"secs":2,"nanos":20987458},"timeBetweenChunks":[{"secs":0,"nanos":341542},{"secs":0,"nanos":211875},{"secs":0,"nanos":66500},{"secs":0,"nanos":101291},{"secs":0,"nanos":54459},{"secs":0,"nanos":90250},{"secs":0,"nanos":160875},{"secs":0,"nanos":137292},{"secs":0,"nanos":47357041},{"secs":0,"nanos":138042},{"secs":0,"nanos":662833},{"secs":0,"nanos":14983000},{"secs":0,"nanos":246042},{"secs":0,"nanos":57667},{"secs":0,"nanos":243500},{"secs":0,"nanos":62292},{"secs":0,"nanos":33791},{"secs":0,"nanos":30750},{"secs":0,"nanos":9292},{"secs":0,"nanos":750}],"responseStreamLen":195},"usage":null,"service":{"requestId":"5d05238c-e41c-4c0f-94a4-ab7ddcd4a880","statusCode":null}}}
21+
22+
{"result":"ok","messageStart":{"role":"assistant"}}
23+
{"result":"ok","contentBlockDelta":{"delta":{"text":"Goodbye! Feel"},"contentBlockIndex":null}}
24+
{"result":"ok","contentBlockDelta":{"delta":{"text":" free to come"},"contentBlockIndex":null}}
25+
{"result":"ok","contentBlockDelta":{"delta":{"text":" back anytime if"},"contentBlockIndex":null}}
26+
{"result":"ok","contentBlockDelta":{"delta":{"text":" you need help with AWS"},"contentBlockIndex":null}}
27+
{"result":"ok","contentBlockDelta":{"delta":{"text":","},"contentBlockIndex":null}}
28+
{"result":"ok","contentBlockDelta":{"delta":{"text":" coding"},"contentBlockIndex":null}}
29+
{"result":"ok","contentBlockDelta":{"delta":{"text":", or system"},"contentBlockIndex":null}}
30+
{"result":"ok","contentBlockDelta":{"delta":{"text":" administration tasks"},"contentBlockIndex":null}}
31+
{"result":"ok","contentBlockDelta":{"delta":{"text":"."},"contentBlockIndex":null}}
32+
{"result":"ok","messageStop":{"stopReason":"endTurn"}}
33+
{"result":"ok","metadata":{"metrics":{"requestStartTime":"2025-11-04T00:44:34.096012Z","requestEndTime":"2025-11-04T00:44:36.149234Z","timeToFirstChunk":{"secs":2,"nanos":26682459},"timeBetweenChunks":[{"secs":0,"nanos":277500},{"secs":0,"nanos":191416},{"secs":0,"nanos":45791},{"secs":0,"nanos":35875},{"secs":0,"nanos":38708},{"secs":0,"nanos":376417},{"secs":0,"nanos":80500},{"secs":0,"nanos":32375},{"secs":0,"nanos":33458},{"secs":0,"nanos":50375},{"secs":0,"nanos":24768792},{"secs":0,"nanos":5042}],"responseStreamLen":106},"usage":null,"service":{"requestId":"d66155e6-4641-4795-92a6-021fbe5ff5c7","statusCode":null}}}

crates/agent/tests/mod.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,9 +49,11 @@ async fn test_agent_defaults() {
4949
.build()
5050
.await
5151
.unwrap();
52+
53+
test.wait_until_agent_initializes(Duration::from_millis(100)).await;
5254

5355
test.send_prompt("start turn".to_string()).await;
54-
56+
5557
test.wait_until_agent_stop(Duration::from_secs(2)).await;
5658

5759
for req in test.requests() {

crates/agent/tests/test_hooks.rs

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
mod common;
2+
3+
use agent::agent_config::definitions::*;
4+
use common::*;
5+
use std::collections::HashMap;
6+
use std::time::Duration;
7+
use tracing::info;
8+
9+
#[tokio::test]
10+
async fn test_agent_spawn_hook() {
11+
let _ = tracing_subscriber::fmt::try_init();
12+
// creates the agent config with the agent spawn hook
13+
let mut hooks = HashMap::new();
14+
hooks.insert(
15+
HookTrigger::AgentSpawn,
16+
vec![HookConfig::ShellCommand(CommandHook {
17+
command: "echo 'Agent initialized'".to_string(),
18+
opts: BaseHookConfig {
19+
timeout_ms: 5000,
20+
max_output_size: 1024,
21+
cache_ttl_seconds: 0,
22+
matcher: None,
23+
},
24+
})],
25+
);
26+
27+
let agent_config = AgentConfig::V2025_08_22(AgentConfigV2025_08_22 {
28+
hooks,
29+
..Default::default()
30+
});
31+
let mut test: TestCase = TestCase::builder()
32+
.test_name("agent spawn hook behavior")
33+
.with_agent_config(agent_config)
34+
.with_responses(
35+
parse_response_streams(include_str!("./mock_responses/simple_two_turn.jsonl"))
36+
.await
37+
.unwrap(),
38+
)
39+
.build()
40+
.await
41+
.unwrap();
42+
43+
test.wait_until_agent_initializes(Duration::from_millis(500)).await;
44+
test.send_prompt("hello".to_string()).await;
45+
info!("before stop");
46+
test.wait_until_agent_stop(Duration::from_secs(10)).await;
47+
info!("after stop");
48+
for (i, req) in test.requests().iter().enumerate() {
49+
info!("Request {}: {:#?}", i, req);
50+
}
51+
}

0 commit comments

Comments
 (0)