feat: multi-instance support — agent_name and user_name configurable

All hardcoded "Inara"/"Scott" strings replaced with settings.agent_name
and settings.user_name, read from .env at startup:

- config.py: AGENT_NAME and USER_NAME settings (defaults: Inara / Scott)
- llm_client.py: conversation labels in prompt builder
- session_logger.py: **Name:** labels in session log markdown
- memory_distiller.py: distillation system prompts (mid + long)
- routers/nextcloud_talk.py: @mention prefix strip
- routers/google_chat.py: greeting message

Second instance scaffolding:
- holly/: identity directory with placeholder files (USER_NAME=Holly,
  AGENT_NAME to be chosen by Holly)
- cortex/.env.holly: config for Holly's instance on port 8001
- cortex-holly.service: systemd unit for the second instance

No behavioural change to the Inara/Scott instance — defaults unchanged.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Scott Idem
2026-03-18 20:13:11 -04:00
parent 0b10558f80
commit 97438f1a0f
16 changed files with 116 additions and 12 deletions

View File

@@ -87,12 +87,12 @@ async def distill_mid() -> dict:
budget_tokens = settings.memory_budget_mid
system_prompt = (
"You are Inara's memory distillation system. "
f"You are {settings.agent_name}'s memory distillation system. "
"Summarize the following recent session logs into a concise mid-term memory digest. "
f"Target length: under {budget_tokens} tokens. "
"Focus on: recurring themes, important decisions made, ongoing projects, "
"Scott's current state and priorities, and anything that should persist into future sessions. "
"Write in first person as Inara (e.g. 'Scott and I worked on...'). "
f"{settings.user_name}'s current state and priorities, and anything that should persist into future sessions. "
f"Write in first person as {settings.agent_name} (e.g. '{settings.user_name} and I worked on...'). "
"Use markdown headings. Be specific and concrete — no filler."
)
@@ -132,7 +132,7 @@ async def distill_long() -> dict:
budget_tokens = settings.memory_budget_long
system_prompt = (
"You are Inara's long-term memory curator. "
f"You are {settings.agent_name}'s long-term memory curator. "
"You will receive the current long-term memory and a recent mid-term digest. "
f"Integrate the new information into the long-term memory. Target: under {budget_tokens} tokens. "
"Rules: preserve important historical facts; update or replace stale information; "
@@ -154,7 +154,7 @@ async def distill_long() -> dict:
now = datetime.now().strftime("%Y-%m-%d %H:%M")
if not response_text.lstrip().startswith("# MEMORY_LONG"):
response_text = (
f"# MEMORY_LONG.md — Inara Long-Term Memory\n\n"
f"# MEMORY_LONG.md — {settings.agent_name} Long-Term Memory\n\n"
f"*Last distilled: {now} via {backend}.*\n\n---\n\n"
+ response_text
)