everydaytok commited on
Commit
8629b61
·
verified ·
1 Parent(s): dcbe0f5

Update app.js

Browse files
Files changed (1) hide show
  1. app.js +45 -5
app.js CHANGED
@@ -54,6 +54,11 @@ const StateManager = {
54
  setFrozen: async (projectId, status) => {
55
  if (activeProjects.has(projectId)) activeProjects.get(projectId).isFrozen = status;
56
  await supabase.from('leads').update({ is_frozen: status }).eq('id', projectId);
 
 
 
 
 
57
  }
58
  };
59
 
@@ -95,8 +100,6 @@ function extractCommands(text) {
95
  parse(/<schedule_briefing>([\s\S]*?)<\/schedule_briefing>/gi, 'schedule_briefing');
96
  parse(/<freeze_project>([\s\S]*?)<\/freeze_project>/gi, 'freeze_project', false);
97
  parse(/<thrust_complete>([\s\S]*?)<\/thrust_complete>/gi, 'thrust_complete', false);
98
-
99
- // NEW: Parse AI checking off tasks
100
  parse(/<complete_task>([\s\S]*?)<\/complete_task>/gi, 'complete_task', false);
101
 
102
  return commands;
@@ -142,7 +145,6 @@ async function executeCommands(userId, projectId, commands) {
142
  await registerMorningCron(projectId, cmd.payload.timezone_offset || 0);
143
  }
144
 
145
- // NEW: AI checks off a specific task
146
  if (cmd.type === 'complete_task') {
147
  const { data: active } = await supabase.from('thrusts').select('id').eq('lead_id', projectId).eq('status', 'active').single();
148
  if (active) {
@@ -151,7 +153,6 @@ async function executeCommands(userId, projectId, commands) {
151
  }
152
  }
153
 
154
- // NEW: AI marks thrust as complete, we delete all its tasks
155
  if (cmd.type === 'thrust_complete') {
156
  const { data: active } = await supabase.from('thrusts').select('id').eq('lead_id', projectId).eq('status', 'active').single();
157
  if (active) {
@@ -161,6 +162,11 @@ async function executeCommands(userId, projectId, commands) {
161
  }
162
  }
163
 
 
 
 
 
 
164
  if (cmd.type === 'notification' && FRONT_URL) {
165
  fetch(`${FRONT_URL}/internal/notify`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ user_id: userId, type: 'toast', message: cmd.payload }) }).catch(() => {});
166
  }
@@ -207,7 +213,6 @@ app.post('/process', async (req, res) => {
207
  let cmds = extractCommands(aiResult.text);
208
  let flags = await executeCommands(userId, projectId, cmds);
209
 
210
- // Escalation: If fast model marks thrust complete, ask smart model for next thrust immediately
211
  if (flags.thrustComplete && task_type === 'log_ingestion') {
212
  const escalationPrompt = "The previous thrust is complete based on logs. Generate the next Thrust immediately to keep momentum.";
213
  const smartResult = await callAI(history, escalationPrompt, context, prompts.director_system_prompt, projectContext, SMART_MODEL_ID);
@@ -224,5 +229,40 @@ app.post('/process', async (req, res) => {
224
  } catch (e) { res.status(500).json({ error: "Processing Error" }); }
225
  });
226
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
227
  app.get('/', async (req, res) => res.status(200).json({ status: "Alive" }));
228
  app.listen(PORT, () => console.log(`✅ Core Online: ${PORT}`));
 
54
  setFrozen: async (projectId, status) => {
55
  if (activeProjects.has(projectId)) activeProjects.get(projectId).isFrozen = status;
56
  await supabase.from('leads').update({ is_frozen: status }).eq('id', projectId);
57
+ },
58
+ isFrozen: async (projectId) => {
59
+ if (activeProjects.has(projectId)) return activeProjects.get(projectId).isFrozen;
60
+ const { data } = await supabase.from('leads').select('is_frozen').eq('id', projectId).single();
61
+ return data?.is_frozen || false;
62
  }
63
  };
64
 
 
100
  parse(/<schedule_briefing>([\s\S]*?)<\/schedule_briefing>/gi, 'schedule_briefing');
101
  parse(/<freeze_project>([\s\S]*?)<\/freeze_project>/gi, 'freeze_project', false);
102
  parse(/<thrust_complete>([\s\S]*?)<\/thrust_complete>/gi, 'thrust_complete', false);
 
 
103
  parse(/<complete_task>([\s\S]*?)<\/complete_task>/gi, 'complete_task', false);
104
 
105
  return commands;
 
145
  await registerMorningCron(projectId, cmd.payload.timezone_offset || 0);
146
  }
147
 
 
148
  if (cmd.type === 'complete_task') {
149
  const { data: active } = await supabase.from('thrusts').select('id').eq('lead_id', projectId).eq('status', 'active').single();
150
  if (active) {
 
153
  }
154
  }
155
 
 
156
  if (cmd.type === 'thrust_complete') {
157
  const { data: active } = await supabase.from('thrusts').select('id').eq('lead_id', projectId).eq('status', 'active').single();
158
  if (active) {
 
162
  }
163
  }
164
 
165
+ if (cmd.type === 'freeze_project') {
166
+ const isFrozen = cmd.payload === 'true';
167
+ await StateManager.setFrozen(projectId, isFrozen);
168
+ }
169
+
170
  if (cmd.type === 'notification' && FRONT_URL) {
171
  fetch(`${FRONT_URL}/internal/notify`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ user_id: userId, type: 'toast', message: cmd.payload }) }).catch(() => {});
172
  }
 
213
  let cmds = extractCommands(aiResult.text);
214
  let flags = await executeCommands(userId, projectId, cmds);
215
 
 
216
  if (flags.thrustComplete && task_type === 'log_ingestion') {
217
  const escalationPrompt = "The previous thrust is complete based on logs. Generate the next Thrust immediately to keep momentum.";
218
  const smartResult = await callAI(history, escalationPrompt, context, prompts.director_system_prompt, projectContext, SMART_MODEL_ID);
 
229
  } catch (e) { res.status(500).json({ error: "Processing Error" }); }
230
  });
231
 
232
+ // --- AUTOMATED MORNING BRIEFING ---
233
+ app.post('/automated-briefing', async (req, res) => {
234
+ const { projectId } = req.body;
235
+
236
+ try {
237
+ const isFrozen = await StateManager.isFrozen(projectId);
238
+ const { data: lastThrust } = await supabase.from('thrusts').select('created_at').eq('lead_id', projectId).order('created_at', { ascending: false }).limit(1).single();
239
+
240
+ const lastThrustDate = lastThrust ? new Date(lastThrust.created_at).getDate() : 0;
241
+ const todayDate = new Date().getDate();
242
+
243
+ if (isFrozen) return res.json({ status: "skipped_frozen" });
244
+ if (lastThrustDate === todayDate) return res.json({ status: "skipped_exists" });
245
+
246
+ // TONE DIRECTIVE INJECTED INTO PROMPT
247
+ const prompt = "It is morning. Generate today's Morning Briefing (New Thrust). Look at the RECENT TIMELINE to see what was accomplished yesterday. Adopt a highly conversational, proactive tone in the markdown (e.g., 'Morning! You finished X yesterday. Today, the priority is Y.'). If the project has been idle for days, use <freeze_project>true</freeze_project>.";
248
+
249
+ const { data: lead } = await supabase.from('leads').select('*').eq('id', projectId).single();
250
+ const { data: timeline } = await supabase.from('timeline_events').select('*').eq('lead_id', projectId).order('created_at', { ascending: false }).limit(5);
251
+
252
+ const projectContext = `[PRD]: ${lead.requirements_doc}\n[RECENT TIMELINE]: ${JSON.stringify(timeline)}`;
253
+ const history = await StateManager.getHistory(projectId);
254
+
255
+ const aiResult = await callAI(history, prompt, {}, prompts.director_system_prompt, projectContext, SMART_MODEL_ID);
256
+
257
+ await StateManager.addHistory(projectId, 'model', aiResult.text);
258
+ const cmds = extractCommands(aiResult.text);
259
+ await executeCommands(lead.user_id, projectId, cmds);
260
+
261
+ await StateManager.setFrozen(projectId, true);
262
+ res.json({ success: true });
263
+
264
+ } catch (e) { res.status(500).json({ error: e.message }); }
265
+ });
266
+
267
  app.get('/', async (req, res) => res.status(200).json({ status: "Alive" }));
268
  app.listen(PORT, () => console.log(`✅ Core Online: ${PORT}`));