feature/insight-chat-improvements #83
@@ -119,8 +119,8 @@ impl InsightGenerator {
|
|||||||
location_dao: Arc<Mutex<Box<dyn LocationHistoryDao>>>,
|
location_dao: Arc<Mutex<Box<dyn LocationHistoryDao>>>,
|
||||||
search_dao: Arc<Mutex<Box<dyn SearchHistoryDao>>>,
|
search_dao: Arc<Mutex<Box<dyn SearchHistoryDao>>>,
|
||||||
tag_dao: Arc<Mutex<Box<dyn TagDao>>>,
|
tag_dao: Arc<Mutex<Box<dyn TagDao>>>,
|
||||||
knowledge_dao: Arc<Mutex<Box<dyn KnowledgeDao>>>,
|
|
||||||
face_dao: Arc<Mutex<Box<dyn crate::faces::FaceDao>>>,
|
face_dao: Arc<Mutex<Box<dyn crate::faces::FaceDao>>>,
|
||||||
|
knowledge_dao: Arc<Mutex<Box<dyn KnowledgeDao>>>,
|
||||||
libraries: Vec<Library>,
|
libraries: Vec<Library>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
@@ -135,8 +135,8 @@ impl InsightGenerator {
|
|||||||
location_dao,
|
location_dao,
|
||||||
search_dao,
|
search_dao,
|
||||||
tag_dao,
|
tag_dao,
|
||||||
knowledge_dao,
|
|
||||||
face_dao,
|
face_dao,
|
||||||
|
knowledge_dao,
|
||||||
libraries,
|
libraries,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2180,15 +2180,16 @@ Return ONLY the summary, nothing else."#,
|
|||||||
log::info!("tool_get_faces_in_photo: file_path='{}'", file_path);
|
log::info!("tool_get_faces_in_photo: file_path='{}'", file_path);
|
||||||
|
|
||||||
// Resolve content_hash from any library that has this rel_path.
|
// Resolve content_hash from any library that has this rel_path.
|
||||||
// Walk libraries in their declared order and take the first hit.
|
// Hold the FaceDao lock once across all libraries — resolve_content_hash
|
||||||
let mut content_hash: Option<String> = None;
|
// is synchronous and there's no await in the loop body.
|
||||||
for lib in &self.libraries {
|
let content_hash: Option<String> = {
|
||||||
let mut dao = self.face_dao.lock().expect("Unable to lock FaceDao");
|
let mut dao = self.face_dao.lock().expect("Unable to lock FaceDao");
|
||||||
if let Ok(Some(h)) = dao.resolve_content_hash(cx, lib.id, &file_path) {
|
self.libraries.iter().find_map(|lib| {
|
||||||
content_hash = Some(h);
|
dao.resolve_content_hash(cx, lib.id, &file_path)
|
||||||
break;
|
.ok()
|
||||||
}
|
.flatten()
|
||||||
}
|
})
|
||||||
|
};
|
||||||
let Some(content_hash) = content_hash else {
|
let Some(content_hash) = content_hash else {
|
||||||
return "No content_hash found for that file path (the photo may not be indexed yet, \
|
return "No content_hash found for that file path (the photo may not be indexed yet, \
|
||||||
or the path doesn't match any library)."
|
or the path doesn't match any library)."
|
||||||
@@ -2215,9 +2216,11 @@ Return ONLY the summary, nothing else."#,
|
|||||||
|
|
||||||
let mut out = format!("Found {} face(s) in this photo:\n", faces.len());
|
let mut out = format!("Found {} face(s) in this photo:\n", faces.len());
|
||||||
for f in &bound {
|
for f in &bound {
|
||||||
|
// Invariant: `bound` is filtered on `person_name.is_some()` above.
|
||||||
|
let name = f.person_name.as_deref().expect("bound face must have a name");
|
||||||
out.push_str(&format!(
|
out.push_str(&format!(
|
||||||
"- {} (confidence {:.2}, bbox x={:.2} y={:.2} w={:.2} h={:.2}, source: {})\n",
|
"- {} (confidence {:.2}, bbox x={:.2} y={:.2} w={:.2} h={:.2}, source: {})\n",
|
||||||
f.person_name.as_deref().unwrap_or("?"),
|
name,
|
||||||
f.confidence,
|
f.confidence,
|
||||||
f.bbox_x,
|
f.bbox_x,
|
||||||
f.bbox_y,
|
f.bbox_y,
|
||||||
|
|||||||
@@ -201,8 +201,8 @@ async fn main() -> anyhow::Result<()> {
|
|||||||
location_dao,
|
location_dao,
|
||||||
search_dao,
|
search_dao,
|
||||||
tag_dao,
|
tag_dao,
|
||||||
knowledge_dao,
|
|
||||||
face_dao,
|
face_dao,
|
||||||
|
knowledge_dao,
|
||||||
all_libs.clone(),
|
all_libs.clone(),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -1437,7 +1437,6 @@ impl FaceDao for SqliteFaceDao {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn has_any_faces(&mut self, ctx: &opentelemetry::Context) -> anyhow::Result<bool> {
|
fn has_any_faces(&mut self, ctx: &opentelemetry::Context) -> anyhow::Result<bool> {
|
||||||
use anyhow::Context;
|
|
||||||
let mut conn = self.connection.lock().expect("face dao lock");
|
let mut conn = self.connection.lock().expect("face dao lock");
|
||||||
trace_db_call(ctx, "query", "has_any_faces", |_span| {
|
trace_db_call(ctx, "query", "has_any_faces", |_span| {
|
||||||
face_detections::table
|
face_detections::table
|
||||||
|
|||||||
@@ -234,8 +234,8 @@ impl Default for AppState {
|
|||||||
location_dao.clone(),
|
location_dao.clone(),
|
||||||
search_dao.clone(),
|
search_dao.clone(),
|
||||||
tag_dao.clone(),
|
tag_dao.clone(),
|
||||||
knowledge_dao,
|
|
||||||
face_dao.clone(),
|
face_dao.clone(),
|
||||||
|
knowledge_dao,
|
||||||
libraries_vec.clone(),
|
libraries_vec.clone(),
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -376,8 +376,8 @@ impl AppState {
|
|||||||
location_dao.clone(),
|
location_dao.clone(),
|
||||||
search_dao.clone(),
|
search_dao.clone(),
|
||||||
tag_dao.clone(),
|
tag_dao.clone(),
|
||||||
knowledge_dao,
|
|
||||||
face_dao.clone(),
|
face_dao.clone(),
|
||||||
|
knowledge_dao,
|
||||||
vec![test_lib],
|
vec![test_lib],
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user