diff --git a/app/page.tsx b/app/page.tsx index ae740c5..bd70585 100644 --- a/app/page.tsx +++ b/app/page.tsx @@ -10,6 +10,7 @@ import UXDesignerPrompt from "@/components/UXDesignerPrompt"; import SlidesGenerator from "@/components/SlidesGenerator"; import GoogleAdsGenerator from "@/components/GoogleAdsGenerator"; import MarketResearcher from "@/components/MarketResearcher"; +import AIAssist from "@/components/AIAssist"; import HistoryPanel from "@/components/HistoryPanel"; import SettingsPanel from "@/components/SettingsPanel"; import modelAdapter from "@/lib/services/adapter-instance"; @@ -38,6 +39,8 @@ export default function Home() { return ; case "market-research": return ; + case "ai-assist": + return ; case "history": return ; case "settings": diff --git a/components/AIAssist.tsx b/components/AIAssist.tsx new file mode 100644 index 0000000..e1637fb --- /dev/null +++ b/components/AIAssist.tsx @@ -0,0 +1,386 @@ +"use client"; + +import { useState, useRef, useEffect } from "react"; +import { Button } from "@/components/ui/button"; +import { Input } from "@/components/ui/input"; +import { Card, CardHeader, CardTitle, CardDescription, CardContent } from "@/components/ui/card"; +import { Badge } from "@/components/ui/badge"; +import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"; +import useStore from "@/lib/store"; +import { translations } from "@/lib/i18n/translations"; +import modelAdapter from "@/lib/services/adapter-instance"; +import { + MessageSquare, Send, Sparkles, Brain, Cpu, Code2, Palette, FileText, Search, + BarChart, Rocket, Terminal, Eye, History, Trash2, Loader2, Bot, User, + Settings, Layers, AppWindow, Smartphone, Monitor, X +} from "lucide-react"; +import { cn } from "@/lib/utils"; +import { AIAssistMessage } from "@/types"; + +const AGENTS = [ + { id: "general", label: "General Intel", icon: Bot, color: "slate" }, + { id: "content", label: "Content Optimization", icon: FileText, color: "amber" }, + { id: "seo", label: "SEO Analyst", icon: Search, color: "emerald" }, + { id: "smm", label: "SMM Strategy", icon: BarChart, color: "pink" }, + { id: "pm", label: "Project Manager", icon: Rocket, color: "indigo" }, + { id: "code", label: "Code Architect", icon: Terminal, color: "violet" }, + { id: "design", label: "UI/UX Designer", icon: Palette, color: "orange" }, + { id: "web", label: "Web Dev Preview", icon: Monitor, color: "blue" }, + { id: "app", label: "App Dev Preview", icon: Smartphone, color: "cyan" } +]; + +const AIAssist = () => { + const { language, selectedProvider, selectedModels, apiKeys, aiAssistHistory, setAIAssistHistory } = useStore(); + const t = translations[language].aiAssist; + const common = translations[language].common; + + const [input, setInput] = useState(""); + const [isProcessing, setIsProcessing] = useState(false); + const [currentAgent, setCurrentAgent] = useState("general"); + const [activeTab, setActiveTab] = useState("chat"); + const [previewData, setPreviewData] = useState<{ type: string; data: string; language?: string } | null>(null); + + const scrollRef = useRef(null); + + useEffect(() => { + if (scrollRef.current) { + scrollRef.current.scrollTop = scrollRef.current.scrollHeight; + } + }, [aiAssistHistory]); + + const handleSendMessage = async () => { + if (!input.trim() || isProcessing) return; + + const userMessage: AIAssistMessage = { + role: "user", + content: input, + timestamp: new Date() + }; + + setAIAssistHistory(prev => [...prev, userMessage]); + setInput(""); + setIsProcessing(true); + + try { + const apiKey = apiKeys[selectedProvider]; + const isQwenOAuth = selectedProvider === "qwen" && modelAdapter.hasQwenAuth(); + + if (!isQwenOAuth && (!apiKey || !apiKey.trim())) { + throw new Error(`Please configure your ${selectedProvider.toUpperCase()} API key in Settings`); + } + + // Call model adapter for AI Assist + // Note: We'll implement generateAIAssist in model-adapter.ts next + const result = await modelAdapter.generateAIAssist({ + messages: aiAssistHistory.concat(userMessage), + currentAgent + }, selectedProvider, selectedModels[selectedProvider]); + + if (result.success && result.data) { + try { + // Expecting a structured response with possible agent switch and preview + const cleanJson = result.data.replace(/```json\s*([\s\S]*?)\s*```/i, '$1').trim(); + const parsed = JSON.parse(cleanJson); + + const assistantMessage: AIAssistMessage = { + role: "assistant", + content: parsed.content, + agent: parsed.agent || currentAgent, + preview: parsed.preview, + timestamp: new Date() + }; + + if (parsed.agent && parsed.agent !== currentAgent) { + setCurrentAgent(parsed.agent); + } + + if (parsed.preview) { + setPreviewData(parsed.preview); + setActiveTab("preview"); + } + + setAIAssistHistory(prev => [...prev, assistantMessage]); + } catch (e) { + // Fallback to plain text if JSON parsing fails + const assistantMessage: AIAssistMessage = { + role: "assistant", + content: result.data, + agent: currentAgent, + timestamp: new Date() + }; + setAIAssistHistory(prev => [...prev, assistantMessage]); + } + } else { + throw new Error(result.error || "Failed to get response"); + } + } catch (err) { + const errorMessage: AIAssistMessage = { + role: "system", + content: err instanceof Error ? err.message : "An unexpected error occurred", + timestamp: new Date() + }; + setAIAssistHistory(prev => [...prev, errorMessage]); + } finally { + setIsProcessing(false); + } + }; + + const clearHistory = () => { + setAIAssistHistory([]); + setPreviewData(null); + setActiveTab("chat"); + setCurrentAgent("general"); + }; + + const renderPreview = () => { + if (!previewData) return ( +
+ +

No active preview to display

+
+ ); + + switch (previewData.type) { + case "code": + case "web": + case "app": + return ( +
+
+
+ + Live Execution Sandbox +
+ Secure Booted +
+
+
{previewData.data}
+
+ +
+
+
+ ); + case "design": + return ( +
+
+
+ + UI Layout Preview +
+
+
+
+ {previewData.data} +
+
+
+ ); + default: + return ( +
+
+ {previewData.data} +
+
+ ); + } + }; + + return ( +
+ {/* Header Section */} +
+
+
+
+ +
+
+

{t.title}

+

{t.description}

+
+
+
+ +
+
+
+ +
+ {/* Chat Panel */} + + +
+
+ + Conversation Thread +
+
+ {AGENTS.map((agent) => ( + + ))} +
+
+
+ + +
+ {aiAssistHistory.length === 0 ? ( +
+
+ +
+

{t.chatStart}

+

Start a conversation to activate specialized AI agents for code, design, SEO, and more.

+
+ ) : ( + aiAssistHistory.map((msg, i) => ( +
+
+ {msg.role === "user" ? : } +
+
+ {msg.agent && ( + + {AGENTS.find(a => a.id === msg.agent)?.label || msg.agent} + + )} +
+ {msg.content} +
+ + {msg.timestamp.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' })} + +
+
+ )) + )} + {isProcessing && ( +
+
+ +
+
+
+
+
+
+
+
+
+
+
+ )} +
+ + {/* Input Area */} +
+
+
+
+
+ setInput(e.target.value)} + onKeyDown={(e) => e.key === 'Enter' && !e.shiftKey && handleSendMessage()} + placeholder={t.placeholder} + className="h-14 pl-12 pr-4 bg-slate-50 border-slate-200 focus:bg-white focus:ring-4 focus:ring-indigo-500/10 transition-all rounded-2xl font-medium" + /> +
+ +
+
+ +
+
+
+ + +
+
+ Powered by {selectedProvider.toUpperCase()} / {selectedModels[selectedProvider]} +
+
+
+
+ + + + {/* Preview Panel (Conditional) */} + {activeTab === "preview" && ( + + +
+ + {t.preview} +
+ +
+ + {renderPreview()} + +
+ )} +
+
+ ); +}; + +export default AIAssist; diff --git a/components/Sidebar.tsx b/components/Sidebar.tsx index 9e60913..996a7d2 100644 --- a/components/Sidebar.tsx +++ b/components/Sidebar.tsx @@ -3,11 +3,11 @@ import { useState } from "react"; import { Button } from "@/components/ui/button"; import useStore from "@/lib/store"; -import { Sparkles, FileText, ListTodo, Palette, Presentation, History, Settings, Github, Menu, X, Megaphone, Languages, Search } from "lucide-react"; +import { Sparkles, FileText, ListTodo, Palette, Presentation, History, Settings, Github, Menu, X, Megaphone, Languages, Search, MessageSquare } from "lucide-react"; import { cn } from "@/lib/utils"; import { translations } from "@/lib/i18n/translations"; -export type View = "enhance" | "prd" | "action" | "uxdesigner" | "slides" | "googleads" | "market-research" | "history" | "settings"; +export type View = "enhance" | "prd" | "action" | "uxdesigner" | "slides" | "googleads" | "market-research" | "ai-assist" | "history" | "settings"; interface SidebarProps { currentView: View; @@ -28,6 +28,7 @@ export default function Sidebar({ currentView, onViewChange }: SidebarProps) { { id: "slides" as View, label: t.slidesGen, icon: Presentation }, { id: "googleads" as View, label: t.googleAds, icon: Megaphone }, { id: "market-research" as View, label: t.marketResearch, icon: Search }, + { id: "ai-assist" as View, label: t.aiAssist, icon: MessageSquare }, { id: "history" as View, label: t.history, icon: History, count: history.length }, { id: "settings" as View, label: t.settings, icon: Settings }, ]; diff --git a/lib/i18n/translations.ts b/lib/i18n/translations.ts index 859125b..3e2acbf 100644 --- a/lib/i18n/translations.ts +++ b/lib/i18n/translations.ts @@ -12,6 +12,7 @@ export const translations = { googleAds: "Google Ads", uxDesigner: "UX Designer", marketResearch: "Market Research", + aiAssist: "AI Assist", settings: "Settings", history: "History", }, @@ -148,6 +149,16 @@ export const translations = { "Synthesizing strategic advantages and identifying gaps...", "Finalizing comprehensive intelligence report..." ] + }, + aiAssist: { + title: "AI Assist", + description: "Conversational intelligence with agent switching", + placeholder: "Discuss any topic, concern or project...", + chatStart: "How can I help you today?", + switchingAgent: "Switching to specialized agent...", + routing: "Routing your request...", + preview: "Real-time Preview", + actions: "Agent Actions" } }, ru: { @@ -161,6 +172,7 @@ export const translations = { googleAds: "Google Реклама", uxDesigner: "UX Дизайнер", marketResearch: "Анализ рынка", + aiAssist: "ИИ Ассистент", settings: "Настройки", history: "История", }, @@ -297,6 +309,16 @@ export const translations = { "Синтез стратегических преимуществ и выявление пробелов...", "Финализация подробного отчета о разведке..." ] + }, + aiAssist: { + title: "ИИ Ассистент", + description: "Диалоговый интеллект с переключением агентов", + placeholder: "Обсудите любую тему, проблему или проект...", + chatStart: "Чем я могу помочь вам сегодня?", + switchingAgent: "Переключение на специализированного агента...", + routing: "Маршрутизация вашего запроса...", + preview: "Предпросмотр в реальном времени", + actions: "Действия агента" } }, he: { @@ -310,6 +332,7 @@ export const translations = { googleAds: "Google Ads", uxDesigner: "מעצב UX", marketResearch: "מחקר שוק", + aiAssist: "סייען AI", settings: "הגדרות", history: "היסטוריה", }, @@ -446,6 +469,16 @@ export const translations = { "מסנכרן יתרונות אסטרטגיים ומזהה פערים...", "מגבש דו\"ח מודיעין מקיף סופי..." ] + }, + aiAssist: { + title: "סייען AI", + description: "אינטליגנציה שיחתית עם החלפת סוכנים", + placeholder: "דון בכל נושא, חשש או פרויקט...", + chatStart: "במה אוכל לעזור לך היום?", + switchingAgent: "עובר לסוכן מתמחה...", + routing: "מנתב את הבקשה שלך...", + preview: "תצוגה מקדימה בזמן אמת", + actions: "פעולות סוכן" } } }; diff --git a/lib/services/model-adapter.ts b/lib/services/model-adapter.ts index 0f7e934..a7d3149 100644 --- a/lib/services/model-adapter.ts +++ b/lib/services/model-adapter.ts @@ -1,4 +1,4 @@ -import type { ModelProvider, APIResponse, ChatMessage } from "@/types"; +import type { ModelProvider, APIResponse, ChatMessage, AIAssistMessage } from "@/types"; import OllamaCloudService from "./ollama-cloud"; import ZaiPlanService from "./zai-plan"; import qwenOAuthService, { QwenOAuthConfig, QwenOAuthToken } from "./qwen-oauth"; @@ -256,6 +256,19 @@ export class ModelAdapter { return this.callWithFallback((service) => service.generateMarketResearch(options, model), providers); } + async generateAIAssist( + options: { + messages: AIAssistMessage[]; + currentAgent: string; + }, + provider?: ModelProvider, + model?: string + ): Promise> { + const fallback = this.buildFallbackProviders(this.preferredProvider, "qwen", "ollama", "zai"); + const providers: ModelProvider[] = provider ? [provider] : fallback; + return this.callWithFallback((service) => service.generateAIAssist(options, model), providers); + } + async chatCompletion( messages: ChatMessage[], diff --git a/lib/services/ollama-cloud.ts b/lib/services/ollama-cloud.ts index c51a22d..5280a15 100644 --- a/lib/services/ollama-cloud.ts +++ b/lib/services/ollama-cloud.ts @@ -1,4 +1,4 @@ -import type { ChatMessage, APIResponse } from "@/types"; +import type { ChatMessage, APIResponse, AIAssistMessage } from "@/types"; export interface OllamaCloudConfig { apiKey?: string; @@ -617,71 +617,119 @@ Perform a DEEP 360° competitive intelligence analysis and generate 5-7 strategi }, model?: string ): Promise> { - const { websiteUrl, additionalUrls = [], competitors = [], productMapping, specialInstructions = "" } = options; - - const systemMessage: ChatMessage = { - role: "system", - content: `You are a WORLD-CLASS Market Research Analyst and Competitive Intelligence Expert. Your task is to perform a deep-dive automated market analysis and competitive intelligence gathering. - -OUTPUT FORMAT - Return ONLY valid JSON with this structure: -\`\`\`json -{ - "executiveSummary": "High-level overview of findings", - "priceComparisonMatrix": [ + const systemPrompt = `You are a WORLD-CLASS Market Research Analyst and Competitive Intelligence Expert. + Your objective is to perform a deep-dive analysis of a business and its competitors based on provided URLs and product mappings. + + You MUST return your analysis in the following STRICT JSON format: { - "product": "Product Name", - "userPrice": "$XX.XX", - "competitorPrices": [ - { "competitor": "Competitor Name", "price": "$XX.XX", "url": "https://competitor.com/product-page" } - ] + "executiveSummary": "A concise overview of the market landscape and key findings.", + "priceComparisonMatrix": [ + { + "product": "Product Name", + "userPrice": "$XX.XX", + "competitorPrices": [ + { "competitor": "Competitor Name", "price": "$XX.XX", "url": "https://competitor.com/product-page" } + ] + } + ], + "featureComparisonTable": [ + { + "feature": "Feature Name", + "userStatus": true/false/text, + "competitorStatus": [ + { "competitor": "Competitor Name", "status": true/false/text } + ] + } + ], + "marketPositioning": { + "landscape": "Description of the current market state.", + "segmentation": "Analysis of target customer segments." + }, + "competitiveAnalysis": { + "advantages": ["Point 1", "Point 2"], + "disadvantages": ["Point 1", "Point 2"] + }, + "recommendations": ["Actionable step 1", "Actionable step 2"], + "methodology": "Brief description of the research process." } - ], - "featureComparisonTable": [ + + Requirements: + 1. Base your analysis on realistic price and feature estimates if exact data isn't visible. + 2. Focus on core technical/business value rather than marketing fluff. + 3. Ensure JSON is valid and properly escaped.`; + + const userMsg = `WEBSITE TO ANALYZE: ${options.websiteUrl} + ADDITIONAL COMPANY URLS: ${options.additionalUrls?.join(', ') || 'None'} + COMPETITOR URLS: ${options.competitors.join(', ')} + PRODUCT/FEATURE MAPPING: ${options.productMapping} + SPECIAL REQUESTS: ${options.specialInstructions || 'Perform comprehensive analysis'} + + Provide a COMPREHENSIVE competitive intelligence report.`; + + const messages: ChatMessage[] = [ + { role: "system", content: systemPrompt }, + { role: "user", content: userMsg } + ]; + + return await this.chatCompletion(messages, model || this.getAvailableModels()[0]); + } + + async generateAIAssist( + options: { + messages: AIAssistMessage[]; + currentAgent: string; + }, + model?: string + ): Promise> { + const systemPrompt = `You are "AI Assist", the master orchestrator of PromptArch. + Your goal is to provide intelligent conversational support and switch to specialized agents when necessary. + + CURRENT SPECIALIZED AGENTS: + - content: Content creation and optimization expert. + - seo: SEO analyst and recommendations specialist. + - smm: SMM strategy and social content planner. + - pm: Project planning and management lead. + - code: Code architect (JavaScript/TypeScript/React focus). + - design: UI/UX designer. + - web: HTML/CSS/JS web development specialist with real-time preview. + - app: Mobile-first app development specialist with real-time preview. + + STRICT OUTPUT FORMAT: + You MUST respond in JSON format if you want to activate a preview or switch agents. { - "feature": "Feature Name", - "userStatus": "Yes/No or description", - "competitorStatus": [ - { "competitor": "Competitor Name", "status": "Yes/No or description" } - ] + "content": "Your natural language response here...", + "agent": "agent_id_to_switch_to (optional)", + "preview": { // (optional) + "type": "code" | "design" | "content" | "seo", + "data": "The actual code, layout, or content to preview", + "language": "javascript/html/css/markdown (optional)" + } } - ], - "marketPositioning": { - "landscape": "Current market landscape description", - "segmentation": "Target market segments" - }, - "competitiveAnalysis": { - "advantages": ["Point 1", "Point 2"], - "disadvantages": ["Point 1", "Point 2"] - }, - "recommendations": ["Rec 1", "Rec 2"], - "methodology": "How the research was conducted" -} -\`\`\` -REQUIREMENTS: -- Analysis must be based on the provided website and competitor URLs. -- Price comparison should be as realistic as possible based on industry knowledge. -- Feature table should focus on core technical and business value. -- Competitive analysis must highlight USP (Unique Selling Proposition).`, - }; + ROUTING LOGIC: + - If user asks for code, switch to 'code' or 'web'. + - If user asks for design/mockups, switch to 'design'. + - If user asks for market/SEO, switch to 'seo'. + - If user asks for marketing/social, switch to 'smm'. + - Maintain the 'content' of the conversation regardless of the agent switch. - const userMessage: ChatMessage = { - role: "user", - content: `🔬 MARKET RESEARCH REQUEST 🔬 + PREVIEW GUIDELINES: + - For 'web'/'app', provide full runnable HTML/CSS/JS. + - For 'code', provide clean, commented snippets. + - For 'design', provide text-based UI components or layout structures. + + RESPONSE TIME REQUIREMENT: Be concise and accurate.`; -PRIMARY WEBSITE: ${websiteUrl} -ADDITIONAL PAGES: ${additionalUrls.join(", ")} -COMPETITORS: ${competitors.join(", ")} -PRODUCT COMPARISON MAPPING: ${productMapping} -${specialInstructions ? `CUSTOM PARAMETERS: ${specialInstructions}` : ""} + const chatMessages: ChatMessage[] = [ + { role: "system", content: systemPrompt }, + ...options.messages.map(m => ({ + role: m.role as "user" | "assistant" | "system", + content: m.content + })) + ]; -Please conduct a comprehensive competitive analysis and market research report.`, - }; - - return this.chatCompletion([systemMessage, userMessage], model || "gpt-oss:120b"); + return await this.chatCompletion(chatMessages, model || this.getAvailableModels()[0]); } } export default OllamaCloudService; - - diff --git a/lib/services/qwen-oauth.ts b/lib/services/qwen-oauth.ts index 3adb99b..363f58b 100644 --- a/lib/services/qwen-oauth.ts +++ b/lib/services/qwen-oauth.ts @@ -1,4 +1,4 @@ -import type { ChatMessage, APIResponse } from "@/types"; +import type { ChatMessage, APIResponse, AIAssistMessage } from "@/types"; const DEFAULT_QWEN_ENDPOINT = "https://dashscope-intl.aliyuncs.com/compatible-mode/v1"; const TOKEN_STORAGE_KEY = "promptarch-qwen-tokens"; @@ -983,6 +983,29 @@ Perform analysis based on provided instructions.`, return this.chatCompletion([systemMessage, userMessage], model || "coder-model"); } + async generateAIAssist( + options: { + messages: AIAssistMessage[]; + currentAgent: string; + }, + model?: string + ): Promise> { + const systemPrompt = `You are "AI Assist". Help conversationally. + Switch agents if needed (content, seo, smm, pm, code, design, web, app). + Output JSON for previews or agent switches: + { "content": "text", "agent": "id", "preview": { "type": "code|design|content|seo", "data": "...", "language": "..." } }`; + + const chatMessages: ChatMessage[] = [ + { role: "system", content: systemPrompt }, + ...options.messages.map(m => ({ + role: m.role as "user" | "assistant" | "system", + content: m.content + })) + ]; + + return await this.chatCompletion(chatMessages, model || this.getAvailableModels()[0]); + } + async listModels(): Promise> { const models = [ "coder-model", @@ -999,6 +1022,5 @@ Perform analysis based on provided instructions.`, const qwenOAuthService = new QwenOAuthService(); export default qwenOAuthService; -export { qwenOAuthService }; diff --git a/lib/services/zai-plan.ts b/lib/services/zai-plan.ts index 9b0b7e7..526487a 100644 --- a/lib/services/zai-plan.ts +++ b/lib/services/zai-plan.ts @@ -1,4 +1,4 @@ -import type { ChatMessage, APIResponse } from "@/types"; +import type { ChatMessage, APIResponse, AIAssistMessage } from "@/types"; export interface ZaiPlanConfig { apiKey?: string; @@ -700,67 +700,105 @@ MISSION: Perform a DEEP 360° competitive intelligence analysis and generate 5-7 ): Promise> { const { websiteUrl, additionalUrls = [], competitors = [], productMapping, specialInstructions = "" } = options; - const systemMessage: ChatMessage = { - role: "system", - content: `You are a WORLD-CLASS Market Research Analyst and Competitive Intelligence Expert. Perform a deep-dive automated market analysis. - -OUTPUT FORMAT - Return ONLY valid JSON with this structure: -\`\`\`json -{ - "executiveSummary": "High-level overview of findings", - "priceComparisonMatrix": [ + const systemPrompt = `You are a WORLD-CLASS Market Research Analyst and Competitive Intelligence Expert. + Focus on accuracy and actionable intelligence. + + You MUST return your analysis in the following STRICT JSON format: { - "product": "Product Name", - "userPrice": "$XX.XX", - "competitorPrices": [ - { "competitor": "Competitor Name", "price": "$XX.XX", "url": "https://competitor.com/product-page" } - ] + "executiveSummary": "A concise overview of the market landscape and key findings.", + "priceComparisonMatrix": [ + { + "product": "Product Name", + "userPrice": "$XX.XX", + "competitorPrices": [ + { "competitor": "Competitor Name", "price": "$XX.XX", "url": "https://competitor.com/product-page" } + ] + } + ], + "featureComparisonTable": [ + { + "feature": "Feature Name", + "userStatus": true/false/text, + "competitorStatus": [ + { "competitor": "Competitor Name", "status": true/false/text } + ] + } + ], + "marketPositioning": { + "landscape": "Description of the current market state.", + "segmentation": "Analysis of target customer segments." + }, + "competitiveAnalysis": { + "advantages": ["Point 1", "Point 2"], + "disadvantages": ["Point 1", "Point 2"] + }, + "recommendations": ["Actionable step 1", "Actionable step 2"], + "methodology": "Brief description of the research process." } - ], - "featureComparisonTable": [ + + Requirements: + 1. Base your analysis on realistic price and feature estimates. + 2. Focus on core technical/business value. + 3. Ensure JSON is valid.`; + + const userMsg = `WEBSITE TO ANALYZE: ${options.websiteUrl} + COMPETITOR URLS: ${options.competitors.join(', ')} + PRODUCT/FEATURE MAPPING: ${options.productMapping} + SPECIAL REQUESTS: ${options.specialInstructions || 'Perform comprehensive analysis'} + + Provide a COMPREHENSIVE competitive intelligence analysis.`; + + const messages: ChatMessage[] = [ + { role: "system", content: systemPrompt }, + { role: "user", content: userMsg } + ]; + + return await this.chatCompletion(messages, model || this.getAvailableModels()[0]); + } + + async generateAIAssist( + options: { + messages: AIAssistMessage[]; + currentAgent: string; + }, + model?: string + ): Promise> { + const systemPrompt = `You are "AI Assist", the master orchestrator of PromptArch. + Your goal is to provide intelligent conversational support and switch to specialized agents when necessary. + + CURRENT SPECIALIZED AGENTS: + - content, seo, smm, pm, code, design, web, app + + STRICT OUTPUT FORMAT: + You MUST respond in JSON format if you want to activate a preview or switch agents. { - "feature": "Feature Name", - "userStatus": "Yes/No or description", - "competitorStatus": [ - { "competitor": "Competitor Name", "status": "Yes/No or description" } - ] + "content": "Your natural language response here...", + "agent": "agent_id_to_switch_to (optional)", + "preview": { // (optional) + "type": "code" | "design" | "content" | "seo", + "data": "The actual code, layout, or content to preview", + "language": "javascript/html/css/markdown (optional)" + } } - ], - "marketPositioning": { - "landscape": "Current market landscape description", - "segmentation": "Target market segments" - }, - "competitiveAnalysis": { - "advantages": ["Point 1", "Point 2"], - "disadvantages": ["Point 1", "Point 2"] - }, - "recommendations": ["Rec 1", "Rec 2"], - "methodology": "How the research was conducted" -} -\`\`\` -REQUIREMENTS: -- Focus on accuracy and actionable intelligence. -- Be realistic with price and feature estimates based on the provided URLs.`, - }; + ROUTING LOGIC: + - Automatically detect user intent and switch agents if appropriate. + - Provide deep technical or creative output based on the active agent. + + PREVIEW GUIDELINES: + - Provide full code for 'web'/'app'/'code'. + - Provide structured analysis for 'seo'/'content'.`; - const userMessage: ChatMessage = { - role: "user", - content: `🔬 MARKET RESEARCH REQUEST 🔬 + const chatMessages: ChatMessage[] = [ + { role: "system", content: systemPrompt }, + ...options.messages.map(m => ({ + role: m.role as "user" | "assistant" | "system", + content: m.content + })) + ]; -PRIMARY WEBSITE: ${websiteUrl} -ADDITIONAL PAGES: ${additionalUrls.join(", ")} -COMPETITORS: ${competitors.join(", ")} -PRODUCT COMPARISON MAPPING: ${productMapping} -${specialInstructions ? `CUSTOM PARAMETERS: ${specialInstructions}` : ""} - -Perform a COMPREHENSIVE competitive intelligence analysis.`, - }; - - return this.chatCompletion([systemMessage, userMessage], model || "glm-4.7", true); + return await this.chatCompletion(chatMessages, model || this.getAvailableModels()[0]); } } export default ZaiPlanService; - - diff --git a/lib/store.ts b/lib/store.ts index 9ca8f62..1054964 100644 --- a/lib/store.ts +++ b/lib/store.ts @@ -1,5 +1,5 @@ import { create } from "zustand"; -import type { ModelProvider, PromptEnhancement, PRD, ActionPlan, SlidesPresentation, GoogleAdsResult, MagicWandResult, MarketResearchResult, AppView } from "@/types"; +import type { ModelProvider, PromptEnhancement, PRD, ActionPlan, SlidesPresentation, GoogleAdsResult, MagicWandResult, MarketResearchResult, AppView, AIAssistMessage } from "@/types"; interface AppState { currentPrompt: string; @@ -10,6 +10,7 @@ interface AppState { googleAdsResult: GoogleAdsResult | null; magicWandResult: MagicWandResult | null; marketResearchResult: MarketResearchResult | null; + aiAssistHistory: AIAssistMessage[]; language: "en" | "ru" | "he"; selectedProvider: ModelProvider; selectedModels: Record; @@ -36,6 +37,7 @@ interface AppState { setGoogleAdsResult: (result: GoogleAdsResult | null) => void; setMagicWandResult: (result: MagicWandResult | null) => void; setMarketResearchResult: (result: MarketResearchResult | null) => void; + setAIAssistHistory: (history: AIAssistMessage[] | ((prev: AIAssistMessage[]) => AIAssistMessage[])) => void; setLanguage: (lang: "en" | "ru" | "he") => void; setSelectedProvider: (provider: ModelProvider) => void; setSelectedModel: (provider: ModelProvider, model: string) => void; @@ -58,6 +60,7 @@ const useStore = create((set) => ({ googleAdsResult: null, magicWandResult: null, marketResearchResult: null, + aiAssistHistory: [], language: "en", selectedProvider: "qwen", selectedModels: { @@ -87,6 +90,9 @@ const useStore = create((set) => ({ setGoogleAdsResult: (result) => set({ googleAdsResult: result }), setMagicWandResult: (result) => set({ magicWandResult: result }), setMarketResearchResult: (result) => set({ marketResearchResult: result }), + setAIAssistHistory: (update) => set((state) => ({ + aiAssistHistory: typeof update === 'function' ? update(state.aiAssistHistory) : update + })), setLanguage: (lang) => set({ language: lang }), setSelectedProvider: (provider) => set({ selectedProvider: provider }), setSelectedModel: (provider, model) => @@ -126,6 +132,7 @@ const useStore = create((set) => ({ googleAdsResult: null, magicWandResult: null, marketResearchResult: null, + aiAssistHistory: [], error: null, }), })); diff --git a/types/index.ts b/types/index.ts index 59abab3..97e26f6 100644 --- a/types/index.ts +++ b/types/index.ts @@ -292,4 +292,16 @@ export interface MarketResearchResult { rawContent: string; } -export type AppView = "prompt-enhancer" | "prd-generator" | "action-plan" | "slides-gen" | "google-ads" | "ux-designer" | "market-research" | "settings" | "history"; +export interface AIAssistMessage { + role: "user" | "assistant" | "system"; + content: string; + agent?: string; + preview?: { + type: "code" | "design" | "content" | "seo"; + data: string; + language?: string; + }; + timestamp: Date; +} + +export type AppView = "prompt-enhancer" | "prd-generator" | "action-plan" | "slides-gen" | "google-ads" | "ux-designer" | "market-research" | "ai-assist" | "settings" | "history";