The user's name, so the assistant knows what to call them.
GET/PUT /v1/profile read and write a small block in the persona's
USER.md, which :class:~locus.prompt.builder.SystemPromptBuilder adds to
every system prompt under "User Profile". Anything else the user keeps in that
file is left alone. The block is plain text, so the CLI and agents see the same
name, and editing it by hand works too.
Functions
render_block
render_block(profile: Profile) -> str
The USER.md block for profile, or "" when it's empty.
Source code in src/locus/server/profile_routes.py
| def render_block(profile: Profile) -> str:
"""The USER.md block for ``profile``, or "" when it's empty."""
values = {key: _clean(getattr(profile, key)) for key, _ in _FIELDS}
if not any(values.values()):
return ""
lines = [START]
lines += [f"{label}: {values[key]}" for key, label in _FIELDS if values[key]]
call_them = values["nickname"] or values["first_name"]
if call_them:
lines.append(
f'Address the user as "{call_them}" when you greet them or speak to them '
"directly, unless they ask you to use a different name."
)
lines.append(END)
return "\n".join(lines) + "\n"
|
parse_block
parse_block(text: str) -> Profile
The profile stored in USER.md text (empty if there is none).
Source code in src/locus/server/profile_routes.py
| def parse_block(text: str) -> Profile:
"""The profile stored in USER.md ``text`` (empty if there is none)."""
match = _BLOCK_RE.search(text)
if not match:
return Profile()
found = {}
for key, label in _FIELDS:
line = re.search(rf"^{label}: (.*)$", match.group(0), re.M)
if line:
found[key] = line.group(1).strip()
return Profile(**found)
|
write_profile
write_profile(path: Path, profile: Profile) -> None
Replace (or add, or remove) the profile block in path.
Source code in src/locus/server/profile_routes.py
| def write_profile(path: Path, profile: Profile) -> None:
"""Replace (or add, or remove) the profile block in ``path``."""
existing = path.read_text(encoding="utf-8") if path.exists() else ""
rest = _BLOCK_RE.sub("", existing).lstrip("\n")
block = render_block(profile)
if not block and not rest:
if path.exists():
path.unlink()
return
content = block + ("\n" + rest if block and rest else rest)
path.parent.mkdir(parents=True, exist_ok=True)
path.write_text(content, encoding="utf-8")
|
profile_path
profile_path(request: Request) -> Path
The USER.md the system prompt reads, honouring a named persona.
Source code in src/locus/server/profile_routes.py
| def profile_path(request: Request) -> Path:
"""The USER.md the system prompt reads, honouring a named persona."""
from locus.core.config import load_config
from locus.prompt.builder import SystemPromptBuilder
config = getattr(request.app.state, "config", None) or load_config()
resolved = SystemPromptBuilder._resolve_persona(config.memory_files)
if not resolved.user_path:
# persona_name = "none" turns persona files off entirely.
raise HTTPException(
status_code=409,
detail='Persona files are turned off (persona_name = "none"), '
"so Locus can't use your name.",
)
return Path(resolved.user_path).expanduser()
|