@hiperplano/aluy-cli 1.0.0-rc.36 → 1.0.0-rc.38

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.
@@ -36,7 +36,10 @@ DEFAULT_PORT = 11435
36
36
  DEFAULT_HOST = "127.0.0.1"
37
37
  ALUY_MEMORY_DIR = os.path.expanduser("~/.aluy/memory")
38
38
  OLLAMA_BASE_URL = "http://127.0.0.1:11434"
39
- EMBEDDER_MODEL = "nomic-embed-text"
39
+ # Embedder CONFIG-DRIVEN: o boot passa `ALUY_MEM0_EMBEDDER` (escolhido na instalação); default
40
+ # bge-m3 (multilíngue, forte). Trocar o embedder muda a DIMENSÃO do vetor (bge-m3/mxbai=1024,
41
+ # nomic=768) ⇒ o store chromadb antigo fica incompatível e o self-heal o reseta no 1º boot.
42
+ EMBEDDER_MODEL = os.environ.get("ALUY_MEM0_EMBEDDER", "bge-m3").strip() or "bge-m3"
40
43
  # LLM local p/ extração de fatos (mem0 add infer=True). SEM isto o mem0 cai no
41
44
  # default OpenAI → 401. Local-first: tudo via Ollama loopback, zero credencial.
42
45
  LLM_MODEL = "qwen2.5:0.5b"
@@ -320,6 +323,38 @@ class ThreadingHTTPServer(ThreadingMixIn, HTTPServer):
320
323
 
321
324
 
322
325
  # ── Main ──────────────────────────────────────────────────────────────────
326
+ EMBEDDER_MARKER = os.path.join(ALUY_MEMORY_DIR, ".embedder")
327
+
328
+
329
+ def _migrate_embedder_if_changed() -> None:
330
+ """Se o embedder mudou desde o último boot (marca em `.embedder` ≠ atual), a dimensão do
331
+ vetor muda e o store chromadb fica incompatível ⇒ reseta proativamente. Best-effort."""
332
+ try:
333
+ prev = None
334
+ if os.path.exists(EMBEDDER_MARKER):
335
+ with open(EMBEDDER_MARKER, encoding="utf-8") as fh:
336
+ prev = fh.read().strip()
337
+ if prev is not None and prev != EMBEDDER_MODEL:
338
+ sys.stderr.write(
339
+ f"aluy-mem0: embedder mudou ({prev} → {EMBEDDER_MODEL}); "
340
+ "dimensão do vetor difere — resetando store p/ recriar.\n"
341
+ )
342
+ _reset_incompatible_stores()
343
+ os.makedirs(ALUY_MEMORY_DIR, mode=0o700, exist_ok=True)
344
+ except Exception: # noqa: BLE001 — migração best-effort, nunca derruba o boot
345
+ pass
346
+
347
+
348
+ def _write_embedder_marker() -> None:
349
+ """Grava qual embedder gerou os vetores atuais (p/ detectar troca no próximo boot)."""
350
+ try:
351
+ os.makedirs(ALUY_MEMORY_DIR, mode=0o700, exist_ok=True)
352
+ with open(EMBEDDER_MARKER, "w", encoding="utf-8") as fh:
353
+ fh.write(EMBEDDER_MODEL)
354
+ except Exception: # noqa: BLE001
355
+ pass
356
+
357
+
323
358
  def _reset_incompatible_stores() -> None:
324
359
  """Move os stores de memória p/ backup, p/ recriar frescos. Chamado quando a versão atual
325
360
  do chromadb/mem0 não lê o store de uma versão anterior (KeyError '_type' no chromadb /
@@ -367,6 +402,13 @@ def main() -> None:
367
402
  # Garante o dir de store com perms corretas.
368
403
  os.makedirs(ALUY_MEMORY_DIR, mode=0o700, exist_ok=True)
369
404
 
405
+ # MIGRAÇÃO DE EMBEDDER (proativa): trocar o embedder muda a DIMENSÃO do vetor (bge-m3/
406
+ # mxbai=1024, nomic=768). O chromadb só estoura a incompatibilidade no ADD/SEARCH (runtime),
407
+ # NÃO no boot — então o self-heal abaixo (que envolve só o `from_config`) não pegaria. Aqui,
408
+ # ANTES de subir: se o embedder mudou desde o último boot, reseta o store (a marca guarda
409
+ # qual embedder gerou os vetores atuais). Best-effort — nunca derruba o boot.
410
+ _migrate_embedder_if_changed()
411
+
370
412
  # Instancia Memory() UMA vez. SELF-HEAL de upgrade: um store gravado por uma versão
371
413
  # ANTERIOR do chromadb/mem0 pode ser ilegível pela atual (ex.: chromadb `KeyError: '_type'`
372
414
  # na config da collection; sqlite `no such column: prev_value` no history). Em vez de
@@ -409,6 +451,9 @@ def main() -> None:
409
451
  else:
410
452
  return # inalcançável (execv substitui o processo) — só p/ o type-checker
411
453
 
454
+ # Store criado/aberto OK com o embedder atual — grava a marca p/ detectar troca futura.
455
+ _write_embedder_marker()
456
+
412
457
  # Injeta no handler.
413
458
  Mem0Handler.memory = memory
414
459
  Mem0Handler.users = _load_users()