Show update instructions CTA to trigger copilot when new data sources are attached to agents

This commit is contained in:
akhisud3195 2025-05-09 19:41:10 +05:30
parent e4cd71e6b1
commit 5bc1dc8b37
3 changed files with 82 additions and 14 deletions

View file

@ -34,7 +34,7 @@ interface AppProps {
dataSources?: z.infer<typeof DataSource>[];
}
const App = forwardRef<{ handleCopyChat: () => void }, AppProps>(function App({
const App = forwardRef<{ handleCopyChat: () => void; handleUserMessage: (message: string) => void }, AppProps>(function App({
projectId,
workflow,
dispatch,
@ -133,7 +133,8 @@ const App = forwardRef<{ handleCopyChat: () => void }, AppProps>(function App({
}, [messages, onCopyJson]);
useImperativeHandle(ref, () => ({
handleCopyChat
handleCopyChat,
handleUserMessage
}), [handleCopyChat]);
return (
@ -194,25 +195,25 @@ const App = forwardRef<{ handleCopyChat: () => void }, AppProps>(function App({
);
});
export function Copilot({
projectId,
workflow,
chatContext = undefined,
dispatch,
isInitialState = false,
dataSources,
}: {
export const Copilot = forwardRef<{ handleUserMessage: (message: string) => void }, {
projectId: string;
workflow: z.infer<typeof Workflow>;
chatContext?: z.infer<typeof CopilotChatContext>;
dispatch: (action: WorkflowDispatch) => void;
isInitialState?: boolean;
dataSources?: z.infer<typeof DataSource>[];
}) {
}>(({
projectId,
workflow,
chatContext = undefined,
dispatch,
isInitialState = false,
dataSources,
}, ref) => {
const [copilotKey, setCopilotKey] = useState(0);
const [showCopySuccess, setShowCopySuccess] = useState(false);
const [messages, setMessages] = useState<z.infer<typeof CopilotMessage>[]>([]);
const appRef = useRef<{ handleCopyChat: () => void }>(null);
const appRef = useRef<{ handleCopyChat: () => void; handleUserMessage: (message: string) => void }>(null);
function handleNewChat() {
setCopilotKey(prev => prev + 1);
@ -228,6 +229,16 @@ export function Copilot({
}, 2000);
}
// Expose handleUserMessage through ref
useImperativeHandle(ref, () => ({
handleUserMessage: (message: string) => {
const app = appRef.current as any;
if (app?.handleUserMessage) {
app.handleUserMessage(message);
}
}
}), []);
return (
<Panel variant="copilot"
tourTarget="copilot"
@ -288,5 +299,5 @@ export function Copilot({
</div>
</Panel>
);
}
});

View file

@ -22,6 +22,7 @@ import { EditableField } from "@/app/lib/components/editable-field";
import { USE_TRANSFER_CONTROL_OPTIONS } from "@/app/lib/feature_flags";
import { Input } from "@/components/ui/input";
import { Info } from "lucide-react";
import { useCopilot } from "../copilot/use-copilot";
// Common section header styles
const sectionHeaderStyles = "text-xs font-medium uppercase tracking-wider text-gray-500 dark:text-gray-400";
@ -44,6 +45,7 @@ export function AgentConfig({
handleUpdate,
handleClose,
useRag,
triggerCopilotChat,
}: {
projectId: string,
workflow: z.infer<typeof Workflow>,
@ -56,6 +58,7 @@ export function AgentConfig({
handleUpdate: (agent: z.infer<typeof WorkflowAgent>) => void,
handleClose: () => void,
useRag: boolean,
triggerCopilotChat: (message: string) => void,
}) {
const [isAdvancedConfigOpen, setIsAdvancedConfigOpen] = useState(false);
const [showGenerateModal, setShowGenerateModal] = useState(false);
@ -65,11 +68,42 @@ export function AgentConfig({
const [localName, setLocalName] = useState(agent.name);
const [nameError, setNameError] = useState<string | null>(null);
const [activeTab, setActiveTab] = useState<TabType>('instructions');
const [showRagCta, setShowRagCta] = useState(false);
const [previousRagSources, setPreviousRagSources] = useState<string[]>([]);
const {
start: startCopilotChat,
} = useCopilot({
projectId,
workflow,
context: null,
dataSources
});
useEffect(() => {
setLocalName(agent.name);
}, [agent.name]);
// Track changes in RAG datasources
useEffect(() => {
const currentSources = agent.ragDataSources || [];
// Show CTA when transitioning from 0 to 1 datasource
if (currentSources.length === 1 && previousRagSources.length === 0) {
setShowRagCta(true);
}
// Hide CTA when all datasources are deleted
if (currentSources.length === 0) {
setShowRagCta(false);
}
setPreviousRagSources(currentSources);
}, [agent.ragDataSources]);
const handleUpdateInstructions = async () => {
const message = `Update the instructions for agent "${agent.name}" to use the rag tool (rag_search) since data sources have been added. If this has already been done, do not take any action, but let me know.`;
triggerCopilotChat(message);
setShowRagCta(false);
};
// Add effect to handle control type update when transfer control is disabled
useEffect(() => {
if (!USE_TRANSFER_CONTROL_OPTIONS && agent.controlType !== 'retain') {
@ -455,7 +489,7 @@ export function AgentConfig({
RAG
</label>
<div className="flex flex-col gap-3">
<div>
<div className="flex items-center gap-3">
<Select
variant="bordered"
placeholder="Add data source"
@ -481,6 +515,17 @@ export function AgentConfig({
))
}
</Select>
{showRagCta && (
<CustomButton
variant="primary"
size="sm"
onClick={handleUpdateInstructions}
className="whitespace-nowrap"
>
Update Instructions
</CustomButton>
)}
</div>
<div className="flex flex-col gap-2">

View file

@ -611,6 +611,16 @@ export function WorkflowEditor({
const [isMcpImportModalOpen, setIsMcpImportModalOpen] = useState(false);
const [isInitialState, setIsInitialState] = useState(true);
const [showTour, setShowTour] = useState(true);
const copilotRef = useRef<{ handleUserMessage: (message: string) => void }>(null);
// Function to trigger copilot chat
const triggerCopilotChat = useCallback((message: string) => {
setShowCopilot(true);
// Small delay to ensure copilot is mounted
setTimeout(() => {
copilotRef.current?.handleUserMessage(message);
}, 100);
}, []);
console.log(`workflow editor chat key: ${state.present.chatKey}`);
@ -992,6 +1002,7 @@ export function WorkflowEditor({
handleUpdate={handleUpdateAgent.bind(null, state.present.selection.name)}
handleClose={handleUnselectAgent}
useRag={useRag}
triggerCopilotChat={triggerCopilotChat}
/>}
{state.present.selection?.type === "tool" && <ToolConfig
key={state.present.selection.name}
@ -1020,6 +1031,7 @@ export function WorkflowEditor({
onResize={(size) => setCopilotWidth(size)}
>
<Copilot
ref={copilotRef}
projectId={state.present.workflow.projectId}
workflow={state.present.workflow}
dispatch={dispatch}