mirror of
https://github.com/smkrv/ha-text-ai.git
synced 2026-07-21 22:54:00 +08:00
Security: - Add SSRF protection via HTTPS-only endpoint validation with private IP blocking - Mask API keys in all log output via safe_log_data() - Sanitize error responses to prevent internal detail leakage - Remove API key pre-population in config flow forms - Harden service schemas with input length limits and type coercion Bug fixes: - Fix temperature=0 rejected due to Python falsy value bug (0 or default) - Fix fire-and-forget race condition in coordinator init (5 async_create_task → awaited async_initialize) - Fix rate limit state not resetting after successful API calls - Fix ConnectionError incorrectly setting is_rate_limited=True - Fix _rotate_history calling async method via sync executor - Fix shutil.move blocking event loop in history migration - Fix async_shutdown removing wrong key from hass.data - Replace os.rename with shutil.move for cross-device safety Improvements: - Add asyncio.Lock for request serialization - Replace async_timeout with stdlib asyncio.timeout (Python 3.12+) - Use SupportsResponse.OPTIONAL for ask_question and get_history services - Use Platform.SENSOR enum instead of string literal - Add strings.json for HA translation framework - Update DEFAULT_ANTHROPIC_MODEL to claude-sonnet-4-6 - Retry only transient errors (429, timeout) in API client Cleanup: - Remove dead code: unused schemas, imports, sync_write_history, check_memory, check_connection - Remove icon copying code from async_setup - Remove unused dependencies from manifest (anthropic, openai, certifi, async-timeout) - Remove empty manifest arrays (bluetooth, mqtt, ssdp, usb, zeroconf) - Fix duplicate JSON keys in 5 translation files - Fix Serbian translation: "Прекључено" → "Искључено" for disconnected state Bump version to 2.4.0
310 lines
11 KiB
JSON
310 lines
11 KiB
JSON
{
|
|
"config": {
|
|
"step": {
|
|
"provider": {
|
|
"title": "Provider Settings",
|
|
"description": "Provide connection details for your chosen AI provider.",
|
|
"data": {
|
|
"name": "Instance name (e.g., 'GPT Assistant', 'Claude Helper')",
|
|
"api_key": "API key for authentication",
|
|
"model": "AI model to use",
|
|
"api_endpoint": "Custom API endpoint URL (optional)",
|
|
"temperature": "Response creativity (0-2, lower = more focused)",
|
|
"max_tokens": "Maximum response length (1-100000 tokens)",
|
|
"request_interval": "Minimum time between requests (0.1-60 seconds)",
|
|
"api_timeout": "API request timeout in seconds (5-600)",
|
|
"context_messages": "Number of context messages to retain (1-20)",
|
|
"max_history_size": "Maximum conversation history size (1-100)"
|
|
}
|
|
},
|
|
"user": {
|
|
"title": "Configure HA Text AI Instance",
|
|
"description": "Set up a new AI assistant instance with your selected provider.",
|
|
"data": {
|
|
"name": "Instance name (e.g., 'GPT Assistant', 'Claude Helper')",
|
|
"api_key": "API key for authentication",
|
|
"model": "AI model to use",
|
|
"temperature": "Response creativity (0-2, lower = more focused)",
|
|
"max_tokens": "Maximum response length (1-100000 tokens)",
|
|
"api_endpoint": "Custom API endpoint URL (optional)",
|
|
"api_provider": "API Provider",
|
|
"request_interval": "Minimum time between requests (0.1-60 seconds)",
|
|
"api_timeout": "API request timeout in seconds (5-600)",
|
|
"context_messages": "Number of context messages to retain (1-20)",
|
|
"max_history_size": "Maximum conversation history size (1-100)"
|
|
}
|
|
}
|
|
},
|
|
"error": {
|
|
"history_storage_error": "Failed to initialize history storage. Check permissions.",
|
|
"history_rotation_error": "Error during history file rotation.",
|
|
"history_file_access_error": "Cannot access history storage directory.",
|
|
"name_exists": "An instance with this name already exists",
|
|
"invalid_name": "Invalid instance name",
|
|
"invalid_auth": "Authentication failed - check your API key",
|
|
"invalid_api_key": "Invalid API key - please verify your credentials",
|
|
"cannot_connect": "Failed to connect to API service",
|
|
"invalid_model": "Selected model is not available",
|
|
"rate_limit": "Rate limit exceeded",
|
|
"context_length": "Context length exceeded",
|
|
"rate_limit_exceeded": "API rate limit exceeded",
|
|
"maintenance": "Service is under maintenance",
|
|
"invalid_response": "Invalid API response received",
|
|
"api_error": "API service error occurred",
|
|
"timeout": "Request timed out",
|
|
"invalid_instance": "Invalid instance specified",
|
|
"unknown": "Unexpected error occurred",
|
|
"empty": "Name cannot be empty",
|
|
"invalid_characters": "Name can only contain letters, numbers, spaces, underscores and hyphens",
|
|
"name_too_long": "Name must be 50 characters or less"
|
|
},
|
|
"abort": {
|
|
"already_configured": "Instance already configured"
|
|
}
|
|
},
|
|
"options": {
|
|
"step": {
|
|
"init": {
|
|
"title": "Select Provider",
|
|
"description": "Choose the AI provider for this instance. The integration will reload after saving changes.",
|
|
"data": {
|
|
"api_provider": "API Provider"
|
|
}
|
|
},
|
|
"settings": {
|
|
"title": "Connection & Model Settings",
|
|
"description": "Configure API credentials and model parameters. Changes will take effect after the integration reloads.",
|
|
"data": {
|
|
"api_key": "API Key",
|
|
"api_endpoint": "API Endpoint URL",
|
|
"model": "AI model",
|
|
"temperature": "Response creativity (0-2)",
|
|
"max_tokens": "Maximum response length (1-100000)",
|
|
"request_interval": "Minimum request interval (0.1-60 seconds)",
|
|
"api_timeout": "API request timeout in seconds (5-600)",
|
|
"context_messages": "Number of previous messages to include in context (1-20)",
|
|
"max_history_size": "Maximum conversation history size (1-100)"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"selector": {
|
|
"api_provider": {
|
|
"options": {
|
|
"openai": "OpenAI (compatible)",
|
|
"anthropic": "Anthropic (compatible)",
|
|
"deepseek": "DeepSeek",
|
|
"gemini": "Google Gemini"
|
|
}
|
|
}
|
|
},
|
|
"services": {
|
|
"ask_question": {
|
|
"name": "Ask Question (HA Text AI)",
|
|
"description": "Send a question to the AI model and receive a detailed response. This service now returns response data directly, eliminating the need for separate text sensors and the 255-character limitation. The response will also be stored in the conversation history.",
|
|
"fields": {
|
|
"instance": {
|
|
"name": "Instance",
|
|
"description": "Name of the HA Text AI instance to use"
|
|
},
|
|
"question": {
|
|
"name": "Question",
|
|
"description": "Your question or prompt for the AI assistant"
|
|
},
|
|
"context_messages": {
|
|
"name": "Context Messages",
|
|
"description": "Number of previous messages to include in context (1-20)"
|
|
},
|
|
"system_prompt": {
|
|
"name": "System Prompt",
|
|
"description": "Optional system prompt to set context for this specific question"
|
|
},
|
|
"model": {
|
|
"name": "Model",
|
|
"description": "Select AI model to use (optional, overrides default setting)"
|
|
},
|
|
"temperature": {
|
|
"name": "Temperature",
|
|
"description": "Controls response creativity (0.0-2.0)"
|
|
},
|
|
"max_tokens": {
|
|
"name": "Max Tokens",
|
|
"description": "Maximum length of the response (1-100000 tokens)"
|
|
},
|
|
"structured_output": {
|
|
"name": "Structured Output",
|
|
"description": "Enable JSON structured output mode. When enabled, the AI will respond with valid JSON matching the provided schema."
|
|
},
|
|
"json_schema": {
|
|
"name": "JSON Schema",
|
|
"description": "JSON Schema defining the structure of the expected response. Required when structured_output is enabled."
|
|
}
|
|
}
|
|
},
|
|
"clear_history": {
|
|
"name": "Clear History",
|
|
"description": "Delete all stored questions and responses from the conversation history",
|
|
"fields": {
|
|
"instance": {
|
|
"name": "Instance",
|
|
"description": "Name of the HA Text AI instance to clear history for"
|
|
}
|
|
}
|
|
},
|
|
"get_history": {
|
|
"name": "Get History",
|
|
"description": "Retrieve conversation history with optional filtering and sorting",
|
|
"fields": {
|
|
"instance": {
|
|
"name": "Instance",
|
|
"description": "Name of the HA Text AI instance to get history from"
|
|
},
|
|
"limit": {
|
|
"name": "Limit",
|
|
"description": "Number of conversations to return (1-100)"
|
|
},
|
|
"filter_model": {
|
|
"name": "Filter Model",
|
|
"description": "Filter conversations by specific AI model"
|
|
},
|
|
"start_date": {
|
|
"name": "Start Date",
|
|
"description": "Filter conversations starting from this date/time"
|
|
},
|
|
"include_metadata": {
|
|
"name": "Include Metadata",
|
|
"description": "Include additional information like tokens used, response time, etc."
|
|
},
|
|
"sort_order": {
|
|
"name": "Sort Order",
|
|
"description": "Sort order for results (newest or oldest first)"
|
|
}
|
|
}
|
|
},
|
|
"set_system_prompt": {
|
|
"name": "Set System Prompt",
|
|
"description": "Set default system behavior instructions for all future conversations",
|
|
"fields": {
|
|
"instance": {
|
|
"name": "Instance",
|
|
"description": "Name of the HA Text AI instance to set system prompt for"
|
|
},
|
|
"prompt": {
|
|
"name": "System Prompt",
|
|
"description": "Instructions that define how the AI should behave and respond"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"entity": {
|
|
"sensor": {
|
|
"ha_text_ai": {
|
|
"name": "{name}",
|
|
"state": {
|
|
"ready": "Ready",
|
|
"processing": "Processing",
|
|
"error": "Error",
|
|
"disconnected": "Disconnected",
|
|
"rate_limited": "Rate Limited",
|
|
"maintenance": "Maintenance",
|
|
"initializing": "Initializing",
|
|
"retrying": "Retrying",
|
|
"queued": "Queued"
|
|
},
|
|
"state_attributes": {
|
|
"question": {
|
|
"name": "Last Question"
|
|
},
|
|
"response": {
|
|
"name": "Last Response"
|
|
},
|
|
"model": {
|
|
"name": "Current Model"
|
|
},
|
|
"temperature": {
|
|
"name": "Temperature"
|
|
},
|
|
"max_tokens": {
|
|
"name": "Max Tokens"
|
|
},
|
|
"system_prompt": {
|
|
"name": "System Prompt"
|
|
},
|
|
"response_time": {
|
|
"name": "Last Response Time"
|
|
},
|
|
"total_responses": {
|
|
"name": "Total Responses"
|
|
},
|
|
"error_count": {
|
|
"name": "Error Count"
|
|
},
|
|
"last_error": {
|
|
"name": "Last Error"
|
|
},
|
|
"api_status": {
|
|
"name": "API Status"
|
|
},
|
|
"tokens_used": {
|
|
"name": "Total Tokens Used"
|
|
},
|
|
"average_response_time": {
|
|
"name": "Average Response Time"
|
|
},
|
|
"last_request_time": {
|
|
"name": "Last Request Time"
|
|
},
|
|
"is_processing": {
|
|
"name": "Processing Status"
|
|
},
|
|
"is_rate_limited": {
|
|
"name": "Rate Limited Status"
|
|
},
|
|
"is_maintenance": {
|
|
"name": "Maintenance Status"
|
|
},
|
|
"api_version": {
|
|
"name": "API Version"
|
|
},
|
|
"endpoint_status": {
|
|
"name": "Endpoint Status"
|
|
},
|
|
"performance_metrics": {
|
|
"name": "Performance Metrics"
|
|
},
|
|
"history_size": {
|
|
"name": "History Size"
|
|
},
|
|
"uptime": {
|
|
"name": "Uptime"
|
|
},
|
|
"total_tokens": {
|
|
"name": "Total Tokens"
|
|
},
|
|
"prompt_tokens": {
|
|
"name": "Prompt Tokens"
|
|
},
|
|
"completion_tokens": {
|
|
"name": "Completion Tokens"
|
|
},
|
|
"successful_requests": {
|
|
"name": "Successful Requests"
|
|
},
|
|
"failed_requests": {
|
|
"name": "Failed Requests"
|
|
},
|
|
"average_latency": {
|
|
"name": "Average Latency"
|
|
},
|
|
"max_latency": {
|
|
"name": "Maximum Latency"
|
|
},
|
|
"min_latency": {
|
|
"name": "Minimum Latency"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|