From 25b0b1e5090bbbd443c61f25e836603f977cb1b7 Mon Sep 17 00:00:00 2001 From: xiaoyuyu6420 <93528429+xiaoyuyu6420@users.noreply.github.com> Date: Tue, 21 Jul 2026 01:45:19 +0800 Subject: [PATCH 1/3] fix: sanitize unsupported image MIME types (e.g. GIF) in context cleaner Fixes #9295. When a provider declares image modality support, the context sanitizer previously kept every image block as-is. Animated GIFs can then be persisted into session history and later cause continuous failures on OpenAI-compatible Gemini gateways that reject image/gif. - Drop image/gif data URLs and .gif http(s) URLs to a [Image] placeholder even when the provider supports image modality. - Keep the existing full image-strip path when image modality is absent. - Preserve JPEG/PNG/WebP and unknown-MIME images when image is supported. - Add unit coverage for the reporter scenario and related edge cases. --- astrbot/core/provider/modalities.py | 87 ++++++++++- tests/unit/test_modalities_sanitize.py | 205 +++++++++++++++++++++++++ 2 files changed, 289 insertions(+), 3 deletions(-) create mode 100644 tests/unit/test_modalities_sanitize.py diff --git a/astrbot/core/provider/modalities.py b/astrbot/core/provider/modalities.py index 66ac74e9b7..2f0e940703 100644 --- a/astrbot/core/provider/modalities.py +++ b/astrbot/core/provider/modalities.py @@ -34,6 +34,72 @@ def _message_to_dict(message: dict[str, Any] | Message) -> dict[str, Any] | None return None +# Image MIME types that some OpenAI-compatible gateways reject even when the +# model claims image support. Animated GIFs in particular are accepted by raw +# Gemini (which wants image/heif/video/mp4 for animations) but rejected by +# several Gemini-flavored OpenAI proxies with "mime type is not supported". +# Keeping this list narrow avoids over-stripping providers that do accept GIF +# (e.g. Anthropic Claude). See issue #9295. +_UNSUPPORTED_IMAGE_MIMES = frozenset({"image/gif"}) + +# Lazily-built extension → MIME mapping used only for http(s) URL fallback. +_IMAGE_EXT_TO_MIME: dict[str, str] = { + ".gif": "image/gif", +} + + +def _extract_image_mime(part: dict[str, Any]) -> str | None: + """Best-effort extraction of an image MIME type from a multimodal part. + + Handles the OpenAI-style ``{"image_url": {"url": ...}}`` and the Anthropic / + Gemini-style ``{"source": {"media_type": ...}}`` / ``{"mimeType": ...}`` + layouts, as well as a bare ``{"url": ...}`` or ``{"image_url": ""}``. + + Returns: + The lowercased MIME type (e.g. ``image/gif``) if it can be determined, + otherwise ``None``. + """ + image_url = part.get("image_url") + if isinstance(image_url, dict): + url = image_url.get("url") + else: + url = image_url + if not isinstance(url, str): + url = part.get("url") if isinstance(part.get("url"), str) else None + + if isinstance(url, str): + # data URLs look like "data:image/gif;base64,...." + if url.lower().startswith("data:"): + head = url[5:].split(",", 1)[0] + # head is e.g. "image/gif;base64" + mime = head.split(";", 1)[0].strip().lower() + if mime: + return mime + else: + # Fall back to the URL path extension for http(s) URLs. + path = url.split("?", 1)[0].split("#", 1)[0].lower() + for ext, mime in _IMAGE_EXT_TO_MIME.items(): + if path.endswith(ext): + return mime + + source = part.get("source") + if isinstance(source, dict): + media_type = source.get("media_type") + if isinstance(media_type, str): + return media_type.lower() + + mime_type = part.get("mimeType") or part.get("mime_type") + if isinstance(mime_type, str): + return mime_type.lower() + + return None + + +def _is_unsupported_image_mime(mime: str | None) -> bool: + """Return True when the MIME is known to be rejected by some providers.""" + return bool(mime) and mime in _UNSUPPORTED_IMAGE_MIMES + + def sanitize_contexts_by_modalities( contexts: Sequence[dict[str, Any] | Message], modalities: list[str] | None, @@ -51,7 +117,11 @@ def sanitize_contexts_by_modalities( supports_image = "image" in modalities supports_audio = "audio" in modalities supports_tool_use = "tool_use" in modalities - if supports_image and supports_audio and supports_tool_use: + # Even when the provider declares all modalities, we may still need to walk + # the contexts to drop specific image MIME types (e.g. image/gif) that some + # OpenAI-compatible gateways reject. See issue #9295. + needs_mime_pass = supports_image and bool(_UNSUPPORTED_IMAGE_MIMES) + if supports_image and supports_audio and supports_tool_use and not needs_mime_pass: copied_contexts = [] for msg in contexts: copied_msg = _message_to_dict(msg) @@ -83,7 +153,7 @@ def sanitize_contexts_by_modalities( msg.pop("tool_calls", None) msg.pop("tool_call_id", None) - if not supports_image or not supports_audio: + if not supports_image or not supports_audio or needs_mime_pass: content = msg.get("content") if isinstance(content, list): filtered_parts: list[Any] = [] @@ -91,7 +161,18 @@ def sanitize_contexts_by_modalities( for part in content: if isinstance(part, dict): part_type = str(part.get("type", "")).lower() - if not supports_image and part_type in {"image_url", "image"}: + if part_type in {"image_url", "image"} and ( + not supports_image + or _is_unsupported_image_mime(_extract_image_mime(part)) + ): + # Either the model has no image modality at all, or it + # declares image support but the specific MIME (e.g. + # image/gif) is rejected by some OpenAI-compatible + # gateways (notably certain Gemini endpoints that only + # accept JPEG/PNG/WebP). Replacing the block with a + # placeholder prevents the unsupported bytes from being + # persisted into the session history and poisoning all + # subsequent requests. See issue #9295. removed_any_multimodal = True stats.fixed_image_blocks += 1 filtered_parts.append({"type": "text", "text": "[Image]"}) diff --git a/tests/unit/test_modalities_sanitize.py b/tests/unit/test_modalities_sanitize.py new file mode 100644 index 0000000000..a338d8783f --- /dev/null +++ b/tests/unit/test_modalities_sanitize.py @@ -0,0 +1,205 @@ +"""Tests for ``astrbot.core.provider.modalities.sanitize_contexts_by_modalities``. + +These tests focus on the image MIME handling added for issue #9295, where an +animated GIF referenced via a quote could poison the session history and make +subsequent requests to GIF-rejecting Gemini-compatible gateways fail forever. +""" + +from __future__ import annotations + +from astrbot.core.provider.modalities import ( + ContextSanitizeStats, + sanitize_contexts_by_modalities, +) + + +def _image_url_part(url: str) -> dict: + return {"type": "image_url", "image_url": {"url": url}} + + +def _user(*parts: dict) -> dict: + return {"role": "user", "content": list(parts)} + + +GIF_DATA_URL = "data:image/gif;base64,R0lGODlh8ADwAPcAAPxzxg==" +PNG_DATA_URL = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAAB" +JPEG_DATA_URL = "data:image/jpeg;base64,/9j/4AAQSkZJRgABAQEAYABgAAD" +WEBP_DATA_URL = "data:image/webp;base64,UklGRkBAAABXRUJQ" + + +# --------------------------------------------------------------------------- +# Issue #9295: GIF must be stripped even when the model claims image support +# --------------------------------------------------------------------------- + + +def test_gif_data_url_replaced_when_image_supported_but_gif_unsupported() -> None: + """Reproduces the exact reporter scenario. + + Provider declares ``[text, image, audio, tool_use]`` (which used to hit the + fast-path and skip sanitizing), and the context carries a ``data:image/gif`` + block. The GIF must be replaced with ``[Image]``. + """ + contexts = [_user(_image_url_part(GIF_DATA_URL))] + sanitized, stats = sanitize_contexts_by_modalities( + contexts, + ["text", "image", "audio", "tool_use"], + ) + + content = sanitized[0]["content"] + assert content == [{"type": "text", "text": "[Image]"}] + assert stats.fixed_image_blocks == 1 + assert stats.changed + + +def test_gif_data_url_replaced_when_only_text_and_image_supported() -> None: + """Stripping also applies to the regular image-supported path.""" + contexts = [_user(_image_url_part(GIF_DATA_URL))] + sanitized, stats = sanitize_contexts_by_modalities( + contexts, + ["text", "image"], + ) + + assert sanitized[0]["content"] == [{"type": "text", "text": "[Image]"}] + assert stats.fixed_image_blocks == 1 + + +def test_gif_http_url_replaced_by_extension_fallback() -> None: + """http(s) URLs ending in ``.gif`` are also detected via extension.""" + contexts = [_user(_image_url_part("https://example.com/animation.gif"))] + sanitized, stats = sanitize_contexts_by_modalities( + contexts, + ["text", "image", "tool_use"], + ) + + assert sanitized[0]["content"] == [{"type": "text", "text": "[Image]"}] + assert stats.fixed_image_blocks == 1 + + +def test_gif_http_url_with_query_string_still_detected() -> None: + """Query/fragment suffixes on the URL must not defeat detection.""" + contexts = [ + _user(_image_url_part("https://cdn.example.com/a.GIF?token=abc#frag")), + ] + sanitized, stats = sanitize_contexts_by_modalities(contexts, ["text", "image"]) + + assert sanitized[0]["content"] == [{"type": "text", "text": "[Image]"}] + assert stats.fixed_image_blocks == 1 + + +# --------------------------------------------------------------------------- +# Non-GIF images must be preserved when image is supported +# --------------------------------------------------------------------------- + + +def test_png_preserved_when_image_supported() -> None: + contexts = [_user(_image_url_part(PNG_DATA_URL))] + sanitized, stats = sanitize_contexts_by_modalities( + contexts, + ["text", "image", "audio", "tool_use"], + ) + + assert sanitized[0]["content"] == [_image_url_part(PNG_DATA_URL)] + assert stats.fixed_image_blocks == 0 + assert not stats.changed + + +def test_jpeg_and_webp_preserved_when_image_supported() -> None: + contexts = [ + _user(_image_url_part(JPEG_DATA_URL), _image_url_part(WEBP_DATA_URL)), + ] + sanitized, stats = sanitize_contexts_by_modalities( + contexts, + ["text", "image"], + ) + + assert sanitized[0]["content"] == [ + _image_url_part(JPEG_DATA_URL), + _image_url_part(WEBP_DATA_URL), + ] + assert not stats.changed + + +def test_unknown_mime_image_preserved_when_image_supported() -> None: + """When no MIME can be determined we must not strip the image. + + Stripping on "unknown" would over-aggressively drop legitimate images and + break providers that accept arbitrary image formats. + """ + contexts = [_user({"type": "image_url", "image_url": {"url": "abc-not-a-url"}})] + sanitized, stats = sanitize_contexts_by_modalities(contexts, ["text", "image"]) + + assert sanitized[0]["content"] == contexts[0]["content"] + assert not stats.changed + + +# --------------------------------------------------------------------------- +# Existing behavior: full removal when image modality is not declared +# --------------------------------------------------------------------------- + + +def test_all_images_removed_when_image_not_supported() -> None: + """Pre-existing behavior must remain: no image modality → strip everything.""" + contexts = [ + _user( + _image_url_part(GIF_DATA_URL), + _image_url_part(PNG_DATA_URL), + ) + ] + sanitized, stats = sanitize_contexts_by_modalities(contexts, ["text"]) + + assert sanitized[0]["content"] == [ + {"type": "text", "text": "[Image]"}, + {"type": "text", "text": "[Image]"}, + ] + assert stats.fixed_image_blocks == 2 + + +def test_audio_branch_unchanged_by_gif_handling() -> None: + """The audio-stripping branch must keep working independently.""" + contexts = [ + _user( + {"type": "input_audio", "input_audio": {"data": "abc", "format": "mp3"}}, + ) + ] + sanitized, stats = sanitize_contexts_by_modalities(contexts, ["text", "image"]) + + assert sanitized[0]["content"] == [{"type": "text", "text": "[Audio]"}] + assert stats.fixed_audio_blocks == 1 + assert stats.fixed_image_blocks == 0 + + +def test_mixed_text_and_gif_only_gif_is_replaced() -> None: + """A GIF between text parts must only drop the GIF, preserving the text.""" + contexts = [ + _user( + {"type": "text", "text": "look at this"}, + _image_url_part(GIF_DATA_URL), + {"type": "text", "text": "isn't it cool"}, + ) + ] + sanitized, stats = sanitize_contexts_by_modalities( + contexts, + ["text", "image", "audio", "tool_use"], + ) + + assert sanitized[0]["content"] == [ + {"type": "text", "text": "look at this"}, + {"type": "text", "text": "[Image]"}, + {"type": "text", "text": "isn't it cool"}, + ] + assert stats.fixed_image_blocks == 1 + + +def test_empty_modalities_returns_contexts_unchanged() -> None: + contexts = [_user(_image_url_part(GIF_DATA_URL))] + sanitized, stats = sanitize_contexts_by_modalities(contexts, None) + + assert sanitized[0]["content"] == contexts[0]["content"] + assert not stats.changed + + +def test_empty_contexts_returns_empty() -> None: + sanitized, stats = sanitize_contexts_by_modalities([], ["text", "image"]) + assert sanitized == [] + assert isinstance(stats, ContextSanitizeStats) + assert not stats.changed From 2d6f9723e9cf3f0a4db7bd79716f539a59007abf Mon Sep 17 00:00:00 2001 From: xiaoyuyu6420 <93528429+xiaoyuyu6420@users.noreply.github.com> Date: Tue, 21 Jul 2026 09:32:27 +0800 Subject: [PATCH 2/3] fix: normalize MIME params and harden URL parsing in context sanitizer Address Sourcery/Gemini review feedback on #9335 without adding new abstractions. - Strip parameters (e.g. "image/gif; charset=binary") and whitespace from source.media_type and mimeType/mime_type before comparing against _UNSUPPORTED_IMAGE_MIMES, so parameterized GIF values are still detected. - Strip surrounding whitespace from image URLs defensively. - Switch the http(s) URL path extraction from a manual split('?', '#') to urllib.parse.urlsplit, which keeps percent-encoded delimiters inside the path and is more robust for edge cases. - Inline the normalization at both call sites instead of introducing a helper, keeping it consistent with the existing data-URL branch and honoring the repo's No-Unnecessary-Helpers rule. Adds 5 unit tests covering parameterized media_type/mimeType, the encoded path case, and a non-GIF-with-params regression guard. --- astrbot/core/provider/modalities.py | 18 ++++-- tests/unit/test_modalities_sanitize.py | 78 ++++++++++++++++++++++++++ 2 files changed, 91 insertions(+), 5 deletions(-) diff --git a/astrbot/core/provider/modalities.py b/astrbot/core/provider/modalities.py index 2f0e940703..bae20ac31d 100644 --- a/astrbot/core/provider/modalities.py +++ b/astrbot/core/provider/modalities.py @@ -4,6 +4,7 @@ from collections.abc import Sequence from dataclasses import dataclass from typing import Any +from urllib.parse import urlsplit from astrbot import logger from astrbot.core.agent.message import Message @@ -56,7 +57,7 @@ def _extract_image_mime(part: dict[str, Any]) -> str | None: layouts, as well as a bare ``{"url": ...}`` or ``{"image_url": ""}``. Returns: - The lowercased MIME type (e.g. ``image/gif``) if it can be determined, + The normalized MIME type (e.g. ``image/gif``) if it can be determined, otherwise ``None``. """ image_url = part.get("image_url") @@ -68,6 +69,7 @@ def _extract_image_mime(part: dict[str, Any]) -> str | None: url = part.get("url") if isinstance(part.get("url"), str) else None if isinstance(url, str): + url = url.strip() # data URLs look like "data:image/gif;base64,...." if url.lower().startswith("data:"): head = url[5:].split(",", 1)[0] @@ -76,8 +78,10 @@ def _extract_image_mime(part: dict[str, Any]) -> str | None: if mime: return mime else: - # Fall back to the URL path extension for http(s) URLs. - path = url.split("?", 1)[0].split("#", 1)[0].lower() + # Fall back to the URL path extension for http(s) URLs. urlsplit + # robustly separates the path from query/fragment even when those + # delimiters appear percent-encoded inside the path itself. + path = urlsplit(url).path.lower() for ext, mime in _IMAGE_EXT_TO_MIME.items(): if path.endswith(ext): return mime @@ -86,11 +90,15 @@ def _extract_image_mime(part: dict[str, Any]) -> str | None: if isinstance(source, dict): media_type = source.get("media_type") if isinstance(media_type, str): - return media_type.lower() + # Normalize by stripping parameters (e.g. "image/gif; charset=binary" + # -> "image/gif") so it matches _UNSUPPORTED_IMAGE_MIMES. + return media_type.split(";", 1)[0].strip().lower() mime_type = part.get("mimeType") or part.get("mime_type") if isinstance(mime_type, str): - return mime_type.lower() + # Strip parameters (e.g. "image/gif;codec=xyz" -> "image/gif") to align + # with the data-URL and source.media_type handling above. + return mime_type.split(";", 1)[0].strip().lower() return None diff --git a/tests/unit/test_modalities_sanitize.py b/tests/unit/test_modalities_sanitize.py index a338d8783f..966101708a 100644 --- a/tests/unit/test_modalities_sanitize.py +++ b/tests/unit/test_modalities_sanitize.py @@ -86,6 +86,84 @@ def test_gif_http_url_with_query_string_still_detected() -> None: assert stats.fixed_image_blocks == 1 +def test_gif_http_url_path_strips_query_via_urlsplit() -> None: + """A real ``?`` inside the path (percent-encoded) must not be mis-split. + + ``urlsplit`` keeps the percent-encoded ``%3F`` inside the path, so a path + ending in ``.gif`` followed by an encoded delimiter is still detected. + """ + contexts = [ + _user( + _image_url_part( + "https://cdn.example.com/path%3Fextra/anim.gif?sig=1#x", + ), + ), + ] + sanitized, stats = sanitize_contexts_by_modalities(contexts, ["text", "image"]) + + assert sanitized[0]["content"] == [{"type": "text", "text": "[Image]"}] + assert stats.fixed_image_blocks == 1 + + +def test_anthropic_media_type_with_params_still_detected() -> None: + """``media_type`` carrying parameters must normalize down to ``image/gif``.""" + contexts = [ + _user( + { + "type": "image", + "source": { + "type": "base64", + "media_type": "image/gif; charset=binary", + "data": "R0lGODlh8ADwAPcAAPxzxg==", + }, + }, + ), + ] + sanitized, stats = sanitize_contexts_by_modalities( + contexts, + ["text", "image", "audio", "tool_use"], + ) + + assert sanitized[0]["content"] == [{"type": "text", "text": "[Image]"}] + assert stats.fixed_image_blocks == 1 + + +def test_gemini_mimetype_field_with_params_still_detected() -> None: + """A bare ``mimeType``/``mime_type`` with params must also be normalized.""" + contexts = [ + _user( + { + "type": "image", + "mimeType": " image/gif;codec=xyz ", + }, + ), + ] + sanitized, stats = sanitize_contexts_by_modalities(contexts, ["text", "image"]) + + assert sanitized[0]["content"] == [{"type": "text", "text": "[Image]"}] + assert stats.fixed_image_blocks == 1 + + +def test_non_gif_media_type_with_params_preserved() -> None: + """Non-unsupported MIME with parameters must be preserved, not stripped.""" + contexts = [ + _user( + { + "type": "image", + "source": { + "type": "base64", + "media_type": "image/png; charset=utf-8", + "data": "iVBORw0KGgoAAAANSUhEUgAAAAEAAAAB", + }, + }, + ), + ] + sanitized, stats = sanitize_contexts_by_modalities(contexts, ["text", "image"]) + + assert sanitized[0]["content"] == contexts[0]["content"] + assert not stats.changed + + # --------------------------------------------------------------------------- # Non-GIF images must be preserved when image is supported # --------------------------------------------------------------------------- From dfb9c7a03964d57e60a36281e01f09a106116960 Mon Sep 17 00:00:00 2001 From: xiaoyuyu6420 <93528429+xiaoyuyu6420@users.noreply.github.com> Date: Tue, 28 Jul 2026 11:31:14 +0800 Subject: [PATCH 3/3] feat(provider): add configurable image MIME whitelist (supported_image_mimes) Replaces the hardcoded GIF blocklist with a per-provider whitelist, addressing feedback that the global blocklist was too heavy-handed. Changes: - Add 'supported_image_mimes' config field (checkbox: JPEG/PNG/WebP/GIF) in provider settings. Unchecked = fallback blocklist (GIF filtered on known- problematic gateways). Checked = strict whitelist mode. - sanitize_contexts_by_modalities() now accepts supported_image_mimes param. - When whitelist is provided, only images with MIME types in the list are kept. - When whitelist is None/empty, existing GIF blocklist is used as fallback (backward compatible, preserves #9295 fix). - Schema-driven UI: WebUI auto-generates the checkbox group from config schema. - Update i18n (en-US, zh-CN) for the new field. - Add 4 tests: whitelist filtering, whitelist includes GIF, None fallback, empty-list fallback. Fixes suggestion from @sujoshua and Sourcery review on #9335. Tests: 20 passed (16 existing + 4 new whitelist tests). --- astrbot/core/agent/context/compressor.py | 1 + .../agent/runners/tool_loop_agent_runner.py | 1 + astrbot/core/config/default.py | 17 + astrbot/core/provider/modalities.py | 59 +- .../en-US/features/config-metadata.json | 3357 ++++++++--------- .../zh-CN/features/config-metadata.json | 3305 ++++++++-------- tests/unit/test_modalities_sanitize.py | 71 + 7 files changed, 3285 insertions(+), 3526 deletions(-) diff --git a/astrbot/core/agent/context/compressor.py b/astrbot/core/agent/context/compressor.py index 759604dd93..685d417426 100644 --- a/astrbot/core/agent/context/compressor.py +++ b/astrbot/core/agent/context/compressor.py @@ -268,6 +268,7 @@ async def __call__(self, messages: list[Message]) -> list[Message]: sanitized_summary_contexts, sanitize_stats = sanitize_contexts_by_modalities( summary_contexts, self.provider.provider_config.get("modalities", None), + self.provider.provider_config.get("supported_image_mimes", None), ) log_context_sanitize_stats(sanitize_stats) diff --git a/astrbot/core/agent/runners/tool_loop_agent_runner.py b/astrbot/core/agent/runners/tool_loop_agent_runner.py index 98754f9b6a..44d31484f0 100644 --- a/astrbot/core/agent/runners/tool_loop_agent_runner.py +++ b/astrbot/core/agent/runners/tool_loop_agent_runner.py @@ -595,6 +595,7 @@ def _sanitize_contexts_for_provider( sanitized_contexts, stats = sanitize_contexts_by_modalities( contexts, self.provider.provider_config.get("modalities", None), + self.provider.provider_config.get("supported_image_mimes", None), ) log_context_sanitize_stats(stats) return sanitized_contexts diff --git a/astrbot/core/config/default.py b/astrbot/core/config/default.py index 52e7036320..d454ac9b6f 100644 --- a/astrbot/core/config/default.py +++ b/astrbot/core/config/default.py @@ -2075,6 +2075,23 @@ "render_type": "checkbox", "hint": "模型支持的模态及能力。", }, + "supported_image_mimes": { + "description": "支持的图片 MIME 类型", + "type": "list", + "items": {"type": "string"}, + "options": [ + "image/jpeg", + "image/png", + "image/webp", + "image/gif", + ], + "labels": ["JPEG", "PNG", "WebP", "GIF"], + "render_type": "checkbox", + "hint": ( + "模型支持的图片格式。不勾选时保留全部(仅过滤已知不安全格式如 GIF)。" + "勾选后仅保留勾选的格式。" + ), + }, "custom_headers": { "description": "自定义请求头", "type": "dict", diff --git a/astrbot/core/provider/modalities.py b/astrbot/core/provider/modalities.py index bae20ac31d..b5739bed01 100644 --- a/astrbot/core/provider/modalities.py +++ b/astrbot/core/provider/modalities.py @@ -111,7 +111,22 @@ def _is_unsupported_image_mime(mime: str | None) -> bool: def sanitize_contexts_by_modalities( contexts: Sequence[dict[str, Any] | Message], modalities: list[str] | None, + supported_image_mimes: list[str] | None = None, ) -> tuple[list[dict[str, Any]], ContextSanitizeStats]: + """Sanitize message contexts based on provider capabilities. + + Args: + contexts: The message contexts to sanitize. + modalities: List of modalities the provider supports (e.g. ["text", "image"]). + supported_image_mimes: Whitelist of image MIME types the provider accepts. + When None or empty, a fallback blocklist (_UNSUPPORTED_IMAGE_MIMES) is used + to filter known-problematic formats (e.g. image/gif for some Gemini gateways). + When provided, images with MIME types not in this list are replaced with + "[Image]" placeholders. + + Returns: + Tuple of (sanitized contexts, statistics). + """ if not contexts: return [], ContextSanitizeStats() if not modalities or not isinstance(modalities, list): @@ -125,10 +140,12 @@ def sanitize_contexts_by_modalities( supports_image = "image" in modalities supports_audio = "audio" in modalities supports_tool_use = "tool_use" in modalities - # Even when the provider declares all modalities, we may still need to walk - # the contexts to drop specific image MIME types (e.g. image/gif) that some - # OpenAI-compatible gateways reject. See issue #9295. - needs_mime_pass = supports_image and bool(_UNSUPPORTED_IMAGE_MIMES) + # Determine whether we need a MIME-filtering pass. When a whitelist is + # provided, we always filter; otherwise we fall back to the hardcoded + # blocklist for known-problematic MIME types (e.g. image/gif). + needs_mime_pass = supports_image and ( + bool(supported_image_mimes) or bool(_UNSUPPORTED_IMAGE_MIMES) + ) if supports_image and supports_audio and supports_tool_use and not needs_mime_pass: copied_contexts = [] for msg in contexts: @@ -169,18 +186,28 @@ def sanitize_contexts_by_modalities( for part in content: if isinstance(part, dict): part_type = str(part.get("type", "")).lower() - if part_type in {"image_url", "image"} and ( - not supports_image - or _is_unsupported_image_mime(_extract_image_mime(part)) - ): - # Either the model has no image modality at all, or it - # declares image support but the specific MIME (e.g. - # image/gif) is rejected by some OpenAI-compatible - # gateways (notably certain Gemini endpoints that only - # accept JPEG/PNG/WebP). Replacing the block with a - # placeholder prevents the unsupported bytes from being - # persisted into the session history and poisoning all - # subsequent requests. See issue #9295. + # Determine whether this image part should be dropped. + should_drop_image = False + if part_type in {"image_url", "image"}: + if not supports_image: + # Provider declares no image support at all. + should_drop_image = True + else: + # Provider supports image, but may have MIME restrictions. + mime = _extract_image_mime(part) + if supported_image_mimes: + # Whitelist mode: drop if MIME not in the list. + if mime not in supported_image_mimes: + should_drop_image = True + else: + # Fallback blocklist mode: drop if MIME is known + # to be rejected by some gateways (e.g. image/gif). + if _is_unsupported_image_mime(mime): + should_drop_image = True + if should_drop_image: + # Replacing the block with a placeholder prevents unsupported + # bytes from being persisted into the session history and + # poisoning all subsequent requests. See issue #9295. removed_any_multimodal = True stats.fixed_image_blocks += 1 filtered_parts.append({"type": "text", "text": "[Image]"}) diff --git a/dashboard/src/i18n/locales/en-US/features/config-metadata.json b/dashboard/src/i18n/locales/en-US/features/config-metadata.json index 979be4fed4..ee7a5b5ef4 100644 --- a/dashboard/src/i18n/locales/en-US/features/config-metadata.json +++ b/dashboard/src/i18n/locales/en-US/features/config-metadata.json @@ -1,1788 +1,1637 @@ { - "ai_group": { - "name": "AI", - "agent_runner": { - "description": "Agent Runner", - "hint": "Select the runner for AI conversations. Defaults to AstrBot's built-in Agent runner, which supports knowledge base, persona, and tool calling features. You don't need to modify this section unless you plan to integrate third-party Agent runners like Dify, Coze, or DeerFlow.", - "provider_settings": { - "enable": { - "description": "Enable", - "hint": "Master switch for AI conversations" - }, - "agent_runner_type": { - "description": "Runner", - "labels": [ - "Built-in Agent", - "Dify", - "Coze", - "Alibaba Cloud Bailian Application", - "DeerFlow" - ] - }, - "coze_agent_runner_provider_id": { - "description": "Coze Agent Runner Provider ID" - }, - "dify_agent_runner_provider_id": { - "description": "Dify Agent Runner Provider ID" - }, - "dashscope_agent_runner_provider_id": { - "description": "Alibaba Cloud Bailian Application Agent Runner Provider ID" - }, - "deerflow_agent_runner_provider_id": { - "description": "DeerFlow Agent Runner Provider ID" - } - } - }, - "ai": { - "description": "Model", - "hint": "When using non-built-in Agent runners, the default chat model and default image caption model may not take effect, but some plugins rely on these settings to invoke AI capabilities.", - "provider_settings": { - "default_provider_id": { - "description": "Default Chat Model", - "hint": "Uses the first model when left empty" - }, - "fallback_chat_models": { - "description": "Fallback chat model IDs", - "hint": "When the primary chat model request fails, fallback to these chat models in order." - }, - "request_max_retries": { - "description": "Request Max Retries", - "hint": "Maximum attempts for a single model request when retryable errors occur." - }, - "default_image_caption_provider_id": { - "description": "Default Image Caption Model", - "hint": "Leave empty to disable; useful for non-multimodal models" - }, - "image_caption_prompt": { - "description": "Image Caption Prompt" - } - }, - "provider_stt_settings": { - "enable": { - "description": "Enable Speech-to-Text", - "hint": "Master switch for STT" - }, - "provider_id": { - "description": "Default Speech-to-Text Model", - "hint": "Users can also select session-specific STT models using the /provider command." - } - }, - "provider_tts_settings": { - "enable": { - "description": "Enable Text-to-Speech", - "hint": "Master switch for TTS" - }, - "provider_id": { - "description": "Default Text-to-Speech Model" - }, - "trigger_probability": { - "description": "TTS Trigger Probability" - } - } - }, - "persona": { - "description": "Persona", - "hint": "Set the default persona for AI conversations. Personas can be managed in the Persona tab.", - "provider_settings": { - "default_personality": { - "description": "Default Persona" - } - } - }, - "knowledgebase": { - "description": "Knowledge Base", - "kb_names": { - "description": "Knowledge Base List", - "hint": "Supports multiple selections" - }, - "kb_fusion_top_k": { - "description": "Fusion Search Results Count", - "hint": "Number of results returned after fusing search results from multiple knowledge bases" - }, - "kb_final_top_k": { - "description": "Final Results Count", - "hint": "Number of results retrieved from the knowledge base. Higher values may provide more relevant information but could also introduce noise. Adjust based on actual needs" - }, - "kb_agentic_mode": { - "description": "Agentic Knowledge Base Retrieval", - "hint": "When enabled, knowledge base retrieval becomes an LLM Tool, allowing the model to autonomously decide when to query the knowledge base. Requires the model to support function calling." - } - }, - "websearch": { - "description": "Web Search", - "provider_settings": { - "web_search": { - "description": "Enable Web Search" - }, - "websearch_provider": { - "description": "Web Search Provider" - }, - "websearch_tavily_key": { - "description": "Tavily API Key", - "hint": "Multiple keys can be added for rotation." - }, - "websearch_bocha_key": { - "description": "BoCha API Key", - "hint": "Multiple keys can be added for rotation." + "ai_group": { + "name": "AI", + "agent_runner": { + "description": "Agent Runner", + "hint": "Select the runner for AI conversations. Defaults to AstrBot's built-in Agent runner, which supports knowledge base, persona, and tool calling features. You don't need to modify this section unless you plan to integrate third-party Agent runners like Dify, Coze, or DeerFlow.", + "provider_settings": { + "enable": { + "description": "Enable", + "hint": "Master switch for AI conversations", + }, + "agent_runner_type": { + "description": "Runner", + "labels": [ + "Built-in Agent", + "Dify", + "Coze", + "Alibaba Cloud Bailian Application", + "DeerFlow", + ], + }, + "coze_agent_runner_provider_id": { + "description": "Coze Agent Runner Provider ID" + }, + "dify_agent_runner_provider_id": { + "description": "Dify Agent Runner Provider ID" + }, + "dashscope_agent_runner_provider_id": { + "description": "Alibaba Cloud Bailian Application Agent Runner Provider ID" + }, + "deerflow_agent_runner_provider_id": { + "description": "DeerFlow Agent Runner Provider ID" + }, + }, }, - "websearch_brave_key": { - "description": "Brave Search API Key", - "hint": "Multiple keys can be added for rotation." + "ai": { + "description": "Model", + "hint": "When using non-built-in Agent runners, the default chat model and default image caption model may not take effect, but some plugins rely on these settings to invoke AI capabilities.", + "provider_settings": { + "default_provider_id": { + "description": "Default Chat Model", + "hint": "Uses the first model when left empty", + }, + "fallback_chat_models": { + "description": "Fallback chat model IDs", + "hint": "When the primary chat model request fails, fallback to these chat models in order.", + }, + "request_max_retries": { + "description": "Request Max Retries", + "hint": "Maximum attempts for a single model request when retryable errors occur.", + }, + "default_image_caption_provider_id": { + "description": "Default Image Caption Model", + "hint": "Leave empty to disable; useful for non-multimodal models", + }, + "image_caption_prompt": {"description": "Image Caption Prompt"}, + }, + "provider_stt_settings": { + "enable": { + "description": "Enable Speech-to-Text", + "hint": "Master switch for STT", + }, + "provider_id": { + "description": "Default Speech-to-Text Model", + "hint": "Users can also select session-specific STT models using the /provider command.", + }, + }, + "provider_tts_settings": { + "enable": { + "description": "Enable Text-to-Speech", + "hint": "Master switch for TTS", + }, + "provider_id": {"description": "Default Text-to-Speech Model"}, + "trigger_probability": {"description": "TTS Trigger Probability"}, + }, }, - "websearch_firecrawl_key": { - "description": "Firecrawl API Key", - "hint": "Multiple keys can be added for rotation." + "persona": { + "description": "Persona", + "hint": "Set the default persona for AI conversations. Personas can be managed in the Persona tab.", + "provider_settings": { + "default_personality": {"description": "Default Persona"} + }, }, - "websearch_baidu_app_builder_key": { - "description": "Baidu Qianfan Smart Cloud APP Builder API Key", - "hint": "Reference: [https://console.bce.baidu.com/iam/#/iam/apikey/list](https://console.bce.baidu.com/iam/#/iam/apikey/list)" + "knowledgebase": { + "description": "Knowledge Base", + "kb_names": { + "description": "Knowledge Base List", + "hint": "Supports multiple selections", + }, + "kb_fusion_top_k": { + "description": "Fusion Search Results Count", + "hint": "Number of results returned after fusing search results from multiple knowledge bases", + }, + "kb_final_top_k": { + "description": "Final Results Count", + "hint": "Number of results retrieved from the knowledge base. Higher values may provide more relevant information but could also introduce noise. Adjust based on actual needs", + }, + "kb_agentic_mode": { + "description": "Agentic Knowledge Base Retrieval", + "hint": "When enabled, knowledge base retrieval becomes an LLM Tool, allowing the model to autonomously decide when to query the knowledge base. Requires the model to support function calling.", + }, }, - "web_search_link": { - "description": "Display Source Citations" + "websearch": { + "description": "Web Search", + "provider_settings": { + "web_search": {"description": "Enable Web Search"}, + "websearch_provider": {"description": "Web Search Provider"}, + "websearch_tavily_key": { + "description": "Tavily API Key", + "hint": "Multiple keys can be added for rotation.", + }, + "websearch_bocha_key": { + "description": "BoCha API Key", + "hint": "Multiple keys can be added for rotation.", + }, + "websearch_brave_key": { + "description": "Brave Search API Key", + "hint": "Multiple keys can be added for rotation.", + }, + "websearch_firecrawl_key": { + "description": "Firecrawl API Key", + "hint": "Multiple keys can be added for rotation.", + }, + "websearch_baidu_app_builder_key": { + "description": "Baidu Qianfan Smart Cloud APP Builder API Key", + "hint": "Reference: [https://console.bce.baidu.com/iam/#/iam/apikey/list](https://console.bce.baidu.com/iam/#/iam/apikey/list)", + }, + "web_search_link": {"description": "Display Source Citations"}, + "websearch_exa_key": { + "description": "Exa API Key", + "hint": "Multiple keys can be added for rotation. Get a key at https://dashboard.exa.ai", + }, + }, }, - "websearch_exa_key": { - "description": "Exa API Key", - "hint": "Multiple keys can be added for rotation. Get a key at https://dashboard.exa.ai" - } - } - }, - "file_extract": { - "description": "File Extract", - "provider_settings": { "file_extract": { - "enable": { - "description": "Enable File Extract" - }, - "provider": { - "description": "File Extract Provider" - }, - "moonshotai_api_key": { - "description": "Moonshot AI API Key" - } - } - } - }, - "agent_computer_use": { - "description": "Agent Computer Use", - "hint": "Allows the AstrBot to access and use your computer or an sandbox environment to perform more complex tasks. See: [Computer Use](https://docs.astrbot.app/use/computer.html).", - "provider_settings": { - "computer_use_runtime": { - "description": "Computer Use Runtime", - "hint": "Environment allowed for Agent usage. `local` means the local machine environment, `sandbox` means the sandbox environment, and `none` means no environment is allowed." + "description": "File Extract", + "provider_settings": { + "file_extract": { + "enable": {"description": "Enable File Extract"}, + "provider": {"description": "File Extract Provider"}, + "moonshotai_api_key": {"description": "Moonshot AI API Key"}, + } + }, }, - "computer_use_require_admin": { - "description": "Require AstrBot Admin Permission", - "hint": "When enabled, AstrBot admin permission is required to use computer capabilities. Admins can be added in Platform Config. Use the /sid command to view admin IDs." + "agent_computer_use": { + "description": "Agent Computer Use", + "hint": "Allows the AstrBot to access and use your computer or an sandbox environment to perform more complex tasks. See: [Computer Use](https://docs.astrbot.app/use/computer.html).", + "provider_settings": { + "computer_use_runtime": { + "description": "Computer Use Runtime", + "hint": "Environment allowed for Agent usage. `local` means the local machine environment, `sandbox` means the sandbox environment, and `none` means no environment is allowed.", + }, + "computer_use_require_admin": { + "description": "Require AstrBot Admin Permission", + "hint": "When enabled, AstrBot admin permission is required to use computer capabilities. Admins can be added in Platform Config. Use the /sid command to view admin IDs.", + }, + "sandbox": { + "booter": {"description": "Sandbox Environment Driver"}, + "shipyard_neo_endpoint": { + "description": "Shipyard Neo API Endpoint", + "hint": "Bay API address, default http://127.0.0.1:8114.", + }, + "shipyard_neo_access_token": { + "description": "Shipyard Neo Access Token", + "hint": "Bay API Key (sk-bay-...). Leave empty for auto-discovery from credentials.json.", + }, + "shipyard_neo_profile": { + "description": "Shipyard Neo Profile", + "hint": "Sandbox profile for Shipyard Neo, e.g. python-default. Leave empty to auto-select the most capable profile.", + }, + "shipyard_neo_ttl": { + "description": "Shipyard Neo Sandbox TTL", + "hint": "Sandbox time-to-live in seconds.", + }, + "cua_image": { + "description": "CUA Image", + "hint": "CUA sandbox image or OS type. Defaults to linux. Supported values depend on the installed CUA SDK.", + }, + "cua_os_type": { + "description": "CUA OS Type", + "hint": "CUA sandbox operating system type. Defaults to linux.", + }, + "cua_idle_timeout": { + "description": "CUA Idle Timeout", + "hint": "Idle timeout for CUA sandbox sessions in seconds. When greater than 0, AstrBot proactively shuts down an idle CUA sandbox after that amount of inactivity; 0 disables it.", + }, + "cua_telemetry_enabled": { + "description": "CUA Telemetry", + "hint": "Allow the CUA SDK to send telemetry data. Disabled by default.", + }, + "cua_local": { + "description": "CUA Local Sandbox", + "hint": "Prefer a local CUA sandbox. Enabled by default to avoid requiring CUA_API_KEY for cloud sandboxes. Disable this to use CUA cloud sandboxes.", + }, + "cua_api_key": { + "description": "CUA API Key", + "hint": "CUA cloud sandbox API key. Required only when local sandbox is disabled. You can also provide it via the CUA_API_KEY environment variable.", + }, + "shipyard_endpoint": { + "description": "Shipyard API Endpoint", + "hint": "API access address for Shipyard service.", + }, + "shipyard_access_token": { + "description": "Shipyard Access Token", + "hint": "Access token for accessing Shipyard service.", + }, + "shipyard_ttl": { + "description": "Shipyard Session TTL", + "hint": "Session time-to-live in seconds.", + }, + "shipyard_max_sessions": { + "description": "Shipyard Max Sessions", + "hint": "Maximum number of Shipyard sessions an instance can handle.", + }, + }, + }, }, - "sandbox": { - "booter": { - "description": "Sandbox Environment Driver" - }, - "shipyard_neo_endpoint": { - "description": "Shipyard Neo API Endpoint", - "hint": "Bay API address, default http://127.0.0.1:8114." - }, - "shipyard_neo_access_token": { - "description": "Shipyard Neo Access Token", - "hint": "Bay API Key (sk-bay-...). Leave empty for auto-discovery from credentials.json." - }, - "shipyard_neo_profile": { - "description": "Shipyard Neo Profile", - "hint": "Sandbox profile for Shipyard Neo, e.g. python-default. Leave empty to auto-select the most capable profile." - }, - "shipyard_neo_ttl": { - "description": "Shipyard Neo Sandbox TTL", - "hint": "Sandbox time-to-live in seconds." - }, - "cua_image": { - "description": "CUA Image", - "hint": "CUA sandbox image or OS type. Defaults to linux. Supported values depend on the installed CUA SDK." - }, - "cua_os_type": { - "description": "CUA OS Type", - "hint": "CUA sandbox operating system type. Defaults to linux." - }, - "cua_idle_timeout": { - "description": "CUA Idle Timeout", - "hint": "Idle timeout for CUA sandbox sessions in seconds. When greater than 0, AstrBot proactively shuts down an idle CUA sandbox after that amount of inactivity; 0 disables it." - }, - "cua_telemetry_enabled": { - "description": "CUA Telemetry", - "hint": "Allow the CUA SDK to send telemetry data. Disabled by default." - }, - "cua_local": { - "description": "CUA Local Sandbox", - "hint": "Prefer a local CUA sandbox. Enabled by default to avoid requiring CUA_API_KEY for cloud sandboxes. Disable this to use CUA cloud sandboxes." - }, - "cua_api_key": { - "description": "CUA API Key", - "hint": "CUA cloud sandbox API key. Required only when local sandbox is disabled. You can also provide it via the CUA_API_KEY environment variable." - }, - "shipyard_endpoint": { - "description": "Shipyard API Endpoint", - "hint": "API access address for Shipyard service." - }, - "shipyard_access_token": { - "description": "Shipyard Access Token", - "hint": "Access token for accessing Shipyard service." - }, - "shipyard_ttl": { - "description": "Shipyard Session TTL", - "hint": "Session time-to-live in seconds." - }, - "shipyard_max_sessions": { - "description": "Shipyard Max Sessions", - "hint": "Maximum number of Shipyard sessions an instance can handle." - } - } - } - }, - "proactive_capability": { - "description": "Proactive Agent", - "hint": "AstrBot will wake up, run your tasks, and deliver the results to you. See [Proactive Agent](https://docs.astrbot.app/en/use/proactive-agent.html)", - "provider_settings": { "proactive_capability": { - "add_cron_tools": { - "description": "Enable", - "hint": "When enabled, related tools will be passed to the Agent to implement proactive Agent capabilities. You can tell AstrBot what to do at a future time, and it will be triggered on schedule to execute the task, and report the result back to you." - } - } - } - }, - "truncate_and_compress": { - "hint": "[Context Management](https://docs.astrbot.app/en/use/context-compress.html)", - "description": "Context Management Strategy", - "provider_settings": { - "max_context_length": { - "description": "Max Turns Before Compression", - "hint": "Persistent conversation history is truncated or LLM-compressed by the strategy below only after it exceeds this many turns. Request-time contexts are also constrained by this value before sending. -1 means no turn-based limit." - }, - "dequeue_context_length": { - "description": "Turns to Discard When Limit Exceeded", - "hint": "When history exceeds 'Max Turns Before Compression' and LLM compression is unavailable, discard this many oldest turns at once. Request-time truncation also reuses this value." - }, - "context_limit_reached_strategy": { - "description": "Handling for History Limits or Context Window Pressure", - "labels": [ - "Truncate by Turns", - "Compress by LLM" - ], - "hint": "Persistent conversation history uses this strategy only after exceeding 'Max Turns Before Compression'. Before each request, the same strategy may also protect the in-flight context when tokens approach the model window." - }, - "llm_compress_instruction": { - "description": "Context Compression Instruction", - "hint": "If empty, the default prompt will be used." + "description": "Proactive Agent", + "hint": "AstrBot will wake up, run your tasks, and deliver the results to you. See [Proactive Agent](https://docs.astrbot.app/en/use/proactive-agent.html)", + "provider_settings": { + "proactive_capability": { + "add_cron_tools": { + "description": "Enable", + "hint": "When enabled, related tools will be passed to the Agent to implement proactive Agent capabilities. You can tell AstrBot what to do at a future time, and it will be triggered on schedule to execute the task, and report the result back to you.", + } + } + }, }, - "llm_compress_keep_recent_ratio": { - "description": "Recent Context Token Ratio to Keep", - "hint": "Keep recent exact context by current context token ratio, from 0-0.3. 0.15 means keeping 15%; values above 0 keep at least the latest round." + "truncate_and_compress": { + "hint": "[Context Management](https://docs.astrbot.app/en/use/context-compress.html)", + "description": "Context Management Strategy", + "provider_settings": { + "max_context_length": { + "description": "Max Turns Before Compression", + "hint": "Persistent conversation history is truncated or LLM-compressed by the strategy below only after it exceeds this many turns. Request-time contexts are also constrained by this value before sending. -1 means no turn-based limit.", + }, + "dequeue_context_length": { + "description": "Turns to Discard When Limit Exceeded", + "hint": "When history exceeds 'Max Turns Before Compression' and LLM compression is unavailable, discard this many oldest turns at once. Request-time truncation also reuses this value.", + }, + "context_limit_reached_strategy": { + "description": "Handling for History Limits or Context Window Pressure", + "labels": ["Truncate by Turns", "Compress by LLM"], + "hint": "Persistent conversation history uses this strategy only after exceeding 'Max Turns Before Compression'. Before each request, the same strategy may also protect the in-flight context when tokens approach the model window.", + }, + "llm_compress_instruction": { + "description": "Context Compression Instruction", + "hint": "If empty, the default prompt will be used.", + }, + "llm_compress_keep_recent_ratio": { + "description": "Recent Context Token Ratio to Keep", + "hint": "Keep recent exact context by current context token ratio, from 0-0.3. 0.15 means keeping 15%; values above 0 keep at least the latest round.", + }, + "llm_compress_provider_id": { + "description": "Model Provider ID for Context Compression", + "hint": "When left empty, the current chat model will be used for compression. If the model is unavailable or compression fails, AstrBot falls back to the 'Truncate by Turns' strategy.", + }, + "fallback_max_context_tokens": { + "description": "Fallback context window size", + "hint": "When max_context_tokens is 0 and the model is not in built-in metadata, use this value as the context window size. Default: 128000.", + }, + }, }, - "llm_compress_provider_id": { - "description": "Model Provider ID for Context Compression", - "hint": "When left empty, the current chat model will be used for compression. If the model is unavailable or compression fails, AstrBot falls back to the 'Truncate by Turns' strategy." + "others": { + "description": "Other Settings", + "provider_settings": { + "display_reasoning_text": {"description": "Display Reasoning Content"}, + "llm_safety_mode": { + "description": "Healthy Mode", + "hint": "Add safety guardrails to model replies.", + }, + "safety_mode_strategy": { + "description": "Healthy Mode Strategy", + "hint": "How to apply healthy mode.", + }, + "identifier": { + "description": "User Identification", + "hint": "When enabled, user ID information will be included in the prompt.", + }, + "group_name_display": { + "description": "Display Group Name", + "hint": "When enabled, group name information will be included in the prompt on supported platforms (OneBot v11).", + }, + "datetime_system_prompt": { + "description": "Real-world Time Awareness", + "hint": "When enabled, current time information will be appended to the system prompt.", + }, + "show_tool_use_status": {"description": "Output Function Call Status"}, + "show_tool_call_result": { + "description": "Output Tool Call Results", + "hint": 'Only takes effect when "Output Function Call Status" is enabled, and shows at most 70 characters.', + }, + "buffer_intermediate_messages": { + "description": "Merge Agent Intermediate Messages", + "hint": "When enabled, intermediate text generated during multi-step tool calls in non-streaming mode will be buffered and sent as a single merged reply after the Agent finishes.", + }, + "sanitize_context_by_modalities": { + "description": "Sanitize History by Modalities", + "hint": "When enabled, sanitizes contexts before each LLM request by removing image blocks and tool-call structures that the current provider's modalities do not support (this changes what the model sees).", + }, + "max_quoted_fallback_images": { + "description": "Forwarded Image Fetch Limit", + "hint": "Maximum number of images injected from forwarded-message parsing; extra images are truncated.", + }, + "quoted_message_parser": { + "max_component_chain_depth": { + "description": "Forwarded Rich-Text Parse Depth", + "hint": "Maximum recursive depth when parsing rich-text component chains inside forwarded messages.", + }, + "max_forward_node_depth": { + "description": "Forward Nesting Parse Depth", + "hint": "Maximum recursive depth when parsing nested forwarded nodes.", + }, + "max_forward_fetch": { + "description": "Forward Recursive Fetch Limit", + "hint": "Maximum number of recursive get_forward_msg fetch operations.", + }, + "warn_on_action_failure": { + "description": "Warn on Forward Parse Failure", + "hint": "When enabled, log warnings when all get_msg/get_forward_msg attempts fail.", + }, + }, + "max_agent_step": {"description": "Maximum Tool Call Rounds"}, + "tool_call_timeout": {"description": "Tool Call Timeout (seconds)"}, + "tool_schema_mode": { + "description": "Tool Schema Mode", + "hint": "Skills-like sends name/description first and re-queries for parameters; Full sends the complete schema in one step.", + "labels": ["Skills-like (two-stage)", "Full schema"], + }, + "streaming_response": {"description": "Streaming Output"}, + "unsupported_streaming_strategy": { + "description": "Platforms Without Streaming Support", + "hint": "Select the handling method for platforms that don't support streaming responses. Real-time segmented reply sends content immediately when the system detects segment points like punctuation during streaming reception", + "labels": [ + "Real-time Segmented Reply", + "Disable Streaming Response", + ], + }, + "wake_prefix": { + "description": "Additional LLM Chat Wake Prefix", + "hint": "If the wake prefix is / and the additional chat wake prefix is chat, then /chat is required to trigger LLM requests", + }, + "prompt_prefix": { + "description": "User Prompt", + "hint": "You can use {{prompt}} as a placeholder for user input. If no placeholder is provided, it will be added before the user input.", + }, + "image_compress_enabled": { + "description": "Enable image compression", + "hint": "When enabled, large local images are compressed before being sent to multimodal models.", + }, + "image_compress_options": { + "description": "Image compression settings", + "hint": "Control image resize limits, JPEG quality, and the minimum size threshold for compression.", + "max_size": { + "description": "Maximum edge length", + "hint": "Longest edge of the compressed image in pixels. Images larger than this are resized proportionally.", + }, + "quality": { + "description": "JPEG quality", + "hint": "JPEG output quality from 1 to 100. Higher values preserve more detail but produce larger files.", + }, + }, + "reachability_check": { + "description": "Provider Reachability Check", + "hint": "When running the /provider command, test provider connectivity in parallel. This actively pings models and may consume extra tokens.", + }, + }, + "provider_tts_settings": { + "dual_output": { + "description": "Output Both Voice and Text When TTS is Enabled" + } + }, }, - "fallback_max_context_tokens": { - "description": "Fallback context window size", - "hint": "When max_context_tokens is 0 and the model is not in built-in metadata, use this value as the context window size. Default: 128000." - } - } }, - "others": { - "description": "Other Settings", - "provider_settings": { - "display_reasoning_text": { - "description": "Display Reasoning Content" - }, - "llm_safety_mode": { - "description": "Healthy Mode", - "hint": "Add safety guardrails to model replies." - }, - "safety_mode_strategy": { - "description": "Healthy Mode Strategy", - "hint": "How to apply healthy mode." - }, - "identifier": { - "description": "User Identification", - "hint": "When enabled, user ID information will be included in the prompt." - }, - "group_name_display": { - "description": "Display Group Name", - "hint": "When enabled, group name information will be included in the prompt on supported platforms (OneBot v11)." - }, - "datetime_system_prompt": { - "description": "Real-world Time Awareness", - "hint": "When enabled, current time information will be appended to the system prompt." - }, - "show_tool_use_status": { - "description": "Output Function Call Status" - }, - "show_tool_call_result": { - "description": "Output Tool Call Results", - "hint": "Only takes effect when \"Output Function Call Status\" is enabled, and shows at most 70 characters." - }, - "buffer_intermediate_messages": { - "description": "Merge Agent Intermediate Messages", - "hint": "When enabled, intermediate text generated during multi-step tool calls in non-streaming mode will be buffered and sent as a single merged reply after the Agent finishes." - }, - "sanitize_context_by_modalities": { - "description": "Sanitize History by Modalities", - "hint": "When enabled, sanitizes contexts before each LLM request by removing image blocks and tool-call structures that the current provider's modalities do not support (this changes what the model sees)." - }, - "max_quoted_fallback_images": { - "description": "Forwarded Image Fetch Limit", - "hint": "Maximum number of images injected from forwarded-message parsing; extra images are truncated." - }, - "quoted_message_parser": { - "max_component_chain_depth": { - "description": "Forwarded Rich-Text Parse Depth", - "hint": "Maximum recursive depth when parsing rich-text component chains inside forwarded messages." - }, - "max_forward_node_depth": { - "description": "Forward Nesting Parse Depth", - "hint": "Maximum recursive depth when parsing nested forwarded nodes." - }, - "max_forward_fetch": { - "description": "Forward Recursive Fetch Limit", - "hint": "Maximum number of recursive get_forward_msg fetch operations." - }, - "warn_on_action_failure": { - "description": "Warn on Forward Parse Failure", - "hint": "When enabled, log warnings when all get_msg/get_forward_msg attempts fail." - } - }, - "max_agent_step": { - "description": "Maximum Tool Call Rounds" - }, - "tool_call_timeout": { - "description": "Tool Call Timeout (seconds)" - }, - "tool_schema_mode": { - "description": "Tool Schema Mode", - "hint": "Skills-like sends name/description first and re-queries for parameters; Full sends the complete schema in one step.", - "labels": [ - "Skills-like (two-stage)", - "Full schema" - ] - }, - "streaming_response": { - "description": "Streaming Output" + "platform_group": { + "name": "Platform", + "platform": { + "description": "Message Platform Adapters", + "active_send_mode": {"description": "Use Proactive Send API"}, + "appid": { + "description": "App ID", + "hint": "Required. App ID for the current messaging platform. See the platform integration docs for how to obtain it.", + }, + "callback_server_host": { + "description": "Callback Server Host", + "hint": "Callback server host. Leave empty to disable the callback server.", + }, + "card_template_id": { + "description": "Card Template ID", + "hint": "Optional. DingTalk interactive card template ID. When enabled, streaming replies will use interactive cards.", + }, + "discord_activity_name": { + "description": "Discord Activity Name", + "hint": "Optional Discord activity name. Leave empty to disable.", + }, + "discord_allow_bot_messages": { + "description": "Allow Bot Messages", + "hint": "When enabled, AstrBot will receive messages from other Discord bots. Useful for bot-to-bot communication scenarios (e.g., message forwarding). Disabled by default.", + }, + "discord_command_register": { + "description": "Register Discord slash commands", + "hint": "When enabled, AstrBot will automatically register plugin commands as Discord slash commands", + }, + "discord_proxy": { + "description": "Discord Proxy URL", + "hint": "Optional proxy URL: http://ip:port", + }, + "discord_token": { + "description": "Discord Bot Token", + "hint": "Enter your Discord Bot Token here.", + }, + "enable": { + "description": "Enable", + "hint": "Whether to enable this adapter. Disabled adapters will not receive messages.", + }, + "enable_group_c2c": { + "description": "Enable Message List Private Chat", + "hint": "When enabled, the bot can receive private chats from QQ message list. You may need to add the bot as a friend by scanning a QR code in the QQ bot platform. See docs.", + }, + "enable_guild_direct_message": { + "description": "Enable Guild Direct Messages", + "hint": "When enabled, the bot can receive guild direct messages.", + }, + "id": {"description": "Bot Name", "hint": "Bot name"}, + "is_sandbox": {"description": "Sandbox Mode"}, + "kf_name": { + "description": "WeChat Customer Service Account Name", + "hint": "Optional. Customer service account name (not ID). Get it at https://kf.weixin.qq.com/kf/frame#/accounts", + }, + "lark_connection_mode": { + "description": "Subscription Mode", + "labels": ["Long Connection Mode", "Webhook Server Mode"], + }, + "lark_encrypt_key": { + "description": "Encrypt Key", + "hint": "Encryption key for decrypting Lark callback data.", + }, + "lark_verification_token": { + "description": "Verification Token", + "hint": "Token for verifying Lark callback requests.", + }, + "misskey_allow_insecure_downloads": { + "description": "Allow Insecure Downloads (Disable SSL Verification)", + "hint": "If remote servers have certificate issues, SSL verification will be disabled as a fallback. Use only when necessary due to security risks.", + }, + "misskey_default_visibility": { + "description": "Default Post Visibility", + "hint": "Default visibility for bot posts. public: public, home: home timeline, followers: followers only.", + }, + "misskey_download_chunk_size": { + "description": "Stream Download Chunk Size (bytes)", + "hint": "Bytes read per chunk during streaming download and MD5 calculation. Too small increases overhead; too large uses more memory.", + }, + "misskey_download_timeout": { + "description": "Remote Download Timeout (seconds)", + "hint": "Timeout for downloading remote files (seconds), used when falling back to local upload.", + }, + "misskey_enable_chat": { + "description": "Enable Chat Message Responses", + "hint": "When enabled, the bot listens and responds to private chat messages.", + }, + "misskey_enable_file_upload": { + "description": "Enable File Upload to Misskey", + "hint": "When enabled, the adapter uploads files in message chains to Misskey. URL files try server-side upload first; if async upload fails, it falls back to local download and upload.", + }, + "misskey_instance_url": { + "description": "Misskey Instance URL", + "hint": "e.g. https://misskey.example. The Misskey instance where the bot account lives.", + }, + "misskey_local_only": { + "description": "Local Only (No Federation)", + "hint": "When enabled, bot posts are visible only on this instance and are not federated.", + }, + "misskey_max_download_bytes": { + "description": "Max Download Size (bytes)", + "hint": "To limit download size to prevent OOM, set the maximum bytes; empty or null means no limit.", + }, + "misskey_token": { + "description": "Misskey Access Token", + "hint": "API access token generated in the connection service settings.", + }, + "misskey_upload_concurrency": { + "description": "Upload Concurrency Limit", + "hint": "Max number of concurrent upload tasks (integer, default 3).", + }, + "misskey_upload_folder": { + "description": "Target Drive Folder ID", + "hint": "Optional: ID of the target folder in Misskey drive. Leave empty to use the root folder.", + }, + "port": { + "description": "Callback Server Port", + "hint": "Callback server port. Leave empty to disable the callback server.", + }, + "satori_api_base_url": { + "description": "Satori API Endpoint", + "hint": "Base URL for the Satori API.", + }, + "satori_auto_reconnect": { + "description": "Enable Auto Reconnect", + "hint": "Automatically reconnect the WebSocket when disconnected.", + }, + "satori_endpoint": { + "description": "Satori WebSocket Endpoint", + "hint": "WebSocket endpoint for Satori events.", + }, + "satori_heartbeat_interval": { + "description": "Satori Heartbeat Interval", + "hint": "Interval in seconds between heartbeat messages.", + }, + "satori_reconnect_delay": { + "description": "Satori Reconnect Delay", + "hint": "Delay before attempting to reconnect (seconds).", + }, + "satori_token": { + "description": "Satori Token", + "hint": "Token for Satori API authentication.", + }, + "secret": {"description": "Secret", "hint": "Required."}, + "slack_connection_mode": { + "description": "Slack Connection Mode", + "hint": "The connection mode for Slack. `webhook` uses a webhook server, `socket` uses Slack's Socket Mode.", + }, + "slack_webhook_host": { + "description": "Slack Webhook Host", + "hint": "Only valid when Slack connection mode is `webhook`.", + }, + "slack_webhook_path": { + "description": "Slack Webhook Path", + "hint": "Only valid when Slack connection mode is `webhook`.", + }, + "slack_webhook_port": { + "description": "Slack Webhook Port", + "hint": "Only valid when Slack connection mode is `webhook`.", + }, + "telegram_command_auto_refresh": { + "description": "Telegram Command Auto Refresh", + "hint": "When enabled, AstrBot automatically refreshes Telegram commands at runtime. (Setting this alone has no effect)", + }, + "telegram_command_register": { + "description": "Telegram Command Registration", + "hint": "When enabled, AstrBot automatically registers Telegram commands.", + }, + "telegram_command_register_interval": { + "description": "Telegram Command Auto Refresh Interval", + "hint": "Telegram command auto-refresh interval in seconds.", + }, + "telegram_polling_restart_delay": { + "description": "Telegram Polling Restart Delay", + "hint": "Waiting time in seconds when the polling loop needs to restart after unexpected exits. Defaults to 5s.", + }, + "telegram_token": { + "description": "Bot Token", + "hint": "If you are in mainland China, set a proxy or change api_base in Other Settings.", + }, + "mattermost_url": { + "description": "Mattermost URL", + "hint": "Mattermost service URL, for example https://chat.example.com.", + }, + "mattermost_bot_token": { + "description": "Mattermost Bot Token", + "hint": "The access token generated after creating a bot account in Mattermost.", + }, + "mattermost_reconnect_delay": { + "description": "Mattermost Reconnect Delay", + "hint": "Delay in seconds before reconnecting after the WebSocket disconnects. Defaults to 5 seconds.", + }, + "type": {"description": "Adapter Type"}, + "unified_webhook_mode": { + "description": "Unified Webhook Mode", + "hint": "When enabled, use AstrBot unified webhook entry without opening a separate port. Callback URL is /api/v1/webhooks/platforms/{webhook_uuid}.", + }, + "webhook_uuid": { + "description": "Webhook UUID", + "hint": "Unique identifier for unified webhook mode; generated when creating the platform.", + }, + "wecom_ai_bot_name": { + "description": "WeCom AI Bot Name", + "hint": "Must be correct; otherwise some commands won't work.", + }, + "wecom_ai_bot_connection_mode": { + "description": "WeCom AI Bot Connection Mode", + "hint": "Webhook mode requires Token/EncodingAESKey; long_connection mode requires BotID/Secret.", + }, + "wecomaibot_friend_message_welcome_text": { + "description": "WeCom AI Bot DM Welcome Message", + "hint": "When a user enters a DM session on that day, reply with a welcome message. Leave empty to disable.", + }, + "wecomaibot_init_respond_text": { + "description": "WeCom AI Bot Initial Response Text", + "hint": "First reply when the bot receives a message. Leave empty to disable.", + }, + "wecomaibot_token": { + "description": "WeCom AI Bot Token", + "hint": "Used for authentication in webhook callback mode.", + }, + "wecomaibot_encoding_aes_key": { + "description": "WeCom AI Bot EncodingAESKey", + "hint": "Used for message encryption/decryption in webhook callback mode.", + }, + "wecomaibot_ws_bot_id": { + "description": "Long Connection BotID", + "hint": "BotID credential for WeCom AI Bot long connection mode.", + }, + "wecomaibot_ws_secret": { + "description": "Long Connection Secret", + "hint": "Secret credential for WeCom AI Bot long connection mode.", + }, + "wecomaibot_ws_url": { + "description": "Long Connection WebSocket URL", + "hint": "Default is wss://openws.work.weixin.qq.com and usually does not need changes.", + }, + "wecomaibot_heartbeat_interval": { + "description": "Long Connection Heartbeat Interval", + "hint": "Heartbeat interval (seconds) in long connection mode. 30 seconds is recommended.", + }, + "wpp_active_message_poll": { + "description": "Enable Proactive Message Polling", + "hint": "Only enable if WeChat messages are not syncing to AstrBot on time. Disabled by default.", + }, + "wpp_active_message_poll_interval": { + "description": "Proactive Message Poll Interval", + "hint": "Interval in seconds, default 3, should not exceed 60 or it may be considered old messages.", + }, + "ws_reverse_host": { + "description": "Reverse WebSocket Host", + "hint": "AstrBot acts as the server.", + }, + "ws_reverse_port": {"description": "Reverse WebSocket Port"}, + "ws_reverse_token": { + "description": "Reverse WebSocket Token", + "hint": "Reverse WebSocket token. If not set, token verification is disabled.", + }, + "msg_push_webhook_url": { + "description": "WeCom Message Push Webhook URL", + "hint": "Used for proactive message push. It is strongly recommended to set this for a better message sending experience.", + }, + "only_use_webhook_url_to_send": { + "description": "Send Replies via Webhook Only", + "hint": "When enabled, all WeCom AI Bot replies are sent through msg_push_webhook_url. The message push webhook supports more message types (such as images, files, etc.). If you do not need the typing effect, it is strongly recommended to use this option. ", + }, + "weixin_oc_base_url": { + "description": "API Base URL", + "hint": "Default: https://ilinkai.weixin.qq.com", + }, + "weixin_oc_bot_type": { + "description": "bot_type (QR login parameter)", + "hint": "Default: 3", + }, + "weixin_oc_qr_poll_interval": { + "description": "QR status poll interval (seconds)", + "hint": "Polling interval in seconds for QR code status.", + }, + "weixin_oc_long_poll_timeout_ms": { + "description": "getUpdates long-poll timeout (ms)", + "hint": "Timeout parameter for polling messages.", + }, + "weixin_oc_api_timeout_ms": { + "description": "HTTP timeout (ms)", + "hint": "Generic API request timeout.", + }, + "weixin_oc_token": { + "description": "Token after login (optional)", + "hint": "Automatically written after QR login; can be filled manually for advanced scenarios.", + }, + "kook_bot_token": { + "description": "Bot Token", + "type": "string", + "hint": "Required. The Bot Token obtained from the KOOK Developer Platform.", + }, + "kook_reconnect_delay": { + "description": "Reconnect Delay", + "type": "int", + "hint": "Delay time for reconnection (seconds), using an exponential backoff strategy.", + }, + "kook_max_reconnect_delay": { + "description": "Max Reconnect Delay", + "type": "int", + "hint": "The maximum value for reconnection delay (seconds).", + }, + "kook_max_retry_delay": { + "description": "Max Retry Delay", + "type": "int", + "hint": "The maximum delay time for retries (seconds).", + }, + "kook_heartbeat_interval": { + "description": "Heartbeat Interval", + "type": "int", + "hint": "The interval time for heartbeat detection (seconds).", + }, + "kook_heartbeat_timeout": { + "description": "Heartbeat Timeout", + "type": "int", + "hint": "The timeout duration for heartbeat detection (seconds).", + }, + "kook_max_heartbeat_failures": { + "description": "Max Heartbeat Failures", + "type": "int", + "hint": "Maximum allowed heartbeat failures; the connection will be dropped if exceeded.", + }, + "kook_max_consecutive_failures": { + "description": "Max Consecutive Failures", + "type": "int", + "hint": "Maximum allowed consecutive failures; retries will stop if exceeded.", + }, }, - "unsupported_streaming_strategy": { - "description": "Platforms Without Streaming Support", - "hint": "Select the handling method for platforms that don't support streaming responses. Real-time segmented reply sends content immediately when the system detects segment points like punctuation during streaming reception", - "labels": [ - "Real-time Segmented Reply", - "Disable Streaming Response" - ] + "general": { + "description": "General", + "admins_id": {"description": "Administrator IDs"}, + "platform_settings": { + "unique_session": { + "description": "Isolate Sessions", + "hint": "When enabled, group members have independent contexts.", + }, + "friend_message_needs_wake_prefix": { + "description": "Private Messages Require Wake Word" + }, + "reply_prefix": {"description": "Reply Text Prefix"}, + "reply_with_mention": {"description": "Mention Sender in Reply"}, + "reply_with_quote": {"description": "Quote Sender's Message in Reply"}, + "forward_threshold": { + "description": "Forward Message Word Count Threshold" + }, + "empty_mention_waiting": { + "description": "Trigger Waiting on Mention-only Messages" + }, + }, + "wake_prefix": {"description": "Wake Word"}, + "disable_builtin_commands": { + "description": "Disable Built-in Commands", + "hint": "Disable all built-in AstrBot commands such as help, sid, new, etc.", + }, }, - "wake_prefix": { - "description": "Additional LLM Chat Wake Prefix", - "hint": "If the wake prefix is / and the additional chat wake prefix is chat, then /chat is required to trigger LLM requests" + "whitelist": { + "description": "Whitelist", + "platform_settings": { + "enable_id_white_list": { + "description": "Enable Whitelist", + "hint": "When enabled, only sessions in the whitelist will be responded to. If the whitelist is empty, the whitelist is disabled and all IDs are allowed.", + }, + "id_whitelist": { + "description": "Whitelist ID List", + "hint": "Use /sid to get IDs. If the list is empty, it means whitelist is disabled (all IDs are in the whitelist).", + }, + "id_whitelist_log": { + "description": "Output Logs", + "hint": "When enabled, INFO level logs will be output when a message doesn't pass the whitelist.", + }, + "wl_ignore_admin_on_group": { + "description": "Administrator Group Messages Bypass ID Whitelist" + }, + "wl_ignore_admin_on_friend": { + "description": "Administrator Private Messages Bypass ID Whitelist" + }, + }, }, - "prompt_prefix": { - "description": "User Prompt", - "hint": "You can use {{prompt}} as a placeholder for user input. If no placeholder is provided, it will be added before the user input." + "rate_limit": { + "description": "Rate Limiting", + "platform_settings": { + "rate_limit": { + "time": {"description": "Message Rate Limit Time (seconds)"}, + "count": {"description": "Message Rate Limit Count"}, + "strategy": {"description": "Rate Limit Strategy"}, + } + }, }, - "image_compress_enabled": { - "description": "Enable image compression", - "hint": "When enabled, large local images are compressed before being sent to multimodal models." + "content_safety": { + "description": "Content Safety", + "content_safety": { + "also_use_in_response": { + "description": "Also Check Model Response Content" + }, + "baidu_aip": { + "enable": { + "description": "Use Baidu Content Safety Moderation", + "hint": "You need to manually install the baidu-aip library.", + }, + "app_id": {"description": "App ID"}, + "api_key": {"description": "API Key"}, + "secret_key": {"description": "Secret Key"}, + }, + "internal_keywords": { + "enable": {"description": "Keyword Check"}, + "extra_keywords": { + "description": "Additional Keywords", + "hint": "Additional keyword blocklist, supports regular expressions.", + }, + }, + }, }, - "image_compress_options": { - "description": "Image compression settings", - "hint": "Control image resize limits, JPEG quality, and the minimum size threshold for compression.", - "max_size": { - "description": "Maximum edge length", - "hint": "Longest edge of the compressed image in pixels. Images larger than this are resized proportionally." - }, - "quality": { - "description": "JPEG quality", - "hint": "JPEG output quality from 1 to 100. Higher values preserve more detail but produce larger files." - } + "t2i": { + "description": "Text-to-Image", + "t2i": {"description": "Text-to-Image Output"}, + "t2i_word_threshold": {"description": "Text-to-Image Word Count Threshold"}, + }, + "others": { + "description": "Other Settings", + "platform_settings": { + "ignore_bot_self_message": {"description": "Ignore Bot's Own Messages"}, + "ignore_at_all": {"description": "Ignore @All Events"}, + "no_permission_reply": { + "description": "Reply When User Has Insufficient Permissions" + }, + }, + "platform_specific": { + "lark": { + "pre_ack_emoji": { + "enable": { + "description": "[Lark] Enable Pre-acknowledgment Emoji" + }, + "emojis": { + "description": "Emoji List (Lark Emoji Enum Names)", + "hint": "Emoji enum names reference: [https://open.feishu.cn/document/server-docs/im-v1/message-reaction/emojis-introduce](https://open.feishu.cn/document/server-docs/im-v1/message-reaction/emojis-introduce)", + }, + } + }, + "telegram": { + "pre_ack_emoji": { + "enable": { + "description": "[Telegram] Enable Pre-acknowledgment Emoji" + }, + "emojis": { + "description": "Emoji List (Unicode)", + "hint": "Telegram only supports a fixed reaction set, reference: [https://gist.github.com/Soulter/3f22c8e5f9c7e152e967e8bc28c97fc9](https://gist.github.com/Soulter/3f22c8e5f9c7e152e967e8bc28c97fc9)", + }, + } + }, + "discord": { + "pre_ack_emoji": { + "enable": { + "description": "[Discord] Enable Pre-acknowledgment Emoji" + }, + "emojis": { + "description": "Emoji List (Unicode or Custom Emoji Name)", + "hint": "Enter Unicode emoji symbols, e.g., 👍, 🤔, ⏳", + }, + } + }, + }, }, - "reachability_check": { - "description": "Provider Reachability Check", - "hint": "When running the /provider command, test provider connectivity in parallel. This actively pings models and may consume extra tokens." - } - }, - "provider_tts_settings": { - "dual_output": { - "description": "Output Both Voice and Text When TTS is Enabled" - } - } - } - }, - "platform_group": { - "name": "Platform", - "platform": { - "description": "Message Platform Adapters", - "active_send_mode": { - "description": "Use Proactive Send API" - }, - "appid": { - "description": "App ID", - "hint": "Required. App ID for the current messaging platform. See the platform integration docs for how to obtain it." - }, - "callback_server_host": { - "description": "Callback Server Host", - "hint": "Callback server host. Leave empty to disable the callback server." - }, - "card_template_id": { - "description": "Card Template ID", - "hint": "Optional. DingTalk interactive card template ID. When enabled, streaming replies will use interactive cards." - }, - "discord_activity_name": { - "description": "Discord Activity Name", - "hint": "Optional Discord activity name. Leave empty to disable." - }, - "discord_allow_bot_messages": { - "description": "Allow Bot Messages", - "hint": "When enabled, AstrBot will receive messages from other Discord bots. Useful for bot-to-bot communication scenarios (e.g., message forwarding). Disabled by default." - }, - "discord_command_register": { - "description": "Register Discord slash commands", - "hint": "When enabled, AstrBot will automatically register plugin commands as Discord slash commands" - }, - "discord_proxy": { - "description": "Discord Proxy URL", - "hint": "Optional proxy URL: http://ip:port" - }, - "discord_token": { - "description": "Discord Bot Token", - "hint": "Enter your Discord Bot Token here." - }, - "enable": { - "description": "Enable", - "hint": "Whether to enable this adapter. Disabled adapters will not receive messages." - }, - "enable_group_c2c": { - "description": "Enable Message List Private Chat", - "hint": "When enabled, the bot can receive private chats from QQ message list. You may need to add the bot as a friend by scanning a QR code in the QQ bot platform. See docs." - }, - "enable_guild_direct_message": { - "description": "Enable Guild Direct Messages", - "hint": "When enabled, the bot can receive guild direct messages." - }, - "id": { - "description": "Bot Name", - "hint": "Bot name" - }, - "is_sandbox": { - "description": "Sandbox Mode" - }, - "kf_name": { - "description": "WeChat Customer Service Account Name", - "hint": "Optional. Customer service account name (not ID). Get it at https://kf.weixin.qq.com/kf/frame#/accounts" - }, - "lark_connection_mode": { - "description": "Subscription Mode", - "labels": [ - "Long Connection Mode", - "Webhook Server Mode" - ] - }, - "lark_encrypt_key": { - "description": "Encrypt Key", - "hint": "Encryption key for decrypting Lark callback data." - }, - "lark_verification_token": { - "description": "Verification Token", - "hint": "Token for verifying Lark callback requests." - }, - "misskey_allow_insecure_downloads": { - "description": "Allow Insecure Downloads (Disable SSL Verification)", - "hint": "If remote servers have certificate issues, SSL verification will be disabled as a fallback. Use only when necessary due to security risks." - }, - "misskey_default_visibility": { - "description": "Default Post Visibility", - "hint": "Default visibility for bot posts. public: public, home: home timeline, followers: followers only." - }, - "misskey_download_chunk_size": { - "description": "Stream Download Chunk Size (bytes)", - "hint": "Bytes read per chunk during streaming download and MD5 calculation. Too small increases overhead; too large uses more memory." - }, - "misskey_download_timeout": { - "description": "Remote Download Timeout (seconds)", - "hint": "Timeout for downloading remote files (seconds), used when falling back to local upload." - }, - "misskey_enable_chat": { - "description": "Enable Chat Message Responses", - "hint": "When enabled, the bot listens and responds to private chat messages." - }, - "misskey_enable_file_upload": { - "description": "Enable File Upload to Misskey", - "hint": "When enabled, the adapter uploads files in message chains to Misskey. URL files try server-side upload first; if async upload fails, it falls back to local download and upload." - }, - "misskey_instance_url": { - "description": "Misskey Instance URL", - "hint": "e.g. https://misskey.example. The Misskey instance where the bot account lives." - }, - "misskey_local_only": { - "description": "Local Only (No Federation)", - "hint": "When enabled, bot posts are visible only on this instance and are not federated." - }, - "misskey_max_download_bytes": { - "description": "Max Download Size (bytes)", - "hint": "To limit download size to prevent OOM, set the maximum bytes; empty or null means no limit." - }, - "misskey_token": { - "description": "Misskey Access Token", - "hint": "API access token generated in the connection service settings." - }, - "misskey_upload_concurrency": { - "description": "Upload Concurrency Limit", - "hint": "Max number of concurrent upload tasks (integer, default 3)." - }, - "misskey_upload_folder": { - "description": "Target Drive Folder ID", - "hint": "Optional: ID of the target folder in Misskey drive. Leave empty to use the root folder." - }, - "port": { - "description": "Callback Server Port", - "hint": "Callback server port. Leave empty to disable the callback server." - }, - "satori_api_base_url": { - "description": "Satori API Endpoint", - "hint": "Base URL for the Satori API." - }, - "satori_auto_reconnect": { - "description": "Enable Auto Reconnect", - "hint": "Automatically reconnect the WebSocket when disconnected." - }, - "satori_endpoint": { - "description": "Satori WebSocket Endpoint", - "hint": "WebSocket endpoint for Satori events." - }, - "satori_heartbeat_interval": { - "description": "Satori Heartbeat Interval", - "hint": "Interval in seconds between heartbeat messages." - }, - "satori_reconnect_delay": { - "description": "Satori Reconnect Delay", - "hint": "Delay before attempting to reconnect (seconds)." - }, - "satori_token": { - "description": "Satori Token", - "hint": "Token for Satori API authentication." - }, - "secret": { - "description": "Secret", - "hint": "Required." - }, - "slack_connection_mode": { - "description": "Slack Connection Mode", - "hint": "The connection mode for Slack. `webhook` uses a webhook server, `socket` uses Slack's Socket Mode." - }, - "slack_webhook_host": { - "description": "Slack Webhook Host", - "hint": "Only valid when Slack connection mode is `webhook`." - }, - "slack_webhook_path": { - "description": "Slack Webhook Path", - "hint": "Only valid when Slack connection mode is `webhook`." - }, - "slack_webhook_port": { - "description": "Slack Webhook Port", - "hint": "Only valid when Slack connection mode is `webhook`." - }, - "telegram_command_auto_refresh": { - "description": "Telegram Command Auto Refresh", - "hint": "When enabled, AstrBot automatically refreshes Telegram commands at runtime. (Setting this alone has no effect)" - }, - "telegram_command_register": { - "description": "Telegram Command Registration", - "hint": "When enabled, AstrBot automatically registers Telegram commands." - }, - "telegram_command_register_interval": { - "description": "Telegram Command Auto Refresh Interval", - "hint": "Telegram command auto-refresh interval in seconds." - }, - "telegram_polling_restart_delay": { - "description": "Telegram Polling Restart Delay", - "hint": "Waiting time in seconds when the polling loop needs to restart after unexpected exits. Defaults to 5s." - }, - "telegram_token": { - "description": "Bot Token", - "hint": "If you are in mainland China, set a proxy or change api_base in Other Settings." - }, - "mattermost_url": { - "description": "Mattermost URL", - "hint": "Mattermost service URL, for example https://chat.example.com." - }, - "mattermost_bot_token": { - "description": "Mattermost Bot Token", - "hint": "The access token generated after creating a bot account in Mattermost." - }, - "mattermost_reconnect_delay": { - "description": "Mattermost Reconnect Delay", - "hint": "Delay in seconds before reconnecting after the WebSocket disconnects. Defaults to 5 seconds." - }, - "type": { - "description": "Adapter Type" - }, - "unified_webhook_mode": { - "description": "Unified Webhook Mode", - "hint": "When enabled, use AstrBot unified webhook entry without opening a separate port. Callback URL is /api/v1/webhooks/platforms/{webhook_uuid}." - }, - "webhook_uuid": { - "description": "Webhook UUID", - "hint": "Unique identifier for unified webhook mode; generated when creating the platform." - }, - "wecom_ai_bot_name": { - "description": "WeCom AI Bot Name", - "hint": "Must be correct; otherwise some commands won't work." - }, - "wecom_ai_bot_connection_mode": { - "description": "WeCom AI Bot Connection Mode", - "hint": "Webhook mode requires Token/EncodingAESKey; long_connection mode requires BotID/Secret." - }, - "wecomaibot_friend_message_welcome_text": { - "description": "WeCom AI Bot DM Welcome Message", - "hint": "When a user enters a DM session on that day, reply with a welcome message. Leave empty to disable." - }, - "wecomaibot_init_respond_text": { - "description": "WeCom AI Bot Initial Response Text", - "hint": "First reply when the bot receives a message. Leave empty to disable." - }, - "wecomaibot_token": { - "description": "WeCom AI Bot Token", - "hint": "Used for authentication in webhook callback mode." - }, - "wecomaibot_encoding_aes_key": { - "description": "WeCom AI Bot EncodingAESKey", - "hint": "Used for message encryption/decryption in webhook callback mode." - }, - "wecomaibot_ws_bot_id": { - "description": "Long Connection BotID", - "hint": "BotID credential for WeCom AI Bot long connection mode." - }, - "wecomaibot_ws_secret": { - "description": "Long Connection Secret", - "hint": "Secret credential for WeCom AI Bot long connection mode." - }, - "wecomaibot_ws_url": { - "description": "Long Connection WebSocket URL", - "hint": "Default is wss://openws.work.weixin.qq.com and usually does not need changes." - }, - "wecomaibot_heartbeat_interval": { - "description": "Long Connection Heartbeat Interval", - "hint": "Heartbeat interval (seconds) in long connection mode. 30 seconds is recommended." - }, - "wpp_active_message_poll": { - "description": "Enable Proactive Message Polling", - "hint": "Only enable if WeChat messages are not syncing to AstrBot on time. Disabled by default." - }, - "wpp_active_message_poll_interval": { - "description": "Proactive Message Poll Interval", - "hint": "Interval in seconds, default 3, should not exceed 60 or it may be considered old messages." - }, - "ws_reverse_host": { - "description": "Reverse WebSocket Host", - "hint": "AstrBot acts as the server." - }, - "ws_reverse_port": { - "description": "Reverse WebSocket Port" - }, - "ws_reverse_token": { - "description": "Reverse WebSocket Token", - "hint": "Reverse WebSocket token. If not set, token verification is disabled." - }, - "msg_push_webhook_url": { - "description": "WeCom Message Push Webhook URL", - "hint": "Used for proactive message push. It is strongly recommended to set this for a better message sending experience." - }, - "only_use_webhook_url_to_send": { - "description": "Send Replies via Webhook Only", - "hint": "When enabled, all WeCom AI Bot replies are sent through msg_push_webhook_url. The message push webhook supports more message types (such as images, files, etc.). If you do not need the typing effect, it is strongly recommended to use this option. " - }, - "weixin_oc_base_url": { - "description": "API Base URL", - "hint": "Default: https://ilinkai.weixin.qq.com" - }, - "weixin_oc_bot_type": { - "description": "bot_type (QR login parameter)", - "hint": "Default: 3" - }, - "weixin_oc_qr_poll_interval": { - "description": "QR status poll interval (seconds)", - "hint": "Polling interval in seconds for QR code status." - }, - "weixin_oc_long_poll_timeout_ms": { - "description": "getUpdates long-poll timeout (ms)", - "hint": "Timeout parameter for polling messages." - }, - "weixin_oc_api_timeout_ms": { - "description": "HTTP timeout (ms)", - "hint": "Generic API request timeout." - }, - "weixin_oc_token": { - "description": "Token after login (optional)", - "hint": "Automatically written after QR login; can be filled manually for advanced scenarios." - }, - "kook_bot_token": { - "description": "Bot Token", - "type": "string", - "hint": "Required. The Bot Token obtained from the KOOK Developer Platform." - }, - "kook_reconnect_delay": { - "description": "Reconnect Delay", - "type": "int", - "hint": "Delay time for reconnection (seconds), using an exponential backoff strategy." - }, - "kook_max_reconnect_delay": { - "description": "Max Reconnect Delay", - "type": "int", - "hint": "The maximum value for reconnection delay (seconds)." - }, - "kook_max_retry_delay": { - "description": "Max Retry Delay", - "type": "int", - "hint": "The maximum delay time for retries (seconds)." - }, - "kook_heartbeat_interval": { - "description": "Heartbeat Interval", - "type": "int", - "hint": "The interval time for heartbeat detection (seconds)." - }, - "kook_heartbeat_timeout": { - "description": "Heartbeat Timeout", - "type": "int", - "hint": "The timeout duration for heartbeat detection (seconds)." - }, - "kook_max_heartbeat_failures": { - "description": "Max Heartbeat Failures", - "type": "int", - "hint": "Maximum allowed heartbeat failures; the connection will be dropped if exceeded." - }, - "kook_max_consecutive_failures": { - "description": "Max Consecutive Failures", - "type": "int", - "hint": "Maximum allowed consecutive failures; retries will stop if exceeded." - } }, - "general": { - "description": "General", - "admins_id": { - "description": "Administrator IDs" - }, - "platform_settings": { - "unique_session": { - "description": "Isolate Sessions", - "hint": "When enabled, group members have independent contexts." - }, - "friend_message_needs_wake_prefix": { - "description": "Private Messages Require Wake Word" - }, - "reply_prefix": { - "description": "Reply Text Prefix" - }, - "reply_with_mention": { - "description": "Mention Sender in Reply" - }, - "reply_with_quote": { - "description": "Quote Sender's Message in Reply" - }, - "forward_threshold": { - "description": "Forward Message Word Count Threshold" + "plugin_group": { + "name": "Plugin", + "plugin": { + "description": "Plugins", + "plugin_set": { + "description": "Available Plugins", + "hint": "All non-disabled plugins are enabled by default. If a plugin is disabled on the plugins page, selections here will not take effect.", + }, }, - "empty_mention_waiting": { - "description": "Trigger Waiting on Mention-only Messages" - } - }, - "wake_prefix": { - "description": "Wake Word" - }, - "disable_builtin_commands": { - "description": "Disable Built-in Commands", - "hint": "Disable all built-in AstrBot commands such as help, sid, new, etc." - } }, - "whitelist": { - "description": "Whitelist", - "platform_settings": { - "enable_id_white_list": { - "description": "Enable Whitelist", - "hint": "When enabled, only sessions in the whitelist will be responded to. If the whitelist is empty, the whitelist is disabled and all IDs are allowed." - }, - "id_whitelist": { - "description": "Whitelist ID List", - "hint": "Use /sid to get IDs. If the list is empty, it means whitelist is disabled (all IDs are in the whitelist)." - }, - "id_whitelist_log": { - "description": "Output Logs", - "hint": "When enabled, INFO level logs will be output when a message doesn't pass the whitelist." + "ext_group": { + "name": "Ext.", + "segmented_reply": { + "description": "Segmented Reply", + "platform_settings": { + "segmented_reply": { + "enable": {"description": "Enable Segmented Reply"}, + "only_llm_result": {"description": "Segment Only LLM Results"}, + "interval_method": { + "description": "Interval Method", + "hint": "random uses a random delay. log calculates delay by message length: $y=log_{log\\_base}(x)$, where x is word count and y is in seconds.", + }, + "interval": { + "description": "Random Interval Time", + "hint": "Format: minimum,maximum (e.g., 1.5,3.5)", + }, + "log_base": { + "description": "Logarithm Base", + "hint": "Base for logarithmic intervals, defaults to 2.6. Value range: 1.0-10.0.", + }, + "words_count_threshold": { + "description": "Segmented Reply Word Count Threshold", + "hint": "Segmented reply word count threshold. Only messages with less than this number of words will be segmented, and messages with more than this number of words will be sent directly (not segmented).", + }, + "split_mode": { + "description": "Split Mode", + "hint": "Used to segment a message. By default, it will be separated by punctuation marks like period, question mark, etc. For example, filling `[。?!]` will remove all periods, question marks, and exclamation marks. re.findall(r'', text)", + "labels": ["Regex", "Words List"], + }, + "regex": { + "description": "Segmentation Regular Expression", + "hint": "Used to identify split points with a regular expression. Prefer patterns that match separators.", + }, + "split_words": { + "description": "Split Word List", + "hint": "Split when any word in the list is detected", + }, + "content_cleanup_rule": { + "description": "Content Filtering Regular Expression", + "hint": "Remove specified content from segmented content. For example, `[。?!]` will remove all periods, question marks, and exclamation marks.", + }, + } + }, }, - "wl_ignore_admin_on_group": { - "description": "Administrator Group Messages Bypass ID Whitelist" + "ltm": { + "description": "Group Chat Context Awareness (formerly Chat Memory Enhancement)", + "provider_ltm_settings": { + "group_icl_enable": { + "description": "Enable Group Chat Context Awareness" + }, + "group_message_max_cnt": {"description": "Maximum Message Count"}, + "image_caption": { + "description": "Auto-understand Images", + "hint": "Requires setting a group chat image caption model.", + }, + "image_caption_provider_id": { + "description": "Group Chat Image Caption Model", + "hint": "Used for image understanding in group chat context awareness, configured separately from the default image caption model.", + }, + "active_reply": { + "enable": {"description": "Active Reply"}, + "method": {"description": "Active Reply Method"}, + "possibility_reply": { + "description": "Reply Probability", + "hint": "Value between 0.0-1.0", + }, + "whitelist": { + "description": "Active Reply Whitelist", + "hint": "Whitelist filtering is disabled when empty. Use /sid to get IDs.", + }, + }, + }, }, - "wl_ignore_admin_on_friend": { - "description": "Administrator Private Messages Bypass ID Whitelist" - } - } - }, - "rate_limit": { - "description": "Rate Limiting", - "platform_settings": { - "rate_limit": { - "time": { - "description": "Message Rate Limit Time (seconds)" - }, - "count": { - "description": "Message Rate Limit Count" - }, - "strategy": { - "description": "Rate Limit Strategy" - } - } - } }, - "content_safety": { - "description": "Content Safety", - "content_safety": { - "also_use_in_response": { - "description": "Also Check Model Response Content" - }, - "baidu_aip": { - "enable": { - "description": "Use Baidu Content Safety Moderation", - "hint": "You need to manually install the baidu-aip library." - }, - "app_id": { - "description": "App ID" - }, - "api_key": { - "description": "API Key" - }, - "secret_key": { - "description": "Secret Key" - } + "system_group": { + "name": "System", + "system": { + "description": "System Settings", + "t2i_strategy": { + "description": "Text-to-Image Strategy", + "hint": "Text-to-image strategy. `remote` uses a remote HTML-based rendering service, `local` uses PIL for local rendering. When using local, place a TTF font named 'font.ttf' in the data/ directory to customize the font.", + }, + "t2i_endpoint": { + "description": "Text-to-Image Service API Endpoint", + "hint": "Uses AstrBot API service when empty", + }, + "t2i_template": { + "description": "Text-to-Image Custom Template", + "hint": "When enabled, you can customize HTML templates for text-to-image rendering.", + }, + "t2i_active_template": { + "description": "Currently Active Text-to-Image Rendering Template", + "hint": "This value is maintained by the text-to-image template management page.", + }, + "log_level": { + "description": "Console Log Level", + "hint": "Log level for console output.", + }, + "log_file_enable": { + "description": "Enable File Logging", + "hint": "Write logs to a file in addition to the console.", + }, + "log_file_path": { + "description": "Log File Path", + "hint": "Relative paths are resolved under the data directory, e.g. logs/astrbot.log; absolute paths are supported.", + }, + "log_file_max_mb": { + "description": "Log File Max Size (MB)", + "hint": "Rotate when exceeding this size; default 20MB.", + }, + "temp_dir_max_size": { + "description": "Temp Directory Size Limit (MB)", + "hint": "Limits total size of data/temp in MB. The system checks every 10 minutes, and when exceeded, deletes oldest files first to release about 30% of current size.", + }, + "trace_log_enable": { + "description": "Enable Trace File Logging", + "hint": "Write trace events to a separate file (does not change console output).", + }, + "trace_log_path": { + "description": "Trace Log File Path", + "hint": "Relative paths are resolved under the data directory, e.g. logs/astrbot.trace.log; absolute paths are supported.", + }, + "trace_log_max_mb": { + "description": "Trace Log Max Size (MB)", + "hint": "Rotate when exceeding this size; default 20MB.", + }, + "pip_install_arg": { + "description": "Additional pip Installation Arguments", + "hint": "When installing plugin dependencies, Python's pip tool will be used. Additional arguments can be provided here, such as `--break-system-package`.", + }, + "pypi_index_url": { + "description": "PyPI Repository URL", + "hint": "PyPI repository URL for installing Python dependencies. Defaults to [https://mirrors.aliyun.com/pypi/simple/](https://mirrors.aliyun.com/pypi/simple/)", + }, + "callback_api_base": { + "description": "Externally Accessible Callback API Address", + "hint": "External services may access AstrBot's backend through callback links generated by AstrBot (such as file download links). Since AstrBot cannot automatically determine the externally accessible host address in the deployment environment, this configuration item is needed to explicitly specify how external services should access AstrBot's address. Examples: [http://localhost:6185](http://localhost:6185), [https://example.com](https://example.com), etc.", + }, + "disable_metrics": { + "description": "Disable Anonymous Usage Statistics", + "hint": "When disabled, AstrBot will not upload anonymous usage statistics.", + }, + "dashboard": { + "trust_proxy_headers": { + "description": "Trust Proxy Headers for Client IP", + "hint": "When disabled, ignore X-Forwarded-For/X-Real-IP and use the connection address only.", + }, + "auth_rate_limit": { + "enable": { + "description": "Enable Login Rate Limiting", + "hint": "When disabled, authentication endpoints (login, TOTP, etc.) will not be rate-limited.", + }, + "average_interval": { + "description": "Endpoint Rate Limit Average Interval (seconds)", + "hint": "Minimum average interval between authentication requests. For example, 1.0 means at most 1 request per second.", + }, + "max_burst": { + "description": "Endpoint Rate Limit Max Burst", + "hint": "Maximum number of consecutive burst requests allowed. For example, 3 allows up to 3 requests in a short burst.", + }, + }, + "ssl": { + "enable": { + "description": "Enable WebUI HTTPS", + "hint": "When enabled, WebUI serves directly over HTTPS.", + }, + "cert_file": { + "description": "SSL Certificate File Path", + "hint": "Certificate file path (PEM). Supports absolute and relative paths (relative to current working directory).", + }, + "key_file": { + "description": "SSL Private Key File Path", + "hint": "Private key file path (PEM). Supports absolute and relative paths (relative to current working directory).", + }, + "ca_certs": { + "description": "SSL CA Certificate File Path", + "hint": "Optional. Path to CA certificate file.", + }, + }, + "totp": { + "enable": { + "description": "Enable WebUI TOTP", + "hint": "When enabled, a TOTP code is required during dashboard login.", + }, + "manage": "Manage", + "configuration": "TOTP", + "statusPending": "Setup required", + "statusEnabled": "Enabled", + "setupRequiredHint": "TOTP is enabled but not yet configured. Click Manage to complete setup.", + "setupTitle": "Set up TOTP", + "setupSubtitle": "Scan this QR code in your authenticator app, then enter a verification code.", + "setupConfirm": "Verify and continue", + "activeSubtitle": "Use this QR code or secret to add another authenticator device.", + "rotateTitle": "Rotate TOTP Secret", + "rotateSubtitle": "Generate a new secret, then enter a code from your authenticator to confirm the replacement.", + "rotate": "Rotate", + "rotateRecovery": "Rotate Recovery Code", + "rotateConfirm": "Confirm Rotation", + "rotateCancel": "Cancel", + "rotateCode": "Verification Code", + "rotateCodeHint": "Enter the code from your authenticator app to confirm the new key.", + "rotateError": "Invalid code, please try again.", + "recoveryTitle": "Recovery Codes", + "recoverySubtitle": "This recovery code is shown once. Save it before continuing.", + "recoveryWarning": "If lost, account access cannot be restored through normal means.", + "recoveryAcknowledge": "I have saved my recovery codes", + "recoveryClose": "Done", + "disableTitle": "Disable TOTP", + "disableSubtitle": "Enter a verification code to disable two-factor authentication.", + "disableRecoverySubtitle": "Enter a recovery code to disable two-factor authentication.", + "disableCode": "Verification Code", + "disableRecoveryCode": "Recovery Code", + "disableConfirm": "Disable", + "disableCancel": "Cancel", + "disableError": "Verification failed. Please try again.", + "disableUseRecovery": "Can't use TOTP?", + "disableUseCode": "Use verification code", + "configSaveTitle": "Two-Factor Verification", + "configSaveSubtitle": "Enter a verification code to change protected configuration.", + "configSaveRotationHint": "When rotating TOTP keys, both the old and new verification codes are accepted (allowed once per rotation operation).", + "configSaveCode": "Verification Code", + "configSaveConfirm": "Continue", + "configSaveCancel": "Cancel", + "configSaveError": "Verification failed. Please try again.", + }, + }, + "timezone": { + "description": "Timezone", + "hint": "Timezone setting. Please enter an IANA timezone name, such as Asia/Shanghai. Uses system default timezone when empty. For all timezones, see: [https://data.iana.org/time-zones/tzdb-2021a/zone1970.tab](https://data.iana.org/time-zones/tzdb-2021a/zone1970.tab)", + }, + "http_proxy": { + "description": "HTTP Proxy", + "hint": "When enabled, proxy will be set by adding environment variables. Format: `http://ip:port`", + }, + "no_proxy": {"description": "Direct Connection Address List"}, }, - "internal_keywords": { - "enable": { - "description": "Keyword Check" - }, - "extra_keywords": { - "description": "Additional Keywords", - "hint": "Additional keyword blocklist, supports regular expressions." - } - } - } }, - "t2i": { - "description": "Text-to-Image", - "t2i": { - "description": "Text-to-Image Output" - }, - "t2i_word_threshold": { - "description": "Text-to-Image Word Count Threshold" - } - }, - "others": { - "description": "Other Settings", - "platform_settings": { - "ignore_bot_self_message": { - "description": "Ignore Bot's Own Messages" - }, - "ignore_at_all": { - "description": "Ignore @All Events" - }, - "no_permission_reply": { - "description": "Reply When User Has Insufficient Permissions" - } - }, - "platform_specific": { - "lark": { - "pre_ack_emoji": { - "enable": { - "description": "[Lark] Enable Pre-acknowledgment Emoji" + "provider_group": { + "provider": { + "genie_onnx_model_dir": { + "description": "ONNX Model Directory", + "hint": "The directory path containing the ONNX model files", }, - "emojis": { - "description": "Emoji List (Lark Emoji Enum Names)", - "hint": "Emoji enum names reference: [https://open.feishu.cn/document/server-docs/im-v1/message-reaction/emojis-introduce](https://open.feishu.cn/document/server-docs/im-v1/message-reaction/emojis-introduce)" - } - } - }, - "telegram": { - "pre_ack_emoji": { - "enable": { - "description": "[Telegram] Enable Pre-acknowledgment Emoji" + "genie_language": {"description": "Language"}, + "xai_native_search": { + "description": "Enable native search", + "hint": "When enabled, uses xAI Chat Completions native Live Search for web queries (billed on demand). Only applies to xAI providers.", }, - "emojis": { - "description": "Emoji List (Unicode)", - "hint": "Telegram only supports a fixed reaction set, reference: [https://gist.github.com/Soulter/3f22c8e5f9c7e152e967e8bc28c97fc9](https://gist.github.com/Soulter/3f22c8e5f9c7e152e967e8bc28c97fc9)" - } - } - }, - "discord": { - "pre_ack_emoji": { - "enable": { - "description": "[Discord] Enable Pre-acknowledgment Emoji" + "rerank_api_base": { + "description": "Rerank Model API Base URL", + "hint": "The full request URL is formed by combining the Base URL and a path suffix (defaults to /v1/rerank).", + }, + "rerank_api_suffix": { + "description": "API URL path suffix", + "hint": "Path appended to base_url, e.g. /v1/rerank. Leave empty to disable auto-append.", + }, + "rerank_api_key": { + "description": "API Key", + "hint": "Leave empty if no API key is required.", + }, + "rerank_model": {"description": "Rerank model name"}, + "return_documents": { + "description": "Return source documents in rerank results", + "hint": "Default is false to reduce network overhead.", + }, + "instruct": { + "description": "Custom rerank task description", + "hint": "Only effective for qwen3-rerank models. Recommended to write in English.", + }, + "nvidia_rerank_api_base": {"description": "API Base URL"}, + "nvidia_rerank_api_key": {"description": "API Key"}, + "nvidia_rerank_model": { + "description": "Rerank Model Name", + "hint": "Please refer to the NVIDIA Docs for the model name.", + }, + "nvidia_rerank_model_endpoint": { + "description": "Custom Model Endpoint", + "hint": "Custom URL suffix endpoint, defaults to /reranking.", + }, + "nvidia_rerank_truncate": { + "description": "Text Truncation Strategy", + "hint": "Whether to truncate the input to fit the model's maximum context length when the input text is too long.", + }, + "tei_rerank_truncate": { + "description": "Truncate Long Text", + "hint": "Whether to automatically truncate input when it exceeds the model's maximum context length. Requires Truncation Direction when enabled.", + }, + "tei_rerank_truncation_direction": { + "description": "Truncation Direction", + "hint": "Choose to truncate from the left or right side of the text. Only takes effect when Truncate Long Text is True.", + }, + "tei_rerank_raw_scores": { + "description": "Return Raw Scores", + "hint": "If True, returns raw model logit scores (which may be negative) without sigmoid normalization. Default is False.", + }, + "tei_rerank_return_text": { + "description": "Return Document Text in Results", + "hint": "If True, each result will include the original document text. Default is False to reduce network overhead.", + }, + "launch_model_if_not_running": { + "description": "Auto-start model if not running", + "hint": "If the model is not running in Xinference, attempt to start it automatically. Recommended to disable in production.", + }, + "modalities": { + "description": "Model capabilities", + "hint": "Modalities supported by the model. If the model does not support images, uncheck image.", + "labels": ["Text", "Image", "Audio", "Tool use"], + }, + "supported_image_mimes": { + "description": "Supported image MIME types", + "hint": "Image formats the model accepts. When unchecked, all formats are kept (only known-unsafe formats like GIF are filtered on some gateways). When checked, only selected formats are preserved.", + "labels": ["JPEG", "PNG", "WebP", "GIF"], + }, + "custom_headers": { + "description": "Custom request headers", + "hint": "Key/value pairs added here are merged into the OpenAI SDK default_headers for custom HTTP headers. Values must be strings.", + }, + "ollama_disable_thinking": { + "description": "Disable thinking mode", + "hint": "Close Ollama thinking mode.", + }, + "custom_extra_body": { + "description": "Custom request body parameters", + "hint": "Add extra parameters to requests, such as temperature, top_p, max_tokens, etc.", + "template_schema": { + "temperature": { + "description": "Temperature", + "hint": "Controls randomness, typically 0-2. Higher is more random.", + "name": "Temperature", + }, + "top_p": { + "description": "Top-p sampling", + "hint": "Nucleus sampling parameter, usually 0-1. Controls probability mass considered.", + "name": "Top-p", + }, + "max_tokens": { + "description": "Max tokens", + "hint": "Maximum number of generated tokens.", + "name": "Max Tokens", + }, + }, + }, + "gpt_weights_path": { + "description": "GPT model file path", + "hint": "The .ckpt file. Use an absolute path without quotes. Leave empty to use the GPT_SoVITS built-in SoVITS model (recommended to change defaults in GPT_SoVITS).", + }, + "sovits_weights_path": { + "description": "SoVITS model file path", + "hint": "The .pth file. Use an absolute path without quotes. Leave empty to use the GPT_SoVITS built-in SoVITS model (recommended to change defaults in GPT_SoVITS).", + }, + "gsv_default_parms": { + "description": "GPT_SoVITS default parameters", + "hint": "Reference audio file path and text are required; other parameters are optional.", + "gsv_ref_audio_path": { + "description": "Reference audio file path", + "hint": "Required! Use an absolute path without quotes.", + }, + "gsv_prompt_text": { + "description": "Reference audio text", + "hint": "Required! Provide the transcript of the reference audio.", + }, + "gsv_prompt_lang": { + "description": "Reference audio text language", + "hint": "Language of the reference audio text; default is Chinese.", + }, + "gsv_aux_ref_audio_paths": { + "description": "Auxiliary reference audio file paths", + "hint": "Auxiliary reference audio files; optional.", + }, + "gsv_text_lang": { + "description": "Text language", + "hint": "Default is Chinese.", + }, + "gsv_top_k": {"description": "Speech diversity", "hint": ""}, + "gsv_top_p": {"description": "Nucleus sampling threshold", "hint": ""}, + "gsv_temperature": {"description": "Speech randomness", "hint": ""}, + "gsv_text_split_method": { + "description": "Text splitting method", + "hint": "Options: `cut0` no split, `cut1` split every 4 sentences, `cut2` split every 50 chars, `cut3` split by Chinese period, `cut4` split by English period, `cut5` split by punctuation.", + }, + "gsv_batch_size": {"description": "Batch size", "hint": ""}, + "gsv_batch_threshold": {"description": "Batch threshold", "hint": ""}, + "gsv_split_bucket": { + "description": "Split text into buckets for parallel processing", + "hint": "", + }, + "gsv_speed_factor": { + "description": "Speech playback speed", + "hint": "1 is the original speed.", + }, + "gsv_fragment_interval": { + "description": "Interval between speech segments", + "hint": "", + }, + "gsv_streaming_mode": { + "description": "Enable streaming mode", + "hint": "", + }, + "gsv_seed": { + "description": "Random seed", + "hint": "For reproducible results.", + }, + "gsv_parallel_infer": { + "description": "Run inference in parallel", + "hint": "", + }, + "gsv_repetition_penalty": { + "description": "Repetition penalty", + "hint": "", + }, + "gsv_media_type": { + "description": "Output media type", + "hint": "Recommended: wav", + }, + }, + "embedding_dimensions": { + "description": "Embedding dimensions", + "hint": "Embedding vector dimensions. May need adjustment per model; see model documentation. This must be correct or the vector database will not work.", + }, + "embedding_dimensions_mode": { + "description": "Embedding dimensions mode", + "hint": "Controls whether to send the dimensions parameter in OpenAI-compatible embedding requests. auto sends it only for official OpenAI embedding-3 models; use always when a compatible API supports it, or never when it rejects the parameter.", + }, + "embedding_model": { + "description": "Embedding model", + "hint": "Embedding model name.", + }, + "embedding_api_key": {"description": "API Key"}, + "embedding_api_base": {"description": "API Base URL"}, + "openai_embedding": { + "hint": "If testing fails, try adding /v1 at the end for some OpenAI API versions." + }, + "gemini_embedding": { + "hint": "Gemini Embedding does not require manually adding /v1beta." + }, + "volcengine_cluster": { + "description": "Volcengine cluster", + "hint": "For voice cloning models, choose volcano_icl or volcano_icl_concurr; default is volcano_tts.", + }, + "volcengine_voice_type": { + "description": "Volcengine voice", + "hint": "Enter voice id (Voice_type).", + }, + "volcengine_speed_ratio": { + "description": "Speech rate", + "hint": "Speech rate, range 0.2 to 3.0, default 1.0.", + }, + "volcengine_volume_ratio": { + "description": "Volume", + "hint": "Volume, range 0.0 to 2.0, default 1.0.", + }, + "azure_tts_voice": {"description": "Voice style", "hint": "API voice name"}, + "azure_tts_style": { + "description": "Style", + "hint": "A voice-specific speaking style. Can express emotions like happy, sympathetic, and calm.", + }, + "azure_tts_role": { + "description": "Role (optional)", + "hint": "Speaking role-play. The voice can emulate different ages and genders without changing the voice name. For example, a male voice can raise pitch to simulate a female voice, but the voice name does not change. If the role is missing or unsupported, this attribute is ignored.", + }, + "azure_tts_rate": { + "description": "Speech rate", + "hint": "Controls speaking rate. You can apply the rate at word or sentence level. Rate should be 0.5x to 2x of original audio.", + }, + "azure_tts_volume": { + "description": "Speech volume", + "hint": "Controls volume level. You can apply changes at sentence level. Use 0.0 to 100.0 (quiet to loud, e.g., 75). Default is 100.0.", + }, + "azure_tts_region": { + "description": "API region", + "hint": "Region where Azure TTS processes data. See https://learn.microsoft.com/zh-cn/azure/ai-services/speech-service/regions", + }, + "azure_tts_subscription_key": { + "description": "Service subscription key", + "hint": "Azure TTS subscription key (not a token).", + }, + "dashscope_tts_voice": {"description": "Voice"}, + "gm_resp_image_modal": { + "description": "Enable image modality", + "hint": "When enabled, responses can include images. Requires model support or it will error. See the Google Gemini website for supported models. Tip: if you need image generation, disable the `Enable member recognition` setting for better results.", + }, + "gm_native_search": { + "description": "Enable native search", + "hint": "When enabled, all function tools are disabled. Check official docs for free quota limits.", + }, + "gm_native_coderunner": { + "description": "Enable native code runner", + "hint": "When enabled, all function tools are disabled.", + }, + "gm_url_context": { + "description": "Enable URL context", + "hint": "When enabled, all function tools are disabled.", + }, + "gm_safety_settings": { + "description": "Safety filters", + "hint": "Set the safety filtering level for model input. Levels: NONE (no blocking), HIGH (block high risk), MEDIUM_AND_ABOVE (block medium risk and above), LOW_AND_ABOVE (block low risk and above). See Gemini API docs.", + "harassment": { + "description": "Harassment", + "hint": "Negative or harmful comments", + }, + "hate_speech": { + "description": "Hate speech", + "hint": "Rude, disrespectful, or profane content", + }, + "sexually_explicit": { + "description": "Sexually explicit content", + "hint": "References to sexual acts or other obscene content", + }, + "dangerous_content": { + "description": "Dangerous content", + "hint": "Content that promotes, encourages, or assists harmful behavior", + }, + }, + "gm_thinking_config": { + "description": "Thinking Config", + "budget": { + "description": "Thinking Budget", + "hint": "Guides the model on the specific number of thinking tokens to use for reasoning. See: https://ai.google.dev/gemini-api/docs/thinking#set-budget", + }, + "level": { + "description": "Thinking Level", + "hint": "Recommended for Gemini 3 models and onwards, lets you control reasoning behavior.See: https://ai.google.dev/gemini-api/docs/thinking#thinking-levels", + }, + }, + "anth_thinking_config": { + "description": "Thinking Config", + "type": { + "description": "Thinking Type", + "hint": "Set 'adaptive' for Opus 4.6+ / Sonnet 4.6+ (recommended). Leave empty to use manual budget mode. See: https://platform.claude.com/docs/en/build-with-claude/adaptive-thinking", + }, + "budget": { + "description": "Thinking Budget", + "hint": "Anthropic thinking.budget_tokens param. Must >= 1024. Only used when type is empty. Deprecated on Opus 4.6 / Sonnet 4.6. See: https://platform.claude.com/docs/en/build-with-claude/extended-thinking", + }, + "effort": { + "description": "Effort Level", + "hint": "Controls thinking depth when type is 'adaptive'. 'high' is the default. 'max' is Opus 4.6 only. See: https://platform.claude.com/docs/en/build-with-claude/effort", + }, + }, + "minimax-group-id": { + "description": "User group", + "hint": "Visible in Account Management -> Basic Info.", + }, + "minimax-langboost": { + "description": "Target language/dialect", + "hint": "Enhances recognition for specified languages/dialects and improves speech performance in those scenarios.", + }, + "minimax-voice-speed": { + "description": "Speech rate", + "hint": "Speech speed for synthesis, range [0.5, 2], default 1.0. Higher is faster.", + }, + "minimax-voice-vol": { + "description": "Volume", + "hint": "Volume for synthesis, range (0, 10], default 1.0. Higher is louder.", + }, + "minimax-voice-pitch": { + "description": "Pitch", + "hint": "Pitch for synthesis, range [-12, 12], default 0.", + }, + "minimax-is-timber-weight": { + "description": "Enable mixed voices", + "hint": "Enable mixing up to four voices with custom weights. When enabled, single voice settings are ignored.", + }, + "minimax-timber-weight": { + "description": "Mixed voices", + "hint": "Mixed voices and their weights. Up to four voices, integer weights in [1, 100]. Get presets and templates from the official API TTS debug console. Must be a JSON string; check the console to confirm parsing. See defaults and the official code preview for structure.", + }, + "minimax-voice-id": { + "description": "Single voice", + "hint": "Single voice ID; see the official documentation.", + }, + "minimax-voice-emotion": { + "description": "Emotion", + "hint": "Controls emotion of synthesized speech. When set to auto, it selects emotion based on text.", + }, + "minimax-voice-latex": { + "description": "Read LaTeX formulas", + "hint": "Read LaTeX formulas, but ensure input text is formatted per the official requirements.", + }, + "minimax-voice-english-normalization": { + "description": "English text normalization", + "hint": "Improves number-reading performance but slightly increases latency.", + }, + "rag_options": { + "description": "RAG options", + "hint": "Knowledge base retrieval settings, optional. Only supported for Agent app types (agent apps, including RAG apps). For Bailian apps, enabling this disables multi-turn conversations.", + "pipeline_ids": { + "description": "Knowledge base ID list", + "hint": "Retrieve all documents in the specified knowledge bases. Go to https://bailian.console.aliyun.com/ Data Apps -> Knowledge Index to create and get IDs.", + }, + "file_ids": { + "description": "Unstructured document IDs", + "hint": "Retrieve specified unstructured documents. Go to https://bailian.console.aliyun.com/ Data Management to create and get IDs.", + }, + "output_reference": { + "description": "Output knowledge base/document references", + "hint": "Append reference sources to the end of each answer. Default is False.", + }, + }, + "sensevoice_hint": { + "description": "Deploy SenseVoice", + "hint": "Before enabling, install funasr, funasr_onnx, torchaudio, torch, modelscope, and jieba (CPU by default, about 1 GB download), and install ffmpeg. Otherwise STT will not work.", + }, + "is_emotion": { + "description": "Emotion recognition", + "hint": "Enable emotion recognition. happy?sad?angry?neutral?fearful?disgusted?surprised?unknown", + }, + "stt_model": { + "description": "Model name", + "hint": "Model name on modelscope. Default: iic/SenseVoiceSmall.", + }, + "variables": { + "description": "Workflow fixed input variables", + "hint": "Optional. Fixed workflow input variables are used as workflow inputs. You can also set variables dynamically with /set during a chat. If names conflict, dynamic settings take precedence.", + }, + "dashscope_app_type": { + "description": "App type", + "hint": "Bailian app type.", + }, + "timeout": {"description": "Timeout", "hint": "Timeout in seconds."}, + "openai-tts-voice": { + "description": "voice", + "hint": "OpenAI TTS voice. OpenAI defaults: 'alloy', 'echo', 'fable', 'onyx', 'nova', 'shimmer'.", + }, + "elevenlabs-tts-voice-id": { + "description": "Voice ID", + "hint": "ElevenLabs voice ID. Browse and copy voice IDs at https://elevenlabs.io/app/voice-library. Default 'JBFqnCBsd6RMkjVDRZzb' (George).", + }, + "elevenlabs-tts-output-format": { + "description": "Output format", + "hint": "Audio output format, e.g. 'mp3_44100_128', 'mp3_22050_32', 'wav_44100', or 'opus_48000_128'. Raw PCM/u-law/a-law formats are not supported. Default 'mp3_44100_128'.", + }, + "elevenlabs-tts-stability": { + "description": "Stability", + "hint": "Voice stability, range [0, 1]. Higher is more consistent, lower is more expressive. Leave empty to use the server default.", + }, + "elevenlabs-tts-similarity-boost": { + "description": "Similarity boost", + "hint": "How closely the output matches the original voice, range [0, 1]. Leave empty to use the server default.", + }, + "elevenlabs-tts-style": { + "description": "Style exaggeration", + "hint": "Style exaggeration of the voice, range [0, 1]. Higher values increase latency. Leave empty to use the server default.", + }, + "elevenlabs-tts-use-speaker-boost": { + "description": "Speaker boost", + "hint": "Boost similarity to the original speaker. May slightly increase latency.", + }, + "mimo-tts-voice": { + "description": "Voice", + "hint": "MiMo TTS voice name. Supported values include 'mimo_default', 'default_en', and 'default_zh'.", + }, + "mimo-tts-format": { + "description": "Output format", + "hint": "Audio format generated by MiMo TTS. Supported values: 'wav', 'mp3', and 'pcm'.", + }, + "mimo-tts-style-prompt": { + "description": "Style prompt", + "hint": "Prepended to the synthesis target text as a tag to control speed, emotion, character, or style, such as happy, faster, Sun Wukong, or whispering. Optional.", + }, + "mimo-tts-dialect": { + "description": "Dialect", + "hint": "Combined with the style prompt inside the leading tag, for example Northeastern Mandarin, Sichuan dialect, Henan dialect, or Cantonese. Optional.", + }, + "mimo-tts-seed-text": { + "description": "Seed text", + "hint": "Sent as an optional user message to help guide tone and speaking style. It is not appended to the synthesis target text.", + }, + "fishaudio-tts-character": { + "description": "character", + "hint": "Fishaudio TTS character. Default is Klee. More roles: https://fish.audio/zh-CN/discovery", + }, + "fishaudio-tts-reference-id": { + "description": "reference_id", + "hint": "Fishaudio TTS reference model ID (optional). If set, the model ID is used directly instead of looking up by role name. Example: 626bb6d3f3364c9cbc3aa6a67300a664. More models: https://fish.audio/zh-CN/discovery; open a model detail page to copy the model ID.", + }, + "whisper_hint": { + "description": "Notes for local Whisper deployment", + "hint": "Before enabling, install the openai-whisper library (NVIDIA users download ~2GB mainly for torch and cuda; CPU users download ~1GB), and install ffmpeg. Otherwise STT will not work.", + }, + "whisper_device": { + "description": "Inference device", + "hint": "Whisper inference device. Apple Silicon can use mps; other environments should use cpu. If mps is selected but unavailable, AstrBot will fall back to cpu.", + }, + "id": {"description": "ID"}, + "type": {"description": "Provider category"}, + "provider_type": {"description": "Provider capability type"}, + "enable": {"description": "Enable"}, + "key": {"description": "API Key"}, + "api_base": {"description": "API Base URL"}, + "proxy": { + "description": "Proxy address", + "hint": "HTTP/HTTPS proxy URL, e.g. http://127.0.0.1:7890. Applies only to this provider's API requests and does not affect Docker internal networking.", + }, + "model": { + "description": "Model ID", + "hint": "Model name, e.g., gpt-4o-mini, deepseek-chat.", + }, + "max_context_tokens": { + "description": "Model context window size", + "hint": "Maximum context tokens. If 0, it auto-fills from model metadata (if available); you can also edit manually.", + }, + "dify_api_key": { + "description": "API Key", + "hint": "Dify API Key. This field is required.", + }, + "dify_api_base": { + "description": "API Base URL", + "hint": "Dify API Base URL. Default: https://api.dify.ai/v1", + }, + "dify_api_type": { + "description": "Dify app type", + "hint": "Dify API type. According to Dify docs, supported types are chat, chatflow, agent, workflow.", + }, + "dify_workflow_output_key": { + "description": "Dify workflow output variable name", + "hint": "Dify workflow output variable name. Only used when app type is workflow. Default: astrbot_wf_output.", + }, + "dify_query_input_key": { + "description": "Prompt input variable name", + "hint": "Input variable name for the message text. Default: astrbot_text_query.", + }, + "coze_api_key": { + "description": "Coze API Key", + "hint": "Coze API key for accessing Coze services.", + }, + "bot_id": { + "description": "Bot ID", + "hint": "Coze bot ID, obtained after creating a bot on the Coze platform.", + }, + "coze_api_base": { + "description": "API Base URL", + "hint": "Base URL for the Coze API. Default: https://api.coze.cn", + }, + "deerflow_api_base": { + "description": "API Base URL", + "hint": "DeerFlow API gateway URL. Default: http://127.0.0.1:2026", + }, + "deerflow_api_key": { + "description": "DeerFlow API Key", + "hint": "Optional. Fill this if your DeerFlow gateway is protected by Bearer auth.", + }, + "deerflow_auth_header": { + "description": "Authorization Header", + "hint": "Optional. Custom Authorization header value; takes precedence over DeerFlow API Key.", + }, + "deerflow_assistant_id": { + "description": "Assistant ID", + "hint": "LangGraph assistant_id, default is lead_agent.", + }, + "deerflow_model_name": { + "description": "Model name override", + "hint": "Optional. Overrides DeerFlow default model (maps to runtime context model_name).", + }, + "deerflow_thinking_enabled": {"description": "Enable thinking mode"}, + "deerflow_plan_mode": { + "description": "Enable plan mode", + "hint": "Maps to DeerFlow is_plan_mode.", + }, + "deerflow_subagent_enabled": { + "description": "Enable subagent", + "hint": "Maps to DeerFlow subagent_enabled.", + }, + "deerflow_max_concurrent_subagents": { + "description": "Max concurrent subagents", + "hint": "Maps to DeerFlow max_concurrent_subagents. Effective only when subagent is enabled. Default: 3.", + }, + "deerflow_recursion_limit": { + "description": "Recursion limit", + "hint": "Maps to LangGraph recursion_limit.", + }, + "auto_save_history": { + "description": "Conversation history managed by Coze", + "hint": "When enabled, Coze manages conversation history. AstrBot's locally saved context will not take effect (read-only), and operations on AstrBot context will not apply. If disabled, AstrBot manages the context.", }, - "emojis": { - "description": "Emoji List (Unicode or Custom Emoji Name)", - "hint": "Enter Unicode emoji symbols, e.g., 👍, 🤔, ⏳" - } - } - } - } - } - }, - "plugin_group": { - "name": "Plugin", - "plugin": { - "description": "Plugins", - "plugin_set": { - "description": "Available Plugins", - "hint": "All non-disabled plugins are enabled by default. If a plugin is disabled on the plugins page, selections here will not take effect." - } - } - }, - "ext_group": { - "name": "Ext.", - "segmented_reply": { - "description": "Segmented Reply", - "platform_settings": { - "segmented_reply": { - "enable": { - "description": "Enable Segmented Reply" - }, - "only_llm_result": { - "description": "Segment Only LLM Results" - }, - "interval_method": { - "description": "Interval Method", - "hint": "random uses a random delay. log calculates delay by message length: $y=log_{log\\_base}(x)$, where x is word count and y is in seconds." - }, - "interval": { - "description": "Random Interval Time", - "hint": "Format: minimum,maximum (e.g., 1.5,3.5)" - }, - "log_base": { - "description": "Logarithm Base", - "hint": "Base for logarithmic intervals, defaults to 2.6. Value range: 1.0-10.0." - }, - "words_count_threshold": { - "description": "Segmented Reply Word Count Threshold", - "hint": "Segmented reply word count threshold. Only messages with less than this number of words will be segmented, and messages with more than this number of words will be sent directly (not segmented)." - }, - "split_mode": { - "description": "Split Mode", - "hint": "Used to segment a message. By default, it will be separated by punctuation marks like period, question mark, etc. For example, filling `[。?!]` will remove all periods, question marks, and exclamation marks. re.findall(r'', text)", - "labels": [ - "Regex", - "Words List" - ] - }, - "regex": { - "description": "Segmentation Regular Expression", - "hint": "Used to identify split points with a regular expression. Prefer patterns that match separators." - }, - "split_words": { - "description": "Split Word List", - "hint": "Split when any word in the list is detected" - }, - "content_cleanup_rule": { - "description": "Content Filtering Regular Expression", - "hint": "Remove specified content from segmented content. For example, `[。?!]` will remove all periods, question marks, and exclamation marks." - } } - } }, - "ltm": { - "description": "Group Chat Context Awareness (formerly Chat Memory Enhancement)", - "provider_ltm_settings": { - "group_icl_enable": { - "description": "Enable Group Chat Context Awareness" - }, - "group_message_max_cnt": { - "description": "Maximum Message Count" - }, - "image_caption": { - "description": "Auto-understand Images", - "hint": "Requires setting a group chat image caption model." - }, - "image_caption_provider_id": { - "description": "Group Chat Image Caption Model", - "hint": "Used for image understanding in group chat context awareness, configured separately from the default image caption model." - }, - "active_reply": { - "enable": { - "description": "Active Reply" - }, - "method": { - "description": "Active Reply Method" - }, - "possibility_reply": { - "description": "Reply Probability", - "hint": "Value between 0.0-1.0" - }, - "whitelist": { - "description": "Active Reply Whitelist", - "hint": "Whitelist filtering is disabled when empty. Use /sid to get IDs." - } - } - } - } - }, - "system_group": { - "name": "System", - "system": { - "description": "System Settings", - "t2i_strategy": { - "description": "Text-to-Image Strategy", - "hint": "Text-to-image strategy. `remote` uses a remote HTML-based rendering service, `local` uses PIL for local rendering. When using local, place a TTF font named 'font.ttf' in the data/ directory to customize the font." - }, - "t2i_endpoint": { - "description": "Text-to-Image Service API Endpoint", - "hint": "Uses AstrBot API service when empty" - }, - "t2i_template": { - "description": "Text-to-Image Custom Template", - "hint": "When enabled, you can customize HTML templates for text-to-image rendering." - }, - "t2i_active_template": { - "description": "Currently Active Text-to-Image Rendering Template", - "hint": "This value is maintained by the text-to-image template management page." - }, - "log_level": { - "description": "Console Log Level", - "hint": "Log level for console output." - }, - "log_file_enable": { - "description": "Enable File Logging", - "hint": "Write logs to a file in addition to the console." - }, - "log_file_path": { - "description": "Log File Path", - "hint": "Relative paths are resolved under the data directory, e.g. logs/astrbot.log; absolute paths are supported." - }, - "log_file_max_mb": { - "description": "Log File Max Size (MB)", - "hint": "Rotate when exceeding this size; default 20MB." - }, - "temp_dir_max_size": { - "description": "Temp Directory Size Limit (MB)", - "hint": "Limits total size of data/temp in MB. The system checks every 10 minutes, and when exceeded, deletes oldest files first to release about 30% of current size." - }, - "trace_log_enable": { - "description": "Enable Trace File Logging", - "hint": "Write trace events to a separate file (does not change console output)." - }, - "trace_log_path": { - "description": "Trace Log File Path", - "hint": "Relative paths are resolved under the data directory, e.g. logs/astrbot.trace.log; absolute paths are supported." - }, - "trace_log_max_mb": { - "description": "Trace Log Max Size (MB)", - "hint": "Rotate when exceeding this size; default 20MB." - }, - "pip_install_arg": { - "description": "Additional pip Installation Arguments", - "hint": "When installing plugin dependencies, Python's pip tool will be used. Additional arguments can be provided here, such as `--break-system-package`." - }, - "pypi_index_url": { - "description": "PyPI Repository URL", - "hint": "PyPI repository URL for installing Python dependencies. Defaults to [https://mirrors.aliyun.com/pypi/simple/](https://mirrors.aliyun.com/pypi/simple/)" - }, - "callback_api_base": { - "description": "Externally Accessible Callback API Address", - "hint": "External services may access AstrBot's backend through callback links generated by AstrBot (such as file download links). Since AstrBot cannot automatically determine the externally accessible host address in the deployment environment, this configuration item is needed to explicitly specify how external services should access AstrBot's address. Examples: [http://localhost:6185](http://localhost:6185), [https://example.com](https://example.com), etc." - }, - "disable_metrics": { - "description": "Disable Anonymous Usage Statistics", - "hint": "When disabled, AstrBot will not upload anonymous usage statistics." - }, - "dashboard": { - "trust_proxy_headers": { - "description": "Trust Proxy Headers for Client IP", - "hint": "When disabled, ignore X-Forwarded-For/X-Real-IP and use the connection address only." - }, - "auth_rate_limit": { - "enable": { - "description": "Enable Login Rate Limiting", - "hint": "When disabled, authentication endpoints (login, TOTP, etc.) will not be rate-limited." - }, - "average_interval": { - "description": "Endpoint Rate Limit Average Interval (seconds)", - "hint": "Minimum average interval between authentication requests. For example, 1.0 means at most 1 request per second." - }, - "max_burst": { - "description": "Endpoint Rate Limit Max Burst", - "hint": "Maximum number of consecutive burst requests allowed. For example, 3 allows up to 3 requests in a short burst." - } - }, - "ssl": { - "enable": { - "description": "Enable WebUI HTTPS", - "hint": "When enabled, WebUI serves directly over HTTPS." - }, - "cert_file": { - "description": "SSL Certificate File Path", - "hint": "Certificate file path (PEM). Supports absolute and relative paths (relative to current working directory)." - }, - "key_file": { - "description": "SSL Private Key File Path", - "hint": "Private key file path (PEM). Supports absolute and relative paths (relative to current working directory)." - }, - "ca_certs": { - "description": "SSL CA Certificate File Path", - "hint": "Optional. Path to CA certificate file." - } - }, - "totp": { - "enable": { - "description": "Enable WebUI TOTP", - "hint": "When enabled, a TOTP code is required during dashboard login." - }, - "manage": "Manage", - "configuration": "TOTP", - "statusPending": "Setup required", - "statusEnabled": "Enabled", - "setupRequiredHint": "TOTP is enabled but not yet configured. Click Manage to complete setup.", - "setupTitle": "Set up TOTP", - "setupSubtitle": "Scan this QR code in your authenticator app, then enter a verification code.", - "setupConfirm": "Verify and continue", - "activeSubtitle": "Use this QR code or secret to add another authenticator device.", - "rotateTitle": "Rotate TOTP Secret", - "rotateSubtitle": "Generate a new secret, then enter a code from your authenticator to confirm the replacement.", - "rotate": "Rotate", - "rotateRecovery": "Rotate Recovery Code", - "rotateConfirm": "Confirm Rotation", - "rotateCancel": "Cancel", - "rotateCode": "Verification Code", - "rotateCodeHint": "Enter the code from your authenticator app to confirm the new key.", - "rotateError": "Invalid code, please try again.", - "recoveryTitle": "Recovery Codes", - "recoverySubtitle": "This recovery code is shown once. Save it before continuing.", - "recoveryWarning": "If lost, account access cannot be restored through normal means.", - "recoveryAcknowledge": "I have saved my recovery codes", - "recoveryClose": "Done", - "disableTitle": "Disable TOTP", - "disableSubtitle": "Enter a verification code to disable two-factor authentication.", - "disableRecoverySubtitle": "Enter a recovery code to disable two-factor authentication.", - "disableCode": "Verification Code", - "disableRecoveryCode": "Recovery Code", - "disableConfirm": "Disable", - "disableCancel": "Cancel", - "disableError": "Verification failed. Please try again.", - "disableUseRecovery": "Can't use TOTP?", - "disableUseCode": "Use verification code", - "configSaveTitle": "Two-Factor Verification", - "configSaveSubtitle": "Enter a verification code to change protected configuration.", - "configSaveRotationHint": "When rotating TOTP keys, both the old and new verification codes are accepted (allowed once per rotation operation).", - "configSaveCode": "Verification Code", - "configSaveConfirm": "Continue", - "configSaveCancel": "Cancel", - "configSaveError": "Verification failed. Please try again." - } - }, - "timezone": { - "description": "Timezone", - "hint": "Timezone setting. Please enter an IANA timezone name, such as Asia/Shanghai. Uses system default timezone when empty. For all timezones, see: [https://data.iana.org/time-zones/tzdb-2021a/zone1970.tab](https://data.iana.org/time-zones/tzdb-2021a/zone1970.tab)" - }, - "http_proxy": { - "description": "HTTP Proxy", - "hint": "When enabled, proxy will be set by adding environment variables. Format: `http://ip:port`" - }, - "no_proxy": { - "description": "Direct Connection Address List" - } - } - }, - "provider_group": { - "provider": { - "genie_onnx_model_dir": { - "description": "ONNX Model Directory", - "hint": "The directory path containing the ONNX model files" - }, - "genie_language": { - "description": "Language" - }, - "xai_native_search": { - "description": "Enable native search", - "hint": "When enabled, uses xAI Chat Completions native Live Search for web queries (billed on demand). Only applies to xAI providers." - }, - "rerank_api_base": { - "description": "Rerank Model API Base URL", - "hint": "The full request URL is formed by combining the Base URL and a path suffix (defaults to /v1/rerank)." - }, - "rerank_api_suffix": { - "description": "API URL path suffix", - "hint": "Path appended to base_url, e.g. /v1/rerank. Leave empty to disable auto-append." - }, - "rerank_api_key": { - "description": "API Key", - "hint": "Leave empty if no API key is required." - }, - "rerank_model": { - "description": "Rerank model name" - }, - "return_documents": { - "description": "Return source documents in rerank results", - "hint": "Default is false to reduce network overhead." - }, - "instruct": { - "description": "Custom rerank task description", - "hint": "Only effective for qwen3-rerank models. Recommended to write in English." - }, - "nvidia_rerank_api_base": { - "description": "API Base URL" - }, - "nvidia_rerank_api_key": { - "description": "API Key" - }, - "nvidia_rerank_model": { - "description": "Rerank Model Name", - "hint": "Please refer to the NVIDIA Docs for the model name." - }, - "nvidia_rerank_model_endpoint": { - "description": "Custom Model Endpoint", - "hint": "Custom URL suffix endpoint, defaults to /reranking." - }, - "nvidia_rerank_truncate": { - "description": "Text Truncation Strategy", - "hint": "Whether to truncate the input to fit the model's maximum context length when the input text is too long." - }, - "tei_rerank_truncate": { - "description": "Truncate Long Text", - "hint": "Whether to automatically truncate input when it exceeds the model's maximum context length. Requires Truncation Direction when enabled." - }, - "tei_rerank_truncation_direction": { - "description": "Truncation Direction", - "hint": "Choose to truncate from the left or right side of the text. Only takes effect when Truncate Long Text is True." - }, - "tei_rerank_raw_scores": { - "description": "Return Raw Scores", - "hint": "If True, returns raw model logit scores (which may be negative) without sigmoid normalization. Default is False." - }, - "tei_rerank_return_text": { - "description": "Return Document Text in Results", - "hint": "If True, each result will include the original document text. Default is False to reduce network overhead." - }, - "launch_model_if_not_running": { - "description": "Auto-start model if not running", - "hint": "If the model is not running in Xinference, attempt to start it automatically. Recommended to disable in production." - }, - "modalities": { - "description": "Model capabilities", - "hint": "Modalities supported by the model. If the model does not support images, uncheck image.", - "labels": [ - "Text", - "Image", - "Audio", - "Tool use" - ] - }, - "custom_headers": { - "description": "Custom request headers", - "hint": "Key/value pairs added here are merged into the OpenAI SDK default_headers for custom HTTP headers. Values must be strings." - }, - "ollama_disable_thinking": { - "description": "Disable thinking mode", - "hint": "Close Ollama thinking mode." - }, - "custom_extra_body": { - "description": "Custom request body parameters", - "hint": "Add extra parameters to requests, such as temperature, top_p, max_tokens, etc.", - "template_schema": { - "temperature": { - "description": "Temperature", - "hint": "Controls randomness, typically 0-2. Higher is more random.", - "name": "Temperature" - }, - "top_p": { - "description": "Top-p sampling", - "hint": "Nucleus sampling parameter, usually 0-1. Controls probability mass considered.", - "name": "Top-p" - }, - "max_tokens": { - "description": "Max tokens", - "hint": "Maximum number of generated tokens.", - "name": "Max Tokens" - } - } - }, - "gpt_weights_path": { - "description": "GPT model file path", - "hint": "The .ckpt file. Use an absolute path without quotes. Leave empty to use the GPT_SoVITS built-in SoVITS model (recommended to change defaults in GPT_SoVITS)." - }, - "sovits_weights_path": { - "description": "SoVITS model file path", - "hint": "The .pth file. Use an absolute path without quotes. Leave empty to use the GPT_SoVITS built-in SoVITS model (recommended to change defaults in GPT_SoVITS)." - }, - "gsv_default_parms": { - "description": "GPT_SoVITS default parameters", - "hint": "Reference audio file path and text are required; other parameters are optional.", - "gsv_ref_audio_path": { - "description": "Reference audio file path", - "hint": "Required! Use an absolute path without quotes." - }, - "gsv_prompt_text": { - "description": "Reference audio text", - "hint": "Required! Provide the transcript of the reference audio." - }, - "gsv_prompt_lang": { - "description": "Reference audio text language", - "hint": "Language of the reference audio text; default is Chinese." - }, - "gsv_aux_ref_audio_paths": { - "description": "Auxiliary reference audio file paths", - "hint": "Auxiliary reference audio files; optional." - }, - "gsv_text_lang": { - "description": "Text language", - "hint": "Default is Chinese." - }, - "gsv_top_k": { - "description": "Speech diversity", - "hint": "" - }, - "gsv_top_p": { - "description": "Nucleus sampling threshold", - "hint": "" - }, - "gsv_temperature": { - "description": "Speech randomness", - "hint": "" - }, - "gsv_text_split_method": { - "description": "Text splitting method", - "hint": "Options: `cut0` no split, `cut1` split every 4 sentences, `cut2` split every 50 chars, `cut3` split by Chinese period, `cut4` split by English period, `cut5` split by punctuation." - }, - "gsv_batch_size": { - "description": "Batch size", - "hint": "" - }, - "gsv_batch_threshold": { - "description": "Batch threshold", - "hint": "" - }, - "gsv_split_bucket": { - "description": "Split text into buckets for parallel processing", - "hint": "" - }, - "gsv_speed_factor": { - "description": "Speech playback speed", - "hint": "1 is the original speed." - }, - "gsv_fragment_interval": { - "description": "Interval between speech segments", - "hint": "" - }, - "gsv_streaming_mode": { - "description": "Enable streaming mode", - "hint": "" - }, - "gsv_seed": { - "description": "Random seed", - "hint": "For reproducible results." - }, - "gsv_parallel_infer": { - "description": "Run inference in parallel", - "hint": "" - }, - "gsv_repetition_penalty": { - "description": "Repetition penalty", - "hint": "" - }, - "gsv_media_type": { - "description": "Output media type", - "hint": "Recommended: wav" - } - }, - "embedding_dimensions": { - "description": "Embedding dimensions", - "hint": "Embedding vector dimensions. May need adjustment per model; see model documentation. This must be correct or the vector database will not work." - }, - "embedding_dimensions_mode": { - "description": "Embedding dimensions mode", - "hint": "Controls whether to send the dimensions parameter in OpenAI-compatible embedding requests. auto sends it only for official OpenAI embedding-3 models; use always when a compatible API supports it, or never when it rejects the parameter." - }, - "embedding_model": { - "description": "Embedding model", - "hint": "Embedding model name." - }, - "embedding_api_key": { - "description": "API Key" - }, - "embedding_api_base": { - "description": "API Base URL" - }, - "openai_embedding": { - "hint": "If testing fails, try adding /v1 at the end for some OpenAI API versions." - }, - "gemini_embedding": { - "hint": "Gemini Embedding does not require manually adding /v1beta." - }, - "volcengine_cluster": { - "description": "Volcengine cluster", - "hint": "For voice cloning models, choose volcano_icl or volcano_icl_concurr; default is volcano_tts." - }, - "volcengine_voice_type": { - "description": "Volcengine voice", - "hint": "Enter voice id (Voice_type)." - }, - "volcengine_speed_ratio": { - "description": "Speech rate", - "hint": "Speech rate, range 0.2 to 3.0, default 1.0." - }, - "volcengine_volume_ratio": { - "description": "Volume", - "hint": "Volume, range 0.0 to 2.0, default 1.0." - }, - "azure_tts_voice": { - "description": "Voice style", - "hint": "API voice name" - }, - "azure_tts_style": { - "description": "Style", - "hint": "A voice-specific speaking style. Can express emotions like happy, sympathetic, and calm." - }, - "azure_tts_role": { - "description": "Role (optional)", - "hint": "Speaking role-play. The voice can emulate different ages and genders without changing the voice name. For example, a male voice can raise pitch to simulate a female voice, but the voice name does not change. If the role is missing or unsupported, this attribute is ignored." - }, - "azure_tts_rate": { - "description": "Speech rate", - "hint": "Controls speaking rate. You can apply the rate at word or sentence level. Rate should be 0.5x to 2x of original audio." - }, - "azure_tts_volume": { - "description": "Speech volume", - "hint": "Controls volume level. You can apply changes at sentence level. Use 0.0 to 100.0 (quiet to loud, e.g., 75). Default is 100.0." - }, - "azure_tts_region": { - "description": "API region", - "hint": "Region where Azure TTS processes data. See https://learn.microsoft.com/zh-cn/azure/ai-services/speech-service/regions" - }, - "azure_tts_subscription_key": { - "description": "Service subscription key", - "hint": "Azure TTS subscription key (not a token)." - }, - "dashscope_tts_voice": { - "description": "Voice" - }, - "gm_resp_image_modal": { - "description": "Enable image modality", - "hint": "When enabled, responses can include images. Requires model support or it will error. See the Google Gemini website for supported models. Tip: if you need image generation, disable the `Enable member recognition` setting for better results." - }, - "gm_native_search": { - "description": "Enable native search", - "hint": "When enabled, all function tools are disabled. Check official docs for free quota limits." - }, - "gm_native_coderunner": { - "description": "Enable native code runner", - "hint": "When enabled, all function tools are disabled." - }, - "gm_url_context": { - "description": "Enable URL context", - "hint": "When enabled, all function tools are disabled." - }, - "gm_safety_settings": { - "description": "Safety filters", - "hint": "Set the safety filtering level for model input. Levels: NONE (no blocking), HIGH (block high risk), MEDIUM_AND_ABOVE (block medium risk and above), LOW_AND_ABOVE (block low risk and above). See Gemini API docs.", - "harassment": { - "description": "Harassment", - "hint": "Negative or harmful comments" - }, - "hate_speech": { - "description": "Hate speech", - "hint": "Rude, disrespectful, or profane content" - }, - "sexually_explicit": { - "description": "Sexually explicit content", - "hint": "References to sexual acts or other obscene content" - }, - "dangerous_content": { - "description": "Dangerous content", - "hint": "Content that promotes, encourages, or assists harmful behavior" - } - }, - "gm_thinking_config": { - "description": "Thinking Config", - "budget": { - "description": "Thinking Budget", - "hint": "Guides the model on the specific number of thinking tokens to use for reasoning. See: https://ai.google.dev/gemini-api/docs/thinking#set-budget" - }, - "level": { - "description": "Thinking Level", - "hint": "Recommended for Gemini 3 models and onwards, lets you control reasoning behavior.See: https://ai.google.dev/gemini-api/docs/thinking#thinking-levels" - } - }, - "anth_thinking_config": { - "description": "Thinking Config", - "type": { - "description": "Thinking Type", - "hint": "Set 'adaptive' for Opus 4.6+ / Sonnet 4.6+ (recommended). Leave empty to use manual budget mode. See: https://platform.claude.com/docs/en/build-with-claude/adaptive-thinking" - }, - "budget": { - "description": "Thinking Budget", - "hint": "Anthropic thinking.budget_tokens param. Must >= 1024. Only used when type is empty. Deprecated on Opus 4.6 / Sonnet 4.6. See: https://platform.claude.com/docs/en/build-with-claude/extended-thinking" - }, - "effort": { - "description": "Effort Level", - "hint": "Controls thinking depth when type is 'adaptive'. 'high' is the default. 'max' is Opus 4.6 only. See: https://platform.claude.com/docs/en/build-with-claude/effort" - } - }, - "minimax-group-id": { - "description": "User group", - "hint": "Visible in Account Management -> Basic Info." - }, - "minimax-langboost": { - "description": "Target language/dialect", - "hint": "Enhances recognition for specified languages/dialects and improves speech performance in those scenarios." - }, - "minimax-voice-speed": { - "description": "Speech rate", - "hint": "Speech speed for synthesis, range [0.5, 2], default 1.0. Higher is faster." - }, - "minimax-voice-vol": { - "description": "Volume", - "hint": "Volume for synthesis, range (0, 10], default 1.0. Higher is louder." - }, - "minimax-voice-pitch": { - "description": "Pitch", - "hint": "Pitch for synthesis, range [-12, 12], default 0." - }, - "minimax-is-timber-weight": { - "description": "Enable mixed voices", - "hint": "Enable mixing up to four voices with custom weights. When enabled, single voice settings are ignored." - }, - "minimax-timber-weight": { - "description": "Mixed voices", - "hint": "Mixed voices and their weights. Up to four voices, integer weights in [1, 100]. Get presets and templates from the official API TTS debug console. Must be a JSON string; check the console to confirm parsing. See defaults and the official code preview for structure." - }, - "minimax-voice-id": { - "description": "Single voice", - "hint": "Single voice ID; see the official documentation." - }, - "minimax-voice-emotion": { - "description": "Emotion", - "hint": "Controls emotion of synthesized speech. When set to auto, it selects emotion based on text." - }, - "minimax-voice-latex": { - "description": "Read LaTeX formulas", - "hint": "Read LaTeX formulas, but ensure input text is formatted per the official requirements." - }, - "minimax-voice-english-normalization": { - "description": "English text normalization", - "hint": "Improves number-reading performance but slightly increases latency." - }, - "rag_options": { - "description": "RAG options", - "hint": "Knowledge base retrieval settings, optional. Only supported for Agent app types (agent apps, including RAG apps). For Bailian apps, enabling this disables multi-turn conversations.", - "pipeline_ids": { - "description": "Knowledge base ID list", - "hint": "Retrieve all documents in the specified knowledge bases. Go to https://bailian.console.aliyun.com/ Data Apps -> Knowledge Index to create and get IDs." - }, - "file_ids": { - "description": "Unstructured document IDs", - "hint": "Retrieve specified unstructured documents. Go to https://bailian.console.aliyun.com/ Data Management to create and get IDs." - }, - "output_reference": { - "description": "Output knowledge base/document references", - "hint": "Append reference sources to the end of each answer. Default is False." - } - }, - "sensevoice_hint": { - "description": "Deploy SenseVoice", - "hint": "Before enabling, install funasr, funasr_onnx, torchaudio, torch, modelscope, and jieba (CPU by default, about 1 GB download), and install ffmpeg. Otherwise STT will not work." - }, - "is_emotion": { - "description": "Emotion recognition", - "hint": "Enable emotion recognition. happy?sad?angry?neutral?fearful?disgusted?surprised?unknown" - }, - "stt_model": { - "description": "Model name", - "hint": "Model name on modelscope. Default: iic/SenseVoiceSmall." - }, - "variables": { - "description": "Workflow fixed input variables", - "hint": "Optional. Fixed workflow input variables are used as workflow inputs. You can also set variables dynamically with /set during a chat. If names conflict, dynamic settings take precedence." - }, - "dashscope_app_type": { - "description": "App type", - "hint": "Bailian app type." - }, - "timeout": { - "description": "Timeout", - "hint": "Timeout in seconds." - }, - "openai-tts-voice": { - "description": "voice", - "hint": "OpenAI TTS voice. OpenAI defaults: 'alloy', 'echo', 'fable', 'onyx', 'nova', 'shimmer'." - }, - "elevenlabs-tts-voice-id": { - "description": "Voice ID", - "hint": "ElevenLabs voice ID. Browse and copy voice IDs at https://elevenlabs.io/app/voice-library. Default 'JBFqnCBsd6RMkjVDRZzb' (George)." - }, - "elevenlabs-tts-output-format": { - "description": "Output format", - "hint": "Audio output format, e.g. 'mp3_44100_128', 'mp3_22050_32', 'wav_44100', or 'opus_48000_128'. Raw PCM/u-law/a-law formats are not supported. Default 'mp3_44100_128'." - }, - "elevenlabs-tts-stability": { - "description": "Stability", - "hint": "Voice stability, range [0, 1]. Higher is more consistent, lower is more expressive. Leave empty to use the server default." - }, - "elevenlabs-tts-similarity-boost": { - "description": "Similarity boost", - "hint": "How closely the output matches the original voice, range [0, 1]. Leave empty to use the server default." - }, - "elevenlabs-tts-style": { - "description": "Style exaggeration", - "hint": "Style exaggeration of the voice, range [0, 1]. Higher values increase latency. Leave empty to use the server default." - }, - "elevenlabs-tts-use-speaker-boost": { - "description": "Speaker boost", - "hint": "Boost similarity to the original speaker. May slightly increase latency." - }, - "mimo-tts-voice": { - "description": "Voice", - "hint": "MiMo TTS voice name. Supported values include 'mimo_default', 'default_en', and 'default_zh'." - }, - "mimo-tts-format": { - "description": "Output format", - "hint": "Audio format generated by MiMo TTS. Supported values: 'wav', 'mp3', and 'pcm'." - }, - "mimo-tts-style-prompt": { - "description": "Style prompt", - "hint": "Prepended to the synthesis target text as a tag to control speed, emotion, character, or style, such as happy, faster, Sun Wukong, or whispering. Optional." - }, - "mimo-tts-dialect": { - "description": "Dialect", - "hint": "Combined with the style prompt inside the leading tag, for example Northeastern Mandarin, Sichuan dialect, Henan dialect, or Cantonese. Optional." - }, - "mimo-tts-seed-text": { - "description": "Seed text", - "hint": "Sent as an optional user message to help guide tone and speaking style. It is not appended to the synthesis target text." - }, - "fishaudio-tts-character": { - "description": "character", - "hint": "Fishaudio TTS character. Default is Klee. More roles: https://fish.audio/zh-CN/discovery" - }, - "fishaudio-tts-reference-id": { - "description": "reference_id", - "hint": "Fishaudio TTS reference model ID (optional). If set, the model ID is used directly instead of looking up by role name. Example: 626bb6d3f3364c9cbc3aa6a67300a664. More models: https://fish.audio/zh-CN/discovery; open a model detail page to copy the model ID." - }, - "whisper_hint": { - "description": "Notes for local Whisper deployment", - "hint": "Before enabling, install the openai-whisper library (NVIDIA users download ~2GB mainly for torch and cuda; CPU users download ~1GB), and install ffmpeg. Otherwise STT will not work." - }, - "whisper_device": { - "description": "Inference device", - "hint": "Whisper inference device. Apple Silicon can use mps; other environments should use cpu. If mps is selected but unavailable, AstrBot will fall back to cpu." - }, - "id": { - "description": "ID" - }, - "type": { - "description": "Provider category" - }, - "provider_type": { - "description": "Provider capability type" - }, - "enable": { - "description": "Enable" - }, - "key": { - "description": "API Key" - }, - "api_base": { - "description": "API Base URL" - }, - "proxy": { - "description": "Proxy address", - "hint": "HTTP/HTTPS proxy URL, e.g. http://127.0.0.1:7890. Applies only to this provider's API requests and does not affect Docker internal networking." - }, - "model": { - "description": "Model ID", - "hint": "Model name, e.g., gpt-4o-mini, deepseek-chat." - }, - "max_context_tokens": { - "description": "Model context window size", - "hint": "Maximum context tokens. If 0, it auto-fills from model metadata (if available); you can also edit manually." - }, - "dify_api_key": { - "description": "API Key", - "hint": "Dify API Key. This field is required." - }, - "dify_api_base": { - "description": "API Base URL", - "hint": "Dify API Base URL. Default: https://api.dify.ai/v1" - }, - "dify_api_type": { - "description": "Dify app type", - "hint": "Dify API type. According to Dify docs, supported types are chat, chatflow, agent, workflow." - }, - "dify_workflow_output_key": { - "description": "Dify workflow output variable name", - "hint": "Dify workflow output variable name. Only used when app type is workflow. Default: astrbot_wf_output." - }, - "dify_query_input_key": { - "description": "Prompt input variable name", - "hint": "Input variable name for the message text. Default: astrbot_text_query." - }, - "coze_api_key": { - "description": "Coze API Key", - "hint": "Coze API key for accessing Coze services." - }, - "bot_id": { - "description": "Bot ID", - "hint": "Coze bot ID, obtained after creating a bot on the Coze platform." - }, - "coze_api_base": { - "description": "API Base URL", - "hint": "Base URL for the Coze API. Default: https://api.coze.cn" - }, - "deerflow_api_base": { - "description": "API Base URL", - "hint": "DeerFlow API gateway URL. Default: http://127.0.0.1:2026" - }, - "deerflow_api_key": { - "description": "DeerFlow API Key", - "hint": "Optional. Fill this if your DeerFlow gateway is protected by Bearer auth." - }, - "deerflow_auth_header": { - "description": "Authorization Header", - "hint": "Optional. Custom Authorization header value; takes precedence over DeerFlow API Key." - }, - "deerflow_assistant_id": { - "description": "Assistant ID", - "hint": "LangGraph assistant_id, default is lead_agent." - }, - "deerflow_model_name": { - "description": "Model name override", - "hint": "Optional. Overrides DeerFlow default model (maps to runtime context model_name)." - }, - "deerflow_thinking_enabled": { - "description": "Enable thinking mode" - }, - "deerflow_plan_mode": { - "description": "Enable plan mode", - "hint": "Maps to DeerFlow is_plan_mode." - }, - "deerflow_subagent_enabled": { - "description": "Enable subagent", - "hint": "Maps to DeerFlow subagent_enabled." - }, - "deerflow_max_concurrent_subagents": { - "description": "Max concurrent subagents", - "hint": "Maps to DeerFlow max_concurrent_subagents. Effective only when subagent is enabled. Default: 3." - }, - "deerflow_recursion_limit": { - "description": "Recursion limit", - "hint": "Maps to LangGraph recursion_limit." - }, - "auto_save_history": { - "description": "Conversation history managed by Coze", - "hint": "When enabled, Coze manages conversation history. AstrBot's locally saved context will not take effect (read-only), and operations on AstrBot context will not apply. If disabled, AstrBot manages the context." - } - } - }, - "help": { - "documentation": "Official Documentation", - "support": "Join Support Group", - "helpText": "Don't understand the configuration? See {documentation} or {support}.", - "helpPrefix": "Don't understand the configuration? See", - "helpMiddle": "or", - "helpSuffix": "." - } + "help": { + "documentation": "Official Documentation", + "support": "Join Support Group", + "helpText": "Don't understand the configuration? See {documentation} or {support}.", + "helpPrefix": "Don't understand the configuration? See", + "helpMiddle": "or", + "helpSuffix": ".", + }, } diff --git a/dashboard/src/i18n/locales/zh-CN/features/config-metadata.json b/dashboard/src/i18n/locales/zh-CN/features/config-metadata.json index 5036a51606..8151aebbf2 100644 --- a/dashboard/src/i18n/locales/zh-CN/features/config-metadata.json +++ b/dashboard/src/i18n/locales/zh-CN/features/config-metadata.json @@ -1,1790 +1,1583 @@ { - "ai_group": { - "name": "AI 配置", - "agent_runner": { - "description": "Agent 执行方式", - "hint": "选择 AI 对话的执行器,默认为 AstrBot 内置 Agent 执行器,可使用 AstrBot 内的知识库、人格、工具调用功能。如果不打算接入 Dify、Coze、DeerFlow 等第三方 Agent 执行器,不需要修改此节。", - "provider_settings": { - "enable": { - "description": "启用", - "hint": "AI 对话总开关" - }, - "agent_runner_type": { - "description": "执行器", - "labels": [ - "内置 Agent", - "Dify", - "Coze", - "阿里云百炼应用", - "DeerFlow" - ] - }, - "coze_agent_runner_provider_id": { - "description": "Coze Agent 执行器提供商 ID" - }, - "dify_agent_runner_provider_id": { - "description": "Dify Agent 执行器提供商 ID" - }, - "dashscope_agent_runner_provider_id": { - "description": "阿里云百炼应用 Agent 执行器提供商 ID" - }, - "deerflow_agent_runner_provider_id": { - "description": "DeerFlow Agent 执行器提供商 ID" - } - } - }, - "ai": { - "description": "模型", - "hint": "当使用非内置 Agent 执行器时,默认对话模型和默认图片转述模型可能会无效,但某些插件会依赖此配置项来调用 AI 能力。", - "provider_settings": { - "default_provider_id": { - "description": "默认对话模型", - "hint": "留空时使用第一个模型" - }, - "fallback_chat_models": { - "description": "回退对话模型列表", - "hint": "主对话模型请求失败时,按顺序切换到这些对话模型。" - }, - "request_max_retries": { - "description": "请求最大重试次数", - "hint": "单次模型请求遇到可重试错误时的最大尝试次数。" - }, - "default_image_caption_provider_id": { - "description": "默认图片转述模型", - "hint": "留空代表不使用,可用于非多模态模型" - }, - "image_caption_prompt": { - "description": "图片转述提示词" - } - }, - "provider_stt_settings": { - "enable": { - "description": "启用语音转文本", - "hint": "STT 总开关" - }, - "provider_id": { - "description": "默认语音转文本模型", - "hint": "用户也可使用 /provider 指令单独选择会话的 STT 模型。" - } - }, - "provider_tts_settings": { - "enable": { - "description": "启用文本转语音", - "hint": "TTS 总开关" - }, - "provider_id": { - "description": "默认文本转语音模型" - }, - "trigger_probability": { - "description": "TTS 触发概率" - } - } - }, - "persona": { - "description": "人格", - "hint": "赋予 AstrBot 人格。", - "provider_settings": { - "default_personality": { - "description": "默认采用的人格" - } - } - }, - "knowledgebase": { - "description": "知识库", - "hint": "AstrBot 的 “外置大脑”。", - "kb_names": { - "description": "知识库列表", - "hint": "支持多选" - }, - "kb_fusion_top_k": { - "description": "融合检索结果数", - "hint": "多个知识库检索结果融合后的返回结果数量" - }, - "kb_final_top_k": { - "description": "最终返回结果数", - "hint": "从知识库中检索到的结果数量,越大可能获得越多相关信息,但也可能引入噪音。建议根据实际需求调整" - }, - "kb_agentic_mode": { - "description": "Agentic 知识库检索", - "hint": "启用后,知识库检索将作为 LLM Tool,由模型自主决定何时调用知识库进行查询。需要模型支持函数调用能力。" - } - }, - "websearch": { - "description": "网页搜索", - "hint": "让 AstrBot 能够访问互联网,获悉时讯。", - "provider_settings": { - "web_search": { - "description": "启用网页搜索" - }, - "websearch_provider": { - "description": "网页搜索提供商" - }, - "websearch_tavily_key": { - "description": "Tavily API Key", - "hint": "可添加多个 Key 进行轮询。" - }, - "websearch_bocha_key": { - "description": "BoCha API Key", - "hint": "可添加多个 Key 进行轮询。" + "ai_group": { + "name": "AI 配置", + "agent_runner": { + "description": "Agent 执行方式", + "hint": "选择 AI 对话的执行器,默认为 AstrBot 内置 Agent 执行器,可使用 AstrBot 内的知识库、人格、工具调用功能。如果不打算接入 Dify、Coze、DeerFlow 等第三方 Agent 执行器,不需要修改此节。", + "provider_settings": { + "enable": {"description": "启用", "hint": "AI 对话总开关"}, + "agent_runner_type": { + "description": "执行器", + "labels": [ + "内置 Agent", + "Dify", + "Coze", + "阿里云百炼应用", + "DeerFlow", + ], + }, + "coze_agent_runner_provider_id": { + "description": "Coze Agent 执行器提供商 ID" + }, + "dify_agent_runner_provider_id": { + "description": "Dify Agent 执行器提供商 ID" + }, + "dashscope_agent_runner_provider_id": { + "description": "阿里云百炼应用 Agent 执行器提供商 ID" + }, + "deerflow_agent_runner_provider_id": { + "description": "DeerFlow Agent 执行器提供商 ID" + }, + }, }, - "websearch_brave_key": { - "description": "Brave Search API Key", - "hint": "可添加多个 Key 进行轮询。" + "ai": { + "description": "模型", + "hint": "当使用非内置 Agent 执行器时,默认对话模型和默认图片转述模型可能会无效,但某些插件会依赖此配置项来调用 AI 能力。", + "provider_settings": { + "default_provider_id": { + "description": "默认对话模型", + "hint": "留空时使用第一个模型", + }, + "fallback_chat_models": { + "description": "回退对话模型列表", + "hint": "主对话模型请求失败时,按顺序切换到这些对话模型。", + }, + "request_max_retries": { + "description": "请求最大重试次数", + "hint": "单次模型请求遇到可重试错误时的最大尝试次数。", + }, + "default_image_caption_provider_id": { + "description": "默认图片转述模型", + "hint": "留空代表不使用,可用于非多模态模型", + }, + "image_caption_prompt": {"description": "图片转述提示词"}, + }, + "provider_stt_settings": { + "enable": {"description": "启用语音转文本", "hint": "STT 总开关"}, + "provider_id": { + "description": "默认语音转文本模型", + "hint": "用户也可使用 /provider 指令单独选择会话的 STT 模型。", + }, + }, + "provider_tts_settings": { + "enable": {"description": "启用文本转语音", "hint": "TTS 总开关"}, + "provider_id": {"description": "默认文本转语音模型"}, + "trigger_probability": {"description": "TTS 触发概率"}, + }, }, - "websearch_firecrawl_key": { - "description": "Firecrawl API Key", - "hint": "可添加多个 Key 进行轮询。" + "persona": { + "description": "人格", + "hint": "赋予 AstrBot 人格。", + "provider_settings": { + "default_personality": {"description": "默认采用的人格"} + }, }, - "websearch_baidu_app_builder_key": { - "description": "百度千帆智能云 APP Builder API Key", - "hint": "参考:[https://console.bce.baidu.com/iam/#/iam/apikey/list](https://console.bce.baidu.com/iam/#/iam/apikey/list)" + "knowledgebase": { + "description": "知识库", + "hint": "AstrBot 的 “外置大脑”。", + "kb_names": {"description": "知识库列表", "hint": "支持多选"}, + "kb_fusion_top_k": { + "description": "融合检索结果数", + "hint": "多个知识库检索结果融合后的返回结果数量", + }, + "kb_final_top_k": { + "description": "最终返回结果数", + "hint": "从知识库中检索到的结果数量,越大可能获得越多相关信息,但也可能引入噪音。建议根据实际需求调整", + }, + "kb_agentic_mode": { + "description": "Agentic 知识库检索", + "hint": "启用后,知识库检索将作为 LLM Tool,由模型自主决定何时调用知识库进行查询。需要模型支持函数调用能力。", + }, }, - "web_search_link": { - "description": "显示来源引用" + "websearch": { + "description": "网页搜索", + "hint": "让 AstrBot 能够访问互联网,获悉时讯。", + "provider_settings": { + "web_search": {"description": "启用网页搜索"}, + "websearch_provider": {"description": "网页搜索提供商"}, + "websearch_tavily_key": { + "description": "Tavily API Key", + "hint": "可添加多个 Key 进行轮询。", + }, + "websearch_bocha_key": { + "description": "BoCha API Key", + "hint": "可添加多个 Key 进行轮询。", + }, + "websearch_brave_key": { + "description": "Brave Search API Key", + "hint": "可添加多个 Key 进行轮询。", + }, + "websearch_firecrawl_key": { + "description": "Firecrawl API Key", + "hint": "可添加多个 Key 进行轮询。", + }, + "websearch_baidu_app_builder_key": { + "description": "百度千帆智能云 APP Builder API Key", + "hint": "参考:[https://console.bce.baidu.com/iam/#/iam/apikey/list](https://console.bce.baidu.com/iam/#/iam/apikey/list)", + }, + "web_search_link": {"description": "显示来源引用"}, + "websearch_exa_key": { + "description": "Exa API Key", + "hint": "可添加多个 Key 进行轮询。获取 Key: https://dashboard.exa.ai", + }, + }, }, - "websearch_exa_key": { - "description": "Exa API Key", - "hint": "可添加多个 Key 进行轮询。获取 Key: https://dashboard.exa.ai" - } - } - }, - "file_extract": { - "description": "文档解析能力", - "provider_settings": { "file_extract": { - "enable": { - "description": "启用文档解析能力" - }, - "provider": { - "description": "文档解析提供商" - }, - "moonshotai_api_key": { - "description": "Moonshot AI API Key" - } - } - } - }, - "agent_computer_use": { - "description": "使用电脑能力", - "hint": "让 AstrBot 访问和使用本机环境或者隔离的沙盒环境,以执行更复杂的任务。详见: [电脑使用](https://docs.astrbot.app/use/computer.html)。", - "provider_settings": { - "computer_use_runtime": { - "description": "运行环境", - "hint": "允许 Agent 访问的环境。local 为本机环境,sandbox 为沙箱环境,none 为不允许任何环境。" + "description": "文档解析能力", + "provider_settings": { + "file_extract": { + "enable": {"description": "启用文档解析能力"}, + "provider": {"description": "文档解析提供商"}, + "moonshotai_api_key": {"description": "Moonshot AI API Key"}, + } + }, }, - "computer_use_require_admin": { - "description": "需要 AstrBot 管理员权限", - "hint": "开启后,需要 AstrBot 管理员权限才能调用使用电脑能力。在平台配置->管理员中可添加管理员。使用 /sid 指令查看管理员 ID。" + "agent_computer_use": { + "description": "使用电脑能力", + "hint": "让 AstrBot 访问和使用本机环境或者隔离的沙盒环境,以执行更复杂的任务。详见: [电脑使用](https://docs.astrbot.app/use/computer.html)。", + "provider_settings": { + "computer_use_runtime": { + "description": "运行环境", + "hint": "允许 Agent 访问的环境。local 为本机环境,sandbox 为沙箱环境,none 为不允许任何环境。", + }, + "computer_use_require_admin": { + "description": "需要 AstrBot 管理员权限", + "hint": "开启后,需要 AstrBot 管理员权限才能调用使用电脑能力。在平台配置->管理员中可添加管理员。使用 /sid 指令查看管理员 ID。", + }, + "sandbox": { + "booter": {"description": "沙箱环境驱动器"}, + "shipyard_neo_endpoint": { + "description": "Shipyard Neo API Endpoint", + "hint": "Shipyard Neo(Bay) 服务的 API 地址,默认 http://127.0.0.1:8114。", + }, + "shipyard_neo_access_token": { + "description": "Shipyard Neo 访问令牌", + "hint": "Bay 的 API Key(sk-bay-...)。留空时自动从 credentials.json 发现。", + }, + "shipyard_neo_profile": { + "description": "Shipyard Neo Profile", + "hint": "Shipyard Neo 沙箱 profile,例如 python-default。留空时自动选择能力更完整的 profile。", + }, + "shipyard_neo_ttl": { + "description": "Shipyard Neo Sandbox 存活时间(秒)", + "hint": "Shipyard Neo 沙箱的生存时间(秒)。", + }, + "cua_image": { + "description": "CUA 镜像", + "hint": "CUA 沙箱镜像/系统类型,默认 linux。可填写 linux、macos、windows、android,具体取决于 CUA SDK 支持。", + }, + "cua_os_type": { + "description": "CUA 操作系统类型", + "hint": "CUA 沙箱操作系统类型,默认 linux。", + }, + "cua_idle_timeout": { + "description": "CUA 空闲超时(秒)", + "hint": "CUA 沙箱空闲超时时间(秒)。大于 0 时,AstrBot 会在会话空闲达到该时长后主动关闭 CUA 沙箱;0 表示禁用。", + }, + "cua_telemetry_enabled": { + "description": "CUA 遥测", + "hint": "是否允许 CUA SDK 发送遥测数据。默认关闭。", + }, + "cua_local": { + "description": "CUA 本地沙箱", + "hint": "是否优先使用 CUA 本地沙箱。默认开启,避免云端沙箱要求 CUA_API_KEY。关闭后可使用 CUA 云端沙箱。", + }, + "cua_api_key": { + "description": "CUA API Key", + "hint": "CUA 云端沙箱 API Key。仅在关闭本地沙箱时需要。也可以通过 CUA_API_KEY 环境变量提供。", + }, + "shipyard_endpoint": { + "description": "Shipyard API Endpoint", + "hint": "Shipyard 服务的 API 访问地址。", + }, + "shipyard_access_token": { + "description": "Shipyard 访问令牌", + "hint": "用于访问 Shipyard 服务的访问令牌。", + }, + "shipyard_ttl": { + "description": "Shipyard Ship 存活时间(秒)", + "hint": "Shipyard 会话的生存时间(秒)。", + }, + "shipyard_max_sessions": { + "description": "Shipyard Ship 会话复用上限", + "hint": "决定了一个实例承载的最大会话数量。", + }, + }, + }, }, - "sandbox": { - "booter": { - "description": "沙箱环境驱动器" - }, - "shipyard_neo_endpoint": { - "description": "Shipyard Neo API Endpoint", - "hint": "Shipyard Neo(Bay) 服务的 API 地址,默认 http://127.0.0.1:8114。" - }, - "shipyard_neo_access_token": { - "description": "Shipyard Neo 访问令牌", - "hint": "Bay 的 API Key(sk-bay-...)。留空时自动从 credentials.json 发现。" - }, - "shipyard_neo_profile": { - "description": "Shipyard Neo Profile", - "hint": "Shipyard Neo 沙箱 profile,例如 python-default。留空时自动选择能力更完整的 profile。" - }, - "shipyard_neo_ttl": { - "description": "Shipyard Neo Sandbox 存活时间(秒)", - "hint": "Shipyard Neo 沙箱的生存时间(秒)。" - }, - "cua_image": { - "description": "CUA 镜像", - "hint": "CUA 沙箱镜像/系统类型,默认 linux。可填写 linux、macos、windows、android,具体取决于 CUA SDK 支持。" - }, - "cua_os_type": { - "description": "CUA 操作系统类型", - "hint": "CUA 沙箱操作系统类型,默认 linux。" - }, - "cua_idle_timeout": { - "description": "CUA 空闲超时(秒)", - "hint": "CUA 沙箱空闲超时时间(秒)。大于 0 时,AstrBot 会在会话空闲达到该时长后主动关闭 CUA 沙箱;0 表示禁用。" - }, - "cua_telemetry_enabled": { - "description": "CUA 遥测", - "hint": "是否允许 CUA SDK 发送遥测数据。默认关闭。" - }, - "cua_local": { - "description": "CUA 本地沙箱", - "hint": "是否优先使用 CUA 本地沙箱。默认开启,避免云端沙箱要求 CUA_API_KEY。关闭后可使用 CUA 云端沙箱。" - }, - "cua_api_key": { - "description": "CUA API Key", - "hint": "CUA 云端沙箱 API Key。仅在关闭本地沙箱时需要。也可以通过 CUA_API_KEY 环境变量提供。" - }, - "shipyard_endpoint": { - "description": "Shipyard API Endpoint", - "hint": "Shipyard 服务的 API 访问地址。" - }, - "shipyard_access_token": { - "description": "Shipyard 访问令牌", - "hint": "用于访问 Shipyard 服务的访问令牌。" - }, - "shipyard_ttl": { - "description": "Shipyard Ship 存活时间(秒)", - "hint": "Shipyard 会话的生存时间(秒)。" - }, - "shipyard_max_sessions": { - "description": "Shipyard Ship 会话复用上限", - "hint": "决定了一个实例承载的最大会话数量。" - } - } - } - }, - "proactive_capability": { - "description": "主动型能力", - "hint": "让 AstrBot 能够在某一时刻自动唤醒,帮你完成任务。详见: [主动型 Agent](https://docs.astrbot.app/use/proactive-agent.html)。", - "provider_settings": { "proactive_capability": { - "add_cron_tools": { - "description": "启用", - "hint": "启用后,将会传递给 Agent 相关工具来实现主动型 Agent。你可以告诉 AstrBot 未来某个时间要做的事情,它将被定时触发然后执行任务,然后将结果发送给你。" - } - } - } - }, - "truncate_and_compress": { - "hint": "AstrBot 如何管理工作记忆。详见: [上下文管理策略](https://docs.astrbot.app/use/context-compress.html)。", - "description": "上下文管理策略", - "provider_settings": { - "max_context_length": { - "description": "压缩前最多保留对话轮数", - "hint": "普通会话历史超过该轮数后,才会按下方策略进行持久化截断或 LLM 压缩;请求发送前也会先按该值约束上下文。-1 表示不按轮数限制。" - }, - "dequeue_context_length": { - "description": "轮次超限时一次丢弃轮数", - "hint": "当超过\"压缩前最多保留对话轮数\"且无法使用 LLM 压缩时,一次丢弃多少轮旧对话;请求期截断也会复用该值。" - }, - "context_limit_reached_strategy": { - "description": "历史超限或上下文接近上限时的处理方式", - "labels": [ - "按对话轮数截断", - "由 LLM 压缩上下文" - ], - "hint": "普通会话历史仅在超过\"压缩前最多保留对话轮数\"后执行该策略;请求发送前也会在上下文 token 接近模型窗口时使用同一策略保护本次请求。" - }, - "llm_compress_instruction": { - "description": "上下文压缩提示词", - "hint": "如果为空则使用默认提示词。" + "description": "主动型能力", + "hint": "让 AstrBot 能够在某一时刻自动唤醒,帮你完成任务。详见: [主动型 Agent](https://docs.astrbot.app/use/proactive-agent.html)。", + "provider_settings": { + "proactive_capability": { + "add_cron_tools": { + "description": "启用", + "hint": "启用后,将会传递给 Agent 相关工具来实现主动型 Agent。你可以告诉 AstrBot 未来某个时间要做的事情,它将被定时触发然后执行任务,然后将结果发送给你。", + } + } + }, }, - "llm_compress_keep_recent_ratio": { - "description": "压缩时保留最近上下文比例", - "hint": "按当前上下文 token 数保留最近内容,范围 0-0.3。0.15 表示保留 15%;比例大于 0 时至少保留最后一轮。" + "truncate_and_compress": { + "hint": "AstrBot 如何管理工作记忆。详见: [上下文管理策略](https://docs.astrbot.app/use/context-compress.html)。", + "description": "上下文管理策略", + "provider_settings": { + "max_context_length": { + "description": "压缩前最多保留对话轮数", + "hint": "普通会话历史超过该轮数后,才会按下方策略进行持久化截断或 LLM 压缩;请求发送前也会先按该值约束上下文。-1 表示不按轮数限制。", + }, + "dequeue_context_length": { + "description": "轮次超限时一次丢弃轮数", + "hint": '当超过"压缩前最多保留对话轮数"且无法使用 LLM 压缩时,一次丢弃多少轮旧对话;请求期截断也会复用该值。', + }, + "context_limit_reached_strategy": { + "description": "历史超限或上下文接近上限时的处理方式", + "labels": ["按对话轮数截断", "由 LLM 压缩上下文"], + "hint": '普通会话历史仅在超过"压缩前最多保留对话轮数"后执行该策略;请求发送前也会在上下文 token 接近模型窗口时使用同一策略保护本次请求。', + }, + "llm_compress_instruction": { + "description": "上下文压缩提示词", + "hint": "如果为空则使用默认提示词。", + }, + "llm_compress_keep_recent_ratio": { + "description": "压缩时保留最近上下文比例", + "hint": "按当前上下文 token 数保留最近内容,范围 0-0.3。0.15 表示保留 15%;比例大于 0 时至少保留最后一轮。", + }, + "llm_compress_provider_id": { + "description": "用于上下文压缩的模型提供商 ID", + "hint": '留空时使用当前聊天模型进行压缩;如果模型不可用或压缩失败,将回退为"按对话轮数截断"的策略。', + }, + "fallback_max_context_tokens": { + "description": "上下文窗口兜底值", + "hint": "当 max_context_tokens 为 0 且模型不在内置元数据中时,使用此值作为上下文窗口大小。默认 128000。", + }, + }, }, - "llm_compress_provider_id": { - "description": "用于上下文压缩的模型提供商 ID", - "hint": "留空时使用当前聊天模型进行压缩;如果模型不可用或压缩失败,将回退为\"按对话轮数截断\"的策略。" + "others": { + "description": "其他配置", + "provider_settings": { + "display_reasoning_text": {"description": "显示思考内容"}, + "llm_safety_mode": { + "description": "健康模式", + "hint": "引导模型输出健康、安全、积极的内容,避免有害或敏感话题。", + }, + "safety_mode_strategy": { + "description": "健康模式策略", + "hint": "选择健康模式的实现方式。", + }, + "identifier": { + "description": "用户识别", + "hint": "启用后,会在提示词前包含用户 ID 信息。", + }, + "group_name_display": { + "description": "显示群名称", + "hint": "启用后,在支持的平台(OneBot v11)上会在提示词前包含群名称信息。", + }, + "datetime_system_prompt": { + "description": "现实世界时间感知", + "hint": "启用后,会在系统提示词中附带当前时间信息。", + }, + "show_tool_use_status": {"description": "输出函数调用状态"}, + "show_tool_call_result": { + "description": "输出函数调用返回结果", + "hint": "仅在启用“输出函数调用状态”时生效,且最多展示 70 个字符。", + }, + "buffer_intermediate_messages": { + "description": "合并 Agent 中间消息", + "hint": "开启后,非流式模式下多步工具调用过程中产生的中间文本将缓冲,待 Agent 完成后合并为一条回复发送。", + }, + "sanitize_context_by_modalities": { + "description": "按模型能力清理历史上下文", + "hint": "开启后,在每次请求 LLM 前会按当前模型提供商中所选择的模型能力删除对话中不支持的图片/工具调用结构(会改变模型看到的历史)", + }, + "max_quoted_fallback_images": { + "description": "转发消息中图片获取上限", + "hint": "转发消息解析到的图片最多注入数量,超出部分会截断。", + }, + "quoted_message_parser": { + "max_component_chain_depth": { + "description": "转发消息富文本解析深度", + "hint": "解析转发消息中的富文本组件链时允许的最大递归深度。", + }, + "max_forward_node_depth": { + "description": "转发消息嵌套解析深度", + "hint": "解析嵌套转发节点时允许的最大递归深度。", + }, + "max_forward_fetch": { + "description": "转发消息递归拉取上限", + "hint": "递归调用 get_forward_msg 拉取转发内容的最大次数。", + }, + "warn_on_action_failure": { + "description": "转发消息解析失败告警", + "hint": "开启后,get_msg/get_forward_msg 全部尝试失败时输出 warning 日志。", + }, + }, + "max_agent_step": {"description": "工具调用轮数上限"}, + "tool_call_timeout": {"description": "工具调用超时时间(秒)"}, + "tool_schema_mode": { + "description": "工具调用模式", + "hint": "skills-like 先下发工具名称与描述,再下发参数;full 一次性下发完整参数。", + "labels": ["Skills-like(两阶段)", "Full(完整参数)"], + }, + "streaming_response": {"description": "流式输出"}, + "unsupported_streaming_strategy": { + "description": "不支持流式回复的平台", + "hint": "选择在不支持流式回复的平台上的处理方式。实时分段回复会在系统接收流式响应检测到诸如标点符号等分段点时,立即发送当前已接收的内容", + "labels": ["实时分段回复", "关闭流式回复"], + }, + "wake_prefix": { + "description": "LLM 聊天额外唤醒前缀", + "hint": "如果唤醒前缀为 /, 额外聊天唤醒前缀为 chat,则需要 /chat 才会触发 LLM 请求", + }, + "prompt_prefix": { + "description": "用户提示词", + "hint": "可使用 {{prompt}} 作为用户输入的占位符。如果不输入占位符则代表添加在用户输入的前面。", + }, + "image_compress_enabled": { + "description": "启用图片压缩", + "hint": "启用后,发送给多模态模型前会先压缩本地大图片。", + }, + "image_compress_options": { + "description": "图片压缩配置", + "hint": "用于控制图片压缩的尺寸、质量和触发阈值。", + "max_size": { + "description": "最大边长", + "hint": "压缩后图片的最长边,单位为像素。超过该尺寸时会按比例缩放。", + }, + "quality": { + "description": "JPEG 质量", + "hint": "JPEG 输出质量,范围为 1-100。值越高,画质越好,文件也越大。", + }, + }, + "reachability_check": { + "description": "提供商可达性检测", + "hint": "/provider 命令列出模型时并发检测连通性。开启后会主动调用模型测试连通性,可能产生额外 token 消耗。", + }, + }, + "provider_tts_settings": { + "dual_output": {"description": "开启 TTS 时同时输出语音和文字内容"} + }, }, - "fallback_max_context_tokens": { - "description": "上下文窗口兜底值", - "hint": "当 max_context_tokens 为 0 且模型不在内置元数据中时,使用此值作为上下文窗口大小。默认 128000。" - } - } }, - "others": { - "description": "其他配置", - "provider_settings": { - "display_reasoning_text": { - "description": "显示思考内容" - }, - "llm_safety_mode": { - "description": "健康模式", - "hint": "引导模型输出健康、安全、积极的内容,避免有害或敏感话题。" - }, - "safety_mode_strategy": { - "description": "健康模式策略", - "hint": "选择健康模式的实现方式。" - }, - "identifier": { - "description": "用户识别", - "hint": "启用后,会在提示词前包含用户 ID 信息。" - }, - "group_name_display": { - "description": "显示群名称", - "hint": "启用后,在支持的平台(OneBot v11)上会在提示词前包含群名称信息。" - }, - "datetime_system_prompt": { - "description": "现实世界时间感知", - "hint": "启用后,会在系统提示词中附带当前时间信息。" - }, - "show_tool_use_status": { - "description": "输出函数调用状态" - }, - "show_tool_call_result": { - "description": "输出函数调用返回结果", - "hint": "仅在启用“输出函数调用状态”时生效,且最多展示 70 个字符。" - }, - "buffer_intermediate_messages": { - "description": "合并 Agent 中间消息", - "hint": "开启后,非流式模式下多步工具调用过程中产生的中间文本将缓冲,待 Agent 完成后合并为一条回复发送。" - }, - "sanitize_context_by_modalities": { - "description": "按模型能力清理历史上下文", - "hint": "开启后,在每次请求 LLM 前会按当前模型提供商中所选择的模型能力删除对话中不支持的图片/工具调用结构(会改变模型看到的历史)" - }, - "max_quoted_fallback_images": { - "description": "转发消息中图片获取上限", - "hint": "转发消息解析到的图片最多注入数量,超出部分会截断。" - }, - "quoted_message_parser": { - "max_component_chain_depth": { - "description": "转发消息富文本解析深度", - "hint": "解析转发消息中的富文本组件链时允许的最大递归深度。" - }, - "max_forward_node_depth": { - "description": "转发消息嵌套解析深度", - "hint": "解析嵌套转发节点时允许的最大递归深度。" - }, - "max_forward_fetch": { - "description": "转发消息递归拉取上限", - "hint": "递归调用 get_forward_msg 拉取转发内容的最大次数。" - }, - "warn_on_action_failure": { - "description": "转发消息解析失败告警", - "hint": "开启后,get_msg/get_forward_msg 全部尝试失败时输出 warning 日志。" - } - }, - "max_agent_step": { - "description": "工具调用轮数上限" - }, - "tool_call_timeout": { - "description": "工具调用超时时间(秒)" - }, - "tool_schema_mode": { - "description": "工具调用模式", - "hint": "skills-like 先下发工具名称与描述,再下发参数;full 一次性下发完整参数。", - "labels": [ - "Skills-like(两阶段)", - "Full(完整参数)" - ] - }, - "streaming_response": { - "description": "流式输出" + "platform_group": { + "name": "平台配置", + "platform": { + "description": "消息平台适配器", + "active_send_mode": {"description": "是否换用主动发送接口"}, + "appid": { + "description": "appid", + "hint": "必填项。当前消息平台的 AppID。如何获取请参考对应平台接入文档。", + }, + "callback_server_host": { + "description": "回调服务器主机", + "hint": "回调服务器主机。留空则不启用回调服务器。", + }, + "card_template_id": { + "description": "卡片模板 ID", + "hint": "可选。钉钉互动卡片模板 ID。启用后将使用互动卡片进行流式回复。", + }, + "discord_activity_name": { + "description": "Discord 活动名称", + "hint": "可选的 Discord 活动名称。留空则不设置活动。", + }, + "discord_allow_bot_messages": { + "description": "允许接收机器人消息", + "hint": "启用后,AstrBot 将接收来自其他 Discord 机器人的消息。适用于机器人间通信场景(如消息转发)。默认关闭。", + }, + "discord_command_register": { + "description": "注册 Discord 指令", + "hint": "启用后,自动将插件指令注册为 Discord 斜杠指令", + }, + "discord_proxy": { + "description": "Discord 代理地址", + "hint": "可选的代理地址:http://ip:port", + }, + "discord_token": { + "description": "Discord Bot Token", + "hint": "在此处填入你的 Discord Bot Token", + }, + "enable": { + "description": "启用", + "hint": "是否启用该适配器。未启用的适配器对应的消息平台将不会接收到消息。", + }, + "enable_group_c2c": { + "description": "启用消息列表单聊", + "hint": "启用后,机器人可以接收到 QQ 消息列表中的私聊消息。你可能需要在 QQ 机器人平台上通过扫描二维码的方式添加机器人为你的好友。详见文档。", + }, + "enable_guild_direct_message": { + "description": "启用频道私聊", + "hint": "启用后,机器人可以接收到频道的私聊消息。", + }, + "id": {"description": "机器人名称", "hint": "机器人名称"}, + "is_sandbox": {"description": "沙箱模式"}, + "kf_name": { + "description": "微信客服账号名", + "hint": "如果填写此项,即代表你将使用企业微信客服,而不是企业微信应用。可在 https://kf.weixin.qq.com/kf/frame#/accounts 获取。", + }, + "lark_connection_mode": { + "description": "订阅方式", + "labels": ["长连接模式", "推送至服务器模式"], + }, + "lark_encrypt_key": { + "description": "Encrypt Key", + "hint": "用于解密飞书回调数据的加密密钥", + }, + "lark_verification_token": { + "description": "Verification Token", + "hint": "用于验证飞书回调请求的令牌", + }, + "misskey_allow_insecure_downloads": { + "description": "允许不安全下载(禁用 SSL 验证)", + "hint": "当远端服务器存在证书问题导致无法正常下载时,自动禁用 SSL 验证作为回退方案。适用于某些图床的证书配置问题。启用有安全风险,仅在必要时使用。", + }, + "misskey_default_visibility": { + "description": "默认帖子可见性", + "hint": "机器人发帖时的默认可见性设置。public:公开,home:主页时间线,followers:仅关注者。", + }, + "misskey_download_chunk_size": { + "description": "流式下载分块大小(字节)", + "hint": "流式下载和计算 MD5 时使用的每次读取字节数,过小会增加开销,过大会占用内存。", + }, + "misskey_download_timeout": { + "description": "远端下载超时时间(秒)", + "hint": "下载远程文件时的超时时间(秒),用于异步上传回退到本地上传的场景。", + }, + "misskey_enable_chat": { + "description": "启用聊天消息响应", + "hint": "启用后,机器人将会监听和响应私信聊天消息", + }, + "misskey_enable_file_upload": { + "description": "启用文件上传到 Misskey", + "hint": "启用后,适配器会尝试将消息链中的文件上传到 Misskey。URL 文件会先尝试服务器端上传,异步上传失败时会回退到下载后本地上传。", + }, + "misskey_instance_url": { + "description": "Misskey 实例 URL", + "hint": "例如 https://misskey.example,填写 Bot 账号所在的 Misskey 实例地址", + }, + "misskey_local_only": { + "description": "仅限本站(不参与联合)", + "hint": "启用后,机器人发出的帖子将仅在本实例可见,不会联合到其他实例", + }, + "misskey_max_download_bytes": { + "description": "最大允许下载字节数(超出则中止)", + "hint": "如果希望限制下载文件的最大大小以防止 OOM,请填写最大字节数;留空或 null 表示不限制。", + }, + "misskey_token": { + "description": "Misskey Access Token", + "hint": "连接服务设置生成的 API 鉴权访问令牌(Access token)", + }, + "misskey_upload_concurrency": { + "description": "并发上传限制", + "hint": "同时进行的文件上传任务上限(整数,默认 3)。", + }, + "misskey_upload_folder": { + "description": "上传到网盘的目标文件夹 ID", + "hint": "可选:填写 Misskey 网盘中目标文件夹的 ID,上传的文件将放置到该文件夹内。留空则使用账号网盘根目录。", + }, + "port": { + "description": "回调服务器端口", + "hint": "回调服务器端口。留空则不启用回调服务器。", + }, + "satori_api_base_url": { + "description": "Satori API 终结点", + "hint": "Satori API 的基础地址。", + }, + "satori_auto_reconnect": { + "description": "启用自动重连", + "hint": "断开连接时是否自动重新连接 WebSocket。", + }, + "satori_endpoint": { + "description": "Satori WebSocket 终结点", + "hint": "Satori 事件的 WebSocket 端点。", + }, + "satori_heartbeat_interval": { + "description": "Satori 心跳间隔", + "hint": "发送心跳消息的间隔(秒)。", + }, + "satori_reconnect_delay": { + "description": "Satori 重连延迟", + "hint": "尝试重新连接前的延迟时间(秒)。", + }, + "satori_token": { + "description": "Satori 令牌", + "hint": "用于 Satori API 身份验证的令牌。", + }, + "secret": {"description": "secret", "hint": "必填项。"}, + "slack_connection_mode": { + "description": "Slack Connection Mode", + "hint": "The connection mode for Slack. `webhook` uses a webhook server, `socket` uses Slack's Socket Mode.", + }, + "slack_webhook_host": { + "description": "Slack Webhook Host", + "hint": "Only valid when Slack connection mode is `webhook`.", + }, + "slack_webhook_path": { + "description": "Slack Webhook Path", + "hint": "Only valid when Slack connection mode is `webhook`.", + }, + "slack_webhook_port": { + "description": "Slack Webhook Port", + "hint": "Only valid when Slack connection mode is `webhook`.", + }, + "telegram_command_auto_refresh": { + "description": "Telegram 命令自动刷新", + "hint": "启用后,AstrBot 将会在运行时自动刷新 Telegram 命令。(单独设置此项无效)", + }, + "telegram_command_register": { + "description": "Telegram 命令注册", + "hint": "启用后,AstrBot 将会自动注册 Telegram 命令。", + }, + "telegram_command_register_interval": { + "description": "Telegram 命令自动刷新间隔", + "hint": "Telegram 命令自动刷新间隔,单位为秒。", + }, + "telegram_polling_restart_delay": { + "description": "Telegram 轮询重启延迟", + "hint": "当轮询意外结束尝试自动重启时的延迟时间,单位为秒。默认为 5s。", + }, + "telegram_token": { + "description": "Bot Token", + "hint": "如果你的网络环境为中国大陆,请在 `其他配置` 处设置代理或更改 api_base。", + }, + "mattermost_url": { + "description": "Mattermost URL", + "hint": "Mattermost 服务地址,例如 https://chat.example.com。", + }, + "mattermost_bot_token": { + "description": "Mattermost Bot Token", + "hint": "在 Mattermost 中创建 Bot 账户后生成的访问令牌。", + }, + "mattermost_reconnect_delay": { + "description": "Mattermost 重连延迟", + "hint": "WebSocket 断开后的重连等待时间,单位为秒。默认 5 秒。", + }, + "type": {"description": "适配器类型"}, + "unified_webhook_mode": { + "description": "统一 Webhook 模式", + "hint": "Webhook 模式下使用 AstrBot 统一 Webhook 入口,无需单独开启端口。回调地址为 /api/v1/webhooks/platforms/{webhook_uuid}。", + }, + "webhook_uuid": { + "description": "Webhook UUID", + "hint": "统一 Webhook 模式下的唯一标识符,创建平台时自动生成。", + }, + "wecom_ai_bot_name": { + "description": "企业微信智能机器人的名字", + "hint": "请务必填写正确,否则无法使用一些指令。", + }, + "wecom_ai_bot_connection_mode": { + "description": "企业微信智能机器人连接模式", + "hint": "Webhook 回调模式需要配置 Token/EncodingAESKey;长连接模式需要配置 BotID/Secret。", + }, + "wecomaibot_friend_message_welcome_text": { + "description": "企业微信智能机器人私聊欢迎语", + "hint": "可选。当用户当天进入智能机器人单聊会话,回复欢迎语,如 “💭 思考中...”。留空则不回复。", + }, + "wecomaibot_init_respond_text": { + "description": "企业微信智能机器人初始响应文本", + "hint": "可选。当机器人收到消息时,首先回复的文本内容。留空则不设置。", + }, + "wecomaibot_token": { + "description": "企业微信智能机器人 Token", + "hint": "用于 Webhook 回调模式的身份验证。", + }, + "wecomaibot_encoding_aes_key": { + "description": "企业微信智能机器人 EncodingAESKey", + "hint": "用于 Webhook 回调模式的消息加密解密。", + }, + "wecomaibot_ws_bot_id": { + "description": "长连接 BotID", + "hint": "企业微信智能机器人长连接模式凭证 BotID。", + }, + "wecomaibot_ws_secret": { + "description": "长连接 Secret", + "hint": "企业微信智能机器人长连接模式凭证 Secret。", + }, + "wecomaibot_ws_url": { + "description": "长连接 WebSocket 地址", + "hint": "默认值为 wss://openws.work.weixin.qq.com,一般无需修改。", + }, + "wecomaibot_heartbeat_interval": { + "description": "长连接心跳间隔", + "hint": "长连接模式心跳间隔(秒),建议 30 秒。", + }, + "wpp_active_message_poll": { + "description": "是否启用主动消息轮询", + "hint": "只有当你发现微信消息没有按时同步到 AstrBot 时,才需要启用这个功能,默认不启用。", + }, + "wpp_active_message_poll_interval": { + "description": "主动消息轮询间隔", + "hint": "主动消息轮询间隔,单位为秒,默认 3 秒,最大不要超过 60 秒,否则可能被认为是旧消息。", + }, + "ws_reverse_host": { + "description": "反向 Websocket 主机", + "hint": "AstrBot 将作为服务器端。", + }, + "ws_reverse_port": {"description": "反向 Websocket 端口"}, + "ws_reverse_token": { + "description": "反向 Websocket Token", + "hint": "反向 Websocket Token。未设置则不启用 Token 验证。", + }, + "msg_push_webhook_url": { + "description": "企业微信消息推送 Webhook URL", + "hint": "可选。用于主动消息推送,请在企微群->消息推送得到 URL。建议设置此项以带来更好的消息发送体验。", + }, + "only_use_webhook_url_to_send": { + "description": "仅使用 Webhook 发送消息", + "hint": "可选。启用后,企业微信智能机器人的所有回复都改为通过消息推送 Webhook 发送。消息推送 Webhook 支持更多的消息类型(如图片、文件等)。如果不需要打字机效果,强烈建议使用此选项。", + }, + "weixin_oc_base_url": { + "description": "Base URL 地址", + "hint": "默认值: https://ilinkai.weixin.qq.com", + }, + "weixin_oc_bot_type": { + "description": "扫码参数 bot_type", + "hint": "默认值: 3", + }, + "weixin_oc_qr_poll_interval": { + "description": "二维码状态轮询间隔(秒)", + "hint": "每隔多少秒轮询一次二维码状态。", + }, + "weixin_oc_long_poll_timeout_ms": { + "description": "getUpdates 长轮询超时时间(毫秒)", + "hint": "会话消息拉取接口超时参数。", + }, + "weixin_oc_api_timeout_ms": { + "description": "HTTP 请求超时(毫秒)", + "hint": "通用 API 请求超时参数。", + }, + "weixin_oc_token": { + "description": "登录后 token(可留空)", + "hint": "扫码登录成功后会自动写入;高级场景可手动填写。", + }, + "kook_bot_token": { + "description": "机器人 Token", + "type": "string", + "hint": "必填项。从 KOOK 开发者平台获取的机器人 Token", + }, + "kook_reconnect_delay": { + "description": "重连延迟", + "type": "int", + "hint": "重连延迟时间(秒),使用指数退避策略", + }, + "kook_max_reconnect_delay": { + "description": "最大重连延迟", + "type": "int", + "hint": "重连延迟的最大值(秒)", + }, + "kook_max_retry_delay": { + "description": "最大重试延迟", + "type": "int", + "hint": "重试的最大延迟时间(秒)", + }, + "kook_heartbeat_interval": { + "description": "心跳间隔", + "type": "int", + "hint": "心跳检测间隔时间(秒)", + }, + "kook_heartbeat_timeout": { + "description": "心跳超时时间", + "type": "int", + "hint": "心跳检测超时时间(秒)", + }, + "kook_max_heartbeat_failures": { + "description": "最大心跳失败次数", + "type": "int", + "hint": "允许的最大心跳失败次数,超过后断开连接", + }, + "kook_max_consecutive_failures": { + "description": "最大连续失败次数", + "type": "int", + "hint": "允许的最大连续失败次数,超过后停止重试", + }, }, - "unsupported_streaming_strategy": { - "description": "不支持流式回复的平台", - "hint": "选择在不支持流式回复的平台上的处理方式。实时分段回复会在系统接收流式响应检测到诸如标点符号等分段点时,立即发送当前已接收的内容", - "labels": [ - "实时分段回复", - "关闭流式回复" - ] + "general": { + "description": "基本", + "admins_id": {"description": "管理员 ID"}, + "platform_settings": { + "unique_session": { + "description": "隔离会话", + "hint": "启用后,群成员的上下文独立。", + }, + "friend_message_needs_wake_prefix": { + "description": "私聊消息需要唤醒词" + }, + "reply_prefix": {"description": "回复时的文本前缀"}, + "reply_with_mention": {"description": "回复时 @ 发送人"}, + "reply_with_quote": {"description": "回复时引用发送人消息"}, + "forward_threshold": {"description": "转发消息的字数阈值"}, + "empty_mention_waiting": {"description": "只 @ 机器人是否触发等待"}, + }, + "wake_prefix": {"description": "唤醒词"}, + "disable_builtin_commands": { + "description": "禁用自带指令", + "hint": "禁用所有 AstrBot 自带指令,如 help, sid, new 等", + }, }, - "wake_prefix": { - "description": "LLM 聊天额外唤醒前缀", - "hint": "如果唤醒前缀为 /, 额外聊天唤醒前缀为 chat,则需要 /chat 才会触发 LLM 请求" + "whitelist": { + "description": "白名单", + "platform_settings": { + "enable_id_white_list": { + "description": "启用白名单", + "hint": "启用后,只有在白名单内的会话会被响应,白名单列表为空时代表不启用白名单(所有 ID 都会被放行)。", + }, + "id_whitelist": { + "description": "白名单 ID 列表", + "hint": "使用 /sid 获取 ID。列表为空时表示该白名单不启用(即所有 ID 都在白名单内)。", + }, + "id_whitelist_log": { + "description": "输出日志", + "hint": "启用后,当一条消息没通过白名单时,会输出 INFO 级别的日志。", + }, + "wl_ignore_admin_on_group": { + "description": "管理员群组消息无视 ID 白名单" + }, + "wl_ignore_admin_on_friend": { + "description": "管理员私聊消息无视 ID 白名单" + }, + }, }, - "prompt_prefix": { - "description": "用户提示词", - "hint": "可使用 {{prompt}} 作为用户输入的占位符。如果不输入占位符则代表添加在用户输入的前面。" + "rate_limit": { + "description": "速率限制", + "platform_settings": { + "rate_limit": { + "time": {"description": "消息速率限制时间(秒)"}, + "count": {"description": "消息速率限制计数"}, + "strategy": {"description": "速率限制策略"}, + } + }, }, - "image_compress_enabled": { - "description": "启用图片压缩", - "hint": "启用后,发送给多模态模型前会先压缩本地大图片。" + "content_safety": { + "description": "内容安全", + "content_safety": { + "also_use_in_response": {"description": "同时检查模型的响应内容"}, + "baidu_aip": { + "enable": { + "description": "使用百度内容安全审核", + "hint": "您需要手动安装 baidu-aip 库。", + }, + "app_id": {"description": "App ID"}, + "api_key": {"description": "API Key"}, + "secret_key": {"description": "Secret Key"}, + }, + "internal_keywords": { + "enable": {"description": "关键词检查"}, + "extra_keywords": { + "description": "额外关键词", + "hint": "额外的屏蔽关键词列表,支持正则表达式。", + }, + }, + }, }, - "image_compress_options": { - "description": "图片压缩配置", - "hint": "用于控制图片压缩的尺寸、质量和触发阈值。", - "max_size": { - "description": "最大边长", - "hint": "压缩后图片的最长边,单位为像素。超过该尺寸时会按比例缩放。" - }, - "quality": { - "description": "JPEG 质量", - "hint": "JPEG 输出质量,范围为 1-100。值越高,画质越好,文件也越大。" - } + "t2i": { + "description": "文本转图像", + "t2i": {"description": "文本转图像输出"}, + "t2i_word_threshold": {"description": "文本转图像字数阈值"}, + }, + "others": { + "description": "其他配置", + "platform_settings": { + "ignore_bot_self_message": {"description": "是否忽略机器人自身的消息"}, + "ignore_at_all": {"description": "是否忽略 @ 全体成员事件"}, + "no_permission_reply": {"description": "用户权限不足时是否回复"}, + }, + "platform_specific": { + "lark": { + "pre_ack_emoji": { + "enable": {"description": "[飞书] 启用预回应表情"}, + "emojis": { + "description": "表情列表(飞书表情枚举名)", + "hint": "表情枚举名参考:[https://open.feishu.cn/document/server-docs/im-v1/message-reaction/emojis-introduce](https://open.feishu.cn/document/server-docs/im-v1/message-reaction/emojis-introduce)", + }, + } + }, + "telegram": { + "pre_ack_emoji": { + "enable": {"description": "[Telegram] 启用预回应表情"}, + "emojis": { + "description": "表情列表(Unicode)", + "hint": "Telegram 仅支持固定反应集合,参考:[https://gist.github.com/Soulter/3f22c8e5f9c7e152e967e8bc28c97fc9](https://gist.github.com/Soulter/3f22c8e5f9c7e152e967e8bc28c97fc9)", + }, + } + }, + "discord": { + "pre_ack_emoji": { + "enable": {"description": "[Discord] 启用预回应表情"}, + "emojis": { + "description": "表情列表(Unicode 或自定义表情名)", + "hint": "填写 Unicode 表情符号,例如:👍、🤔、⏳", + }, + } + }, + }, }, - "reachability_check": { - "description": "提供商可达性检测", - "hint": "/provider 命令列出模型时并发检测连通性。开启后会主动调用模型测试连通性,可能产生额外 token 消耗。" - } - }, - "provider_tts_settings": { - "dual_output": { - "description": "开启 TTS 时同时输出语音和文字内容" - } - } - } - }, - "platform_group": { - "name": "平台配置", - "platform": { - "description": "消息平台适配器", - "active_send_mode": { - "description": "是否换用主动发送接口" - }, - "appid": { - "description": "appid", - "hint": "必填项。当前消息平台的 AppID。如何获取请参考对应平台接入文档。" - }, - "callback_server_host": { - "description": "回调服务器主机", - "hint": "回调服务器主机。留空则不启用回调服务器。" - }, - "card_template_id": { - "description": "卡片模板 ID", - "hint": "可选。钉钉互动卡片模板 ID。启用后将使用互动卡片进行流式回复。" - }, - "discord_activity_name": { - "description": "Discord 活动名称", - "hint": "可选的 Discord 活动名称。留空则不设置活动。" - }, - "discord_allow_bot_messages": { - "description": "允许接收机器人消息", - "hint": "启用后,AstrBot 将接收来自其他 Discord 机器人的消息。适用于机器人间通信场景(如消息转发)。默认关闭。" - }, - "discord_command_register": { - "description": "注册 Discord 指令", - "hint": "启用后,自动将插件指令注册为 Discord 斜杠指令" - }, - "discord_proxy": { - "description": "Discord 代理地址", - "hint": "可选的代理地址:http://ip:port" - }, - "discord_token": { - "description": "Discord Bot Token", - "hint": "在此处填入你的 Discord Bot Token" - }, - "enable": { - "description": "启用", - "hint": "是否启用该适配器。未启用的适配器对应的消息平台将不会接收到消息。" - }, - "enable_group_c2c": { - "description": "启用消息列表单聊", - "hint": "启用后,机器人可以接收到 QQ 消息列表中的私聊消息。你可能需要在 QQ 机器人平台上通过扫描二维码的方式添加机器人为你的好友。详见文档。" - }, - "enable_guild_direct_message": { - "description": "启用频道私聊", - "hint": "启用后,机器人可以接收到频道的私聊消息。" - }, - "id": { - "description": "机器人名称", - "hint": "机器人名称" - }, - "is_sandbox": { - "description": "沙箱模式" - }, - "kf_name": { - "description": "微信客服账号名", - "hint": "如果填写此项,即代表你将使用企业微信客服,而不是企业微信应用。可在 https://kf.weixin.qq.com/kf/frame#/accounts 获取。" - }, - "lark_connection_mode": { - "description": "订阅方式", - "labels": [ - "长连接模式", - "推送至服务器模式" - ] - }, - "lark_encrypt_key": { - "description": "Encrypt Key", - "hint": "用于解密飞书回调数据的加密密钥" - }, - "lark_verification_token": { - "description": "Verification Token", - "hint": "用于验证飞书回调请求的令牌" - }, - "misskey_allow_insecure_downloads": { - "description": "允许不安全下载(禁用 SSL 验证)", - "hint": "当远端服务器存在证书问题导致无法正常下载时,自动禁用 SSL 验证作为回退方案。适用于某些图床的证书配置问题。启用有安全风险,仅在必要时使用。" - }, - "misskey_default_visibility": { - "description": "默认帖子可见性", - "hint": "机器人发帖时的默认可见性设置。public:公开,home:主页时间线,followers:仅关注者。" - }, - "misskey_download_chunk_size": { - "description": "流式下载分块大小(字节)", - "hint": "流式下载和计算 MD5 时使用的每次读取字节数,过小会增加开销,过大会占用内存。" - }, - "misskey_download_timeout": { - "description": "远端下载超时时间(秒)", - "hint": "下载远程文件时的超时时间(秒),用于异步上传回退到本地上传的场景。" - }, - "misskey_enable_chat": { - "description": "启用聊天消息响应", - "hint": "启用后,机器人将会监听和响应私信聊天消息" - }, - "misskey_enable_file_upload": { - "description": "启用文件上传到 Misskey", - "hint": "启用后,适配器会尝试将消息链中的文件上传到 Misskey。URL 文件会先尝试服务器端上传,异步上传失败时会回退到下载后本地上传。" - }, - "misskey_instance_url": { - "description": "Misskey 实例 URL", - "hint": "例如 https://misskey.example,填写 Bot 账号所在的 Misskey 实例地址" - }, - "misskey_local_only": { - "description": "仅限本站(不参与联合)", - "hint": "启用后,机器人发出的帖子将仅在本实例可见,不会联合到其他实例" - }, - "misskey_max_download_bytes": { - "description": "最大允许下载字节数(超出则中止)", - "hint": "如果希望限制下载文件的最大大小以防止 OOM,请填写最大字节数;留空或 null 表示不限制。" - }, - "misskey_token": { - "description": "Misskey Access Token", - "hint": "连接服务设置生成的 API 鉴权访问令牌(Access token)" - }, - "misskey_upload_concurrency": { - "description": "并发上传限制", - "hint": "同时进行的文件上传任务上限(整数,默认 3)。" - }, - "misskey_upload_folder": { - "description": "上传到网盘的目标文件夹 ID", - "hint": "可选:填写 Misskey 网盘中目标文件夹的 ID,上传的文件将放置到该文件夹内。留空则使用账号网盘根目录。" - }, - "port": { - "description": "回调服务器端口", - "hint": "回调服务器端口。留空则不启用回调服务器。" - }, - "satori_api_base_url": { - "description": "Satori API 终结点", - "hint": "Satori API 的基础地址。" - }, - "satori_auto_reconnect": { - "description": "启用自动重连", - "hint": "断开连接时是否自动重新连接 WebSocket。" - }, - "satori_endpoint": { - "description": "Satori WebSocket 终结点", - "hint": "Satori 事件的 WebSocket 端点。" - }, - "satori_heartbeat_interval": { - "description": "Satori 心跳间隔", - "hint": "发送心跳消息的间隔(秒)。" - }, - "satori_reconnect_delay": { - "description": "Satori 重连延迟", - "hint": "尝试重新连接前的延迟时间(秒)。" - }, - "satori_token": { - "description": "Satori 令牌", - "hint": "用于 Satori API 身份验证的令牌。" - }, - "secret": { - "description": "secret", - "hint": "必填项。" - }, - "slack_connection_mode": { - "description": "Slack Connection Mode", - "hint": "The connection mode for Slack. `webhook` uses a webhook server, `socket` uses Slack's Socket Mode." - }, - "slack_webhook_host": { - "description": "Slack Webhook Host", - "hint": "Only valid when Slack connection mode is `webhook`." - }, - "slack_webhook_path": { - "description": "Slack Webhook Path", - "hint": "Only valid when Slack connection mode is `webhook`." - }, - "slack_webhook_port": { - "description": "Slack Webhook Port", - "hint": "Only valid when Slack connection mode is `webhook`." - }, - "telegram_command_auto_refresh": { - "description": "Telegram 命令自动刷新", - "hint": "启用后,AstrBot 将会在运行时自动刷新 Telegram 命令。(单独设置此项无效)" - }, - "telegram_command_register": { - "description": "Telegram 命令注册", - "hint": "启用后,AstrBot 将会自动注册 Telegram 命令。" - }, - "telegram_command_register_interval": { - "description": "Telegram 命令自动刷新间隔", - "hint": "Telegram 命令自动刷新间隔,单位为秒。" - }, - "telegram_polling_restart_delay": { - "description": "Telegram 轮询重启延迟", - "hint": "当轮询意外结束尝试自动重启时的延迟时间,单位为秒。默认为 5s。" - }, - "telegram_token": { - "description": "Bot Token", - "hint": "如果你的网络环境为中国大陆,请在 `其他配置` 处设置代理或更改 api_base。" - }, - "mattermost_url": { - "description": "Mattermost URL", - "hint": "Mattermost 服务地址,例如 https://chat.example.com。" - }, - "mattermost_bot_token": { - "description": "Mattermost Bot Token", - "hint": "在 Mattermost 中创建 Bot 账户后生成的访问令牌。" - }, - "mattermost_reconnect_delay": { - "description": "Mattermost 重连延迟", - "hint": "WebSocket 断开后的重连等待时间,单位为秒。默认 5 秒。" - }, - "type": { - "description": "适配器类型" - }, - "unified_webhook_mode": { - "description": "统一 Webhook 模式", - "hint": "Webhook 模式下使用 AstrBot 统一 Webhook 入口,无需单独开启端口。回调地址为 /api/v1/webhooks/platforms/{webhook_uuid}。" - }, - "webhook_uuid": { - "description": "Webhook UUID", - "hint": "统一 Webhook 模式下的唯一标识符,创建平台时自动生成。" - }, - "wecom_ai_bot_name": { - "description": "企业微信智能机器人的名字", - "hint": "请务必填写正确,否则无法使用一些指令。" - }, - "wecom_ai_bot_connection_mode": { - "description": "企业微信智能机器人连接模式", - "hint": "Webhook 回调模式需要配置 Token/EncodingAESKey;长连接模式需要配置 BotID/Secret。" - }, - "wecomaibot_friend_message_welcome_text": { - "description": "企业微信智能机器人私聊欢迎语", - "hint": "可选。当用户当天进入智能机器人单聊会话,回复欢迎语,如 “💭 思考中...”。留空则不回复。" - }, - "wecomaibot_init_respond_text": { - "description": "企业微信智能机器人初始响应文本", - "hint": "可选。当机器人收到消息时,首先回复的文本内容。留空则不设置。" - }, - "wecomaibot_token": { - "description": "企业微信智能机器人 Token", - "hint": "用于 Webhook 回调模式的身份验证。" - }, - "wecomaibot_encoding_aes_key": { - "description": "企业微信智能机器人 EncodingAESKey", - "hint": "用于 Webhook 回调模式的消息加密解密。" - }, - "wecomaibot_ws_bot_id": { - "description": "长连接 BotID", - "hint": "企业微信智能机器人长连接模式凭证 BotID。" - }, - "wecomaibot_ws_secret": { - "description": "长连接 Secret", - "hint": "企业微信智能机器人长连接模式凭证 Secret。" - }, - "wecomaibot_ws_url": { - "description": "长连接 WebSocket 地址", - "hint": "默认值为 wss://openws.work.weixin.qq.com,一般无需修改。" - }, - "wecomaibot_heartbeat_interval": { - "description": "长连接心跳间隔", - "hint": "长连接模式心跳间隔(秒),建议 30 秒。" - }, - "wpp_active_message_poll": { - "description": "是否启用主动消息轮询", - "hint": "只有当你发现微信消息没有按时同步到 AstrBot 时,才需要启用这个功能,默认不启用。" - }, - "wpp_active_message_poll_interval": { - "description": "主动消息轮询间隔", - "hint": "主动消息轮询间隔,单位为秒,默认 3 秒,最大不要超过 60 秒,否则可能被认为是旧消息。" - }, - "ws_reverse_host": { - "description": "反向 Websocket 主机", - "hint": "AstrBot 将作为服务器端。" - }, - "ws_reverse_port": { - "description": "反向 Websocket 端口" - }, - "ws_reverse_token": { - "description": "反向 Websocket Token", - "hint": "反向 Websocket Token。未设置则不启用 Token 验证。" - }, - "msg_push_webhook_url": { - "description": "企业微信消息推送 Webhook URL", - "hint": "可选。用于主动消息推送,请在企微群->消息推送得到 URL。建议设置此项以带来更好的消息发送体验。" - }, - "only_use_webhook_url_to_send": { - "description": "仅使用 Webhook 发送消息", - "hint": "可选。启用后,企业微信智能机器人的所有回复都改为通过消息推送 Webhook 发送。消息推送 Webhook 支持更多的消息类型(如图片、文件等)。如果不需要打字机效果,强烈建议使用此选项。" - }, - "weixin_oc_base_url": { - "description": "Base URL 地址", - "hint": "默认值: https://ilinkai.weixin.qq.com" - }, - "weixin_oc_bot_type": { - "description": "扫码参数 bot_type", - "hint": "默认值: 3" - }, - "weixin_oc_qr_poll_interval": { - "description": "二维码状态轮询间隔(秒)", - "hint": "每隔多少秒轮询一次二维码状态。" - }, - "weixin_oc_long_poll_timeout_ms": { - "description": "getUpdates 长轮询超时时间(毫秒)", - "hint": "会话消息拉取接口超时参数。" - }, - "weixin_oc_api_timeout_ms": { - "description": "HTTP 请求超时(毫秒)", - "hint": "通用 API 请求超时参数。" - }, - "weixin_oc_token": { - "description": "登录后 token(可留空)", - "hint": "扫码登录成功后会自动写入;高级场景可手动填写。" - }, - "kook_bot_token": { - "description": "机器人 Token", - "type": "string", - "hint": "必填项。从 KOOK 开发者平台获取的机器人 Token" - }, - "kook_reconnect_delay": { - "description": "重连延迟", - "type": "int", - "hint": "重连延迟时间(秒),使用指数退避策略" - }, - "kook_max_reconnect_delay": { - "description": "最大重连延迟", - "type": "int", - "hint": "重连延迟的最大值(秒)" - }, - "kook_max_retry_delay": { - "description": "最大重试延迟", - "type": "int", - "hint": "重试的最大延迟时间(秒)" - }, - "kook_heartbeat_interval": { - "description": "心跳间隔", - "type": "int", - "hint": "心跳检测间隔时间(秒)" - }, - "kook_heartbeat_timeout": { - "description": "心跳超时时间", - "type": "int", - "hint": "心跳检测超时时间(秒)" - }, - "kook_max_heartbeat_failures": { - "description": "最大心跳失败次数", - "type": "int", - "hint": "允许的最大心跳失败次数,超过后断开连接" - }, - "kook_max_consecutive_failures": { - "description": "最大连续失败次数", - "type": "int", - "hint": "允许的最大连续失败次数,超过后停止重试" - } }, - "general": { - "description": "基本", - "admins_id": { - "description": "管理员 ID" - }, - "platform_settings": { - "unique_session": { - "description": "隔离会话", - "hint": "启用后,群成员的上下文独立。" - }, - "friend_message_needs_wake_prefix": { - "description": "私聊消息需要唤醒词" - }, - "reply_prefix": { - "description": "回复时的文本前缀" - }, - "reply_with_mention": { - "description": "回复时 @ 发送人" - }, - "reply_with_quote": { - "description": "回复时引用发送人消息" - }, - "forward_threshold": { - "description": "转发消息的字数阈值" + "plugin_group": { + "name": "插件配置", + "plugin": { + "description": "插件", + "plugin_set": { + "description": "可用插件", + "hint": "默认启用全部未被禁用的插件。若插件在插件页面被禁用,则此处的选择不会生效。", + }, }, - "empty_mention_waiting": { - "description": "只 @ 机器人是否触发等待" - } - }, - "wake_prefix": { - "description": "唤醒词" - }, - "disable_builtin_commands": { - "description": "禁用自带指令", - "hint": "禁用所有 AstrBot 自带指令,如 help, sid, new 等" - } }, - "whitelist": { - "description": "白名单", - "platform_settings": { - "enable_id_white_list": { - "description": "启用白名单", - "hint": "启用后,只有在白名单内的会话会被响应,白名单列表为空时代表不启用白名单(所有 ID 都会被放行)。" - }, - "id_whitelist": { - "description": "白名单 ID 列表", - "hint": "使用 /sid 获取 ID。列表为空时表示该白名单不启用(即所有 ID 都在白名单内)。" - }, - "id_whitelist_log": { - "description": "输出日志", - "hint": "启用后,当一条消息没通过白名单时,会输出 INFO 级别的日志。" + "ext_group": { + "name": "扩展功能", + "segmented_reply": { + "description": "分段回复", + "platform_settings": { + "segmented_reply": { + "enable": {"description": "启用分段回复"}, + "only_llm_result": {"description": "仅对 LLM 结果分段"}, + "interval_method": { + "description": "间隔方法", + "hint": "random 为随机时间,log 为根据消息长度计算,$y=log_(x)$,x为字数,y的单位为秒。", + }, + "interval": { + "description": "随机间隔时间", + "hint": "格式:最小值,最大值(如:1.5,3.5)", + }, + "log_base": { + "description": "对数底数", + "hint": "对数间隔的底数,默认为 2.6。取值范围为 1.0-10.0。", + }, + "words_count_threshold": { + "description": "分段回复字数阈值", + "hint": "分段回复的字数上限。只有字数小于此值的消息才会被分段,超过此值的长消息将直接发送(不分段),默认为 150。", + }, + "split_mode": { + "description": "分段模式", + "hint": "用于分隔一段消息。默认情况下会根据句号、问号等标点符号分隔。如填写 `[。?!]` 将移除所有的句号、问号、感叹号。re.findall(r'', text)", + "labels": ["正则表达式", "分段词列表"], + }, + "regex": { + "description": "分段正则表达式", + "hint": "用于按正则规则识别分段点。建议使用能匹配分隔符的表达式。", + }, + "split_words": { + "description": "分段词列表", + "hint": "检测到列表中的任意词时进行分段", + }, + "content_cleanup_rule": { + "description": "内容过滤正则表达式", + "hint": "移除分段后内容中的指定内容。如填写 `[。?!]` 将移除所有的句号、问号、感叹号。", + }, + } + }, }, - "wl_ignore_admin_on_group": { - "description": "管理员群组消息无视 ID 白名单" + "ltm": { + "description": "群聊上下文感知(原聊天记忆增强)", + "provider_ltm_settings": { + "group_icl_enable": {"description": "启用群聊上下文感知"}, + "group_message_max_cnt": {"description": "最大消息数量"}, + "image_caption": { + "description": "自动理解图片", + "hint": "需要设置群聊图片转述模型。", + }, + "image_caption_provider_id": { + "description": "群聊图片转述模型", + "hint": "用于群聊上下文感知的图片理解,与默认图片转述模型分开配置。", + }, + "active_reply": { + "enable": {"description": "主动回复"}, + "method": {"description": "主动回复方法"}, + "possibility_reply": { + "description": "回复概率", + "hint": "0.0-1.0 之间的数值", + }, + "whitelist": { + "description": "主动回复白名单", + "hint": "为空时不启用白名单过滤。使用 /sid 获取 ID。", + }, + }, + }, }, - "wl_ignore_admin_on_friend": { - "description": "管理员私聊消息无视 ID 白名单" - } - } }, - "rate_limit": { - "description": "速率限制", - "platform_settings": { - "rate_limit": { - "time": { - "description": "消息速率限制时间(秒)" - }, - "count": { - "description": "消息速率限制计数" - }, - "strategy": { - "description": "速率限制策略" - } - } - } - }, - "content_safety": { - "description": "内容安全", - "content_safety": { - "also_use_in_response": { - "description": "同时检查模型的响应内容" - }, - "baidu_aip": { - "enable": { - "description": "使用百度内容安全审核", - "hint": "您需要手动安装 baidu-aip 库。" - }, - "app_id": { - "description": "App ID" - }, - "api_key": { - "description": "API Key" - }, - "secret_key": { - "description": "Secret Key" - } + "system_group": { + "name": "系统配置", + "system": { + "description": "系统配置", + "t2i_strategy": { + "description": "文本转图像策略", + "hint": "文本转图像策略。`remote` 为使用远程基于 HTML 的渲染服务,`local` 为使用 PIL 本地渲染。当使用 local 时,将 ttf 字体命名为 'font.ttf' 放在 data/ 目录下可自定义字体。", + }, + "t2i_endpoint": { + "description": "文本转图像服务 API 地址", + "hint": "为空时使用 AstrBot API 服务", + }, + "t2i_template": { + "description": "文本转图像自定义模版", + "hint": "启用后可自定义 HTML 模板用于文转图渲染。", + }, + "t2i_active_template": { + "description": "当前应用的文转图渲染模板", + "hint": "此处的值由文转图模板管理页面进行维护。", + }, + "log_level": { + "description": "控制台日志级别", + "hint": "控制台输出日志的级别。", + }, + "log_file_enable": { + "description": "启用文件日志", + "hint": "在控制台输出的同时,将日志写入文件。", + }, + "log_file_path": { + "description": "日志文件路径", + "hint": "相对路径以 data 目录为基准,例如 logs/astrbot.log;支持绝对路径。", + }, + "log_file_max_mb": { + "description": "日志文件大小上限 (MB)", + "hint": "超过大小后自动轮转,默认 20MB。", + }, + "temp_dir_max_size": { + "description": "临时目录大小上限 (MB)", + "hint": "用于限制 data/temp 目录总大小,单位为 MB。系统每 10 分钟检查一次,超限时按文件修改时间从旧到新删除,释放约 30% 当前体积。", + }, + "trace_log_enable": { + "description": "启用 Trace 文件日志", + "hint": "将 Trace 事件写入独立文件(不影响控制台输出)。", + }, + "trace_log_path": { + "description": "Trace 日志文件路径", + "hint": "相对路径以 data 目录为基准,例如 logs/astrbot.trace.log;支持绝对路径。", + }, + "trace_log_max_mb": { + "description": "Trace 日志大小上限 (MB)", + "hint": "超过大小后自动轮转,默认 20MB。", + }, + "pip_install_arg": { + "description": "pip 安装额外参数", + "hint": "安装插件依赖时,会使用 Python 的 pip 工具。这里可以填写额外的参数,如 `--break-system-package` 等。", + }, + "pypi_index_url": { + "description": "PyPI 软件仓库地址", + "hint": "安装 Python 依赖时请求的 PyPI 软件仓库地址。默认为 [https://mirrors.aliyun.com/pypi/simple/](https://mirrors.aliyun.com/pypi/simple/)", + }, + "callback_api_base": { + "description": "对外可达的回调接口地址", + "hint": "外部服务可能会通过 AstrBot 生成的回调链接(如文件下载链接)访问 AstrBot 后端。由于 AstrBot 无法自动判断部署环境中对外可达的主机地址(host),因此需要通过此配置项显式指定外部服务如何访问 AstrBot 的地址。如 [http://localhost:6185](http://localhost:6185),[https://example.com](https://example.com) 等。", + }, + "disable_metrics": { + "description": "禁用匿名使用统计", + "hint": "禁用后,AstrBot 将不再上传匿名使用统计数据。", + }, + "dashboard": { + "trust_proxy_headers": { + "description": "信任代理请求头获取客户端 IP", + "hint": "关闭时忽略 X-Forwarded-For/X-Real-IP,仅使用连接地址。", + }, + "auth_rate_limit": { + "enable": { + "description": "启用登录验证速率限制", + "hint": "关闭后将不对登录、TOTP 等身份验证接口进行速率限制。", + }, + "average_interval": { + "description": "验证端点速率限制平均间隔(秒)", + "hint": "两次身份验证请求之间的最小平均间隔时间。例如设置为 1.0 表示每秒最多处理 1 个请求。", + }, + "max_burst": { + "description": "验证端点速率限制最大突发数", + "hint": "允许的瞬时最大突发请求数。例如设置为 3 表示在短时间内最多连续处理 3 个请求。", + }, + }, + "ssl": { + "enable": { + "description": "启用 WebUI HTTPS", + "hint": "启用后,WebUI 将直接使用 HTTPS 提供服务。", + }, + "cert_file": { + "description": "SSL 证书文件路径", + "hint": "证书文件路径(PEM)。支持绝对路径和相对路径(相对于当前工作目录)。", + }, + "key_file": { + "description": "SSL 私钥文件路径", + "hint": "私钥文件路径(PEM)。支持绝对路径和相对路径(相对于当前工作目录)。", + }, + "ca_certs": { + "description": "SSL CA 证书文件路径", + "hint": "可选。用于指定 CA 证书文件路径。", + }, + }, + "totp": { + "enable": { + "description": "启用 WebUI TOTP 双因素认证", + "hint": "启用后,登录 WebUI 需要额外输入验证码。", + }, + "manage": "管理", + "configuration": "TOTP", + "statusPending": "需完成设置", + "statusEnabled": "已启用", + "setupRequiredHint": "TOTP 已开启但尚未完成配置,请点击“管理”完成初始化。", + "setupTitle": "设置 TOTP", + "setupSubtitle": "请使用认证器应用扫描二维码,然后输入验证码。", + "setupConfirm": "验证并继续", + "activeSubtitle": "可使用此二维码和密钥添加新的认证器设备。", + "rotateTitle": "更换 TOTP 密钥", + "rotateSubtitle": "生成新密钥并完成验证后,将替换当前密钥。", + "rotate": "更换密钥", + "rotateRecovery": "更换恢复码", + "rotateConfirm": "确认更换", + "rotateCancel": "取消", + "rotateCode": "验证码", + "rotateCodeHint": "输入认证器应用中的验证码以确认新密钥。", + "rotateError": "验证码无效,请重试。", + "recoveryTitle": "恢复码", + "recoverySubtitle": "恢复码仅展示一次,请在继续前妥善保存。", + "recoveryWarning": "若恢复码丢失将无法通过常规途径恢复账户访问权限。", + "recoveryAcknowledge": "我已保存恢复码", + "recoveryClose": "完成", + "disableTitle": "关闭 TOTP", + "disableSubtitle": "输入验证码以确认关闭双因素认证。", + "disableRecoverySubtitle": "输入恢复码以确认关闭双因素认证。", + "disableCode": "验证码", + "disableRecoveryCode": "恢复码", + "disableConfirm": "确认关闭", + "disableCancel": "取消", + "disableError": "验证失败,请重试。", + "disableUseRecovery": "无法使用TOTP?", + "disableUseCode": "使用验证码", + "configSaveTitle": "两步验证", + "configSaveSubtitle": "输入验证码以更改受保护的配置。", + "configSaveRotationHint": "轮换 TOTP 密钥时,轮换前和轮换后的验证码均可用(仅轮换操作中单次允许)。", + "configSaveCode": "验证码", + "configSaveConfirm": "继续", + "configSaveCancel": "取消", + "configSaveError": "验证失败,请重试。", + }, + }, + "timezone": { + "description": "时区", + "hint": "时区设置。请填写 IANA 时区名称, 如 Asia/Shanghai, 为空时使用系统默认时区。所有时区请查看: [https://data.iana.org/time-zones/tzdb-2021a/zone1970.tab](https://data.iana.org/time-zones/tzdb-2021a/zone1970.tab)", + }, + "http_proxy": { + "description": "HTTP 代理", + "hint": "启用后,会以添加环境变量的方式设置代理。格式为 `http://ip:port`", + }, + "no_proxy": {"description": "直连地址列表"}, }, - "internal_keywords": { - "enable": { - "description": "关键词检查" - }, - "extra_keywords": { - "description": "额外关键词", - "hint": "额外的屏蔽关键词列表,支持正则表达式。" - } - } - } }, - "t2i": { - "description": "文本转图像", - "t2i": { - "description": "文本转图像输出" - }, - "t2i_word_threshold": { - "description": "文本转图像字数阈值" - } - }, - "others": { - "description": "其他配置", - "platform_settings": { - "ignore_bot_self_message": { - "description": "是否忽略机器人自身的消息" - }, - "ignore_at_all": { - "description": "是否忽略 @ 全体成员事件" - }, - "no_permission_reply": { - "description": "用户权限不足时是否回复" - } - }, - "platform_specific": { - "lark": { - "pre_ack_emoji": { - "enable": { - "description": "[飞书] 启用预回应表情" + "provider_group": { + "provider": { + "genie_onnx_model_dir": { + "description": "ONNX Model Directory", + "hint": "The directory path containing the ONNX model files", }, - "emojis": { - "description": "表情列表(飞书表情枚举名)", - "hint": "表情枚举名参考:[https://open.feishu.cn/document/server-docs/im-v1/message-reaction/emojis-introduce](https://open.feishu.cn/document/server-docs/im-v1/message-reaction/emojis-introduce)" - } - } - }, - "telegram": { - "pre_ack_emoji": { - "enable": { - "description": "[Telegram] 启用预回应表情" + "genie_language": {"description": "Language"}, + "xai_native_search": { + "description": "启用原生搜索功能", + "hint": "启用后,将通过 xAI 的 Chat Completions 原生 Live Search 进行联网检索(按需计费)。仅对 xAI 提供商生效。", }, - "emojis": { - "description": "表情列表(Unicode)", - "hint": "Telegram 仅支持固定反应集合,参考:[https://gist.github.com/Soulter/3f22c8e5f9c7e152e967e8bc28c97fc9](https://gist.github.com/Soulter/3f22c8e5f9c7e152e967e8bc28c97fc9)" - } - } - }, - "discord": { - "pre_ack_emoji": { - "enable": { - "description": "[Discord] 启用预回应表情" + "rerank_api_base": { + "description": "重排序模型 API Base URL", + "hint": "最终请求路径由 Base URL 和路径后缀拼接而成(默认为 /v1/rerank)。", + }, + "rerank_api_suffix": { + "description": "API URL 路径后缀", + "hint": "追加到 base_url 后的路径后缀,如 /v1/rerank。留空则不追加。", + }, + "rerank_api_key": { + "description": "API Key", + "hint": "如果不需要 API Key, 请留空。", + }, + "rerank_model": {"description": "重排序模型名称"}, + "return_documents": { + "description": "是否在排序结果中返回文档原文", + "hint": "默认值false,以减少网络传输开销。", + }, + "instruct": { + "description": "自定义排序任务类型说明", + "hint": "仅在使用 qwen3-rerank 模型时生效。建议使用英文撰写。", + }, + "nvidia_rerank_api_base": {"description": "API Base URL"}, + "nvidia_rerank_api_key": {"description": "API Key"}, + "nvidia_rerank_model": { + "description": "重排序模型名称", + "hint": "请参照NVIDIA Docs中模型名称填写。", + }, + "nvidia_rerank_model_endpoint": { + "description": "自定义模型端点", + "hint": "自定义URL末尾端点,默认为 /reranking", + }, + "nvidia_rerank_truncate": { + "description": "文本截断策略", + "hint": "当输入文本过长时,是否截断输入以适应模型的最大上下文长度。", + }, + "tei_rerank_truncate": { + "description": "截断超长文本", + "hint": "当输入超过模型最大上下文长度时,是否自动截断。启用后需配合 截断方向 使用。", + }, + "tei_rerank_truncation_direction": { + "description": "截断方向", + "hint": "选择从文本的左侧(left)还是右侧(right)开始截断。仅在 截断超长文本 为 True 时生效。", + }, + "tei_rerank_raw_scores": { + "description": "返回原始分数", + "hint": "如果为 True,返回模型原始 logit 分数(可能为负值),不经过 sigmoid 归一化。默认 False。", + }, + "tei_rerank_return_text": { + "description": "返回排序结果中的文档原文", + "hint": "如果为 True,每个排序结果将附带原始文本。默认 False 以减少网络传输。", + }, + "launch_model_if_not_running": { + "description": "模型未运行时自动启动", + "hint": "如果模型当前未在 Xinference 服务中运行,是否尝试自动启动它。在生产环境中建议关闭。", + }, + "modalities": { + "description": "模型能力", + "hint": "模型支持的模态及能力。", + "labels": ["文本", "图像", "音频", "工具使用"], + }, + "supported_image_mimes": { + "description": "支持的图片 MIME 类型", + "hint": "模型支持的图片格式。不勾选时保留全部(仅过滤已知不安全格式如 GIF)。勾选后仅保留勾选的格式。", + "labels": ["JPEG", "PNG", "WebP", "GIF"], + }, + "custom_headers": { + "description": "自定义请求头", + "hint": "此处添加的键值对将被合并到 OpenAI SDK 的 default_headers 中,用于自定义 HTTP 请求头。值必须为字符串。", + }, + "ollama_disable_thinking": { + "description": "关闭思考模式", + "hint": "关闭 Ollama 思考模式。", + }, + "custom_extra_body": { + "description": "自定义请求体参数", + "hint": "用于在请求时添加额外的参数,如 temperature, top_p, max_tokens, reasoning_effort 等。", + "template_schema": { + "temperature": { + "description": "温度参数", + "hint": "控制输出的随机性,范围通常为 0-2。值越高越随机。", + "name": "Temperature", + }, + "top_p": { + "description": "Top-p 采样", + "hint": "核采样参数,范围通常为 0-1。控制模型考虑的概率质量。", + "name": "Top-p", + }, + "max_tokens": { + "description": "最大词元(Tokens)数", + "hint": "生成的最大词元(Tokens)数。", + "name": "Max Tokens", + }, + }, + }, + "gpt_weights_path": { + "description": "GPT模型文件路径", + "hint": "即“.ckpt”后缀的文件,请使用绝对路径,路径两端不要带双引号,不填则默认用GPT_SoVITS内置的SoVITS模型(建议直接在GPT_SoVITS中改默认模型)", + }, + "sovits_weights_path": { + "description": "SoVITS模型文件路径", + "hint": "即“.pth”后缀的文件,请使用绝对路径,路径两端不要带双引号,不填则默认用GPT_SoVITS内置的SoVITS模型(建议直接在GPT_SoVITS中改默认模型)", + }, + "gsv_default_parms": { + "description": "GPT_SoVITS默认参数", + "hint": "参考音频文件路径、参考音频文本必填,其他参数根据个人爱好自行填写", + "gsv_ref_audio_path": { + "description": "参考音频文件路径", + "hint": "必填!请使用绝对路径!路径两端不要带双引号!", + }, + "gsv_prompt_text": { + "description": "参考音频文本", + "hint": "必填!请填写参考音频讲述的文本", + }, + "gsv_prompt_lang": { + "description": "参考音频文本语言", + "hint": "请填写参考音频讲述的文本的语言,默认为中文", + }, + "gsv_aux_ref_audio_paths": { + "description": "辅助参考音频文件路径", + "hint": "辅助参考音频文件,可不填", + }, + "gsv_text_lang": {"description": "文本语言", "hint": "默认为中文"}, + "gsv_top_k": {"description": "生成语音的多样性", "hint": ""}, + "gsv_top_p": {"description": "核采样的阈值", "hint": ""}, + "gsv_temperature": {"description": "生成语音的随机性", "hint": ""}, + "gsv_text_split_method": { + "description": "切分文本的方法", + "hint": "可选值: `cut0`:不切分 `cut1`:四句一切 `cut2`:50字一切 `cut3`:按中文句号切 `cut4`:按英文句号切 `cut5`:按标点符号切", + }, + "gsv_batch_size": {"description": "批处理大小", "hint": ""}, + "gsv_batch_threshold": {"description": "批处理阈值", "hint": ""}, + "gsv_split_bucket": { + "description": "将文本分割成桶以便并行处理", + "hint": "", + }, + "gsv_speed_factor": { + "description": "语音播放速度", + "hint": "1为原始语速", + }, + "gsv_fragment_interval": { + "description": "语音片段之间的间隔时间", + "hint": "", + }, + "gsv_streaming_mode": {"description": "启用流模式", "hint": ""}, + "gsv_seed": {"description": "随机种子", "hint": "用于结果的可重复性"}, + "gsv_parallel_infer": {"description": "并行执行推理", "hint": ""}, + "gsv_repetition_penalty": {"description": "重复惩罚因子", "hint": ""}, + "gsv_media_type": { + "description": "输出媒体的类型", + "hint": "建议用wav", + }, + }, + "embedding_dimensions": { + "description": "嵌入维度", + "hint": "嵌入向量的维度。根据模型不同,可能需要调整,请参考具体模型的文档。此配置项请务必填写正确,否则将导致向量数据库无法正常工作。", + }, + "embedding_dimensions_mode": { + "description": "嵌入维度参数发送模式", + "hint": "控制是否在 OpenAI 兼容 Embedding 请求中发送 dimensions 参数。auto 会仅对官方 OpenAI embedding-3 模型自动发送;第三方兼容 API 如需该参数可改为 always,报错时改为 never。", + }, + "embedding_model": {"description": "嵌入模型", "hint": "嵌入模型名称。"}, + "embedding_api_key": {"description": "API Key"}, + "embedding_api_base": {"description": "API Base URL"}, + "openai_embedding": { + "hint": "如果测试不通过,可以尝试添加 /v1 在末尾以兼容部分 OpenAI API 版本。" + }, + "gemini_embedding": {"hint": "Gemini Embedding 无需手动添加 /v1beta。"}, + "volcengine_cluster": { + "description": "火山引擎集群", + "hint": "若使用语音复刻大模型,可选volcano_icl或volcano_icl_concurr,默认使用volcano_tts", + }, + "volcengine_voice_type": { + "description": "火山引擎音色", + "hint": "输入声音id(Voice_type)", + }, + "volcengine_speed_ratio": { + "description": "语速设置", + "hint": "语速设置,范围为 0.2 到 3.0,默认值为 1.0", + }, + "volcengine_volume_ratio": { + "description": "音量设置", + "hint": "音量设置,范围为 0.0 到 2.0,默认值为 1.0", + }, + "azure_tts_voice": {"description": "音色设置", "hint": "API 音色"}, + "azure_tts_style": { + "description": "风格设置", + "hint": "声音特定的讲话风格。 可以表达快乐、同情和平静等情绪。", + }, + "azure_tts_role": { + "description": "模仿设置(可选)", + "hint": "讲话角色扮演。 声音可以模仿不同的年龄和性别,但声音名称不会更改。 例如,男性语音可以提高音调和改变语调来模拟女性语音,但语音名称不会更改。 如果角色缺失或不受声音的支持,则会忽略此属性。", + }, + "azure_tts_rate": { + "description": "语速设置", + "hint": "指示文本的讲出速率。可在字词或句子层面应用语速。 速率变化应为原始音频的 0.5 到 2 倍。", + }, + "azure_tts_volume": { + "description": "语音音量设置", + "hint": "指示语音的音量级别。 可在句子层面应用音量的变化。以从 0.0 到 100.0(从最安静到最大声,例如 75)的数字表示。 默认值为 100.0。", + }, + "azure_tts_region": { + "description": "API 地区", + "hint": "Azure_TTS 处理数据所在区域,具体参考 https://learn.microsoft.com/zh-cn/azure/ai-services/speech-service/regions", + }, + "azure_tts_subscription_key": { + "description": "服务订阅密钥", + "hint": "Azure_TTS 服务的订阅密钥(注意不是令牌)", + }, + "dashscope_tts_voice": {"description": "音色"}, + "gm_resp_image_modal": { + "description": "启用图片模态", + "hint": "启用后,将支持返回图片内容。需要模型支持,否则会报错。具体支持模型请查看 Google Gemini 官方网站。温馨提示,如果您需要生成图片,请关闭 `启用群员识别` 配置获得更好的效果。", + }, + "gm_native_search": { + "description": "启用原生搜索功能", + "hint": "启用后所有函数工具将全部失效,免费次数限制请查阅官方文档", + }, + "gm_native_coderunner": { + "description": "启用原生代码执行器", + "hint": "启用后所有函数工具将全部失效", + }, + "gm_url_context": { + "description": "启用URL上下文功能", + "hint": "启用后所有函数工具将全部失效", + }, + "gm_safety_settings": { + "description": "安全过滤器", + "hint": "设置模型输入的内容安全过滤级别。过滤级别分类为NONE(不屏蔽)、HIGH(高风险时屏蔽)、MEDIUM_AND_ABOVE(中等风险及以上屏蔽)、LOW_AND_ABOVE(低风险及以上时屏蔽),具体参见Gemini API文档。", + "harassment": {"description": "骚扰内容", "hint": "负面或有害评论"}, + "hate_speech": { + "description": "仇恨言论", + "hint": "粗鲁、无礼或亵渎性质内容", + }, + "sexually_explicit": { + "description": "露骨色情内容", + "hint": "包含性行为或其他淫秽内容的引用", + }, + "dangerous_content": { + "description": "危险内容", + "hint": "宣扬、助长或鼓励有害行为的信息", + }, + }, + "gm_thinking_config": { + "description": "思考配置", + "budget": { + "description": "思考预算", + "hint": "用于指定模型推理时使用的思考 token 数量上限。参见: https://ai.google.dev/gemini-api/docs/thinking#set-budget", + }, + "level": { + "description": "思考级别", + "hint": "推荐用于 Gemini 3 及以上模型,可控制推理行为。参见: https://ai.google.dev/gemini-api/docs/thinking#thinking-levels", + }, + }, + "anth_thinking_config": { + "description": "思考配置", + "type": { + "description": "思考类型", + "hint": "设为 'adaptive' 以使用自适应思考(推荐 Opus 4.6+ / Sonnet 4.6+)。留空则使用手动预算模式。参见: https://platform.claude.com/docs/en/build-with-claude/adaptive-thinking", + }, + "budget": { + "description": "思考预算", + "hint": "Anthropic thinking.budget_tokens 参数。必须 >= 1024。仅在思考类型为空时生效。Opus 4.6 / Sonnet 4.6 已弃用。参见: https://platform.claude.com/docs/en/build-with-claude/extended-thinking", + }, + "effort": { + "description": "思考深度", + "hint": "当思考类型为 'adaptive' 时控制思考深度。'high' 为默认值。'max' 仅限 Opus 4.6。参见: https://platform.claude.com/docs/en/build-with-claude/effort", + }, + }, + "minimax-group-id": { + "description": "用户组", + "hint": "于账户管理->基本信息中可见", + }, + "minimax-langboost": { + "description": "指定语言/方言", + "hint": "增强对指定的小语种和方言的识别能力,设置后可以提升在指定小语种/方言场景下的语音表现", + }, + "minimax-voice-speed": { + "description": "语速", + "hint": "生成声音的语速, 取值[0.5, 2], 默认为1.0, 取值越大,语速越快", + }, + "minimax-voice-vol": { + "description": "音量", + "hint": "生成声音的音量, 取值(0, 10], 默认为1.0, 取值越大,音量越高", + }, + "minimax-voice-pitch": { + "description": "语调", + "hint": "生成声音的语调, 取值[-12, 12], 默认为0", + }, + "minimax-is-timber-weight": { + "description": "启用混合音色", + "hint": "启用混合音色, 支持以自定义权重混合最多四种音色, 启用后自动忽略单一音色设置", + }, + "minimax-timber-weight": { + "description": "混合音色", + "hint": "混合音色及其权重, 最多支持四种音色, 权重为整数, 取值[1, 100]. 可在官网API语音调试台预览代码获得预设以及编写模板, 需要严格按照json字符串格式编写, 可以查看控制台判断是否解析成功. 具体结构可参照默认值以及官网代码预览.", + }, + "minimax-voice-id": { + "description": "单一音色", + "hint": "单一音色编号, 详见官网文档", + }, + "minimax-voice-emotion": { + "description": "情绪", + "hint": "控制合成语音的情绪。当为 auto 时,将根据文本内容自动选择情绪。", + }, + "minimax-voice-latex": { + "description": "支持朗读latex公式", + "hint": "朗读latex公式, 但是需要确保输入文本按官网要求格式化", + }, + "minimax-voice-english-normalization": { + "description": "支持英语文本规范化", + "hint": "可提升数字阅读场景的性能,但会略微增加延迟", + }, + "rag_options": { + "description": "RAG 选项", + "hint": "检索知识库设置, 非必填。仅 Agent 应用类型支持(智能体应用, 包括 RAG 应用)。阿里云百炼应用开启此功能后将无法多轮对话。", + "pipeline_ids": { + "description": "知识库 ID 列表", + "hint": "对指定知识库内所有文档进行检索, 前往 https://bailian.console.aliyun.com/ 数据应用->知识索引创建和获取 ID。", + }, + "file_ids": { + "description": "非结构化文档 ID, 传入该参数将对指定非结构化文档进行检索。", + "hint": "对指定非结构化文档进行检索。前往 https://bailian.console.aliyun.com/ 数据管理创建和获取 ID。", + }, + "output_reference": { + "description": "是否输出知识库/文档的引用", + "hint": "在每次回答尾部加上引用源。默认为 False。", + }, + }, + "sensevoice_hint": { + "description": "部署SenseVoice", + "hint": "启用前请 pip 安装 funasr、funasr_onnx、torchaudio、torch、modelscope、jieba 库(默认使用CPU,大约下载 1 GB),并且安装 ffmpeg。否则将无法正常转文字。", + }, + "is_emotion": { + "description": "情绪识别", + "hint": "是否开启情绪识别。happy|sad|angry|neutral|fearful|disgusted|surprised|unknown", + }, + "stt_model": { + "description": "模型名称", + "hint": "modelscope 上的模型名称。默认:iic/SenseVoiceSmall。", + }, + "variables": { + "description": "工作流固定输入变量", + "hint": "可选。工作流固定输入变量,将会作为工作流的输入。也可以在对话时使用 /set 指令动态设置变量。如果变量名冲突,优先使用动态设置的变量。", + }, + "dashscope_app_type": { + "description": "应用类型", + "hint": "百炼应用的应用类型。", + }, + "timeout": {"description": "超时时间", "hint": "超时时间,单位为秒。"}, + "openai-tts-voice": { + "description": "voice", + "hint": "OpenAI TTS 的声音。OpenAI 默认支持:'alloy', 'echo', 'fable', 'onyx', 'nova', 'shimmer'", + }, + "elevenlabs-tts-voice-id": { + "description": "音色 ID", + "hint": "ElevenLabs 音色 ID。可在 https://elevenlabs.io/app/voice-library 浏览并复制音色 ID。默认 'JBFqnCBsd6RMkjVDRZzb'(George)。", + }, + "elevenlabs-tts-output-format": { + "description": "输出格式", + "hint": "音频输出格式,例如 'mp3_44100_128'、'mp3_22050_32'、'wav_44100'、'opus_48000_128'。不支持裸 PCM/u-law/a-law 格式。默认 'mp3_44100_128'。", + }, + "elevenlabs-tts-stability": { + "description": "稳定性", + "hint": "音色稳定性,范围 [0, 1]。值越高越稳定,越低越富有表现力。留空则使用服务端默认值。", + }, + "elevenlabs-tts-similarity-boost": { + "description": "相似度增强", + "hint": "输出与原始音色的接近程度,范围 [0, 1]。留空则使用服务端默认值。", + }, + "elevenlabs-tts-style": { + "description": "风格夸张度", + "hint": "音色风格的夸张程度,范围 [0, 1]。值越高延迟越大。留空则使用服务端默认值。", + }, + "elevenlabs-tts-use-speaker-boost": { + "description": "说话人增强", + "hint": "增强与原始说话人的相似度,可能略微增加延迟。", + }, + "mimo-tts-voice": { + "description": "音色", + "hint": "MiMo TTS 的音色名称。可选值包括 'mimo_default'、'default_en'、'default_zh'。", + }, + "mimo-tts-format": { + "description": "输出格式", + "hint": "MiMo TTS 生成音频的格式。支持 'wav'、'mp3'、'pcm'。", + }, + "mimo-tts-style-prompt": { + "description": "风格提示词", + "hint": "会以 标签形式添加到待合成文本开头,用于控制语速、情绪、角色或风格,例如 开心、变快、孙悟空、悄悄话。可留空。", + }, + "mimo-tts-dialect": { + "description": "方言", + "hint": "会与风格提示词一起写入开头的 标签中,例如 东北话、四川话、河南话、粤语。可留空。", + }, + "mimo-tts-seed-text": { + "description": "种子文本", + "hint": "作为可选的 user 消息发送,用于辅助调节语气和风格,不会拼接到待合成文本中。", + }, + "fishaudio-tts-character": { + "description": "character", + "hint": "fishaudio TTS 的角色。默认为可莉。更多角色请访问:https://fish.audio/zh-CN/discovery", + }, + "fishaudio-tts-reference-id": { + "description": "reference_id", + "hint": "fishaudio TTS 的参考模型ID(可选)。如果填入此字段,将直接使用模型ID而不通过角色名称查询。例如:626bb6d3f3364c9cbc3aa6a67300a664。更多模型请访问:https://fish.audio/zh-CN/discovery,进入模型详情界面后可复制模型ID", + }, + "whisper_hint": { + "description": "本地部署 Whisper 模型须知", + "hint": "启用前请 pip 安装 openai-whisper 库(N卡用户大约下载 2GB,主要是 torch 和 cuda,CPU 用户大约下载 1 GB),并且安装 ffmpeg。否则将无法正常转文字。", + }, + "whisper_device": { + "description": "推理设备", + "hint": "Whisper 推理设备。Apple Silicon 可选 mps;其他环境建议使用 cpu。若指定 mps 但当前环境不可用,将自动回退到 cpu。", + }, + "id": {"description": "ID"}, + "type": {"description": "模型提供商种类"}, + "provider_type": {"description": "模型提供商能力种类"}, + "enable": {"description": "启用"}, + "key": {"description": "API Key"}, + "api_base": {"description": "API Base URL"}, + "proxy": { + "description": "代理地址", + "hint": "HTTP/HTTPS 代理地址,格式如 http://127.0.0.1:7890。仅对该提供商的 API 请求生效,不影响 Docker 内网通信。", + }, + "model": { + "description": "模型 ID", + "hint": "模型名称,如 gpt-4o-mini, deepseek-chat。", + }, + "max_context_tokens": { + "description": "模型上下文窗口大小", + "hint": "模型最大上下文 Token 大小。如果为 0,则会自动从模型元数据填充(如有)。", + }, + "dify_api_key": { + "description": "API Key", + "hint": "Dify API Key。此项必填。", + }, + "dify_api_base": { + "description": "API Base URL", + "hint": "Dify API Base URL。默认为 https://api.dify.ai/v1", + }, + "dify_api_type": { + "description": "Dify 应用类型", + "hint": "Dify API 类型。根据 Dify 官网,目前支持 chat, chatflow, agent, workflow 三种应用类型。", + }, + "dify_workflow_output_key": { + "description": "Dify Workflow 输出变量名", + "hint": "Dify Workflow 输出变量名。当应用类型为 workflow 时才使用。默认为 astrbot_wf_output。", + }, + "dify_query_input_key": { + "description": "Prompt 输入变量名", + "hint": "发送的消息文本内容对应的输入变量名。默认为 astrbot_text_query。", + }, + "coze_api_key": { + "description": "Coze API Key", + "hint": "Coze API 密钥,用于访问 Coze 服务。", + }, + "bot_id": { + "description": "Bot ID", + "hint": "Coze 机器人的 ID,在 Coze 平台上创建机器人后获得。", + }, + "coze_api_base": { + "description": "API Base URL", + "hint": "Coze API 的基础 URL 地址,默认为 https://api.coze.cn", + }, + "deerflow_api_base": { + "description": "API Base URL", + "hint": "DeerFlow API 网关地址,默认为 http://127.0.0.1:2026", + }, + "deerflow_api_key": { + "description": "DeerFlow API Key", + "hint": "可选。若 DeerFlow 网关配置了 Bearer 鉴权,则在此填写。", + }, + "deerflow_auth_header": { + "description": "Authorization Header", + "hint": "可选。自定义 Authorization 请求头,优先级高于 DeerFlow API Key。", + }, + "deerflow_assistant_id": { + "description": "Assistant ID", + "hint": "DeerFlow 2.0 LangGraph assistant_id,默认为 lead_agent。", + }, + "deerflow_model_name": { + "description": "模型名称覆盖", + "hint": "可选。覆盖 DeerFlow 默认模型(对应运行时 configurable 的 model_name)。", + }, + "deerflow_thinking_enabled": {"description": "启用思考模式"}, + "deerflow_plan_mode": { + "description": "启用计划模式", + "hint": "对应 DeerFlow 2.0 运行时 configurable 的 is_plan_mode。", + }, + "deerflow_subagent_enabled": { + "description": "启用子智能体", + "hint": "对应 DeerFlow 2.0 运行时 configurable 的 subagent_enabled。", + }, + "deerflow_max_concurrent_subagents": { + "description": "子智能体最大并发数", + "hint": "对应 DeerFlow 2.0 运行时 configurable 的 max_concurrent_subagents。仅在启用子智能体时生效,默认 3。", + }, + "deerflow_recursion_limit": { + "description": "递归深度上限", + "hint": "对应 LangGraph recursion_limit。", + }, + "auto_save_history": { + "description": "由 Coze 管理对话记录", + "hint": "启用后,将由 Coze 进行对话历史记录管理, 此时 AstrBot 本地保存的上下文不会生效(仅供浏览), 对 AstrBot 的上下文进行的操作也不会生效。如果为禁用, 则使用 AstrBot 管理上下文。", }, - "emojis": { - "description": "表情列表(Unicode 或自定义表情名)", - "hint": "填写 Unicode 表情符号,例如:👍、🤔、⏳" - } - } - } - } - } - }, - "plugin_group": { - "name": "插件配置", - "plugin": { - "description": "插件", - "plugin_set": { - "description": "可用插件", - "hint": "默认启用全部未被禁用的插件。若插件在插件页面被禁用,则此处的选择不会生效。" - } - } - }, - "ext_group": { - "name": "扩展功能", - "segmented_reply": { - "description": "分段回复", - "platform_settings": { - "segmented_reply": { - "enable": { - "description": "启用分段回复" - }, - "only_llm_result": { - "description": "仅对 LLM 结果分段" - }, - "interval_method": { - "description": "间隔方法", - "hint": "random 为随机时间,log 为根据消息长度计算,$y=log_(x)$,x为字数,y的单位为秒。" - }, - "interval": { - "description": "随机间隔时间", - "hint": "格式:最小值,最大值(如:1.5,3.5)" - }, - "log_base": { - "description": "对数底数", - "hint": "对数间隔的底数,默认为 2.6。取值范围为 1.0-10.0。" - }, - "words_count_threshold": { - "description": "分段回复字数阈值", - "hint": "分段回复的字数上限。只有字数小于此值的消息才会被分段,超过此值的长消息将直接发送(不分段),默认为 150。" - }, - "split_mode": { - "description": "分段模式", - "hint": "用于分隔一段消息。默认情况下会根据句号、问号等标点符号分隔。如填写 `[。?!]` 将移除所有的句号、问号、感叹号。re.findall(r'', text)", - "labels": [ - "正则表达式", - "分段词列表" - ] - }, - "regex": { - "description": "分段正则表达式", - "hint": "用于按正则规则识别分段点。建议使用能匹配分隔符的表达式。" - }, - "split_words": { - "description": "分段词列表", - "hint": "检测到列表中的任意词时进行分段" - }, - "content_cleanup_rule": { - "description": "内容过滤正则表达式", - "hint": "移除分段后内容中的指定内容。如填写 `[。?!]` 将移除所有的句号、问号、感叹号。" - } } - } }, - "ltm": { - "description": "群聊上下文感知(原聊天记忆增强)", - "provider_ltm_settings": { - "group_icl_enable": { - "description": "启用群聊上下文感知" - }, - "group_message_max_cnt": { - "description": "最大消息数量" - }, - "image_caption": { - "description": "自动理解图片", - "hint": "需要设置群聊图片转述模型。" - }, - "image_caption_provider_id": { - "description": "群聊图片转述模型", - "hint": "用于群聊上下文感知的图片理解,与默认图片转述模型分开配置。" - }, - "active_reply": { - "enable": { - "description": "主动回复" - }, - "method": { - "description": "主动回复方法" - }, - "possibility_reply": { - "description": "回复概率", - "hint": "0.0-1.0 之间的数值" - }, - "whitelist": { - "description": "主动回复白名单", - "hint": "为空时不启用白名单过滤。使用 /sid 获取 ID。" - } - } - } - } - }, - "system_group": { - "name": "系统配置", - "system": { - "description": "系统配置", - "t2i_strategy": { - "description": "文本转图像策略", - "hint": "文本转图像策略。`remote` 为使用远程基于 HTML 的渲染服务,`local` 为使用 PIL 本地渲染。当使用 local 时,将 ttf 字体命名为 'font.ttf' 放在 data/ 目录下可自定义字体。" - }, - "t2i_endpoint": { - "description": "文本转图像服务 API 地址", - "hint": "为空时使用 AstrBot API 服务" - }, - "t2i_template": { - "description": "文本转图像自定义模版", - "hint": "启用后可自定义 HTML 模板用于文转图渲染。" - }, - "t2i_active_template": { - "description": "当前应用的文转图渲染模板", - "hint": "此处的值由文转图模板管理页面进行维护。" - }, - "log_level": { - "description": "控制台日志级别", - "hint": "控制台输出日志的级别。" - }, - "log_file_enable": { - "description": "启用文件日志", - "hint": "在控制台输出的同时,将日志写入文件。" - }, - "log_file_path": { - "description": "日志文件路径", - "hint": "相对路径以 data 目录为基准,例如 logs/astrbot.log;支持绝对路径。" - }, - "log_file_max_mb": { - "description": "日志文件大小上限 (MB)", - "hint": "超过大小后自动轮转,默认 20MB。" - }, - "temp_dir_max_size": { - "description": "临时目录大小上限 (MB)", - "hint": "用于限制 data/temp 目录总大小,单位为 MB。系统每 10 分钟检查一次,超限时按文件修改时间从旧到新删除,释放约 30% 当前体积。" - }, - "trace_log_enable": { - "description": "启用 Trace 文件日志", - "hint": "将 Trace 事件写入独立文件(不影响控制台输出)。" - }, - "trace_log_path": { - "description": "Trace 日志文件路径", - "hint": "相对路径以 data 目录为基准,例如 logs/astrbot.trace.log;支持绝对路径。" - }, - "trace_log_max_mb": { - "description": "Trace 日志大小上限 (MB)", - "hint": "超过大小后自动轮转,默认 20MB。" - }, - "pip_install_arg": { - "description": "pip 安装额外参数", - "hint": "安装插件依赖时,会使用 Python 的 pip 工具。这里可以填写额外的参数,如 `--break-system-package` 等。" - }, - "pypi_index_url": { - "description": "PyPI 软件仓库地址", - "hint": "安装 Python 依赖时请求的 PyPI 软件仓库地址。默认为 [https://mirrors.aliyun.com/pypi/simple/](https://mirrors.aliyun.com/pypi/simple/)" - }, - "callback_api_base": { - "description": "对外可达的回调接口地址", - "hint": "外部服务可能会通过 AstrBot 生成的回调链接(如文件下载链接)访问 AstrBot 后端。由于 AstrBot 无法自动判断部署环境中对外可达的主机地址(host),因此需要通过此配置项显式指定外部服务如何访问 AstrBot 的地址。如 [http://localhost:6185](http://localhost:6185),[https://example.com](https://example.com) 等。" - }, - "disable_metrics": { - "description": "禁用匿名使用统计", - "hint": "禁用后,AstrBot 将不再上传匿名使用统计数据。" - }, - "dashboard": { - "trust_proxy_headers": { - "description": "信任代理请求头获取客户端 IP", - "hint": "关闭时忽略 X-Forwarded-For/X-Real-IP,仅使用连接地址。" - }, - "auth_rate_limit": { - "enable": { - "description": "启用登录验证速率限制", - "hint": "关闭后将不对登录、TOTP 等身份验证接口进行速率限制。" - }, - "average_interval": { - "description": "验证端点速率限制平均间隔(秒)", - "hint": "两次身份验证请求之间的最小平均间隔时间。例如设置为 1.0 表示每秒最多处理 1 个请求。" - }, - "max_burst": { - "description": "验证端点速率限制最大突发数", - "hint": "允许的瞬时最大突发请求数。例如设置为 3 表示在短时间内最多连续处理 3 个请求。" - } - }, - "ssl": { - "enable": { - "description": "启用 WebUI HTTPS", - "hint": "启用后,WebUI 将直接使用 HTTPS 提供服务。" - }, - "cert_file": { - "description": "SSL 证书文件路径", - "hint": "证书文件路径(PEM)。支持绝对路径和相对路径(相对于当前工作目录)。" - }, - "key_file": { - "description": "SSL 私钥文件路径", - "hint": "私钥文件路径(PEM)。支持绝对路径和相对路径(相对于当前工作目录)。" - }, - "ca_certs": { - "description": "SSL CA 证书文件路径", - "hint": "可选。用于指定 CA 证书文件路径。" - } - }, - "totp": { - "enable": { - "description": "启用 WebUI TOTP 双因素认证", - "hint": "启用后,登录 WebUI 需要额外输入验证码。" - }, - "manage": "管理", - "configuration": "TOTP", - "statusPending": "需完成设置", - "statusEnabled": "已启用", - "setupRequiredHint": "TOTP 已开启但尚未完成配置,请点击“管理”完成初始化。", - "setupTitle": "设置 TOTP", - "setupSubtitle": "请使用认证器应用扫描二维码,然后输入验证码。", - "setupConfirm": "验证并继续", - "activeSubtitle": "可使用此二维码和密钥添加新的认证器设备。", - "rotateTitle": "更换 TOTP 密钥", - "rotateSubtitle": "生成新密钥并完成验证后,将替换当前密钥。", - "rotate": "更换密钥", - "rotateRecovery": "更换恢复码", - "rotateConfirm": "确认更换", - "rotateCancel": "取消", - "rotateCode": "验证码", - "rotateCodeHint": "输入认证器应用中的验证码以确认新密钥。", - "rotateError": "验证码无效,请重试。", - "recoveryTitle": "恢复码", - "recoverySubtitle": "恢复码仅展示一次,请在继续前妥善保存。", - "recoveryWarning": "若恢复码丢失将无法通过常规途径恢复账户访问权限。", - "recoveryAcknowledge": "我已保存恢复码", - "recoveryClose": "完成", - "disableTitle": "关闭 TOTP", - "disableSubtitle": "输入验证码以确认关闭双因素认证。", - "disableRecoverySubtitle": "输入恢复码以确认关闭双因素认证。", - "disableCode": "验证码", - "disableRecoveryCode": "恢复码", - "disableConfirm": "确认关闭", - "disableCancel": "取消", - "disableError": "验证失败,请重试。", - "disableUseRecovery": "无法使用TOTP?", - "disableUseCode": "使用验证码", - "configSaveTitle": "两步验证", - "configSaveSubtitle": "输入验证码以更改受保护的配置。", - "configSaveRotationHint": "轮换 TOTP 密钥时,轮换前和轮换后的验证码均可用(仅轮换操作中单次允许)。", - "configSaveCode": "验证码", - "configSaveConfirm": "继续", - "configSaveCancel": "取消", - "configSaveError": "验证失败,请重试。" - } - }, - "timezone": { - "description": "时区", - "hint": "时区设置。请填写 IANA 时区名称, 如 Asia/Shanghai, 为空时使用系统默认时区。所有时区请查看: [https://data.iana.org/time-zones/tzdb-2021a/zone1970.tab](https://data.iana.org/time-zones/tzdb-2021a/zone1970.tab)" - }, - "http_proxy": { - "description": "HTTP 代理", - "hint": "启用后,会以添加环境变量的方式设置代理。格式为 `http://ip:port`" - }, - "no_proxy": { - "description": "直连地址列表" - } - } - }, - "provider_group": { - "provider": { - "genie_onnx_model_dir": { - "description": "ONNX Model Directory", - "hint": "The directory path containing the ONNX model files" - }, - "genie_language": { - "description": "Language" - }, - "xai_native_search": { - "description": "启用原生搜索功能", - "hint": "启用后,将通过 xAI 的 Chat Completions 原生 Live Search 进行联网检索(按需计费)。仅对 xAI 提供商生效。" - }, - "rerank_api_base": { - "description": "重排序模型 API Base URL", - "hint": "最终请求路径由 Base URL 和路径后缀拼接而成(默认为 /v1/rerank)。" - }, - "rerank_api_suffix": { - "description": "API URL 路径后缀", - "hint": "追加到 base_url 后的路径后缀,如 /v1/rerank。留空则不追加。" - }, - "rerank_api_key": { - "description": "API Key", - "hint": "如果不需要 API Key, 请留空。" - }, - "rerank_model": { - "description": "重排序模型名称" - }, - "return_documents": { - "description": "是否在排序结果中返回文档原文", - "hint": "默认值false,以减少网络传输开销。" - }, - "instruct": { - "description": "自定义排序任务类型说明", - "hint": "仅在使用 qwen3-rerank 模型时生效。建议使用英文撰写。" - }, - "nvidia_rerank_api_base": { - "description": "API Base URL" - }, - "nvidia_rerank_api_key": { - "description": "API Key" - }, - "nvidia_rerank_model": { - "description": "重排序模型名称", - "hint": "请参照NVIDIA Docs中模型名称填写。" - }, - "nvidia_rerank_model_endpoint": { - "description": "自定义模型端点", - "hint": "自定义URL末尾端点,默认为 /reranking" - }, - "nvidia_rerank_truncate": { - "description": "文本截断策略", - "hint": "当输入文本过长时,是否截断输入以适应模型的最大上下文长度。" - }, - "tei_rerank_truncate": { - "description": "截断超长文本", - "hint": "当输入超过模型最大上下文长度时,是否自动截断。启用后需配合 截断方向 使用。" - }, - "tei_rerank_truncation_direction": { - "description": "截断方向", - "hint": "选择从文本的左侧(left)还是右侧(right)开始截断。仅在 截断超长文本 为 True 时生效。" - }, - "tei_rerank_raw_scores": { - "description": "返回原始分数", - "hint": "如果为 True,返回模型原始 logit 分数(可能为负值),不经过 sigmoid 归一化。默认 False。" - }, - "tei_rerank_return_text": { - "description": "返回排序结果中的文档原文", - "hint": "如果为 True,每个排序结果将附带原始文本。默认 False 以减少网络传输。" - }, - "launch_model_if_not_running": { - "description": "模型未运行时自动启动", - "hint": "如果模型当前未在 Xinference 服务中运行,是否尝试自动启动它。在生产环境中建议关闭。" - }, - "modalities": { - "description": "模型能力", - "hint": "模型支持的模态及能力。", - "labels": [ - "文本", - "图像", - "音频", - "工具使用" - ] - }, - "custom_headers": { - "description": "自定义请求头", - "hint": "此处添加的键值对将被合并到 OpenAI SDK 的 default_headers 中,用于自定义 HTTP 请求头。值必须为字符串。" - }, - "ollama_disable_thinking": { - "description": "关闭思考模式", - "hint": "关闭 Ollama 思考模式。" - }, - "custom_extra_body": { - "description": "自定义请求体参数", - "hint": "用于在请求时添加额外的参数,如 temperature, top_p, max_tokens, reasoning_effort 等。", - "template_schema": { - "temperature": { - "description": "温度参数", - "hint": "控制输出的随机性,范围通常为 0-2。值越高越随机。", - "name": "Temperature" - }, - "top_p": { - "description": "Top-p 采样", - "hint": "核采样参数,范围通常为 0-1。控制模型考虑的概率质量。", - "name": "Top-p" - }, - "max_tokens": { - "description": "最大词元(Tokens)数", - "hint": "生成的最大词元(Tokens)数。", - "name": "Max Tokens" - } - } - }, - "gpt_weights_path": { - "description": "GPT模型文件路径", - "hint": "即“.ckpt”后缀的文件,请使用绝对路径,路径两端不要带双引号,不填则默认用GPT_SoVITS内置的SoVITS模型(建议直接在GPT_SoVITS中改默认模型)" - }, - "sovits_weights_path": { - "description": "SoVITS模型文件路径", - "hint": "即“.pth”后缀的文件,请使用绝对路径,路径两端不要带双引号,不填则默认用GPT_SoVITS内置的SoVITS模型(建议直接在GPT_SoVITS中改默认模型)" - }, - "gsv_default_parms": { - "description": "GPT_SoVITS默认参数", - "hint": "参考音频文件路径、参考音频文本必填,其他参数根据个人爱好自行填写", - "gsv_ref_audio_path": { - "description": "参考音频文件路径", - "hint": "必填!请使用绝对路径!路径两端不要带双引号!" - }, - "gsv_prompt_text": { - "description": "参考音频文本", - "hint": "必填!请填写参考音频讲述的文本" - }, - "gsv_prompt_lang": { - "description": "参考音频文本语言", - "hint": "请填写参考音频讲述的文本的语言,默认为中文" - }, - "gsv_aux_ref_audio_paths": { - "description": "辅助参考音频文件路径", - "hint": "辅助参考音频文件,可不填" - }, - "gsv_text_lang": { - "description": "文本语言", - "hint": "默认为中文" - }, - "gsv_top_k": { - "description": "生成语音的多样性", - "hint": "" - }, - "gsv_top_p": { - "description": "核采样的阈值", - "hint": "" - }, - "gsv_temperature": { - "description": "生成语音的随机性", - "hint": "" - }, - "gsv_text_split_method": { - "description": "切分文本的方法", - "hint": "可选值: `cut0`:不切分 `cut1`:四句一切 `cut2`:50字一切 `cut3`:按中文句号切 `cut4`:按英文句号切 `cut5`:按标点符号切" - }, - "gsv_batch_size": { - "description": "批处理大小", - "hint": "" - }, - "gsv_batch_threshold": { - "description": "批处理阈值", - "hint": "" - }, - "gsv_split_bucket": { - "description": "将文本分割成桶以便并行处理", - "hint": "" - }, - "gsv_speed_factor": { - "description": "语音播放速度", - "hint": "1为原始语速" - }, - "gsv_fragment_interval": { - "description": "语音片段之间的间隔时间", - "hint": "" - }, - "gsv_streaming_mode": { - "description": "启用流模式", - "hint": "" - }, - "gsv_seed": { - "description": "随机种子", - "hint": "用于结果的可重复性" - }, - "gsv_parallel_infer": { - "description": "并行执行推理", - "hint": "" - }, - "gsv_repetition_penalty": { - "description": "重复惩罚因子", - "hint": "" - }, - "gsv_media_type": { - "description": "输出媒体的类型", - "hint": "建议用wav" - } - }, - "embedding_dimensions": { - "description": "嵌入维度", - "hint": "嵌入向量的维度。根据模型不同,可能需要调整,请参考具体模型的文档。此配置项请务必填写正确,否则将导致向量数据库无法正常工作。" - }, - "embedding_dimensions_mode": { - "description": "嵌入维度参数发送模式", - "hint": "控制是否在 OpenAI 兼容 Embedding 请求中发送 dimensions 参数。auto 会仅对官方 OpenAI embedding-3 模型自动发送;第三方兼容 API 如需该参数可改为 always,报错时改为 never。" - }, - "embedding_model": { - "description": "嵌入模型", - "hint": "嵌入模型名称。" - }, - "embedding_api_key": { - "description": "API Key" - }, - "embedding_api_base": { - "description": "API Base URL" - }, - "openai_embedding": { - "hint": "如果测试不通过,可以尝试添加 /v1 在末尾以兼容部分 OpenAI API 版本。" - }, - "gemini_embedding": { - "hint": "Gemini Embedding 无需手动添加 /v1beta。" - }, - "volcengine_cluster": { - "description": "火山引擎集群", - "hint": "若使用语音复刻大模型,可选volcano_icl或volcano_icl_concurr,默认使用volcano_tts" - }, - "volcengine_voice_type": { - "description": "火山引擎音色", - "hint": "输入声音id(Voice_type)" - }, - "volcengine_speed_ratio": { - "description": "语速设置", - "hint": "语速设置,范围为 0.2 到 3.0,默认值为 1.0" - }, - "volcengine_volume_ratio": { - "description": "音量设置", - "hint": "音量设置,范围为 0.0 到 2.0,默认值为 1.0" - }, - "azure_tts_voice": { - "description": "音色设置", - "hint": "API 音色" - }, - "azure_tts_style": { - "description": "风格设置", - "hint": "声音特定的讲话风格。 可以表达快乐、同情和平静等情绪。" - }, - "azure_tts_role": { - "description": "模仿设置(可选)", - "hint": "讲话角色扮演。 声音可以模仿不同的年龄和性别,但声音名称不会更改。 例如,男性语音可以提高音调和改变语调来模拟女性语音,但语音名称不会更改。 如果角色缺失或不受声音的支持,则会忽略此属性。" - }, - "azure_tts_rate": { - "description": "语速设置", - "hint": "指示文本的讲出速率。可在字词或句子层面应用语速。 速率变化应为原始音频的 0.5 到 2 倍。" - }, - "azure_tts_volume": { - "description": "语音音量设置", - "hint": "指示语音的音量级别。 可在句子层面应用音量的变化。以从 0.0 到 100.0(从最安静到最大声,例如 75)的数字表示。 默认值为 100.0。" - }, - "azure_tts_region": { - "description": "API 地区", - "hint": "Azure_TTS 处理数据所在区域,具体参考 https://learn.microsoft.com/zh-cn/azure/ai-services/speech-service/regions" - }, - "azure_tts_subscription_key": { - "description": "服务订阅密钥", - "hint": "Azure_TTS 服务的订阅密钥(注意不是令牌)" - }, - "dashscope_tts_voice": { - "description": "音色" - }, - "gm_resp_image_modal": { - "description": "启用图片模态", - "hint": "启用后,将支持返回图片内容。需要模型支持,否则会报错。具体支持模型请查看 Google Gemini 官方网站。温馨提示,如果您需要生成图片,请关闭 `启用群员识别` 配置获得更好的效果。" - }, - "gm_native_search": { - "description": "启用原生搜索功能", - "hint": "启用后所有函数工具将全部失效,免费次数限制请查阅官方文档" - }, - "gm_native_coderunner": { - "description": "启用原生代码执行器", - "hint": "启用后所有函数工具将全部失效" - }, - "gm_url_context": { - "description": "启用URL上下文功能", - "hint": "启用后所有函数工具将全部失效" - }, - "gm_safety_settings": { - "description": "安全过滤器", - "hint": "设置模型输入的内容安全过滤级别。过滤级别分类为NONE(不屏蔽)、HIGH(高风险时屏蔽)、MEDIUM_AND_ABOVE(中等风险及以上屏蔽)、LOW_AND_ABOVE(低风险及以上时屏蔽),具体参见Gemini API文档。", - "harassment": { - "description": "骚扰内容", - "hint": "负面或有害评论" - }, - "hate_speech": { - "description": "仇恨言论", - "hint": "粗鲁、无礼或亵渎性质内容" - }, - "sexually_explicit": { - "description": "露骨色情内容", - "hint": "包含性行为或其他淫秽内容的引用" - }, - "dangerous_content": { - "description": "危险内容", - "hint": "宣扬、助长或鼓励有害行为的信息" - } - }, - "gm_thinking_config": { - "description": "思考配置", - "budget": { - "description": "思考预算", - "hint": "用于指定模型推理时使用的思考 token 数量上限。参见: https://ai.google.dev/gemini-api/docs/thinking#set-budget" - }, - "level": { - "description": "思考级别", - "hint": "推荐用于 Gemini 3 及以上模型,可控制推理行为。参见: https://ai.google.dev/gemini-api/docs/thinking#thinking-levels" - } - }, - "anth_thinking_config": { - "description": "思考配置", - "type": { - "description": "思考类型", - "hint": "设为 'adaptive' 以使用自适应思考(推荐 Opus 4.6+ / Sonnet 4.6+)。留空则使用手动预算模式。参见: https://platform.claude.com/docs/en/build-with-claude/adaptive-thinking" - }, - "budget": { - "description": "思考预算", - "hint": "Anthropic thinking.budget_tokens 参数。必须 >= 1024。仅在思考类型为空时生效。Opus 4.6 / Sonnet 4.6 已弃用。参见: https://platform.claude.com/docs/en/build-with-claude/extended-thinking" - }, - "effort": { - "description": "思考深度", - "hint": "当思考类型为 'adaptive' 时控制思考深度。'high' 为默认值。'max' 仅限 Opus 4.6。参见: https://platform.claude.com/docs/en/build-with-claude/effort" - } - }, - "minimax-group-id": { - "description": "用户组", - "hint": "于账户管理->基本信息中可见" - }, - "minimax-langboost": { - "description": "指定语言/方言", - "hint": "增强对指定的小语种和方言的识别能力,设置后可以提升在指定小语种/方言场景下的语音表现" - }, - "minimax-voice-speed": { - "description": "语速", - "hint": "生成声音的语速, 取值[0.5, 2], 默认为1.0, 取值越大,语速越快" - }, - "minimax-voice-vol": { - "description": "音量", - "hint": "生成声音的音量, 取值(0, 10], 默认为1.0, 取值越大,音量越高" - }, - "minimax-voice-pitch": { - "description": "语调", - "hint": "生成声音的语调, 取值[-12, 12], 默认为0" - }, - "minimax-is-timber-weight": { - "description": "启用混合音色", - "hint": "启用混合音色, 支持以自定义权重混合最多四种音色, 启用后自动忽略单一音色设置" - }, - "minimax-timber-weight": { - "description": "混合音色", - "hint": "混合音色及其权重, 最多支持四种音色, 权重为整数, 取值[1, 100]. 可在官网API语音调试台预览代码获得预设以及编写模板, 需要严格按照json字符串格式编写, 可以查看控制台判断是否解析成功. 具体结构可参照默认值以及官网代码预览." - }, - "minimax-voice-id": { - "description": "单一音色", - "hint": "单一音色编号, 详见官网文档" - }, - "minimax-voice-emotion": { - "description": "情绪", - "hint": "控制合成语音的情绪。当为 auto 时,将根据文本内容自动选择情绪。" - }, - "minimax-voice-latex": { - "description": "支持朗读latex公式", - "hint": "朗读latex公式, 但是需要确保输入文本按官网要求格式化" - }, - "minimax-voice-english-normalization": { - "description": "支持英语文本规范化", - "hint": "可提升数字阅读场景的性能,但会略微增加延迟" - }, - "rag_options": { - "description": "RAG 选项", - "hint": "检索知识库设置, 非必填。仅 Agent 应用类型支持(智能体应用, 包括 RAG 应用)。阿里云百炼应用开启此功能后将无法多轮对话。", - "pipeline_ids": { - "description": "知识库 ID 列表", - "hint": "对指定知识库内所有文档进行检索, 前往 https://bailian.console.aliyun.com/ 数据应用->知识索引创建和获取 ID。" - }, - "file_ids": { - "description": "非结构化文档 ID, 传入该参数将对指定非结构化文档进行检索。", - "hint": "对指定非结构化文档进行检索。前往 https://bailian.console.aliyun.com/ 数据管理创建和获取 ID。" - }, - "output_reference": { - "description": "是否输出知识库/文档的引用", - "hint": "在每次回答尾部加上引用源。默认为 False。" - } - }, - "sensevoice_hint": { - "description": "部署SenseVoice", - "hint": "启用前请 pip 安装 funasr、funasr_onnx、torchaudio、torch、modelscope、jieba 库(默认使用CPU,大约下载 1 GB),并且安装 ffmpeg。否则将无法正常转文字。" - }, - "is_emotion": { - "description": "情绪识别", - "hint": "是否开启情绪识别。happy|sad|angry|neutral|fearful|disgusted|surprised|unknown" - }, - "stt_model": { - "description": "模型名称", - "hint": "modelscope 上的模型名称。默认:iic/SenseVoiceSmall。" - }, - "variables": { - "description": "工作流固定输入变量", - "hint": "可选。工作流固定输入变量,将会作为工作流的输入。也可以在对话时使用 /set 指令动态设置变量。如果变量名冲突,优先使用动态设置的变量。" - }, - "dashscope_app_type": { - "description": "应用类型", - "hint": "百炼应用的应用类型。" - }, - "timeout": { - "description": "超时时间", - "hint": "超时时间,单位为秒。" - }, - "openai-tts-voice": { - "description": "voice", - "hint": "OpenAI TTS 的声音。OpenAI 默认支持:'alloy', 'echo', 'fable', 'onyx', 'nova', 'shimmer'" - }, - "elevenlabs-tts-voice-id": { - "description": "音色 ID", - "hint": "ElevenLabs 音色 ID。可在 https://elevenlabs.io/app/voice-library 浏览并复制音色 ID。默认 'JBFqnCBsd6RMkjVDRZzb'(George)。" - }, - "elevenlabs-tts-output-format": { - "description": "输出格式", - "hint": "音频输出格式,例如 'mp3_44100_128'、'mp3_22050_32'、'wav_44100'、'opus_48000_128'。不支持裸 PCM/u-law/a-law 格式。默认 'mp3_44100_128'。" - }, - "elevenlabs-tts-stability": { - "description": "稳定性", - "hint": "音色稳定性,范围 [0, 1]。值越高越稳定,越低越富有表现力。留空则使用服务端默认值。" - }, - "elevenlabs-tts-similarity-boost": { - "description": "相似度增强", - "hint": "输出与原始音色的接近程度,范围 [0, 1]。留空则使用服务端默认值。" - }, - "elevenlabs-tts-style": { - "description": "风格夸张度", - "hint": "音色风格的夸张程度,范围 [0, 1]。值越高延迟越大。留空则使用服务端默认值。" - }, - "elevenlabs-tts-use-speaker-boost": { - "description": "说话人增强", - "hint": "增强与原始说话人的相似度,可能略微增加延迟。" - }, - "mimo-tts-voice": { - "description": "音色", - "hint": "MiMo TTS 的音色名称。可选值包括 'mimo_default'、'default_en'、'default_zh'。" - }, - "mimo-tts-format": { - "description": "输出格式", - "hint": "MiMo TTS 生成音频的格式。支持 'wav'、'mp3'、'pcm'。" - }, - "mimo-tts-style-prompt": { - "description": "风格提示词", - "hint": "会以 标签形式添加到待合成文本开头,用于控制语速、情绪、角色或风格,例如 开心、变快、孙悟空、悄悄话。可留空。" - }, - "mimo-tts-dialect": { - "description": "方言", - "hint": "会与风格提示词一起写入开头的 标签中,例如 东北话、四川话、河南话、粤语。可留空。" - }, - "mimo-tts-seed-text": { - "description": "种子文本", - "hint": "作为可选的 user 消息发送,用于辅助调节语气和风格,不会拼接到待合成文本中。" - }, - "fishaudio-tts-character": { - "description": "character", - "hint": "fishaudio TTS 的角色。默认为可莉。更多角色请访问:https://fish.audio/zh-CN/discovery" - }, - "fishaudio-tts-reference-id": { - "description": "reference_id", - "hint": "fishaudio TTS 的参考模型ID(可选)。如果填入此字段,将直接使用模型ID而不通过角色名称查询。例如:626bb6d3f3364c9cbc3aa6a67300a664。更多模型请访问:https://fish.audio/zh-CN/discovery,进入模型详情界面后可复制模型ID" - }, - "whisper_hint": { - "description": "本地部署 Whisper 模型须知", - "hint": "启用前请 pip 安装 openai-whisper 库(N卡用户大约下载 2GB,主要是 torch 和 cuda,CPU 用户大约下载 1 GB),并且安装 ffmpeg。否则将无法正常转文字。" - }, - "whisper_device": { - "description": "推理设备", - "hint": "Whisper 推理设备。Apple Silicon 可选 mps;其他环境建议使用 cpu。若指定 mps 但当前环境不可用,将自动回退到 cpu。" - }, - "id": { - "description": "ID" - }, - "type": { - "description": "模型提供商种类" - }, - "provider_type": { - "description": "模型提供商能力种类" - }, - "enable": { - "description": "启用" - }, - "key": { - "description": "API Key" - }, - "api_base": { - "description": "API Base URL" - }, - "proxy": { - "description": "代理地址", - "hint": "HTTP/HTTPS 代理地址,格式如 http://127.0.0.1:7890。仅对该提供商的 API 请求生效,不影响 Docker 内网通信。" - }, - "model": { - "description": "模型 ID", - "hint": "模型名称,如 gpt-4o-mini, deepseek-chat。" - }, - "max_context_tokens": { - "description": "模型上下文窗口大小", - "hint": "模型最大上下文 Token 大小。如果为 0,则会自动从模型元数据填充(如有)。" - }, - "dify_api_key": { - "description": "API Key", - "hint": "Dify API Key。此项必填。" - }, - "dify_api_base": { - "description": "API Base URL", - "hint": "Dify API Base URL。默认为 https://api.dify.ai/v1" - }, - "dify_api_type": { - "description": "Dify 应用类型", - "hint": "Dify API 类型。根据 Dify 官网,目前支持 chat, chatflow, agent, workflow 三种应用类型。" - }, - "dify_workflow_output_key": { - "description": "Dify Workflow 输出变量名", - "hint": "Dify Workflow 输出变量名。当应用类型为 workflow 时才使用。默认为 astrbot_wf_output。" - }, - "dify_query_input_key": { - "description": "Prompt 输入变量名", - "hint": "发送的消息文本内容对应的输入变量名。默认为 astrbot_text_query。" - }, - "coze_api_key": { - "description": "Coze API Key", - "hint": "Coze API 密钥,用于访问 Coze 服务。" - }, - "bot_id": { - "description": "Bot ID", - "hint": "Coze 机器人的 ID,在 Coze 平台上创建机器人后获得。" - }, - "coze_api_base": { - "description": "API Base URL", - "hint": "Coze API 的基础 URL 地址,默认为 https://api.coze.cn" - }, - "deerflow_api_base": { - "description": "API Base URL", - "hint": "DeerFlow API 网关地址,默认为 http://127.0.0.1:2026" - }, - "deerflow_api_key": { - "description": "DeerFlow API Key", - "hint": "可选。若 DeerFlow 网关配置了 Bearer 鉴权,则在此填写。" - }, - "deerflow_auth_header": { - "description": "Authorization Header", - "hint": "可选。自定义 Authorization 请求头,优先级高于 DeerFlow API Key。" - }, - "deerflow_assistant_id": { - "description": "Assistant ID", - "hint": "DeerFlow 2.0 LangGraph assistant_id,默认为 lead_agent。" - }, - "deerflow_model_name": { - "description": "模型名称覆盖", - "hint": "可选。覆盖 DeerFlow 默认模型(对应运行时 configurable 的 model_name)。" - }, - "deerflow_thinking_enabled": { - "description": "启用思考模式" - }, - "deerflow_plan_mode": { - "description": "启用计划模式", - "hint": "对应 DeerFlow 2.0 运行时 configurable 的 is_plan_mode。" - }, - "deerflow_subagent_enabled": { - "description": "启用子智能体", - "hint": "对应 DeerFlow 2.0 运行时 configurable 的 subagent_enabled。" - }, - "deerflow_max_concurrent_subagents": { - "description": "子智能体最大并发数", - "hint": "对应 DeerFlow 2.0 运行时 configurable 的 max_concurrent_subagents。仅在启用子智能体时生效,默认 3。" - }, - "deerflow_recursion_limit": { - "description": "递归深度上限", - "hint": "对应 LangGraph recursion_limit。" - }, - "auto_save_history": { - "description": "由 Coze 管理对话记录", - "hint": "启用后,将由 Coze 进行对话历史记录管理, 此时 AstrBot 本地保存的上下文不会生效(仅供浏览), 对 AstrBot 的上下文进行的操作也不会生效。如果为禁用, 则使用 AstrBot 管理上下文。" - } - } - }, - "help": { - "documentation": "官方文档", - "support": "加群询问", - "helpText": "不了解配置?请见 {documentation} 或 {support}。", - "helpPrefix": "不了解配置?请见", - "helpMiddle": "或", - "helpSuffix": "。" - } + "help": { + "documentation": "官方文档", + "support": "加群询问", + "helpText": "不了解配置?请见 {documentation} 或 {support}。", + "helpPrefix": "不了解配置?请见", + "helpMiddle": "或", + "helpSuffix": "。", + }, } diff --git a/tests/unit/test_modalities_sanitize.py b/tests/unit/test_modalities_sanitize.py index 966101708a..0f1c1cba60 100644 --- a/tests/unit/test_modalities_sanitize.py +++ b/tests/unit/test_modalities_sanitize.py @@ -281,3 +281,74 @@ def test_empty_contexts_returns_empty() -> None: assert sanitized == [] assert isinstance(stats, ContextSanitizeStats) assert not stats.changed + + +# --------------------------------------------------------------------------- +# Whitelist mode: supported_image_mimes parameter +# --------------------------------------------------------------------------- + + +def test_whitelist_filters_gif_but_preserves_jpeg_and_png() -> None: + """When whitelist excludes GIF, GIF is replaced but JPEG/PNG are kept.""" + contexts = [ + _user( + _image_url_part(GIF_DATA_URL), + _image_url_part(JPEG_DATA_URL), + _image_url_part(PNG_DATA_URL), + ), + ] + sanitized, stats = sanitize_contexts_by_modalities( + contexts, + ["text", "image"], + supported_image_mimes=["image/jpeg", "image/png"], + ) + + assert sanitized[0]["content"] == [ + {"type": "text", "text": "[Image]"}, # GIF replaced + _image_url_part(JPEG_DATA_URL), # JPEG preserved + _image_url_part(PNG_DATA_URL), # PNG preserved + ] + assert stats.fixed_image_blocks == 1 + + +def test_whitelist_includes_gif_preserves_gif() -> None: + """When whitelist includes GIF, GIF is preserved.""" + contexts = [_user(_image_url_part(GIF_DATA_URL))] + sanitized, stats = sanitize_contexts_by_modalities( + contexts, + ["text", "image"], + supported_image_mimes=["image/jpeg", "image/png", "image/gif"], + ) + + assert sanitized[0]["content"] == [_image_url_part(GIF_DATA_URL)] + assert not stats.changed + + +def test_whitelist_none_falls_back_to_blocklist_gif_replaced() -> None: + """When whitelist is None, fallback blocklist applies (GIF replaced). + + This ensures backward compatibility: users who don't configure + supported_image_mimes still get the #9295 GIF fix. + """ + contexts = [_user(_image_url_part(GIF_DATA_URL))] + sanitized, stats = sanitize_contexts_by_modalities( + contexts, + ["text", "image"], + supported_image_mimes=None, + ) + + assert sanitized[0]["content"] == [{"type": "text", "text": "[Image]"}] + assert stats.fixed_image_blocks == 1 + + +def test_whitelist_empty_list_same_as_none() -> None: + """Empty list for whitelist behaves the same as None (blocklist fallback).""" + contexts = [_user(_image_url_part(GIF_DATA_URL))] + sanitized, stats = sanitize_contexts_by_modalities( + contexts, + ["text", "image"], + supported_image_mimes=[], + ) + + assert sanitized[0]["content"] == [{"type": "text", "text": "[Image]"}] + assert stats.fixed_image_blocks == 1