fix: Coordinator split, Gemini chat context, review findings fixes

- Extract HistoryManager (history.py) and MetricsManager (metrics.py) from coordinator
- Fix Gemini chat: use client.chats.create(history=...) instead of sequential send_message
- Fix float("inf") in metrics breaking json.dump persistence
- Fix _get_current_state checking wrong error key ("error" vs "error_message")
- Fix API key re-entry requirement when endpoint/provider changes in options flow
- Make CONF_API_KEY optional in options schema (stored key used as fallback)
- Add DNS rebinding protection via socket.getaddrinfo in validate_endpoint
- Remove mass assignment vulnerability in config_flow._create_entry
- Add description_placeholders to all error re-show paths
- Fix history migration overwriting existing JSON data
- Return list copy from get_limited_history to prevent reference leaks
- Add history_info to _get_safe_initial_state for data shape consistency
- Add defensive None check in _get_sanitized_last_response
- Move dt_util import to module level in config_flow
- Remove dead fallback branches in coordinator.last_response property
- Fix sensor min_latency display after float("inf") removal
- Fix history directory permissions from 0o777 to 0o755
- Deduplicate schema definitions via _build_provider_schema()
- Use centralized build_auth_headers from providers.py
This commit is contained in:
SMKRV
2026-03-12 01:50:17 +03:00
parent 63c5c7c51e
commit c54bfcff3b
7 changed files with 1053 additions and 1200 deletions
+22 -9
View File
@@ -429,7 +429,6 @@ class APIClient:
def generate_content():
# For single message without history, use generate_content
if len(contents) <= 1:
# If we have no content yet, create a simple prompt
if not contents:
prompt = "I need your assistance."
else:
@@ -441,16 +440,30 @@ class APIClient:
config=config
)
else:
# For multi-turn conversations, use chat
chat = client.chats.create(model=model, config=config)
# For multi-turn conversations, pass history to chat
# and only send the last user message
last_user_msg = None
history = []
# Send all messages in sequence
for content in contents:
if content["role"] == "user":
response = chat.send_message(content["parts"][0]["text"])
# We don't send assistant messages as they're already part of the history
# Find the last user message — that's the new query
for i in range(len(contents) - 1, -1, -1):
if contents[i]["role"] == "user":
last_user_msg = contents[i]["parts"][0]["text"]
history = contents[:i]
break
return response
if last_user_msg is None:
# No user messages at all — shouldn't happen, but handle gracefully
return client.models.generate_content(
model=model,
contents="I need your assistance.",
config=config
)
chat = client.chats.create(
model=model, config=config, history=history
)
return chat.send_message(last_user_msg)
response = await asyncio.to_thread(generate_content)