feat(memory-lancedb): support query cmd for llm CLI (#71112)

* feat(memory-lancedb): support query cmd for llm CLI

* address review comments

* address review comments

* trigger ci
This commit is contained in:
vinoyang
2026-04-29 18:42:40 +08:00
committed by GitHub
parent 4528682487
commit 6b44dce0c8

View File

@@ -256,6 +256,11 @@ class MemoryDB {
await this.ensureInitialized();
return this.table!.countRows();
}
async getTable(): Promise<LanceDB.Table> {
await this.ensureInitialized();
return this.table!;
}
}
// ============================================================================
@@ -815,6 +820,74 @@ export default definePluginEntry({
console.log(JSON.stringify(output, null, 2));
});
memory
.command("query")
.description("Query memories (non-vector search)")
.option("--cols <columns>", "Columns to select, comma-separated")
.option("--filter <condition>", "Filter condition")
.option("--limit <n>", "Limit number of results", "10")
.option("--order-by <order>", "Order by column and direction (e.g., createdAt:desc)")
.action(async (opts) => {
const table = await db.getTable();
let query = table.query();
let sortColAdded = false;
let sortColName: string | undefined;
if (opts.cols) {
const columns = (opts.cols as string).split(",").map((c: string) => c.trim());
if (opts.orderBy) {
const [sortCol] = opts.orderBy.split(":");
sortColName = sortCol;
if (!columns.includes(sortCol)) {
columns.push(sortCol);
sortColAdded = true;
}
}
query = query.select(columns);
} else {
query = query.select(["id", "text", "importance", "category", "createdAt"]);
}
if (opts.filter) {
const filterCondition = String(opts.filter);
if (filterCondition.length > 200) {
throw new Error("Filter condition exceeds maximum length of 200 characters");
}
if (!/^[a-zA-Z0-9_\-\s='"><!.,()%*]+$/.test(filterCondition)) {
throw new Error("Filter condition contains invalid characters");
}
query = query.where(filterCondition);
}
const limit = Number.parseInt(opts.limit, 10);
if (Number.isNaN(limit) || limit <= 0) {
throw new Error("Invalid limit: must be a positive integer");
}
// Fetch all filtered rows first if we need to order them in memory
if (!opts.orderBy) {
query = query.limit(limit);
}
let rows = await query.toArray();
if (opts.orderBy) {
const [col, dir] = opts.orderBy.split(":");
const direction = dir?.toLowerCase() === "desc" ? -1 : 1;
rows.sort((a, b) => {
if (a[col] < b[col]) {
return -1 * direction;
}
if (a[col] > b[col]) {
return 1 * direction;
}
return 0;
});
rows = rows.slice(0, limit);
if (sortColAdded && sortColName) {
for (const row of rows) {
delete row[sortColName];
}
}
}
console.log(JSON.stringify(rows, null, 2));
});
memory
.command("stats")
.description("Show memory statistics")