Skip to content

Commit c19371a

Browse files
brettchien超渡法師
authored andcommitted
chore(acp): apply chaodu-agent NITs from PR #760
- pool.liveness_check_secs: hoist the recv-loop poll cadence out of a hard-coded const onto PoolConfig so deployments can tune it. Default remains 30s. - adapter: change hard-timeout error message from ({}m) to ({}s) so non-multiple-of-60 ceilings render correctly (e.g. 90s → "(90s)"). - acp/connection: emit a tracing::trace! line when an id-bearing message arrives whose pending entry was already abandoned. Behaviour is unchanged — the adapter recv loop still filters by request_id; this just makes the stale-response path observable at trace level. cargo check + cargo clippy -- -D warnings + cargo test --bin openab all clean (238 passed).
1 parent 1f5e488 commit c19371a

6 files changed

Lines changed: 26 additions & 7 deletions

File tree

config.toml.example

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,8 @@ max_sessions = 10
106106
session_ttl_hours = 24
107107
# Hard ceiling (sec) per prompt; see #732. Default: 1800 (30 min).
108108
# prompt_hard_timeout_secs = 1800
109+
# Liveness-check cadence (sec) for the recv loop; see #732. Default: 30.
110+
# liveness_check_secs = 30
109111

110112
[markdown]
111113
tables = "code" # "code" (default) | "bullets" | "off"

src/acp/connection.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use tokio::io::{AsyncBufReadExt, AsyncWriteExt, BufReader};
1010
use tokio::process::{Child, ChildStdin};
1111
use tokio::sync::{mpsc, oneshot, Mutex};
1212
use tokio::task::JoinHandle;
13-
use tracing::{debug, error, info};
13+
use tracing::{debug, error, info, trace};
1414

1515
/// Pick the most permissive selectable permission option from ACP options.
1616
fn pick_best_option(options: &[Value]) -> Option<String> {
@@ -319,6 +319,10 @@ impl AcpConnection {
319319
let _ = tx.send(msg);
320320
continue;
321321
}
322+
// Stale id (#732): pending was already abandoned. Falls through
323+
// to subscriber forwarding; the adapter recv loop filters by
324+
// request_id so it can't leak into the next prompt.
325+
trace!(request_id = id, "stale id-bearing message after abandon");
322326
}
323327

324328
// Notification → forward to subscriber

src/adapter.rs

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -153,16 +153,15 @@ pub trait ChatAdapter: Send + Sync + 'static {
153153

154154
// --- AdapterRouter ---
155155

156-
/// Polling cadence for the recv-loop liveness check (#732).
157-
const LIVENESS_CHECK_INTERVAL: std::time::Duration = std::time::Duration::from_secs(30);
158-
159156
/// Shared logic for routing messages to ACP agents, managing sessions,
160157
/// streaming edits, and controlling reactions. Platform-independent.
161158
pub struct AdapterRouter {
162159
pool: Arc<SessionPool>,
163160
reactions_config: ReactionsConfig,
164161
table_mode: TableMode,
165162
prompt_hard_timeout: std::time::Duration,
163+
/// Polling cadence for the recv-loop liveness check (#732).
164+
liveness_check_interval: std::time::Duration,
166165
}
167166

168167
impl AdapterRouter {
@@ -171,12 +170,14 @@ impl AdapterRouter {
171170
reactions_config: ReactionsConfig,
172171
table_mode: TableMode,
173172
prompt_hard_timeout_secs: u64,
173+
liveness_check_secs: u64,
174174
) -> Self {
175175
Self {
176176
pool,
177177
reactions_config,
178178
table_mode,
179179
prompt_hard_timeout: std::time::Duration::from_secs(prompt_hard_timeout_secs),
180+
liveness_check_interval: std::time::Duration::from_secs(liveness_check_secs),
180181
}
181182
}
182183

@@ -342,6 +343,7 @@ impl AdapterRouter {
342343
let table_mode = self.table_mode;
343344
let tool_display = self.reactions_config.tool_display;
344345
let prompt_hard_timeout = self.prompt_hard_timeout;
346+
let liveness_check_interval = self.liveness_check_interval;
345347

346348
self.pool
347349
.with_connection(thread_key, |conn| {
@@ -415,16 +417,16 @@ impl AdapterRouter {
415417
// Reader saw EOF and already drained pending; nothing to abandon.
416418
None => break,
417419
},
418-
_ = tokio::time::sleep(LIVENESS_CHECK_INTERVAL) => {
420+
_ = tokio::time::sleep(liveness_check_interval) => {
419421
if !conn.alive() {
420422
response_error = Some("Agent process died".into());
421423
conn.abandon_request(request_id).await;
422424
break;
423425
}
424426
if prompt_start.elapsed() > prompt_hard_timeout {
425427
response_error = Some(format!(
426-
"Agent exceeded hard timeout ({}m)",
427-
prompt_hard_timeout.as_secs() / 60,
428+
"Agent exceeded hard timeout ({}s)",
429+
prompt_hard_timeout.as_secs(),
428430
));
429431
conn.abandon_request(request_id).await;
430432
break;

src/config.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -319,6 +319,11 @@ pub struct PoolConfig {
319319
/// next prompt's subscriber.
320320
#[serde(default = "default_prompt_hard_timeout_secs")]
321321
pub prompt_hard_timeout_secs: u64,
322+
/// Polling cadence (seconds) for the recv-loop liveness check (#732).
323+
/// Lower = faster reaction to a dead agent / hard ceiling at the cost of
324+
/// more wakeups while the agent is streaming normally.
325+
#[serde(default = "default_liveness_check_secs")]
326+
pub liveness_check_secs: u64,
322327
}
323328

324329
#[derive(Debug, Clone, Deserialize)]
@@ -443,6 +448,9 @@ fn default_ttl_hours() -> u64 {
443448
pub(crate) fn default_prompt_hard_timeout_secs() -> u64 {
444449
30 * 60
445450
}
451+
pub(crate) fn default_liveness_check_secs() -> u64 {
452+
30
453+
}
446454
fn default_true() -> bool {
447455
true
448456
}
@@ -491,6 +499,7 @@ impl Default for PoolConfig {
491499
max_sessions: default_max_sessions(),
492500
session_ttl_hours: default_ttl_hours(),
493501
prompt_hard_timeout_secs: default_prompt_hard_timeout_secs(),
502+
liveness_check_secs: default_liveness_check_secs(),
494503
}
495504
}
496505
}

src/dispatch.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1073,6 +1073,7 @@ mod tests {
10731073
crate::config::ReactionsConfig::default(),
10741074
crate::markdown::TableMode::Off,
10751075
crate::config::default_prompt_hard_timeout_secs(),
1076+
crate::config::default_liveness_check_secs(),
10761077
));
10771078
Dispatcher::with_idle_timeout(router, 10, 24_000, grouping, DEFAULT_CONSUMER_IDLE_TIMEOUT)
10781079
}

src/main.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,7 @@ async fn main() -> anyhow::Result<()> {
148148
cfg.reactions,
149149
cfg.markdown.tables,
150150
cfg.pool.prompt_hard_timeout_secs,
151+
cfg.pool.liveness_check_secs,
151152
));
152153

153154
// Shutdown signal for Slack adapter

0 commit comments

Comments
 (0)