From 9d9151ba6e6c06fe213d20f5e4aaabbec6750946 Mon Sep 17 00:00:00 2001 From: Guillermo Serrahima Date: Mon, 29 Jun 2026 10:32:46 +0200 Subject: Added current user to context --- agent/orchestrator/api.py | 7 +++++++ agent/orchestrator/context.py | 19 ++++++++++++------- agent/orchestrator/loop.py | 26 +++++++++++++++++++++++++- 3 files changed, 44 insertions(+), 8 deletions(-) diff --git a/agent/orchestrator/api.py b/agent/orchestrator/api.py index c3582d4..956f7b5 100644 --- a/agent/orchestrator/api.py +++ b/agent/orchestrator/api.py @@ -24,6 +24,7 @@ class ChatCompletionRequest(BaseModel): model_config = ConfigDict(extra="allow") model: str messages: list[ChatMessage] + user: str | None = None @app.get("/v1/models") @@ -36,9 +37,15 @@ def list_models(): @app.post("/v1/chat/completions") def chat_completions(req: ChatCompletionRequest): + # Open WebUI sends user info via custom headers when ENABLE_FORWARD_USER_INFO_HEADERS=true + user_name = request.headers.get("x-openwebui-user-name") + user_email = request.headers.get("x-openwebui-user-email") + # prefer name (friendlier), fall back to email, fall back to None + user = user_name or user_email try: response_text = handle_turn( messages=[Message(role=m.role, content=m.content) for m in req.messages], + user=user, ) except Exception as e: raise HTTPException(status_code=500, detail=str(e)) diff --git a/agent/orchestrator/context.py b/agent/orchestrator/context.py index f8679ff..e9c1975 100644 --- a/agent/orchestrator/context.py +++ b/agent/orchestrator/context.py @@ -31,12 +31,17 @@ def _today_diary_entries() -> list[str]: conn.close() -def build_turn_context() -> str: - diary = _today_diary_entries() - diary_section = ( - "## Today's diary so far\n\n" + "\n".join(diary) - if diary - else "## Today's diary so far\n\n(no entries yet today)" +def build_turn_context(user: str | None = None) -> str: + diary_entries = _today_diary_entries() + diary = ( + "\n".join(diary_entries) + if diary_entries + else "(no entries yet today)" ) now = datetime.now(timezone.utc).astimezone().isoformat(timespec="seconds") - return f"## Current time\n\n{now}\n\n{diary_section}" + + time_section = f"## Current time\n{now}\n\n" + user_section = f"## User\n{user}\n\n" if user else "" + diary_section = f"## Today's diary so far\n{diary}" + + return f"{time_section}{user_section}{diary_section}" diff --git a/agent/orchestrator/loop.py b/agent/orchestrator/loop.py index ed2c0a8..07e81e8 100644 --- a/agent/orchestrator/loop.py +++ b/agent/orchestrator/loop.py @@ -9,10 +9,34 @@ from .context import build_turn_context from .models import Message, ModelRequest, call_model -def handle_turn(messages: list[Message]) -> str: +def handle_turn(messages: list[Message], user: str | None = None) -> str: + decorated = _decorate_latest_user(messages, user) request = ModelRequest( messages=messages, turn_context=build_turn_context(), ) response = call_model(request) return response.content + +def _decorate_latest_user(messages: list[Message], user: str | None) -> list[Message]: + """Prepend [timestamp] [user: name] to the latest user message only. + + Older user messages keep their original form, they were already decorated + at the time they were sent, and Open WebUI is feeding us back the conversation + history including those decorations. + """ + if not messages: + return messages + # find the latest user message; decorate it + decorated = list(messages) + for i in range(len(decorated) - 1, -1, -1): + if decorated[i].role == "user": + now = datetime.now(timezone.utc).astimezone().isoformat(timespec="seconds") + name = f"[user: {user}] " if user else "" + prefix = f"[{now}] {name}" + decorated[i] = Message( + role="user", + content=prefix + decorated[i].content, + ) + break + return decorated -- cgit v1.2.3