nexo-brain 1.2.2 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -239,11 +239,9 @@ def handle_heartbeat(sid: str, task: str, context_hint: str = '') -> str:
239
239
  'wazion': 'wazion', 'chrome extension': 'wazion', 'vps': 'wazion',
240
240
  'meta': 'meta-ads', 'facebook': 'meta-ads', 'advantage': 'meta-ads',
241
241
  'google ads': 'google-ads', 'pmax': 'google-ads', 'campaign': 'google-ads',
242
- 'project_a': 'project_a', 'user_contact': 'project_a',
243
- 'shared-hosting': 'infrastructure', 'servidor': 'infrastructure', 'ssh': 'infrastructure',
242
+ 'server': 'infrastructure', 'ssh': 'infrastructure', 'deploy': 'infrastructure',
244
243
  'analytics': 'google-analytics', 'ga4': 'google-analytics',
245
244
  'nexo brain': 'nexo', 'nexo-brain': 'nexo', 'cognitive': 'nexo',
246
- 'ecommerce': 'shopify',
247
245
  }
248
246
  hint_lower = context_hint.lower()
249
247
  detected_area = None
@@ -347,7 +345,7 @@ def handle_context_packet(area: str, files: str = "") -> str:
347
345
  for the given area. Use this before delegating to a subagent.
348
346
 
349
347
  Args:
350
- area: Project/area name (e.g., 'wazion', 'shopify', 'meta-ads', 'project_a', 'nexo')
348
+ area: Project/area name (e.g., 'shopify', 'meta-ads', 'infrastructure', 'nexo')
351
349
  files: Optional comma-separated file paths for guard check
352
350
  """
353
351
  from db import get_db
@@ -360,7 +358,7 @@ def handle_context_packet(area: str, files: str = "") -> str:
360
358
  (f"%{area}%", f"%{area}%")
361
359
  ).fetchall()
362
360
  if learnings:
363
- parts.append("## ERRORES CONOCIDOSNO REPETIR")
361
+ parts.append("## KNOWN ERRORSDO NOT REPEAT")
364
362
  for l in learnings:
365
363
  parts.append(f" L#{l['id']}: {l['title']}")
366
364
  # First 200 chars of content
@@ -373,7 +371,7 @@ def handle_context_packet(area: str, files: str = "") -> str:
373
371
  (f"%{area}%", f"%{area}%")
374
372
  ).fetchall()
375
373
  if changes:
376
- parts.append("## CAMBIOS RECIENTES")
374
+ parts.append("## RECENT CHANGES")
377
375
  for c in changes:
378
376
  parts.append(f" C#{c['id']}: {c['what_changed'][:150]}")
379
377
  if c['why']:
@@ -386,9 +384,9 @@ def handle_context_packet(area: str, files: str = "") -> str:
386
384
  (f"%{area}%", f"%{area}%")
387
385
  ).fetchall()
388
386
  if followups:
389
- parts.append("## FOLLOWUPS ACTIVOS")
387
+ parts.append("## ACTIVE FOLLOWUPS")
390
388
  for f in followups:
391
- parts.append(f" {f['id']}: {f['description'][:150]} (fecha: {f['date']})")
389
+ parts.append(f" {f['id']}: {f['description'][:150]} (date: {f['date']})")
392
390
  parts.append("")
393
391
 
394
392
  # 4. Preferences related to this area
@@ -398,7 +396,7 @@ def handle_context_packet(area: str, files: str = "") -> str:
398
396
  (f"%{area}%", f"%{area}%")
399
397
  ).fetchall()
400
398
  if prefs:
401
- parts.append("## PREFERENCIAS")
399
+ parts.append("## PREFERENCES")
402
400
  for p in prefs:
403
401
  parts.append(f" {p['key']}: {p['value'][:150]}")
404
402
  parts.append("")
@@ -416,18 +414,28 @@ def handle_context_packet(area: str, files: str = "") -> str:
416
414
  rehearse=False,
417
415
  )
418
416
  if results:
419
- parts.append("## MEMORIAS COGNITIVAS RELEVANTES")
417
+ parts.append("## RELEVANT COGNITIVE MEMORIES")
420
418
  for r in results:
421
419
  parts.append(f" [{r['source_type']}] {r['source_title'] or r['content'][:80]}")
422
420
  parts.append("")
423
421
  except Exception:
424
422
  pass
425
423
 
424
+ # 6. Data flow tracing requirement (mandatory for all subagents)
425
+ parts.append("## MANDATORY RULE: DATA FLOW TRACING")
426
+ parts.append("BEFORE modifying any file or data, answer these 3 questions:")
427
+ parts.append(" 1. WHO PRODUCES this data? (which function/cron/endpoint generates it)")
428
+ parts.append(" 2. WHO CONSUMES this data? (which other files/functions read it)")
429
+ parts.append(" 3. WHAT BREAKS if I change it? (downstream effects)")
430
+ parts.append("If you cannot answer all 3 → READ the code that produces and consumes BEFORE touching it.")
431
+ parts.append("If you still cannot answer → STOP and return the question. DO NOT guess.")
432
+ parts.append("")
433
+
426
434
  if not parts:
427
435
  return f"No context found for area '{area}'. The subagent will start with no project-specific knowledge."
428
436
 
429
437
  header = f"CONTEXT PACKET — {area.upper()}\n{'='*40}\n\n"
430
- footer = f"\n{'='*40}\nINSTRUCCIÓN: Si no estás 100% seguro de un dato, PARA y devuelve la pregunta. NO inventes."
438
+ footer = f"\n{'='*40}\nRULE: If you are not 100% sure about a piece of data, STOP and return the question. DO NOT make things up."
431
439
  return header + "\n".join(parts) + footer
432
440
 
433
441
 
@@ -448,7 +456,7 @@ def handle_smart_startup_query() -> str:
448
456
  for f in followups:
449
457
  query_parts.append(f['description'][:100])
450
458
 
451
- # 2. Due reminders (what user needs to know)
459
+ # 2. Due reminders (what the owner needs to know)
452
460
  reminders = conn.execute(
453
461
  "SELECT description FROM reminders WHERE status = 'PENDIENTE' AND date <= date('now', '+1 day') ORDER BY date ASC LIMIT 5"
454
462
  ).fetchall()