rairo commited on
Commit
773d4f7
·
verified ·
1 Parent(s): 723fe6e

Update main.py

Browse files
Files changed (1) hide show
  1. main.py +78 -76
main.py CHANGED
@@ -36,7 +36,6 @@ logger = logging.getLogger("SOZO_ATHENA")
36
  app = Flask(__name__)
37
  CORS(app)
38
 
39
- # --- Firebase Initialization ---
40
  try:
41
  logger.info("Initializing Firebase Admin SDK...")
42
  credentials_json_string = os.environ.get("FIREBASE")
@@ -60,9 +59,8 @@ except Exception as e:
60
  bucket = storage.bucket()
61
  db_ref = db.reference()
62
 
63
- # --- Google GenAI Client Initialization (Gemini 3.0) ---
64
  try:
65
- logger.info("Initializing Google GenAI Client...")
66
  api_key = os.environ.get("Gemini")
67
  if not api_key:
68
  raise ValueError("The 'Gemini' API key is not set.")
@@ -73,22 +71,20 @@ except Exception as e:
73
  logger.error(f"FATAL: Error initializing GenAI Client: {e}")
74
  exit(1)
75
 
76
- # Model Constants
77
  ATHENA_FLASH = "gemini-3-flash-preview"
78
  ATHENA_PRO = "gemini-3-pro-image-preview"
79
- BRIEFING_MODEL = "gemini-3-flash-preview"
80
 
81
- # Grounding / External API
82
  WOLFRAM_APP_ID = os.environ.get("WOLFRAM_APP_ID")
83
  OPENALEX_MAILTO = os.environ.get("OPENALEX_MAILTO", "rairo@sozofix.tech")
84
 
85
  # -----------------------------------------------------------------------------
86
- # 2. HELPER FUNCTIONS & GROUNDING
87
  # -----------------------------------------------------------------------------
88
 
89
  def verify_token(auth_header):
90
  if not auth_header or not auth_header.startswith('Bearer '):
91
- logger.warning("Missing or invalid Authorization header.")
92
  return None
93
  token = auth_header.split('Bearer ')[1]
94
  try:
@@ -113,19 +109,19 @@ def upload_to_storage(data_bytes, destination_blob_name, content_type):
113
  blob.make_public()
114
  return blob.public_url
115
  except Exception as e:
116
- logger.error(f"Failed to upload to Firebase Storage: {e}")
117
  return None
118
 
119
  def query_wolfram_alpha(query):
120
- if not WOLFRAM_APP_ID: return "Grounded in theoretical physics."
121
  try:
122
  url = f"http://api.wolframalpha.com/v1/result?appid={WOLFRAM_APP_ID}&i={query}"
123
  response = requests.get(url, timeout=5)
124
- return response.text if response.status_code == 200 else "Fact-checking..."
125
- except: return "Grounding context pending."
126
 
127
  # -----------------------------------------------------------------------------
128
- # 3. TITANESS MEDIA ENGINE (PARALLEL BLUEPRINTS & NARRATION)
129
  # -----------------------------------------------------------------------------
130
 
131
  def generate_narration_task(text, uid, epiphany_id, layer_name):
@@ -136,40 +132,38 @@ def generate_narration_task(text, uid, epiphany_id, layer_name):
136
  headers = {"Authorization": f"Token {api_key}", "Content-Type": "text/plain"}
137
  response = requests.post(DEEPGRAM_URL, headers=headers, data=text.encode('utf-8'))
138
  response.raise_for_status()
139
- path = f"users/{uid}/epiphanies/{epiphany_id}/narrations/{layer_name}.mp3"
140
  return layer_name, upload_to_storage(response.content, path, 'audio/mpeg')
141
  except Exception as e:
142
- logger.error(f"TTS Task Error [{layer_name}]: {e}")
143
  return layer_name, None
144
 
145
- def generate_blueprint_task(subject, text, uid, epiphany_id, layer_name):
146
- """Nano Banana Pro: High-fidelity 4K blueprints."""
147
  try:
148
  prompt = (
149
- f"Generate a technical 4K blueprint infographic of a {subject}'s {layer_name}. "
150
- f"Context: {text}. Style: Leonardo Da Vinci sketch meets modern 4K schematic. "
151
- f"Midnight navy background, white-line art. Use Google Search to ensure physical accuracy."
152
  )
153
  response = client.models.generate_content(
154
  model=ATHENA_PRO,
155
  contents=prompt,
156
  config=types.GenerateContentConfig(
157
- tools=[{"google_search": {}}],
158
  image_config=types.ImageConfig(aspect_ratio="16:9", image_size="4K")
159
  )
160
  )
161
  image_parts = [part for part in response.parts if part.inline_data]
162
  if image_parts:
163
- img_bytes = image_parts[0].inline_data.data
164
  path = f"users/{uid}/epiphanies/{epiphany_id}/blueprints/{layer_name}.png"
165
- return layer_name, upload_to_storage(img_bytes, path, 'image/png')
166
  return layer_name, None
167
  except Exception as e:
168
- logger.error(f"Nano Banana Pro Task Error [{layer_name}]: {e}")
169
  return layer_name, None
170
 
171
  # -----------------------------------------------------------------------------
172
- # 4. EPIPHANY & THEIA ENDPOINTS
173
  # -----------------------------------------------------------------------------
174
 
175
  @app.route('/api/image-proxy', methods=['GET'])
@@ -183,7 +177,7 @@ def image_proxy():
183
 
184
  @app.route('/api/epiphany/generate', methods=['POST'])
185
  def generate_epiphany():
186
- """Core Epiphany + Feynman Scholar Search."""
187
  uid = verify_token(request.headers.get('Authorization'))
188
  if not uid: return jsonify({'error': 'Unauthorized'}), 401
189
 
@@ -197,23 +191,23 @@ def generate_epiphany():
197
  pil_image = Image.open(io.BytesIO(image_bytes)).convert('RGB')
198
 
199
  try:
200
- # Step 1: ID
201
- id_prompt = "Identify this object/system precisely. Reply with ONLY the name."
202
  subject = client.models.generate_content(model=ATHENA_FLASH, contents=[id_prompt, pil_image]).text.strip()
203
- logger.info(f"Subject: {subject}")
204
 
205
- # Step 2: Feynman Synthesis + Universal Research Search
206
  physics_fact = query_wolfram_alpha(f"physics laws of {subject}")
207
  synthesis_prompt = f"""
208
- Act as Athena. Analyze '{subject}' grounded in this: {physics_fact}.
209
  Style: Richard Feynman. Simple analogies, profound scientific truths.
210
 
211
  Tasks:
212
  1. Search the web (ArXiv, Patents, Journals) for 3 diverse sources about {subject} using Google Search.
213
  2. Create 4 Discovery Layers (JSON keys: title, genesis, scientific_core, engineering_edge, cross_pollination).
214
- 3. For each of the 3 research sources, provide its URL, Title, and a 2-sentence Feynman Summary.
215
 
216
- Return JSON ONLY.
217
  """
218
 
219
  res = client.models.generate_content(
@@ -225,25 +219,34 @@ def generate_epiphany():
225
  )
226
  )
227
 
228
- data = json.loads(res.text)
 
 
 
 
 
 
 
 
 
 
229
  epiphany_id = str(uuid.uuid4())
230
  layers = ['genesis', 'scientific_core', 'engineering_edge', 'cross_pollination']
231
 
232
  # Step 3: Parallel Media (Titaness Execution)
233
- final_audios = {}
234
- final_blueprints = {}
235
  with ThreadPoolExecutor(max_workers=8) as executor:
236
  aud_futures = [executor.submit(generate_narration_task, data[l], uid, epiphany_id, l) for l in layers]
237
  blu_futures = [executor.submit(generate_blueprint_task, subject, data[l], uid, epiphany_id, l) for l in layers]
238
  for f in aud_futures:
239
  k, v = f.result()
240
- final_audios[k] = v
241
  for f in blu_futures:
242
  k, v = f.result()
243
- final_blueprints[k] = v
244
 
245
  # Step 4: Storage
246
- image_url = upload_to_storage(image_bytes, f"users/{uid}/epiphanies/{epiphany_id}/original.jpg", 'image/jpeg')
247
  epiphany_record = {
248
  "epiphanyId": epiphany_id,
249
  "uid": uid,
@@ -253,11 +256,11 @@ def generate_epiphany():
253
  "layers": {
254
  l: {
255
  "text": data[l],
256
- "audio": final_audios.get(l),
257
- "blueprint": final_blueprints.get(l)
258
  } for l in layers
259
  },
260
- "scholar": data.get('scholar_sources', []),
261
  "createdAt": datetime.utcnow().isoformat()
262
  }
263
 
@@ -266,39 +269,34 @@ def generate_epiphany():
266
  return jsonify(epiphany_record), 201
267
 
268
  except Exception as e:
269
- logger.error(f"Epiphany Gen Error: {e}")
270
  return jsonify({'error': str(e)}), 500
271
 
272
  @app.route('/api/epiphany/theia', methods=['POST'])
273
  def theia_sweep():
274
- """
275
- Separate Feature: Theia Mode.
276
- Takes an epiphany context and performs an annotated 'Universal Sight Sweep'.
277
- """
278
  uid = verify_token(request.headers.get('Authorization'))
279
  if not uid: return jsonify({'error': 'Unauthorized'}), 401
280
-
281
  user_ref = db_ref.child(f'users/{uid}')
282
  if user_ref.get().get('credits', 0) < 4:
283
- return jsonify({'error': 'Need 4 Sparks for Theia Mode.'}), 402
284
 
285
  epiphany_id = request.form.get('epiphanyId')
286
  image_file = request.files['image']
287
 
288
- # Fetch context from existing epiphany
289
- context_data = db_ref.child(f'epiphanies/{epiphany_id}').get() or {}
290
- subject = context_data.get('subject', 'Unknown System')
291
 
292
  sweep_prompt = f"""
293
- Activate Theia Mode for: {subject}.
294
- Task: Use Python Code Execution to perform a surgical spatial deconstruction of this image.
295
- Identify every functional component.
296
- For each component return:
297
  1. Label.
298
  2. Bounding Box [ymin, xmin, ymax, xmax] (0-1000).
299
- 3. A 20-word Feynman-style 'Micro-Epiphany' about its role.
300
-
301
- Return JSON list ONLY.
302
  """
303
 
304
  try:
@@ -311,11 +309,16 @@ def theia_sweep():
311
  response_mime_type='application/json'
312
  )
313
  )
314
- annotations = json.loads(res.text)
 
 
 
 
 
315
  user_ref.update({'credits': user_ref.get().get('credits', 0) - 4})
316
  return jsonify({"annotations": annotations}), 200
317
  except Exception as e:
318
- logger.error(f"Theia Mode Error: {e}")
319
  return jsonify({'error': str(e)}), 500
320
 
321
  @app.route('/api/epiphany/deep-dive', methods=['POST'])
@@ -327,7 +330,7 @@ def deep_dive():
327
  pil_image = Image.open(io.BytesIO(image_file.read())).convert('RGB')
328
  res = client.models.generate_content(
329
  model=ATHENA_FLASH,
330
- contents=["Feynman style: Explain this zoomed-in detail in 50 words.", pil_image]
331
  )
332
  user_ref = db_ref.child(f'users/{uid}')
333
  user_ref.update({'credits': max(0, user_ref.get().get('credits', 0) - 1)})
@@ -335,7 +338,7 @@ def deep_dive():
335
  except Exception as e: return jsonify({'error': str(e)}), 500
336
 
337
  # -----------------------------------------------------------------------------
338
- # 5. CHIRON, ADMIN & AUTH (NO REGRESSION)
339
  # -----------------------------------------------------------------------------
340
 
341
  @app.route('/api/user/call-briefing', methods=['GET'])
@@ -344,12 +347,12 @@ def get_chiron_briefing():
344
  if not uid: return jsonify({'error': 'Unauthorized'}), 401
345
  try:
346
  last = db_ref.child('epiphanies').order_by_child('uid').equal_to(uid).limit_to_last(1).get() or {}
347
- ctx = "New Seeker."
348
  if last:
349
  e = list(last.values())[0]
350
- ctx = f"Subject: {e['subject']}. Recent Research: {e.get('scholar', [])[:1]}"
351
- prompt = f"Prep Chiron (Socratic Mentor). Context: {ctx}. 4-sentence brief."
352
- res = client.models.generate_content(model=BRIEFING_MODEL, contents=[prompt])
353
  return jsonify({"memory_summary": res.text.strip()}), 200
354
  except Exception as e: return jsonify({'error': str(e)}), 500
355
 
@@ -360,11 +363,10 @@ def log_usage():
360
  data = request.json
361
  cost = math.ceil(data.get("durationSeconds", 0) / 60) * 3
362
  user_ref = db_ref.child(f'users/{uid}')
363
- new_bal = max(0, user_ref.get().get('credits', 0) - cost)
364
- user_ref.update({'credits': new_bal})
365
  if data.get("transcript"):
366
  db_ref.child(f'transcripts/{uid}').push({"text": data["transcript"], "at": datetime.utcnow().isoformat()})
367
- return jsonify({"success": True, "remainingCredits": new_bal}), 200
368
 
369
  @app.route('/api/admin/dashboard', methods=['GET'])
370
  def admin_dashboard():
@@ -391,6 +393,10 @@ def request_sparks():
391
  db_ref.child('credit_requests').push({"uid": uid, "at": datetime.utcnow().isoformat(), "status": "pending"})
392
  return jsonify({"success": True})
393
 
 
 
 
 
394
  @app.route('/api/auth/signup', methods=['POST'])
395
  def signup():
396
  uid = verify_token(request.headers.get('Authorization'))
@@ -412,7 +418,7 @@ def social_signin():
412
  return jsonify({'uid': uid, **user_ref.get()}), 200
413
 
414
  @app.route('/api/user/profile', methods=['GET'])
415
- def profile():
416
  uid = verify_token(request.headers.get('Authorization'))
417
  if not uid: return jsonify({'error': 'Unauthorized'}), 401
418
  return jsonify(db_ref.child(f'users/{uid}').get())
@@ -424,10 +430,6 @@ def list_epiphanies():
424
  res = db_ref.child('epiphanies').order_by_child('uid').equal_to(uid).get() or {}
425
  return jsonify(list(res.values()))
426
 
427
- # -----------------------------------------------------------------------------
428
- # 8. MAIN EXECUTION
429
- # -----------------------------------------------------------------------------
430
-
431
  if __name__ == '__main__':
432
- logger.info("Titaness Final Backbone Active on 7860...")
433
  app.run(debug=False, host="0.0.0.0", port=7860)
 
36
  app = Flask(__name__)
37
  CORS(app)
38
 
 
39
  try:
40
  logger.info("Initializing Firebase Admin SDK...")
41
  credentials_json_string = os.environ.get("FIREBASE")
 
59
  bucket = storage.bucket()
60
  db_ref = db.reference()
61
 
 
62
  try:
63
+ logger.info("Initializing Google GenAI Client (Gemini 3.0)...")
64
  api_key = os.environ.get("Gemini")
65
  if not api_key:
66
  raise ValueError("The 'Gemini' API key is not set.")
 
71
  logger.error(f"FATAL: Error initializing GenAI Client: {e}")
72
  exit(1)
73
 
74
+ # Corrected Model Constants
75
  ATHENA_FLASH = "gemini-3-flash-preview"
76
  ATHENA_PRO = "gemini-3-pro-image-preview"
 
77
 
78
+ # Grounding API Keys
79
  WOLFRAM_APP_ID = os.environ.get("WOLFRAM_APP_ID")
80
  OPENALEX_MAILTO = os.environ.get("OPENALEX_MAILTO", "rairo@sozofix.tech")
81
 
82
  # -----------------------------------------------------------------------------
83
+ # 2. HELPER FUNCTIONS & AUTH
84
  # -----------------------------------------------------------------------------
85
 
86
  def verify_token(auth_header):
87
  if not auth_header or not auth_header.startswith('Bearer '):
 
88
  return None
89
  token = auth_header.split('Bearer ')[1]
90
  try:
 
109
  blob.make_public()
110
  return blob.public_url
111
  except Exception as e:
112
+ logger.error(f"Storage Upload Error: {e}")
113
  return None
114
 
115
  def query_wolfram_alpha(query):
116
+ if not WOLFRAM_APP_ID: return "Grounded in first principles."
117
  try:
118
  url = f"http://api.wolframalpha.com/v1/result?appid={WOLFRAM_APP_ID}&i={query}"
119
  response = requests.get(url, timeout=5)
120
+ return response.text if response.status_code == 200 else "Constants verifying..."
121
+ except: return "Grounding in progress."
122
 
123
  # -----------------------------------------------------------------------------
124
+ # 3. TITANESS MEDIA ENGINE (AUDIO + INFOGRAPHICS)
125
  # -----------------------------------------------------------------------------
126
 
127
  def generate_narration_task(text, uid, epiphany_id, layer_name):
 
132
  headers = {"Authorization": f"Token {api_key}", "Content-Type": "text/plain"}
133
  response = requests.post(DEEPGRAM_URL, headers=headers, data=text.encode('utf-8'))
134
  response.raise_for_status()
135
+ path = f"users/{uid}/epiphanies/{epiphany_id}/audio/{layer_name}.mp3"
136
  return layer_name, upload_to_storage(response.content, path, 'audio/mpeg')
137
  except Exception as e:
138
+ logger.error(f"Narration Task Error: {e}")
139
  return layer_name, None
140
 
141
+ def generate_blueprint_task(subject, layer_text, uid, epiphany_id, layer_name):
142
+ """Nano Banana Pro: Generates 4K Technical Blueprints."""
143
  try:
144
  prompt = (
145
+ f"Generate a technical 4K blueprint infographic of {subject} - {layer_name}. "
146
+ f"Context: {layer_text}. Style: White-line schematic on midnight navy background. 4K quality."
 
147
  )
148
  response = client.models.generate_content(
149
  model=ATHENA_PRO,
150
  contents=prompt,
151
  config=types.GenerateContentConfig(
 
152
  image_config=types.ImageConfig(aspect_ratio="16:9", image_size="4K")
153
  )
154
  )
155
  image_parts = [part for part in response.parts if part.inline_data]
156
  if image_parts:
157
+ image_bytes = image_parts[0].inline_data.data
158
  path = f"users/{uid}/epiphanies/{epiphany_id}/blueprints/{layer_name}.png"
159
+ return layer_name, upload_to_storage(image_bytes, path, 'image/png')
160
  return layer_name, None
161
  except Exception as e:
162
+ logger.error(f"Nano Banana Pro Error [{layer_name}]: {e}")
163
  return layer_name, None
164
 
165
  # -----------------------------------------------------------------------------
166
+ # 4. CORE ENDPOINTS (EPIPHANY, THEIA, PROXY)
167
  # -----------------------------------------------------------------------------
168
 
169
  @app.route('/api/image-proxy', methods=['GET'])
 
177
 
178
  @app.route('/api/epiphany/generate', methods=['POST'])
179
  def generate_epiphany():
180
+ logger.info(">>> START generate_epiphany")
181
  uid = verify_token(request.headers.get('Authorization'))
182
  if not uid: return jsonify({'error': 'Unauthorized'}), 401
183
 
 
191
  pil_image = Image.open(io.BytesIO(image_bytes)).convert('RGB')
192
 
193
  try:
194
+ # Step 1: Rapid ID
195
+ id_prompt = "Identify this precisely. Reply with ONLY the name."
196
  subject = client.models.generate_content(model=ATHENA_FLASH, contents=[id_prompt, pil_image]).text.strip()
197
+ logger.info(f"Subject identified: {subject}")
198
 
199
+ # Step 2: Synthesis + Feynman Scholar (Unified Search)
200
  physics_fact = query_wolfram_alpha(f"physics laws of {subject}")
201
  synthesis_prompt = f"""
202
+ Act as Athena. Analyze '{subject}' grounded in: {physics_fact}.
203
  Style: Richard Feynman. Simple analogies, profound scientific truths.
204
 
205
  Tasks:
206
  1. Search the web (ArXiv, Patents, Journals) for 3 diverse sources about {subject} using Google Search.
207
  2. Create 4 Discovery Layers (JSON keys: title, genesis, scientific_core, engineering_edge, cross_pollination).
208
+ 3. For each research source, provide Title, URL, and a 2-sentence Feynman Summary. (JSON key: scholar).
209
 
210
+ Return a JSON OBJECT only.
211
  """
212
 
213
  res = client.models.generate_content(
 
219
  )
220
  )
221
 
222
+ # TYPE-SAFE JSON PARSING
223
+ raw_json = res.text.strip()
224
+ if raw_json.startswith("```json"):
225
+ raw_json = re.search(r'```json\n(.*?)\n```', raw_json, re.DOTALL).group(1)
226
+
227
+ data = json.loads(raw_json)
228
+ # Fix for "list indices" error: If Gemini returns a list, take the first object
229
+ if isinstance(data, list):
230
+ data = data[0]
231
+ logger.info("Handled JSON List-to-Object conversion.")
232
+
233
  epiphany_id = str(uuid.uuid4())
234
  layers = ['genesis', 'scientific_core', 'engineering_edge', 'cross_pollination']
235
 
236
  # Step 3: Parallel Media (Titaness Execution)
237
+ audios, blueprints = {}, {}
 
238
  with ThreadPoolExecutor(max_workers=8) as executor:
239
  aud_futures = [executor.submit(generate_narration_task, data[l], uid, epiphany_id, l) for l in layers]
240
  blu_futures = [executor.submit(generate_blueprint_task, subject, data[l], uid, epiphany_id, l) for l in layers]
241
  for f in aud_futures:
242
  k, v = f.result()
243
+ audios[k] = v
244
  for f in blu_futures:
245
  k, v = f.result()
246
+ blueprints[k] = v
247
 
248
  # Step 4: Storage
249
+ image_url = upload_to_storage(image_bytes, f"users/{uid}/epiphanies/{epiphany_id}/vision.jpg", 'image/jpeg')
250
  epiphany_record = {
251
  "epiphanyId": epiphany_id,
252
  "uid": uid,
 
256
  "layers": {
257
  l: {
258
  "text": data[l],
259
+ "audio": audios.get(l),
260
+ "blueprint": blueprints.get(l)
261
  } for l in layers
262
  },
263
+ "scholar": data.get('scholar', []),
264
  "createdAt": datetime.utcnow().isoformat()
265
  }
266
 
 
269
  return jsonify(epiphany_record), 201
270
 
271
  except Exception as e:
272
+ logger.error(f"Epiphany Gen Error: {e}\n{traceback.format_exc()}")
273
  return jsonify({'error': str(e)}), 500
274
 
275
  @app.route('/api/epiphany/theia', methods=['POST'])
276
  def theia_sweep():
277
+ """Independent Feature: Annotated deconstruction using Code Execution."""
 
 
 
278
  uid = verify_token(request.headers.get('Authorization'))
279
  if not uid: return jsonify({'error': 'Unauthorized'}), 401
280
+
281
  user_ref = db_ref.child(f'users/{uid}')
282
  if user_ref.get().get('credits', 0) < 4:
283
+ return jsonify({'error': 'Need 4 Sparks for Theia Sweep.'}), 402
284
 
285
  epiphany_id = request.form.get('epiphanyId')
286
  image_file = request.files['image']
287
 
288
+ # Context fetch
289
+ context = db_ref.child(f'epiphanies/{epiphany_id}').get() or {}
290
+ subject = context.get('subject', 'Complex System')
291
 
292
  sweep_prompt = f"""
293
+ Theia Mode Activation: {subject}.
294
+ Task: Use Python Code Execution for spatial deconstruction.
295
+ Identify components and for each return:
 
296
  1. Label.
297
  2. Bounding Box [ymin, xmin, ymax, xmax] (0-1000).
298
+ 3. 20-word Feynman-style Micro-Epiphany.
299
+ Return JSON list.
 
300
  """
301
 
302
  try:
 
309
  response_mime_type='application/json'
310
  )
311
  )
312
+
313
+ raw_json = res.text.strip()
314
+ if raw_json.startswith("```json"):
315
+ raw_json = re.search(r'```json\n(.*?)\n```', raw_json, re.DOTALL).group(1)
316
+
317
+ annotations = json.loads(raw_json)
318
  user_ref.update({'credits': user_ref.get().get('credits', 0) - 4})
319
  return jsonify({"annotations": annotations}), 200
320
  except Exception as e:
321
+ logger.error(f"Theia Error: {e}")
322
  return jsonify({'error': str(e)}), 500
323
 
324
  @app.route('/api/epiphany/deep-dive', methods=['POST'])
 
330
  pil_image = Image.open(io.BytesIO(image_file.read())).convert('RGB')
331
  res = client.models.generate_content(
332
  model=ATHENA_FLASH,
333
+ contents=["In 50 words Feynman style, explain this zoom detail.", pil_image]
334
  )
335
  user_ref = db_ref.child(f'users/{uid}')
336
  user_ref.update({'credits': max(0, user_ref.get().get('credits', 0) - 1)})
 
338
  except Exception as e: return jsonify({'error': str(e)}), 500
339
 
340
  # -----------------------------------------------------------------------------
341
+ # 5. CHIRON & SYSTEM UTILS
342
  # -----------------------------------------------------------------------------
343
 
344
  @app.route('/api/user/call-briefing', methods=['GET'])
 
347
  if not uid: return jsonify({'error': 'Unauthorized'}), 401
348
  try:
349
  last = db_ref.child('epiphanies').order_by_child('uid').equal_to(uid).limit_to_last(1).get() or {}
350
+ ctx = "New seeker."
351
  if last:
352
  e = list(last.values())[0]
353
+ ctx = f"Subject: {e['subject']}. Research: {e.get('scholar', [])}"
354
+ prompt = f"Prep Chiron (Mentor). Context: {ctx}. 4-sentence brief."
355
+ res = client.models.generate_content(model=ATHENA_FLASH, contents=[prompt])
356
  return jsonify({"memory_summary": res.text.strip()}), 200
357
  except Exception as e: return jsonify({'error': str(e)}), 500
358
 
 
363
  data = request.json
364
  cost = math.ceil(data.get("durationSeconds", 0) / 60) * 3
365
  user_ref = db_ref.child(f'users/{uid}')
366
+ user_ref.update({'credits': max(0, (user_ref.get().get('credits', 0)) - cost)})
 
367
  if data.get("transcript"):
368
  db_ref.child(f'transcripts/{uid}').push({"text": data["transcript"], "at": datetime.utcnow().isoformat()})
369
+ return jsonify({"success": True})
370
 
371
  @app.route('/api/admin/dashboard', methods=['GET'])
372
  def admin_dashboard():
 
393
  db_ref.child('credit_requests').push({"uid": uid, "at": datetime.utcnow().isoformat(), "status": "pending"})
394
  return jsonify({"success": True})
395
 
396
+ # -----------------------------------------------------------------------------
397
+ # 6. AUTH & USER PROFILE
398
+ # -----------------------------------------------------------------------------
399
+
400
  @app.route('/api/auth/signup', methods=['POST'])
401
  def signup():
402
  uid = verify_token(request.headers.get('Authorization'))
 
418
  return jsonify({'uid': uid, **user_ref.get()}), 200
419
 
420
  @app.route('/api/user/profile', methods=['GET'])
421
+ def get_profile():
422
  uid = verify_token(request.headers.get('Authorization'))
423
  if not uid: return jsonify({'error': 'Unauthorized'}), 401
424
  return jsonify(db_ref.child(f'users/{uid}').get())
 
430
  res = db_ref.child('epiphanies').order_by_child('uid').equal_to(uid).get() or {}
431
  return jsonify(list(res.values()))
432
 
 
 
 
 
433
  if __name__ == '__main__':
434
+ logger.info("Titaness Paradigm Server Active...")
435
  app.run(debug=False, host="0.0.0.0", port=7860)