Skip to content

Commit 22010fb

Browse files
committed
test: fix tests previously broken with config.toml changes
1 parent 69186dd commit 22010fb

7 files changed

Lines changed: 175 additions & 94 deletions

File tree

src/channels/api.rs

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2425,8 +2425,12 @@ async fn handle_clarification_ticket_reply(
24252425
}
24262426
};
24272427
let Some(ticket) = ticket else {
2428-
return ApiError::new(StatusCode::NOT_FOUND, "not_found", "Unknown clarification ticket")
2429-
.into_response();
2428+
return ApiError::new(
2429+
StatusCode::NOT_FOUND,
2430+
"not_found",
2431+
"Unknown clarification ticket",
2432+
)
2433+
.into_response();
24302434
};
24312435

24322436
let (rtx, rrx) = oneshot::channel();
@@ -2445,7 +2449,10 @@ async fn handle_clarification_ticket_reply(
24452449
crate::bus::METADATA_SYNTHETIC_BACKGROUND_RESUME.to_string(),
24462450
Value::Bool(true),
24472451
);
2448-
metadata.insert("clarification_ticket_id".to_string(), Value::String(ticket_id));
2452+
metadata.insert(
2453+
"clarification_ticket_id".to_string(),
2454+
Value::String(ticket_id),
2455+
);
24492456
if let Err(e) = state
24502457
.bus_tx
24512458
.send(BusMessage::Inbound(InboundMessage {

src/config.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1387,7 +1387,7 @@ pub struct ApiConfig {
13871387
pub bind_address: Option<String>,
13881388
}
13891389

1390-
#[derive(Debug, Deserialize, Serialize, Clone)]
1390+
#[derive(Debug, Deserialize, Serialize, Clone, Default)]
13911391
pub struct ProviderConfig {
13921392
/// One of `KNOWN_PROVIDERS` (e.g. `"gemini"`, `"openai"`, `"deepseek"`, `"openrouter"`,
13931393
/// `"anthropic"`) or the `OPENAI_COMPATIBLE` sentinel for any third-party endpoint speaking
@@ -2113,8 +2113,8 @@ mod placeholder_key_tests {
21132113

21142114
fn provider_with_key(key: &str) -> ProviderConfig {
21152115
ProviderConfig {
2116-
provider_name: "deepseek".to_string(),
2117-
model_name: "deepseek-v4-pro".to_string(),
2116+
provider_name: "nonexistent-provider".to_string(),
2117+
model_name: "some-model".to_string(),
21182118
models: None,
21192119
api_key_env: "".to_string(),
21202120
api_key: Some(key.to_string()),

src/execution/local.rs

Lines changed: 28 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -532,7 +532,7 @@ impl ExecutionProvider for LocalExecutionProvider {
532532
}
533533

534534
let mode = self.pick_mode(&req).await?;
535-
535+
536536
if matches!(self.config.python_runtime, LocalPythonRuntime::UvManaged) {
537537
let _ = self.resolve_python_executable().await?;
538538
}
@@ -606,7 +606,7 @@ impl ExecutionProvider for LocalExecutionProvider {
606606

607607
let result: Result<RunResult, ExecutionError> = {
608608
let (mut cmd, stdin_body) = build_command(&session.mode, &spec.code)?;
609-
609+
610610
let mut has_local_venv = false;
611611
for ancestor in cwd.ancestors() {
612612
if ancestor.join(".venv").is_dir() {
@@ -629,7 +629,7 @@ impl ExecutionProvider for LocalExecutionProvider {
629629
}
630630
}
631631
}
632-
632+
633633
cmd.current_dir(&cwd);
634634
cmd.stdin(if stdin_body.is_some() {
635635
Stdio::piped()
@@ -666,11 +666,8 @@ impl ExecutionProvider for LocalExecutionProvider {
666666
}
667667

668668
let work = async move {
669-
match tokio::time::timeout(
670-
timeout,
671-
drain_child_pipes(child, max_each, stdin_body),
672-
)
673-
.await
669+
match tokio::time::timeout(timeout, drain_child_pipes(child, max_each, stdin_body))
670+
.await
674671
{
675672
Err(_) => {
676673
if let Some(p) = pid {
@@ -1063,7 +1060,6 @@ mod tests {
10631060
let _ = fs::remove_dir_all(&dir);
10641061
}
10651062

1066-
10671063
#[test]
10681064
fn uv_env_key_changes_with_python_or_requirements() {
10691065
let dir = temp_sandbox();
@@ -1172,7 +1168,10 @@ mod tests {
11721168
.unwrap();
11731169
// $PSVersionTable exists in PowerShell but not in CMD
11741170
let r = prov
1175-
.run(&h.id, RunSpec::new("if ($PSVersionTable) { echo 'ps-ok' }", 30))
1171+
.run(
1172+
&h.id,
1173+
RunSpec::new("if ($PSVersionTable) { echo 'ps-ok' }", 30),
1174+
)
11761175
.await
11771176
.unwrap();
11781177
assert!(r.stdout.contains("ps-ok"), "{r:?}");
@@ -1187,20 +1186,31 @@ mod tests {
11871186
fs::create_dir_all(&venv_dir).unwrap();
11881187
// Create a dummy file to simulate a real venv
11891188
fs::write(venv_dir.join("pyvenv.cfg"), "home = .").unwrap();
1190-
1189+
11911190
let mut cfg = LocalExecutionConfig::new(dir.clone(), dir.clone(), true);
11921191
cfg.python_runtime = LocalPythonRuntime::UvManaged;
11931192
let prov = LocalExecutionProvider::new(cfg).unwrap();
1194-
1195-
let h = prov.create_session(SessionCreateRequest::default()).await.unwrap();
1196-
1193+
1194+
let h = prov
1195+
.create_session(SessionCreateRequest::default())
1196+
.await
1197+
.unwrap();
1198+
11971199
// Use a command that prints the environment variable we inject
1198-
let code = if cfg!(windows) { "echo %UV_PROJECT_ENVIRONMENT%" } else { "echo $UV_PROJECT_ENVIRONMENT" };
1200+
let code = if cfg!(windows) {
1201+
"echo %UV_PROJECT_ENVIRONMENT%"
1202+
} else {
1203+
"echo $UV_PROJECT_ENVIRONMENT"
1204+
};
11991205
let r = prov.run(&h.id, RunSpec::new(code, 30)).await.unwrap();
1200-
1206+
12011207
// It should NOT contain the managed environment path because .venv exists
1202-
assert!(!r.stdout.contains(".system_generated"), "UV_PROJECT_ENVIRONMENT was injected despite local .venv: {}", r.stdout);
1203-
1208+
assert!(
1209+
!r.stdout.contains(".system_generated"),
1210+
"UV_PROJECT_ENVIRONMENT was injected despite local .venv: {}",
1211+
r.stdout
1212+
);
1213+
12041214
prov.close_session(&h.id).await.unwrap();
12051215
let _ = fs::remove_dir_all(&dir);
12061216
}

src/main.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,9 @@ use tokio::sync::{mpsc, watch, RwLock};
77
use clap::{Args as ClapArgs, Parser, Subcommand};
88
use colored::Colorize;
99
use isanagent::agent::{AgentLogic, AgentLogicParams};
10-
use isanagent::bus::{BusMessage, InboundMessage, LoggerControlMessage, OutboundMessage, TelemetryEvent};
10+
use isanagent::bus::{
11+
BusMessage, InboundMessage, LoggerControlMessage, OutboundMessage, TelemetryEvent,
12+
};
1113
use isanagent::channels::terminal::{
1214
build_agent_thought_terminal_notice, build_tool_call_terminal_notice,
1315
build_tool_progress_terminal_notice, build_tool_result_terminal_notice,
@@ -1116,7 +1118,8 @@ Enable [api], [slack], or [email] (with enabled = true) so the agent can receive
11161118
}
11171119
});
11181120

1119-
if workspace.config.background_jobs_enabled() && workspace.config.background_jobs_auto_resume() {
1121+
if workspace.config.background_jobs_enabled() && workspace.config.background_jobs_auto_resume()
1122+
{
11201123
recover_background_jobs_on_startup(&memory_node, &bus_tx, &global_outbound_tx).await;
11211124
}
11221125

src/memory.rs

Lines changed: 101 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -1545,10 +1545,15 @@ impl ActorLogic<MemoryMessage> for SqliteMemoryActor {
15451545
})();
15461546
let _ = reply.send(res);
15471547
}
1548-
MemoryMessage::ListBackgroundJobs { chat_id, limit, reply } => {
1548+
MemoryMessage::ListBackgroundJobs {
1549+
chat_id,
1550+
limit,
1551+
reply,
1552+
} => {
15491553
let res = (|| -> Result<Vec<BackgroundJobRecord>, String> {
15501554
let lim = limit.clamp(1, 500) as i64;
1551-
let sql_all = "SELECT job_id, kind, chat_id, channel, thread_id, state, payload_json,
1555+
let sql_all =
1556+
"SELECT job_id, kind, chat_id, channel, thread_id, state, payload_json,
15521557
resume_after_restart, detached, last_error, created_at_ms, updated_at_ms
15531558
FROM background_jobs ORDER BY updated_at_ms DESC LIMIT ?1";
15541559
let sql_chat = "SELECT job_id, kind, chat_id, channel, thread_id, state, payload_json,
@@ -1557,48 +1562,61 @@ impl ActorLogic<MemoryMessage> for SqliteMemoryActor {
15571562
let mut out = Vec::new();
15581563
if let Some(chat_id) = chat_id {
15591564
let mut stmt = self.conn.prepare(sql_chat).map_err(|e| e.to_string())?;
1560-
let rows = stmt.query_map(params![chat_id, lim], |row| {
1561-
Ok(BackgroundJobRecord {
1562-
job_id: row.get(0)?,
1563-
kind: row.get(1)?,
1564-
chat_id: row.get(2)?,
1565-
channel: row.get(3)?,
1566-
thread_id: row.get(4)?,
1567-
state: row.get(5)?,
1568-
payload_json: row.get(6)?,
1569-
resume_after_restart: row.get::<_, i64>(7)? != 0,
1570-
detached: row.get::<_, i64>(8)? != 0,
1571-
last_error: row.get(9)?,
1572-
created_at_ms: row.get(10)?,
1573-
updated_at_ms: row.get(11)?,
1565+
let rows = stmt
1566+
.query_map(params![chat_id, lim], |row| {
1567+
Ok(BackgroundJobRecord {
1568+
job_id: row.get(0)?,
1569+
kind: row.get(1)?,
1570+
chat_id: row.get(2)?,
1571+
channel: row.get(3)?,
1572+
thread_id: row.get(4)?,
1573+
state: row.get(5)?,
1574+
payload_json: row.get(6)?,
1575+
resume_after_restart: row.get::<_, i64>(7)? != 0,
1576+
detached: row.get::<_, i64>(8)? != 0,
1577+
last_error: row.get(9)?,
1578+
created_at_ms: row.get(10)?,
1579+
updated_at_ms: row.get(11)?,
1580+
})
15741581
})
1575-
}).map_err(|e| e.to_string())?;
1576-
for r in rows { out.push(r.map_err(|e| e.to_string())?); }
1582+
.map_err(|e| e.to_string())?;
1583+
for r in rows {
1584+
out.push(r.map_err(|e| e.to_string())?);
1585+
}
15771586
} else {
15781587
let mut stmt = self.conn.prepare(sql_all).map_err(|e| e.to_string())?;
1579-
let rows = stmt.query_map(params![lim], |row| {
1580-
Ok(BackgroundJobRecord {
1581-
job_id: row.get(0)?,
1582-
kind: row.get(1)?,
1583-
chat_id: row.get(2)?,
1584-
channel: row.get(3)?,
1585-
thread_id: row.get(4)?,
1586-
state: row.get(5)?,
1587-
payload_json: row.get(6)?,
1588-
resume_after_restart: row.get::<_, i64>(7)? != 0,
1589-
detached: row.get::<_, i64>(8)? != 0,
1590-
last_error: row.get(9)?,
1591-
created_at_ms: row.get(10)?,
1592-
updated_at_ms: row.get(11)?,
1588+
let rows = stmt
1589+
.query_map(params![lim], |row| {
1590+
Ok(BackgroundJobRecord {
1591+
job_id: row.get(0)?,
1592+
kind: row.get(1)?,
1593+
chat_id: row.get(2)?,
1594+
channel: row.get(3)?,
1595+
thread_id: row.get(4)?,
1596+
state: row.get(5)?,
1597+
payload_json: row.get(6)?,
1598+
resume_after_restart: row.get::<_, i64>(7)? != 0,
1599+
detached: row.get::<_, i64>(8)? != 0,
1600+
last_error: row.get(9)?,
1601+
created_at_ms: row.get(10)?,
1602+
updated_at_ms: row.get(11)?,
1603+
})
15931604
})
1594-
}).map_err(|e| e.to_string())?;
1595-
for r in rows { out.push(r.map_err(|e| e.to_string())?); }
1605+
.map_err(|e| e.to_string())?;
1606+
for r in rows {
1607+
out.push(r.map_err(|e| e.to_string())?);
1608+
}
15961609
}
15971610
Ok(out)
15981611
})();
15991612
let _ = reply.send(res);
16001613
}
1601-
MemoryMessage::UpdateBackgroundJobState { job_id, state, last_error, reply } => {
1614+
MemoryMessage::UpdateBackgroundJobState {
1615+
job_id,
1616+
state,
1617+
last_error,
1618+
reply,
1619+
} => {
16021620
let res = (|| -> Result<(), String> {
16031621
let now = Utc::now().timestamp_millis();
16041622
self.conn.execute(
@@ -1623,7 +1641,12 @@ impl ActorLogic<MemoryMessage> for SqliteMemoryActor {
16231641
).map_err(|e| format!("insert notifications: {}", e)).map(|_| ());
16241642
let _ = reply.send(res);
16251643
}
1626-
MemoryMessage::ListNotifications { chat_id, limit, unseen_only, reply } => {
1644+
MemoryMessage::ListNotifications {
1645+
chat_id,
1646+
limit,
1647+
unseen_only,
1648+
reply,
1649+
} => {
16271650
let res = (|| -> Result<Vec<NotificationRecord>, String> {
16281651
let lim = limit.clamp(1, 500) as i64;
16291652
let mut out = Vec::new();
@@ -1633,44 +1656,59 @@ impl ActorLogic<MemoryMessage> for SqliteMemoryActor {
16331656
(false, true) => "SELECT notification_id, chat_id, channel, thread_id, kind, title, body, action_kind, action_payload, seen_at_ms, resolved_at_ms, created_at_ms FROM notifications WHERE seen_at_ms IS NULL ORDER BY created_at_ms DESC LIMIT ?1",
16341657
(false, false) => "SELECT notification_id, chat_id, channel, thread_id, kind, title, body, action_kind, action_payload, seen_at_ms, resolved_at_ms, created_at_ms FROM notifications ORDER BY created_at_ms DESC LIMIT ?1",
16351658
};
1636-
let mapper = |row: &rusqlite::Row| -> Result<NotificationRecord, rusqlite::Error> {
1637-
Ok(NotificationRecord {
1638-
notification_id: row.get(0)?,
1639-
chat_id: row.get(1)?,
1640-
channel: row.get(2)?,
1641-
thread_id: row.get(3)?,
1642-
kind: row.get(4)?,
1643-
title: row.get(5)?,
1644-
body: row.get(6)?,
1645-
action_kind: row.get(7)?,
1646-
action_payload: row.get(8)?,
1647-
seen_at_ms: row.get(9)?,
1648-
resolved_at_ms: row.get(10)?,
1649-
created_at_ms: row.get(11)?,
1650-
})
1651-
};
1659+
let mapper =
1660+
|row: &rusqlite::Row| -> Result<NotificationRecord, rusqlite::Error> {
1661+
Ok(NotificationRecord {
1662+
notification_id: row.get(0)?,
1663+
chat_id: row.get(1)?,
1664+
channel: row.get(2)?,
1665+
thread_id: row.get(3)?,
1666+
kind: row.get(4)?,
1667+
title: row.get(5)?,
1668+
body: row.get(6)?,
1669+
action_kind: row.get(7)?,
1670+
action_payload: row.get(8)?,
1671+
seen_at_ms: row.get(9)?,
1672+
resolved_at_ms: row.get(10)?,
1673+
created_at_ms: row.get(11)?,
1674+
})
1675+
};
16521676
if let Some(chat_id) = chat_id {
16531677
let mut stmt = self.conn.prepare(sql).map_err(|e| e.to_string())?;
1654-
let rows = stmt.query_map(params![chat_id, lim], mapper).map_err(|e| e.to_string())?;
1655-
for r in rows { out.push(r.map_err(|e| e.to_string())?); }
1678+
let rows = stmt
1679+
.query_map(params![chat_id, lim], mapper)
1680+
.map_err(|e| e.to_string())?;
1681+
for r in rows {
1682+
out.push(r.map_err(|e| e.to_string())?);
1683+
}
16561684
} else {
16571685
let mut stmt = self.conn.prepare(sql).map_err(|e| e.to_string())?;
1658-
let rows = stmt.query_map(params![lim], mapper).map_err(|e| e.to_string())?;
1659-
for r in rows { out.push(r.map_err(|e| e.to_string())?); }
1686+
let rows = stmt
1687+
.query_map(params![lim], mapper)
1688+
.map_err(|e| e.to_string())?;
1689+
for r in rows {
1690+
out.push(r.map_err(|e| e.to_string())?);
1691+
}
16601692
}
16611693
Ok(out)
16621694
})();
16631695
let _ = reply.send(res);
16641696
}
1665-
MemoryMessage::MarkNotificationSeen { notification_id, reply } => {
1697+
MemoryMessage::MarkNotificationSeen {
1698+
notification_id,
1699+
reply,
1700+
} => {
16661701
let now = Utc::now().timestamp_millis();
16671702
let res = self.conn.execute(
16681703
"UPDATE notifications SET seen_at_ms = COALESCE(seen_at_ms, ?1) WHERE notification_id = ?2",
16691704
params![now, notification_id],
16701705
).map_err(|e| format!("mark notification seen: {}", e)).map(|_| ());
16711706
let _ = reply.send(res);
16721707
}
1673-
MemoryMessage::ResolveNotification { notification_id, reply } => {
1708+
MemoryMessage::ResolveNotification {
1709+
notification_id,
1710+
reply,
1711+
} => {
16741712
let now = Utc::now().timestamp_millis();
16751713
let res = self.conn.execute(
16761714
"UPDATE notifications SET resolved_at_ms = COALESCE(resolved_at_ms, ?1) WHERE notification_id = ?2",
@@ -1693,7 +1731,11 @@ impl ActorLogic<MemoryMessage> for SqliteMemoryActor {
16931731
).map_err(|e| format!("upsert clarification_tickets: {}", e)).map(|_| ());
16941732
let _ = reply.send(res);
16951733
}
1696-
MemoryMessage::ResolveClarificationTicket { ticket_id, response, reply } => {
1734+
MemoryMessage::ResolveClarificationTicket {
1735+
ticket_id,
1736+
response,
1737+
reply,
1738+
} => {
16971739
let now = Utc::now().timestamp_millis();
16981740
let res = self.conn.execute(
16991741
"UPDATE clarification_tickets SET response = ?1, status = 'answered', updated_at_ms = ?2 WHERE ticket_id = ?3",

0 commit comments

Comments
 (0)