rspace-online/server/mi-data-queries.ts

67 lines
2.6 KiB
TypeScript

/**
* MI Data Queries — dispatches content queries to module-specific readers.
*
* Used by the agentic loop to fetch module data server-side and feed
* results back into the LLM context.
*/
import { getUpcomingEventsForMI } from "../modules/rcal/mod";
import { getRecentNotesForMI } from "../modules/rnotes/mod";
import { getRecentTasksForMI } from "../modules/rtasks/mod";
export interface MiQueryResult {
ok: boolean;
module: string;
queryType: string;
data: any;
summary: string;
}
/**
* Query module content by type. Returns structured data + a text summary
* the LLM can consume.
*/
export function queryModuleContent(
space: string,
module: string,
queryType: "recent" | "summary" | "count",
limit = 5,
): MiQueryResult {
switch (module) {
case "rnotes": {
const notes = getRecentNotesForMI(space, limit);
if (queryType === "count") {
return { ok: true, module, queryType, data: { count: notes.length }, summary: `${notes.length} recent notes found.` };
}
const lines = notes.map((n) => `- "${n.title}" (${n.type}, updated ${new Date(n.updatedAt).toLocaleDateString()})${n.tags.length ? ` [${n.tags.join(", ")}]` : ""}: ${n.contentPlain.slice(0, 100)}...`);
return { ok: true, module, queryType, data: notes, summary: lines.length ? `Recent notes:\n${lines.join("\n")}` : "No notes found." };
}
case "rtasks": {
const tasks = getRecentTasksForMI(space, limit);
if (queryType === "count") {
return { ok: true, module, queryType, data: { count: tasks.length }, summary: `${tasks.length} open tasks found.` };
}
const lines = tasks.map((t) => `- "${t.title}" [${t.status}]${t.priority ? ` (${t.priority})` : ""}${t.description ? `: ${t.description.slice(0, 80)}` : ""}`);
return { ok: true, module, queryType, data: tasks, summary: lines.length ? `Open tasks:\n${lines.join("\n")}` : "No open tasks." };
}
case "rcal": {
const events = getUpcomingEventsForMI(space, 14, limit);
if (queryType === "count") {
return { ok: true, module, queryType, data: { count: events.length }, summary: `${events.length} upcoming events.` };
}
const lines = events.map((e) => {
const date = e.allDay ? e.start.split("T")[0] : e.start;
let line = `- ${date}: ${e.title}`;
if (e.location) line += ` (${e.location})`;
return line;
});
return { ok: true, module, queryType, data: events, summary: lines.length ? `Upcoming events:\n${lines.join("\n")}` : "No upcoming events." };
}
default:
return { ok: false, module, queryType, data: null, summary: `Module "${module}" does not support content queries.` };
}
}