* feat(plugin): support icon field in metadata.yaml for sidebar icon
* feat(sidebar): add isRawTitle support for non-i18n sidebar titles
* feat(sidebar): add usePluginSidebarItems composable for dynamic plugin WebUI entries
* feat(sidebar): inject plugin WebUI items into sidebar before More group
* refactor(plugin-page): remove header, make iframe full-screen
* feat(sidebar): restore plugin WebUI collapsible group
* fix(plugin-page): prevent iframe from capturing mousemove during sidebar resize
- Use absolute positioning instead of negative margin for full-screen layout
- Zero container padding for plugin page route in FullLayout
- Disable pointer-events on iframe during sidebar drag to avoid event capture
* refactor(sidebar): share plugin state reactively instead of polling
- Replace polling + events with module-level reactive shared state
- useExtensionPage.getExtensions() populates pluginSidebarState
- usePluginSidebarItems uses computed() to derive sidebar menu
- Zero additional API calls, updates instantly on any plugin change
* fix(sidebar): restore initial plugin data fetch on sidebar mount
* feat(sidebar): render plugin icons via MDI SVG CDN instead of subset font
- Plugin icons loaded from https://cdn.jsdelivr.net/npm/@mdi/svg@7/svg/
- Removes subset limitation - plugins can use any MDI icon
- Fallback to subset font class for built-in sidebar items
- Default icon remains mdi-puzzle when plugin doesn't specify one
* fix(sidebar): render plugin icons as inline SVG with currentColor for theme matching
* docs: add plugin sidebar icon documentation
* docs: require mdi- prefix for plugin icon field
* chore: ruff format
* fix: address review feedback
- Add SVG sanitization to prevent XSS via v-html (reject <script>, event handlers)
- Extract MORE_GROUP_KEY shared constant to avoid hardcoded i18n key
- Parallel SVG loading with Promise.all instead of serial
- Pure buildPluginItems, mutate iconSvg in place to avoid redundant rebuilds
- Fallback to default icon SVG when loading fails
- Revert accidental pnpm-lock.yaml changes
* chore: remove webui icon
---------
Co-authored-by: Soulter <905617992@qq.com>
* feat(plugin): pass theme through plugin page asset URLs and initial context
Add theme query parameter propagation through the plugin page asset pipeline
so that the bridge SDK initial context includes isDark.
* feat(plugin): inject data-theme and color-scheme into plugin page HTML
Set data-theme on <html> and add color-scheme meta tag server-side
to prevent flash when entering plugin pages in dark mode.
* feat(webui): add isDark getter to customizer store
* feat(webui): sync theme to plugin iframe via URL param and postMessage
Append theme query parameter to iframe src URL and include isDark
in the postMessage context. Watch uiTheme changes to re-send context.
* feat(bridge): auto-apply data-theme from context in plugin bridge SDK
Set data-theme attribute on document.documentElement when context
includes isDark, enabling live theme switching via postMessage.
* docs: add light/dark theme adaptation guide for plugin pages
Add theme adaptation section to existing plugin-pages docs in both
Chinese and English, covering CSS variables and onContext() usage.
* test: add theme sync tests for plugin page bridge and content
Verify isDark in bridge SDK initial context with various theme params,
and verify data-theme and color-scheme injection in rewritten HTML.
* fix(plugin): use case-insensitive regex for head tag in HTML rewrite
Replace string match for <head> with case-insensitive regex to handle
uppercase tags and tags with attributes, preventing duplicate injection
of color-scheme meta tag.
* refactor(webui): generalize isDark getter to support any dark theme
Replace hardcoded PurpleThemeDark check with suffix-based detection
so all dark theme variants are recognized automatically.
* refactor(plugin): extract theme helpers for HTML rewriting
Extract _get_request_theme and _apply_theme_to_html to eliminate
duplicate theme-parsing logic and isolate HTML mutation. Use case-
insensitive regex for head tag detection to prevent duplicate
injection when tags use mixed casing.
* style: apply ruff formatting to plugin page tests
Wrap long function call lines for consistency with project style.
* fix(plugin): handle existing data-theme and case-sensitive fallback in HTML rewrite
Strip any existing data-theme attribute before adding the new one to
prevent duplicate attributes. Use case-insensitive regex for the
<head> fallback insertion to avoid corrupting <html> tag attributes.
* fix(webui): add null guard to isDark getter
Guard against undefined uiTheme to prevent TypeError when the
theme config has not been initialized.
* fix(webui): centralize theme mapping and preserve hash in plugin page URL
Extract themeParam computed to avoid drift between URL and context.
Include hash fragment in iframe URL to support SPA hash routing.
* fix(webui): address CR feedback - deduplicate color-scheme meta, harden isDark getter, consolidate theme source
- _apply_theme_to_html: strip existing color-scheme meta before injecting to
avoid duplicates; merge data-theme strip+add into single-pass regex callback
- customizer.ts: replace brittle endsWith('Dark') with explicit theme name check
- _rewrite_plugin_page_html: use _get_request_theme() directly instead of
reading theme from extra_query_params
* fix(webui): 简化 isDark 推导、优化查询参数构建、使用暗色主题集合
- isDark 推导简化为 theme == "dark"(None == "dark" 为 False,去掉多余三元表达式)
- _prepare_plugin_page_query_params 改为线性构建,先计算再构建字典
- isDark getter 改用显式 DARK_THEMES Set,替代硬编码单值比较
---------
Co-authored-by: lxfight <lxfight@192.168.5.50>
* Enhance Reply chain handling for Record components
Added processing for Record components within Reply chains, including WAV conversion and STT functionality.
* Refactor STT processing for Record components
* Add STT record function for voice-to-text processing
* Update stage.py
* Update stage.py
* Update stage.py
* feat: future task UI
* fix: update filter label for UMO in English and Chinese locales
* feat: enhance cron job management with delivery target handling and UI improvements
* fix: update session label to indicate optional delivery target
* feat: add tooltip for last run time and error in cron job display
* fix(dashboard): relax frame security headers when running under launcher
When AstrBot is launched by the AstrBot Launcher, the dashboard is
embedded in a cross-origin iframe (the Tauri webview). The plugin page
responses set X-Frame-Options: SAMEORIGIN and CSP frame-ancestors
'self', both of which inspect the *entire* ancestor chain — not just the
immediate parent. Because the top-level Tauri webview has a different
origin, these headers block the plugin page from loading inside the
nested iframe, resulting in 'localhost refused to connect'.
Fix: skip the restrictive frame headers when ASTRBOT_LAUNCHER=1 is set,
which the launcher already injects as an environment variable. Other
security measures (iframe sandbox, JWT asset_token, postMessage bridge)
remain in place.
* fix(dashboard): preserve object-src and base-uri CSP directives under launcher
Keep object-src 'none' and base-uri 'self' in the CSP header even when
ASTRBOT_LAUNCHER is set. Only frame-ancestors and X-Frame-Options need
to be relaxed because the Tauri webview is a cross-origin ancestor.
* fix(dashboard): tighten ASTRBOT_LAUNCHER check and always emit CSP
Use explicit value check ('1' / 'true') instead of truthiness for the
ASTRBOT_LAUNCHER env var. Always emit a Content-Security-Policy header
and only conditionally prepend frame-ancestors 'self' — this keeps
object-src 'none' and base-uri 'self' active under the launcher.
* fix(context): restore turn cap, serialize content parts and tool calls for llm compress, fix AftCompact debug log
Three context-compaction regression fixes after #8226:
1. Restore max_context_length -> enforce_max_turns propagation so
normal turn-based truncation works again.
2. Serialize ContentPart and ToolCall objects into plain dicts in
_message_to_dict so llm_compress no longer fails with JSON
serialization errors.
3. Print _provider_messages (compacted) instead of run_context.messages
(unchanged) in AftCompact debug log; truncate long role lists to
first4,...,last4 to avoid log spam.
Assertions in tests are also hardened to avoid coupling to exact prompt
wording.
* fix(tool_loop_agent_runner): simplify context handling by removing redundant provider messages
* fix(tool_loop_agent_runner): rename context manager variables for clarity
* fix: update context compression to use recent token ratio instead of fixed count
* fix: enhance LLMSummaryCompressor to sanitize contexts and improve message handling
* ruff format
---------
Co-authored-by: Soulter <905617992@qq.com>
* fix(provider): wrap batch embedding texts in Content to avoid collapse on gemini-embedding-2
* fix(gemini_embedding): format list comprehension for better readability
---------
Co-authored-by: Rat0323 <Rat0323@users.noreply.github.com>
Co-authored-by: Soulter <905617992@qq.com>
Refactor file handling to resolve sources more effectively, including decoding file URIs and handling base64 data. Update methods to ensure compatibility with different file formats and paths.
* fix(ltm): prevent wake commands from being recorded as group chat context
* test: fix mock event get_extra return value in group context wiring tests
* test: strengthen group context mock and add slash-command skip test
* fix(console): use toast for pip-install error display
The pip-install dialog displayed error messages as unstyled inline
<small> text with no color differentiation from success messages.
Replaced with useToast() to show errors as red snackbar, consistent
with the rest of the dashboard.
* fix(console): use i18n for pip-install toast fallback messages
Set MiniMax-M3 as the default fallback model for the Token Plan provider.
The model list itself is already fetched dynamically from the MiniMax API,
so all available models including M3 are auto-discovered. This change just
updates the hardcoded fallback used when no model is configured to the
current flagship.
MiniMax-M2.7 remains fully usable; users can still configure it explicitly.
* feat: add TOTP two-factor authentication for dashboard login
* fix: ensure TOTP verification uses UTC for accurate time comparison
* fix: update recovery code validation logic for disabling TOTP
* test: add unit tests for TOTP functionality and recovery code validation
* chore: format
* feat: add trust_proxy_headers switch for auth rate-limit IP source
* feat: make dashboard auth rate-limit configurable via system settings
Add auth_rate_limit config block to dashboard settings with enable
(default: true), average_interval (default: 1.0s), and max_burst
(default: 3) options. The dashboard auth middleware now reads from
config instead of using hardcoded values. The average_interval and
max_burst fields are conditionally shown only when rate limiting is
enabled.
* fix: normalize dashboard client IP from trusted proxy headers
* refactor: encapsulate rate limiter state into registry, add TTL
* feat: show dynamic page title during two-factor verification
* fix: require two-factor verification for protected config saves
* chore: format
* refactor: reorganize TOTP verification UI components for better layout
* refactor: clean up recovery stage UI by removing unused styles and improving label handling
* docs: add TOTP two-factor authentication documentation for WebUI
---------
Co-authored-by: Soulter <905617992@qq.com>
* fix: improve template list config handling
* feat(webui): show template list display item
* feat(webui): allow hiding template list hints
* docs: document template list metadata fields
* fix: support file fields in template list configs
* refactor(ltm): redesign long-term memory with context compaction
- Add raw_records / contexts / summaries data model per group
- Add LLM summary compaction strategy alongside truncation
- Add turn-based (_split_into_rounds) granularity
- Add image caption integration into LTM history
- Add tool_call / tool_result persistence into raw_records
- Add active reply support driven by LTM state
- Improve summary injection prefix with system note and delimiters
- Add info-level logging for summary compaction lifecycle
- Clarify default summary prompt with explicit preserve/drop rules
- Add context_guard for history overflow protection in agent runner
- Add internal agent history compaction in agent_sub_stages
- Add comprehensive LTM unit tests and compaction test suites
* fix(ltm): handle malformed JSON in tool args and clean up lock on session removal
* fix(ltm): guard against duplicate system prompt note injection
* fix(ltm): fall back to user message when internal marker parsing fails
- Treat lines starting with <T:CALL>, <T:RES, or <BOT/ as regular user
messages when their respective parsers return None, instead of silently
dropping them. Defensive guard against malformed internal markers.
* fix(ltm): release session lock during LLM summary generation
* fix(ltm): trim raw_records in handle_message to prevent unbounded growth
* perf(ltm): use len(s) instead of len(s.encode()) in trim loop
Avoid allocating a new bytes object for every string when calculating
buffer size in _trim_raw_records. Character count is sufficient for
the approximate memory cap.
* feat(ltm): make user segment truncation limits configurable
* feat(ltm): pre-fill default LTM summary prompt in config and i18n
* refactor(ltm): hardcode internal segment/trim constants
* refactor(ltm): unify compaction strategy with main agent runner
* feat(ltm): add @mention weight marker for group chat messages
* test: fix test failures from LTM compaction unification
* chore(dashboard): remove obsolete LTM compaction i18n metadata
* chore: shrink codebase
* feat(group-chat): implement group chat context management and related functionality
---------
Co-authored-by: Tsukumi <112180165+Tsukumi233@users.noreply.github.com>
Co-authored-by: zenfun <zenfun510@gmail.com>
Co-authored-by: Soulter <905617992@qq.com>
* fix: plugin name in the marketplace does not match the local plugin
* chore: update test
* Update astrbot/dashboard/routes/plugin.py
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
* Update astrbot/dashboard/routes/plugin.py
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
* Update astrbot/dashboard/routes/plugin.py
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
* chore: reformat code
* Clean up unused variables in useExtensionPage.js
Removed unused sets for installed repositories and names.
* fix: 统一repo匹配逻辑,移除fallback
---------
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>