fix: write mcp edge explanations to canonical field
This commit is contained in:
@@ -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.
|
||||||
*/
|
*/
|
||||||
|
|||||||
Reference in New Issue
Block a user