Add AI prompt tool for natural language graph operations
New MCP tool and portal UI for executing natural language instructions against the memory graph via Ollama (qwen3-coder:30b). Single LLM call generates a JSON action plan which is executed sequentially. Supports 8 action types: add_node, update_node, remove_node, add_edge, remove_edge, bulk_tag, reorganize, query. Actions can reference previous results via $result[N].field interpolation. Uses /api/chat with few-shot assistant example, format:json, and temperature:0 for reliable output.
This commit is contained in:
@@ -8,6 +8,7 @@ import QueryBar from './components/QueryBar';
|
||||
import LinkModal from './components/LinkModal';
|
||||
import Toast from './components/Toast';
|
||||
import MaintenancePanel from './components/MaintenancePanel';
|
||||
import PromptPanel from './components/PromptPanel';
|
||||
|
||||
export default function App() {
|
||||
const [selectedId, setSelectedId] = useState<string | null>(null);
|
||||
@@ -17,6 +18,7 @@ export default function App() {
|
||||
const [drawerOpen, setDrawerOpen] = useState(false);
|
||||
const [showQuery, setShowQuery] = useState(false);
|
||||
const [showMaintenance, setShowMaintenance] = useState(false);
|
||||
const [showPrompt, setShowPrompt] = useState(false);
|
||||
const qc = useQueryClient();
|
||||
|
||||
const refresh = useCallback(() => {
|
||||
@@ -38,13 +40,14 @@ export default function App() {
|
||||
const handler = (e: KeyboardEvent) => {
|
||||
if (e.key === 'Escape') {
|
||||
if (selectedId) setSelectedId(null);
|
||||
else if (showPrompt) setShowPrompt(false);
|
||||
else if (showQuery) setShowQuery(false);
|
||||
else if (drawerOpen) setDrawerOpen(false);
|
||||
}
|
||||
};
|
||||
window.addEventListener('keydown', handler);
|
||||
return () => window.removeEventListener('keydown', handler);
|
||||
}, [selectedId, drawerOpen, showQuery]);
|
||||
}, [selectedId, drawerOpen, showQuery, showPrompt]);
|
||||
|
||||
return (
|
||||
<div className="h-screen w-screen overflow-hidden relative">
|
||||
@@ -76,6 +79,13 @@ export default function App() {
|
||||
>
|
||||
?
|
||||
</button>
|
||||
<button
|
||||
onClick={() => setShowPrompt(!showPrompt)}
|
||||
className="w-12 h-12 rounded-full bg-amber-600/90 backdrop-blur border border-amber-500 text-white hover:bg-amber-500 shadow-lg flex items-center justify-center text-lg"
|
||||
title="AI Prompt"
|
||||
>
|
||||
✦
|
||||
</button>
|
||||
<button
|
||||
onClick={() => setShowMaintenance(!showMaintenance)}
|
||||
className="w-12 h-12 rounded-full bg-emerald-600/90 backdrop-blur border border-emerald-500 text-white hover:bg-emerald-500 shadow-lg flex items-center justify-center text-lg"
|
||||
@@ -141,6 +151,22 @@ export default function App() {
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Prompt panel — slides up from bottom */}
|
||||
{showPrompt && (
|
||||
<div className="fixed inset-0 z-40" onClick={() => setShowPrompt(false)}>
|
||||
<div className="absolute inset-0 bg-black/40" />
|
||||
<div
|
||||
className="absolute bottom-0 left-0 right-0 h-[70vh] animate-slide-in-up"
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
>
|
||||
<PromptPanel
|
||||
onClose={() => setShowPrompt(false)}
|
||||
onDone={() => { refresh(); notify('Prompt executed'); }}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{showAddNode && (
|
||||
<AddNodeModal
|
||||
onClose={() => setShowAddNode(false)}
|
||||
|
||||
Reference in New Issue
Block a user