fix: rust 1.95.0 clippy lints and matrix-sdk 0.17 API changes
Toolchain bump surfaced new lints (derivable_impls, unnecessary_unwrap, unnecessary_sort_by, while_let_loop, collapsible_match, unnecessary_option_map_or_else, cmp_owned) across bft-json-crdt and huskies-server. All fixed mechanically. Cargo.toml: dropped the no-longer-existing `rustls-tls` matrix-sdk feature, then chased through the 0.17 API breakage: - Relation::Reply is now a tuple variant wrapping Reply, not a struct variant with `in_reply_to` - UserIdentifier::UserIdOrLocalpart removed — use UserIdentifier::Matrix(MatrixUserIdentifier::new(..)) - SendMessageLikeEventResult no longer exposes event_id directly; it's now on the inner `response` field Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -135,7 +135,7 @@ fn loc_top_n(project_root: &std::path::Path, top_n: usize) -> String {
|
||||
})
|
||||
.collect();
|
||||
|
||||
files.sort_by(|a, b| b.0.cmp(&a.0));
|
||||
files.sort_by_key(|b| std::cmp::Reverse(b.0));
|
||||
files.truncate(top_n);
|
||||
|
||||
if files.is_empty() {
|
||||
|
||||
@@ -61,7 +61,7 @@ pub(super) async fn is_reply_to_bot(
|
||||
bot_sent_event_ids: &TokioMutex<HashSet<OwnedEventId>>,
|
||||
) -> bool {
|
||||
let candidate_ids: Vec<&OwnedEventId> = match relates_to {
|
||||
Some(Relation::Reply { in_reply_to }) => vec![&in_reply_to.event_id],
|
||||
Some(Relation::Reply(reply)) => vec![&reply.in_reply_to.event_id],
|
||||
Some(Relation::Thread(thread)) => {
|
||||
let mut ids = vec![&thread.event_id];
|
||||
if let Some(irti) = &thread.in_reply_to {
|
||||
@@ -216,8 +216,9 @@ mod tests {
|
||||
sent.lock().await.insert(event_id.clone());
|
||||
|
||||
let in_reply_to = matrix_sdk::ruma::events::relation::InReplyTo::new(event_id);
|
||||
let relates_to: Option<Relation<RoomMessageEventContentWithoutRelation>> =
|
||||
Some(Relation::Reply { in_reply_to });
|
||||
let relates_to: Option<Relation<RoomMessageEventContentWithoutRelation>> = Some(
|
||||
Relation::Reply(matrix_sdk::ruma::events::relation::Reply::new(in_reply_to)),
|
||||
);
|
||||
|
||||
assert!(is_reply_to_bot(relates_to.as_ref(), &sent).await);
|
||||
}
|
||||
@@ -231,8 +232,9 @@ mod tests {
|
||||
let in_reply_to = matrix_sdk::ruma::events::relation::InReplyTo::new(
|
||||
"$other:example.com".parse::<OwnedEventId>().unwrap(),
|
||||
);
|
||||
let relates_to: Option<Relation<RoomMessageEventContentWithoutRelation>> =
|
||||
Some(Relation::Reply { in_reply_to });
|
||||
let relates_to: Option<Relation<RoomMessageEventContentWithoutRelation>> = Some(
|
||||
Relation::Reply(matrix_sdk::ruma::events::relation::Reply::new(in_reply_to)),
|
||||
);
|
||||
|
||||
assert!(!is_reply_to_bot(relates_to.as_ref(), &sent).await);
|
||||
}
|
||||
|
||||
@@ -92,7 +92,9 @@ pub async fn run_bot(
|
||||
{
|
||||
use matrix_sdk::ruma::api::client::uiaa;
|
||||
let password_auth = uiaa::AuthData::Password(uiaa::Password::new(
|
||||
uiaa::UserIdentifier::UserIdOrLocalpart(config.username.clone().unwrap_or_default()),
|
||||
uiaa::UserIdentifier::Matrix(uiaa::MatrixUserIdentifier::new(
|
||||
config.username.clone().unwrap_or_default(),
|
||||
)),
|
||||
config.password.clone().unwrap_or_default(),
|
||||
));
|
||||
if let Err(e) = client
|
||||
|
||||
@@ -48,7 +48,7 @@ impl ChatTransport for MatrixTransport {
|
||||
.await
|
||||
.map_err(|e| format!("Matrix send error: {e}"))?;
|
||||
|
||||
Ok(resp.event_id.to_string())
|
||||
Ok(resp.response.event_id.to_string())
|
||||
}
|
||||
|
||||
async fn edit_message(
|
||||
|
||||
@@ -156,10 +156,7 @@ fn is_inside_code_fence(text: &str) -> bool {
|
||||
pub fn drain_complete_paragraphs(buffer: &mut String) -> Vec<String> {
|
||||
let mut paragraphs = Vec::new();
|
||||
let mut search_from = 0;
|
||||
loop {
|
||||
let Some(pos) = buffer[search_from..].find("\n\n") else {
|
||||
break;
|
||||
};
|
||||
while let Some(pos) = buffer[search_from..].find("\n\n") {
|
||||
let abs_pos = search_from + pos;
|
||||
// Only split at this boundary when we are NOT inside a code fence.
|
||||
if is_inside_code_fence(&buffer[..abs_pos]) {
|
||||
|
||||
+2
-3
@@ -200,6 +200,7 @@ pub(crate) fn resolve_path_arg(path_str: Option<&str>, cwd: &std::path::Path) ->
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use std::path::Path;
|
||||
|
||||
#[test]
|
||||
fn parse_no_args() {
|
||||
@@ -411,9 +412,7 @@ mod tests {
|
||||
fn resolve_path_arg_returns_path_for_absolute_arg() {
|
||||
let cwd = PathBuf::from("/home/user/project");
|
||||
let result = resolve_path_arg(Some("/some/absolute/path"), &cwd).unwrap();
|
||||
assert!(
|
||||
result.ends_with("absolute/path") || result == PathBuf::from("/some/absolute/path")
|
||||
);
|
||||
assert!(result.ends_with("absolute/path") || result == Path::new("/some/absolute/path"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
@@ -44,13 +44,11 @@ pub async fn crdt_sync_handler(
|
||||
// ── Bearer-token check (pre-upgrade) ────────────────────────────
|
||||
let require_token = REQUIRE_TOKEN.get().copied().unwrap_or(false);
|
||||
match ¶ms.token {
|
||||
Some(t) => {
|
||||
if !validate_join_token(t) {
|
||||
slog!("[crdt-sync] Rejected connection: invalid or expired token");
|
||||
return poem::Response::builder()
|
||||
.status(StatusCode::UNAUTHORIZED)
|
||||
.body("invalid or expired token");
|
||||
}
|
||||
Some(t) if !validate_join_token(t) => {
|
||||
slog!("[crdt-sync] Rejected connection: invalid or expired token");
|
||||
return poem::Response::builder()
|
||||
.status(StatusCode::UNAUTHORIZED)
|
||||
.body("invalid or expired token");
|
||||
}
|
||||
None if require_token => {
|
||||
slog!("[crdt-sync] Rejected connection: token required but not provided");
|
||||
@@ -58,7 +56,7 @@ pub async fn crdt_sync_handler(
|
||||
.status(StatusCode::UNAUTHORIZED)
|
||||
.body("token required");
|
||||
}
|
||||
None => {}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
// ── WebSocket upgrade ────────────────────────────────────────────
|
||||
|
||||
@@ -101,16 +101,13 @@ pub(crate) fn tool_ensure_acceptance(args: &Value, ctx: &AppContext) -> Result<S
|
||||
file_results = project_root.as_deref().and_then(|root| {
|
||||
crate::http::workflow::read_test_results_from_story_file(root, story_id)
|
||||
});
|
||||
file_results.as_ref().map_or_else(
|
||||
|| {
|
||||
// No results anywhere — use empty default for the acceptance check
|
||||
// (it will fail with "No test results recorded")
|
||||
static EMPTY: std::sync::OnceLock<crate::workflow::StoryTestResults> =
|
||||
std::sync::OnceLock::new();
|
||||
EMPTY.get_or_init(Default::default)
|
||||
},
|
||||
|r| r,
|
||||
)
|
||||
file_results.as_ref().unwrap_or_else(|| {
|
||||
// No results anywhere — use empty default for the acceptance check
|
||||
// (it will fail with "No test results recorded")
|
||||
static EMPTY: std::sync::OnceLock<crate::workflow::StoryTestResults> =
|
||||
std::sync::OnceLock::new();
|
||||
EMPTY.get_or_init(Default::default)
|
||||
})
|
||||
};
|
||||
|
||||
let coverage = workflow.coverage.get(story_id);
|
||||
|
||||
@@ -90,11 +90,8 @@ pub async fn ws_handler(ws: WebSocket, ctx: Data<&Arc<AppContext>>) -> impl poem
|
||||
let mut pending_perms: HashMap<String, oneshot::Sender<PermissionDecision>> =
|
||||
HashMap::new();
|
||||
|
||||
loop {
|
||||
// Outer loop: wait for the next WebSocket message.
|
||||
let Some(Ok(WsMessage::Text(text))) = stream.next().await else {
|
||||
break;
|
||||
};
|
||||
// Outer loop: wait for the next WebSocket message.
|
||||
while let Some(Ok(WsMessage::Text(text))) = stream.next().await {
|
||||
|
||||
// Handle read-RPC frames (discriminated by "kind", not "type").
|
||||
if let Some(rpc_resp) = crate::crdt_sync::try_handle_rpc_text(&text).await {
|
||||
|
||||
Reference in New Issue
Block a user