rspace-online/lib/mi-tool-schema.ts

60 lines
3.5 KiB
TypeScript

/**
* MI Tool Schema — lightweight registry of canvas shape types with keyword
* matching, so MI can suggest relevant tools as clickable chips.
*/
export interface ToolHint {
tagName: string;
label: string;
icon: string;
keywords: string[];
}
const TOOL_HINTS: ToolHint[] = [
{ tagName: "folk-markdown", label: "Note", icon: "📝", keywords: ["note", "text", "markdown", "write", "document"] },
{ tagName: "folk-wrapper", label: "Card", icon: "📋", keywords: ["card", "wrapper", "container", "group"] },
{ tagName: "folk-slide", label: "Slide", icon: "🖼️", keywords: ["slide", "presentation", "deck"] },
{ tagName: "folk-chat", label: "Chat", icon: "💬", keywords: ["chat", "message", "conversation", "talk"] },
{ tagName: "folk-embed", label: "Embed", icon: "🔗", keywords: ["embed", "iframe", "website", "url", "link"] },
{ tagName: "folk-calendar", label: "Calendar", icon: "📅", keywords: ["calendar", "date", "schedule", "event"] },
{ tagName: "folk-map", label: "Map", icon: "🗺️", keywords: ["map", "location", "place", "geo"] },
{ tagName: "folk-image-gen", label: "AI Image", icon: "🎨", keywords: ["image", "picture", "photo", "generate", "art", "draw"] },
{ tagName: "folk-video-gen", label: "AI Video", icon: "🎬", keywords: ["video", "clip", "animate", "movie", "film"] },
{ tagName: "folk-prompt", label: "AI Chat", icon: "🤖", keywords: ["ai", "prompt", "llm", "assistant", "gpt"] },
{ tagName: "folk-transcription", label: "Transcribe", icon: "🎙️", keywords: ["transcribe", "audio", "speech", "voice", "record"] },
{ tagName: "folk-video-chat", label: "Video Call", icon: "📹", keywords: ["video call", "webcam", "meeting"] },
{ tagName: "folk-obs-note", label: "Obsidian Note", icon: "📓", keywords: ["obsidian", "note", "vault"] },
{ tagName: "folk-workflow-block", label: "Workflow", icon: "⚙️", keywords: ["workflow", "automation", "block", "process"] },
{ tagName: "folk-social-post", label: "Social Post", icon: "📣", keywords: ["social", "post", "twitter", "instagram", "campaign"] },
{ tagName: "folk-splat", label: "3D Gaussian", icon: "💎", keywords: ["3d", "splat", "gaussian", "point cloud"] },
{ tagName: "folk-drawfast", label: "Drawing", icon: "✏️", keywords: ["draw", "sketch", "whiteboard", "pencil"] },
{ tagName: "folk-rapp", label: "rApp Embed", icon: "📦", keywords: ["rapp", "module", "embed", "app"] },
{ tagName: "folk-feed", label: "Feed", icon: "📡", keywords: ["feed", "data", "stream", "flow"] },
{ tagName: "folk-piano", label: "Piano", icon: "🎹", keywords: ["piano", "music", "instrument", "midi"] },
{ tagName: "folk-choice-vote", label: "Vote", icon: "🗳️", keywords: ["vote", "poll", "election", "choice"] },
{ tagName: "folk-choice-rank", label: "Ranking", icon: "📊", keywords: ["rank", "order", "priority", "sort"] },
{ tagName: "folk-choice-spider", label: "Spider Chart", icon: "🕸️", keywords: ["spider", "radar", "criteria", "evaluate"] },
];
/**
* Given a user query, return matching tool hints (max 3).
* Matches if any keyword appears in the query (case-insensitive).
*/
export function suggestTools(query: string): ToolHint[] {
const q = query.toLowerCase();
const scored: { hint: ToolHint; score: number }[] = [];
for (const hint of TOOL_HINTS) {
let score = 0;
for (const kw of hint.keywords) {
if (q.includes(kw)) score += kw.length; // longer keyword match = higher relevance
}
if (score > 0) scored.push({ hint, score });
}
return scored
.sort((a, b) => b.score - a.score)
.slice(0, 3)
.map((s) => s.hint);
}