Skip to content

Commit 3cdc314

Browse files
fix(acp-runner): apply CodeRabbit inline findings
- prompt_converter: include cache_creation_tokens and cache_read_tokens in UsageUpdate context window calculation - rpc_server: return error replies and early-return on store failures in handle_new_session, handle_set_session_mode, handle_set_session_model, and handle_fork_session; move new_id UUID generation after successful load - connect_integration: use get_host() for container host (supports remote/ rootless Docker), fix NKey seed to valid 58-char canonical format Signed-off-by: Jorge <jramirezhdez02@gmail.com>
1 parent 08b91eb commit 3cdc314

3 files changed

Lines changed: 86 additions & 47 deletions

File tree

rsworkspace/crates/trogon-acp-runner/src/prompt_converter.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,11 +93,15 @@ impl PromptEventConverter {
9393

9494
PromptEvent::UsageUpdate {
9595
input_tokens,
96+
cache_creation_tokens,
97+
cache_read_tokens,
9698
output_tokens,
9799
context_window,
98100
..
99101
} => {
100-
let used = (input_tokens + output_tokens) as u64;
102+
let used =
103+
(input_tokens + cache_creation_tokens + cache_read_tokens + output_tokens)
104+
as u64;
101105
let size = context_window.unwrap_or(DEFAULT_CONTEXT_WINDOW);
102106
let notif = self.notif(SessionUpdate::UsageUpdate(UsageUpdate::new(used, size)));
103107
(vec![notif], None)

rsworkspace/crates/trogon-acp-runner/src/rpc_server.rs

Lines changed: 60 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -282,6 +282,12 @@ impl RpcServer {
282282

283283
if let Err(e) = self.store.save(&session_id, &state).await {
284284
warn!(session_id = %session_id, error = %e, "rpc: failed to save new session");
285+
self.reply(
286+
&msg,
287+
&serde_json::json!({ "error": format!("failed to save session: {e}") }),
288+
)
289+
.await;
290+
return;
285291
}
286292

287293
self.publish_session_ready(&session_id).await;
@@ -322,17 +328,28 @@ impl RpcServer {
322328
};
323329

324330
let session_id = request.session_id.to_string();
325-
match self.store.load(&session_id).await {
326-
Ok(mut state) => {
327-
state.mode = request.mode_id.to_string();
328-
state.updated_at = now_iso8601();
329-
if let Err(e) = self.store.save(&session_id, &state).await {
330-
warn!(session_id = %session_id, error = %e, "rpc: failed to persist mode update");
331-
}
332-
}
331+
let mut state = match self.store.load(&session_id).await {
332+
Ok(s) => s,
333333
Err(e) => {
334334
warn!(session_id = %session_id, error = %e, "rpc: failed to load session for mode update");
335+
self.reply(
336+
&msg,
337+
&serde_json::json!({ "error": format!("failed to load session: {e}") }),
338+
)
339+
.await;
340+
return;
335341
}
342+
};
343+
state.mode = request.mode_id.to_string();
344+
state.updated_at = now_iso8601();
345+
if let Err(e) = self.store.save(&session_id, &state).await {
346+
warn!(session_id = %session_id, error = %e, "rpc: failed to persist mode update");
347+
self.reply(
348+
&msg,
349+
&serde_json::json!({ "error": format!("failed to save session: {e}") }),
350+
)
351+
.await;
352+
return;
336353
}
337354

338355
self.reply(&msg, &SetSessionModeResponse::new()).await;
@@ -349,17 +366,28 @@ impl RpcServer {
349366
};
350367

351368
let session_id = request.session_id.to_string();
352-
match self.store.load(&session_id).await {
353-
Ok(mut state) => {
354-
state.model = Some(request.model_id.to_string());
355-
state.updated_at = now_iso8601();
356-
if let Err(e) = self.store.save(&session_id, &state).await {
357-
warn!(session_id = %session_id, error = %e, "rpc: failed to persist model update");
358-
}
359-
}
369+
let mut state = match self.store.load(&session_id).await {
370+
Ok(s) => s,
360371
Err(e) => {
361372
warn!(session_id = %session_id, error = %e, "rpc: failed to load session for model update");
373+
self.reply(
374+
&msg,
375+
&serde_json::json!({ "error": format!("failed to load session: {e}") }),
376+
)
377+
.await;
378+
return;
362379
}
380+
};
381+
state.model = Some(request.model_id.to_string());
382+
state.updated_at = now_iso8601();
383+
if let Err(e) = self.store.save(&session_id, &state).await {
384+
warn!(session_id = %session_id, error = %e, "rpc: failed to persist model update");
385+
self.reply(
386+
&msg,
387+
&serde_json::json!({ "error": format!("failed to save session: {e}") }),
388+
)
389+
.await;
390+
return;
363391
}
364392

365393
self.reply(&msg, &SetSessionModelResponse::new()).await;
@@ -429,20 +457,26 @@ impl RpcServer {
429457
};
430458

431459
let source_id = request.session_id.to_string();
432-
let new_id = uuid::Uuid::new_v4().to_string();
433460

434-
match self.store.load(&source_id).await {
435-
Ok(mut state) => {
436-
let now = now_iso8601();
437-
state.created_at = now.clone();
438-
state.updated_at = now;
439-
if let Err(e) = self.store.save(&new_id, &state).await {
440-
warn!(new_id = %new_id, error = %e, "rpc: failed to save forked session");
441-
}
442-
}
461+
let mut state = match self.store.load(&source_id).await {
462+
Ok(s) => s,
443463
Err(e) => {
444464
warn!(source_id = %source_id, error = %e, "rpc: failed to load source session for fork");
465+
self.reply(
466+
&msg,
467+
&serde_json::json!({ "error": format!("failed to load source session: {e}") }),
468+
)
469+
.await;
470+
return;
445471
}
472+
};
473+
474+
let new_id = uuid::Uuid::new_v4().to_string();
475+
let now = now_iso8601();
476+
state.created_at = now.clone();
477+
state.updated_at = now;
478+
if let Err(e) = self.store.save(&new_id, &state).await {
479+
warn!(new_id = %new_id, error = %e, "rpc: failed to save forked session");
446480
}
447481

448482
self.reply(&msg, &ForkSessionResponse::new(new_id)).await;

rsworkspace/crates/trogon-nats/tests/connect_integration.rs

Lines changed: 21 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -15,20 +15,21 @@ use testcontainers_modules::testcontainers::runners::AsyncRunner;
1515
use trogon_nats::auth::{NatsAuth, NatsConfig};
1616
use trogon_nats::connect::{ConnectError, connect};
1717

18-
async fn start_nats() -> Result<(ContainerAsync<Nats>, u16), Box<dyn std::error::Error>> {
18+
async fn start_nats() -> Result<(ContainerAsync<Nats>, String, u16), Box<dyn std::error::Error>> {
1919
let container = Nats::default().start().await?;
20+
let host = container.get_host().await?.to_string();
2021
let port = container.get_host_port_ipv4(4222).await?;
21-
Ok((container, port))
22+
Ok((container, host, port))
2223
}
2324

2425
/// Covers the `NatsAuth::None` arm (lines 123-128) and the success branch (130-138).
2526
/// Also exercises `apply_reconnect_options` (lines 69-74) indirectly.
2627
#[tokio::test]
2728
#[ignore = "requires Docker"]
2829
async fn connect_with_no_auth_succeeds() -> Result<(), Box<dyn std::error::Error>> {
29-
let (_container, port) = start_nats().await?;
30+
let (_container, host, port) = start_nats().await?;
3031

31-
let config = NatsConfig::new(vec![format!("nats://127.0.0.1:{port}")], NatsAuth::None);
32+
let config = NatsConfig::new(vec![format!("nats://{host}:{port}")], NatsAuth::None);
3233

3334
connect(&config, Duration::from_secs(10))
3435
.await
@@ -42,10 +43,10 @@ async fn connect_with_no_auth_succeeds() -> Result<(), Box<dyn std::error::Error
4243
async fn connect_with_token_auth_succeeds_on_open_server() -> Result<(), Box<dyn std::error::Error>>
4344
{
4445
// An open NATS server accepts any token — the token is just passed through.
45-
let (_container, port) = start_nats().await?;
46+
let (_container, host, port) = start_nats().await?;
4647

4748
let config = NatsConfig::new(
48-
vec![format!("nats://127.0.0.1:{port}")],
49+
vec![format!("nats://{host}:{port}")],
4950
NatsAuth::Token("any-token".to_string()),
5051
);
5152

@@ -60,10 +61,10 @@ async fn connect_with_token_auth_succeeds_on_open_server() -> Result<(), Box<dyn
6061
#[ignore = "requires Docker"]
6162
async fn connect_with_user_password_succeeds_on_open_server()
6263
-> Result<(), Box<dyn std::error::Error>> {
63-
let (_container, port) = start_nats().await?;
64+
let (_container, host, port) = start_nats().await?;
6465

6566
let config = NatsConfig::new(
66-
vec![format!("nats://127.0.0.1:{port}")],
67+
vec![format!("nats://{host}:{port}")],
6768
NatsAuth::UserPassword {
6869
user: "user".to_string(),
6970
password: "pass".to_string(),
@@ -84,17 +85,15 @@ async fn connect_with_user_password_succeeds_on_open_server()
8485
#[tokio::test]
8586
#[ignore = "requires Docker"]
8687
async fn connect_with_nkey_auth_on_open_server() -> Result<(), Box<dyn std::error::Error>> {
87-
let (_container, port) = start_nats().await?;
88+
let (_container, host, port) = start_nats().await?;
8889

89-
// A valid NKey user seed (base32-encoded, 58-char canonical format).
90-
// On an open server the key is not validated — the test simply exercises
91-
// the `NatsAuth::NKey` branch in `connect()`.
92-
let seed = "SUACSSL3UAHUDXKFSNVUZRF5UHPMWZ6BFDTJ7M6USDRCRBZLYKI4LZPFZFR".to_string();
90+
// A valid NKey user seed (base32-encoded, 58-char canonical format,
91+
// starts with "SU"). On an open server the key is not validated against
92+
// a registered user — the test simply exercises the `NatsAuth::NKey`
93+
// branch in `connect()`.
94+
let seed = "SUANQDPB2RUOE4ETUA26CNX7FUKE5ZZKFCQIIW63OX225F2CO7UEXTM7ZY".to_string();
9395

94-
let config = NatsConfig::new(
95-
vec![format!("nats://127.0.0.1:{port}")],
96-
NatsAuth::NKey(seed),
97-
);
96+
let config = NatsConfig::new(vec![format!("nats://{host}:{port}")], NatsAuth::NKey(seed));
9897

9998
let result = connect(&config, Duration::from_secs(10)).await;
10099
assert!(
@@ -134,10 +133,11 @@ async fn connect_with_wrong_token_returns_authorization_violation()
134133
.with_cmd(["--auth", "correct-token"])
135134
.start()
136135
.await?;
136+
let host = container.get_host().await?.to_string();
137137
let port = container.get_host_port_ipv4(4222).await?;
138138

139139
let config = NatsConfig::new(
140-
vec![format!("nats://127.0.0.1:{port}")],
140+
vec![format!("nats://{host}:{port}")],
141141
NatsAuth::Token("wrong-token".to_string()),
142142
);
143143

@@ -160,10 +160,11 @@ async fn connect_with_correct_token_succeeds() -> Result<(), Box<dyn std::error:
160160
.with_cmd(["--auth", "correct-token"])
161161
.start()
162162
.await?;
163+
let host = container.get_host().await?.to_string();
163164
let port = container.get_host_port_ipv4(4222).await?;
164165

165166
let config = NatsConfig::new(
166-
vec![format!("nats://127.0.0.1:{port}")],
167+
vec![format!("nats://{host}:{port}")],
167168
NatsAuth::Token("correct-token".to_string()),
168169
);
169170

@@ -190,7 +191,7 @@ async fn connect_to_unreachable_server_returns_ok_with_background_retry() {
190191
let port = listener.local_addr().unwrap().port();
191192
drop(listener);
192193

193-
let config = NatsConfig::new(vec![format!("nats://127.0.0.1:{port}")], NatsAuth::None);
194+
let config = NatsConfig::new(vec![format!("nats://{host}:{port}")], NatsAuth::None);
194195

195196
// connect() must return within a few seconds (INITIAL_CONNECT_CHECK_SECS + margin).
196197
let result = tokio::time::timeout(

0 commit comments

Comments
 (0)