fix: multi-user distillation + datetime in context + session log labels
Distillation was silently operating on scott/inara for all users due to ContextVar defaults. All three distill endpoints now require ?user=&persona= query params and validate them via persona.validate(). Memory distiller signatures changed from Optional to required positional args — no more global settings fallback. Scheduler now iterates all users/personas instead of hardcoding the primary user. - context_loader: inject current date/time as first system prompt section - session_logger: use get_user()/get_persona() from context instead of settings globals so Holly/Brian sessions show correct speaker labels - memory_distiller: system prompts now reference u.title()/p.title() instead of settings.user_name/settings.agent_name - distill router: Query(...) enforces params; _resolve() validates persona - scheduler: _all_personas() helper iterates every user/persona for distill - app.js: runDistill() now appends ?user=&persona= via _fileParams Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -19,41 +19,54 @@ logger = logging.getLogger(__name__)
|
||||
_scheduler: AsyncIOScheduler | None = None
|
||||
|
||||
|
||||
def _all_personas() -> list[tuple[str, str]]:
|
||||
"""Return [(username, persona_name)] for every persona on this instance."""
|
||||
from persona import list_users, list_user_personas
|
||||
pairs = []
|
||||
for u in list_users():
|
||||
for p in list_user_personas(u):
|
||||
pairs.append((u, p))
|
||||
return pairs
|
||||
|
||||
|
||||
async def _run_short() -> None:
|
||||
from memory_distiller import distill_short
|
||||
try:
|
||||
result = distill_short()
|
||||
logger.info("auto distill short: %d files, %d chars", result["files_included"], result["chars_written"])
|
||||
except Exception as e:
|
||||
logger.error("auto distill short failed: %s", e)
|
||||
for u, p in _all_personas():
|
||||
try:
|
||||
result = distill_short(u, p)
|
||||
logger.info("auto distill short [%s/%s]: %d files, %d chars", u, p, result["files_included"], result["chars_written"])
|
||||
except Exception as e:
|
||||
logger.error("auto distill short [%s/%s] failed: %s", u, p, e)
|
||||
|
||||
|
||||
async def _run_mid() -> None:
|
||||
from memory_distiller import distill_mid
|
||||
from notification import notify
|
||||
try:
|
||||
result = await distill_mid()
|
||||
if "error" in result:
|
||||
logger.warning("auto distill mid skipped: %s", result["error"])
|
||||
else:
|
||||
logger.info("auto distill mid: %d chars via %s", result["chars_written"], result["backend"])
|
||||
await notify(result["username"], f"📝 Weekly memory digest complete ({result['chars_written']} chars via {result['backend']}).")
|
||||
except Exception as e:
|
||||
logger.error("auto distill mid failed: %s", e)
|
||||
for u, p in _all_personas():
|
||||
try:
|
||||
result = await distill_mid(u, p)
|
||||
if "error" in result:
|
||||
logger.warning("auto distill mid [%s/%s] skipped: %s", u, p, result["error"])
|
||||
else:
|
||||
logger.info("auto distill mid [%s/%s]: %d chars via %s", u, p, result["chars_written"], result["backend"])
|
||||
await notify(u, f"📝 Weekly memory digest complete ({result['chars_written']} chars via {result['backend']}).")
|
||||
except Exception as e:
|
||||
logger.error("auto distill mid [%s/%s] failed: %s", u, p, e)
|
||||
|
||||
|
||||
async def _run_long() -> None:
|
||||
from memory_distiller import distill_long
|
||||
from notification import notify
|
||||
try:
|
||||
result = await distill_long()
|
||||
if "error" in result:
|
||||
logger.warning("auto distill long skipped: %s", result["error"])
|
||||
else:
|
||||
logger.info("auto distill long: %d chars via %s", result["chars_written"], result["backend"])
|
||||
await notify(result["username"], f"🧠 Monthly long-term memory integration complete ({result['chars_written']} chars via {result['backend']}). Worth a quick review.")
|
||||
except Exception as e:
|
||||
logger.error("auto distill long failed: %s", e)
|
||||
for u, p in _all_personas():
|
||||
try:
|
||||
result = await distill_long(u, p)
|
||||
if "error" in result:
|
||||
logger.warning("auto distill long [%s/%s] skipped: %s", u, p, result["error"])
|
||||
else:
|
||||
logger.info("auto distill long [%s/%s]: %d chars via %s", u, p, result["chars_written"], result["backend"])
|
||||
await notify(u, f"🧠 Monthly long-term memory integration complete ({result['chars_written']} chars via {result['backend']}). Worth a quick review.")
|
||||
except Exception as e:
|
||||
logger.error("auto distill long [%s/%s] failed: %s", u, p, e)
|
||||
|
||||
|
||||
def get_scheduler() -> AsyncIOScheduler | None:
|
||||
|
||||
Reference in New Issue
Block a user