perf: completely eradicate large vector allocations and state locking double-clones in main, meta, env, workspaces, and notes modules
This commit is contained in:
1 parent
6b37799cc5
commit
9476bcd649
9 files changed
+352
-125
No files matched your search
@@ -0,0 +1,61 @@
|
|||||||
|
import os
|
||||||
|
|
||||||
|
def fix_env_and_workspaces():
|
||||||
|
filepath = 'server/src/handlers_v2/env.rs'
|
||||||
|
with open(filepath, 'r', encoding='utf-8') as f:
|
||||||
|
content = f.read()
|
||||||
|
|
||||||
|
old_env = """ let fps = state.env_fingerprints.read();
|
||||||
|
if let Some(fp) = fps.get(&req.namespace) {"""
|
||||||
|
|
||||||
|
new_env = """ let data = state.env_fingerprints.read_with(|fps| {
|
||||||
|
fps.get(&req.namespace).cloned()
|
||||||
|
});
|
||||||
|
if let Some(fp) = data {"""
|
||||||
|
|
||||||
|
if old_env in content:
|
||||||
|
content = content.replace(old_env, new_env)
|
||||||
|
print('Replaced env read')
|
||||||
|
else:
|
||||||
|
print('Could not find old_env')
|
||||||
|
|
||||||
|
with open(filepath, 'w', encoding='utf-8') as f:
|
||||||
|
f.write(content)
|
||||||
|
|
||||||
|
filepath = 'server/src/handlers_v2/workspaces.rs'
|
||||||
|
with open(filepath, 'r', encoding='utf-8') as f:
|
||||||
|
content = f.read()
|
||||||
|
|
||||||
|
old_ws = """ let query = req.query.to_lowercase();
|
||||||
|
let snippets = state.snippets.read();
|
||||||
|
let mut results = Vec::new();
|
||||||
|
for s in snippets {
|
||||||
|
if contains_ignore_ascii_case(&s.name, &query)
|
||||||
|
|| contains_ignore_ascii_case(&s.description, &query)
|
||||||
|
|| contains_ignore_ascii_case(&s.language, &query)
|
||||||
|
{
|
||||||
|
results.push(s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let data = serde_json::to_string(&results).unwrap_or_default();"""
|
||||||
|
|
||||||
|
new_ws = """ let query = req.query.to_lowercase();
|
||||||
|
let data = state.snippets.read_with(|snippets| {
|
||||||
|
let results: Vec<_> = snippets.iter().filter(|s| {
|
||||||
|
contains_ignore_ascii_case(&s.name, &query)
|
||||||
|
|| contains_ignore_ascii_case(&s.description, &query)
|
||||||
|
|| contains_ignore_ascii_case(&s.language, &query)
|
||||||
|
}).cloned().collect();
|
||||||
|
serde_json::to_string(&results).unwrap_or_default()
|
||||||
|
});"""
|
||||||
|
|
||||||
|
if old_ws in content:
|
||||||
|
content = content.replace(old_ws, new_ws)
|
||||||
|
print('Replaced workspaces read')
|
||||||
|
else:
|
||||||
|
print('Could not find old_ws')
|
||||||
|
|
||||||
|
with open(filepath, 'w', encoding='utf-8') as f:
|
||||||
|
f.write(content)
|
||||||
|
|
||||||
|
fix_env_and_workspaces()
|
||||||
@@ -0,0 +1,60 @@
|
|||||||
|
import os
|
||||||
|
|
||||||
|
def fix_main_stats():
|
||||||
|
filepath = 'server/src/main.rs'
|
||||||
|
with open(filepath, 'r', encoding='utf-8') as f:
|
||||||
|
content = f.read()
|
||||||
|
|
||||||
|
old_stats = """ let (entities, relations) = {
|
||||||
|
let graph = state_clone.get_full_graph();
|
||||||
|
(graph.entities.len(), graph.relations.len())
|
||||||
|
};
|
||||||
|
let tasks = state_clone.tasks.read().len();
|
||||||
|
let snippets = state_clone.snippets.read().len();
|
||||||
|
let tech_debts = state_clone.tech_debts.read().len();
|
||||||
|
let adrs = state_clone.adrs.read().len();
|
||||||
|
|
||||||
|
let ledger = state_clone.ledger.read().len();
|
||||||
|
let sticky = state_clone.sticky.read().len();
|
||||||
|
let error_fixes = state_clone.error_fixes.read().len();
|
||||||
|
let pinned_files = state_clone.pinned_files.read().len();
|
||||||
|
let session_summaries = state_clone.session_summaries.read().len();
|
||||||
|
let handoff_memos = state_clone.handoff_memos.read().len();
|
||||||
|
let env_fingerprints = state_clone.env_fingerprints.read().len();
|
||||||
|
let env_requirements = state_clone.env_requirements.read().len();
|
||||||
|
let milestones = state_clone.milestones.read().len();
|
||||||
|
let environments = state_clone.environments.read().len();
|
||||||
|
let pr_checklists = state_clone.pr_checklists.read().len();
|
||||||
|
let gates = state_clone.gates.read().len();
|
||||||
|
let context_workspaces = state_clone.context_workspaces.read().len();"""
|
||||||
|
|
||||||
|
new_stats = """ let (entities, relations) = state_clone.read_graph(|g| (g.entities.len(), g.relations.len()));
|
||||||
|
let tasks = state_clone.tasks.read_with(|items| items.len());
|
||||||
|
let snippets = state_clone.snippets.read_with(|items| items.len());
|
||||||
|
let tech_debts = state_clone.tech_debts.read_with(|items| items.len());
|
||||||
|
let adrs = state_clone.adrs.read_with(|items| items.len());
|
||||||
|
|
||||||
|
let ledger = state_clone.ledger.read_with(|items| items.len());
|
||||||
|
let sticky = state_clone.sticky.read_with(|items| items.len());
|
||||||
|
let error_fixes = state_clone.error_fixes.read_with(|items| items.len());
|
||||||
|
let pinned_files = state_clone.pinned_files.read_with(|items| items.len());
|
||||||
|
let session_summaries = state_clone.session_summaries.read_with(|items| items.len());
|
||||||
|
let handoff_memos = state_clone.handoff_memos.read_with(|items| items.len());
|
||||||
|
let env_fingerprints = state_clone.env_fingerprints.read_with(|items| items.len());
|
||||||
|
let env_requirements = state_clone.env_requirements.read_with(|items| items.len());
|
||||||
|
let milestones = state_clone.milestones.read_with(|items| items.len());
|
||||||
|
let environments = state_clone.environments.read_with(|items| items.len());
|
||||||
|
let pr_checklists = state_clone.pr_checklists.read_with(|items| items.len());
|
||||||
|
let gates = state_clone.gates.read_with(|items| items.len());
|
||||||
|
let context_workspaces = state_clone.context_workspaces.read_with(|items| items.len());"""
|
||||||
|
|
||||||
|
if old_stats in content:
|
||||||
|
content = content.replace(old_stats, new_stats)
|
||||||
|
print('Replaced stats reads')
|
||||||
|
else:
|
||||||
|
print('Could not find old_stats')
|
||||||
|
|
||||||
|
with open(filepath, 'w', encoding='utf-8') as f:
|
||||||
|
f.write(content)
|
||||||
|
|
||||||
|
fix_main_stats()
|
||||||
@@ -0,0 +1,111 @@
|
|||||||
|
import os
|
||||||
|
|
||||||
|
def fix_meta():
|
||||||
|
filepath = 'server/src/handlers_v2/meta.rs'
|
||||||
|
with open(filepath, 'r', encoding='utf-8') as f:
|
||||||
|
content = f.read()
|
||||||
|
|
||||||
|
old_omni = """ let q = req.query.to_lowercase();
|
||||||
|
let tech_debts: Vec<_> = state
|
||||||
|
.tech_debts
|
||||||
|
.read()
|
||||||
|
.into_iter()
|
||||||
|
.filter(|d| {
|
||||||
|
req.namespace.as_ref().is_none_or(|ns| d.namespace == *ns)
|
||||||
|
&& (contains_ignore_ascii_case(&d.description, &q)
|
||||||
|
|| contains_ignore_ascii_case(&d.ideal_solution, &q))
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
let memos: Vec<_> = state
|
||||||
|
.handoff_memos
|
||||||
|
.read()
|
||||||
|
.into_iter()
|
||||||
|
.filter(|m| {
|
||||||
|
req.namespace.as_ref().is_none_or(|ns| m.namespace == *ns)
|
||||||
|
&& contains_ignore_ascii_case(&m.content, &q)
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
let error_fixes: Vec<_> = state
|
||||||
|
.error_fixes
|
||||||
|
.read()
|
||||||
|
.into_iter()
|
||||||
|
.filter(|f| {
|
||||||
|
contains_ignore_ascii_case(&f.signature, &q)
|
||||||
|
|| contains_ignore_ascii_case(&f.solution, &q)
|
||||||
|
})
|
||||||
|
.collect();"""
|
||||||
|
|
||||||
|
new_omni = """ let q = req.query.to_lowercase();
|
||||||
|
let tech_debts = state.tech_debts.read_with(|debts| {
|
||||||
|
debts.iter().filter(|d| {
|
||||||
|
req.namespace.as_ref().is_none_or(|ns| d.namespace == *ns)
|
||||||
|
&& (contains_ignore_ascii_case(&d.description, &q)
|
||||||
|
|| contains_ignore_ascii_case(&d.ideal_solution, &q))
|
||||||
|
}).cloned().collect::<Vec<_>>()
|
||||||
|
});
|
||||||
|
let memos = state.handoff_memos.read_with(|memos| {
|
||||||
|
memos.iter().filter(|m| {
|
||||||
|
req.namespace.as_ref().is_none_or(|ns| m.namespace == *ns)
|
||||||
|
&& contains_ignore_ascii_case(&m.content, &q)
|
||||||
|
}).cloned().collect::<Vec<_>>()
|
||||||
|
});
|
||||||
|
let error_fixes = state.error_fixes.read_with(|fixes| {
|
||||||
|
fixes.iter().filter(|f| {
|
||||||
|
contains_ignore_ascii_case(&f.signature, &q)
|
||||||
|
|| contains_ignore_ascii_case(&f.solution, &q)
|
||||||
|
}).cloned().collect::<Vec<_>>()
|
||||||
|
});"""
|
||||||
|
|
||||||
|
if old_omni in content:
|
||||||
|
content = content.replace(old_omni, new_omni)
|
||||||
|
print('Replaced omni_search vecs')
|
||||||
|
else:
|
||||||
|
print('Could not find old_omni')
|
||||||
|
|
||||||
|
old_health = """ let active_tasks = state
|
||||||
|
.tasks
|
||||||
|
.read()
|
||||||
|
.into_iter()
|
||||||
|
.filter(|t| t.status != "done")
|
||||||
|
.count();
|
||||||
|
let unresolved_debt = state
|
||||||
|
.tech_debts
|
||||||
|
.read()
|
||||||
|
.into_iter()
|
||||||
|
.filter(|d| d.namespace == req.namespace && !d.is_resolved)
|
||||||
|
.count();
|
||||||
|
let unread_memos = state
|
||||||
|
.handoff_memos
|
||||||
|
.read()
|
||||||
|
.into_iter()
|
||||||
|
.filter(|m| m.namespace == req.namespace)
|
||||||
|
.count();
|
||||||
|
let active_milestones = state
|
||||||
|
.milestones
|
||||||
|
.read()
|
||||||
|
.into_iter()
|
||||||
|
.filter(|m| m.namespace == req.namespace && m.status != "done")
|
||||||
|
.count();
|
||||||
|
let remaining_checklists = state
|
||||||
|
.pr_checklists
|
||||||
|
.read()
|
||||||
|
.into_iter()
|
||||||
|
.filter(|c| c.namespace == req.namespace)
|
||||||
|
.count();"""
|
||||||
|
|
||||||
|
new_health = """ let active_tasks = state.tasks.read_with(|tasks| tasks.iter().filter(|t| t.status != "done").count());
|
||||||
|
let unresolved_debt = state.tech_debts.read_with(|debts| debts.iter().filter(|d| d.namespace == req.namespace && !d.is_resolved).count());
|
||||||
|
let unread_memos = state.handoff_memos.read_with(|memos| memos.iter().filter(|m| m.namespace == req.namespace).count());
|
||||||
|
let active_milestones = state.milestones.read_with(|milestones| milestones.iter().filter(|m| m.namespace == req.namespace && m.status != "done").count());
|
||||||
|
let remaining_checklists = state.pr_checklists.read_with(|checklists| checklists.iter().filter(|c| c.namespace == req.namespace).count());"""
|
||||||
|
|
||||||
|
if old_health in content:
|
||||||
|
content = content.replace(old_health, new_health)
|
||||||
|
print('Replaced health counters')
|
||||||
|
else:
|
||||||
|
print('Could not find old_health')
|
||||||
|
|
||||||
|
with open(filepath, 'w', encoding='utf-8') as f:
|
||||||
|
f.write(content)
|
||||||
|
|
||||||
|
fix_meta()
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
import os
|
||||||
|
|
||||||
|
def fix_notes():
|
||||||
|
filepath = 'server/src/handlers_v2/notes.rs'
|
||||||
|
with open(filepath, 'r', encoding='utf-8') as f:
|
||||||
|
content = f.read()
|
||||||
|
|
||||||
|
old_standup = """ let tasks = state
|
||||||
|
.tasks
|
||||||
|
.read()
|
||||||
|
.into_iter()
|
||||||
|
.filter(|t| t.updated_at >= cutoff)
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
let changes = state
|
||||||
|
.ledger
|
||||||
|
.read()
|
||||||
|
.into_iter()
|
||||||
|
.filter(|c| c.timestamp >= cutoff)
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
let summaries = state
|
||||||
|
.session_summaries
|
||||||
|
.read()
|
||||||
|
.into_iter()
|
||||||
|
.filter(|s| s.namespace == req.namespace && s.timestamp >= cutoff)
|
||||||
|
.collect::<Vec<_>>();"""
|
||||||
|
|
||||||
|
new_standup = """ let tasks = state.tasks.read_with(|items| items.iter().filter(|t| t.updated_at >= cutoff).cloned().collect::<Vec<_>>());
|
||||||
|
let changes = state.ledger.read_with(|items| items.iter().filter(|c| c.timestamp >= cutoff).cloned().collect::<Vec<_>>());
|
||||||
|
let summaries = state.session_summaries.read_with(|items| items.iter().filter(|s| s.namespace == req.namespace && s.timestamp >= cutoff).cloned().collect::<Vec<_>>());"""
|
||||||
|
|
||||||
|
if old_standup in content:
|
||||||
|
content = content.replace(old_standup, new_standup)
|
||||||
|
print('Replaced standup in notes.rs')
|
||||||
|
else:
|
||||||
|
print('Could not find old_standup in notes.rs')
|
||||||
|
|
||||||
|
with open(filepath, 'w', encoding='utf-8') as f:
|
||||||
|
f.write(content)
|
||||||
|
|
||||||
|
fix_notes()
|
||||||
@@ -61,9 +61,11 @@ impl McpTool for ReadEnvFingerprintHandler {
|
|||||||
async fn execute(&self, args: Value, state: Arc<MemoryState>) -> Result<String, String> {
|
async fn execute(&self, args: Value, state: Arc<MemoryState>) -> Result<String, String> {
|
||||||
let req: ReadEnvFingerprintTool =
|
let req: ReadEnvFingerprintTool =
|
||||||
serde_json::from_value(args).map_err(|e| e.to_string())?;
|
serde_json::from_value(args).map_err(|e| e.to_string())?;
|
||||||
let fps = state.env_fingerprints.read();
|
let data = state.env_fingerprints.read_with(|fps| {
|
||||||
if let Some(fp) = fps.get(&req.namespace) {
|
fps.get(&req.namespace).cloned()
|
||||||
let data = serde_json::to_string(fp).unwrap_or_default();
|
});
|
||||||
|
if let Some(fp) = data {
|
||||||
|
let data = serde_json::to_string(&fp).unwrap_or_default();
|
||||||
Ok(data.to_string())
|
Ok(data.to_string())
|
||||||
} else {
|
} else {
|
||||||
Ok("{}".to_string())
|
Ok("{}".to_string())
|
||||||
@@ -164,3 +166,4 @@ impl McpTool for GetEnvironmentDetailsHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -368,60 +368,57 @@ impl McpTool for OmniSearchHandler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
for t in state.tasks.read() {
|
state.tasks.read_with(|all_tasks| {
|
||||||
if matches
|
for t in all_tasks {
|
||||||
.iter()
|
if matches
|
||||||
.any(|(id, typ, _, _, _)| id == &t.id && typ == "task")
|
.iter()
|
||||||
{
|
.any(|(id, typ, _, _, _)| id == &t.id && typ == "task")
|
||||||
tasks.push(t);
|
{
|
||||||
|
tasks.push(t.clone());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
for s in state.snippets.read() {
|
state.snippets.read_with(|all_snippets| {
|
||||||
if matches
|
for s in all_snippets {
|
||||||
.iter()
|
if matches
|
||||||
.any(|(id, typ, _, _, _)| id == &s.name && typ == "snippet")
|
.iter()
|
||||||
{
|
.any(|(id, typ, _, _, _)| id == &s.name && typ == "snippet")
|
||||||
snippets.push(s);
|
{
|
||||||
|
snippets.push(s.clone());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
for a in state.adrs.read() {
|
state.adrs.read_with(|all_adrs| {
|
||||||
if matches
|
for a in all_adrs {
|
||||||
.iter()
|
if matches
|
||||||
.any(|(id, typ, _, _, _)| id == &a.id && typ == "adr")
|
.iter()
|
||||||
{
|
.any(|(id, typ, _, _, _)| id == &a.id && typ == "adr")
|
||||||
adrs.push(a);
|
{
|
||||||
|
adrs.push(a.clone());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
|
|
||||||
let q = req.query.to_lowercase();
|
let q = req.query.to_lowercase();
|
||||||
let tech_debts: Vec<_> = state
|
let tech_debts = state.tech_debts.read_with(|debts| {
|
||||||
.tech_debts
|
debts.iter().filter(|d| {
|
||||||
.read()
|
|
||||||
.into_iter()
|
|
||||||
.filter(|d| {
|
|
||||||
req.namespace.as_ref().is_none_or(|ns| d.namespace == *ns)
|
req.namespace.as_ref().is_none_or(|ns| d.namespace == *ns)
|
||||||
&& (contains_ignore_ascii_case(&d.description, &q)
|
&& (contains_ignore_ascii_case(&d.description, &q)
|
||||||
|| contains_ignore_ascii_case(&d.ideal_solution, &q))
|
|| contains_ignore_ascii_case(&d.ideal_solution, &q))
|
||||||
})
|
}).cloned().collect::<Vec<_>>()
|
||||||
.collect();
|
});
|
||||||
let memos: Vec<_> = state
|
let memos = state.handoff_memos.read_with(|memos| {
|
||||||
.handoff_memos
|
memos.iter().filter(|m| {
|
||||||
.read()
|
|
||||||
.into_iter()
|
|
||||||
.filter(|m| {
|
|
||||||
req.namespace.as_ref().is_none_or(|ns| m.namespace == *ns)
|
req.namespace.as_ref().is_none_or(|ns| m.namespace == *ns)
|
||||||
&& contains_ignore_ascii_case(&m.content, &q)
|
&& contains_ignore_ascii_case(&m.content, &q)
|
||||||
})
|
}).cloned().collect::<Vec<_>>()
|
||||||
.collect();
|
});
|
||||||
let error_fixes: Vec<_> = state
|
let error_fixes = state.error_fixes.read_with(|fixes| {
|
||||||
.error_fixes
|
fixes.iter().filter(|f| {
|
||||||
.read()
|
|
||||||
.into_iter()
|
|
||||||
.filter(|f| {
|
|
||||||
contains_ignore_ascii_case(&f.signature, &q)
|
contains_ignore_ascii_case(&f.signature, &q)
|
||||||
|| contains_ignore_ascii_case(&f.solution, &q)
|
|| contains_ignore_ascii_case(&f.solution, &q)
|
||||||
})
|
}).cloned().collect::<Vec<_>>()
|
||||||
.collect();
|
});
|
||||||
|
|
||||||
let report = serde_json::json!({
|
let report = serde_json::json!({
|
||||||
"knowledge_graph": kg.entities,
|
"knowledge_graph": kg.entities,
|
||||||
@@ -453,36 +450,11 @@ impl McpTool for GetProjectHealthHandler {
|
|||||||
|
|
||||||
async fn execute(&self, args: Value, state: Arc<MemoryState>) -> Result<String, String> {
|
async fn execute(&self, args: Value, state: Arc<MemoryState>) -> Result<String, String> {
|
||||||
let req: GetProjectHealthTool = serde_json::from_value(args).map_err(|e| e.to_string())?;
|
let req: GetProjectHealthTool = serde_json::from_value(args).map_err(|e| e.to_string())?;
|
||||||
let active_tasks = state
|
let active_tasks = state.tasks.read_with(|tasks| tasks.iter().filter(|t| t.status != "done").count());
|
||||||
.tasks
|
let unresolved_debt = state.tech_debts.read_with(|debts| debts.iter().filter(|d| d.namespace == req.namespace && !d.is_resolved).count());
|
||||||
.read()
|
let unread_memos = state.handoff_memos.read_with(|memos| memos.iter().filter(|m| m.namespace == req.namespace).count());
|
||||||
.into_iter()
|
let active_milestones = state.milestones.read_with(|milestones| milestones.iter().filter(|m| m.namespace == req.namespace && m.status != "done").count());
|
||||||
.filter(|t| t.status != "done")
|
let remaining_checklists = state.pr_checklists.read_with(|checklists| checklists.iter().filter(|c| c.namespace == req.namespace).count());
|
||||||
.count();
|
|
||||||
let unresolved_debt = state
|
|
||||||
.tech_debts
|
|
||||||
.read()
|
|
||||||
.into_iter()
|
|
||||||
.filter(|d| d.namespace == req.namespace && !d.is_resolved)
|
|
||||||
.count();
|
|
||||||
let unread_memos = state
|
|
||||||
.handoff_memos
|
|
||||||
.read()
|
|
||||||
.into_iter()
|
|
||||||
.filter(|m| m.namespace == req.namespace)
|
|
||||||
.count();
|
|
||||||
let active_milestones = state
|
|
||||||
.milestones
|
|
||||||
.read()
|
|
||||||
.into_iter()
|
|
||||||
.filter(|m| m.namespace == req.namespace && m.status != "done")
|
|
||||||
.count();
|
|
||||||
let remaining_checklists = state
|
|
||||||
.pr_checklists
|
|
||||||
.read()
|
|
||||||
.into_iter()
|
|
||||||
.filter(|c| c.namespace == req.namespace)
|
|
||||||
.count();
|
|
||||||
|
|
||||||
let report = serde_json::json!({
|
let report = serde_json::json!({
|
||||||
"active_tasks": active_tasks,
|
"active_tasks": active_tasks,
|
||||||
@@ -498,3 +470,4 @@ impl McpTool for GetProjectHealthHandler {
|
|||||||
use crate::handlers_v2::utils::*;
|
use crate::handlers_v2::utils::*;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -254,24 +254,9 @@ impl McpTool for GenerateStandupReportHandler {
|
|||||||
.unwrap_or_default()
|
.unwrap_or_default()
|
||||||
.as_secs()
|
.as_secs()
|
||||||
.saturating_sub(req.hours_lookback * 3600);
|
.saturating_sub(req.hours_lookback * 3600);
|
||||||
let tasks = state
|
let tasks = state.tasks.read_with(|items| items.iter().filter(|t| t.updated_at >= cutoff).cloned().collect::<Vec<_>>());
|
||||||
.tasks
|
let changes = state.ledger.read_with(|items| items.iter().filter(|c| c.timestamp >= cutoff).cloned().collect::<Vec<_>>());
|
||||||
.read()
|
let summaries = state.session_summaries.read_with(|items| items.iter().filter(|s| s.namespace == req.namespace && s.timestamp >= cutoff).cloned().collect::<Vec<_>>());
|
||||||
.into_iter()
|
|
||||||
.filter(|t| t.updated_at >= cutoff)
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
let changes = state
|
|
||||||
.ledger
|
|
||||||
.read()
|
|
||||||
.into_iter()
|
|
||||||
.filter(|c| c.timestamp >= cutoff)
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
let summaries = state
|
|
||||||
.session_summaries
|
|
||||||
.read()
|
|
||||||
.into_iter()
|
|
||||||
.filter(|s| s.namespace == req.namespace && s.timestamp >= cutoff)
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
let report = serde_json::json!({ "tasks_updated": tasks, "code_changes": changes, "session_summaries": summaries });
|
let report = serde_json::json!({ "tasks_updated": tasks, "code_changes": changes, "session_summaries": summaries });
|
||||||
Ok(report.to_string())
|
Ok(report.to_string())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -147,17 +147,14 @@ impl McpTool for SearchSnippetsHandler {
|
|||||||
async fn execute(&self, args: Value, state: Arc<MemoryState>) -> Result<String, String> {
|
async fn execute(&self, args: Value, state: Arc<MemoryState>) -> Result<String, String> {
|
||||||
let req: SearchSnippetsTool = serde_json::from_value(args).map_err(|e| e.to_string())?;
|
let req: SearchSnippetsTool = serde_json::from_value(args).map_err(|e| e.to_string())?;
|
||||||
let query = req.query.to_lowercase();
|
let query = req.query.to_lowercase();
|
||||||
let snippets = state.snippets.read();
|
let data = state.snippets.read_with(|snippets| {
|
||||||
let mut results = Vec::new();
|
let results: Vec<_> = snippets.iter().filter(|s| {
|
||||||
for s in snippets {
|
contains_ignore_ascii_case(&s.name, &query)
|
||||||
if contains_ignore_ascii_case(&s.name, &query)
|
|| contains_ignore_ascii_case(&s.description, &query)
|
||||||
|| contains_ignore_ascii_case(&s.description, &query)
|
|| contains_ignore_ascii_case(&s.language, &query)
|
||||||
|| contains_ignore_ascii_case(&s.language, &query)
|
}).cloned().collect();
|
||||||
{
|
serde_json::to_string(&results).unwrap_or_default()
|
||||||
results.push(s);
|
});
|
||||||
}
|
|
||||||
}
|
|
||||||
let data = serde_json::to_string(&results).unwrap_or_default();
|
|
||||||
Ok(data.to_string())
|
Ok(data.to_string())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+18
-21
@@ -355,28 +355,25 @@ async fn run_server(state: Arc<MemoryState>) -> Result<(), Box<dyn std::error::E
|
|||||||
get({
|
get({
|
||||||
let state_clone = app_state.handler.state.clone();
|
let state_clone = app_state.handler.state.clone();
|
||||||
move || async move {
|
move || async move {
|
||||||
let (entities, relations) = {
|
let (entities, relations) = state_clone.read_graph(|g| (g.entities.len(), g.relations.len()));
|
||||||
let graph = state_clone.get_full_graph();
|
let tasks = state_clone.tasks.read_with(|items| items.len());
|
||||||
(graph.entities.len(), graph.relations.len())
|
let snippets = state_clone.snippets.read_with(|items| items.len());
|
||||||
};
|
let tech_debts = state_clone.tech_debts.read_with(|items| items.len());
|
||||||
let tasks = state_clone.tasks.read().len();
|
let adrs = state_clone.adrs.read_with(|items| items.len());
|
||||||
let snippets = state_clone.snippets.read().len();
|
|
||||||
let tech_debts = state_clone.tech_debts.read().len();
|
|
||||||
let adrs = state_clone.adrs.read().len();
|
|
||||||
|
|
||||||
let ledger = state_clone.ledger.read().len();
|
let ledger = state_clone.ledger.read_with(|items| items.len());
|
||||||
let sticky = state_clone.sticky.read().len();
|
let sticky = state_clone.sticky.read_with(|items| items.len());
|
||||||
let error_fixes = state_clone.error_fixes.read().len();
|
let error_fixes = state_clone.error_fixes.read_with(|items| items.len());
|
||||||
let pinned_files = state_clone.pinned_files.read().len();
|
let pinned_files = state_clone.pinned_files.read_with(|items| items.len());
|
||||||
let session_summaries = state_clone.session_summaries.read().len();
|
let session_summaries = state_clone.session_summaries.read_with(|items| items.len());
|
||||||
let handoff_memos = state_clone.handoff_memos.read().len();
|
let handoff_memos = state_clone.handoff_memos.read_with(|items| items.len());
|
||||||
let env_fingerprints = state_clone.env_fingerprints.read().len();
|
let env_fingerprints = state_clone.env_fingerprints.read_with(|items| items.len());
|
||||||
let env_requirements = state_clone.env_requirements.read().len();
|
let env_requirements = state_clone.env_requirements.read_with(|items| items.len());
|
||||||
let milestones = state_clone.milestones.read().len();
|
let milestones = state_clone.milestones.read_with(|items| items.len());
|
||||||
let environments = state_clone.environments.read().len();
|
let environments = state_clone.environments.read_with(|items| items.len());
|
||||||
let pr_checklists = state_clone.pr_checklists.read().len();
|
let pr_checklists = state_clone.pr_checklists.read_with(|items| items.len());
|
||||||
let gates = state_clone.gates.read().len();
|
let gates = state_clone.gates.read_with(|items| items.len());
|
||||||
let context_workspaces = state_clone.context_workspaces.read().len();
|
let context_workspaces = state_clone.context_workspaces.read_with(|items| items.len());
|
||||||
|
|
||||||
axum::Json(serde_json::json!({
|
axum::Json(serde_json::json!({
|
||||||
"entities": entities,
|
"entities": entities,
|
||||||
|
|||||||
Reference in new issue
Block a user