diff --git a/Claude outputs/main.py b/Claude outputs/main.py index a39f77f..614b62b 100644 --- a/Claude outputs/main.py +++ b/Claude outputs/main.py @@ -409,6 +409,25 @@ def _as_calendar_local(dt: datetime) -> datetime: return dt +_WEEKDAYS_DE = ["Montag", "Dienstag", "Mittwoch", "Donnerstag", "Freitag", "Samstag", "Sonntag"] +_MONTHS_DE = [ + "Januar", "Februar", "Maerz", "April", "Mai", "Juni", + "Juli", "August", "September", "Oktober", "November", "Dezember", +] + + +def _current_datetime_context(now: datetime = None) -> str: + """Chat has no other grounding for 'heute'/'morgen'/'naechste Woche' - + without this, Claude only knows dates the user states explicitly.""" + now = now or datetime.now(CALENDAR_TIMEZONE) + weekday = _WEEKDAYS_DE[now.weekday()] + month = _MONTHS_DE[now.month - 1] + return ( + f"Aktuelles Datum und Uhrzeit: {weekday}, {now.day}. {month} {now.year}, " + f"{now.strftime('%H:%M')} Uhr ({now.strftime('%d.%m.%Y')})." + ) + + def _create_event_sync(summary: str, start: str, end: str, description: str = "", calendar: str = DEFAULT_CALENDAR) -> dict: cal = _caldav_calendar(calendar) cal.save_event( @@ -1026,7 +1045,7 @@ async def run_chat_completion(claude_messages: list, conversation_id: int): memory_context = await build_memory_context(latest_user_message, conversation_id) system_prompt = ( - f"{CLAUDE_SYSTEM_PROMPT}\n\n{CALENDAR_ASSISTANT_INSTRUCTIONS}\n\n" + f"{CLAUDE_SYSTEM_PROMPT}\n\n{_current_datetime_context()}\n\n{CALENDAR_ASSISTANT_INSTRUCTIONS}\n\n" f"{MEMORY_ASSISTANT_INSTRUCTIONS}\n\n{ORDER_ASSISTANT_INSTRUCTIONS}" ) if memory_context: diff --git a/Claude outputs/tests/test_chat_tools.py b/Claude outputs/tests/test_chat_tools.py index 13f5699..e344117 100644 --- a/Claude outputs/tests/test_chat_tools.py +++ b/Claude outputs/tests/test_chat_tools.py @@ -1,5 +1,6 @@ import os import sys +from datetime import datetime from unittest.mock import AsyncMock, MagicMock, patch sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..")) @@ -143,3 +144,32 @@ async def test_run_chat_completion_lists_recent_emails(): assert text == "Du hast 5 neue Mails." assert output_tokens == 6 + 8 assert total_tokens == 15 + 6 + 20 + 8 + + +def test_current_datetime_context_formats_german_weekday_and_month(): + fixed = datetime(2026, 9, 13, 21, 15, tzinfo=main.CALENDAR_TIMEZONE) + + context = main._current_datetime_context(fixed) + + assert context == ( + "Aktuelles Datum und Uhrzeit: Sonntag, 13. September 2026, 21:15 Uhr (13.09.2026)." + ) + + +@pytest.mark.asyncio +async def test_run_chat_completion_includes_current_datetime_in_system_prompt(): + completion = MagicMock() + completion.stop_reason = "end_turn" + completion.content = [_text_block("Hallo!")] + completion.usage = _usage(10, 5) + + main.claude_client = MagicMock() + main.claude_client.messages.create.return_value = completion + + with patch.object(main, "build_memory_context", new=AsyncMock(return_value="")), patch.object( + main, "_current_datetime_context", return_value="Aktuelles Datum und Uhrzeit: TESTMARKER" + ): + await main.run_chat_completion([{"role": "user", "content": "Hi"}], conversation_id=1) + + _, kwargs = main.claude_client.messages.create.call_args + assert "TESTMARKER" in kwargs["system"]