180 lines
7.3 KiB
TypeScript
180 lines
7.3 KiB
TypeScript
import React from 'react';
|
|
import { useCopilotAction } from '@copilotkit/react-core';
|
|
import { blogWriterApi, BlogResearchResponse, BlogOutlineSection } from '../../services/blogWriterApi';
|
|
|
|
const useCopilotActionTyped = useCopilotAction as any;
|
|
|
|
interface ResearchDataActionsProps {
|
|
research: BlogResearchResponse | null;
|
|
onOutlineCreated: (outline: BlogOutlineSection[]) => void;
|
|
onTitleOptionsSet: (titles: string[]) => void;
|
|
}
|
|
|
|
export const ResearchDataActions: React.FC<ResearchDataActionsProps> = ({
|
|
research,
|
|
onOutlineCreated,
|
|
onTitleOptionsSet
|
|
}) => {
|
|
// Chat with Research Data
|
|
useCopilotActionTyped({
|
|
name: 'chatWithResearchData',
|
|
description: 'Chat with the research data to explore insights, ask questions, and get recommendations',
|
|
parameters: [
|
|
{ name: 'question', type: 'string', description: 'Question or topic to explore in the research data', required: true }
|
|
],
|
|
handler: async ({ question }: { question: string }) => {
|
|
if (!research) {
|
|
return {
|
|
success: false,
|
|
message: 'No research data available. Please complete research first.',
|
|
suggestion: 'Try asking: "I want to research a topic for my blog"'
|
|
};
|
|
}
|
|
|
|
// Provide comprehensive research context for the copilot to answer intelligently
|
|
const researchContext = {
|
|
sources: research.sources.length,
|
|
primaryKeywords: research.keyword_analysis?.primary || [],
|
|
secondaryKeywords: research.keyword_analysis?.secondary || [],
|
|
longTailKeywords: research.keyword_analysis?.long_tail || [],
|
|
searchIntent: research.keyword_analysis?.search_intent || 'informational',
|
|
contentAngles: research.suggested_angles || [],
|
|
competitorAnalysis: research.competitor_analysis || {},
|
|
searchQueries: research.search_queries || [],
|
|
topSources: research.sources.slice(0, 5).map(s => ({
|
|
title: s.title,
|
|
credibility: s.credibility_score,
|
|
excerpt: s.excerpt?.substring(0, 200)
|
|
}))
|
|
};
|
|
|
|
return {
|
|
success: true,
|
|
message: `I can help you explore the research data! Here's what I found:`,
|
|
research_context: researchContext,
|
|
user_question: question,
|
|
next_step_suggestion: 'Ready to create an outline? Try: "Create outline with custom inputs" or "Let\'s proceed to create an outline"'
|
|
};
|
|
},
|
|
render: ({ status, result }: any) => {
|
|
if (status === 'complete' && result?.success) {
|
|
return (
|
|
<div style={{
|
|
padding: '16px',
|
|
backgroundColor: '#f0f8ff',
|
|
borderRadius: '8px',
|
|
border: '1px solid #1976d2',
|
|
margin: '8px 0'
|
|
}}>
|
|
<h4 style={{ margin: '0 0 12px 0', color: '#1976d2' }}>🔍 Research Data Insights</h4>
|
|
<div style={{ fontSize: '14px', color: '#333', lineHeight: '1.5', marginBottom: '12px' }}>
|
|
<p style={{ margin: '0 0 8px 0' }}><strong>Your Question:</strong> {result.user_question}</p>
|
|
<p style={{ margin: '0 0 8px 0' }}><strong>Research Summary:</strong></p>
|
|
<ul style={{ margin: '0 0 8px 0', paddingLeft: '20px' }}>
|
|
<li>{result.research_context.sources} authoritative sources found</li>
|
|
<li>Primary keywords: {result.research_context.primaryKeywords.join(', ')}</li>
|
|
<li>Search intent: {result.research_context.searchIntent}</li>
|
|
<li>{result.research_context.contentAngles.length} content angles identified</li>
|
|
</ul>
|
|
</div>
|
|
<div style={{
|
|
padding: '12px',
|
|
backgroundColor: '#e3f2fd',
|
|
borderRadius: '6px',
|
|
border: '1px solid #1976d2'
|
|
}}>
|
|
<p style={{ margin: '0 0 8px 0', fontWeight: '500', color: '#1976d2' }}>💡 Next Step:</p>
|
|
<p style={{ margin: '0', fontSize: '14px', color: '#333' }}>{result.next_step_suggestion}</p>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|
|
return null;
|
|
}
|
|
});
|
|
|
|
// Create Outline with Custom Inputs
|
|
useCopilotActionTyped({
|
|
name: 'createOutlineWithCustomInputs',
|
|
description: 'Create an outline with custom instructions and requirements from the user',
|
|
parameters: [
|
|
{ name: 'customInstructions', type: 'string', description: 'Custom instructions for outline generation', required: true }
|
|
],
|
|
handler: async ({ customInstructions }: { customInstructions: string }) => {
|
|
if (!research) {
|
|
return {
|
|
success: false,
|
|
message: 'No research data available. Please complete research first.',
|
|
suggestion: 'Try asking: "I want to research a topic for my blog"'
|
|
};
|
|
}
|
|
|
|
try {
|
|
// Create a custom outline request with user instructions
|
|
const customOutlineRequest = {
|
|
research: research,
|
|
word_count: 1500,
|
|
custom_instructions: customInstructions
|
|
};
|
|
|
|
const outlineResponse = await blogWriterApi.generateOutline(customOutlineRequest);
|
|
onOutlineCreated(outlineResponse.outline);
|
|
onTitleOptionsSet(outlineResponse.title_options);
|
|
|
|
return {
|
|
success: true,
|
|
message: `Created custom outline with ${outlineResponse.outline.length} sections based on your instructions: "${customInstructions}"`,
|
|
outline_sections: outlineResponse.outline.length,
|
|
title_options: outlineResponse.title_options.length,
|
|
next_step_suggestion: 'Great! Now you can enhance sections, generate content, or refine the outline further.'
|
|
};
|
|
} catch (error) {
|
|
return {
|
|
success: false,
|
|
message: `Custom outline creation failed: ${error}`,
|
|
suggestion: 'Try providing more specific instructions or ask me to help refine your requirements.'
|
|
};
|
|
}
|
|
},
|
|
render: ({ status }: any) => {
|
|
if (status === 'inProgress' || status === 'executing') {
|
|
return (
|
|
<div style={{
|
|
padding: '16px',
|
|
backgroundColor: '#f8f9fa',
|
|
borderRadius: '8px',
|
|
border: '1px solid #e0e0e0',
|
|
margin: '8px 0'
|
|
}}>
|
|
<div style={{ display: 'flex', alignItems: 'center', gap: '12px', marginBottom: '12px' }}>
|
|
<div style={{
|
|
width: '20px',
|
|
height: '20px',
|
|
border: '2px solid #673ab7',
|
|
borderTop: '2px solid transparent',
|
|
borderRadius: '50%',
|
|
animation: 'spin 1s linear infinite'
|
|
}} />
|
|
<h4 style={{ margin: 0, color: '#673ab7' }}>🎨 Creating Custom Outline</h4>
|
|
</div>
|
|
<div style={{ fontSize: '14px', color: '#666', lineHeight: '1.5' }}>
|
|
<p style={{ margin: '0 0 8px 0' }}>• Analyzing your custom instructions...</p>
|
|
<p style={{ margin: '0 0 8px 0' }}>• Applying requirements to research data...</p>
|
|
<p style={{ margin: '0' }}>• Generating tailored outline structure...</p>
|
|
</div>
|
|
<style>{`
|
|
@keyframes spin {
|
|
0% { transform: rotate(0deg); }
|
|
100% { transform: rotate(360deg); }
|
|
}
|
|
`}</style>
|
|
</div>
|
|
);
|
|
}
|
|
return null;
|
|
}
|
|
});
|
|
|
|
return null; // This component only provides the CopilotKit actions, no UI
|
|
};
|