setQueryLimit(event.target.value)} />
diff --git a/dashboard/src/i18n/locales/en.json b/dashboard/src/i18n/locales/en.json
index a3bc03cf..a4e16283 100644
--- a/dashboard/src/i18n/locales/en.json
+++ b/dashboard/src/i18n/locales/en.json
@@ -19,7 +19,7 @@
"overview": "Overview",
"botConfig": "Bot Configuration",
"botResources": "Bot Resources",
- "extensionsMonitor": "Extensions & Monitor",
+ "extensionsMonitor": "Plugins & Extensions",
"system": "System"
},
"menu": {
@@ -27,16 +27,18 @@
"botMainConfig": "Bot Main Config",
"aiModelProvider": "AI Model Providers",
"modelManagement": "Model Management",
+ "promptManagement": "Prompt Management",
"adapterConfig": "Adapter Config",
"emojiManagement": "Emoji Management",
"expressionManagement": "Expression Management",
"slangManagement": "Slang Management",
"personInfo": "Person Info",
"knowledgeGraph": "Long-Term Memory Graph",
- "knowledgeBase": "Long-Term Memory Console",
+ "knowledgeBase": "Long-Term Memory",
"pluginMarket": "Plugin Market",
"configTemplate": "Config Templates",
- "pluginConfig": "Plugin Config",
+ "pluginConfig": "Plugin Management",
+ "mcpSettings": "MCP Settings",
"logViewer": "Log Viewer",
"maisakaMonitor": "MaiSaka Chat Monitor",
"localChat": "Local Chat",
@@ -500,17 +502,13 @@
"title": "Personality",
"description": "Define the bot's personality and speaking style"
},
- "emoji": {
- "title": "Emoji",
- "description": "Configure emoji-related settings"
- },
- "other": {
- "title": "Other Settings",
- "description": "Configure global slang and other basic options"
- },
- "siliconFlow": {
+ "apiProvider": {
"title": "API Setup",
- "description": "Configure the SiliconFlow API key"
+ "description": "Configure the API provider"
+ },
+ "modelSetup": {
+ "title": "Model Setup",
+ "description": "Configure planner and replyer models"
}
},
"loading": {
@@ -528,7 +526,12 @@
"selectPlatform": "Please select a platform",
"enterNickname": "Please enter a nickname",
"enterQqAccount": "Please enter a QQ account",
- "enterAccountId": "Please enter an account ID"
+ "enterAccountId": "Please enter an account ID",
+ "enterProviderName": "Please enter an API provider name",
+ "enterBaseUrl": "Please enter the API base URL",
+ "enterApiKey": "Please enter the API key",
+ "enterPlannerModelIdentifier": "Please enter the planner model identifier",
+ "enterReplyerModelIdentifier": "Please enter the replyer model identifier"
},
"toast": {
"loadFailedTitle": "Failed to load configuration",
@@ -667,33 +670,43 @@
"description": "Allow the bot to learn and use group-specific slang"
}
},
- "siliconFlow": {
- "about": {
- "title": "About SiliconFlow",
- "description": "SiliconFlow provides broad model coverage, including DeepSeek V3, Qwen, vision models, speech recognition, and embedding models. A single API key unlocks all MaiBot features.",
- "link": "Get an API key from SiliconFlow"
+ "apiProvider": {
+ "providerName": {
+ "label": "API Provider Name *",
+ "placeholder": "For example OpenAI, DeepSeek, or self-hosted",
+ "description": "This name is written to model_config.toml and referenced by the models below"
+ },
+ "baseUrl": {
+ "label": "API Base URL *",
+ "description": "Enter an OpenAI-compatible endpoint, for example https://api.example.com/v1"
},
"apiKey": {
- "label": "SiliconFlow API Key *",
- "description": "Enter your SiliconFlow API key. Once provided, MaiBot will automatically configure all required models.",
+ "label": "API Key *",
+ "description": "Enter the API key for this provider",
"show": "Show API key",
"hide": "Hide API key"
- },
- "autoConfig": {
- "title": "The following models will be configured automatically:",
- "items": {
- "deepseek": "DeepSeek V3 - primary chat and tool model",
- "qwen3": "Qwen3 30B - frequent small tasks and tool calls",
- "qwen3Vl": "Qwen3 VL 30B - image recognition",
- "senseVoice": "SenseVoice - speech recognition",
- "bgeM3": "BGE-M3 - text embeddings",
- "lpmm": "Knowledge-base-related models (LPMM)"
+ }
+ },
+ "modelSetup": {
+ "planner": {
+ "identifier": {
+ "label": "planner Model Identifier *",
+ "description": "The real model ID provided by the API service; the model name will be initialized from it"
+ },
+ "visual": {
+ "label": "Enable vision"
}
},
- "hint": {
- "title": "Tip: ",
- "description": "After finishing the wizard, you can add more API providers and models in \"System Settings -> Model Config\"."
- }
+ "replyer": {
+ "identifier": {
+ "label": "replyer Model Identifier *",
+ "description": "The real model ID provided by the API service; the model name will be initialized from it"
+ },
+ "visual": {
+ "label": "Enable vision"
+ }
+ },
+ "saveHint": "You can configure more detailed task assignment later."
}
}
},
diff --git a/dashboard/src/i18n/locales/ja.json b/dashboard/src/i18n/locales/ja.json
index 3dd08798..d318efc9 100644
--- a/dashboard/src/i18n/locales/ja.json
+++ b/dashboard/src/i18n/locales/ja.json
@@ -19,7 +19,7 @@
"overview": "概要",
"botConfig": "ボット設定",
"botResources": "ボットリソース",
- "extensionsMonitor": "拡張機能 & 監視",
+ "extensionsMonitor": "プラグインと拡張",
"system": "システム"
},
"menu": {
@@ -27,16 +27,18 @@
"botMainConfig": "ボットメイン設定",
"aiModelProvider": "AIモデルプロバイダー",
"modelManagement": "モデル管理",
+ "promptManagement": "Prompt 管理",
"adapterConfig": "アダプター設定",
"emojiManagement": "絵文字管理",
"expressionManagement": "表現管理",
"slangManagement": "スラング管理",
"personInfo": "人物情報",
"knowledgeGraph": "長期記憶グラフ",
- "knowledgeBase": "長期記憶コンソール",
+ "knowledgeBase": "長期記憶",
"pluginMarket": "プラグインマーケット",
"configTemplate": "設定テンプレート",
- "pluginConfig": "プラグイン設定",
+ "pluginConfig": "プラグイン管理",
+ "mcpSettings": "MCP 設定",
"logViewer": "ログビューア",
"maisakaMonitor": "MaiSaka チャット監視",
"localChat": "ローカルチャット",
@@ -500,17 +502,13 @@
"title": "人格設定",
"description": "ボットの性格や話し方を定義します"
},
- "emoji": {
- "title": "絵文字パック",
- "description": "絵文字パック関連の設定を行います"
- },
- "other": {
- "title": "その他の設定",
- "description": "グローバルスラングなどの基本オプションを設定します"
- },
- "siliconFlow": {
+ "apiProvider": {
"title": "API設定",
- "description": "SiliconFlow API キーを設定します"
+ "description": "APIプロバイダーを設定します"
+ },
+ "modelSetup": {
+ "title": "モデル設定",
+ "description": "planner と replyer モデルを設定します"
}
},
"loading": {
@@ -528,7 +526,12 @@
"selectPlatform": "プラットフォームを選択してください",
"enterNickname": "ニックネームを入力してください",
"enterQqAccount": "QQ アカウントを入力してください",
- "enterAccountId": "アカウント ID を入力してください"
+ "enterAccountId": "アカウント ID を入力してください",
+ "enterProviderName": "APIプロバイダー名を入力してください",
+ "enterBaseUrl": "API Base URL を入力してください",
+ "enterApiKey": "API Key を入力してください",
+ "enterPlannerModelIdentifier": "planner モデル識別子を入力してください",
+ "enterReplyerModelIdentifier": "replyer モデル識別子を入力してください"
},
"toast": {
"loadFailedTitle": "設定の読み込みに失敗しました",
@@ -667,33 +670,43 @@
"description": "グループ内のスラングを学習して使えるようにします"
}
},
- "siliconFlow": {
- "about": {
- "title": "SiliconFlow について",
- "description": "SiliconFlow は DeepSeek V3、Qwen、ビジョンモデル、音声認識、埋め込みモデルなど幅広いモデルを提供します。API Key が1つあれば MaiBot の全機能を利用できます。",
- "link": "SiliconFlow で API Key を取得する"
+ "apiProvider": {
+ "providerName": {
+ "label": "APIプロバイダー名 *",
+ "placeholder": "例: OpenAI、DeepSeek、自ホストサービス",
+ "description": "この名前は model_config.toml に保存され、下のモデルから参照されます"
+ },
+ "baseUrl": {
+ "label": "API Base URL *",
+ "description": "OpenAI互換エンドポイントを入力してください。例: https://api.example.com/v1"
},
"apiKey": {
- "label": "SiliconFlow API Key *",
- "description": "SiliconFlow の API Key を入力してください。入力後、MaiBot が必要なモデルを自動設定します。",
+ "label": "API Key *",
+ "description": "このプロバイダーの API Key を入力してください",
"show": "API Key を表示",
- "hide": "API Key を隠す"
- },
- "autoConfig": {
- "title": "以下のモデルが自動設定されます:",
- "items": {
- "deepseek": "DeepSeek V3 - メインの会話・ツールモデル",
- "qwen3": "Qwen3 30B - 頻繁な小タスクとツール呼び出し",
- "qwen3Vl": "Qwen3 VL 30B - 画像認識",
- "senseVoice": "SenseVoice - 音声認識",
- "bgeM3": "BGE-M3 - テキスト埋め込み",
- "lpmm": "知識ベース関連モデル (LPMM)"
+ "hide": "API Key を非表示"
+ }
+ },
+ "modelSetup": {
+ "planner": {
+ "identifier": {
+ "label": "planner モデル識別子 *",
+ "description": "APIサービスが提供する実際のモデルID。モデル名はこの識別子で初期化されます"
+ },
+ "visual": {
+ "label": "ビジョンを有効化"
}
},
- "hint": {
- "title": "ヒント:",
- "description": "ウィザード完了後は、「システム設定 -> モデル設定」でさらに API プロバイダーやモデルを追加できます。"
- }
+ "replyer": {
+ "identifier": {
+ "label": "replyer モデル識別子 *",
+ "description": "APIサービスが提供する実際のモデルID。モデル名はこの識別子で初期化されます"
+ },
+ "visual": {
+ "label": "ビジョンを有効化"
+ }
+ },
+ "saveHint": "より詳細なタスク割り当ては後で設定できます。"
}
}
},
diff --git a/dashboard/src/i18n/locales/ko.json b/dashboard/src/i18n/locales/ko.json
index 5a6f294d..3a4d9bb9 100644
--- a/dashboard/src/i18n/locales/ko.json
+++ b/dashboard/src/i18n/locales/ko.json
@@ -19,7 +19,7 @@
"overview": "개요",
"botConfig": "봇 설정",
"botResources": "봇 리소스",
- "extensionsMonitor": "확장 기능 & 모니터",
+ "extensionsMonitor": "플러그인 및 확장",
"system": "시스템"
},
"menu": {
@@ -27,16 +27,18 @@
"botMainConfig": "봇 메인 설정",
"aiModelProvider": "AI 모델 공급자",
"modelManagement": "모델 관리",
+ "promptManagement": "Prompt 관리",
"adapterConfig": "어댑터 설정",
"emojiManagement": "이모티콘 관리",
"expressionManagement": "표현 관리",
"slangManagement": "슬랭 관리",
"personInfo": "인물 정보",
"knowledgeGraph": "장기 기억 그래프",
- "knowledgeBase": "장기 기억 콘솔",
+ "knowledgeBase": "장기 기억",
"pluginMarket": "플러그인 마켓",
"configTemplate": "설정 템플릿",
- "pluginConfig": "플러그인 설정",
+ "pluginConfig": "플러그인 관리",
+ "mcpSettings": "MCP 설정",
"logViewer": "로그 뷰어",
"maisakaMonitor": "MaiSaka 채팅 모니터",
"localChat": "로컬 채팅",
@@ -500,17 +502,13 @@
"title": "성격 설정",
"description": "봇의 성격과 말투를 정의합니다"
},
- "emoji": {
- "title": "이모지 팩",
- "description": "이모지 관련 설정을 구성합니다"
- },
- "other": {
- "title": "기타 설정",
- "description": "전역 슬랭 등 기본 옵션을 설정합니다"
- },
- "siliconFlow": {
+ "apiProvider": {
"title": "API 설정",
- "description": "SiliconFlow API 키를 설정합니다"
+ "description": "API 제공자를 설정합니다"
+ },
+ "modelSetup": {
+ "title": "모델 설정",
+ "description": "planner와 replyer 모델을 설정합니다"
}
},
"loading": {
@@ -528,7 +526,12 @@
"selectPlatform": "플랫폼을 선택해 주세요",
"enterNickname": "닉네임을 입력해 주세요",
"enterQqAccount": "QQ 계정을 입력해 주세요",
- "enterAccountId": "계정 ID를 입력해 주세요"
+ "enterAccountId": "계정 ID를 입력해 주세요",
+ "enterProviderName": "API 제공자 이름을 입력해 주세요",
+ "enterBaseUrl": "API Base URL을 입력해 주세요",
+ "enterApiKey": "API Key를 입력해 주세요",
+ "enterPlannerModelIdentifier": "planner 모델 식별자를 입력해 주세요",
+ "enterReplyerModelIdentifier": "replyer 모델 식별자를 입력해 주세요"
},
"toast": {
"loadFailedTitle": "설정 불러오기에 실패했습니다",
@@ -667,33 +670,43 @@
"description": "봇이 그룹 슬랭을 학습하고 사용할 수 있게 합니다"
}
},
- "siliconFlow": {
- "about": {
- "title": "SiliconFlow 소개",
- "description": "SiliconFlow 는 DeepSeek V3, Qwen, 비전 모델, 음성 인식, 임베딩 모델 등 폭넓은 모델을 제공합니다. API Key 하나로 MaiBot 의 모든 기능을 사용할 수 있습니다.",
- "link": "SiliconFlow 에서 API Key 받기"
+ "apiProvider": {
+ "providerName": {
+ "label": "API 제공자 이름 *",
+ "placeholder": "예: OpenAI, DeepSeek, 자체 호스팅",
+ "description": "이 이름은 model_config.toml에 저장되며 아래 모델에서 참조됩니다"
+ },
+ "baseUrl": {
+ "label": "API Base URL *",
+ "description": "OpenAI 호환 엔드포인트를 입력해 주세요. 예: https://api.example.com/v1"
},
"apiKey": {
- "label": "SiliconFlow API Key *",
- "description": "SiliconFlow API Key를 입력해 주세요. 입력하면 MaiBot 이 필요한 모델을 자동으로 구성합니다.",
+ "label": "API Key *",
+ "description": "이 제공자의 API Key를 입력해 주세요",
"show": "API Key 표시",
"hide": "API Key 숨기기"
- },
- "autoConfig": {
- "title": "다음 모델이 자동으로 구성됩니다:",
- "items": {
- "deepseek": "DeepSeek V3 - 주요 대화 및 도구 모델",
- "qwen3": "Qwen3 30B - 잦은 소규모 작업과 도구 호출",
- "qwen3Vl": "Qwen3 VL 30B - 이미지 인식",
- "senseVoice": "SenseVoice - 음성 인식",
- "bgeM3": "BGE-M3 - 텍스트 임베딩",
- "lpmm": "지식 베이스 관련 모델 (LPMM)"
+ }
+ },
+ "modelSetup": {
+ "planner": {
+ "identifier": {
+ "label": "planner 모델 식별자 *",
+ "description": "API 서비스가 제공하는 실제 모델 ID입니다. 모델 이름은 이 식별자로 초기화됩니다"
+ },
+ "visual": {
+ "label": "비전 사용"
}
},
- "hint": {
- "title": "팁: ",
- "description": "마법사를 마친 뒤에는 \"시스템 설정 -> 모델 설정\"에서 더 많은 API 제공자와 모델을 추가할 수 있습니다."
- }
+ "replyer": {
+ "identifier": {
+ "label": "replyer 모델 식별자 *",
+ "description": "API 서비스가 제공하는 실제 모델 ID입니다. 모델 이름은 이 식별자로 초기화됩니다"
+ },
+ "visual": {
+ "label": "비전 사용"
+ }
+ },
+ "saveHint": "더 자세한 작업 할당은 나중에 설정할 수 있습니다."
}
}
},
diff --git a/dashboard/src/i18n/locales/zh.json b/dashboard/src/i18n/locales/zh.json
index 4325f589..d1efaefd 100644
--- a/dashboard/src/i18n/locales/zh.json
+++ b/dashboard/src/i18n/locales/zh.json
@@ -19,7 +19,7 @@
"overview": "概览",
"botConfig": "麦麦配置编辑",
"botResources": "麦麦资源管理",
- "extensionsMonitor": "扩展与监控",
+ "extensionsMonitor": "插件与扩展",
"system": "系统"
},
"menu": {
@@ -27,16 +27,18 @@
"botMainConfig": "麦麦主程序配置",
"aiModelProvider": "AI模型厂商配置",
"modelManagement": "模型管理与分配",
+ "promptManagement": "Prompt 管理",
"adapterConfig": "麦麦适配器配置",
"emojiManagement": "表情包管理",
"expressionManagement": "表达方式管理",
"slangManagement": "黑话管理",
"personInfo": "人物信息管理",
"knowledgeGraph": "长期记忆图谱",
- "knowledgeBase": "长期记忆控制台",
+ "knowledgeBase": "长期记忆",
"pluginMarket": "插件市场",
"configTemplate": "配置模板市场",
- "pluginConfig": "插件配置",
+ "pluginConfig": "插件管理",
+ "mcpSettings": "MCP 设置",
"logViewer": "日志查看器",
"maisakaMonitor": "MaiSaka 聊天流监控",
"localChat": "本地聊天室",
@@ -500,17 +502,13 @@
"title": "人格配置",
"description": "定义机器人的性格和说话风格"
},
- "emoji": {
- "title": "表情包",
- "description": "配置表情包相关设置"
- },
- "other": {
- "title": "其他设置",
- "description": "配置全局黑话等基础选项"
- },
- "siliconFlow": {
+ "apiProvider": {
"title": "API配置",
- "description": "配置硅基流动 API 密钥"
+ "description": "配置 API 提供商"
+ },
+ "modelSetup": {
+ "title": "模型配置",
+ "description": "配置 planner 和 replyer 模型"
}
},
"loading": {
@@ -528,7 +526,12 @@
"selectPlatform": "请选择平台",
"enterNickname": "请输入昵称",
"enterQqAccount": "请输入 QQ 账号",
- "enterAccountId": "请输入账号 ID"
+ "enterAccountId": "请输入账号 ID",
+ "enterProviderName": "请输入 API 提供商名称",
+ "enterBaseUrl": "请输入 API Base URL",
+ "enterApiKey": "请输入 API Key",
+ "enterPlannerModelIdentifier": "请输入 planner 模型标识符",
+ "enterReplyerModelIdentifier": "请输入 replyer 模型标识符"
},
"toast": {
"loadFailedTitle": "加载配置失败",
@@ -559,8 +562,8 @@
"footer": "您可以随时在设置中修改这些配置",
"defaults": {
"personality": {
- "personality": "是一个女大学生,现在在读大二,会刷贴吧。",
- "replyStyle": "请回复得平淡一些,简短一些,说中文,不要刻意突出自身学科背景。可以参考贴吧、知乎和微博的回复风格。",
+ "personality": "是一个大二女大学生,现在正在上网和群友聊天。有轻微攻击性",
+ "replyStyle": "你的风格平淡简短。可以参考贴吧,知乎和微博的回复风格。不浮夸不长篇大论,不要过分修辞和复杂句。",
"multipleReplyStyles": {
"plain": "你的风格平淡但不失讽刺,很简短,很白话。可以参考贴吧、微博的回复风格。",
"shortText": "用1-2个字进行回复",
@@ -577,7 +580,7 @@
"platform": {
"label": "平台 *",
"placeholder": "请选择平台",
- "description": "选择机器人运行的平台",
+ "description": "选择麦麦Bot运行的平台",
"options": {
"custom": "其他平台"
}
@@ -589,7 +592,7 @@
"qqAccount": {
"label": "QQ账号 *",
"placeholder": "请输入机器人的 QQ 账号",
- "description": "机器人登录使用的 QQ 账号"
+ "description": "运行麦麦Bot的 QQ 账号"
},
"primaryAccount": {
"label": "账号 ID *",
@@ -599,7 +602,7 @@
"nickname": {
"label": "昵称 *",
"placeholder": "请输入机器人的昵称",
- "description": "机器人的主要称呼名称"
+ "description": "麦麦Bot的名称"
},
"alias": {
"label": "别名",
@@ -667,33 +670,43 @@
"description": "允许机器人学习和使用群组黑话"
}
},
- "siliconFlow": {
- "about": {
- "title": "关于硅基流动 (SiliconFlow)",
- "description": "硅基流动提供了完整的模型覆盖,包括 DeepSeek V3、Qwen、视觉模型、语音识别和嵌入模型。只需一个 API Key 即可使用麦麦的所有功能!",
- "link": "前往硅基流动获取 API Key"
+ "apiProvider": {
+ "providerName": {
+ "label": "API 提供商名称 *",
+ "placeholder": "例如 OpenAI、DeepSeek、自建服务",
+ "description": "为api提供商命名"
+ },
+ "baseUrl": {
+ "label": "API Base URL *",
+ "description": "请填写 OpenAI 兼容接口地址,例如 https://api.example.com/v1"
},
"apiKey": {
- "label": "SiliconFlow API Key *",
- "description": "请输入您的硅基流动 API 密钥。获取后,麦麦将自动配置所有必需的模型。",
+ "label": "API Key *",
+ "description": "请填写该提供商的 API Key",
"show": "显示 API Key",
"hide": "隐藏 API Key"
- },
- "autoConfig": {
- "title": "将自动配置以下模型:",
- "items": {
- "deepseek": "DeepSeek V3 - 主要对话和工具模型",
- "qwen3": "Qwen3 30B - 高频小任务和工具调用",
- "qwen3Vl": "Qwen3 VL 30B - 图像识别",
- "senseVoice": "SenseVoice - 语音识别",
- "bgeM3": "BGE-M3 - 文本嵌入",
- "lpmm": "知识库相关模型 (LPMM)"
+ }
+ },
+ "modelSetup": {
+ "planner": {
+ "identifier": {
+ "label": "planner 模型标识符 *",
+ "description": "API 服务商提供的真实模型 ID,模型名称会自动初始化为该标识符"
+ },
+ "visual": {
+ "label": "启用视觉"
}
},
- "hint": {
- "title": "💡 提示:",
- "description": "完成向导后,您可以在“系统设置 -> 模型配置”中添加更多 API 提供商和模型。"
- }
+ "replyer": {
+ "identifier": {
+ "label": "replyer 模型标识符 *",
+ "description": "API 服务商提供的真实模型 ID,模型名称会自动初始化为该标识符"
+ },
+ "visual": {
+ "label": "启用视觉"
+ }
+ },
+ "saveHint": "你可以稍后配置更详细的任务分配。"
}
}
},
diff --git a/dashboard/src/lib/maisaka-monitor-client.ts b/dashboard/src/lib/maisaka-monitor-client.ts
index 76d3f972..40935278 100644
--- a/dashboard/src/lib/maisaka-monitor-client.ts
+++ b/dashboard/src/lib/maisaka-monitor-client.ts
@@ -26,6 +26,10 @@ export interface MaisakaToolCall {
export interface SessionStartEvent {
session_id: string
session_name: string
+ is_group_chat?: boolean
+ group_id?: string | null
+ user_id?: string | null
+ platform?: string
timestamp: number
}
@@ -91,6 +95,60 @@ export interface ToolExecutionEvent {
timestamp: number
}
+export interface MaisakaRequestBlock {
+ messages: MaisakaMessage[]
+ selected_history_count: number
+ tool_count: number
+}
+
+export interface MaisakaPlannerBlock {
+ content: string | null
+ tool_calls: MaisakaToolCall[]
+ prompt_tokens: number
+ completion_tokens: number
+ total_tokens: number
+ duration_ms: number
+ prompt_html_uri?: string
+}
+
+export interface MaisakaTimingGateBlock {
+ request: MaisakaRequestBlock | null
+ result: {
+ action: 'continue' | 'wait' | 'no_reply' | null
+ content: string | null
+ tool_calls: MaisakaToolCall[]
+ tool_results: unknown[]
+ prompt_tokens: number
+ completion_tokens: number
+ total_tokens: number
+ duration_ms: number
+ }
+}
+
+export interface MaisakaFinalizedToolResult {
+ tool_call_id: string
+ tool_name: string
+ tool_args: Record
+ success: boolean
+ duration_ms: number
+ summary: string
+ detail?: unknown
+}
+
+export interface PlannerFinalizedEvent {
+ session_id: string
+ cycle_id: number
+ timestamp: number
+ timing_gate: MaisakaTimingGateBlock | null
+ request: MaisakaRequestBlock | null
+ planner: MaisakaPlannerBlock | null
+ tools: MaisakaFinalizedToolResult[]
+ final_state: {
+ time_records: Record
+ agent_state: string
+ }
+}
+
export interface CycleEndEvent {
session_id: string
cycle_id: number
@@ -128,6 +186,7 @@ export type MaisakaMonitorEvent =
| { type: 'timing_gate.result'; data: TimingGateResultEvent }
| { type: 'planner.request'; data: PlannerRequestEvent }
| { type: 'planner.response'; data: PlannerResponseEvent }
+ | { type: 'planner.finalized'; data: PlannerFinalizedEvent }
| { type: 'tool.execution'; data: ToolExecutionEvent }
| { type: 'cycle.end'; data: CycleEndEvent }
| { type: 'replier.request'; data: ReplierRequestEvent }
diff --git a/dashboard/src/lib/memory-api.ts b/dashboard/src/lib/memory-api.ts
index 0c84bd3d..23663bbc 100644
--- a/dashboard/src/lib/memory-api.ts
+++ b/dashboard/src/lib/memory-api.ts
@@ -901,12 +901,16 @@ export async function getMemoryProfiles(limit: number = 50): Promise {
const params = new URLSearchParams({
person_id: options.personId ?? '',
person_keyword: options.personKeyword ?? '',
+ platform: options.platform ?? '',
+ user_id: options.userId ?? '',
limit: String(options.limit ?? 12),
force_refresh: options.forceRefresh ? 'true' : 'false',
})
diff --git a/dashboard/src/lib/pack-api.ts b/dashboard/src/lib/pack-api.ts
index c56b732f..2ca9b7b4 100644
--- a/dashboard/src/lib/pack-api.ts
+++ b/dashboard/src/lib/pack-api.ts
@@ -53,6 +53,7 @@ export interface PackTaskConfigs {
utils_small?: PackTaskConfig
tool_use?: PackTaskConfig
replyer?: PackTaskConfig
+ learner?: PackTaskConfig
planner?: PackTaskConfig
vlm?: PackTaskConfig
voice?: PackTaskConfig
diff --git a/dashboard/src/lib/plugin-api/marketplace.ts b/dashboard/src/lib/plugin-api/marketplace.ts
index a7054088..0842a91a 100644
--- a/dashboard/src/lib/plugin-api/marketplace.ts
+++ b/dashboard/src/lib/plugin-api/marketplace.ts
@@ -35,6 +35,12 @@ interface PluginApiResponse {
}
homepage_url?: string
repository_url?: string
+ urls?: {
+ repository?: string
+ homepage?: string
+ documentation?: string
+ issues?: string
+ }
keywords: string[]
categories?: string[]
default_locale: string
@@ -44,6 +50,28 @@ interface PluginApiResponse {
[key: string]: unknown
}
+function normalizePluginManifest(manifest: PluginApiResponse['manifest']): PluginInfo['manifest'] {
+ const repositoryUrl = manifest.repository_url || manifest.urls?.repository
+ const homepageUrl = manifest.homepage_url || manifest.urls?.homepage
+
+ return {
+ manifest_version: manifest.manifest_version || 1,
+ name: manifest.name,
+ version: manifest.version,
+ description: manifest.description || '',
+ author: manifest.author || { name: 'Unknown' },
+ license: manifest.license || 'Unknown',
+ host_application: manifest.host_application || { min_version: '0.0.0' },
+ homepage_url: homepageUrl,
+ repository_url: repositoryUrl,
+ urls: manifest.urls,
+ keywords: manifest.keywords || [],
+ categories: manifest.categories || [],
+ default_locale: manifest.default_locale || 'zh-CN',
+ locales_path: manifest.locales_path,
+ }
+}
+
/**
* 从远程获取插件列表(通过后端代理避免 CORS)
*/
@@ -88,21 +116,7 @@ export async function fetchPluginList(): Promise> {
})
.map((item) => ({
id: item.id,
- manifest: {
- manifest_version: item.manifest.manifest_version || 1,
- name: item.manifest.name,
- version: item.manifest.version,
- description: item.manifest.description || '',
- author: item.manifest.author || { name: 'Unknown' },
- license: item.manifest.license || 'Unknown',
- host_application: item.manifest.host_application || { min_version: '0.0.0' },
- homepage_url: item.manifest.homepage_url,
- repository_url: item.manifest.repository_url,
- keywords: item.manifest.keywords || [],
- categories: item.manifest.categories || [],
- default_locale: item.manifest.default_locale || 'zh-CN',
- locales_path: item.manifest.locales_path,
- },
+ manifest: normalizePluginManifest(item.manifest),
downloads: 0,
rating: 0,
review_count: 0,
diff --git a/dashboard/src/lib/plugin-api/types.ts b/dashboard/src/lib/plugin-api/types.ts
index 395bce0d..fe0148f8 100644
--- a/dashboard/src/lib/plugin-api/types.ts
+++ b/dashboard/src/lib/plugin-api/types.ts
@@ -44,6 +44,10 @@ export interface InstalledPlugin {
[key: string]: unknown // 允许其他字段
}
path: string
+ enabled?: boolean
+ disabled?: boolean
+ loaded?: boolean
+ load_status?: 'success' | 'failed' | 'inactive' | 'disabled' | 'unknown'
}
/**
* 旧版本插件格式(直接包含 version 字段)
diff --git a/dashboard/src/lib/prompt-api.ts b/dashboard/src/lib/prompt-api.ts
new file mode 100644
index 00000000..79da5248
--- /dev/null
+++ b/dashboard/src/lib/prompt-api.ts
@@ -0,0 +1,49 @@
+import { parseResponse } from '@/lib/api-helpers'
+import { fetchWithAuth } from '@/lib/fetch-with-auth'
+import type { ApiResponse } from '@/types/api'
+
+const API_BASE = '/api/webui/config/prompts'
+
+export interface PromptFileInfo {
+ name: string
+ size: number
+ modified_at: number
+}
+
+export interface PromptCatalog {
+ success: boolean
+ languages: string[]
+ files: Record
+}
+
+export interface PromptFileContent {
+ success: boolean
+ language: string
+ filename: string
+ content: string
+}
+
+export async function getPromptCatalog(): Promise> {
+ const response = await fetchWithAuth(API_BASE)
+ return parseResponse(response)
+}
+
+export async function getPromptFile(
+ language: string,
+ filename: string
+): Promise> {
+ const response = await fetchWithAuth(`${API_BASE}/${encodeURIComponent(language)}/${encodeURIComponent(filename)}`)
+ return parseResponse(response)
+}
+
+export async function updatePromptFile(
+ language: string,
+ filename: string,
+ content: string
+): Promise> {
+ const response = await fetchWithAuth(`${API_BASE}/${encodeURIComponent(language)}/${encodeURIComponent(filename)}`, {
+ method: 'PUT',
+ body: JSON.stringify({ content }),
+ })
+ return parseResponse(response)
+}
diff --git a/dashboard/src/lib/version.ts b/dashboard/src/lib/version.ts
index 8a261cfd..03625ffb 100644
--- a/dashboard/src/lib/version.ts
+++ b/dashboard/src/lib/version.ts
@@ -5,7 +5,7 @@
* 修改此处的版本号后,所有展示版本的地方都会自动更新
*/
-export const APP_VERSION = '1.0.2'
+export const APP_VERSION = '1.0.3'
export const APP_NAME = 'MaiBot Dashboard'
export const APP_FULL_NAME = `${APP_NAME} v${APP_VERSION}`
diff --git a/dashboard/src/router.tsx b/dashboard/src/router.tsx
index ef480e6a..34cfc454 100644
--- a/dashboard/src/router.tsx
+++ b/dashboard/src/router.tsx
@@ -86,6 +86,12 @@ const modelConfigRoute = createRoute({
})
// 配置路由 - 麦麦适配器配置(已停用,引导跳转到插件配置;旧实现保留在 ./routes/config/adapter)
+const promptManagementRoute = createRoute({
+ getParentRoute: () => protectedRoute,
+ path: '/config/prompts',
+ component: lazyRouteComponent(() => import('./routes/config/prompts'), 'PromptManagementPage'),
+})
+
const adapterConfigRoute = createRoute({
getParentRoute: () => protectedRoute,
path: '/config/adapter',
@@ -206,6 +212,12 @@ const pluginMirrorsRoute = createRoute({
})
// 设置页路由
+const mcpSettingsRoute = createRoute({
+ getParentRoute: () => protectedRoute,
+ path: '/mcp-settings',
+ component: lazyRouteComponent(() => import('./routes/mcp-settings'), 'MCPSettingsPage'),
+})
+
const settingsRoute = createRoute({
getParentRoute: () => protectedRoute,
path: '/settings',
@@ -262,6 +274,7 @@ const routeTree = rootRoute.addChildren([
botConfigRoute,
modelProviderConfigRoute,
modelConfigRoute,
+ promptManagementRoute,
adapterConfigRoute,
emojiManagementRoute,
expressionManagementRoute,
@@ -274,6 +287,7 @@ const routeTree = rootRoute.addChildren([
modelPresetsRoute,
pluginConfigRoute,
pluginMirrorsRoute,
+ mcpSettingsRoute,
logsRoute,
plannerMonitorRoute,
chatRoute,
diff --git a/dashboard/src/routes/config/bot.tsx b/dashboard/src/routes/config/bot.tsx
index 6263e2ef..08c0bf5a 100644
--- a/dashboard/src/routes/config/bot.tsx
+++ b/dashboard/src/routes/config/bot.tsx
@@ -29,7 +29,6 @@ import { Code2, Info, Layout, Power, Save } from 'lucide-react'
import type { ConfigSchema } from '@/types/config-schema'
import {
ChatTalkValueRulesHook,
- ExperimentalChatPromptsHook,
ExpressionGroupsHook,
ExpressionLearningListHook,
KeywordRulesHook,
@@ -53,11 +52,9 @@ const TAB_ORDER = [
'expression',
'emoji',
'response_post_process',
- 'lpmm_knowledge',
'webui',
- 'maisaka',
'plugin_runtime',
- 'debug',
+ 'log',
]
// ==================== Tab 分组类型与构建 ====================
@@ -156,23 +153,21 @@ function BotConfigPageContent() {
const [expressionConfig, setExpressionConfig] = useState(null)
const [emojiConfig, setEmojiConfig] = useState(null)
const [memoryConfig, setMemoryConfig] = useState(null)
- const [relationshipConfig, setRelationshipConfig] = useState(null)
+ const [visualConfig, setVisualConfig] = useState(null)
const [voiceConfig, setVoiceConfig] = useState(null)
const [messageReceiveConfig, setMessageReceiveConfig] = useState(null)
- const [lpmmConfig, setLpmmConfig] = useState(null)
const [keywordReactionConfig, setKeywordReactionConfig] = useState(null)
const [responsePostProcessConfig, setResponsePostProcessConfig] = useState(null)
const [chineseTypoConfig, setChineseTypoConfig] = useState(null)
const [responseSplitterConfig, setResponseSplitterConfig] = useState(null)
const [debugConfig, setDebugConfig] = useState(null)
- const [experimentalConfig, setExperimentalConfig] = useState(null)
const [maimMessageConfig, setMaimMessageConfig] = useState(null)
const [telemetryConfig, setTelemetryConfig] = useState(null)
const [webuiConfig, setWebuiConfig] = useState(null)
const [databaseConfig, setDatabaseConfig] = useState(null)
- const [maisakaConfig, setMaisakaConfig] = useState(null)
const [mcpConfig, setMcpConfig] = useState(null)
const [pluginRuntimeConfig, setPluginRuntimeConfig] = useState(null)
+ const [aMemorixConfig, setAMemorixConfig] = useState(null)
// Schema 状态(用于动态 tab 分组)
const [configSchema, setConfigSchema] = useState(null)
@@ -253,23 +248,21 @@ function BotConfigPageContent() {
setExpressionConfig((config.expression ?? {}) as ConfigSectionData)
setEmojiConfig((config.emoji ?? {}) as ConfigSectionData)
setMemoryConfig((config.memory ?? {}) as ConfigSectionData)
- setRelationshipConfig((config.relationship ?? {}) as ConfigSectionData)
+ setVisualConfig((config.visual ?? {}) as ConfigSectionData)
setVoiceConfig((config.voice ?? {}) as ConfigSectionData)
setMessageReceiveConfig((config.message_receive ?? {}) as ConfigSectionData)
- setLpmmConfig((config.lpmm_knowledge ?? {}) as ConfigSectionData)
setKeywordReactionConfig((config.keyword_reaction ?? {}) as ConfigSectionData)
setResponsePostProcessConfig((config.response_post_process ?? {}) as ConfigSectionData)
setChineseTypoConfig((config.chinese_typo ?? {}) as ConfigSectionData)
setResponseSplitterConfig((config.response_splitter ?? {}) as ConfigSectionData)
setDebugConfig((config.debug ?? {}) as ConfigSectionData)
- setExperimentalConfig((config.experimental ?? {}) as ConfigSectionData)
setMaimMessageConfig((config.maim_message ?? {}) as ConfigSectionData)
setTelemetryConfig((config.telemetry ?? {}) as ConfigSectionData)
setWebuiConfig((config.webui ?? {}) as ConfigSectionData)
setDatabaseConfig((config.database ?? {}) as ConfigSectionData)
- setMaisakaConfig((config.maisaka ?? {}) as ConfigSectionData)
setMcpConfig((config.mcp ?? {}) as ConfigSectionData)
setPluginRuntimeConfig((config.plugin_runtime ?? {}) as ConfigSectionData)
+ setAMemorixConfig((config.a_memorix ?? {}) as ConfigSectionData)
}, [])
/**
@@ -285,23 +278,21 @@ function BotConfigPageContent() {
expression: expressionConfig,
emoji: emojiConfig,
memory: memoryConfig,
- relationship: relationshipConfig,
+ visual: visualConfig,
voice: voiceConfig,
message_receive: messageReceiveConfig,
- lpmm_knowledge: lpmmConfig,
keyword_reaction: keywordReactionConfig,
response_post_process: responsePostProcessConfig,
chinese_typo: chineseTypoConfig,
response_splitter: responseSplitterConfig,
debug: debugConfig,
- experimental: experimentalConfig,
maim_message: maimMessageConfig,
telemetry: telemetryConfig,
webui: webuiConfig,
database: databaseConfig,
- maisaka: maisakaConfig,
mcp: mcpConfig,
plugin_runtime: pluginRuntimeConfig,
+ a_memorix: aMemorixConfig,
}
}, [
botConfig,
@@ -310,23 +301,21 @@ function BotConfigPageContent() {
expressionConfig,
emojiConfig,
memoryConfig,
- relationshipConfig,
+ visualConfig,
voiceConfig,
messageReceiveConfig,
- lpmmConfig,
keywordReactionConfig,
responsePostProcessConfig,
chineseTypoConfig,
responseSplitterConfig,
debugConfig,
- experimentalConfig,
maimMessageConfig,
telemetryConfig,
webuiConfig,
databaseConfig,
- maisakaConfig,
mcpConfig,
pluginRuntimeConfig,
+ aMemorixConfig,
])
// 加载源代码
@@ -406,7 +395,6 @@ function BotConfigPageContent() {
useEffect(() => {
const hookEntries = [
['chat.talk_value_rules', ChatTalkValueRulesHook],
- ['experimental.chat_prompts', ExperimentalChatPromptsHook],
['expression.expression_groups', ExpressionGroupsHook],
['expression.learning_list', ExpressionLearningListHook],
['keyword_reaction.keyword_rules', KeywordRulesHook],
@@ -442,23 +430,21 @@ function BotConfigPageContent() {
useConfigAutoSave(expressionConfig, 'expression', initialLoadRef.current, triggerAutoSave)
useConfigAutoSave(emojiConfig, 'emoji', initialLoadRef.current, triggerAutoSave)
useConfigAutoSave(memoryConfig, 'memory', initialLoadRef.current, triggerAutoSave)
- useConfigAutoSave(relationshipConfig, 'relationship', initialLoadRef.current, triggerAutoSave)
+ useConfigAutoSave(visualConfig, 'visual', initialLoadRef.current, triggerAutoSave)
useConfigAutoSave(voiceConfig, 'voice', initialLoadRef.current, triggerAutoSave)
useConfigAutoSave(messageReceiveConfig, 'message_receive', initialLoadRef.current, triggerAutoSave)
- useConfigAutoSave(lpmmConfig, 'lpmm_knowledge', initialLoadRef.current, triggerAutoSave)
useConfigAutoSave(keywordReactionConfig, 'keyword_reaction', initialLoadRef.current, triggerAutoSave)
useConfigAutoSave(responsePostProcessConfig, 'response_post_process', initialLoadRef.current, triggerAutoSave)
useConfigAutoSave(chineseTypoConfig, 'chinese_typo', initialLoadRef.current, triggerAutoSave)
useConfigAutoSave(responseSplitterConfig, 'response_splitter', initialLoadRef.current, triggerAutoSave)
useConfigAutoSave(debugConfig, 'debug', initialLoadRef.current, triggerAutoSave)
- useConfigAutoSave(experimentalConfig, 'experimental', initialLoadRef.current, triggerAutoSave)
useConfigAutoSave(maimMessageConfig, 'maim_message', initialLoadRef.current, triggerAutoSave)
useConfigAutoSave(telemetryConfig, 'telemetry', initialLoadRef.current, triggerAutoSave)
useConfigAutoSave(webuiConfig, 'webui', initialLoadRef.current, triggerAutoSave)
useConfigAutoSave(databaseConfig, 'database', initialLoadRef.current, triggerAutoSave)
- useConfigAutoSave(maisakaConfig, 'maisaka', initialLoadRef.current, triggerAutoSave)
useConfigAutoSave(mcpConfig, 'mcp', initialLoadRef.current, triggerAutoSave)
useConfigAutoSave(pluginRuntimeConfig, 'plugin_runtime', initialLoadRef.current, triggerAutoSave)
+ useConfigAutoSave(aMemorixConfig, 'a_memorix', initialLoadRef.current, triggerAutoSave)
// 保存源代码
const saveSourceCode = async () => {
@@ -657,23 +643,21 @@ function BotConfigPageContent() {
expression: expressionConfig,
emoji: emojiConfig,
memory: memoryConfig,
- relationship: relationshipConfig,
+ visual: visualConfig,
voice: voiceConfig,
message_receive: messageReceiveConfig,
- lpmm_knowledge: lpmmConfig,
keyword_reaction: keywordReactionConfig,
response_post_process: responsePostProcessConfig,
chinese_typo: chineseTypoConfig,
response_splitter: responseSplitterConfig,
debug: debugConfig,
- experimental: experimentalConfig,
maim_message: maimMessageConfig,
telemetry: telemetryConfig,
webui: webuiConfig,
database: databaseConfig,
- maisaka: maisakaConfig,
mcp: mcpConfig,
plugin_runtime: pluginRuntimeConfig,
+ a_memorix: aMemorixConfig,
}),
[
botConfig,
@@ -682,23 +666,21 @@ function BotConfigPageContent() {
expressionConfig,
emojiConfig,
memoryConfig,
- relationshipConfig,
+ visualConfig,
voiceConfig,
messageReceiveConfig,
- lpmmConfig,
keywordReactionConfig,
responsePostProcessConfig,
chineseTypoConfig,
responseSplitterConfig,
debugConfig,
- experimentalConfig,
maimMessageConfig,
telemetryConfig,
webuiConfig,
databaseConfig,
- maisakaConfig,
mcpConfig,
pluginRuntimeConfig,
+ aMemorixConfig,
]
)
@@ -710,23 +692,21 @@ function BotConfigPageContent() {
expression: setExpressionConfig,
emoji: setEmojiConfig,
memory: setMemoryConfig,
- relationship: setRelationshipConfig,
+ visual: setVisualConfig,
voice: setVoiceConfig,
message_receive: setMessageReceiveConfig,
- lpmm_knowledge: setLpmmConfig,
keyword_reaction: setKeywordReactionConfig,
response_post_process: setResponsePostProcessConfig,
chinese_typo: setChineseTypoConfig,
response_splitter: setResponseSplitterConfig,
debug: setDebugConfig,
- experimental: setExperimentalConfig,
maim_message: setMaimMessageConfig,
telemetry: setTelemetryConfig,
webui: setWebuiConfig,
database: setDatabaseConfig,
- maisaka: setMaisakaConfig,
mcp: setMcpConfig,
plugin_runtime: setPluginRuntimeConfig,
+ a_memorix: setAMemorixConfig,
}
sectionSetterMap[sectionName]?.(value)
diff --git a/dashboard/src/routes/config/bot/hooks/complexFieldHooks.tsx b/dashboard/src/routes/config/bot/hooks/complexFieldHooks.tsx
index a39e5cb4..2bb2f111 100644
--- a/dashboard/src/routes/config/bot/hooks/complexFieldHooks.tsx
+++ b/dashboard/src/routes/config/bot/hooks/complexFieldHooks.tsx
@@ -101,12 +101,6 @@ export const ExpressionGroupsHook = createJsonFieldHook({
placeholder: '[\n {\n "expression_groups": [\n {\n "platform": "qq",\n "item_id": "123456",\n "rule_type": "group"\n }\n ]\n }\n]',
})
-export const ExperimentalChatPromptsHook = createJsonFieldHook({
- emptyValue: [],
- helperText: '实验配置中的定向 Prompt 列表使用 JSON 编辑。每一项应包含 platform、item_id、rule_type、prompt。',
- placeholder: '[\n {\n "platform": "qq",\n "item_id": "123456",\n "rule_type": "group",\n "prompt": "这里填写额外提示词"\n }\n]',
-})
-
export const MCPRootItemsHook = createJsonFieldHook({
emptyValue: [],
helperText: 'MCP Roots 条目为对象数组,使用 JSON 编辑。',
diff --git a/dashboard/src/routes/config/bot/hooks/index.ts b/dashboard/src/routes/config/bot/hooks/index.ts
index c4988b1e..a5120209 100644
--- a/dashboard/src/routes/config/bot/hooks/index.ts
+++ b/dashboard/src/routes/config/bot/hooks/index.ts
@@ -12,7 +12,6 @@ export type {
} from './useAutoSave'
export {
ChatTalkValueRulesHook,
- ExperimentalChatPromptsHook,
ExpressionGroupsHook,
ExpressionLearningListHook,
KeywordRulesHook,
diff --git a/dashboard/src/routes/config/bot/sections/ExperimentalSection.tsx b/dashboard/src/routes/config/bot/sections/ExperimentalSection.tsx
deleted file mode 100644
index 5f86d821..00000000
--- a/dashboard/src/routes/config/bot/sections/ExperimentalSection.tsx
+++ /dev/null
@@ -1,311 +0,0 @@
-import React from 'react'
-import { Label } from '@/components/ui/label'
-import { Textarea } from '@/components/ui/textarea'
-import { Input } from '@/components/ui/input'
-import { Button } from '@/components/ui/button'
-import { Switch } from '@/components/ui/switch'
-import {
- Select,
- SelectContent,
- SelectItem,
- SelectTrigger,
- SelectValue,
-} from '@/components/ui/select'
-import {
- AlertDialog,
- AlertDialogAction,
- AlertDialogCancel,
- AlertDialogContent,
- AlertDialogDescription,
- AlertDialogFooter,
- AlertDialogHeader,
- AlertDialogTitle,
- AlertDialogTrigger,
-} from '@/components/ui/alert-dialog'
-import {
- Popover,
- PopoverContent,
- PopoverTrigger,
-} from '@/components/ui/popover'
-import { Plus, Trash2, AlertTriangle, Eye, Code2 } from 'lucide-react'
-import type { ExperimentalConfig } from '../types'
-
-interface ChatPromptData {
- platform: string
- id: string
- type: 'group' | 'private'
- prompt: string
-}
-
-interface ExperimentalSectionProps {
- config: ExperimentalConfig
- onChange: (config: ExperimentalConfig) => void
-}
-
-export const ExperimentalSection = React.memo(function ExperimentalSection({ config, onChange }: ExperimentalSectionProps) {
- // 解析 chat_prompt 字符串为结构化数据
- const parseChatPrompt = (promptStr: string): ChatPromptData => {
- const parts = promptStr.split(':')
- if (parts.length >= 4) {
- const platform = parts[0]
- const id = parts[1]
- const type = parts[2] as 'group' | 'private'
- const prompt = parts.slice(3).join(':') // 处理 prompt 中可能包含的冒号
- return { platform, id, type, prompt }
- }
- return { platform: 'qq', id: '', type: 'group', prompt: '' }
- }
-
- // 将结构化数据转换为字符串
- const stringifyChatPrompt = (data: ChatPromptData): string => {
- return `${data.platform}:${data.id}:${data.type}:${data.prompt}`
- }
-
- const addChatPrompt = () => {
- onChange({ ...config, chat_prompts: [...config.chat_prompts, 'qq::group:'] })
- }
-
- const removeChatPrompt = (index: number) => {
- onChange({
- ...config,
- chat_prompts: config.chat_prompts.filter((_, i) => i !== index),
- })
- }
-
- const updateChatPrompt = (index: number, data: Partial) => {
- const currentData = parseChatPrompt(config.chat_prompts[index])
- const newData = { ...currentData, ...data }
- const newPrompts = [...config.chat_prompts]
- newPrompts[index] = stringifyChatPrompt(newData)
- onChange({ ...config, chat_prompts: newPrompts })
- }
-
- // 预览组件
- const ChatPromptPreview = ({ promptStr }: { promptStr: string }) => {
- return (
-
-
-
-
-
-
-
配置预览
-
- "{promptStr}"
-
-
- 这是保存到 bot_config.toml 文件中的格式
-
-
-
-
- )
- }
-
- return (
-
-
-
-
-
实验性功能
-
- 此部分包含实验性功能,可能不稳定或在未来版本中发生变化。请谨慎使用,并注意不推荐在生产环境中修改私聊规则。
-
-
-
-
-
-
实验性设置
-
-
-
-
- onChange({ ...config, lpmm_memory: checked })
- }
- />
-
-
-
- 开启后,chat_history_summarizer 总结出的历史记录会同时导入到知识库
-
-
-
-
-
-
-
-
-
- 为指定聊天添加额外的 prompt,用于定制特定场景的对话行为
-
-
-
-
-
-
- {config.chat_prompts.map((promptStr, index) => {
- const data = parseChatPrompt(promptStr)
-
- return (
-
-
-
- Prompt 配置 {index + 1}
-
-
-
-
-
-
-
-
-
- 确认删除
-
- 确定要删除这个 prompt 配置吗?此操作无法撤销。
-
-
-
- 取消
- removeChatPrompt(index)}>
- 删除
-
-
-
-
-
-
-
-
- {/* 平台选择 */}
-
-
-
-
-
- {/* ID 输入 */}
-
-
- updateChatPrompt(index, { id: e.target.value })}
- placeholder={data.type === 'group' ? '输入群号' : '输入用户ID'}
- className="font-mono"
- />
-
-
- {/* 类型选择 */}
-
-
-
-
-
- {/* Prompt 内容 */}
-
-
- {/* 原始格式显示 */}
-
-
-
- 原始格式
-
-
- {promptStr || '(未配置)'}
-
-
-
-
- )
- })}
-
- {config.chat_prompts.length === 0 && (
-
-
暂无特定聊天 prompt 配置
-
点击上方"添加配置"按钮创建新配置
-
- )}
-
-
- {/* 使用说明 */}
-
-
💡 使用说明
-
- - 为不同的聊天环境配置专属的行为提示
- - 支持多个平台:QQ、微信、WebUI
- - 可为群聊或私聊分别配置
- - Prompt 会自动注入到该聊天的上下文中
-
-
📝 配置示例
-
- - 摄影群:
这是一个摄影群,你精通摄影知识
- - 二次元群:
这是一个二次元交流群
- - 好友私聊:
这是你与好朋友的私聊
-
-
-
-
-
-
- )
-})
diff --git a/dashboard/src/routes/config/bot/sections/ExpressionSection.tsx b/dashboard/src/routes/config/bot/sections/ExpressionSection.tsx
index fd31e05a..864cb4be 100644
--- a/dashboard/src/routes/config/bot/sections/ExpressionSection.tsx
+++ b/dashboard/src/routes/config/bot/sections/ExpressionSection.tsx
@@ -590,16 +590,16 @@ export const ExpressionSection = React.memo(function ExpressionSection({
id="expression_auto_check_interval"
type="number"
min="60"
- value={config.expression_auto_check_interval ?? 3600}
+ value={config.expression_auto_check_interval ?? 900}
onChange={(e) =>
onChange({
...config,
- expression_auto_check_interval: parseInt(e.target.value) || 3600,
+ expression_auto_check_interval: parseInt(e.target.value) || 900,
})
}
/>
- 表达方式自动检查的间隔时间(单位:秒),默认值:3600秒(1小时)
+ 表达方式自动检查的间隔时间(单位:秒),默认值:900秒(15分钟)
@@ -613,16 +613,16 @@ export const ExpressionSection = React.memo(function ExpressionSection({
type="number"
min="1"
max="100"
- value={config.expression_auto_check_count ?? 10}
+ value={config.expression_auto_check_count ?? 5}
onChange={(e) =>
onChange({
...config,
- expression_auto_check_count: parseInt(e.target.value) || 10,
+ expression_auto_check_count: parseInt(e.target.value) || 5,
})
}
/>
- 每次自动检查时随机选取的表达方式数量,默认值:10条
+ 每次自动检查时随机选取的表达方式数量,默认值:5条