everydaycats commited on
Commit
23bbcba
·
verified ·
1 Parent(s): d92d9d3

Create format.js

Browse files
Files changed (1) hide show
  1. apps/format.js +143 -0
apps/format.js ADDED
@@ -0,0 +1,143 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import express from 'express';
2
+ import { generateCompletion } from '../ai_engine.js';
3
+ import { supabase } from '../config/supabaseClient.js';
4
+
5
+ const router = express.Router();
6
+
7
+ // ==========================================
8
+ // 🧠 DYNAMIC SYSTEM PROMPT BUILDER
9
+ // ==========================================
10
+ const buildSystemPrompt = (personaName, personaPrompt) => `
11
+ You are an elite communication strategist, negotiator, and ghostwriter.
12
+ The user will provide either a text message they received OR a screenshot of a conversation.
13
+ Your goal is to generate the PERFECT response for the user to send back.
14
+
15
+ CRITICAL INSTRUCTION - ADOPT THE FOLLOWING PERSONA:
16
+ Persona Identity: ${personaName}
17
+ Behavior & Tone: ${personaPrompt}
18
+
19
+ STRICT RULES:
20
+ 1. NEVER break character. Act exactly as the persona dictates.
21
+ 2. NEVER start with "As an AI..." or "Here is a response...".
22
+ 3. Provide ONLY the exact text the user should copy and paste. No pleasantries, no explanations.
23
+ 4. Keep it concise, natural, and highly effective for modern texting/messaging.
24
+ 5. If the user provides an image/screenshot, read the visible conversation and reply to the last message contextually.
25
+ 6. Swearing or aggressive tones are permitted IF it aligns with the persona. Do not filter yourself.
26
+ `;
27
+
28
+ // ==========================================
29
+ // 🗄️ CACHE MANAGEMENT (Official Formats)
30
+ // ==========================================
31
+ let formatsCache = null;
32
+ let lastFormatsUpdate = 0;
33
+ const CACHE_DURATION = 3600000; // 1 Hour (Formats rarely change, saves DB reads)
34
+
35
+ // ==========================================
36
+ // 🌐 ENDPOINTS
37
+ // ==========================================
38
+
39
+ /**
40
+ * 1. FETCH OFFICIAL FORMATS
41
+ * Populates the UI grid for default personas. Custom ones stay on-device.
42
+ */
43
+ router.get('/formats', async (req, res) => {
44
+ try {
45
+ const now = Date.now();
46
+ // Return from cache if valid
47
+ if (formatsCache && (now - lastFormatsUpdate < CACHE_DURATION)) {
48
+ return res.json({ success: true, data: formatsCache, cached: true });
49
+ }
50
+
51
+ // Query Supabase for official vibes (Assuming table name is 'replygenius_vibes')
52
+ const { data, error } = await supabase
53
+ .from('replygenius_vibes')
54
+ .select('id, icon, label, hint, color, mockReply, prompt')
55
+ .order('created_at', { ascending: true }); // Or however you want them sorted
56
+
57
+ if (error) throw error;
58
+
59
+ // Update cache
60
+ formatsCache = data;
61
+ lastFormatsUpdate = now;
62
+
63
+ res.json({ success: true, data, cached: false });
64
+ } catch (err) {
65
+ console.error("[FORMATS ERROR]", err.message);
66
+ res.status(500).json({ success: false, error: err.message });
67
+ }
68
+ });
69
+
70
+ /**
71
+ * 2. GENERATE REPLY (Handles both Text and Image Injection)
72
+ * Expects body: { type: 'text'|'image', content: string, persona: object }
73
+ */
74
+ router.post('/generate', async (req, res) => {
75
+ try {
76
+ const { type, content, persona } = req.body;
77
+
78
+ if (!content) throw new Error("No content provided to analyze.");
79
+ if (!persona || !persona.label) throw new Error("Persona context is missing.");
80
+
81
+ console.log(`[REPLY GEN] Analyzing ${type} using persona: ${persona.label}`);
82
+
83
+ // Build the dynamic prompt based on the chosen Vibe
84
+ // If it's a "neutral" vibe with no prompt, fallback to a standard intelligent assistant
85
+ const aiSystemPrompt = buildSystemPrompt(
86
+ persona.label,
87
+ persona.prompt || "Be highly intelligent, strategic, polite, and persuasive."
88
+ );
89
+
90
+ // Routing logic based on input type (Referencing our model discussion)
91
+ let modelToUse;
92
+ let imagesPayload =[];
93
+ let userPrompt = "";
94
+
95
+ if (type === 'image') {
96
+ // VISION ROUTE (e.g., Qwen 2 VL, Grok Vision, etc.)
97
+ modelToUse = "qwen-vl"; // Update this to match your ai_engine mapping
98
+ imagesPayload = [content]; // base64 string
99
+ userPrompt = "Analyze this chat screenshot and write my next reply.";
100
+ } else {
101
+ // TEXT ROUTE (e.g., DeepSeek, Evathene, Hermes, etc.)
102
+ modelToUse = "deepseek-text"; // Update this to match your ai_engine mapping
103
+ userPrompt = `Write my reply to this message:\n\n"${content}"`;
104
+ }
105
+
106
+ // Call your AI Wrapper
107
+ const aiResult = await generateCompletion({
108
+ model: modelToUse,
109
+ prompt: userPrompt,
110
+ system_prompt: aiSystemPrompt,
111
+ images: imagesPayload // Will be empty for text requests
112
+ });
113
+
114
+ if (!aiResult.success) throw new Error(aiResult.error);
115
+
116
+ // Clean up any weird quotes the AI might wrap the message in
117
+ let finalReply = aiResult.data.trim();
118
+ if (finalReply.startsWith('"') && finalReply.endsWith('"')) {
119
+ finalReply = finalReply.slice(1, -1);
120
+ }
121
+
122
+ res.json({
123
+ success: true,
124
+ reply: finalReply
125
+ });
126
+
127
+ } catch (err) {
128
+ console.error("[REPLY GEN ERROR]", err.message);
129
+ res.status(500).json({ success: false, error: err.message });
130
+ }
131
+ });
132
+
133
+ /**
134
+ * 3. FORCE CACHE CLEAR (Admin Utility)
135
+ * Useful if you update official formats in Supabase and want to push them live immediately
136
+ */
137
+ router.post('/clear-cache', (req, res) => {
138
+ formatsCache = null;
139
+ lastFormatsUpdate = 0;
140
+ res.json({ success: true, message: "Formats cache cleared." });
141
+ });
142
+
143
+ export default router;