Add user-configurable timezone and 12/24-hour preferences, then wire them through settings, runtime snapshots, scheduler payloads, wait handling, notifications, backups, memory, plugin metadata, and frontend formatters.
Keep UTC as the boundary for absolute instants while serializing user-facing dates in the configured or browser-resolved timezone. Preserve scheduler wall-clock inputs in the selected timezone, propagate TZ into desktop/runtime process environments, and restart active desktop sessions when the runtime timezone changes.
Cover the risky paths with timezone regression tests for settings normalization, auto and fixed timezone resolution, scheduler round-trips, memory timestamp conversion, and desktop timezone sync.
Split the legacy core speech stack into two built-in, independently toggleable plugins: `_kokoro_tts` for TTS and `_whisper_stt` for STT.
This refactor keeps dependency installation and bootstrap concerns in Docker/bootstrap/preload, while moving speech-specific tooling, APIs, prompts, UI, and runtime behavior into the plugins. Core now exposes engine-agnostic `tts-service` and `stt-service` brokers, with browser-native TTS preserved as the fallback when Kokoro is disabled.
Included in this change:
- add built-in `_kokoro_tts` plugin with plugin-owned synth API, config, status UI, and provider registration
- add built-in `_whisper_stt` plugin with plugin-owned transcribe API, mic runtime, device UI, prompt injection, and provider registration
- remove legacy core speech APIs/helpers/settings/UI and delete unused `webui/js/speech_browser.js`
- replace the old hardcoded speech settings section with a generic voice surface backed by plugin extensions
- update preload/docs/tests to match the new plugin-owned speech architecture
Behavioral intent:
- both plugins are built-in but not `always_enabled`
- users can now hot-switch TTS and STT independently
- browser TTS remains available when `_kokoro_tts` is off
- Whisper mic UI only appears when `_whisper_stt` is enabled
Restyle Settings and standard modals around a streamlined left-rail layout, clearer section hierarchy, advanced settings disclosures, and stronger update states.
Add persistent update visibility with quieter once-daily update notifications, plus Remote Link and Space Agent actions in the canvas rail. Refresh the tunnel experience as a normal Remote Link modal with clearer copy, QR/mobile affordances, and safer state handling.
Persist the active agent profile with each chat context and add a context-scoped endpoint for switching profiles without mutating global settings. Update the WebUI selector and docs to treat settings as the default for new chats, and expose the switch through the A0 connector plugin.
Add full support for loading web UI extensions from plugins: - Frontend: new extensions loader (js/extensions.js) that loads and caches JS and HTML extensions, calls JS hooks, imports HTML as <x-component> tags, normalizes paths, and replaces the old plugins.js auto-inject logic. - Messages: make setMessages async, introduce extension hooks (set_messages_before_loop / after_loop) and integrate JS extension calls; adjust Scroller usage accordingly. - Components: fix x-component path handling in several templates and components import logic. - Backend: add filters to /api/load_webui_extensions and pass them to plugin helper; update helpers to look for plugin extensions under extensions/python instead of backend. - Plugins helper: extend get_webui_extensions to accept file glob filters, dedupe matches, return relative paths, and improve error logging. - Project config: include plugins and usr/plugins JS files in jsconfig.json. - Add a small test extension file and move several plugin extension files from backend/ to python/ directories. - Minor: reset error_retries earlier in agent message loop to avoid stale retry counts.
These changes enable a flexible plugin extension system for both JS and HTML assets, improve caching and path normalization, and wire up backend APIs and helpers to support the new structure.
Updated the settings UI to work with the new backend format that separates settings values from additional metadata.
- Settings components now read from the new structure (settings + additional)
- Removed legacy field-based rendering in favor of direct value binding
- Root passwd masking
- Added knowledge subdirectory selector support
- Enhanced backend `convert_out()`: now ensures current values are always present in dropdown options, preventing UI glitches
- Cleaned up old conversion functions marked for removal
- Simplified task detail opening logic by integrating it into the `settingsModalStore`
- Updated the visibility condition for the task detail view in `scheduler-task-detail.html` to rely solely on the selected task state
rm attributes from components
simplify task display logic
settings components init
scheduler componentize
- Removed the inline scheduler settings script from `index.html` and replaced it with a new component structure in `scheduler-settings.html`, `scheduler-task-editor.html`, `scheduler-task-list.html`, and `scheduler-task-detail.html`.
- Introduced a dedicated `scheduler-store.js` to manage state and logic for the scheduler, enhancing maintainability and separation of concerns.
- Updated the `index.js` to remove the now obsolete `openTaskDetail` function, integrating task detail handling within the new store.
- Removed the deprecated `scheduler.js` file, consolidating functionality into the new component architecture.
settings modal store rename
- Replaced all instances of `$store.settingsModalStore` with `$store.settingsStore` across various settings components.
scheduler tab content x-if