fix: write mcp edge explanations to canonical field

This commit is contained in:
“BeeRad”
2026-04-27 15:02:33 +10:00
parent 1019a2b846
commit ceaace1f4a
2 changed files with 38 additions and 22 deletions
+1 -1
View File
@@ -557,7 +557,7 @@ async function main() {
from_node_id: e.from_node_id, from_node_id: e.from_node_id,
to_node_id: e.to_node_id, to_node_id: e.to_node_id,
type: e.context?.type ?? null, type: e.context?.type ?? null,
explanation: e.context?.explanation ?? null explanation: e.explanation ?? e.context?.explanation ?? null
})) }))
} }
}; };
@@ -21,10 +21,7 @@ function getEdges(filters = {}) {
const rows = query(sql, params); const rows = query(sql, params);
return rows.map(row => ({ return rows.map(formatEdgeRow);
...row,
context: parseContext(row.context)
}));
} }
/** /**
@@ -34,11 +31,7 @@ function getEdgeById(id) {
const rows = query('SELECT * FROM edges WHERE id = ?', [id]); const rows = query('SELECT * FROM edges WHERE id = ?', [id]);
if (rows.length === 0) return null; if (rows.length === 0) return null;
const row = rows[0]; return formatEdgeRow(rows[0]);
return {
...row,
context: parseContext(row.context)
};
} }
/** /**
@@ -59,19 +52,21 @@ function createEdge(edgeData) {
throw new Error('Edge explanation is required'); throw new Error('Edge explanation is required');
} }
const cleanExplanation = explanation.trim();
// Simple context without AI inference // Simple context without AI inference
// The main app can re-infer types when it loads // The main app can re-infer types when it loads
const context = { const context = {
type: 'related_to', type: 'related_to',
confidence: 0.5, confidence: 0.5,
inferred_at: now, inferred_at: now,
explanation: explanation.trim(), explanation: cleanExplanation,
created_via: 'mcp' created_via: 'mcp'
}; };
const stmt = db.prepare(` const stmt = db.prepare(`
INSERT INTO edges (from_node_id, to_node_id, context, source, created_at) INSERT INTO edges (from_node_id, to_node_id, context, source, created_at, explanation)
VALUES (?, ?, ?, ?, ?) VALUES (?, ?, ?, ?, ?, ?)
`); `);
const result = runWithBusyRetry(() => stmt.run( const result = runWithBusyRetry(() => stmt.run(
@@ -79,7 +74,8 @@ function createEdge(edgeData) {
to_node_id, to_node_id,
JSON.stringify(context), JSON.stringify(context),
source, source,
now now,
cleanExplanation
), ),
'createEdge' 'createEdge'
); );
@@ -100,25 +96,36 @@ function updateEdge(id, updates) {
throw new Error(`Edge with ID ${id} not found. Use rah_query_edges to find edges by node ID.`); throw new Error(`Edge with ID ${id} not found. Use rah_query_edges to find edges by node ID.`);
} }
// If explanation changed, update context const cleanExplanation = typeof explanation === 'string' ? explanation.trim() : '';
if (explanation && explanation.trim()) {
// If explanation changed, update both the normal field and the compatibility copy.
if (cleanExplanation) {
const now = new Date().toISOString(); const now = new Date().toISOString();
const newContext = { const newContext = {
...existing.context, ...existing.context,
explanation: explanation.trim(), explanation: cleanExplanation,
inferred_at: now, inferred_at: now,
created_via: 'mcp' created_via: 'mcp'
}; };
const stmt = db.prepare('UPDATE edges SET context = ? WHERE id = ?'); const stmt = db.prepare('UPDATE edges SET context = ?, explanation = ? WHERE id = ?');
runWithBusyRetry(() => stmt.run(JSON.stringify(newContext), id), 'updateEdge'); runWithBusyRetry(() => stmt.run(JSON.stringify(newContext), cleanExplanation, id), 'updateEdge');
} else if (contextUpdates) { } else if (contextUpdates) {
const contextExplanation = typeof contextUpdates.explanation === 'string'
? contextUpdates.explanation.trim()
: '';
const newContext = { const newContext = {
...existing.context, ...existing.context,
...contextUpdates ...contextUpdates,
...(contextExplanation ? { explanation: contextExplanation } : {})
}; };
const stmt = db.prepare('UPDATE edges SET context = ? WHERE id = ?'); if (contextExplanation) {
runWithBusyRetry(() => stmt.run(JSON.stringify(newContext), id), 'updateEdge'); const stmt = db.prepare('UPDATE edges SET context = ?, explanation = ? WHERE id = ?');
runWithBusyRetry(() => stmt.run(JSON.stringify(newContext), contextExplanation, id), 'updateEdge');
} else {
const stmt = db.prepare('UPDATE edges SET context = ? WHERE id = ?');
runWithBusyRetry(() => stmt.run(JSON.stringify(newContext), id), 'updateEdge');
}
} }
return getEdgeById(id); return getEdgeById(id);
@@ -204,6 +211,15 @@ function getEdgeCount() {
return Number(rows[0].count); return Number(rows[0].count);
} }
function formatEdgeRow(row) {
const context = parseContext(row.context);
return {
...row,
context,
explanation: row.explanation || context?.explanation || null
};
}
/** /**
* Parse context JSON safely. * Parse context JSON safely.
*/ */