fix: reconcile supersede replay with current main runtime

This commit is contained in:
Chummy 2026-02-28 11:47:51 +00:00 committed by Chum Yin
parent a88d37f3cb
commit 46b50cbb49
2 changed files with 116 additions and 14 deletions

View File

@ -183,7 +183,6 @@ tempfile = "3.14"
wasmtime = { version = "24.0.6", optional = true, default-features = false, features = ["cranelift", "runtime"] }
wasmtime-wasi = { version = "24.0.6", optional = true, default-features = false, features = ["preview1"] }
# Terminal QR rendering for WhatsApp Web pairing flow.
qrcode = { version = "0.14", optional = true }
@ -196,18 +195,6 @@ wa-rs-proto = { version = "0.2", optional = true, default-features = false }
wa-rs-ureq-http = { version = "0.2", optional = true }
wa-rs-tokio-transport = { version = "0.2", optional = true, default-features = false }
# USB device enumeration (hardware discovery) — only on platforms nusb supports
# (Linux, macOS, Windows). Android/Termux uses target_os="android" and is excluded.
[target.'cfg(any(target_os = "linux", target_os = "macos", target_os = "windows"))'.dependencies]
nusb = { version = "0.2", default-features = false, optional = true }
# probe-rs for STM32/Nucleo memory read (Phase B)
probe-rs = { version = "0.31", optional = true }
# PDF extraction for datasheet RAG (optional, enable with --features rag-pdf)
pdf-extract = { version = "0.10", optional = true }
tempfile = "3.14"
# Raspberry Pi GPIO / Landlock (Linux only) — target-specific to avoid compile failure on macOS
[target.'cfg(target_os = "linux")'.dependencies]
rppal = { version = "0.22", optional = true }

View File

@ -985,6 +985,21 @@ fn runtime_defaults_snapshot(ctx: &ChannelRuntimeContext) -> ChannelRuntimeDefau
}
}
fn runtime_perplexity_filter_snapshot(
ctx: &ChannelRuntimeContext,
) -> crate::config::PerplexityFilterConfig {
if let Some(config_path) = runtime_config_path(ctx) {
let store = runtime_config_store()
.lock()
.unwrap_or_else(|e| e.into_inner());
if let Some(state) = store.get(&config_path) {
return state.perplexity_filter.clone();
}
}
crate::config::PerplexityFilterConfig::default()
}
fn snapshot_non_cli_excluded_tools(ctx: &ChannelRuntimeContext) -> Vec<String> {
ctx.non_cli_excluded_tools
.lock()
@ -2151,7 +2166,8 @@ async fn handle_runtime_command_if_needed(
)
}
}
ChannelRuntimeCommand::ConfirmToolApproval(raw_request_id) => {
ChannelRuntimeCommand::ConfirmToolApproval(raw_request_id)
| ChannelRuntimeCommand::ApprovePendingRequest(raw_request_id) => {
let request_id = raw_request_id.trim().to_string();
if request_id.is_empty() {
"Usage: `/approve-confirm <request-id>`".to_string()
@ -2163,6 +2179,10 @@ async fn handle_runtime_command_if_needed(
reply_target,
) {
Ok(req) => {
ctx.approval_manager.record_non_cli_pending_resolution(
&request_id,
ApprovalResponse::Yes,
);
let tool_name = req.tool_name;
let mut approval_message = if tool_name == APPROVAL_ALL_TOOLS_ONCE_TOKEN {
let remaining = ctx.approval_manager.grant_non_cli_allow_all_once();
@ -2269,6 +2289,101 @@ async fn handle_runtime_command_if_needed(
}
}
}
ChannelRuntimeCommand::DenyToolApproval(raw_request_id) => {
let request_id = raw_request_id.trim().to_string();
if request_id.is_empty() {
"Usage: `/approve-deny <request-id>`".to_string()
} else {
match ctx.approval_manager.reject_non_cli_pending_request(
&request_id,
sender,
source_channel,
reply_target,
) {
Ok(req) => {
ctx.approval_manager.record_non_cli_pending_resolution(
&request_id,
ApprovalResponse::No,
);
runtime_trace::record_event(
"approval_request_rejected",
Some(source_channel),
None,
None,
None,
Some(true),
Some("pending request rejected"),
serde_json::json!({
"request_id": request_id,
"tool_name": req.tool_name,
"sender": sender,
"channel": source_channel,
}),
);
format!(
"Rejected approval request `{}` for `{}`.",
req.request_id,
approval_target_label(&req.tool_name)
)
}
Err(PendingApprovalError::NotFound) => {
runtime_trace::record_event(
"approval_request_rejected",
Some(source_channel),
None,
None,
None,
Some(false),
Some("pending request not found"),
serde_json::json!({
"request_id": request_id,
"sender": sender,
"channel": source_channel,
}),
);
format!(
"Pending approval request `{request_id}` was not found. List requests with `/approve-pending`."
)
}
Err(PendingApprovalError::Expired) => {
runtime_trace::record_event(
"approval_request_rejected",
Some(source_channel),
None,
None,
None,
Some(false),
Some("pending request expired"),
serde_json::json!({
"request_id": request_id,
"sender": sender,
"channel": source_channel,
}),
);
format!("Pending approval request `{request_id}` has expired.")
}
Err(PendingApprovalError::RequesterMismatch) => {
runtime_trace::record_event(
"approval_request_rejected",
Some(source_channel),
None,
None,
None,
Some(false),
Some("pending request rejector mismatch"),
serde_json::json!({
"request_id": request_id,
"sender": sender,
"channel": source_channel,
}),
);
format!(
"Pending approval request `{request_id}` can only be denied by the same sender in the same chat/channel that created it."
)
}
}
}
}
ChannelRuntimeCommand::ListPendingApprovals => {
let rows = ctx.approval_manager.list_non_cli_pending_requests(
Some(sender),