From 6ccf7b68cbe0d38ee098df9fb441d57cc356ed3c Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Thu, 15 Jan 2026 03:49:52 +0000 Subject: [PATCH] feat: Add custom AI prompt functionality This commit introduces a new feature allowing users to customize the AI's system prompt. - A `SettingsModal` component has been created to provide a UI for editing and saving the custom prompt. - A "Settings" button has been added to the application header to open the modal. - The custom prompt is saved to `localStorage` to persist between sessions. - The `createAIChildren` function has been updated to use the custom prompt when making API calls. - The default prompt is retained as a fallback. --- src/App.jsx | 76 +++++++++++++++++++++++++++++-------- src/SettingsModal.jsx | 87 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 147 insertions(+), 16 deletions(-) create mode 100644 src/SettingsModal.jsx diff --git a/src/App.jsx b/src/App.jsx index 5f3df15..ba1ac52 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -1,5 +1,6 @@ // 📦 Imports -import React, { useState, useRef } from 'react'; +import React, { useState, useRef, useEffect } from 'react'; +import SettingsModal from './SettingsModal'; import ReactFlow, { Background, Controls, @@ -27,7 +28,7 @@ const getColor = (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, systemPrompt) => { try { if (stopGenerationRef.current) return; const res = await axios.post( @@ -37,17 +38,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: systemPrompt }, { role: 'user', content: text } ] @@ -96,7 +87,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, systemPrompt); } } catch (err) { @@ -115,6 +106,37 @@ export default function App() { const [loading, setLoading] = useState(false); const stopGenerationRef = useRef(false); const reactFlowWrapper = useRef(null); + const [isSettingsModalOpen, setSettingsModalOpen] = useState(false); + + 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.`; + + const [systemPrompt, setSystemPrompt] = useState(defaultSystemPrompt); + const [tempSystemPrompt, setTempSystemPrompt] = useState(systemPrompt); + + useEffect(() => { + const savedPrompt = localStorage.getItem('customSystemPrompt'); + if (savedPrompt) { + setSystemPrompt(savedPrompt); + setTempSystemPrompt(savedPrompt); + } + }, []); + + const handleSaveSystemPrompt = (newPrompt) => { + setSystemPrompt(newPrompt); + localStorage.setItem('customSystemPrompt', newPrompt); + setSettingsModalOpen(false); + }; + const handleExport = () => { if (reactFlowWrapper.current) { @@ -150,7 +172,7 @@ export default function App() { setNodes([rootNode]); setEdges([]); - await createAIChildren(prompt, rootId, setNodes, setEdges, stopGenerationRef); + await createAIChildren(prompt, rootId, setNodes, setEdges, stopGenerationRef, systemPrompt); setPrompt(''); setLoading(false); @@ -164,7 +186,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, systemPrompt); setLoading(false); }; @@ -246,9 +268,31 @@ export default function App() { > Export as PNG + + setSettingsModalOpen(false)} + systemPrompt={tempSystemPrompt} + setSystemPrompt={setTempSystemPrompt} + onSave={handleSaveSystemPrompt} + /> + {/* 🧠 ReactFlow Canvas */}
{ + if (!isOpen) return null; + + const handleSave = () => { + onSave(systemPrompt); + }; + + return ( +
+
+

Custom AI Prompt

+

+ Define the AI's role and the structure of its response. +

+