feat: advance local-first conflict and search indexing

- 补齐本地 markdown 冲突处理与合并写回路径\n- 增加本地搜索索引路由、刷新与 browser smoke\n- 同步更新 current-priority checklist 的阶段进度
This commit is contained in:
lix-2026
2026-05-19 09:38:57 +08:00
parent 8ed594f1c2
commit 1b5d6a2a2d
12 changed files with 1622 additions and 49 deletions
+11
View File
@@ -4,6 +4,7 @@ use axum::http::{HeaderName, HeaderValue};
use axum::response::{IntoResponse, Response};
use axum::Json;
use serde::Serialize;
use serde_json::Value;
#[derive(Debug, Clone, Serialize)]
#[serde(rename_all = "camelCase")]
@@ -13,6 +14,8 @@ pub struct ErrorBody {
pub message: String,
pub request_id: Option<String>,
pub trace_id: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub details: Option<Value>,
}
#[derive(Debug, Clone)]
@@ -22,6 +25,7 @@ pub struct WebError {
message: String,
request_context: Option<RequestContext>,
headers: Vec<(&'static str, String)>,
details: Option<Value>,
}
impl WebError {
@@ -32,6 +36,7 @@ impl WebError {
message: message.into(),
request_context: None,
headers: Vec::new(),
details: None,
}
}
@@ -69,6 +74,11 @@ impl WebError {
self
}
pub fn with_details(mut self, details: Value) -> Self {
self.details = Some(details);
self
}
pub fn message(&self) -> &str {
&self.message
}
@@ -96,6 +106,7 @@ impl IntoResponse for WebError {
.request_context
.as_ref()
.map(|context| context.trace.trace_id.clone()),
details: self.details,
};
let mut response = (self.status, Json(body)).into_response();
if let Ok(name) = HeaderName::from_lowercase(b"x-error-code") {