From e40565c0de01f1072c5f75663fdda11559afa4e2 Mon Sep 17 00:00:00 2001 From: Schaled Date: Sun, 25 Oct 2026 14:23:10 +0800 Subject: [PATCH] =?UTF-8?q?docs:=20=E6=9B=B4=E6=96=B0=E5=88=B0=201.3.15?= =?UTF-8?q?=EF=BC=88WebUI=201.9.9=EF=BC=9Bzh=20+=20en=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - changelog 补齐 1.3.12–1.3.15 与 WebUI 1.9.6–1.9.9 - bot-config:实验段重组([capabilities] 能力段、[agent] Agent 连接、 快速反应模式移入 [chat.reply_timing])、私聊暂停回复、图片画质、 滚动状态摘要、表达快速/精细两档;移除已删除的键 - model-config:联网服务新增 AnySearch / Exa / Firecrawl - FAQ 聊天与回复、运行时排错按当前行为重写 - 修复上游带入的失效锚点与 en webui-pages 缺失 H1 - docs-quality 脚本:容忍 CRLF 行尾、识别标题 {#id} 自定义锚点 --- en/changelog/index.md | 61 ++++++++++++ en/faq/chat-and-reply.md | 19 ++-- en/faq/troubleshooting-runtime.md | 2 +- en/manual/configuration/bot-config.md | 127 ++++++++++++++++-------- en/manual/configuration/index.md | 2 +- en/manual/configuration/model-config.md | 45 ++++++++- en/plugin/api-reference.md | 2 +- en/plugin/webui-pages.md | 2 + scripts/docs-quality.mjs | 15 ++- zh/changelog/index.md | 61 ++++++++++++ zh/faq/chat-and-reply.md | 19 ++-- zh/faq/troubleshooting-runtime.md | 2 +- zh/manual/configuration/bot-config.md | 127 ++++++++++++++++-------- zh/manual/configuration/index.md | 2 +- zh/manual/configuration/model-config.md | 45 ++++++++- zh/plugin/api-reference.md | 2 +- 16 files changed, 415 insertions(+), 118 deletions(-) diff --git a/en/changelog/index.md b/en/changelog/index.md index 862c49f..b21b8c3 100644 --- a/en/changelog/index.md +++ b/en/changelog/index.md @@ -5,6 +5,67 @@ description: Feature updates, fixes, and configuration changes across MaiBot rel # Changelog +::: timeline 2026-10-23 +### Main program [1.3.15] +* Context compaction now keeps a rolling state summary generated by the utils model and always sent with the Planner context; its length is controlled by `context_compaction_summary_max_chars`. +* Web search adds three new services: AnySearch, Exa, and Firecrawl. +* Plugin management adds `/pm cmd [plugin ID or unique short name] [pic]` to list registered commands per plugin, optionally rendered as an image. +* Private chats support pausing replies: globally, or per platform and user, replacing the old private-chat frequency setting. +* Expression selection now has Fast and Fine modes: Fast is the default and injects a weighted random pick directly; Fine uses expression intent and embedding recall followed by LLM filtering, and requires an embedding model. +* Image quality now offers Normal and High modes; images sent to the Planner and Replyer are compressed to a longest edge of 512 / 1024 pixels respectively. +* Fixed replies not triggering for messages from old bot accounts, send failures caused by wrong quotes, and the retro reply mode being enabled unintentionally. +* In normal and Focus modes, consecutive waiting no longer forcibly ends the conversation; MaiBot is instead reminded to extend the wait or end it. + +### WebUI [1.9.9] +* Learning: expressions and jargon support manual entry and long-text auto learning, with editing, selection, and import to a specific chat or globally; progress viewing, retry on failure, and batch imports are supported. +* Learning: expression and jargon lists can be sorted by activity or creation time and show the group or private-user ID. +* When plugins are downloaded via the CNB mirror, plugin icons load from the mirror too. +* Prompt templates that need an update or fix now show a reminder at the entry point and on the template. +* Agent sessions merge consecutive thinking and reply content and fix lost spaces and line breaks. +* Smoother page-switch animation; fixed clipped home statistics, misaligned layouts, and inconsistent language-menu styling. +::: + +::: timeline 2026-10-22 +### Main program [1.3.14] +* Quick reaction mode is now a formal feature, with improved reply frequency and wait timing for more timely, natural responses. +* Improved default settings and prompts. + +### WebUI [1.9.8] +* First-run onboarding can fill in persona, behavior style, and reply style from a standalone preset list. +::: + +::: timeline 2026-10-21 +### Main program [1.3.13] +* Agent connection (experimental): connect to dsh and dsh Desktop over ACP; models and credentials come from the external Agent's own configuration. +* Plugins can generate long posts in MaiBot's persona and reply with text and stickers to a chosen post, comment, or nested reply. +* Plugin installation failures report clearer causes, with direct download-source switching and retry. +* Added memory diagnostics to help investigate memory growth in long-running instances. +* Reduced memory usage from large image histories; fixed retro reply mode failing on image handling. + +### WebUI [1.9.7] +* The top bar shows an update reminder when a new version is available. +* Fixed a chat-page scroll area that could crash the page. +::: + +::: timeline 2026-10-19 +### Main program [1.3.12] +* Added a standalone computer-operating agent: image-text relay in chats, tasks that survive restarts, and a WebUI view of the desktop, run history, and manual takeover. +* Focus chats in the same group now share one continuous thinking process, with cross-session collaboration, unified waiting, and early wake-up on @ mentions. +* Improved thinking and tool usage; subagent tasks and long tool-result condensation are configured in the `[capabilities]` section. +* Expression and jargon learning can accumulate multiple batches of chat material, so even quiet chats gradually meet the learning threshold. +* Unified the plugin market browsing and usage experience, with better install, update, and enable flows; disabled plugins no longer slow startup, and failed installs no longer damage existing dependencies. +* `/offline` now stops chat activity so MaiBot no longer thinks or wakes up while offline. +* Removed the reply-effect evaluation feature. + +### WebUI [1.9.6] +* Model configuration adds a "MaiBot-tuned reply" template that fills in the required models and reply settings, with a direct reply test. +* Settings adds a "General" section, unifying the language entry for desktop and mobile. +* The learning page merges expressions, jargon, and stickers, clearly showing learning progress and why a task is incomplete. +* Reasoning replay fixed image messages not previewing. +* Mobile improves the bottom-bar transition animation, which can follow the global animation setting. +* Chat observation shows tool execution status even when rounds are collapsed; detailed statistics support spending and token breakdowns by dimension. +::: + ::: timeline 2026-10-19 ### Main program [1.3.11] * Message debouncing now has four fixed modes — Off, Fast, Natural, and Steady — with Natural as the default. Quiet and active chats, the same sender continuing, and a different sender each use their own wait time; a batch waits at most 8 seconds, and an @ mention or name mention enters processing within 1 second. diff --git a/en/faq/chat-and-reply.md b/en/faq/chat-and-reply.md index 99902ab..ba2afac 100644 --- a/en/faq/chat-and-reply.md +++ b/en/faq/chat-and-reply.md @@ -4,36 +4,33 @@ title: Chat and Replies # Chat and Replies -## What is the difference between frequency and dynamic trigger? +## How does MaiBot decide whether to reply? -`[chat.reply_timing].reply_trigger_mode` decides when new messages enter the Planner: +New messages first go through debouncing, then the Planner decides whether to respond. The reply tendency is mainly tuned by the frequency settings `talk_value` and `talk_value_rules`: Mai tries to reply when @-mentioned and replies more easily when named. After several consecutive no-reply decisions, the check pace automatically slows down via `no_action_backoff_*`. -- **`frequency` (default)** — decides whether to think based on the number of new messages; simple and predictable -- **`dynamic`** — estimates the reply likelihood of each message batch, then uses a one-hour sliding window to pull the actual reply count back to the configured target. It **only applies to group chats; private chats are not gated** - -After switching modes, observe for a while before deciding whether to fine-tune `talk_value`. +After changing the frequency, observe for a while before fine-tuning further. ## How do I make MaiBot speak more or less often? -Adjust group or private-chat frequency, then check dynamic frequency rules. When dynamic rules are enabled, a matching rule may override the base value. Personality and group prompts can also affect the Planner's decision to speak. +Adjust group or private-chat frequency, then check the per-chat and per-time rules (`talk_value_rules`). When rules are enabled, a matching rule may override the base value. Personality and group prompts can also affect the Planner's decision to speak. Make small changes and observe the result. ## Why does the bot reply to its own messages? -Check whether the adapter feeds outgoing bot messages back into MaiBot and whether the configured bot account is correct. Then inspect plugin conflicts, message filtering, and dynamic frequency rules. +Check whether the adapter feeds outgoing bot messages back into MaiBot and whether the configured bot account is correct. Then inspect plugin conflicts, message filtering, and frequency rules. If the message path is correct but the Planner still chooses repeated replies, adjust frequency or test another Planner model. The symptom alone does not prove a model-quality issue. ## Why is only the first of several consecutive messages handled? -Whether a new message restarts Planner reasoning depends on the trigger mode and consecutive-interrupt limit. Model latency, tool calls, and context size also affect responsiveness. +First check whether the messages were merged into one batch by debouncing; model latency, tool calls, and context size also slow down a single turn. -Review `planner_interrupt_max_consecutive_count`, but do not copy a fixed value blindly. More permissive interruption improves responsiveness but can increase model calls and context use. +To let new messages arriving during thinking, output, or waiting join immediately and restart reasoning, enable quick reaction mode (`[chat.reply_timing].planner_message_steering`). ## Why are replies slow? -Use logs to identify whether time is spent on model requests, tools, image recognition, adapter delivery, or Planner waiting. Then inspect network latency, model speed, context length, and unnecessary plugins. Also review interruption settings if new messages wait for the previous turn to finish. +Use logs to identify whether time is spent on model requests, tools, image recognition, adapter delivery, or Planner waiting. Then inspect network latency, model speed, context length, and unnecessary plugins. If new messages always wait for the previous turn to finish, enable quick reaction mode (`planner_message_steering`) so they join immediately. ## Why does a reply become a very short fallback phrase? diff --git a/en/faq/troubleshooting-runtime.md b/en/faq/troubleshooting-runtime.md index 1909a3d..bed666d 100644 --- a/en/faq/troubleshooting-runtime.md +++ b/en/faq/troubleshooting-runtime.md @@ -47,7 +47,7 @@ enabled = true # Make sure the rule is enabled # config/bot_config.toml [chat.reply_timing] talk_value = 1 # Group talk willingness (0-1); lower is quieter. Default 1 -private_talk_value = 1 # Private chat talk willingness (0-1). Default 1 +private_reply_paused = false # Private replies paused: make sure this is not true ``` ::: diff --git a/en/manual/configuration/bot-config.md b/en/manual/configuration/bot-config.md index 04006be..a8c8d6d 100644 --- a/en/manual/configuration/bot-config.md +++ b/en/manual/configuration/bot-config.md @@ -67,10 +67,10 @@ The three prompts each cover one thing: ```toml [bot_config.toml ~vscode-icons:file-type-toml~] [chat.reply_timing] -talk_value = 1.0 # Group talk frequency: lower is quieter; 0.3~0.5 is noticeably quieter -private_talk_value = 1.0 # Private talk frequency: same scale -inevitable_at_reply = true # Try to reply when @-mentioned -mentioned_bot_reply = false # Reply more easily when a message mentions Mai's name +talk_value = 1.0 # Group talk frequency: lower is quieter; 0.3~0.5 is notably quiet +private_reply_paused = false # Pause all private replies: true = private chats only receive and store messages +inevitable_at_reply = true # Try to reply when @-mentioned +mentioned_bot_reply = false # Reply more easily when a message mentions Mai's name ``` ::: @@ -205,15 +205,12 @@ multiple_probability = 0 # [Advanced] Chance to temporarily inject one alternat enable_reply_at = true # Let Mai @-mention people at the start of a reply; the model decides when max_context_size = 40 # How many recent messages a group reply considers; more context costs more tokens max_private_context_size = 60 # Recent messages considered for private replies -mid_term_memory = true # Chat recall: proactively recalls what happened in recent chat -mid_term_memory_lenth = 10 # How many recall entries to keep; 0 = keep none +context_compaction_summary_max_chars = 6000 # [Advanced] Max characters of the rolling state summary (1000~8000), generated by the utils model ``` ::: -::: tip The field name lenth is a historical typo -Keep the field name `mid_term_memory_lenth` exactly as written; changing its spelling produces an unknown field. -::: +When the context is nearly full, Mai compresses the older conversation into a rolling state summary with the utils model and always sends it with the Planner context; `context_compaction_summary_max_chars` controls the summary length. Chat recall and long-term memory are handled by A_Memorix, see [A_Memorix Configuration](./amemorix-config.md). #### When to Speak @@ -222,13 +219,12 @@ Keep the field name `mid_term_memory_lenth` exactly as written; changing its spe ```toml [bot_config.toml ~vscode-icons:file-type-toml~] [chat.reply_timing] message_debounce_mode = "natural" # Message debouncing: off / fast / natural / steady +planner_message_steering = false # Quick reaction mode: new messages during thinking/output/wait immediately join and restart reasoning talk_value = 1 # Group talk frequency: 0~1, lower is quieter -private_talk_value = 1 # Private talk frequency: same scale +private_reply_paused = false # Pause all private replies: true = private chats only receive and store messages, without thinking +private_reply_pause_rules = [] # Per-platform and per-user overrides of the global private pause mentioned_bot_reply = false # Reply more easily when a message mentions Mai's name inevitable_at_reply = true # Try to reply when @-mentioned -reply_trigger_mode = "frequency" # When new messages enter the Planner: "frequency" / "dynamic" -planner_interrupt_max_consecutive_count = 0 # [Advanced] How many times new messages may restart an in-progress thought; 0 = unlimited -max_consecutive_wait_count = 3 # Max consecutive wait calls by the Planner; afterwards the wait tool refuses to continue no_action_backoff_base_seconds = 15 # After consecutive no-reply decisions, how long to wait before the next check (seconds) no_action_backoff_cap_seconds = 300 # [Advanced] Upper bound of the backoff wait (seconds) no_action_backoff_start_count = 2 # [Advanced] Start slowing down after this many consecutive no-replies @@ -275,10 +271,20 @@ value = 1.0 A batch is the messages merged and sent to the Planner together. If the previous effective message is more than 30 seconds old (or there is no history), the chat is quiet; otherwise it is active. Continuation and sender changes compare only with the immediately previous message. A batch opened by a bare image waits at least 4 seconds, and stickers inside a batch cannot extend the wait. Each batch waits at most 8 seconds from the first message actually received, or at most 1 second after an @ mention or name mention. A mode change applies from the next effective message; choosing Off ends an in-progress fixed-rule wait. -**How thinking is triggered** — `reply_trigger_mode` decides when new messages enter the Planner: +**Pausing private replies** — with `private_reply_paused = true`, all private chats only receive messages and maintain history without entering thinking; `private_reply_pause_rules` overrides the global setting per platform and user, and can also be toggled per chat stream in the WebUI or set back to follow the global setting: + +::: code-group -- **`frequency` (default)** — decides whether to think based on the number of new messages, with `talk_value` / `talk_value_rules` controlling the rate -- **`dynamic`** — estimates the reply likelihood of each message batch, then uses a one-hour sliding window to pull the actual reply count back toward the target of "expected replies × frequency", keeping idle backoff. It **only applies to group chats; private chats have no gate**. Configure it with `talk_value`, `talk_value_rules`, `mentioned_bot_reply` / `inevitable_at_reply`, and `no_action_backoff_*` +```toml [bot_config.toml ~vscode-icons:file-type-toml~] +[[chat.reply_timing.private_reply_pause_rules]] +platform = "qq" +item_id = "123456" +paused = true # true = pause this private chat; false = keep replying here, overriding a global pause +``` + +::: + +**Quick reaction mode** — with `planner_message_steering` enabled, the Planner is forced to use streaming requests. A new message arriving during thinking, output, or a `wait` immediately interrupts the current round and starts another request; it no longer waits for a quiet window and does not limit consecutive interruptions. Interrupted thinking and output remain in history for review. #### How to Speak @@ -323,6 +329,26 @@ prompt = "Keep replies extra short in this group." ::: +#### Capabilities + +`[capabilities]` centralizes the thinking and tool-usage enhancements; everything is off by default: + +::: code-group + +```toml [bot_config.toml ~vscode-icons:file-type-toml~] +[capabilities] +planner_subagent = false # Sub-agent delegation: give the Planner the subagent tool +advanced_sub_agent = false # Advanced sub-agents: run in the background and return the conclusion as a new message (requires the previous option) +tool_result_condense = false # Condense long tool results into a conclusion before writing them to context +tool_result_condense_threshold = 3000 # [Advanced] Character count that triggers condensing; minimum 500 +``` + +::: + +**Sub-agents** — `planner_subagent = true` gives the Planner a `subagent` tool: a self-contained research or summarization task runs in its own context, may call authorized tools over multiple rounds, and returns only its conclusion. With `advanced_sub_agent = true`, sub-agents run in the background: dispatch returns a task ID immediately and Mai can keep chatting; when the sub-agent finishes, its conclusion returns as a new message that wakes the Planner. `subagent_status` lists tasks and `subagent_stop` terminates one. + +**Condensing long tool results** — with `tool_result_condense = true`, a tool result reaching `tool_result_condense_threshold` characters (default 3000, minimum 500) is first condensed by a sub-agent according to the Planner's current intent, then written to context. This reduces context usage in later rounds at the cost of one extra model request. + #### Experimental Features The whole section is advanced; everything is off by default — opt in per feature. @@ -331,20 +357,12 @@ The whole section is advanced; everything is off by default — opt in per featu ```toml [bot_config.toml ~vscode-icons:file-type-toml~] [experimental] -planner_message_steering = false # Quick reaction mode: new messages during thinking/output/wait immediately join and restart reasoning -planner_optimized_prompt = false # Optimized Planner prompt: describe Mai in the second person and trim task instructions -planner_stop_tool = false # Optimize tool usage: give the Planner a no-argument stop() tool -planner_subagent = false # Sub-agent delegation: give the Planner the subagent tool -advanced_sub_agent = false # Advanced sub-agents: run in the background and return the conclusion as a new message (requires the previous option) -tool_result_condense = false # Condense long tool results into a conclusion before writing them to context -tool_result_condense_threshold = 3000 # [Advanced] Character count that triggers condensing; minimum 500 -replyer_retro_prompt = false # Organize the Replyer prompt the legacy (0.12.x) way, with all instructions in a single template +passive_replyer = false # Passive reply: when the Planner outputs text without calling tools, the text guides one reply -focus_mode = false # Focus on a single chat stream at a time; good for livestreams -focus_on_private = false # Whether Focus also applies to private chats -focus_chat_whitelist = [] # Focus whitelist; empty = all chats matching the type switches may enter -focus_groups = [] # Focus sharing groups: same group shares Focus, different groups do not preempt -focus_cool_time = 120 # Seconds without progress before the focused chat can be woken by others +focus_mode = false # Focus: chats in the same group share one continuously thinking Planner +focus_on_private = false # Whether Focus also applies to private chats +focus_chat_whitelist = [] # Focus whitelist; empty = all chats matching the type switches may enter +focus_groups = [] # Focus sharing groups: same group shares the Planner and full context, different groups do not preempt [experimental.attention_drift] enabled = false # Attention drift: more easily drawn to new topics, memes, and contrast @@ -357,18 +375,12 @@ reaction_style = "lively" # "reserved" / "natural" / "lively" **Rich replies** — Replies can include images. @-mentions follow [`[chat].enable_reply_at`](#context-and-recall), and stickers follow [`[emoji].use_new_send_logic`](#emoji-stickers). -**Quick reaction mode** — with `planner_message_steering` enabled, the Planner is forced to use streaming requests. A new message arriving during thinking, output, or a `wait` immediately interrupts the current round and starts another request; it no longer waits for a quiet window and does not limit consecutive interruptions. Interrupted thinking and output remain in history for review. +**Passive reply** — with `passive_replyer = true`, when the Planner outputs text without calling a tool, that text guides a reply; attachments and plugin parameters are set in advance through `set_reply_options`. When off, the original `reply` tool is used. Toggles take effect from the next round of thinking; Focus is unaffected. -**Sub-agents** — `planner_subagent = true` gives the Planner a `subagent` tool: a self-contained research or summarization task runs in its own context, may call authorized tools over multiple rounds, and returns only its conclusion. With `advanced_sub_agent = true`, sub-agents run in the background: dispatch returns a task ID immediately and Mai can keep chatting; when the sub-agent finishes, its conclusion returns as a new message that wakes the Planner. `subagent_status` lists tasks and `subagent_stop` terminates one. - -**Condensing long tool results** — with `tool_result_condense = true`, a tool result reaching `tool_result_condense_threshold` characters (default 3000, minimum 500) is first condensed by a sub-agent according to the Planner's current intent, then written to context. This reduces context usage in later rounds at the cost of one extra model request. - -**Optimized prompt and tools** — `planner_optimized_prompt = true` describes Mai in the second person and trims task instructions; `planner_stop_tool = true` provides a no-argument `stop()` tool that ends the current round and waits for new messages. +**Focus** — `focus_mode = true` lets chats in the same group share one continuously thinking Planner: all messages enter a shared context, tools address a target through `session_id`, sessions collaborate, waits are unified, and an @ mention wakes the thinking early. `focus_groups` splits chats into sharing groups that do not preempt each other; unmatched chats each form their own group. `focus_chat_whitelist` limits which chats enter Focus; empty means all chats matching the type switches may enter. **Learning rules are not in this section** — expression and jargon learning scopes are configured in `[expression].learning_list` / `[jargon].learning_list`; see [Learning Systems](#learning-systems). The old `[experimental]` learning fields have been removed. -**Retro reply prompt** — with `replyer_retro_prompt = true`, the Replyer prompt is organized the legacy (0.12.x) way: all reply instructions live in a single complete template sent as one `user` message, and the dialogue history is rendered as plain text into template placeholders instead of being sent as image Items. Group chat, "short reply", private chat, and "private chat replying to Mai herself" each use their own template (`retro_replyer`, `retro_replyer_light`, `retro_private_replyer`, `retro_private_replyer_self`); they appear under **Prompt Management** collapsed as "advanced" and can be edited or given custom versions. Changes hot-reload. - #### Message Receiving ::: code-group @@ -416,7 +428,7 @@ Mai learns ways of speaking from chat and reuses them in later replies: [expression] expression_checked_only = false # Only use manually curated expressions; when off, uncurated ones are used too expression_self_reflect = true # Let an AI review entries before writing, less weird content -use_vector_expression = true # Use vector expressions: intent + embedding recall, better quality (needs an embedding model); off = quick pick +use_vector_expression = false # Expression selection: false = fast (default) / true = fine (needs an embedding model) expression_vector_index_path = "data/expression_selection/expression_vector_index.json" # [Advanced] expression_vector_candidate_pool_size = 50 # [Advanced] Candidates handed to the LLM after vector recall, hard cap 50 max_expression_learner = 3 # [Advanced] Learning tasks running at the same time @@ -428,7 +440,7 @@ expression_groups = [] # Multiple chats share learned expressions **Key points:** -- **`use_vector_expression`** — on by default; it switches to expression intent plus embedding-model recall, which selects noticeably better. When off it falls back to quick-picked candidates. +- **`use_vector_expression`** — expression selection has two modes: `false` fast (default), which injects a weighted random pick directly without an extra model call; `true` fine, which uses expression intent and embedding recall followed by LLM filtering, and needs an embedding model. The retro reply mode does not use expression selection. - **`expression_checked_only`** — defaults to `false`, so expressions you have not curated are used as well; set it to `true` if Mai should only use expressions you have reviewed - **`learning_list`** — each rule covers one scope: `use` controls whether learned content is used, `learn` whether learning continues, and `type` accepts `"group"`/`"private"`. There are three ways to write the scope, and the most specific one wins: - **A specific chat** — fill in `item_id` (group number or user ID); `platform` is optional @@ -463,6 +475,7 @@ Controls how image messages enter the planner and replyer. **Whether images are ```toml [bot_config.toml ~vscode-icons:file-type-toml~] [visual] +image_quality = "normal" # Image quality: "normal" (longest edge 512) / "high" (longest edge 1024) max_image_num = 64 # [Advanced] Max images per multimodal request wait_image_recognize_max_time = 32 # Longest wait for image recognition, seconds; 0 = no wait handle_oversized_images = true # Automatically compress or drop oversized images @@ -478,6 +491,8 @@ no_file_result_retention_days = 30 # Days the recognition result outlives the d ::: +**Image quality** — `image_quality` controls the quality of ordinary chat images sent to the planner and replyer: Normal keeps a longest edge of 512 pixels, High 1024 pixels with more detail and higher usage. Images are scaled proportionally, never upscaled, and original images and stickers are untouched. + #### Emoji Stickers ::: code-group @@ -643,6 +658,29 @@ enable = true # Whether to enable MCP tool integration After you save a change to `[mcp]`, MaiBot rebuilds the MCP connections with the new configuration — no restart needed, and the result is logged exactly as it is at startup. A few fields outside the reload signature (such as the whole `elicitation` section and `sampling.include_context_support`) still require a restart; see [MCP Configuration](./mcp-config.md). ::: +#### Agent Connection + +`[agent]` starts an external Agent (experimental) that runs in parallel with normal chat and connects over ACP to dsh, dsh Desktop, or any other ACP program; models and credentials come from the external Agent's own configuration. With `computer_tools` enabled, the Agent can also operate a sandboxed desktop: chats support image-text relay, tasks survive restarts, and the WebUI offers the desktop view, run history, and manual takeover. + +::: code-group + +```toml [bot_config.toml ~vscode-icons:file-type-toml~] +[agent] +enabled = false # Enable the external Agent interface +connection = "dsh" # "dsh" dsh CLI / "dsh_desktop" dsh Desktop / "custom" custom ACP +acp_command = "dsh" # Executable of the external Agent; on Windows use dsh.cmd +acp_cwd = "" # Host working directory of the external process; empty = data/agent/workspace +computer_tools = false # Provide sandboxed desktop tools and the WebUI takeover view +networking = true # Allow sandbox networking; applies on the next sandbox start +desktop_manifest = "" # [Advanced] dsh Desktop bridge file; empty = ~/.dsh/maibot-desktop.json +``` + +::: + +- **dsh CLI / dsh Desktop** — dsh CLI starts automatically with `--profile acp`; dsh Desktop connects to the running desktop app and requires the dsh-maibot-bridge plugin installed in Desktop first. The same session appears on both sides +- **Custom ACP** — with `connection = "custom"`, pass arguments item by item via `acp_args`, extend the environment with `acp_env`, and pick a model option with `acp_model`; `acp_timeout` bounds handshake and shutdown waits +- **Sandboxed desktop** — `computer_tools = true` provides the sandbox desktop tools and WebUI takeover view; Agent input is not executed while a human is taking over. Advanced sandbox settings (memory, startup timeout, screenshot edge) are available in the WebUI + #### Plugin Management ::: code-group @@ -712,7 +750,10 @@ log_cleanup_days = 30 # Days before main logs are cleaned up llm_request_snapshot_limit = 128 # Max failed-request snapshots kept maisaka_prompt_preview_limit = 256 # Max prompt preview groups kept per chat -maisaka_reply_effect_limit = 256 # Max reply-effect records kept per chat + +memory_diagnostics_enabled = true # [Advanced] Standalone memory diagnostics log; at most four 5 MiB files, restart to apply +memory_diagnostics_deep_enabled = false # [Advanced] tracemalloc allocation-site comparison (every ten minutes); extra overhead, restart to apply +memory_diagnostics_interval_seconds = 60.0 # [Advanced] Lightweight memory diagnostics interval (seconds, min 10), restart to apply event_loop_watchdog_enabled = false # [Advanced] Record event-loop stalls, for diagnosing UI/main-loop freezes event_loop_watchdog_warn_seconds = 0.5 # [Advanced] Log a warning once the event loop wake-up delay exceeds this many seconds @@ -733,7 +774,8 @@ library_log_levels = { aiohttp = "WARNING", PIL = "WARNING" } # [Advanced] Lowe [debug] enable_console_input = true # Enable local message and command input in an interactive terminal (on by default) show_maisaka_thinking = true # Show Mai's thinking process in logs or the UI -enable_reply_effect_tracking = false # Record reply-effect scores to observe quality +save_maisaka_reasoning = true # Save full reasoning records of the Planner, tool calls, and chat recall for the WebUI +replyer_retro_prompt = false # Organize the Replyer prompt the legacy (0.12.x) way, with all instructions in a single template force_plugin_compatibility = false # Skip the plugin-declared Host/SDK version check and load directly; takes effect after a restart keep_prompt_preview_json_base64 = false # [Advanced] Keep image base64 in prompt previews; reproducible but large record_tool_structured_content = false # [Advanced] Save structured tool results; grows the database @@ -747,6 +789,7 @@ enable_llm_cache_stats = false # [Advanced] Record prompt-cache statis - **Terminal input** — `enable_console_input` is on by default: in an interactive terminal you can type ordinary messages or manage chats and adapters with `/clear`, `/pm`, `/offline`, `/online`, `/help`, and type `exit()` to close it. A non-interactive terminal (systemd, nohup, `docker run` without `-it`) only logs one extra warning and is otherwise unaffected; changing this requires a restart - **Force plugin compatibility** — `force_plugin_compatibility = true` skips the Host/SDK version-range checks declared by a plugin manifest and loads it anyway; it is **only a temporary fallback** and may load plugins that are in fact incompatible. It logs a single warning and does not affect the plugin market's version compatibility filtering. Requires a restart - **The `/clear` command** — `/clear` is a built-in command available by default; to disable it, use `[plugin].disabled_commands = ["core.clear"]` +- **Retro reply prompt** — with `replyer_retro_prompt = true`, the Replyer prompt is organized the legacy (0.12.x) way: all reply instructions live in a single complete template sent as one `user` message, and the dialogue history is rendered as plain text into template placeholders instead of being sent as image Items. Group chat, "short reply", private chat, and "private chat replying to Mai herself" each use their own template (`retro_replyer`, `retro_replyer_light`, `retro_private_replyer`, `retro_private_replyer_self`); they appear under **Prompt Management** collapsed as "advanced" and can be edited or given custom versions. Changes hot-reload #### Telemetry @@ -811,7 +854,7 @@ Then watch the log or the WebUI: once the file is saved, a successful config-rel **Mai floods the chat** — lower `talk_value` (e.g. 0.3); cap messages per reply with `response_splitter.max_sentence_num` and `max_split_num`; note that `emoji_send_num` is only the candidate pool size — lowering it does not reduce talk frequency. -**Manually added fields disappear** — the config file is upgraded by the program, and unknown or misspelled fields (e.g. `mid_term_memory_lenth` renamed to `length`) are cleaned back to defaults on the next start. Launch once to let the program generate/upgrade the file, then edit the generated fields. +**Manually added fields disappear** — the config file is upgraded by the program, and unknown or misspelled fields (e.g. `max_context_size` misspelled as `max_context_len`) are cleaned back to defaults on the next start. Launch once to let the program generate/upgrade the file, then edit the generated fields. **Personality change feels ineffective** — personality only affects newly generated replies; messages already sent stay unchanged. After confirming the reload message in the log, observe a few more rounds; for occasional style swings try `multiple_reply_style` + `multiple_probability`. diff --git a/en/manual/configuration/index.md b/en/manual/configuration/index.md index 9e5aadf..538619f 100644 --- a/en/manual/configuration/index.md +++ b/en/manual/configuration/index.md @@ -29,7 +29,7 @@ Beyond the two main files, these topics have their own pages: MaiBot watches both files for changes. Whether a restart is required depends on whether the setting controls runtime behavior or how a service starts. -**Applies automatically after saving** — Bot profile, personality, chat policy, reply frequency, model providers, models, task assignments, the `[experimental]` retro reply prompt (`replyer_retro_prompt`), and `[response_splitter].mode` are hot-reloaded. Model changes apply to subsequent requests. Modules with reload callbacks, including A_Memorix and emoji maintenance, also receive the update. +**Applies automatically after saving** — Bot profile, personality, chat policy, reply frequency, model providers, models, task assignments, the `[debug]` retro reply prompt (`replyer_retro_prompt`), and `[response_splitter].mode` are hot-reloaded. Model changes apply to subsequent requests. Modules with reload callbacks, including A_Memorix and emoji maintenance, also receive the update. **Hot-reloaded by the plugin runtime** — A plugin's own `config.toml` has a separate lifecycle. The runtime watches it and calls the plugin configuration-update hook. Enabling, disabling, installing, uninstalling, and source updates normally do not require restarting all of MaiBot. diff --git a/en/manual/configuration/model-config.md b/en/manual/configuration/model-config.md index e8c63ab..0229cc2 100644 --- a/en/manual/configuration/model-config.md +++ b/en/manual/configuration/model-config.md @@ -136,7 +136,7 @@ Give the Planner web search and page-reading tools. Web services are defined sep preview_chars = 4000 # Preview characters returned per call; read the full result with read_tool_result [web.services.deepseek] -adapter = "deepseek" # Protocol: deepseek / tavily / stepsearch_mcp +adapter = "deepseek" # Protocol: deepseek / tavily / stepsearch_mcp / anysearch / exa / firecrawl api_key = "sk-..." # DeepSeek API key # base_url = "https://api.deepseek.com" # Empty uses the official URL; an OpenAI-compatible /v1 URL also works timeout = 60 # Total time limit per call (seconds) @@ -174,12 +174,55 @@ timeout = 60 model_list = ["stepsearch"] ``` +```toml [AnySearch ~vscode-icons:file-type-toml~] +[web] +preview_chars = 4000 + +[web.services.anysearch] +adapter = "anysearch" +api_key = "..." # AnySearch API key +# base_url = "https://api.anysearch.com" # Empty uses the official URL +timeout = 60 + +[model_task_config.web_search] +model_list = ["anysearch"] +``` + +```toml [Exa ~vscode-icons:file-type-toml~] +[web] +preview_chars = 4000 + +[web.services.exa] +adapter = "exa" +api_key = "..." # Exa API key +# base_url = "https://api.exa.ai" # Empty uses the official URL +timeout = 60 + +[model_task_config.web_search] +model_list = ["exa"] +``` + +```toml [Firecrawl ~vscode-icons:file-type-toml~] +[web] +preview_chars = 4000 + +[web.services.firecrawl] +adapter = "firecrawl" +api_key = "fc-..." # Firecrawl API key +# base_url = "https://api.firecrawl.dev" # Empty uses the official URL +timeout = 60 + +[model_task_config.web_search] +model_list = ["firecrawl"] +``` + ::: **Key points:** - **Enabling** — the `web_search` / `web_fetch` tools are registered only when `model_task_config.web_search.model_list` selects a service; leaving it empty disables web tools entirely - **One service** — `model_list` accepts a single service. To switch services, change this value; other definitions can stay +- **AnySearch / Exa / Firecrawl** — all three need only an `api_key`; leave `base_url` empty for the official URL, or point it at a proxy or self-hosted service - **StepSearch MCP** — the endpoint and credentials live in `[mcp.servers]` in `bot_config.toml`; `web.services` only needs `server_ref` and must not set `api_key` or `base_url` - **Long pages** — only `preview_chars` characters are handed to the model per call; the full result is available through `read_tool_result`, which is also used by long-tool-result condensing - **Search arguments** — `web_search` accepts only `query` and `max_results` (1–20, default 5); `web_fetch` accepts only `url` diff --git a/en/plugin/api-reference.md b/en/plugin/api-reference.md index 30acb76..9462f1f 100644 --- a/en/plugin/api-reference.md +++ b/en/plugin/api-reference.md @@ -774,7 +774,7 @@ image_path = Path(claimed["path"]) ::: -Tokens must belong to the claiming plugin, expire after one hour, and can be claimed only once. They originate from authenticated WebUI uploads; arbitrary paths are not substitutes. File contents do not travel through ordinary JSON/RPC. See [WebUI Pages](./webui-pages.md#upload-and-interaction-capabilities) for declarations and format/size limits. +Tokens must belong to the claiming plugin, expire after one hour, and can be claimed only once. They originate from authenticated WebUI uploads; arbitrary paths are not substitutes. File contents do not travel through ordinary JSON/RPC. See [WebUI Pages](./webui-pages.md#image-uploads) for declarations and format/size limits. ## paths — Runtime Paths diff --git a/en/plugin/webui-pages.md b/en/plugin/webui-pages.md index cc29f50..350d809 100644 --- a/en/plugin/webui-pages.md +++ b/en/plugin/webui-pages.md @@ -2,6 +2,8 @@ title: WebUI Pages --- +# WebUI Pages + Add `webui.json` to your plugin directory to expose data and actions in the WebUI. Use predefined components for simple pages and write HTML/CSS/JS for complex interfaces. Both modes call static `@API` methods owned by the plugin. This page describes the in-development `schema_version: 2` protocol and requires matching host and dashboard builds. Updating the Python SDK alone does not update the page protocol. A plugin can mix both modes: diff --git a/scripts/docs-quality.mjs b/scripts/docs-quality.mjs index 773e9e9..c94f050 100644 --- a/scripts/docs-quality.mjs +++ b/scripts/docs-quality.mjs @@ -86,11 +86,18 @@ function scan(p) { return out } +/** 与 VitePress 渲染行为一致:标题带 {#id} 时真实 id 就是该 id,否则为标题文本的 slug */ +const headingId = (raw) => { + const text = raw.replace(/\r$/, '').replace(/`/g, '').trim() + const custom = text.match(/\{#([\w-]+)\}$/) + return custom ? custom[1] : slugify(text) +} + const idsOf = (p) => { const set = new Set() for (const l of lines(p)) { - const m = l.match(/^#{1,6}\s+(.*)$/) - if (m) set.add(slugify(m[1].replace(/`/g, '').trim())) + const m = l.replace(/\r$/, '').match(/^#{1,6}\s+(.*)$/) + if (m) set.add(headingId(m[1])) } return set } @@ -442,9 +449,9 @@ if (haveMaiBot) { for (const p of [...zh, ...en]) { const seen = new Map() for (const l of lines(p)) { - const m = l.match(/^#{1,6}\s+(.*)$/) + const m = l.replace(/\r$/, '').match(/^#{1,6}\s+(.*)$/) if (!m) continue - const s = slugify(m[1].replace(/`/g, '').trim()) + const s = headingId(m[1]) seen.set(s, (seen.get(s) || 0) + 1) } const dup = [...seen.entries()].filter(([, n]) => n > 1) diff --git a/zh/changelog/index.md b/zh/changelog/index.md index 3a1e34c..5985f2f 100644 --- a/zh/changelog/index.md +++ b/zh/changelog/index.md @@ -5,6 +5,67 @@ description: MaiBot 各版本的功能更新、修复与配置变更记录。 # 更新日志 +::: timeline 2026-10-23 +### 主程序 [1.3.15] +* 上下文压缩改为滚动状态摘要:由 utils 模型生成并始终随 Planner 上下文发送,摘要长度由 `context_compaction_summary_max_chars` 控制。 +* 联网搜索新增 AnySearch、Exa、Firecrawl 三种服务。 +* 插件管理新增 `/pm cmd [插件ID或唯一短名称] [pic]`:按插件查看已注册指令,可渲染成图片。 +* 私聊支持暂停回复:可全局设置,也可按平台与用户单独设置,取代原有的私聊频率设置。 +* 表达选择分「快速 / 精细」两档:默认快速,加权随机抽取直接注入;精细档用表达意图与嵌入召回,再由 LLM 筛选,需配置嵌入模型。 +* 图片画质可选「普通 / 超清」两档,发给规划和回复模型时分别按最长边 512 / 1024 像素压缩。 +* 修复旧机器人账号消息无法触发回复、引用错误导致发送失败、复古回复模式误开启的问题。 +* 普通与 Focus 模式连续等待后不再强制结束对话,改为提醒麦麦延长等待或主动结束。 + +### WebUI [1.9.9] +* 学习:表达与黑话支持手动添加和长文自动学习,可编辑、勾选结果并导入指定聊天或全局;支持查看进度、失败重试和分批导入。 +* 学习:表达与黑话列表支持按活跃时间、创建时间排序,并显示群号或私聊用户号。 +* 插件商店使用 CNB 镜像下载时,插件图标也从镜像加载。 +* 提示词模板需要更新或修正时,在入口和对应模板处显示提醒。 +* Agent 会话合并连续的思考与回复内容,修复空格和换行丢失的问题。 +* 优化切页动画,修复首页统计数字裁切、排版错位及语言菜单样式不一致的问题。 +::: + +::: timeline 2026-10-22 +### 主程序 [1.3.14] +* 快速反应模式成为正式功能,并优化回复频率与等待时机,让麦麦的回应更及时、自然。 +* 优化默认设定和提示词。 + +### WebUI [1.9.8] +* 初次引导支持从独立的人设预设列表填入人格、行为风格与回复风格。 +::: + +::: timeline 2026-10-21 +### 主程序 [1.3.13] +* Agent 连接(实验性):通过 ACP 连接 dsh 和 dsh Desktop,模型与凭据使用外部 Agent 自身配置。 +* 插件可生成符合麦麦人格的长文,并按指定主帖、评论或楼中楼回复文字与表情包。 +* 插件安装下载失败时提示更清楚的原因,可直接调整下载源或重试。 +* 新增内存诊断记录,帮助排查长期运行时的内存增长。 +* 降低大量历史图片带来的内存占用;修复复古回复模式处理图片时可能回复失败的问题。 + +### WebUI [1.9.7] +* 顶栏有新版本时直接显示更新提醒。 +* 修复聊天页滚动区域可能导致页面报错的问题。 +::: + +::: timeline 2026-10-19 +### 主程序 [1.3.12] +* 新增可自主操作电脑的独立智能体:支持聊天中的图文传话、重启后继续任务,WebUI 可查看桌面、运行记录并接管操作。 +* Focus 同组聊天共享持续思考,支持跨会话协作、统一等待,被 @ 时提前唤醒。 +* 优化思考与工具使用体验;子代理任务与超长工具结果整理集中到 `[capabilities]` 能力段配置。 +* 表达与黑话学习可累计多批聊天素材,消息较少时也能逐步满足学习条件。 +* 统一插件市场的浏览与使用体验,优化安装、更新和启用流程;禁用插件不再拖慢启动,安装失败不再损坏已有依赖。 +* 执行 `/offline` 后停止相关聊天活动,避免离线后继续思考或唤醒。 +* 移除回复效果评估功能。 + +### WebUI [1.9.6] +* 模型配置新增「麦麦特调回复」模板,自动补齐所需模型与回复设置,支持直接测试回复。 +* 设置新增「通用」栏目,统一桌面端与手机端的语言设置入口。 +* 学习页整合表达方式、黑话和表情包,清楚显示学习进度与未完成原因。 +* 推理重放修复图片消息无法正常预览的问题。 +* 移动端优化底栏切换动画,支持随全局设置关闭动画。 +* 聊天观察收起轮次后也能查看工具执行状态;详细统计支持按不同维度查看花费与 Token 分布。 +::: + ::: timeline 2026-10-19 ### 主程序 [1.3.11] * 消息防抖改为四档固定规则:关闭、快速、自然、沉稳,默认自然。安静与活跃场景、同一人续发与换人分别使用不同等待时间,整批最多等 8 秒,被 @ 或提及后最多 1 秒。 diff --git a/zh/faq/chat-and-reply.md b/zh/faq/chat-and-reply.md index 91307a2..3a61f44 100644 --- a/zh/faq/chat-and-reply.md +++ b/zh/faq/chat-and-reply.md @@ -4,38 +4,35 @@ title: 聊天与回复 # 聊天与回复 -## 频率触发和动态触发有什么区别? +## 麦麦怎么决定要不要回复? -`[chat.reply_timing].reply_trigger_mode` 决定新消息什么时候进入 Planner: +新消息先经过防抖合并,再由 Planner 决定是否回应。回复倾向主要由 `talk_value` 与 `talk_value_rules` 的频率设置调节:被 @ 时会尽量回复,消息提到名字时更容易回复;连续多次不回应后,检查节奏会按 `no_action_backoff_*` 自动放慢。 -- **`frequency`(频率触发,默认)** — 按新消息数量决定是否思考,行为简单、可预期 -- **`dynamic`(动态触发)** — 估算每批消息的回复可能性,再用 1 小时滑动窗口把实际回复次数拉回设定目标。**只对群聊生效,私聊不受该门控影响** - -切换模式后建议观察一段时间,再决定是否微调 `talk_value`。 +调整频率后建议观察一段时间,再决定是否继续微调。 ## 麦麦话太多或话太少怎么办? -先调整群聊或私聊发言频率,再检查是否启用了动态发言频率规则。动态规则启用后,实际频率可能由匹配到的规则覆盖。人格和群聊提示词也会影响 Planner 对“是否应该说话”的判断。 +先调整群聊或私聊发言频率,再检查是否启用了按聊天/时段的频率规则(`talk_value_rules`)。规则启用后,实际频率可能由匹配到的规则覆盖。人格和群聊提示词也会影响 Planner 对“是否应该说话”的判断。 建议小幅调整并观察一段时间,不要把某个数值当作所有群聊都适用的固定答案。 ## 机器人为什么会回复自己的消息? -先确认适配器是否把机器人发出的消息再次作为入站消息送回 MaiBot,并检查适配器中配置的机器人 QQ 号是否正确。随后检查插件冲突、消息过滤和动态发言规则。 +先确认适配器是否把机器人发出的消息再次作为入站消息送回 MaiBot,并检查适配器中配置的机器人 QQ 号是否正确。随后检查插件冲突、消息过滤和频率规则。 如果消息链路正常但 Planner 仍反复选择回复,可以再尝试调整发言频率或更换 Planner 模型。不能仅凭现象断定是模型质量问题。 ## 连续发送多条消息时,为什么只处理了前一条? -MaiBot 收到新消息时,Planner 是否重新思考受触发模式和连续打断上限影响。处理速度还受模型延迟、工具调用和上下文长度影响。 +先看消息是否被防抖合并成一批处理;模型延迟、工具调用和上下文长度也会拖慢单轮处理。 -可以检查 `planner_interrupt_max_consecutive_count`,但不应盲目套用固定推荐值。值越宽松,机器人越容易及时响应新消息,也可能增加模型调用和上下文消耗。 +希望思考、输出或等待期间收到的新消息立即接入并重新推理,可开启快速反应模式(`[chat.reply_timing].planner_message_steering`)。 ## 回复很慢怎么办? 先从日志区分等待发生在模型请求、工具调用、图片识别、适配器发送还是 Planner 等待动作。随后检查网络延迟、模型响应速度、上下文长度和不必要的插件。 -如果机器人必须等上一轮结束才处理新消息,同时检查连续消息打断配置。 +如果机器人必须等上一轮结束才处理新消息,可开启快速反应模式(`planner_message_steering`)让新消息立即接入。 ## 为什么回复变成“懒得说”“不知道”等很短的文本? diff --git a/zh/faq/troubleshooting-runtime.md b/zh/faq/troubleshooting-runtime.md index d965343..254249e 100644 --- a/zh/faq/troubleshooting-runtime.md +++ b/zh/faq/troubleshooting-runtime.md @@ -47,7 +47,7 @@ enabled = true # 确保规则启用 # config/bot_config.toml [chat.reply_timing] talk_value = 1 # 群聊发言意愿(0-1),越小越安静;默认 1 -private_talk_value = 1 # 私聊发言意愿(0-1),默认 1 +private_reply_paused = false # 私聊暂停回复:确认不是 true ``` ::: diff --git a/zh/manual/configuration/bot-config.md b/zh/manual/configuration/bot-config.md index 0c57043..8f6a875 100644 --- a/zh/manual/configuration/bot-config.md +++ b/zh/manual/configuration/bot-config.md @@ -67,10 +67,10 @@ multiple_probability = 0 # 按概率随机换成上面的备用风格;0 = 不 ```toml [bot_config.toml ~vscode-icons:file-type-toml~] [chat.reply_timing] -talk_value = 1.0 # 群聊发言频率:越小越安静,0.3~0.5 明显话少 -private_talk_value = 1.0 # 私聊发言频率:同上 -inevitable_at_reply = true # 被 @ 时尽量回复 -mentioned_bot_reply = false # 消息提到麦麦名字时是否更容易回复 +talk_value = 1.0 # 群聊发言频率:越小越安静,0.3~0.5 明显话少 +private_reply_paused = false # 暂停所有私聊回复:true = 私聊只收消息不回复 +inevitable_at_reply = true # 被 @ 时尽量回复 +mentioned_bot_reply = false # 消息提到麦麦名字时是否更容易回复 ``` ::: @@ -205,15 +205,12 @@ multiple_probability = 0 # [进阶] 每次回复按此概率临时注入一条 enable_reply_at = true # 允许麦麦在回复开头 @ 人;要不要 @ 由模型看聊天内容决定 max_context_size = 40 # 群聊回复参考最近多少条消息;越大越懂上下文,也更耗 token max_private_context_size = 60 # 私聊参考的最近消息数量 -mid_term_memory = true # 聊天回想:主动召回最近聊天发生的事情 -mid_term_memory_lenth = 10 # 最多保留多少条聊天回想;0 = 不保留 +context_compaction_summary_max_chars = 6000 # [进阶] 滚动状态摘要的最大字符数(1000~8000),由 utils 模型生成 ``` ::: -::: tip 字段名 lenth 是历史拼写 -字段名为 `mid_term_memory_lenth`,请保留这个拼写;修改后会被视为未知字段。 -::: +上下文快满时,麦麦会用 utils 模型把更早的对话压成一段滚动状态摘要,始终随 Planner 上下文发送;`context_compaction_summary_max_chars` 控制摘要长度。聊天回想与长期记忆由 A_Memorix 负责,见 [A_Memorix 配置](./amemorix-config.md)。 #### 什么时候发言 @@ -222,13 +219,12 @@ mid_term_memory_lenth = 10 # 最多保留多少条聊天回想;0 = 不 ```toml [bot_config.toml ~vscode-icons:file-type-toml~] [chat.reply_timing] message_debounce_mode = "natural" # 消息防抖:off 关闭 / fast 快速 / natural 自然 / steady 沉稳 +planner_message_steering = false # 快速反应模式:思考/输出/等待期间收到新消息立即接入并重新推理 talk_value = 1 # 群聊发言频率:0~1,越小越安静 -private_talk_value = 1 # 私聊发言频率:同上 +private_reply_paused = false # 暂停所有私聊回复:true = 私聊只收消息并维护历史,不进入思考 +private_reply_pause_rules = [] # 按平台与用户单独覆盖全局私聊暂停设置 mentioned_bot_reply = false # 消息提到麦麦名字时更容易回复 inevitable_at_reply = true # 被 @ 时尽量回复 -reply_trigger_mode = "frequency" # 新消息何时进入 Planner:"frequency" 频率触发 / "dynamic" 动态触发 -planner_interrupt_max_consecutive_count = 0 # [进阶] 思考时来了新消息最多重新思考几次;0 = 不限制 -max_consecutive_wait_count = 3 # Planner 最多连续调用 wait 几次,达到后拒绝继续等待 no_action_backoff_base_seconds = 15 # 连续决定不回复后,下次检查前先等多久(秒) no_action_backoff_cap_seconds = 300 # [进阶] 退避等待的上限(秒) no_action_backoff_start_count = 2 # [进阶] 连续几次不回复后开始放慢检查 @@ -275,10 +271,20 @@ value = 1.0 一批指合并后一起送入判断的消息。上一条有效消息距今超过 30 秒(或没有历史)算安静,否则算活跃;续发与换人只和紧邻的上一条消息比较。裸图开启的新批次至少等 4 秒,批次内纯表情包不能延长等待;整批从第一条实际收到起最多等 8 秒,被 @ 或提及后最多等 1 秒。换档位从下一条有效消息起生效,选择关闭会结束正在进行的固定规则等待。 -**怎么触发思考** — `reply_trigger_mode` 决定新消息何时进入 Planner: +**私聊暂停** — `private_reply_paused = true` 后所有私聊只接收消息并维护历史,不进入思考;`private_reply_pause_rules` 按平台和用户单独覆盖全局设置,也可以在 WebUI 的聊天流设置中切换或恢复跟随全局: + +::: code-group -- **`frequency`(频率触发,默认)** — 按新消息数量决定是否思考,配合 `talk_value` / `talk_value_rules` 控制频率 -- **`dynamic`(动态触发)** — 估计每批消息的回复可能性,再用 1 小时滑动窗口把实际回复次数拉回"预计回复数 × 频率"的目标,并保留空闲退避。**只在群聊生效,私聊不设门控**;通过 `talk_value`、`talk_value_rules`、`mentioned_bot_reply` / `inevitable_at_reply` 与 `no_action_backoff_*` 调节 +```toml [bot_config.toml ~vscode-icons:file-type-toml~] +[[chat.reply_timing.private_reply_pause_rules]] +platform = "qq" +item_id = "123456" +paused = true # true = 暂停这个私聊;false = 该私聊保持回复,覆盖全局暂停 +``` + +::: + +**快速反应模式** — 开启 `planner_message_steering` 后,Planner 强制使用流式请求;思考、输出或 `wait` 等待期间收到新消息会立即中断当前轮并重新请求,不再等静默窗口,也不限制连续打断次数。被打断的思考与输出会保留在历史里,方便回看。 #### 如何发言 @@ -323,6 +329,26 @@ prompt = "这个群里说话要更简短。" ::: +#### 能力 + +`[capabilities]` 集中提供思考与工具使用的增强设置,默认全部关闭: + +::: code-group + +```toml [bot_config.toml ~vscode-icons:file-type-toml~] +[capabilities] +planner_subagent = false # 子代理任务派发:给 Planner 提供 subagent 工具 +advanced_sub_agent = false # 高级子代理:子代理后台运行,结论作为新消息送回(需先开启上一项) +tool_result_condense = false # 超长工具结果整理:超过阈值的工具结果先整理成结论再写入上下文 +tool_result_condense_threshold = 3000 # [进阶] 触发整理的字符数,最低 500 +``` + +::: + +**子代理** — `planner_subagent = true` 给 Planner 提供 `subagent` 工具:把自包含的查询或整理任务交给子代理,子代理在独立上下文里多轮调用被授权的工具,只把结论交还。开启 `advanced_sub_agent = true` 后子代理转到后台,派发后立刻返回任务 ID,麦麦可以继续聊天;子代理结束时结论作为一条新消息送回并唤醒 Planner,同时提供 `subagent_status`(查看任务)和 `subagent_stop`(终止任务)。 + +**超长工具结果整理** — `tool_result_condense = true` 时,工具结果达到 `tool_result_condense_threshold` 字符(默认 3000,最低 500)会先交给子代理按 Planner 当前意图整理成结论,再写入上下文,减少后续每轮的上下文占用;代价是多一次模型请求。 + #### 实验性功能 整段属于进阶设置,默认全部关闭,想尝鲜再逐项打开。 @@ -331,20 +357,12 @@ prompt = "这个群里说话要更简短。" ```toml [bot_config.toml ~vscode-icons:file-type-toml~] [experimental] -planner_message_steering = false # 快速反应模式:思考/输出/等待期间收到新消息立即接入并重新推理 -planner_optimized_prompt = false # 优化 Planner 提示词:用第二人称描述麦麦自己,并精简任务说明 -planner_stop_tool = false # 优化工具使用:给 Planner 提供无参数的 stop() 工具 -planner_subagent = false # 子代理任务派发:给 Planner 提供 subagent 工具 -advanced_sub_agent = false # 高级子代理:子代理后台运行,结论作为新消息送回(需先开启上一项) -tool_result_condense = false # 超长工具结果整理:超过阈值的工具结果先整理成结论再写入上下文 -tool_result_condense_threshold = 3000 # [进阶] 触发整理的字符数,最低 500 -replyer_retro_prompt = false # 按旧版(0.12.x)方式组织 Replyer 提示词,全部指令集中在一份模板里 +passive_replyer = false # 被动回复:Planner 不调用工具而输出正文时,将正文作为指导启动一次回复 -focus_mode = false # 同一时间只专注一个聊天流,适合直播/高强度场景 -focus_on_private = false # Focus 是否也作用于私聊 -focus_chat_whitelist = [] # Focus 白名单;留空 = 所有符合开关的聊天都可进入 -focus_groups = [] # Focus 共享组:同组共享 Focus,不同组互不抢占 -focus_cool_time = 120 # 当前聊天多久没继续后允许被其他聊天唤醒(秒) +focus_mode = false # Focus:同组聊天共享一个持续思考的 Planner +focus_on_private = false # Focus 是否也作用于私聊 +focus_chat_whitelist = [] # Focus 白名单;留空 = 所有符合开关的聊天都可进入 +focus_groups = [] # Focus 共享组:同组共享 Planner 与完整上下文,不同组互不抢占 [experimental.attention_drift] enabled = false # 注意力漂移:更容易被新话题、梗、反差点吸引 @@ -357,18 +375,12 @@ reaction_style = "lively" # 短反应风格:"reserved" / "natural" / " **丰富回复** — 回复可直接携带图片;回复时 @ 人由 [`[chat].enable_reply_at`](#上下文与回想) 控制,回复中的表情由 [`[emoji].use_new_send_logic`](#表情包) 控制。 -**快速反应模式** — 开启 `planner_message_steering` 后,Planner 强制使用流式请求;思考、输出或 `wait` 等待期间收到新消息会立即中断当前轮并重新请求,不再等静默窗口,也不限制连续打断次数。被打断的思考与输出会保留在历史里,方便回看。 +**被动回复** — `passive_replyer = true` 时,Planner 不调用工具而直接输出正文的话,正文会作为指导启动一次回复;附件与插件参数通过 `set_reply_options` 提前设置。关闭时使用原有 `reply` 工具。切换从下一轮思考生效,Focus 不受影响。 -**子代理** — `planner_subagent = true` 给 Planner 提供 `subagent` 工具:把自包含的查询或整理任务交给子代理,子代理在独立上下文里多轮调用被授权的工具,只把结论交还。开启 `advanced_sub_agent = true` 后子代理转到后台,派发后立刻返回任务 ID,麦麦可以继续聊天;子代理结束时结论作为一条新消息送回并唤醒 Planner,同时提供 `subagent_status`(查看任务)和 `subagent_stop`(终止任务)。 - -**超长工具结果整理** — `tool_result_condense = true` 时,工具结果达到 `tool_result_condense_threshold` 字符(默认 3000,最低 500)会先交给子代理按 Planner 当前意图整理成结论,再写入上下文,减少后续每轮的上下文占用;代价是多一次模型请求。 - -**优化提示词与工具** — `planner_optimized_prompt = true` 让 Planner 用第二人称描述麦麦自己,并精简任务说明;`planner_stop_tool = true` 提供一个无参数的 `stop()` 工具,调用后结束本轮思考并等待新消息。 +**Focus** — `focus_mode = true` 让同组聊天共享一个持续思考的 Planner:全部消息共同进入上下文,工具通过 `session_id` 指定处理目标,跨会话协作、统一等待,被 @ 时提前唤醒。`focus_groups` 把聊天分成共享组,不同组互不抢占,未匹配的聊天各自成组;`focus_chat_whitelist` 限定哪些聊天进入 Focus,留空表示所有符合聊天类型开关的聊天都可进入。 **学习规则不在实验段** — 表达方式与黑话的学习范围由 `[expression].learning_list` / `[jargon].learning_list` 配置,详见[学习系统](#学习系统);旧的 `[experimental]` 学习字段已移除。 -**复古回复提示词** — `replyer_retro_prompt = true` 时按旧版(0.12.x)方式组织 Replyer 提示词:全部回复指令集中在一份完整模板里,整段作为一条 `user` 消息发送,历史对话渲染成纯文本填入模板占位符,不再发送图片 Item。群聊、"简短回复"、私聊和"私聊且回复麦麦自己"各用一套模板(`retro_replyer`、`retro_replyer_light`、`retro_private_replyer`、`retro_private_replyer_self`),它们在 **Prompt 管理**里以"高级"折叠展示,可以编辑和创建自定义版本。改动热重载生效。 - #### 消息接收 ::: code-group @@ -416,7 +428,7 @@ reaction = "对方在问早,简短回应即可" [expression] expression_checked_only = false # 仅使用人工精选过的表达;关闭时未精选的表达也会被使用 expression_self_reflect = true # 写入前先让 AI 审核,减少学到奇怪内容 -use_vector_expression = true # 使用向量表达:表达意图 + 嵌入召回,效果更好(需嵌入模型);关闭则随手抽取 +use_vector_expression = false # 表达选择档位:false 快速(默认) / true 精细(需嵌入模型) expression_vector_index_path = "data/expression_selection/expression_vector_index.json" # [进阶] expression_vector_candidate_pool_size = 50 # [进阶] 向量召回后交给 LLM 选择的候选数,硬上限 50 max_expression_learner = 3 # [进阶] 同时运行的学习任务数 @@ -428,7 +440,7 @@ expression_groups = [] # 多个聊天共享学到的表达 **要点:** -- **`use_vector_expression`** — 默认开启,改用表达意图 + 嵌入模型精细召回,效果显著更好;关闭时退回随手抽取的候选。 +- **`use_vector_expression`** — 表达选择分两档:`false` 快速(默认),加权随机抽取表达直接注入,不额外调用模型;`true` 精细,用表达意图与嵌入召回,再由 LLM 按语境筛选,需配置嵌入模型。复古回复不使用表达选择。 - **`expression_checked_only`** — 默认 `false`,即未经人工精选的表达也会参与;如果你只想让麦麦使用你审核过的表达,改为 `true` - **`learning_list`** — 每条规则管一个范围,`use` 控制是否使用已学内容,`learn` 控制是否继续学习,`type` 可选 `"group"` / `"private"`。范围有三种写法,越具体的越优先: - **指定聊天** — 填 `item_id`(群号或 QQ 号),`platform` 可填可不填 @@ -463,6 +475,7 @@ jargon_groups = [] # 多个聊天共享学到的黑话 ```toml [bot_config.toml ~vscode-icons:file-type-toml~] [visual] +image_quality = "normal" # 图片画质:"normal" 普通(最长边 512)/ "high" 超清(最长边 1024) max_image_num = 64 # [进阶] 一次多模态请求最多带多少张图 wait_image_recognize_max_time = 32 # 等识图完成的最长秒数;0 = 不等待 handle_oversized_images = true # 收到过大图片时自动压缩或丢弃 @@ -478,6 +491,8 @@ no_file_result_retention_days = 30 # 图片删掉后识别结果再保留多久 ::: +**图片画质** — `image_quality` 控制聊天普通图片发给规划和回复模型时的画质:普通最长边 512 像素,超清 1024 像素,保留更多细节也更耗用量。等比例缩小、小图不放大,不影响原图和表情包。 + #### 表情包 ::: code-group @@ -643,6 +658,29 @@ enable = true # 是否启用 MCP 工具接入能力 改 `[mcp]` 段保存后,MaiBot 会用新配置重建 MCP 连接,不需要重启;重建结果与启动时一样打印在日志里。少数不在重载判定范围内的字段(如 `elicitation` 整节、`sampling.include_context_support`)仍需重启才生效,详见 [MCP 配置](./mcp-config.md)。 ::: +#### Agent 连接 + +`[agent]` 启动一个与普通聊天并行运行的外接 Agent(实验性),通过 ACP 协议连接 dsh、dsh Desktop 或其他 ACP 程序;模型与凭据使用外部 Agent 自身配置。开启 `computer_tools` 后,Agent 还能操作沙盒桌面:聊天里可以图文传话,任务重启后继续,WebUI 提供桌面画面、运行记录和人工接管。 + +::: code-group + +```toml [bot_config.toml ~vscode-icons:file-type-toml~] +[agent] +enabled = false # 启用外接 Agent 接口 +connection = "dsh" # "dsh" dsh CLI / "dsh_desktop" dsh Desktop / "custom" 自定义 ACP +acp_command = "dsh" # 外部 Agent 可执行程序;Windows 可填 dsh.cmd +acp_cwd = "" # 外部进程的主机工作目录;留空使用 data/agent/workspace +computer_tools = false # 提供沙盒桌面工具与 WebUI 接管界面 +networking = true # 允许沙盒联网;下次启动沙盒时生效 +desktop_manifest = "" # [进阶] dsh Desktop 桥接文件;留空读取 ~/.dsh/maibot-desktop.json +``` + +::: + +- **dsh CLI / dsh Desktop** — dsh CLI 自动以 `--profile acp` 启动;dsh Desktop 连接正在运行的桌面应用,需先在 Desktop 安装 dsh-maibot-bridge 插件,同一会话在两侧显示 +- **自定义 ACP** — `connection = "custom"` 时用 `acp_args` 逐项传参、`acp_env` 追加环境变量、`acp_model` 指定模型选项;`acp_timeout` 控制握手与关停等待 +- **沙盒桌面** — `computer_tools = true` 提供沙盒桌面工具与 WebUI 接管界面;人工接管期间不执行 Agent 输入。沙盒内存、启动超时、截图最长边等进阶参数见 WebUI 中的对应设置 + #### 插件管理 ::: code-group @@ -712,7 +750,10 @@ log_cleanup_days = 30 # 主日志超过多少天后清理 llm_request_snapshot_limit = 128 # 失败模型请求快照最多保留多少份 maisaka_prompt_preview_limit = 256 # 每个聊天最多保留多少组 Prompt 预览 -maisaka_reply_effect_limit = 256 # 每个聊天最多保留多少条回复效果记录 + +memory_diagnostics_enabled = true # [进阶] 独立内存诊断日志;最多四个 5 MiB 文件,重启生效 +memory_diagnostics_deep_enabled = false # [进阶] tracemalloc 分配位置对比(每十分钟);有额外开销,重启生效 +memory_diagnostics_interval_seconds = 60.0 # [进阶] 轻量内存诊断采集间隔(秒,至少 10),重启生效 event_loop_watchdog_enabled = false # [进阶] 记录事件循环卡顿,用于排查界面/主循环卡顿 event_loop_watchdog_warn_seconds = 0.5 # [进阶] 事件循环唤醒延迟超过该秒数时记录一条警告日志 @@ -733,7 +774,8 @@ library_log_levels = { aiohttp = "WARNING", PIL = "WARNING" } # [进阶] 单独 [debug] enable_console_input = true # 在交互式终端中启用本地消息和指令输入(默认开启) show_maisaka_thinking = true # 在日志或界面中显示麦麦的思考过程 -enable_reply_effect_tracking = false # 记录回复效果评分,观察回复质量 +save_maisaka_reasoning = true # 保存 Planner、工具调用及聊天回想的完整推理记录,供 WebUI 查看 +replyer_retro_prompt = false # 按旧版(0.12.x)方式组织 Replyer 提示词,全部指令集中在一份模板里 force_plugin_compatibility = false # 跳过插件声明的 Host/SDK 版本校验直接加载;开启后需重启生效 keep_prompt_preview_json_base64 = false # [进阶] Prompt 预览保留图片 base64;便于复现但占空间 record_tool_structured_content = false # [进阶] 保存工具返回的结构化内容;增加数据库体积 @@ -747,6 +789,7 @@ enable_llm_cache_stats = false # [进阶] 记录模型 prompt cache - **终端输入** — `enable_console_input` 默认开启:在交互式终端里可以直接输入普通消息,或用 `/clear`、`/pm`、`/offline`、`/online`、`/help` 等指令管理聊天和适配器,输入 `exit()` 关闭。非交互终端(systemd、nohup、`docker run` 不带 `-it`)只会多打一条 warning,不影响运行;改动需重启 - **强制插件兼容** — `force_plugin_compatibility = true` 会跳过插件 manifest 声明的 Host/SDK 版本区间校验直接加载,**仅作临时兜底**,可能加载实际不兼容的插件;它只记一条 warning,且不影响插件市场的版本兼容性判断。开启后需重启 - **`/clear` 指令** — `/clear` 是默认可用的内置命令;如需禁用,用 `[plugin].disabled_commands = ["core.clear"]` +- **复古回复提示词** — `replyer_retro_prompt = true` 时按旧版(0.12.x)方式组织 Replyer 提示词:全部回复指令集中在一份完整模板里,整段作为一条 `user` 消息发送,历史对话渲染成纯文本填入模板占位符,不再发送图片 Item。群聊、"简短回复"、私聊和"私聊且回复麦麦自己"各用一套模板(`retro_replyer`、`retro_replyer_light`、`retro_private_replyer`、`retro_private_replyer_self`),它们在 **Prompt 管理**里以"高级"折叠展示,可以编辑和创建自定义版本。改动热重载生效 #### 遥测 @@ -811,7 +854,7 @@ python -c "import tomllib; tomllib.load(open('config/bot_config.toml','rb')); pr **麦麦刷屏话痨** — 调低 `talk_value`(如 0.3);`response_splitter.max_sentence_num` 和 `max_split_num` 限制单次回复条数;注意 `emoji_send_num` 只是发送候选数,调小它不会减少发言频率。 -**手动加的字段被删掉** — 配置文件由程序自动升级,不存在或拼写错误的字段(如把 `mid_term_memory_lenth` 改成 `length`)会在下次启动时被清理回默认值。先启动一次让程序生成/升级文件,再在生成的字段上改值。 +**手动加的字段被删掉** — 配置文件由程序自动升级,不存在或拼写错误的字段(如把 `max_context_size` 拼成 `max_context_len`)会在下次启动时被清理回默认值。先启动一次让程序生成/升级文件,再在生成的字段上改值。 **人设改了感觉没变化** — 人设只影响新生成的回复,已发出的消息不会变。确认日志出现重载成功后,连续观察几轮对话;想让风格偶尔突变,试试 `multiple_reply_style` + `multiple_probability`。 diff --git a/zh/manual/configuration/index.md b/zh/manual/configuration/index.md index 816e0a2..af42ea3 100644 --- a/zh/manual/configuration/index.md +++ b/zh/manual/configuration/index.md @@ -29,7 +29,7 @@ MaiBot 的全部设置都在 `config/` 目录下的两个 TOML 文件里:改 MaiBot 会监听这两个文件的变化。是否需要重启,取决于该设置控制的是运行时行为,还是服务的启动方式。 -**保存后自动生效** — 机器人人设、人格、聊天策略、回复频率、模型提供商、模型与任务分配、`[experimental]` 的复古回复提示词(`replyer_retro_prompt`)、`[response_splitter].mode` 等会热重载。模型变更对后续请求生效;带重载回调的模块(含 A_Memorix、表情维护)也会收到更新。 +**保存后自动生效** — 机器人人设、人格、聊天策略、回复频率、模型提供商、模型与任务分配、`[debug]` 的复古回复提示词(`replyer_retro_prompt`)、`[response_splitter].mode` 等会热重载。模型变更对后续请求生效;带重载回调的模块(含 A_Memorix、表情维护)也会收到更新。 **由插件运行时热重载** — 插件自己的 `config.toml` 有独立生命周期。运行时会监听它并调用插件配置更新钩子。启用、禁用、安装、卸载和源码更新一般不需要重启整个 MaiBot。 diff --git a/zh/manual/configuration/model-config.md b/zh/manual/configuration/model-config.md index c6c1d80..58c54d9 100644 --- a/zh/manual/configuration/model-config.md +++ b/zh/manual/configuration/model-config.md @@ -136,7 +136,7 @@ cache_price_in = 0.0 preview_chars = 4000 # 单次返回的内容预览字数,完整内容用 read_tool_result 读取 [web.services.deepseek] -adapter = "deepseek" # 服务协议:deepseek / tavily / stepsearch_mcp +adapter = "deepseek" # 服务协议:deepseek / tavily / stepsearch_mcp / anysearch / exa / firecrawl api_key = "sk-..." # DeepSeek API 密钥 # base_url = "https://api.deepseek.com" # 留空使用官方地址,也可填 OpenAI 兼容的 /v1 地址 timeout = 60 # 单次调用总时限(秒) @@ -174,12 +174,55 @@ timeout = 60 model_list = ["stepsearch"] ``` +```toml [AnySearch ~vscode-icons:file-type-toml~] +[web] +preview_chars = 4000 + +[web.services.anysearch] +adapter = "anysearch" +api_key = "..." # AnySearch API 密钥 +# base_url = "https://api.anysearch.com" # 留空使用官方地址 +timeout = 60 + +[model_task_config.web_search] +model_list = ["anysearch"] +``` + +```toml [Exa ~vscode-icons:file-type-toml~] +[web] +preview_chars = 4000 + +[web.services.exa] +adapter = "exa" +api_key = "..." # Exa API 密钥 +# base_url = "https://api.exa.ai" # 留空使用官方地址 +timeout = 60 + +[model_task_config.web_search] +model_list = ["exa"] +``` + +```toml [Firecrawl ~vscode-icons:file-type-toml~] +[web] +preview_chars = 4000 + +[web.services.firecrawl] +adapter = "firecrawl" +api_key = "fc-..." # Firecrawl API 密钥 +# base_url = "https://api.firecrawl.dev" # 留空使用官方地址 +timeout = 60 + +[model_task_config.web_search] +model_list = ["firecrawl"] +``` + ::: **要点:** - **启用方式** — 只有 `model_task_config.web_search.model_list` 选中服务后才会注册 `web_search` / `web_fetch` 工具;留空时联网工具完全关闭 - **服务数量** — `model_list` 只能选一个服务;需要切换服务时改这里即可,不用删掉其他定义 +- **AnySearch / Exa / Firecrawl** — 都只需 `api_key`,`base_url` 留空用官方地址、可指向代理或自建服务 - **StepSearch MCP** — 连接地址和鉴权由 `bot_config.toml` 的 `[mcp.servers]` 管理,`web.services` 里只写 `server_ref`,不要再填 `api_key` 或 `base_url` - **长网页** — 单次只把 `preview_chars` 范围内的内容交给模型,完整结果可通过 `read_tool_result` 读取;开启「超长工具结果整理」时也会用到它 - **搜索参数** — `web_search` 只接受 `query` 与 `max_results`(1~20,默认 5);`web_fetch` 只接受 `url` diff --git a/zh/plugin/api-reference.md b/zh/plugin/api-reference.md index ffcec5f..b3b0515 100644 --- a/zh/plugin/api-reference.md +++ b/zh/plugin/api-reference.md @@ -773,7 +773,7 @@ image_path = Path(claimed["path"]) ::: -凭证所属插件必须匹配,一小时过期,只能领取一次。它来自登录保护的 WebUI 上传接口,不接受任意文件路径代替。文件内容不经普通 JSON/RPC 传递。完整页面声明及格式/尺寸限制见[WebUI 页面](./webui-pages.md#上传与交互能力)。 +凭证所属插件必须匹配,一小时过期,只能领取一次。它来自登录保护的 WebUI 上传接口,不接受任意文件路径代替。文件内容不经普通 JSON/RPC 传递。完整页面声明及格式/尺寸限制见[WebUI 页面](./webui-pages.md#图片上传)。 ## paths — 运行时路径