From f4feae7f129e6cc70925edde916696b318d7d35f Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Tue, 13 Jan 2026 03:57:32 +0000 Subject: [PATCH] feat: Allow user to customize AI system prompt This commit introduces a new feature that allows users to customize the system prompt used by the AI to generate mind map nodes. Key changes: - A new `SettingsModal` component has been created to house the new settings. - A "Settings" button has been added to the main application header to open the modal. - The custom system prompt is saved to the browser's local storage to persist between sessions. - The core AI logic in `createAIChildren` has been updated to use the custom prompt if it exists, otherwise falling back to the default prompt. --- src/App.jsx | 93 ++++++++++++++++++++++++++++++++++++------- src/SettingsModal.jsx | 64 +++++++++++++++++++++++++++++ 2 files changed, 142 insertions(+), 15 deletions(-) create mode 100644 src/SettingsModal.jsx diff --git a/src/App.jsx b/src/App.jsx index 5f3df15..5ff8a87 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -11,6 +11,7 @@ import 'reactflow/dist/style.css'; import axios from 'axios'; import html2canvas from 'html2canvas'; import { saveAs } from 'file-saver'; +import SettingsModal from './SettingsModal'; // 🧠 Initial State & Helpers const initialNodes = []; @@ -26,8 +27,20 @@ const getColor = (type) => { } }; +const defaultSystemPrompt = `You are an expert in cause-and-effect analysis. + +Given a news headline or event, break it down into a chain of consequences, like a domino effect. + +Each node must: +- Be short (max 15 words) +- Represent one specific consequence +- Be categorized as either: 'positive', 'neutral', or 'negative' +- Be logically linked to the prompt + +Return only 3 outputs: one of each type.`; + // 🤖 AI Logic with Domino Effect Thinking (Updated: Using Puter AI API) -const createAIChildren = async (text, parentId, setNodes, setEdges, stopGenerationRef) => { +const createAIChildren = async (text, parentId, setNodes, setEdges, stopGenerationRef, customSystemPrompt) => { try { if (stopGenerationRef.current) return; const res = await axios.post( @@ -37,17 +50,7 @@ const createAIChildren = async (text, parentId, setNodes, setEdges, stopGenerati messages: [ { role: 'system', - content: `You are an expert in cause-and-effect analysis. - -Given a news headline or event, break it down into a chain of consequences, like a domino effect. - -Each node must: -- Be short (max 15 words) -- Represent one specific consequence -- Be categorized as either: 'positive', 'neutral', or 'negative' -- Be logically linked to the prompt - -Return only 3 outputs: one of each type.` + content: customSystemPrompt || defaultSystemPrompt, }, { role: 'user', content: text } ] @@ -96,7 +99,7 @@ Return only 3 outputs: one of each type.` // Recursively expand each child one level deep for (const n of newNodes) { if (stopGenerationRef.current) break; - await createAIChildren(n.data.label, n.id, setNodes, setEdges, stopGenerationRef); + await createAIChildren(n.data.label, n.id, setNodes, setEdges, stopGenerationRef, customSystemPrompt); } } catch (err) { @@ -113,6 +116,8 @@ export default function App() { const [edges, setEdges] = useState(initialEdges); const [prompt, setPrompt] = useState(''); const [loading, setLoading] = useState(false); + const [isSettingsModalOpen, setSettingsModalOpen] = useState(false); + const [customSystemPrompt, setCustomSystemPrompt] = useState(localStorage.getItem('customSystemPrompt') || ''); const stopGenerationRef = useRef(false); const reactFlowWrapper = useRef(null); @@ -150,7 +155,7 @@ export default function App() { setNodes([rootNode]); setEdges([]); - await createAIChildren(prompt, rootId, setNodes, setEdges, stopGenerationRef); + await createAIChildren(prompt, rootId, setNodes, setEdges, stopGenerationRef, customSystemPrompt); setPrompt(''); setLoading(false); @@ -164,7 +169,7 @@ export default function App() { const onNodeClick = async (_event, node) => { stopGenerationRef.current = false; setLoading(true); - await createAIChildren(node.data.label, node.id, setNodes, setEdges, stopGenerationRef); + await createAIChildren(node.data.label, node.id, setNodes, setEdges, stopGenerationRef, customSystemPrompt); setLoading(false); }; @@ -246,9 +251,67 @@ export default function App() { > Export as PNG + + setSettingsModalOpen(false)} + > +
+ +