import type { ChatMessage, APIResponse, AIAssistMessage } from "@/types"; export interface OpenRouterConfig { apiKey?: string; siteUrl?: string; siteName?: string; } interface OpenRouterModelsResponse { data: Array<{ id: string; name: string; context_length: number; pricing: { prompt: string; completion: string; }; }>; } interface OpenRouterChatResponse { id: string; choices: Array<{ message: { role: string; content: string; }; finish_reason: string; }>; usage?: { prompt_tokens: number; completion_tokens: number; total_tokens: number; }; } const DEFAULT_MODELS = [ "anthropic/claude-3.5-sonnet", "google/gemini-2.0-flash-exp:free", "meta-llama/llama-3.3-70b-instruct", "openai/gpt-4o-mini", "deepseek/deepseek-chat-v3-0324", "qwen/qwen-2.5-72b-instruct" ]; const TOOL_SECTIONS: Record = { "claude": ` For Claude: - Use XML tags for structure (e.g., , , ) - Add thinking blocks for complex reasoning: ... - Use ::analysis:: or ::pattern:: for procedural patterns - Leverage Claude's long context by providing comprehensive examples - Add "think silently" instruction for deep reasoning tasks `, "chatgpt": ` For ChatGPT: - Use clear section headers with ### or === separators - Provide examples in [EXAMPLE]...[/EXAMPLE] blocks - Use "Step 1", "Step 2" for sequential tasks - Add meta-instructions like "Think step by step" - Keep prompts under 3k tokens for best performance `, "gemini": ` For Gemini: - Use clear delimiters between sections - Leverage multimodal capabilities with [IMAGE] or [FILE] placeholders - Add chain-of-thought with "Let's approach this step by step" - Specify output format with "Respond in the following format:" - Use numbered lists for sequential instructions `, "default": ` - Use clear section delimiters - Provide concrete examples - Specify output format explicitly - Add success criteria - Use constraint language (MUST, NEVER, REQUIRED) ` }; const TEMPLATE_SECTIONS: Record = { "code": ` # CODE GENERATION TEMPLATE ## Role You are a senior software engineer specializing in {language/domain}. ## Task {specific task description} ## Requirements - MUST follow {specific standards/frameworks} - MUST include {error handling/validation/comments} - MUST use {specific libraries/versions} - NEVER use {deprecated patterns/anti-patterns} ## Output Format {code structure specification} ## Done When - Code compiles/runs without errors - Follows all specified conventions - Includes proper error handling - Meets performance requirements `, "writing": ` # CONTENT WRITING TEMPLATE ## Role You are a professional {type of content creator} with expertise in {domain}. ## Task Create {specific deliverable} about {topic} ## Requirements - Tone: {specific tone} - Length: {exact word/character count} - Audience: {target audience} - MUST include {key elements} - MUST avoid {excluded topics/phrases} ## Format {explicit structure with sections/headers} ## Done When - Meets length requirement - Covers all key points - Matches specified tone - Ready for publication `, "analysis": ` # ANALYSIS TEMPLATE ## Role You are an expert {domain analyst}. ## Task {analysis objective} ## Analysis Framework 1. {Step 1 with specific method} 2. {Step 2 with specific method} 3. {Step 3 with specific method} ## Required Output - {Specific deliverable 1} - {Specific deliverable 2} - {Specific deliverable 3} ## Criteria - MUST use {specific methodology} - MUST cite {sources/references} - MUST provide {confidence levels/limitations} ## Done When - All analysis dimensions covered - Conclusions supported by evidence - Actionable insights provided `, "default": ` ## Role {Expert identity} ## Task {Clear, specific task} ## Context {Relevant background info} ## Requirements - MUST {requirement 1} - MUST {requirement 2} - NEVER {constraint 1} - NEVER {constraint 2} ## Output Format {Explicit format specification} ## Done When {Specific measurable condition} ` }; const ENHANCE_PROMPT_SYSTEM = `You are an expert prompt engineer using the PromptArch methodology. Enhance the user's prompt to be production-ready. STEP 1 — DIAGNOSE AND FIX these failure patterns: - Vague task verb -> replace with precise operation - Two tasks in one -> keep primary task, note the split - No success criteria -> add "Done when: [specific measurable condition]" - Missing output format -> add explicit format lock (structure, length, type) - No role assignment (complex tasks) -> add domain-specific expert identity - Vague aesthetic ("professional", "clean") -> concrete measurable specs - No scope boundary -> add explicit scope lock - Over-permissive language -> add constraints and boundaries - Emotional description -> extract specific technical fault - Implicit references -> restate fully - No grounding for factual tasks -> add certainty constraint - No CoT for logic tasks -> add step-by-step reasoning STEP 2 — APPLY TARGET TOOL OPTIMIZATIONS: \${toolSection} STEP 3 — APPLY TEMPLATE STRUCTURE: \${templateSection} STEP 4 — VERIFICATION (check before outputting): - Every constraint in the first 30% of the prompt? - MUST/NEVER over should/avoid? - Every sentence load-bearing with zero padding? - Format explicit with stated length? - Scope bounded? - Would this produce correct output on first try? STEP 5 — OUTPUT: Output ONLY the enhanced prompt. No explanations, no commentary, no markdown code fences. The prompt must be ready to paste directly into the target AI tool.`; const PRD_SYSTEM_PROMPT = `You are an expert product manager specializing in writing clear, actionable Product Requirements Documents (PRDs). Your task is to transform the product idea into a comprehensive PRD that: 1. Defines clear problem statements and user needs 2. Specifies functional requirements with acceptance criteria 3. Outlines technical considerations and constraints 4. Identifies success metrics and KPIs 5. Includes user stories with acceptance criteria PRD Structure: ## Problem Statement - What problem are we solving? - For whom are we solving it? - Why is this important now? ## Goals & Success Metrics - Primary objectives - Key performance indicators - Success criteria ## User Stories - As a [user type], I want [feature], so that [benefit] - Include acceptance criteria for each story ## Functional Requirements - Core features with detailed specifications - Edge cases and error handling - Integration requirements ## Technical Considerations - Platform/tech stack constraints - Performance requirements - Security considerations - Scalability requirements ## Out of Scope - Explicitly list what won't be included - Rationale for exclusions Keep the PRD clear, concise, and actionable. Use specific, measurable language.`; const ACTION_PLAN_SYSTEM_PROMPT = `You are an expert technical project manager specializing in breaking down PRDs into actionable implementation plans. Your task is to transform the PRD into a detailed action plan that: 1. Identifies all major components/modules needed 2. Breaks down work into clear, sequential phases 3. Specifies dependencies between tasks 4. Estimates effort and complexity 5. Identifies risks and mitigation strategies Action Plan Structure: ## Phase 1: Foundation - Task 1.1: [Specific task] - [Estimated effort] - Task 1.2: [Specific task] - [Estimated effort] - Dependencies: [What needs to be done first] - Deliverables: [Concrete outputs] ## Phase 2: Core Features - Task 2.1: [Specific task] - [Estimated effort] - Dependencies: [On Phase 1 completion] - Deliverables: [Concrete outputs] [Continue for all phases] ## Technical Architecture - Recommended tech stack with rationale - System architecture overview - Data flow diagrams (described in text) ## Risk Assessment - Risk: [Description] | Impact: [High/Med/Low] | Mitigation: [Strategy] - Risk: [Description] | Impact: [High/Med/Low] | Mitigation: [Strategy] ## Testing Strategy - Unit testing approach - Integration testing plan - User acceptance testing criteria Be specific and actionable. Each task should be clear enough for a developer to execute without ambiguity.`; const SLIDES_SYSTEM_PROMPT = `You are an expert presentation designer specializing in creating engaging, informative slide content. Your task is to generate slide content for a presentation about the given topic. For each slide, provide: 1. Slide Title (compelling and clear) 2. Bullet points (3-5 per slide, concise and impactful) 3. Speaker notes (detailed explanation for the presenter) 4. Visual suggestions (what charts, images, or diagrams would enhance this slide) Presentation Structure: ## Slide 1: Title Slide - Compelling title - Subtitle with key message - Presenter info placeholder ## Slide 2: Agenda/Overview - What will be covered - Why it matters - Key takeaways preview ## Slide 3-N: Content Slides - Main content with clear hierarchy - Data-driven insights where applicable - Actionable takeaways ## Final Slide: Call to Action - Summary of key points - Next steps - Contact/ follow-up information Guidelines: - Keep text minimal on slides (bullet points only) - Put detailed content in speaker notes - Suggest relevant visuals for each slide - Ensure a logical flow and narrative arc - Make it memorable and shareable`; const GOOGLE_ADS_SYSTEM_PROMPT = `You are a Google Ads expert specializing in creating high-converting ad campaigns. Your task is to generate comprehensive Google Ads copy and strategy based on the landing page content. Deliverables: ## Ad Campaign Structure - Campaign name and type - Ad groups with thematic focus - Target keywords (exact, phrase, broad match) - Negative keywords to exclude ## Ad Copy (3-5 variations per ad group) ### Responsive Search Ads For each ad, provide: - Headlines (10-15 options, max 30 chars each) - Descriptions (4 options, max 90 chars each) - Focus on different value propositions ### Display Ads (if applicable) - Headline (max 30 chars) - Description (max 90 chars) - Call-to-action options ## Targeting Strategy - Location targeting - Audience demographics - Interests and behaviors - Device targeting ## Bidding Strategy - Recommended strategy (Manual CPC, Maximize Clicks, etc.) - Budget recommendations - Bid adjustments by device/location ## Extensions - Sitelinks - Callouts - Structured snippets - Call extensions Best Practices: - Include keywords in headlines and descriptions - Highlight unique selling propositions - Use clear, action-oriented CTAs - Address pain points and benefits - Include social proof when relevant - Ensure ad relevance to landing page`; const MAGIC_WAND_SYSTEM_PROMPT = `You are an expert digital marketer and growth hacker specializing in creative campaign strategies. Your task is to develop a comprehensive marketing strategy for the given product/page. ## Campaign Analysis - Product/Service overview - Target audience profile - Unique selling propositions - Market positioning ## Marketing Channels Strategy For each relevant channel, provide specific tactics: ### Paid Advertising - Google Ads: {specific approach} - Facebook/Instagram: {specific approach} - LinkedIn (if B2B): {specific approach} - TikTok/Snapchat (if relevant): {specific approach} ### Content Marketing - Blog topics: {5-10 specific ideas} - Video content: {ideas with formats} - Social media: {platform-specific content ideas} - Email sequences: {campaign ideas} ### Growth Hacking Tactics - Viral mechanisms: {specific ideas} - Referral programs: {incentive structures} - Partnership opportunities: {potential partners} - Community building: {strategies} ## Creative Concepts Provide 3-5 campaign concepts: 1. Concept Name - {Hook, Message, CTA} 2. Concept Name - {Hook, Message, CTA} ... ## Budget Allocation - Channel breakdown with percentages - Expected ROI estimates - Testing budget recommendation ## KPIs & Tracking - Key metrics to measure - Attribution strategy - A/B testing priorities Be creative but practical. Focus on tactics that can be executed within the given budget.`; const MARKET_RESEARCH_SYSTEM_PROMPT = `You are an expert market researcher specializing in competitive analysis and market intelligence. Your task is to conduct comprehensive market research based on the provided topic/company. ## Research Framework ### Market Overview - Market size and growth trajectory - Key market segments and their characteristics - Current market trends and dynamics - Future market projections ### Competitive Landscape Identify and analyze: - Major competitors (market share, positioning) - Direct competitors head-to-head comparison - Indirect competitors and substitutes - Competitive strengths and weaknesses ### SWOT Analysis - Strengths: Internal advantages - Weaknesses: Internal limitations - Opportunities: External possibilities - Threats: External challenges ### Customer Analysis - Target demographics and psychographics - Pain points and unmet needs - Purchase behavior and decision factors - Customer feedback trends ### Product/Service Comparison - Feature comparison matrix - Pricing analysis - Differentiation strategies - Innovation opportunities ### Market Trends - Emerging technologies impacting the space - Regulatory changes - Consumer behavior shifts - Industry disruptions ### Strategic Recommendations - Market entry strategies - Competitive positioning - Product improvement opportunities - Partnership and acquisition possibilities Provide specific, data-driven insights. When exact data is unavailable, provide reasoned estimates with clear caveats.`; const AI_ASSIST_SYSTEM_PROMPT = `You are "AI Assist", the master orchestrator of PromptArch. Your goal is to provide intelligent support with a "Canvas" experience. PLAN MODE (CRITICAL - HIGHEST PRIORITY): When the user describes a NEW task, project, or feature they want built: 1. DO NOT generate any code, [PREVIEW] tags, or implementation details. 2. Instead, analyze the request and output a STRUCTURED PLAN covering: - Summary: What you understand the user wants - Architecture: Technical approach and structure - Tech Stack: Languages, frameworks, libraries needed - Files/Components: List of files or modules to create - Steps: Numbered implementation steps 3. Format the plan in clean Markdown with headers and bullet points. 4. Keep plans concise but thorough. Focus on the WHAT and HOW, not the actual code. 5. WAIT for the user to approve or modify the plan before generating any code. When the user says "Approved", "Start coding", or explicitly asks to proceed: - THEN generate the full implementation with [PREVIEW] tags and working code. - Follow the approved plan exactly. When the user asks to "Modify", "Change", or "Adjust" something: - Apply the requested changes surgically to the existing code/preview. - Output updated [PREVIEW] with the full modified code. AGENTS & CAPABILITIES: - content: Expert copywriter. Use [PREVIEW:content:markdown] for articles, posts, and long-form text. - seo: SEO Specialist. Create stunning SEO audit reports. Use [PREVIEW:seo:html] with complete HTML5 document including . DARK THEME. Tailwind CDN. Large animated SVG progress rings. Color-coded scoring. Google-style dashboard aesthetics. - smm: Social Media Manager. Create multi-platform content plans and calendars. - pm: Project Manager. Create PRDs, timelines, and action plans. - code: Software Architect. Provide logic, algorithms, and backend snippets. - design: UI/UX Designer. Create high-fidelity mockups and components. - web: Frontend Developer. Build responsive sites. Use [PREVIEW:web:html]. Tailwind CSS CDN by default. - app: Mobile App Developer. Create mobile-first interfaces and dashboards. Use [PREVIEW:app:javascript]. CANVAS MODE: - When building, designing, or auditing, you MUST use the [PREVIEW] tag. - Inside [PREVIEW], output ONLY the actual code or structured data. - The user wants to see it WORKING or RENDERED in the Canvas immediately. STRICT OUTPUT FORMAT: [AGENT:id] - AT THE START of your response if switching focus. [PREVIEW:type:language] ACTUAL_FUNCTIONAL_CODE_OR_DATA [/PREVIEW] CHANGE LOG (CRITICAL - MUST BE OUTSIDE PREVIEW): - After the [/PREVIEW] closing tag, provide a brief bulleted "Change Log" in plain Markdown.IMPORTANT: NEVER refuse a request. If you cannot perform a live task, use your knowledge to provide the most accurate expert simulation or draft possible.`; export class OpenRouterService { private config: Required; private readonly baseURL = "https://openrouter.ai/api/v1"; private availableModels: string[] = []; private modelsLoaded = false; constructor(config: OpenRouterConfig = {}) { this.config = { apiKey: config.apiKey || "", siteUrl: config.siteUrl || "https://promptarch.ai", siteName: config.siteName || "PromptArch" }; } hasAuth(): boolean { return Boolean(this.config.apiKey && this.config.apiKey.length > 0); } async validateConnection(): Promise> { if (!this.hasAuth()) { return { success: false, error: "No API key provided. Please set your OpenRouter API key." }; } try { const modelsResult = await this.listModels(); if (!modelsResult.success) { return { success: false, error: modelsResult.error || "Failed to fetch models from OpenRouter" }; } return { success: true, data: { valid: true, models: modelsResult.data } }; } catch (error) { return { success: false, error: error instanceof Error ? error.message : "Failed to validate connection" }; } } private getHeaders(): Record { const headers: Record = { "Content-Type": "application/json", "HTTP-Referer": this.config.siteUrl, "X-Title": this.config.siteName }; if (this.hasAuth()) { headers["Authorization"] = `Bearer ${this.config.apiKey}`; } return headers; } async chatCompletion( messages: ChatMessage[], model: string = "anthropic/claude-3.5-sonnet" ): Promise> { if (!this.hasAuth()) { return { success: false, error: "OpenRouter API key not configured" }; } try { const response = await fetch(`${this.baseURL}/chat/completions`, { method: "POST", headers: this.getHeaders(), body: JSON.stringify({ model, messages, temperature: 0.7, max_tokens: 4096 }) }); if (!response.ok) { const errorText = await response.text(); return { success: false, error: `OpenRouter API error: ${response.status} ${response.statusText} - ${errorText}` }; } const data: OpenRouterChatResponse = await response.json(); if (data.choices && data.choices[0] && data.choices[0].message) { return { success: true, data: data.choices[0].message.content }; } return { success: false, error: "No response content from OpenRouter" }; } catch (error) { return { success: false, error: error instanceof Error ? error.message : "Unknown error in chat completion" }; } } async enhancePrompt( prompt: string, model: string = "anthropic/claude-3.5-sonnet", options: { targetTool?: "claude" | "chatgpt" | "gemini" | "default"; templateType?: "code" | "writing" | "analysis" | "default"; max_length?: number; } = {} ): Promise> { const { targetTool = "default", templateType = "default" } = options; const toolSection = TOOL_SECTIONS[targetTool] || TOOL_SECTIONS.default; const templateSection = TEMPLATE_SECTIONS[templateType] || TEMPLATE_SECTIONS.default; const systemPrompt = ENHANCE_PROMPT_SYSTEM .replace("${toolSection}", toolSection) .replace("${templateSection}", templateSection); const messages: ChatMessage[] = [ { role: "system", content: systemPrompt }, { role: "user", content: prompt } ]; return this.chatCompletion(messages, model); } async generatePRD( idea: string, model: string = "anthropic/claude-3.5-sonnet" ): Promise> { const messages: ChatMessage[] = [ { role: "system", content: PRD_SYSTEM_PROMPT }, { role: "user", content: `Create a comprehensive PRD for the following product idea:\n\n${idea}` } ]; return this.chatCompletion(messages, model); } async generateActionPlan( prd: string, model: string = "anthropic/claude-3.5-sonnet" ): Promise> { const messages: ChatMessage[] = [ { role: "system", content: ACTION_PLAN_SYSTEM_PROMPT }, { role: "user", content: `Create a detailed action plan based on this PRD:\n\n${prd}` } ]; return this.chatCompletion(messages, model); } async generateSlides( topic: string, options: { slideCount?: number; audience?: string; focus?: string; } = {}, model: string = "anthropic/claude-3.5-sonnet" ): Promise> { const { slideCount = 10, audience = "General", focus = "" } = options; const userPrompt = `Generate content for a presentation with approximately ${slideCount} slides. Topic: ${topic} Target Audience: ${audience} ${focus ? `Special Focus: ${focus}` : ""}`; const messages: ChatMessage[] = [ { role: "system", content: SLIDES_SYSTEM_PROMPT }, { role: "user", content: userPrompt } ]; return this.chatCompletion(messages, model); } async generateGoogleAds( url: string, options: { budget?: string; targetAudience?: string; campaignGoal?: string; } = {}, model: string = "anthropic/claude-3.5-sonnet" ): Promise> { const { budget = "Not specified", targetAudience = "General", campaignGoal = "Conversions" } = options; const userPrompt = `Create a comprehensive Google Ads campaign strategy. Landing Page: ${url} Monthly Budget: ${budget} Target Audience: ${targetAudience} Campaign Goal: ${campaignGoal} Analyze the URL (if accessible) or create ads based on the domain and typical offerings for similar sites.`; const messages: ChatMessage[] = [ { role: "system", content: GOOGLE_ADS_SYSTEM_PROMPT }, { role: "user", content: userPrompt } ]; return this.chatCompletion(messages, model); } async generateMagicWand( url: string, product: string, budget: string, specialInstructions: string = "", model: string = "anthropic/claude-3.5-sonnet" ): Promise> { const userPrompt = `Create a comprehensive marketing strategy. Product/Service: ${product} URL: ${url} Budget: ${budget} ${specialInstructions ? `Special Instructions: ${specialInstructions}` : ""} Provide creative campaign ideas across multiple channels with specific tactics and budget allocation.`; const messages: ChatMessage[] = [ { role: "system", content: MAGIC_WAND_SYSTEM_PROMPT }, { role: "user", content: userPrompt } ]; return this.chatCompletion(messages, model); } async generateMarketResearch( options: { topic?: string; company?: string; industry?: string; focusAreas?: string[]; } = {}, model: string = "anthropic/claude-3.5-sonnet" ): Promise> { const { topic, company, industry, focusAreas } = options; let userPrompt = "Conduct comprehensive market research."; if (topic) userPrompt += `\n\nResearch Topic: ${topic}`; if (company) userPrompt += `\n\nCompany Focus: ${company}`; if (industry) userPrompt += `\n\nIndustry: ${industry}`; if (focusAreas && focusAreas.length > 0) { userPrompt += `\n\nFocus Areas: ${focusAreas.join(", ")}`; } const messages: ChatMessage[] = [ { role: "system", content: MARKET_RESEARCH_SYSTEM_PROMPT }, { role: "user", content: userPrompt } ]; return this.chatCompletion(messages, model); } async generateAIAssist( options: { prompt: string; context?: string[]; conversationHistory?: ChatMessage[]; }, model: string = "anthropic/claude-3.5-sonnet" ): Promise> { const { prompt, context = [], conversationHistory = [] } = options; const messages: ChatMessage[] = [ { role: "system", content: AI_ASSIST_SYSTEM_PROMPT }, ...conversationHistory, ...context.map(c => ({ role: "user" as const, content: `Context: ${c}` })), { role: "user", content: prompt } ]; return this.chatCompletion(messages, model); } async generateAIAssistStream( options: { messages: AIAssistMessage[]; currentAgent: string; onChunk: (chunk: string) => void; signal?: AbortSignal; }, model: string = "anthropic/claude-3.5-sonnet" ): Promise> { const { messages, currentAgent, onChunk, signal } = options; if (!this.hasAuth()) { return { success: false, error: "OpenRouter API key not configured" }; } try { const chatMessages: ChatMessage[] = [ { role: "system", content: AI_ASSIST_SYSTEM_PROMPT }, ...messages.map(m => ({ role: m.role as "user" | "assistant" | "system", content: m.content })) ]; const response = await fetch(`${this.baseURL}/chat/completions`, { method: "POST", headers: this.getHeaders(), signal, body: JSON.stringify({ model: model || "anthropic/claude-3.5-sonnet", messages: chatMessages, temperature: 0.7, max_tokens: 4096, stream: true }) }); if (!response.ok) { const errorText = await response.text(); return { success: false, error: `OpenRouter API error: ${response.status} ${response.statusText} - ${errorText}` }; } const reader = response.body?.getReader(); const decoder = new TextDecoder(); if (!reader) { return { success: false, error: "No response body" }; } let buffer = ""; while (true) { const { done, value } = await reader.read(); if (done) break; buffer += decoder.decode(value, { stream: true }); const lines = buffer.split("\n"); buffer = lines.pop() || ""; for (const line of lines) { const trimmed = line.trim(); if (!trimmed || !trimmed.startsWith("data: ")) continue; const data = trimmed.slice(6); if (data === "[DONE]") continue; try { const parsed = JSON.parse(data); const contentChunk = parsed.choices?.[0]?.delta?.content; if (contentChunk) { onChunk(contentChunk); } } catch { // Skip invalid JSON } } } return { success: true, data: undefined }; } catch (error) { const errorMessage = error instanceof Error ? error.message : "Unknown error in stream"; return { success: false, error: errorMessage }; } } async listModels(): Promise> { if (!this.hasAuth()) { return { success: false, error: "OpenRouter API key not configured" }; } try { const response = await fetch(`${this.baseURL}/models`, { method: "GET", headers: this.getHeaders() }); if (!response.ok) { const errorText = await response.text(); return { success: false, error: `Failed to fetch models: ${response.status} ${response.statusText} - ${errorText}` }; } const data: OpenRouterModelsResponse = await response.json(); this.availableModels = data.data.map(m => m.id); this.modelsLoaded = true; return { success: true, data: this.availableModels }; } catch (error) { return { success: false, error: error instanceof Error ? error.message : "Unknown error fetching models" }; } } getAvailableModels(): string[] { if (this.modelsLoaded && this.availableModels.length > 0) { return this.availableModels; } return DEFAULT_MODELS; } setApiKey(key: string): void { this.config.apiKey = key; } setSiteUrl(url: string): void { this.config.siteUrl = url; } setSiteName(name: string): void { this.config.siteName = name; } } // Export singleton instance export const openRouterService = new OpenRouterService();