mirror of
https://github.com/smkrv/ha-text-ai.git
synced 2026-07-27 01:24:05 +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
309 lines
15 KiB
JSON
309 lines
15 KiB
JSON
{
|
||
"config": {
|
||
"step": {
|
||
"provider": {
|
||
"title": "Подешавања провајдера",
|
||
"description": "Обезбедите детаље о вези за изабраног AI провајдера.",
|
||
"data": {
|
||
"name": "Име инстанце (нпр. 'GPT Асистент', 'Claude Помоћник')",
|
||
"api_key": "API кључ за аутентификацију",
|
||
"model": "AI модел који ће се користити",
|
||
"api_endpoint": "Прилагођени URL API крајње тачке (опционо)",
|
||
"temperature": "Креативност одговора (0-2, нижа = фокусираније)",
|
||
"max_tokens": "Максимална дужина одговора (1-100000 токена)",
|
||
"request_interval": "Минимално време између захтева (0.1-60 секунди)",
|
||
"api_timeout": "Временско ограничење API захтева у секундама (5-600)",
|
||
"context_messages": "Број контекстуалних порука које треба задржати (1-20)",
|
||
"max_history_size": "Максимална величина историје разговора (1-100)"
|
||
}
|
||
},
|
||
"user": {
|
||
"title": "Конфигуришите HA Text AI инстанцу",
|
||
"description": "Подесите нову AI асистент инстанцу са изабраним провајдером.",
|
||
"data": {
|
||
"name": "Име инстанце (нпр. 'GPT Асистент', 'Claude Помоћник')",
|
||
"api_key": "API кључ за аутентификацију",
|
||
"model": "AI модел који ће се користити",
|
||
"temperature": "Креативност одговора (0-2, нижа = фокусираније)",
|
||
"max_tokens": "Максимална дужина одговора (1-100000 токена)",
|
||
"api_endpoint": "Прилагођени URL API крајње тачке (опционо)",
|
||
"api_provider": "API провајдер",
|
||
"request_interval": "Минимално време између захтева (0.1-60 секунди)",
|
||
"api_timeout": "Временско ограничење API захтева у секундама (5-600)",
|
||
"context_messages": "Број контекстуалних порука које треба задржати (1-20)",
|
||
"max_history_size": "Максимална величина историје разговора (1-100)"
|
||
}
|
||
}
|
||
},
|
||
"error": {
|
||
"history_storage_error": "Неуспела инициализација складишта историје. Проверите дозволе.",
|
||
"history_rotation_error": "Грешка током ротације историјских датотека.",
|
||
"history_file_access_error": "Немогуће приступити директоријуму складишта историје.",
|
||
"name_exists": "Инстанца са овим именом већ постоји",
|
||
"invalid_name": "Неважеће име инстанце",
|
||
"invalid_auth": "Аутентификација није успела - проверите ваш API кључ",
|
||
"invalid_api_key": "Неважећи API кључ - молимо проверите ваше акредитиве",
|
||
"cannot_connect": "Неуспело повезивање са API сервисом",
|
||
"invalid_model": "Изабрани модел није доступан",
|
||
"rate_limit": "Пређена граница захтева",
|
||
"context_length": "Дужина контекста пређена",
|
||
"rate_limit_exceeded": "Пређена граница API захтева",
|
||
"maintenance": "Сервис је у одржавању",
|
||
"invalid_response": "Примљен неважећи API одговор",
|
||
"api_error": "Дошло је до грешке у API сервису",
|
||
"timeout": "Време захтева је истекло",
|
||
"invalid_instance": "Неважећа инстанца је назначена",
|
||
"unknown": "Дошло је до неочекиване грешке",
|
||
"empty": "Име не може бити празно",
|
||
"invalid_characters": "Име може садржавати само слова, цифре, размаке, подцрта и цртице",
|
||
"name_too_long": "Име мора бити 50 знакова или мање"
|
||
},
|
||
"abort": {
|
||
"already_configured": "Инстанца је већ конфигурисана"
|
||
}
|
||
},
|
||
"options": {
|
||
"step": {
|
||
"init": {
|
||
"title": "Изаберите провајдера",
|
||
"description": "Изаберите AI провајдера за ову инстанцу. Интеграција ће се поново учитати након чувања измена.",
|
||
"data": {
|
||
"api_provider": "API провајдер"
|
||
}
|
||
},
|
||
"settings": {
|
||
"title": "Подешавања везе и модела",
|
||
"description": "Конфигуришите API акредитиве и параметре модела. Промене ће ступити на снагу након поновног учитавања интеграције.",
|
||
"data": {
|
||
"api_key": "API кључ",
|
||
"api_endpoint": "URL API крајње тачке",
|
||
"model": "AI модел",
|
||
"temperature": "Креативност одговора (0-2)",
|
||
"max_tokens": "Максимална дужина одговора (1-100000)",
|
||
"request_interval": "Минимално време између захтева (0.1-60 секунди)",
|
||
"api_timeout": "Временско ограничење API захтева у секундама (5-600)",
|
||
"context_messages": "Број претходних порука које треба укључити у контекст (1-20)",
|
||
"max_history_size": "Максимална величина историје разговора (1-100)"
|
||
}
|
||
}
|
||
}
|
||
},
|
||
"selector": {
|
||
"api_provider": {
|
||
"options": {
|
||
"openai": "OpenAI (компатибилан)",
|
||
"anthropic": "Anthropic (компатибилан)",
|
||
"deepseek": "DeepSeek",
|
||
"gemini": "Google Gemini"
|
||
}
|
||
}
|
||
},
|
||
"services": {
|
||
"ask_question": {
|
||
"name": "Поставите питање (HA Text AI)",
|
||
"description": "Пошаљите питање AI моделу и добијте детаљан одговор. Овај сервис сада враћа податке одговора директно, елиминишући потребу за засебним текстуалним сензорима и ограничење од 255 карактера. Одговор ће такође бити сачуван у историји разговора.",
|
||
"fields": {
|
||
"instance": {
|
||
"name": "Инстанца",
|
||
"description": "Име HA Text AI инстанце коју ћете користити"
|
||
},
|
||
"question": {
|
||
"name": "Питање",
|
||
"description": "Ваше питање или упит за AI асистента"
|
||
},
|
||
"context_messages": {
|
||
"name": "Контекстуалне поруке",
|
||
"description": "Број претходних порука које треба укључити у контекст (1-20)"
|
||
},
|
||
"system_prompt": {
|
||
"name": "Системски упит",
|
||
"description": "Опционални системски упит за постављање контекста за ово конкретно питање"
|
||
},
|
||
"model": {
|
||
"name": "Модел",
|
||
"description": "Изаберите AI модел који ћете користити (опционо, надмашује подразумевану поставку)"
|
||
},
|
||
"temperature": {
|
||
"name": "Температура",
|
||
"description": "Контролише креативност одговора (0.0-2.0)"
|
||
},
|
||
"max_tokens": {
|
||
"name": "Максимални токени",
|
||
"description": "Максимална дужина одговора (1-100000 токена)"
|
||
},
|
||
"structured_output": {
|
||
"name": "Структурисани излаз",
|
||
"description": "Омогући JSON структурисани излаз. Када је омогућено, AI ће одговарати валидним JSON-ом који одговара датој шеми."
|
||
},
|
||
"json_schema": {
|
||
"name": "JSON шема",
|
||
"description": "JSON шема која дефинише структуру очекиваног одговора. Обавезна када је structured_output омогућен."
|
||
}
|
||
}
|
||
},
|
||
"clear_history": {
|
||
"name": "Обриши историју",
|
||
"description": "Избришите све сачуване питања и одговоре из историје разговора",
|
||
"fields": {
|
||
"instance": {
|
||
"name": "Инстанца",
|
||
"description": "Име HA Text AI инстанце за коју желите да обришете историју"
|
||
}
|
||
}
|
||
},
|
||
"get_history": {
|
||
"name": "Добијте историју",
|
||
"description": "Повратите историју разговора уз опционално филтрирање и сортирање",
|
||
"fields": {
|
||
"instance": {
|
||
"name": "Инстанца",
|
||
"description": "Име HA Text AI инстанце из које желите да добијете историју"
|
||
},
|
||
"limit": {
|
||
"name": "Лимит",
|
||
"description": "Број разговора које треба вратити (1-100)"
|
||
},
|
||
"filter_model": {
|
||
"name": "Филтер модел",
|
||
"description": "Филтрирајте разговоре по одређеном AI моделу"
|
||
},
|
||
"start_date": {
|
||
"name": "Датум почетка",
|
||
"description": "Филтрирајте разговоре који почињу од овог датума/времена"
|
||
},
|
||
"include_metadata": {
|
||
"name": "Укључи метаподатке",
|
||
"description": "Укључите додатне информације као што су коришћени токени, време одговора итд."
|
||
},
|
||
"sort_order": {
|
||
"name": "Редослед сортирања",
|
||
"description": "Редослед сортирања за резултате (најновији или најстарији први)"
|
||
}
|
||
}
|
||
},
|
||
"set_system_prompt": {
|
||
"name": "Поставите системски упит",
|
||
"description": "Поставите подразумеване инструкције за системско понашање за све будуће разговоре",
|
||
"fields": {
|
||
"instance": {
|
||
"name": "Инстанца",
|
||
"description": "Име HA Text AI инстанце за коју желите да поставите системски упит"
|
||
},
|
||
"prompt": {
|
||
"name": "Системски упит",
|
||
"description": "Инструкције које дефинишу како AI треба да се понаша и одговара"
|
||
}
|
||
}
|
||
}
|
||
},
|
||
"entity": {
|
||
"sensor": {
|
||
"ha_text_ai": {
|
||
"name": "{name}",
|
||
"state": {
|
||
"ready": "Спремно",
|
||
"processing": "Обрада",
|
||
"error": "Грешка",
|
||
"disconnected": "Искључено",
|
||
"rate_limited": "Ограничење захтева",
|
||
"maintenance": "Одржавање",
|
||
"initializing": "Инициализује се",
|
||
"retrying": "Покушава поново",
|
||
"queued": "У реду"
|
||
},
|
||
"state_attributes": {
|
||
"question": {
|
||
"name": "Последње питање"
|
||
},
|
||
"response": {
|
||
"name": "Последњи одговор"
|
||
},
|
||
"model": {
|
||
"name": "Тренутни модел"
|
||
},
|
||
"temperature": {
|
||
"name": "Температура"
|
||
},
|
||
"max_tokens": {
|
||
"name": "Максимални токени"
|
||
},
|
||
"system_prompt": {
|
||
"name": "Системски упит"
|
||
},
|
||
"response_time": {
|
||
"name": "Време последњег одговора"
|
||
},
|
||
"total_responses": {
|
||
"name": "Укупно одговора"
|
||
},
|
||
"error_count": {
|
||
"name": "Број грешака"
|
||
},
|
||
"last_error": {
|
||
"name": "Последња грешка"
|
||
},
|
||
"api_status": {
|
||
"name": "Статус API"
|
||
},
|
||
"tokens_used": {
|
||
"name": "Укупно коришћени токени"
|
||
},
|
||
"average_response_time": {
|
||
"name": "Просечно време одговора"
|
||
},
|
||
"last_request_time": {
|
||
"name": "Време последњег захтева"
|
||
},
|
||
"is_processing": {
|
||
"name": "Статус обраде"
|
||
},
|
||
"is_rate_limited": {
|
||
"name": "Статус ограничења захтева"
|
||
},
|
||
"is_maintenance": {
|
||
"name": "Статус одржавања"
|
||
},
|
||
"api_version": {
|
||
"name": "Верзија API"
|
||
},
|
||
"endpoint_status": {
|
||
"name": "Статус крајње тачке"
|
||
},
|
||
"performance_metrics": {
|
||
"name": "Перформансне метрике"
|
||
},
|
||
"history_size": {
|
||
"name": "Величина историје"
|
||
},
|
||
"uptime": {
|
||
"name": "Уптиме"
|
||
},
|
||
"total_tokens": {
|
||
"name": "Укупно токена"
|
||
},
|
||
"prompt_tokens": {
|
||
"name": "Токени упита"
|
||
},
|
||
"completion_tokens": {
|
||
"name": "Токени завршетка"
|
||
},
|
||
"successful_requests": {
|
||
"name": "Успешни захтеви"
|
||
},
|
||
"failed_requests": {
|
||
"name": "Неуспешни захтеви"
|
||
},
|
||
"average_latency": {
|
||
"name": "Просечна латенција"
|
||
},
|
||
"max_latency": {
|
||
"name": "Максимална латенција"
|
||
},
|
||
"min_latency": {
|
||
"name": "Минимална латенција"
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
} |