* fix(dashboard): route conversation history tool messages through ToolCallCard
When viewing conversation history, large tool outputs (e.g. a single
git log --stat producing tens of KB) caused the browser renderer to
freeze. Root cause: formattedMessages mapped every role (including
tool / system / _checkpoint) into user/bot bubbles, and bot plain
strings went through markstream-vue's MarkdownRender. Single 88KB
tool messages plus 88-of-them adding up to ~349KB of synchronous
markdown parsing was enough to block the main thread for 5+ seconds.
This patch:
- Indexes tool-role messages by tool_call_id
- Filters formattedMessages to user/assistant only — tool, system and
_checkpoint roles no longer render as standalone bubbles
- Converts assistant.tool_calls (OpenAI shape, with tc.name/tc.arguments
fallbacks) into the existing tool_call MessagePart, attaching the
paired result so MessageList's ToolCallCard renders it (default
collapsed, no longer feeds large strings into the markdown renderer)
- Drops empty placeholder plain parts when an assistant message only
carries tool_calls
- Sets ts/finished_ts to 0 as a sentinel: ToolCallCard.toolCallDuration
returns "" when startTime <= 0, suppressing a misleading "0ms"
duration that would otherwise appear because conversation history
has no real timing data
Behavior change: tool results are now embedded in their assistant's
ToolCallCard.result instead of appearing as separate bot bubbles.
This matches the main chat UI's behavior.
Fixes#7929
Refs #7372#7456
* style(dashboard): use single scrollbar in conversation history preview
ToolCallCard's result/args panes have their own max-height + overflow,
which produced a nested scrollbar when nested inside the history
preview's already-scrollable .conversation-messages-container. Override
those constraints inside the preview only — the outer 500px-bounded
container already provides scroll bounds, so a single scrollbar feels
cleaner. The main chat UI is unaffected.
---------
Co-authored-by: wanger <wanger@example.com>
* fix(provider): fix Anthropic custom headers and system prompt compatibility
- Pass custom_headers via AsyncAnthropic's `default_headers` parameter
instead of creating a separate httpx.AsyncClient. This avoids
`isinstance` check failures when multiple httpx installations exist
on sys.path (e.g. bundled Python + system Python).
- Use list format for the `system` parameter (`[{"type": "text", ...}]`)
instead of a plain string. The list format is supported by the official
Anthropic API and is also compatible with third-party API proxies that
reject the string format.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix(provider): fix Anthropic custom headers and system prompt compatibility
- Pass custom_headers via AsyncAnthropic's `default_headers` parameter
instead of creating a separate httpx.AsyncClient. This avoids
`isinstance` check failures when multiple httpx installations exist
on sys.path (e.g. bundled Python + system Python).
- Use list format for the `system` parameter (`[{"type": "text", ...}]`)
instead of a plain string. The list format is supported by the official
Anthropic API and is also compatible with third-party API proxies that
reject the string format.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* Add test unit
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* fix: 压缩算法删除 user 消息 Bug 修复
* perf: improve truncate algo
* fix: improve context length error detection for PPIO platform compatibility
- Extend error detection to handle PPIO's error message format:
'The input is longer than the model's context length'
- Add case-insensitive matching using .lower() for robustness
- Maintain backward compatibility with existing 'maximum context length' check
This fixes the issue where PPIO platform models (e.g., ppio/zai-org/glm-5-turbo)
would fail with AgentState.ERROR due to unrecognized context length errors.
---------
Co-authored-by: Soulter <905617992@qq.com>
- New config item fallback_max_context_tokens (default 128k)
- When max_context_tokens is 0 and model not in LLM_METADATAS,
use fallback_max_context_tokens as the context window limit
- Unified global config under provider_settings, in truncate_and_compress section
- i18n: zh-CN, en-US, ru-RU
Co-authored-by: AstrBot <astrbot@container>
* fix: clarify context management UI text to explain execution order
* fix: update hint references to match updated description names
---------
Co-authored-by: Blueteemo <Blueteemo@users.noreply.github.com>
* feat: supports to download plugins via astrbot official plugin storage
* fix: improve exception message for missing root directory name in PluginUpdator
* feat: Implement plugin internationalization support
- Added support for plugins to provide localized names, descriptions, and configuration texts through JSON files in the `.astrbot-plugin/i18n` directory.
- Updated various components to utilize the new internationalization functions, including `ConfigItemRenderer`, `ExtensionCard`, `ItemCard`, `ObjectEditor`, `PluginSetSelector`, and `TemplateListEditor`.
- Enhanced the `usePluginI18n` utility to resolve plugin-specific translations based on the current locale.
- Modified the `common` store to include an `i18n` field for plugin metadata.
- Updated documentation to include guidelines for plugin internationalization.
- Added tests to ensure proper loading of localization files and integration with plugin metadata.
* perf: code quality
* feat: update config path handling for internationalization support
* fix: guard against None system_prompt in _ensure_persona_and_skills
ProviderRequest.system_prompt defaults to None. When a persona with a
prompt is configured, _ensure_persona_and_skills calls
``req.system_prompt += ...`` which crashes with ``TypeError`` when
system_prompt is None.
Added a None guard before the persona prompt injection and skills prompt
appending sections so they always operate on a string.
* chore: delete tests/unit/test_system_prompt_none_bug.py
---------
Co-authored-by: Weilong Liao <37870767+Soulter@users.noreply.github.com>
* feat: update ExtensionCard variant to outlined and adjust InstalledPluginsTab layout for better responsiveness
* feat: update MCP servers management UI and add descriptions for better clarity
* feat: enhance OutlinedActionListItem component with clickable functionality and new slots
feat(i18n): update English, Russian, and Chinese translations for extension and knowledge base features
fix: improve DocumentDetail and KBDetail views with outlined card styles and remove unnecessary dividers
refactor: streamline KBList component to use OutlinedActionListItem for better UI consistency
style: adjust styles for knowledge base components and improve responsive design
test: add security tests for skill file browser and editor to prevent path traversal and file size issues
* feat: update UI components and styles for improved layout and readability
* feat: add PluginDetailPage component for detailed plugin information display
refactor: remove extension preference storage management and related tests
chore: clean up useExtensionPage by removing unused preference storage logic
* feat: add getHandlerDisplayName function for improved handler name display
* fix(dashboard): use v-autocomplete for list+options config field (#7884)
Replace v-select with v-autocomplete in the list+options branch of
ConfigItemRenderer. v-select's keyboard typeahead auto-toggles the
first prefix-matching item in multiple mode, which is unusable for
long option lists (e.g. plugin language pickers). v-autocomplete
filters the dropdown by typed text instead.
Bind v-model:search and clear it in @update:model-value so the search
box resets after each selection, allowing consecutive keyword search.
* perf(dashboard): memoize list config select items via computed
Wrap getSelectItems(itemMeta) in a computed so the options array
is only re-mapped when itemMeta changes, not on every keystroke
in the v-autocomplete search input. Avoids quadratic-ish work for
long option lists
---------
Co-authored-by: wanger <wanger@example.com>
* fix: warn when default chat provider is unset
* fix: align startup warning with provider fallback
* refactor: simplify default chat provider warning guard checks
* feat: warn when default chat provider id is invalid or missing
- Emit a warning when `default_provider_id` points to a
non-existent enabled provider, preventing silent fallback to
an unexpected model.
- Reset the warning guard before each
`provider_manager.initialize()` so configuration reloads
trigger a fresh re-evaluation.
- Harden guard checks to handle `None` `provider_settings` and
`None` provider IDs gracefully.
* test: cover fallback and invalid default provider id warnings
- Add case for `curr_provider_inst=None` to verify fallback to
`providers[0]`.
- Add case for a `default_provider_id` that does not match any enabled
provider.
* style: format default chat provider warning
---------
Co-authored-by: RC-CHN <1051989940@qq.com>
* fix(core): security fix - restrict send_message_to_user to current session only
Closes#7822
SECURITY: Remove the user-controlled 'session' parameter from the
send_message_to_user tool. Previously, a regular user could ask the
LLM to send messages to any arbitrary session (group chat) by
providing a crafted session string, which is a high-risk
vulnerability.
Changes:
- Remove 'session' parameter from tool schema (LLM can no longer
propose it)
- Always use context.context.event.unified_msg_origin as the target
session
- Update description to clearly state that messages can only be sent
to the current user's session
* fix: restore session param but restrict to admin only
- Re-add the parameter removed in the original PR
- Non-admin users can only send to their own session (current_session)
- Admin users can send to any session via the param
- Uses from computer_tools.util (same pattern as fs.py)
- Ref: https://github.com/AstrBotDevs/AstrBot/issues/7822
Co-authored-by: Soulter <soulter@astrbot.app>
* Update message_tools.py
---------
Co-authored-by: AstrBot <bot@astrbot.app>
* feat(shell): add background command execution with output redirection and timeout support
* feat(shell): update timeout parameter to be optional in shell execution methods
* feat(shell): set default timeout for shell execution to 10,000,000 milliseconds
* feat(shell): set default timeout to 300s for shell execution
* feat(shell): reorder timeout parameter in ExecuteShellTool configuration
* feat(shell): implement background command execution with detached shell command support
Co-authored-by: Copilot <copilot@github.com>
* test(shell): remove obsolete test for background shell command output redirection
* fix: reorder import statements in shell.py for consistency
* fix: wrap command in parentheses for background output redirection
---------
Co-authored-by: Copilot <copilot@github.com>
* feat: add one-line deploy script (deploy-cli.sh) and update cli.md
- Add docs/scripts/deploy-cli.sh for one-command deployment (Linux/macOS/WSL)
- Update docs/zh/deploy/astrbot/cli.md to reference local script
- Replace non-existent https://astrbot.app/deploy.sh with raw.githubusercontent.com URL
- Add local run tip and WSL-based Windows support
* fix: address PR review feedback for deploy-cli.sh
- Replace sort -V with Python-native version check (macOS BSD compat)
- Bump Python requirement from >=3.10 to >=3.12 (match pyproject.toml)
- Detect current directory as project root (avoid nested clone)
- Handle existing non-git directory explicitly
- Add curl dependency check
- Support ASTRBOT_REPO and ASTRBOT_DIR env vars for forks/mirrors
- Update cli.md version description to match
* feat: add Windows PowerShell deploy script and update docs
- Add deploy-cli.ps1 for Windows native environment (PowerShell 7+)
- Update cli.md to document Windows one-liner deployment
- Add local script execution instructions for both bash and ps1
* refactor: standardize log messages and improve clarity in various modules
Co-authored-by: Copilot <copilot@github.com>
* docs: 移除一行命令快速部署部分,简化安装说明
* feat: 添加脚本以复制部署 CLI 文件并更新构建命令
* refactor: 更新日志消息以提高可读性,统一英文提示信息
---------
Co-authored-by: Soulter <905617992@qq.com>
Co-authored-by: Copilot <copilot@github.com>
Co-authored-by: Weilong Liao <37870767+Soulter@users.noreply.github.com>
* fix(dashboard): add tooltip for truncated command/tool descriptions in WebUI
- CommandTable.vue: add :title binding to description div
- ToolTable.vue: add :title binding to description and origin_name divs
Fixes#7583 - Webui中超出显示长度的指令描述无法以任何方式看到
* docs: add pre-commit setup guide to AGENTS.md
Extract the pre-commit and ruff setup instructions from README.md
into AGENTS.md so AI agents have a complete reference for
setting up the development environment.
---------
Co-authored-by: AstrBot Fixer <astrbot@fix-bot.local>
Co-authored-by: AstrBot Fixer <astrbot-fixer@users.noreply.github.com>
* fix: restore T2I text template rendering
- keep using {{ text | safe }} instead of text_base64
- inject Shiki runtime by default for T2I templates
- update built-in templates to read markdown from a hidden textarea
- improve WebUI preview sample text and Shiki runtime serving
- add regression tests for template rendering and runtime injection
* fix: prevent injected Shiki runtime from breaking T2I templates
* fix(t2i): restore raw text template rendering
* test(t2i): remove test
* fix(t2i): restore previewText
* fix(stats): TPM now only counts output tokens
- Add range_total_output_tokens accumulation, separate from total tokens
- Change range_avg_tpm formula to use output tokens only
- Update i18n labels to reflect Output TPM
* fix(stats): range