runtime: engram_scan_nodes_by_type_json() filters at the engine
Added a typed scan function: walks the live nodes once, skips transparent layers, keeps only entries whose node_type matches the filter, sorts the survivors by salience, paginates. Header forward decl in el_runtime.h so callers can find it. Empty / NULL filter falls through to engram_scan_nodes_json so the existing GET /api/nodes contract is preserved exactly. This is what every list-X tool in the MCP wrapper has been wanting: listProcesses returning only Process nodes, not all of them, without the wrapper having to fetch + filter client-side.
This commit is contained in:
@@ -4840,6 +4840,43 @@ el_val_t engram_scan_nodes_json(el_val_t limit, el_val_t offset) {
|
||||
return el_wrap_str(b.buf);
|
||||
}
|
||||
|
||||
/* engram_scan_nodes_by_type_json — filter by node_type before paginating.
|
||||
* Empty / NULL type_v falls back to the unfiltered scan (existing behaviour).
|
||||
* Result is JSON array, salience-sorted, transparent layers skipped. */
|
||||
el_val_t engram_scan_nodes_by_type_json(el_val_t type_v, el_val_t limit, el_val_t offset) {
|
||||
const char* type_filter = EL_CSTR(type_v);
|
||||
if (!type_filter || !*type_filter) {
|
||||
return engram_scan_nodes_json(limit, offset);
|
||||
}
|
||||
EngramStore* g = engram_get();
|
||||
int64_t lim = (int64_t)limit; if (lim <= 0) lim = 100;
|
||||
int64_t off = (int64_t)offset; if (off < 0) off = 0;
|
||||
JsonBuf b; jb_init(&b);
|
||||
jb_putc(&b, '[');
|
||||
if (g->node_count == 0) { jb_putc(&b, ']'); return el_wrap_str(b.buf); }
|
||||
int64_t* idx = malloc((size_t)g->node_count * sizeof(int64_t));
|
||||
if (!idx) { jb_putc(&b, ']'); return el_wrap_str(b.buf); }
|
||||
int64_t live = 0;
|
||||
for (int64_t i = 0; i < g->node_count; i++) {
|
||||
if (engram_layer_is_transparent(g->nodes[i].layer_id)) continue;
|
||||
const char* nt = g->nodes[i].node_type;
|
||||
if (!nt || strcmp(nt, type_filter) != 0) continue;
|
||||
idx[live++] = i;
|
||||
}
|
||||
engram_sort_indices_by_salience(idx, live, g->nodes);
|
||||
int64_t end = off + lim;
|
||||
if (end > live) end = live;
|
||||
int first = 1;
|
||||
for (int64_t i = off; i < end; i++) {
|
||||
if (!first) jb_putc(&b, ',');
|
||||
engram_emit_node_json(&b, &g->nodes[idx[i]]);
|
||||
first = 0;
|
||||
}
|
||||
free(idx);
|
||||
jb_putc(&b, ']');
|
||||
return el_wrap_str(b.buf);
|
||||
}
|
||||
|
||||
el_val_t engram_neighbors_json(el_val_t node_id, el_val_t max_depth, el_val_t direction) {
|
||||
/* Re-implement here directly so we serialize without going through
|
||||
* the ElList path. Walks BFS to max_depth, emits {node, edge, hops}
|
||||
|
||||
Reference in New Issue
Block a user