Commit Graph
139 Commits
Author SHA1 Message Date
Dushnilin 6dd085b777 feat(ai-doctor): supercharge AI Doctor with multi-fix, log context, history, and 13 quick fix codes
Backend (runtime.uc, agent_api.uc, tachyon CLI):
- Enrich AI Doctor LLM context with Watchdog state (OOM, streaks, active repairs) and last 15 critical log lines
- Support multi-fix parsing (quick_fixes array) and comma-separated FIX tags
- Add persistent history saving to /tmp/ai_doctor_last.json and ai_doctor_last endpoint
- Expand quick fix codes from 9 to 13 (added clear_dns_cache, update_subscriptions, reset_firewall, restart_network)
- Implement apply_quick_fix CLI command and REST API endpoint

Frontend (fe-app-tachyon, LuCI main.js):
- Add AI Doctor action button in Diagnostics tab
- Add shell methods aiDoctor, aiDoctorLast, applyQuickFix
- Render AI Doctor modal with Multi-Fix buttons and 'Fix All' option
- Integrate toast notifications and state updates
2026-08-11 16:06:19 +03:00
Dushnilin 3d48a22e3c feat(ai-doctor): add model selection per provider
Backend (runtime.uc):
- query_llm() accepts model_override (5th param), falls back to provider default
- ai_doctor() reads ai_doctor_model from UCI and passes to query_llm

Frontend (renderAdvancedSettings.ts):
- aiDoctorModel state field (type / init / load / save)
- Model dropdown per provider with sensible defaults:
  openai: gpt-4o-mini(default)/gpt-4o/gpt-4.1-mini/gpt-4.1/o4-mini
  anthropic: claude-3-5-haiku(default)/claude-3-5-sonnet/claude-3-7-sonnet
  deepseek: deepseek-chat(default)/deepseek-reasoner
  custom: free-text input
- Switching provider resets model to '' (use new provider default)

Legacy LuCI (settings.js):
- ai_doctor_model Value field with placeholder '(provider default)'
2026-08-11 12:37:31 +03:00
Dushnilin 8be248f9fd fix(ui): непрерывная индикация анимации на кнопке обновления без мигания
- При получении 'Another component action is already running' или сетевого
  RPC-сбоя спиннер на нажатой кнопке больше не сбрасывается сразу.
- Добавлено повторное связывание (fallback lookups) с 800ms задержкой, чтобы
  бэкенд успевал прописать запущенный job в state до снятия индикатора.
- При отслеживании запущенного задания теперь учитываются любые фоновые
  акшны для того же компонента.
2026-08-10 21:38:46 +03:00
Dushnilin dd3546f29a fix(updates): предотвратить ложный сброс индикации загрузки при переустановке одинаковых версий
- В waitComponentActionJob добавлен минимальный порог ожидания (10с)
  перед срабатыванием fallback проверки версии Tachyon. При same-release
  обновлениях (одинаковый номер версии, но новый SHA) совпадение версии
  больше не приводит к мгновенному (за 1с) снятию спиннера loading, пока
  бэкенд на самом деле только скачивает и ставит пакет.
- Расширен список транзиентных RPC ошибок (isTransientRpcError) для
  надежного перешивания перезапуска uhttpd/rpcd/ubus во время переустановки.
- Увеличен COMPONENT_ACTION_TRANSIENT_RPC_GRACE_MS до 60с.
2026-08-10 21:30:03 +03:00
Dushnilin 5cbbd0f661 fix(ui): suppress 'Already running' and DNS retry toasts
Lock contention ('Another component action is already running') is an
expected transient state — user clicked a button while a previous action
was still in flight. Showing [error] toast confuses users into thinking
something broke. Filter it from the log watcher notification pipeline.

Also suppress DNS retry debug lines (issue #24 retry logs) from showing
as error toasts.

Added tests for both suppressed patterns.
2026-08-10 21:01:21 +03:00
Dushnilin 31c36118ef refactor(ui): сгруппировать все параметры Settings по вкладкам (cbi-tabgroup)
- Настройки разделены на 6 категорий: DNS, Сеть, Сервисы, Обновления, ИИ и Системные
- Устранена длинная простыня прокрутки — каждая категория открывается во вкладке
2026-08-10 19:30:51 +03:00
Dushnilin c930c15dc3 feat(ai): добавить поддержку Anthropic Claude API в AI Doctor
- В query_llm (runtime.uc) добавлена интеграция с Anthropic Messages API (https://api.anthropic.com/v1/messages) с заголовком x-api-key
- В настройки Settings и Dashboard добавлен выпадающий выбор провайдера 'Anthropic (Claude API)'
- Добавлен русский перевод для опций AI Doctor
2026-08-10 19:16:19 +03:00
Dushnilin 8a71a5a1a4 feat(luci): добавить поле AI Agent REST API Token в стандартную вкладку Settings
- Добавлена опция agent_api_token (AI Agent REST API Bearer Token) в CBI-форму настроек settings.js
- Сохраняет токен через стандартную кнопку Save & Apply в LuCI
2026-08-10 19:13:51 +03:00
Dushnilin e67e8c0984 fix(package): исключить воркеры обновления из зачистки процессов при апгрейде
- kill_matching_command и цикл зачистки fd/1000 прокси в package.uc теперь пропускют процессы ucode (action.uc / updates.uc) и их предков, предотвращая выбивание воркера обновлений по SIGKILL во время prerm
- isTransientRpcError теперь учитывает 'failed to execute' в качестве транзиентной ошибки RPC при перезапуске rpcd / служб во время обновления
2026-08-10 18:57:19 +03:00
Dushnilin 7def6e556f i18n: fix Russian-source translation keys in AmneziaWG .conf import
section.js had 10 _() calls with Russian strings as keys instead of English.
This is a i18n antipattern: source keys must be language-neutral (English).

Changes:
- section.js: replace 10 Russian msgids with English equivalents
  - 'Загрузить конфиг .conf' -> 'Load .conf config'
  - 'Импортировать настройки AmneziaWG из файла .conf' -> 'Import AmneziaWG settings from .conf file'
  - 'Загрузить .conf' -> 'Load .conf'
  - 'Ошибка' (3x) -> 'Error' (reuses existing key)
  - 'Выберите файл с расширением .conf' -> 'Select a file with .conf extension'
  - 'Не удалось разобрать файл:' -> 'Failed to parse file:'
  - 'Загружено!' -> 'Loaded!'
  - 'Готово' -> 'Done'
  - 'Конфиг AmneziaWG успешно загружен!' -> 'AmneziaWG config loaded successfully!'
  - 'Ошибка чтения' -> 'Read error'

- tachyon.ru.po: add RU translations for 9 new English keys
- calls.json / tachyon.pot / tachyon.po: regenerated via locales:actualize

Result: 1108/1108 translated (no orphaned Russian-source entries)
2026-08-10 14:00:35 +03:00
Dushnilin 90980917e4 feat(telegram): выбор секции прокси для Telegram-бота + фикс краша при null cb.from
- get_proxy_args() теперь поддерживает опцию UCI bot_proxy_section:
  если sing-box запущен и секция указана, переключает GLOBAL outbound через REST API
- Исправлен краш 'left-hand side expression is null' при обработке
  callback_query без поля from (например channel_post callbacks)
- В LuCI settings.js добавлен ListValue 'bot_proxy_section' с выпадающим
  списком активных секций (паттерн аналогичен download_via_proxy_section)
- Локализация: ru/tachyon.po и templates/tachyon.pot синхронизированы
- Пересборка main.js через npm run build
2026-08-09 22:34:06 +03:00
Dushnilin af2d07b056 fix(updates): установка пересобранных релизов в рамках одного тега
opkg считает пакет уже установленным при равенстве версий, поэтому
пересборка под тем же тегом молча не применялась: задание завершалось
успехом, билд оставался старым. Добавлен --force-reinstall в
pkg_install_files_command (opkg) и в install.sh; apk не тронут, он
всегда пишет переданный файл.

Детект пересборки больше не зависит только от SHA, которого нет в
релизах старше f974e4a0: добавлен отпечаток билда по published_at и
метаданным ipk-ассета, решение вынесено в tachyon_build_differs с
префиксным сравнением SHA разной длины. Отпечаток установленного
билда пишется в state-файл и попадает в extra.

Telegram уведомляет о пересборках: check_notified_updates пропускает
outdated_same_release, дедуп идёт по версии и SHA, текст показывает
короткие SHA вместо пары одинаковых версий.

Кэш проверки обновлений сохраняет current_sha из результата действия
вместо безусловного latest, иначе неудачная установка выглядела как
"актуально".

Фронт пересобран из TS, ручная правка main.js снята. Добавлен
describeSameReleaseBuild с фолбэк-текстом, когда SHA недоступен.
2026-08-09 16:57:10 +03:00
Dushnilin 3d84d96e49 feat(ui): display short commit SHA alongside release version across LuCI UI 2026-08-09 08:50:38 +03:00
Dushnilin d6860d8a15 fix(fe): исправить типизацию fetchHostnames и обновить бандл LuCI 2026-08-08 13:00:17 +03:00
Dushnilin 55e0f9b303 fix: исправить список серверов в URLTest, ACL для rpcd, Telegram-бот
UI (section.js):
- showUrlTestSettingsModal и showPriorityLevelSettingsModal: предзагрузка
  кэша outbound-имён до открытия модала — CBINamedSection.render() не
  вызывает section.load(), из-за чего DynamicList рендерился без данных
- renderStackedJsonSettingsModal: вызов map.load() перед map.render()

LuCI ACL (luci-app-tachyon.json):
- Добавлены пути /tmp/run/tachyon/... наряду с /var/run/tachyon/...
  На OpenWrt /var — симлинк на /tmp; rpcd резолвит симлинки перед
  проверкой ACL, поэтому /var/run/... никогда не давал прав чтения
  и fs.read() возвращал PermissionError

Postinstall (50_luci-tachyon):
- Добавлен перезапуск rpcd после установки пакета, чтобы новые ACL
  вступали в силу без ручного logout/login в LuCI

Telegram-бот (telegram.uc):
- handle_toggle_mac(): блокировка/разблокировка устройств теперь
  через правила firewall (fw4), а не через UCI blocked_macs
- /cb команда: разрешение токенизированных коллбэков для oversized
  inline-клавиатур (лимит Telegram 64 байта на callback_data)
- /qh_start, /qh_end: интерактивная настройка часов тихого режима
- in_quiet_hours() и daily report: исправлен localtime(time())
  вместо clock() — clock() возвращает [сек, мксек], а не tm-структуру
- Уведомления об обновлениях: current_version вместо installed_version
- Описание команды /restart исправлено

Backend (api.uc, state.uc):
- http_probe(): выделена функция с проверкой HTTP-статуса
  (curl выходит 0 даже при 4xx/5xx — теперь проверяем код явно)
- run_speedtest(): учёт curl exit status
- Math.random() заменён на clock()[1] (Math недоступен без import)
- current_year(): убрано +1900 — localtime().year уже полный год
2026-08-07 20:45:06 +03:00
Dushnilin 138a3831b9 fix(tests): restore exact dashboardFilterChoiceRefreshers registration signature for tests 2026-08-07 17:58:24 +03:00
Dushnilin 7c0959a969 fix(ui): dynamic refresh of outbound choices when focusing or loading section cache 2026-08-07 17:34:42 +03:00
Dushnilin ff92e79c5b fix(ui): resolve empty server list in subscription and urltest filter dropdowns 2026-08-07 17:30:50 +03:00
Dushnilin 37569768d8 fix(tracer): fix rpcd ACL permissions for ruleset files and add source URL display for external .lst lists 2026-08-07 13:35:01 +03:00
Dushnilin 1599a7239c fix(tracer): implement resilient 3-way ruleset reading for domain/IP lists in routing tracer 2026-08-07 13:21:49 +03:00
Dushnilin f2a22a6730 fix(tracer): fix fs.readfile call for domain/IP lists and implement sing-box SIGHUP graceful recovery 2026-08-07 13:14:06 +03:00
Dushnilin 769598390d fix(ui): dynamic Sing-box repository globe link based on installed variant (shtorm-7/Leadaxe/SagerNet) 2026-08-06 22:07:38 +03:00
Dushnilin 131d8ea8c5 feat(awg): add j1-j3 and itime support for sing-box-extended v1.13.16-extended-2.6.0 2026-08-06 16:57:34 +03:00
Dushnilin 89ae37ea4b fix(ci): synchronize PO catalogs, fix DNS action UI, state aggregate signature, and uci array parsing 2026-08-06 16:39:53 +03:00
Dushnilin 39b253bd66 fix(diagnostic): use serviceStatus for zapret/zapret2/byedpi outbound checks instead of Clash API latency probe 2026-08-06 15:00:19 +03:00
Dushnilin 7125e1a48e feat: карточки сервисов на дашборде + секция Hosts в правилах + скрытие вкладки Conditions для Hosts
Дашборд:
- Добавлены карточки статуса Zapret, Zapret2, ByeDpi на панель мониторинга
- Показывают статус (работает/остановлен), количество перезапусков, предупреждения
- Баг: API возвращает boolean а не число — исправлено сравнение

Секция Hosts:
- Перенесены опции hosts из глобальных настроек в отдельный тип секции (action=hosts)
- Опции: пользовательские DNS записи, удалённые списки хостов, автообновление, интервал
- Миграция: автоматический перенос глобальных настроек hosts в секцию
- Вкладка «Условия» скрыта для секций типа Hosts (hosts записи применяются глобально)
- Возвращена кнопка «Import Hosts File» с модальным окном загрузки из файла
- Убраны неиспользуемые опции из settings.js (~280 строк)

Локализация:
- Переведены 6 новых строк для превью импорта hosts
2026-08-06 14:16:18 +03:00
Dushnilin ab606ff166 hosts: restyle remote hosts lists widget to native LuCI look
Replaced custom colored rows/badges with standard CBI table layout:
cbi-section-table, cbi-input-checkbox, cbi-input-text,
cbi-button-action, cbi-button-remove. No custom colors or borders.
2026-08-05 12:45:31 +03:00
Dushnilin d38d42b08a hosts: rewrite remote hosts lists widget with per-URL toggle
Completely replaced DynamicList with a custom renderWidget that shows
each URL as a row with: checkbox toggle, URL label, ON/OFF badge, and
delete button. Disabled URLs are stored in hosts_list_disabled UCI list.
Backend filters them out before downloading. URLs stay in settings
when disabled — they just don't get applied.
2026-08-05 12:27:49 +03:00
Dushnilin 969937428f hosts: add per-URL enable/disable toggle for remote hosts lists
- Backend: get_hosts_urls() now reads hosts_list_disabled list and
  filters out disabled URLs before downloading.
- Backend: hosts_list_status() now returns total and disabled counts.
- Frontend: Added hidden hosts_list_disabled DynamicList option.
- Frontend: Overrode renderWidget on hosts_list_urls to prepend a
  toggle switch (ON/OFF) next to each URL. Toggle syncs with
  hosts_list_disabled via uci.set().
2026-08-05 12:24:39 +03:00
Dushnilin 4d4bdb16d0 fix: watchdog rpcd FD leak heal + updates show outdated_same_release
- watchdog: add ai_heal_rpcd() - monitors rpcd file descriptor count,
  restarts rpcd when FD count exceeds 512 (threshold of 1024 limit).
  Prevents LuCI from showing all services as 'stopped' due to FD exhaustion
  when rpcd can no longer fork to execute /usr/bin/tachyon commands.
  Runs on every watchdog health audit cycle (~15s).

- watchdog: move safe_reload_firewall() definition before ai_heal_nftables()
  and ai_heal_qos() to fix 'left-hand side is not a function' error.
  ucode does not hoist function declarations.

- updates: show Update button for outdated_same_release status (same version
  number but different commit SHA). Previously the button was hidden when
  current_version == latest_version even if SHAs differed.
2026-08-04 22:57:39 +03:00
Dushnilin ff627cfb52 fix: FD-cascade при reinstall + SHA версии в UI + тип outdated_same_release
- action.uc: killall logread перед restart_tachyon_after_successful_change,
  предотвращает FD-каскад при reinstall/update (orphan logread pipe FD)
- action.uc: current_sha/latest_sha в ответе check_update для Tachyon
- updates.uc: SHA пробрасывается через кэш проверки обновлений
- fe/types.ts: outdated_same_release добавлен в union статусов,
  поля current_sha/latest_sha в ComponentActionResult,
  AI Watchdog поля в ConfigSection (pre-existing TS2339 fix)
- fe/store.service.ts: outdated_same_release и SHA в состоянии updatesChecks
- fe/initController.ts: рендер SHA hash-badge для outdated_same_release,
  setCheckResult принимает SHA, applyCachedCheckResults/handleCheckResult обновлены
- fe/styles.ts: .sha-info — monospace badge для отображения коммит-хешей
2026-08-04 16:03:07 +03:00
Dushnilin a3de505a9a chore: switch zapret2 repo to Dushnilin/zapret2-openwrt 2026-08-04 14:04:29 +03:00
Dushnilin 56480443b4 feat: dynamic sing-box repo links + expanded README
- runtime.uc: add sing_box_repo_url to build_system_info() based on
  installed variant (extended→shtorm-7, lx→Leadaxe, stable→SagerNet)
- main.js: use systemInfo.sing_box_repo_url instead of hardcoded URL
- README.md / README.en.md: expanded Watchdog section with all 14 fixes,
  atomic operations, restart protection, data correctness, Telegram
  rate limits, firewall improvements, dynamic repo links, commit-level
  update tracking
2026-08-03 21:52:49 +03:00
Dushnilin 22a236e5d1 feat: commit-level version tracking for same-release updates
Backend:
- constants.uc: add TACHYON_COMMIT_SHA constant (placeholder __COMPILED_COMMIT_SHA__)
- build.sh: capture git rev-parse HEAD and sed-replace commit SHA placeholder
- Makefile: same commit SHA sed replacement for OpenWrt builds
- action.uc: modify check_tachyon() to compare installed commit SHA with
  target_commitish from GitHub release, new status 'outdated_same_release'
- action.uc: reuse release_json for both version and commit SHA extraction
- updater.uc: add release_commit_sha helper to extract target_commitish
- updates.uc: extend cacheable status to include outdated_same_release

Frontend:
- main.js: handle outdated_same_release status in renderComponentCard
- main.js: include outdated_same_release in shouldShowInstallAfterCheck
- main.js: include outdated_same_release in applyCachedCheckResults

i18n:
- Add 'Update is available for current release' and 'Update is available
  for current release:' to .pot and .ru.po files

78 tests pass.
2026-08-03 21:35:06 +03:00
Dushnilin 2965277877 feat: custom hosts lists — remote URL download, dnsmasq addn-hosts, sing-box DNS rules, LuCI UI 2026-08-03 16:05:53 +03:00
Dushnilin 1e1f19d7b4 telegram bot: 12 новых фич + updates panel: кнопки GitHub репозиториев 2026-08-02 10:41:04 +03:00
Dushnilin 336db69429 fix: convert dns_hosts from list to option format in UCI 2026-08-01 22:41:05 +03:00
Dushnilin 0a3ef0dff2 feat: AI Watchdog — 11 новых фич с полной настройкой из LuCI 2026-08-01 14:41:59 +03:00
Dushnilin 3752439895 Tachyon Doctor: новые проверки, авто-фиксы, расширенный AI Doctor 2026-08-01 09:24:44 +03:00
Dushnilin 207f77954a fix: auto-switch DNS servers on protocol change in settings and per-rule 2026-07-31 20:05:33 +03:00
Dushnilin 6061c92571 fix: read dns_type from DOM select instead of UCI for dynamic DNS server filtering 2026-07-31 19:01:07 +03:00
Dushnilin bc04794b73 feat: DoQ в UI + динамическая фильтрация DNS серверов по протоколу (UDP/DoT/DoH/DoQ) 2026-07-31 18:41:58 +03:00
Dushnilin ac1ff6bbb7 fix: кнопки активны после обновления + перевод Reinstall → Переустановить 2026-07-31 18:15:28 +03:00
Dushnilin ac209457d7 feat: кнопка Переустановить для Tachyon на странице обновлений 2026-07-31 17:34:11 +03:00
Dushnilin 7757ceae6a feat: implement WebRTC Leak Protection and Strict DNS DoQ Enforcer 2026-07-30 21:43:56 +03:00
Dushnilin b057e0a48d refactor: удаление неиспользуемого автоподбора Zapret2 и чистка файлов локализации 2026-07-30 16:42:30 +03:00
Dushnilin 6c1d3dc7be LuCI: Remove express/deep scan dropdown, use single deep scan 2026-07-29 22:39:45 +03:00
Dushnilin 4422416227 fix(ui): native rules button layout and tracer community match logic 2026-07-29 18:32:17 +03:00
Dushnilin 3821e92148 style(luci): complete visual redesign of zapret2 strategy tuner with 1-click automated section domain optimization 2026-07-29 13:41:41 +03:00
Dushnilin 03f6699099 feat(zapret2): fully automated 1-click strategy tuner for section domains and fix state directory creation 2026-07-29 13:19:15 +03:00