Compare commits

...

1 Commits

Author SHA1 Message Date
rdmclin2 ee996f702a fix: manual tool disabled 2026-03-24 14:48:35 +08:00
73 changed files with 724 additions and 305 deletions
+1 -1
View File
@@ -88,7 +88,7 @@ async function createTestAgent(title: string = 'Test Agent'): Promise<string> {
// Given Steps
// ============================================
Given('用户在 Home 页面有一个 Agent', async function (this: CustomWorld) {
Given('用户在 Home 页面有一个 Agent', { timeout: 30_000 }, async function (this: CustomWorld) {
console.log(' 📍 Step: 在数据库中创建测试 Agent...');
const agentId = await createTestAgent('E2E Test Agent');
this.testContext.createdAgentId = agentId;
+1 -1
View File
@@ -1,6 +1,7 @@
{
"arguments.moreParams": "إجمالي {{count}} من المعاملات",
"arguments.title": "المعلمات",
"builtins.lobe-activator.apiName.activateTools": "تفعيل الأدوات",
"builtins.lobe-agent-builder.apiName.getAvailableModels": "الحصول على النماذج المتاحة",
"builtins.lobe-agent-builder.apiName.getAvailableTools": "الحصول على المهارات المتاحة",
"builtins.lobe-agent-builder.apiName.getConfig": "الحصول على الإعدادات",
@@ -201,7 +202,6 @@
"builtins.lobe-skills.apiName.runCommand": "تشغيل الأمر",
"builtins.lobe-skills.apiName.searchSkill": "البحث عن المهارات",
"builtins.lobe-skills.title": "المهارات",
"builtins.lobe-tools.apiName.activateTools": "تفعيل الأدوات",
"builtins.lobe-topic-reference.apiName.getTopicContext": "الحصول على سياق الموضوع",
"builtins.lobe-topic-reference.title": "مرجع الموضوع",
"builtins.lobe-user-memory.apiName.addContextMemory": "إضافة ذاكرة السياق",
+1 -1
View File
@@ -1,6 +1,7 @@
{
"arguments.moreParams": "{{count}} параметъра общо",
"arguments.title": "Аргументи",
"builtins.lobe-activator.apiName.activateTools": "Активиране на инструменти",
"builtins.lobe-agent-builder.apiName.getAvailableModels": "Извличане на налични модели",
"builtins.lobe-agent-builder.apiName.getAvailableTools": "Извличане на налични умения",
"builtins.lobe-agent-builder.apiName.getConfig": "Извличане на конфигурация",
@@ -201,7 +202,6 @@
"builtins.lobe-skills.apiName.runCommand": "Изпълни команда",
"builtins.lobe-skills.apiName.searchSkill": "Търсене на умения",
"builtins.lobe-skills.title": "Умения",
"builtins.lobe-tools.apiName.activateTools": "Активиране на инструменти",
"builtins.lobe-topic-reference.apiName.getTopicContext": "Вземи контекста на темата",
"builtins.lobe-topic-reference.title": "Препратка към тема",
"builtins.lobe-user-memory.apiName.addContextMemory": "Добавяне на контекстна памет",
+1 -1
View File
@@ -1,6 +1,7 @@
{
"arguments.moreParams": "{{count}} Parameter insgesamt",
"arguments.title": "Argumente",
"builtins.lobe-activator.apiName.activateTools": "Werkzeuge aktivieren",
"builtins.lobe-agent-builder.apiName.getAvailableModels": "Verfügbare Modelle abrufen",
"builtins.lobe-agent-builder.apiName.getAvailableTools": "Verfügbare Skills abrufen",
"builtins.lobe-agent-builder.apiName.getConfig": "Konfiguration abrufen",
@@ -201,7 +202,6 @@
"builtins.lobe-skills.apiName.runCommand": "Befehl ausführen",
"builtins.lobe-skills.apiName.searchSkill": "Fähigkeiten suchen",
"builtins.lobe-skills.title": "Fähigkeiten",
"builtins.lobe-tools.apiName.activateTools": "Werkzeuge aktivieren",
"builtins.lobe-topic-reference.apiName.getTopicContext": "Themenkontext abrufen",
"builtins.lobe-topic-reference.title": "Themenreferenz",
"builtins.lobe-user-memory.apiName.addContextMemory": "Kontextgedächtnis hinzufügen",
+1 -1
View File
@@ -1,6 +1,7 @@
{
"arguments.moreParams": "{{count}} params in total",
"arguments.title": "Arguments",
"builtins.lobe-activator.apiName.activateTools": "Activate Tools",
"builtins.lobe-agent-builder.apiName.getAvailableModels": "Get available models",
"builtins.lobe-agent-builder.apiName.getAvailableTools": "Get available Skills",
"builtins.lobe-agent-builder.apiName.getConfig": "Get config",
@@ -201,7 +202,6 @@
"builtins.lobe-skills.apiName.runCommand": "Run Command",
"builtins.lobe-skills.apiName.searchSkill": "Search Skills",
"builtins.lobe-skills.title": "Skills",
"builtins.lobe-tools.apiName.activateTools": "Activate Tools",
"builtins.lobe-topic-reference.apiName.getTopicContext": "Get Topic Context",
"builtins.lobe-topic-reference.title": "Topic Reference",
"builtins.lobe-user-memory.apiName.addContextMemory": "Add context memory",
+1 -1
View File
@@ -1,6 +1,7 @@
{
"arguments.moreParams": "{{count}} parámetros en total",
"arguments.title": "Argumentos",
"builtins.lobe-activator.apiName.activateTools": "Activar Herramientas",
"builtins.lobe-agent-builder.apiName.getAvailableModels": "Obtener modelos disponibles",
"builtins.lobe-agent-builder.apiName.getAvailableTools": "Obtener habilidades disponibles",
"builtins.lobe-agent-builder.apiName.getConfig": "Obtener configuración",
@@ -201,7 +202,6 @@
"builtins.lobe-skills.apiName.runCommand": "Ejecutar Comando",
"builtins.lobe-skills.apiName.searchSkill": "Buscar Habilidades",
"builtins.lobe-skills.title": "Habilidades",
"builtins.lobe-tools.apiName.activateTools": "Activar Herramientas",
"builtins.lobe-topic-reference.apiName.getTopicContext": "Obtener contexto del tema",
"builtins.lobe-topic-reference.title": "Referencia de tema",
"builtins.lobe-user-memory.apiName.addContextMemory": "Agregar memoria de contexto",
+1 -1
View File
@@ -1,6 +1,7 @@
{
"arguments.moreParams": "{{count}} پارامتر در مجموع",
"arguments.title": "آرگومان‌ها",
"builtins.lobe-activator.apiName.activateTools": "فعال کردن ابزارها",
"builtins.lobe-agent-builder.apiName.getAvailableModels": "دریافت مدل‌های موجود",
"builtins.lobe-agent-builder.apiName.getAvailableTools": "دریافت مهارت‌های موجود",
"builtins.lobe-agent-builder.apiName.getConfig": "دریافت پیکربندی",
@@ -201,7 +202,6 @@
"builtins.lobe-skills.apiName.runCommand": "اجرای فرمان",
"builtins.lobe-skills.apiName.searchSkill": "جستجوی مهارت‌ها",
"builtins.lobe-skills.title": "مهارت‌ها",
"builtins.lobe-tools.apiName.activateTools": "فعال کردن ابزارها",
"builtins.lobe-topic-reference.apiName.getTopicContext": "دریافت زمینه موضوع",
"builtins.lobe-topic-reference.title": "ارجاع به موضوع",
"builtins.lobe-user-memory.apiName.addContextMemory": "افزودن حافظه زمینه",
+1 -1
View File
@@ -1,6 +1,7 @@
{
"arguments.moreParams": "{{count}} paramètres au total",
"arguments.title": "Arguments",
"builtins.lobe-activator.apiName.activateTools": "Activer les Outils",
"builtins.lobe-agent-builder.apiName.getAvailableModels": "Obtenir les modèles disponibles",
"builtins.lobe-agent-builder.apiName.getAvailableTools": "Obtenir les Compétences disponibles",
"builtins.lobe-agent-builder.apiName.getConfig": "Obtenir la configuration",
@@ -201,7 +202,6 @@
"builtins.lobe-skills.apiName.runCommand": "Exécuter la commande",
"builtins.lobe-skills.apiName.searchSkill": "Rechercher des Compétences",
"builtins.lobe-skills.title": "Compétences",
"builtins.lobe-tools.apiName.activateTools": "Activer les Outils",
"builtins.lobe-topic-reference.apiName.getTopicContext": "Obtenir le contexte du sujet",
"builtins.lobe-topic-reference.title": "Référence de sujet",
"builtins.lobe-user-memory.apiName.addContextMemory": "Ajouter une mémoire de contexte",
+1 -1
View File
@@ -1,6 +1,7 @@
{
"arguments.moreParams": "{{count}} parametri in totale",
"arguments.title": "Argomenti",
"builtins.lobe-activator.apiName.activateTools": "Attiva Strumenti",
"builtins.lobe-agent-builder.apiName.getAvailableModels": "Ottieni modelli disponibili",
"builtins.lobe-agent-builder.apiName.getAvailableTools": "Ottieni Competenze disponibili",
"builtins.lobe-agent-builder.apiName.getConfig": "Ottieni configurazione",
@@ -201,7 +202,6 @@
"builtins.lobe-skills.apiName.runCommand": "Esegui Comando",
"builtins.lobe-skills.apiName.searchSkill": "Cerca Abilità",
"builtins.lobe-skills.title": "Abilità",
"builtins.lobe-tools.apiName.activateTools": "Attiva Strumenti",
"builtins.lobe-topic-reference.apiName.getTopicContext": "Ottieni contesto dell'argomento",
"builtins.lobe-topic-reference.title": "Riferimento argomento",
"builtins.lobe-user-memory.apiName.addContextMemory": "Aggiungi memoria contestuale",
+1 -1
View File
@@ -1,6 +1,7 @@
{
"arguments.moreParams": "合計で{{count}}個のパラメーターがあります",
"arguments.title": "パラメーター一覧",
"builtins.lobe-activator.apiName.activateTools": "ツールをアクティブ化",
"builtins.lobe-agent-builder.apiName.getAvailableModels": "利用可能なモデルを取得",
"builtins.lobe-agent-builder.apiName.getAvailableTools": "利用可能なツールを取得",
"builtins.lobe-agent-builder.apiName.getConfig": "設定を取得",
@@ -201,7 +202,6 @@
"builtins.lobe-skills.apiName.runCommand": "コマンドを実行",
"builtins.lobe-skills.apiName.searchSkill": "スキルを検索",
"builtins.lobe-skills.title": "スキル",
"builtins.lobe-tools.apiName.activateTools": "ツールをアクティブ化",
"builtins.lobe-topic-reference.apiName.getTopicContext": "トピックコンテキストを取得",
"builtins.lobe-topic-reference.title": "トピック参照",
"builtins.lobe-user-memory.apiName.addContextMemory": "コンテキスト記憶を追加",
+1 -1
View File
@@ -1,6 +1,7 @@
{
"arguments.moreParams": "총 {{count}}개의 매개변수가 있습니다",
"arguments.title": "매개변수 목록",
"builtins.lobe-activator.apiName.activateTools": "도구 활성화",
"builtins.lobe-agent-builder.apiName.getAvailableModels": "사용 가능한 모델 가져오기",
"builtins.lobe-agent-builder.apiName.getAvailableTools": "사용 가능한 도구 가져오기",
"builtins.lobe-agent-builder.apiName.getConfig": "설정 가져오기",
@@ -201,7 +202,6 @@
"builtins.lobe-skills.apiName.runCommand": "명령 실행",
"builtins.lobe-skills.apiName.searchSkill": "스킬 검색",
"builtins.lobe-skills.title": "스킬",
"builtins.lobe-tools.apiName.activateTools": "도구 활성화",
"builtins.lobe-topic-reference.apiName.getTopicContext": "토픽 컨텍스트 가져오기",
"builtins.lobe-topic-reference.title": "토픽 참조",
"builtins.lobe-user-memory.apiName.addContextMemory": "상황 기억 추가",
+1 -1
View File
@@ -1,6 +1,7 @@
{
"arguments.moreParams": "{{count}} parameters in totaal",
"arguments.title": "Argumenten",
"builtins.lobe-activator.apiName.activateTools": "Hulpmiddelen Activeren",
"builtins.lobe-agent-builder.apiName.getAvailableModels": "Beschikbare modellen ophalen",
"builtins.lobe-agent-builder.apiName.getAvailableTools": "Beschikbare Skills ophalen",
"builtins.lobe-agent-builder.apiName.getConfig": "Configuratie ophalen",
@@ -201,7 +202,6 @@
"builtins.lobe-skills.apiName.runCommand": "Voer Commando Uit",
"builtins.lobe-skills.apiName.searchSkill": "Vaardigheden Zoeken",
"builtins.lobe-skills.title": "Vaardigheden",
"builtins.lobe-tools.apiName.activateTools": "Hulpmiddelen Activeren",
"builtins.lobe-topic-reference.apiName.getTopicContext": "Onderwerpcontext ophalen",
"builtins.lobe-topic-reference.title": "Onderwerpverwijzing",
"builtins.lobe-user-memory.apiName.addContextMemory": "Contextgeheugen toevoegen",
+1 -1
View File
@@ -1,6 +1,7 @@
{
"arguments.moreParams": "Łącznie {{count}} parametrów",
"arguments.title": "Argumenty",
"builtins.lobe-activator.apiName.activateTools": "Aktywuj Narzędzia",
"builtins.lobe-agent-builder.apiName.getAvailableModels": "Pobierz dostępne modele",
"builtins.lobe-agent-builder.apiName.getAvailableTools": "Pobierz dostępne Umiejętności",
"builtins.lobe-agent-builder.apiName.getConfig": "Pobierz konfigurację",
@@ -201,7 +202,6 @@
"builtins.lobe-skills.apiName.runCommand": "Uruchom Polecenie",
"builtins.lobe-skills.apiName.searchSkill": "Wyszukaj Umiejętności",
"builtins.lobe-skills.title": "Umiejętności",
"builtins.lobe-tools.apiName.activateTools": "Aktywuj Narzędzia",
"builtins.lobe-topic-reference.apiName.getTopicContext": "Pobierz kontekst tematu",
"builtins.lobe-topic-reference.title": "Odwołanie do tematu",
"builtins.lobe-user-memory.apiName.addContextMemory": "Dodaj pamięć kontekstu",
+1 -1
View File
@@ -1,6 +1,7 @@
{
"arguments.moreParams": "{{count}} parâmetros no total",
"arguments.title": "Argumentos",
"builtins.lobe-activator.apiName.activateTools": "Ativar Ferramentas",
"builtins.lobe-agent-builder.apiName.getAvailableModels": "Obter modelos disponíveis",
"builtins.lobe-agent-builder.apiName.getAvailableTools": "Obter Habilidades disponíveis",
"builtins.lobe-agent-builder.apiName.getConfig": "Obter configuração",
@@ -201,7 +202,6 @@
"builtins.lobe-skills.apiName.runCommand": "Executar Comando",
"builtins.lobe-skills.apiName.searchSkill": "Buscar Habilidades",
"builtins.lobe-skills.title": "Habilidades",
"builtins.lobe-tools.apiName.activateTools": "Ativar Ferramentas",
"builtins.lobe-topic-reference.apiName.getTopicContext": "Obter contexto do tópico",
"builtins.lobe-topic-reference.title": "Referência de tópico",
"builtins.lobe-user-memory.apiName.addContextMemory": "Adicionar memória de contexto",
+1 -1
View File
@@ -1,6 +1,7 @@
{
"arguments.moreParams": "Всего параметров: {{count}}",
"arguments.title": "Аргументы",
"builtins.lobe-activator.apiName.activateTools": "Активировать инструменты",
"builtins.lobe-agent-builder.apiName.getAvailableModels": "Получить доступные модели",
"builtins.lobe-agent-builder.apiName.getAvailableTools": "Получить доступные навыки",
"builtins.lobe-agent-builder.apiName.getConfig": "Получить конфигурацию",
@@ -201,7 +202,6 @@
"builtins.lobe-skills.apiName.runCommand": "Выполнить команду",
"builtins.lobe-skills.apiName.searchSkill": "Поиск навыков",
"builtins.lobe-skills.title": "Навыки",
"builtins.lobe-tools.apiName.activateTools": "Активировать инструменты",
"builtins.lobe-topic-reference.apiName.getTopicContext": "Получить контекст темы",
"builtins.lobe-topic-reference.title": "Ссылка на тему",
"builtins.lobe-user-memory.apiName.addContextMemory": "Добавить контекстную память",
+1 -1
View File
@@ -1,6 +1,7 @@
{
"arguments.moreParams": "Toplam {{count}} parametre",
"arguments.title": "Argümanlar",
"builtins.lobe-activator.apiName.activateTools": "Araçları Etkinleştir",
"builtins.lobe-agent-builder.apiName.getAvailableModels": "Mevcut modelleri al",
"builtins.lobe-agent-builder.apiName.getAvailableTools": "Mevcut Yetenekleri al",
"builtins.lobe-agent-builder.apiName.getConfig": "Yapılandırmayı al",
@@ -201,7 +202,6 @@
"builtins.lobe-skills.apiName.runCommand": "Komut Çalıştır",
"builtins.lobe-skills.apiName.searchSkill": "Becerileri Ara",
"builtins.lobe-skills.title": "Beceriler",
"builtins.lobe-tools.apiName.activateTools": "Araçları Etkinleştir",
"builtins.lobe-topic-reference.apiName.getTopicContext": "Konu bağlamını al",
"builtins.lobe-topic-reference.title": "Konu referansı",
"builtins.lobe-user-memory.apiName.addContextMemory": "Bağlam hafızası ekle",
+1 -1
View File
@@ -1,6 +1,7 @@
{
"arguments.moreParams": "Tổng cộng có {{count}} tham số",
"arguments.title": "Tham số",
"builtins.lobe-activator.apiName.activateTools": "Kích hoạt Công cụ",
"builtins.lobe-agent-builder.apiName.getAvailableModels": "Lấy mô hình khả dụng",
"builtins.lobe-agent-builder.apiName.getAvailableTools": "Lấy Kỹ năng khả dụng",
"builtins.lobe-agent-builder.apiName.getConfig": "Lấy cấu hình",
@@ -201,7 +202,6 @@
"builtins.lobe-skills.apiName.runCommand": "Chạy Lệnh",
"builtins.lobe-skills.apiName.searchSkill": "Tìm kiếm Kỹ năng",
"builtins.lobe-skills.title": "Kỹ năng",
"builtins.lobe-tools.apiName.activateTools": "Kích hoạt Công cụ",
"builtins.lobe-topic-reference.apiName.getTopicContext": "Lấy ngữ cảnh chủ đề",
"builtins.lobe-topic-reference.title": "Tham chiếu chủ đề",
"builtins.lobe-user-memory.apiName.addContextMemory": "Thêm trí nhớ ngữ cảnh",
+1 -1
View File
@@ -1,6 +1,7 @@
{
"arguments.moreParams": "等 {{count}} 个参数",
"arguments.title": "参数列表",
"builtins.lobe-activator.apiName.activateTools": "激活工具",
"builtins.lobe-agent-builder.apiName.getAvailableModels": "获取可用模型",
"builtins.lobe-agent-builder.apiName.getAvailableTools": "获取可用技能",
"builtins.lobe-agent-builder.apiName.getConfig": "获取配置",
@@ -201,7 +202,6 @@
"builtins.lobe-skills.apiName.runCommand": "执行命令",
"builtins.lobe-skills.apiName.searchSkill": "搜索技能",
"builtins.lobe-skills.title": "技能",
"builtins.lobe-tools.apiName.activateTools": "激活工具",
"builtins.lobe-topic-reference.apiName.getTopicContext": "获取话题上下文",
"builtins.lobe-topic-reference.title": "话题引用",
"builtins.lobe-user-memory.apiName.addContextMemory": "添加情境记忆",
+1 -1
View File
@@ -1,6 +1,7 @@
{
"arguments.moreParams": "總共有 {{count}} 個參數",
"arguments.title": "參數清單",
"builtins.lobe-activator.apiName.activateTools": "啟用工具",
"builtins.lobe-agent-builder.apiName.getAvailableModels": "取得可用模型",
"builtins.lobe-agent-builder.apiName.getAvailableTools": "取得可用工具",
"builtins.lobe-agent-builder.apiName.getConfig": "取得設定",
@@ -201,7 +202,6 @@
"builtins.lobe-skills.apiName.runCommand": "執行指令",
"builtins.lobe-skills.apiName.searchSkill": "搜尋技能",
"builtins.lobe-skills.title": "技能",
"builtins.lobe-tools.apiName.activateTools": "啟用工具",
"builtins.lobe-topic-reference.apiName.getTopicContext": "取得話題上下文",
"builtins.lobe-topic-reference.title": "話題引用",
"builtins.lobe-user-memory.apiName.addContextMemory": "新增情境記憶",
+1 -1
View File
@@ -201,6 +201,7 @@
"@lobechat/agent-runtime": "workspace:*",
"@lobechat/builtin-agents": "workspace:*",
"@lobechat/builtin-skills": "workspace:*",
"@lobechat/builtin-tool-activator": "workspace:*",
"@lobechat/builtin-tool-agent-builder": "workspace:*",
"@lobechat/builtin-tool-agent-management": "workspace:*",
"@lobechat/builtin-tool-calculator": "workspace:*",
@@ -216,7 +217,6 @@
"@lobechat/builtin-tool-remote-device": "workspace:*",
"@lobechat/builtin-tool-skill-store": "workspace:*",
"@lobechat/builtin-tool-skills": "workspace:*",
"@lobechat/builtin-tool-tools": "workspace:*",
"@lobechat/builtin-tool-topic-reference": "workspace:*",
"@lobechat/builtin-tool-web-browsing": "workspace:*",
"@lobechat/builtin-tools": "workspace:*",
@@ -58,7 +58,7 @@ export const findInMessages = <T>(
* ```typescript
* // Accumulate activated tool identifiers
* const tools = collectFromMessages(messages, (msg) => {
* if (msg.plugin?.identifier === LobeToolIdentifier) {
* if (msg.plugin?.identifier === LobeActivatorIdentifier) {
* return msg.pluginState?.activatedTools;
* }
* }, { role: 'tool' });
@@ -10,7 +10,7 @@ export interface ComputeStepContextParams {
*/
activatedSkills?: StepActivatedSkill[];
/**
* Activated tool identifiers accumulated from lobe-tools messages
* Activated tool identifiers accumulated from lobe-activator messages
*/
activatedToolIds?: string[];
/**
@@ -1,5 +1,5 @@
{
"name": "@lobechat/builtin-tool-tools",
"name": "@lobechat/builtin-tool-activator",
"version": "1.0.0",
"private": true,
"exports": {
@@ -1,6 +1,6 @@
import type { BuiltinServerRuntimeOutput } from '@lobechat/types';
import type { ActivatedToolInfo, ActivateToolsParams } from '../types';
import type { ActivatedToolInfo, ActivateSkillParams, ActivateToolsParams } from '../types';
export interface ToolManifestInfo {
apiDescriptions: Array<{ description: string; name: string }>;
@@ -10,23 +10,35 @@ export interface ToolManifestInfo {
systemRole?: string;
}
export interface ToolsActivatorRuntimeService {
export interface ActivatorRuntimeService {
activateSkill?: (args: ActivateSkillParams) => Promise<BuiltinServerRuntimeOutput>;
getActivatedToolIds: () => string[];
getToolManifests: (identifiers: string[]) => Promise<ToolManifestInfo[]>;
markActivated: (identifiers: string[]) => void;
}
export interface ToolsActivatorExecutionRuntimeOptions {
service: ToolsActivatorRuntimeService;
export interface ActivatorExecutionRuntimeOptions {
service: ActivatorRuntimeService;
}
export class ToolsActivatorExecutionRuntime {
private service: ToolsActivatorRuntimeService;
export class ActivatorExecutionRuntime {
private service: ActivatorRuntimeService;
constructor(options: ToolsActivatorExecutionRuntimeOptions) {
constructor(options: ActivatorExecutionRuntimeOptions) {
this.service = options.service;
}
async activateSkill(args: ActivateSkillParams): Promise<BuiltinServerRuntimeOutput> {
if (!this.service.activateSkill) {
return {
content: 'Skill activation is not available.',
success: false,
};
}
return this.service.activateSkill(args);
}
async activateTools(args: ActivateToolsParams): Promise<BuiltinServerRuntimeOutput> {
const { identifiers } = args;
@@ -0,0 +1,46 @@
'use client';
import { type BuiltinInspectorProps } from '@lobechat/types';
import { cx } from 'antd-style';
import { memo } from 'react';
import { useTranslation } from 'react-i18next';
import { highlightTextStyles, inspectorTextStyles, shinyTextStyles } from '@/styles';
import type { ActivateSkillParams, ActivateSkillState } from '../../../types';
export const ActivateSkillInspector = memo<
BuiltinInspectorProps<ActivateSkillParams, ActivateSkillState>
>(({ args, partialArgs, isArgumentsStreaming, isLoading, pluginState }) => {
const { t } = useTranslation('plugin');
const name = args?.name || partialArgs?.name || '';
const activatedName = pluginState?.name;
if (isArgumentsStreaming) {
if (!name)
return (
<div className={cx(inspectorTextStyles.root, shinyTextStyles.shinyText)}>
<span>{t('builtins.lobe-skills.apiName.activateSkill')}</span>
</div>
);
return (
<div className={cx(inspectorTextStyles.root, shinyTextStyles.shinyText)}>
<span>{t('builtins.lobe-skills.apiName.activateSkill')}:</span>
<span>{name}</span>
</div>
);
}
return (
<div className={cx(inspectorTextStyles.root, isLoading && shinyTextStyles.shinyText)}>
<span>
<span>{t('builtins.lobe-skills.apiName.activateSkill')}:</span>
<span className={highlightTextStyles.primary}>{activatedName || name}</span>
</span>
</div>
);
});
ActivateSkillInspector.displayName = 'ActivateSkillInspector';
@@ -42,7 +42,7 @@ export const ActivateToolsInspector = memo<
if (isArgumentsStreaming || isLoading) {
return (
<div className={cx(inspectorTextStyles.root, shinyTextStyles.shinyText)}>
<span>{t('builtins.lobe-tools.apiName.activateTools')}</span>
<span>{t('builtins.lobe-activator.apiName.activateTools')}</span>
{identifiers && identifiers.length > 0 && (
<span className={styles.tools}>
{identifiers.map((id) => (
@@ -59,7 +59,7 @@ export const ActivateToolsInspector = memo<
// Finished: show activated tool names with avatars
return (
<div className={inspectorTextStyles.root}>
<span>{t('builtins.lobe-tools.apiName.activateTools')}</span>
<span>{t('builtins.lobe-activator.apiName.activateTools')}</span>
{activatedTools && activatedTools.length > 0 && (
<span className={styles.tools}>
{activatedTools.map((tool) => (
@@ -0,0 +1,8 @@
import { ActivatorApiName } from '../../types';
import { ActivateSkillInspector } from './ActivateSkill';
import { ActivateToolsInspector } from './ActivateTools';
export const LobeActivatorInspectors = {
[ActivatorApiName.activateSkill]: ActivateSkillInspector,
[ActivatorApiName.activateTools]: ActivateToolsInspector,
};
@@ -0,0 +1,63 @@
'use client';
import { type BuiltinRenderProps } from '@lobechat/types';
import { Flexbox, Markdown, ScrollShadow } from '@lobehub/ui';
import { createStaticStyles } from 'antd-style';
import { memo } from 'react';
import type { ActivateSkillParams, ActivateSkillState } from '../../../types';
const styles = createStaticStyles(({ css, cssVar }) => ({
container: css`
overflow: hidden;
width: 100%;
border: 1px solid ${cssVar.colorBorderSecondary};
border-radius: 12px;
background: ${cssVar.colorBgContainer};
`,
content: css`
padding-block: 8px;
padding-inline: 16px;
font-size: 14px;
`,
description: css`
font-size: 12px;
color: ${cssVar.colorTextSecondary};
`,
header: css`
padding-block: 8px;
padding-inline: 12px;
border-block-end: 1px solid ${cssVar.colorBorderSecondary};
`,
name: css`
font-weight: 500;
`,
}));
const ActivateSkill = memo<BuiltinRenderProps<ActivateSkillParams, ActivateSkillState>>(
({ content, pluginState }) => {
const { description, name } = pluginState || {};
if (!name) return null;
return (
<Flexbox className={styles.container}>
<Flexbox className={styles.header} gap={4}>
<span className={styles.name}>{name}</span>
{description && <span className={styles.description}>{description}</span>}
</Flexbox>
{content && (
<ScrollShadow className={styles.content} offset={12} size={12} style={{ maxHeight: 400 }}>
<Markdown style={{ overflow: 'unset' }} variant={'chat'}>
{content}
</Markdown>
</ScrollShadow>
)}
</Flexbox>
);
},
);
export default ActivateSkill;
@@ -0,0 +1,6 @@
import { ActivatorApiName } from '../../types';
import ActivateSkill from './ActivateSkill';
export const LobeActivatorRenders = {
[ActivatorApiName.activateSkill]: ActivateSkill,
};
@@ -0,0 +1,4 @@
export { LobeActivatorManifest } from '../manifest';
export * from '../types';
export { LobeActivatorInspectors } from './Inspector';
export { LobeActivatorRenders } from './Render';
@@ -0,0 +1,81 @@
import { BaseExecutor, type BuiltinToolContext, type BuiltinToolResult } from '@lobechat/types';
import type { ActivatorExecutionRuntime } from '../ExecutionRuntime';
import {
type ActivateSkillParams,
type ActivateToolsParams,
ActivatorApiName,
LobeActivatorIdentifier,
} from '../types';
class ActivatorExecutor extends BaseExecutor<typeof ActivatorApiName> {
readonly identifier = LobeActivatorIdentifier;
protected readonly apiEnum = ActivatorApiName;
private runtime: ActivatorExecutionRuntime;
constructor(runtime: ActivatorExecutionRuntime) {
super();
this.runtime = runtime;
}
activateSkill = async (
params: ActivateSkillParams,
ctx: BuiltinToolContext,
): Promise<BuiltinToolResult> => {
try {
if (ctx.signal?.aborted) {
return { stop: true, success: false };
}
const result = await this.runtime.activateSkill(params);
if (result.success) {
return { content: result.content, state: result.state, success: true };
}
return {
content: result.content,
error: { message: result.content, type: 'PluginServerError' },
success: false,
};
} catch (e) {
const err = e as Error;
return {
error: { body: e, message: err.message, type: 'PluginServerError' },
success: false,
};
}
};
activateTools = async (
params: ActivateToolsParams,
ctx: BuiltinToolContext,
): Promise<BuiltinToolResult> => {
try {
if (ctx.signal?.aborted) {
return { stop: true, success: false };
}
const result = await this.runtime.activateTools(params);
if (result.success) {
return { content: result.content, state: result.state, success: true };
}
return {
content: result.content,
error: { message: result.content, type: 'PluginServerError' },
success: false,
};
} catch (e) {
const err = e as Error;
return {
error: { body: e, message: err.message, type: 'PluginServerError' },
success: false,
};
}
};
}
export { ActivatorExecutor };
@@ -0,0 +1,11 @@
export { LobeActivatorManifest } from './manifest';
export { systemPrompt } from './systemRole';
export {
type ActivatedToolInfo,
type ActivateSkillParams,
type ActivateSkillState,
type ActivateToolsParams,
type ActivateToolsState,
ActivatorApiName,
LobeActivatorIdentifier,
} from './types';
@@ -0,0 +1,51 @@
import type { BuiltinToolManifest } from '@lobechat/types';
import { systemPrompt } from './systemRole';
import { ActivatorApiName, LobeActivatorIdentifier } from './types';
export const LobeActivatorManifest: BuiltinToolManifest = {
api: [
{
description:
'Activate tools from the <available_tools> list so their full API schemas become available for use. Call this before using any tool that is not yet activated. You can activate multiple tools at once.',
name: ActivatorApiName.activateTools,
parameters: {
properties: {
identifiers: {
description:
'Array of tool identifiers to activate. Use the identifiers from the <available_tools> list.',
items: {
type: 'string',
},
type: 'array',
},
},
required: ['identifiers'],
type: 'object',
},
},
{
description:
'Activate a skill by name to load its instructions. Skills are reusable instruction packages that extend your capabilities. Returns the skill content that you should follow to complete the task. If the skill is not found, returns a list of available skills.',
name: ActivatorApiName.activateSkill,
parameters: {
properties: {
name: {
description: 'The exact name of the skill to activate.',
type: 'string',
},
},
required: ['name'],
type: 'object',
},
},
],
identifier: LobeActivatorIdentifier,
meta: {
avatar: '🔧',
description: 'Discover and activate tools and skills',
title: 'Tools & Skills Activator',
},
systemRole: systemPrompt,
type: 'builtin',
};
@@ -1,4 +1,4 @@
export const systemPrompt = `You have access to a Tool Discovery system that allows you to dynamically activate tools on demand. Not all tools are loaded by default — you must activate them before use.
export const systemPrompt = `You have access to a Tools & Skills Activator that allows you to dynamically activate tools and skills on demand. Not all tools are loaded by default — you must activate them before use. Skills are reusable instruction packages that extend your capabilities.
<how_it_works>
1. Available tools are listed in the \`<available_tools>\` section of your system prompt
@@ -6,6 +6,7 @@ export const systemPrompt = `You have access to a Tool Discovery system that all
3. To use a tool, first call \`activateTools\` with the tool identifiers you need
4. After activation, the tool's full API schemas become available as native function calls in subsequent turns
5. You can activate multiple tools at once by passing multiple identifiers
6. To activate a skill, call \`activateSkill\` with the skill name — it returns instructions to follow
</how_it_works>
<tool_selection_guidelines>
@@ -15,6 +16,10 @@ export const systemPrompt = `You have access to a Tool Discovery system that all
- After activation, the tools' APIs will be available for you to call directly
- Tools that are already active will be noted in the response
- If an identifier is not found, it will be reported in the response
- **activateSkill**: Call this when the user's task matches one of the available skills
- Provide the exact skill name
- Returns the skill content (instructions, templates, guidelines) that you should follow
- If the skill is not found, you'll receive a list of available skills
</tool_selection_guidelines>
<skill_store_discovery>
@@ -1,6 +1,7 @@
export const LobeToolIdentifier = 'lobe-tools';
export const LobeActivatorIdentifier = 'lobe-activator';
export const ToolsActivatorApiName = {
export const ActivatorApiName = {
activateSkill: 'activateSkill',
activateTools: 'activateTools',
};
@@ -20,3 +21,14 @@ export interface ActivateToolsState {
alreadyActive: string[];
notFound: string[];
}
export interface ActivateSkillParams {
name: string;
}
export interface ActivateSkillState {
description?: string;
hasResources: boolean;
id: string;
name: string;
}
@@ -1,17 +1,11 @@
import type { BuiltinToolManifest } from '@lobechat/types';
import {
activateSkillApi,
execScriptBaseParams,
manifestMeta,
readReferenceApi,
} from './manifest.base';
import { execScriptBaseParams, manifestMeta, readReferenceApi } from './manifest.base';
import { systemPrompt } from './systemRole';
import { SkillsApiName, SkillsIdentifier } from './types';
export const SkillsManifest: BuiltinToolManifest = {
api: [
activateSkillApi,
readReferenceApi,
{
description:
@@ -1,7 +1,6 @@
import type { BuiltinToolManifest } from '@lobechat/types';
import {
activateSkillApi,
execScriptBaseParams,
exportFileApi,
manifestMeta,
@@ -13,7 +12,6 @@ import { SkillsApiName, SkillsIdentifier } from './types';
export const SkillsManifest: BuiltinToolManifest = {
api: [
activateSkillApi,
readReferenceApi,
runCommandApi,
{
@@ -1,25 +1,17 @@
export const systemPrompt = `You have access to a Skills tool that allows you to activate reusable instruction packages (skills) that extend your capabilities. Skills are pre-defined workflows, guidelines, or specialized knowledge that help you handle specific types of tasks.
export const systemPrompt = `You have access to a Skills execution tool that provides runtime capabilities for activated skills. Use these tools when a skill's instructions tell you to read files or run commands.
<core_capabilities>
1. Activate a skill by name to load its instructions (activateSkill)
2. Read reference files attached to a skill (readReference)
3. Execute shell commands specified in a skill's instructions (execScript)
1. Read reference files attached to a skill (readReference)
2. Execute shell commands specified in a skill's instructions (execScript)
</core_capabilities>
<workflow>
1. When the user's request matches an available skill, call activateSkill with the skill name
2. The skill content will be returned - follow those instructions to complete the task
3. If the skill content references additional files, use readReference to load them
4. If the skill content instructs you to run CLI commands, use execScript to execute them
5. Apply the skill's instructions to fulfill the user's request
1. After a skill has been activated, follow its instructions to complete the task
2. If the skill content references additional files, use readReference to load them
3. If the skill content instructs you to run CLI commands, use execScript to execute them
</workflow>
<tool_selection_guidelines>
- **activateSkill**: Call this when the user's task matches one of the available skills
- Provide the exact skill name
- Returns the skill content (instructions, templates, guidelines) that you should follow
- If the skill is not found, you'll receive a list of available skills
- **readReference**: Call this to read reference files mentioned in a skill's content
- Requires the id (returned by activateSkill) and the file path
- Returns the file content for you to use as context
@@ -35,10 +27,8 @@ export const systemPrompt = `You have access to a Skills tool that allows you to
</tool_selection_guidelines>
<best_practices>
- Only activate skills when the user's task clearly matches the skill's purpose
- Follow the skill's instructions carefully once loaded
- Use readReference only for files explicitly mentioned in the skill content
- Use execScript only for commands specified in the skill content
- If activateSkill returns an error with available skills, inform the user what skills are available
</best_practices>
`;
+10 -18
View File
@@ -1,29 +1,21 @@
export const systemPrompt = `You have access to a Skills tool that allows you to activate reusable instruction packages (skills) that extend your capabilities. Skills are pre-defined workflows, guidelines, or specialized knowledge that help you handle specific types of tasks.
export const systemPrompt = `You have access to a Skills execution tool that provides runtime capabilities for activated skills. Use these tools when a skill's instructions tell you to read files, run commands, or export results.
<core_capabilities>
1. Activate a skill by name to load its instructions (activateSkill)
2. Read reference files attached to a skill (readReference)
3. Execute shell commands in the cloud sandbox (runCommand)
4. Execute skill-specific scripts with resource context (execScript)
5. Export files generated during skill execution to cloud storage (exportFile)
1. Read reference files attached to a skill (readReference)
2. Execute shell commands in the cloud sandbox (runCommand)
3. Execute skill-specific scripts with resource context (execScript)
4. Export files generated during skill execution to cloud storage (exportFile)
</core_capabilities>
<workflow>
1. When the user's request matches an available skill, call activateSkill with the skill name
2. The skill content will be returned - follow those instructions to complete the task
3. If the skill content references additional files, use readReference to load them
4. If the skill content instructs you to run CLI commands, use runCommand to execute them
5. If the command requires skill-bundled resources, use execScript instead
6. If the skill execution generates output files, use exportFile to save them for the user
7. Apply the skill's instructions to fulfill the user's request
1. After a skill has been activated, follow its instructions to complete the task
2. If the skill content references additional files, use readReference to load them
3. If the skill content instructs you to run CLI commands, use runCommand to execute them
4. If the command requires skill-bundled resources, use execScript instead
5. If the skill execution generates output files, use exportFile to save them for the user
</workflow>
<tool_selection_guidelines>
- **activateSkill**: Call this when the user's task matches one of the available skills
- Provide the exact skill name
- Returns the skill content (instructions, templates, guidelines) that you should follow
- If the skill is not found, you'll receive a list of available skills
- **readReference**: Call this to read reference files mentioned in a skill's content
- Requires the id (returned by activateSkill) and the file path
- Returns the file content for you to use as context
@@ -1,6 +0,0 @@
import { ToolsActivatorApiName } from '../../types';
import { ActivateToolsInspector } from './ActivateTools';
export const LobeToolsInspectors = {
[ToolsActivatorApiName.activateTools]: ActivateToolsInspector,
};
@@ -1,3 +0,0 @@
export { LobeToolsManifest } from '../manifest';
export * from '../types';
export { LobeToolsInspectors } from './Inspector';
@@ -1,47 +0,0 @@
import { BaseExecutor, type BuiltinToolContext, type BuiltinToolResult } from '@lobechat/types';
import type { ToolsActivatorExecutionRuntime } from '../ExecutionRuntime';
import { type ActivateToolsParams, LobeToolIdentifier, ToolsActivatorApiName } from '../types';
class ToolsActivatorExecutor extends BaseExecutor<typeof ToolsActivatorApiName> {
readonly identifier = LobeToolIdentifier;
protected readonly apiEnum = ToolsActivatorApiName;
private runtime: ToolsActivatorExecutionRuntime;
constructor(runtime: ToolsActivatorExecutionRuntime) {
super();
this.runtime = runtime;
}
activateTools = async (
params: ActivateToolsParams,
ctx: BuiltinToolContext,
): Promise<BuiltinToolResult> => {
try {
if (ctx.signal?.aborted) {
return { stop: true, success: false };
}
const result = await this.runtime.activateTools(params);
if (result.success) {
return { content: result.content, state: result.state, success: true };
}
return {
content: result.content,
error: { message: result.content, type: 'PluginServerError' },
success: false,
};
} catch (e) {
const err = e as Error;
return {
error: { body: e, message: err.message, type: 'PluginServerError' },
success: false,
};
}
};
}
export { ToolsActivatorExecutor };
-9
View File
@@ -1,9 +0,0 @@
export { LobeToolsManifest } from './manifest';
export { systemPrompt } from './systemRole';
export {
type ActivatedToolInfo,
type ActivateToolsParams,
type ActivateToolsState,
LobeToolIdentifier,
ToolsActivatorApiName,
} from './types';
@@ -1,36 +0,0 @@
import type { BuiltinToolManifest } from '@lobechat/types';
import { systemPrompt } from './systemRole';
import { LobeToolIdentifier, ToolsActivatorApiName } from './types';
export const LobeToolsManifest: BuiltinToolManifest = {
api: [
{
description:
'Activate tools from the <available_tools> list so their full API schemas become available for use. Call this before using any tool that is not yet activated. You can activate multiple tools at once.',
name: ToolsActivatorApiName.activateTools,
parameters: {
properties: {
identifiers: {
description:
'Array of tool identifiers to activate. Use the identifiers from the <available_tools> list.',
items: {
type: 'string',
},
type: 'array',
},
},
required: ['identifiers'],
type: 'object',
},
},
],
identifier: LobeToolIdentifier,
meta: {
avatar: '🔧',
description: 'Discover and activate tools on demand',
title: 'Tools',
},
systemRole: systemPrompt,
type: 'builtin',
};
+1 -1
View File
@@ -16,6 +16,7 @@
},
"main": "./src/index.ts",
"dependencies": {
"@lobechat/builtin-tool-activator": "workspace:*",
"@lobechat/builtin-tool-agent-builder": "workspace:*",
"@lobechat/builtin-tool-cloud-sandbox": "workspace:*",
"@lobechat/builtin-tool-group-agent-builder": "workspace:*",
@@ -29,7 +30,6 @@
"@lobechat/builtin-tool-remote-device": "workspace:*",
"@lobechat/builtin-tool-skill-store": "workspace:*",
"@lobechat/builtin-tool-skills": "workspace:*",
"@lobechat/builtin-tool-tools": "workspace:*",
"@lobechat/builtin-tool-topic-reference": "workspace:*",
"@lobechat/builtin-tool-web-browsing": "workspace:*",
"@lobechat/const": "workspace:*"
+2 -2
View File
@@ -1,3 +1,4 @@
import { LobeActivatorManifest } from '@lobechat/builtin-tool-activator';
import { AgentBuilderManifest } from '@lobechat/builtin-tool-agent-builder';
import { AgentManagementManifest } from '@lobechat/builtin-tool-agent-management';
import { CalculatorManifest } from '@lobechat/builtin-tool-calculator';
@@ -12,7 +13,6 @@ import { NotebookManifest } from '@lobechat/builtin-tool-notebook';
import { PageAgentManifest } from '@lobechat/builtin-tool-page-agent';
import { SkillStoreManifest } from '@lobechat/builtin-tool-skill-store';
import { SkillsManifest } from '@lobechat/builtin-tool-skills';
import { LobeToolsManifest } from '@lobechat/builtin-tool-tools';
import { TopicReferenceManifest } from '@lobechat/builtin-tool-topic-reference';
import { WebBrowsingManifest } from '@lobechat/builtin-tool-web-browsing';
@@ -32,6 +32,6 @@ export const builtinToolIdentifiers: string[] = [
MemoryManifest.identifier,
NotebookManifest.identifier,
TopicReferenceManifest.identifier,
LobeToolsManifest.identifier,
LobeActivatorManifest.identifier,
SkillStoreManifest.identifier,
];
+19 -5
View File
@@ -1,3 +1,4 @@
import { LobeActivatorManifest } from '@lobechat/builtin-tool-activator';
import { AgentBuilderManifest } from '@lobechat/builtin-tool-agent-builder';
import { AgentManagementManifest } from '@lobechat/builtin-tool-agent-management';
import { CalculatorManifest } from '@lobechat/builtin-tool-calculator';
@@ -13,7 +14,6 @@ import { PageAgentManifest } from '@lobechat/builtin-tool-page-agent';
import { RemoteDeviceManifest } from '@lobechat/builtin-tool-remote-device';
import { SkillStoreManifest } from '@lobechat/builtin-tool-skill-store';
import { SkillsManifest } from '@lobechat/builtin-tool-skills';
import { LobeToolsManifest } from '@lobechat/builtin-tool-tools';
import { TopicReferenceManifest } from '@lobechat/builtin-tool-topic-reference';
import { WebBrowsingManifest } from '@lobechat/builtin-tool-web-browsing';
import { isDesktop } from '@lobechat/const';
@@ -24,7 +24,7 @@ import { type LobeBuiltinTool } from '@lobechat/types';
* Shared between frontend (createAgentToolsEngine) and server (createServerAgentToolsEngine).
*/
export const defaultToolIds = [
LobeToolsManifest.identifier,
LobeActivatorManifest.identifier,
SkillsManifest.identifier,
SkillStoreManifest.identifier,
WebBrowsingManifest.identifier,
@@ -39,14 +39,28 @@ export const defaultToolIds = [
* Tool IDs that are always enabled regardless of user selection.
* These are core system tools that the agent needs to function properly.
*/
export const alwaysOnToolIds = [LobeToolsManifest.identifier, SkillsManifest.identifier];
export const alwaysOnToolIds = [
LobeActivatorManifest.identifier,
SkillsManifest.identifier,
SkillStoreManifest.identifier,
];
/**
* Tool IDs to exclude from defaults when in manual skill-activate mode.
* These are the tool/skill discovery tools that should be disabled when user wants precise control.
* Other default tools (sandbox, web browsing, etc.) remain available if enabled externally.
*/
export const manualModeExcludeToolIds = [
LobeActivatorManifest.identifier,
SkillStoreManifest.identifier,
];
export const builtinTools: LobeBuiltinTool[] = [
{
discoverable: false,
hidden: true,
identifier: LobeToolsManifest.identifier,
manifest: LobeToolsManifest,
identifier: LobeActivatorManifest.identifier,
manifest: LobeActivatorManifest,
type: 'builtin',
},
{
+7 -2
View File
@@ -1,3 +1,7 @@
import {
LobeActivatorInspectors,
LobeActivatorManifest,
} from '@lobechat/builtin-tool-activator/client';
import {
AgentBuilderInspectors,
AgentBuilderManifest,
@@ -35,7 +39,6 @@ import {
SkillStoreManifest,
} from '@lobechat/builtin-tool-skill-store/client';
import { SkillsInspectors, SkillsManifest } from '@lobechat/builtin-tool-skills/client';
import { LobeToolsInspectors, LobeToolsManifest } from '@lobechat/builtin-tool-tools/client';
import {
WebBrowsingInspectors,
WebBrowsingManifest,
@@ -70,7 +73,9 @@ const BuiltinToolInspectors: Record<string, Record<string, BuiltinInspector>> =
[MemoryManifest.identifier]: MemoryInspectors as Record<string, BuiltinInspector>,
[NotebookManifest.identifier]: NotebookInspectors as Record<string, BuiltinInspector>,
[PageAgentManifest.identifier]: PageAgentInspectors as Record<string, BuiltinInspector>,
[LobeToolsManifest.identifier]: LobeToolsInspectors as Record<string, BuiltinInspector>,
[LobeActivatorManifest.identifier]: LobeActivatorInspectors as Record<string, BuiltinInspector>,
// @deprecated backward compat: old messages stored 'lobe-tools' as identifier
['lobe-tools']: LobeActivatorInspectors as Record<string, BuiltinInspector>,
[SkillStoreManifest.identifier]: SkillStoreInspectors as Record<string, BuiltinInspector>,
[SkillsManifest.identifier]: SkillsInspectors as Record<string, BuiltinInspector>,
[WebBrowsingManifest.identifier]: WebBrowsingInspectors as Record<string, BuiltinInspector>,
+7
View File
@@ -1,3 +1,7 @@
import {
LobeActivatorManifest,
LobeActivatorRenders,
} from '@lobechat/builtin-tool-activator/client';
import { AgentBuilderManifest } from '@lobechat/builtin-tool-agent-builder';
import { AgentBuilderRenders } from '@lobechat/builtin-tool-agent-builder/client';
import { AgentManagementManifest } from '@lobechat/builtin-tool-agent-management';
@@ -44,6 +48,9 @@ const BuiltinToolsRenders: Record<string, Record<string, BuiltinRender>> = {
[NotebookManifest.identifier]: NotebookRenders as Record<string, BuiltinRender>,
[SkillStoreManifest.identifier]: SkillStoreRenders as Record<string, BuiltinRender>,
[SkillsManifest.identifier]: SkillsRenders as Record<string, BuiltinRender>,
[LobeActivatorManifest.identifier]: LobeActivatorRenders as Record<string, BuiltinRender>,
// @deprecated backward compat: old messages stored 'lobe-tools' as identifier
['lobe-tools']: LobeActivatorRenders as Record<string, BuiltinRender>,
[WebBrowsingManifest.identifier]: WebBrowsingRenders as Record<string, BuiltinRender>,
};
@@ -97,12 +97,23 @@ export class ToolsEngine {
* @returns Detailed tools generation result
*/
generateToolsDetailed(params: GenerateToolsParams): ToolsGenerationResult {
const { toolIds = [], model, provider, context, skipDefaultTools } = params;
const {
toolIds = [],
model,
provider,
context,
skipDefaultTools,
excludeDefaultToolIds,
} = params;
// Merge user-provided tool IDs with default tool IDs and deduplicate (unless skipDefaultTools is true)
const effectiveDefaultToolIds = excludeDefaultToolIds
? this.defaultToolIds.filter((id) => !excludeDefaultToolIds.includes(id))
: this.defaultToolIds;
const allToolIds = skipDefaultTools
? toolIds
: [...new Set([...toolIds, ...this.defaultToolIds])];
: [...new Set([...toolIds, ...effectiveDefaultToolIds])];
log(
'Generating detailed tools for model=%s, provider=%s, pluginIds=%o (skipDefaultTools=%s, includes %d default tools)',
@@ -1061,8 +1061,10 @@ describe('ToolsEngine', () => {
describe('explicit activation with always-on builtins', () => {
const builtinManifests: LobeToolManifest[] = [
{
identifier: 'lobe-tools',
api: [{ name: 'run', description: 'Run tool', parameters: {} }],
identifier: 'lobe-activator',
api: [
{ name: 'run', description: 'Discover and activate tools and skills', parameters: {} },
],
meta: { title: 'Tools' },
type: 'builtin',
},
@@ -1107,7 +1109,7 @@ describe('ToolsEngine', () => {
it('should only enable notebook + always-on builtins when user selected only notebook', () => {
const userSelectedPlugins = ['lobe-notebook'];
const defaultToolIds = [
'lobe-tools',
'lobe-activator',
'lobe-skills',
'lobe-skill-store',
'lobe-web-browsing',
@@ -1120,7 +1122,7 @@ describe('ToolsEngine', () => {
// User-selected plugins
...Object.fromEntries(userSelectedPlugins.map((id) => [id, true])),
// Always-on builtin tools
'lobe-tools': true,
'lobe-activator': true,
'lobe-skills': true,
// System-level rules
'lobe-knowledge-base': false, // no knowledge bases enabled
@@ -1141,10 +1143,10 @@ describe('ToolsEngine', () => {
provider: 'openai',
});
// notebook + web-browsing + always-on builtins (lobe-tools, lobe-skills) should be enabled
// notebook + web-browsing + always-on builtins (lobe-activator, lobe-skills) should be enabled
expect(result.enabledToolIds).toContain('lobe-notebook');
expect(result.enabledToolIds).toContain('lobe-web-browsing');
expect(result.enabledToolIds).toContain('lobe-tools');
expect(result.enabledToolIds).toContain('lobe-activator');
expect(result.enabledToolIds).toContain('lobe-skills');
// lobe-skill-store should NOT be enabled (not always-on, not user-selected)
expect(result.enabledToolIds).not.toContain('lobe-skill-store');
@@ -1232,6 +1234,158 @@ describe('ToolsEngine', () => {
});
});
describe('excludeDefaultToolIds (manual skill mode)', () => {
const builtinManifests: LobeToolManifest[] = [
{
identifier: 'lobe-activator',
api: [{ name: 'run', description: 'Run tool', parameters: {} }],
meta: { title: 'Tools' },
type: 'builtin',
},
{
identifier: 'lobe-skills',
api: [{ name: 'run', description: 'Run skill', parameters: {} }],
meta: { title: 'Skills' },
type: 'builtin',
},
{
identifier: 'lobe-skill-store',
api: [{ name: 'search', description: 'Search', parameters: {} }],
meta: { title: 'Skill Store' },
type: 'builtin',
},
{
identifier: 'lobe-web-browsing',
api: [{ name: 'search', description: 'Search web', parameters: {} }],
meta: { title: 'Web Browsing' },
type: 'builtin',
},
{
identifier: 'lobe-cloud-sandbox',
api: [{ name: 'exec', description: 'Execute', parameters: {} }],
meta: { title: 'Cloud Sandbox' },
type: 'builtin',
},
];
const defaultToolIds = [
'lobe-activator',
'lobe-skills',
'lobe-skill-store',
'lobe-web-browsing',
'lobe-cloud-sandbox',
];
const alwaysOnToolIds = ['lobe-activator', 'lobe-skills', 'lobe-skill-store'];
const manualModeExcludeToolIds = ['lobe-activator', 'lobe-skill-store'];
it('should NOT inject lobe-activator and lobe-skill-store in manual mode', () => {
const engine = new ToolsEngine({
manifestSchemas: builtinManifests,
defaultToolIds,
enableChecker: createEnableChecker({
rules: {
...Object.fromEntries(alwaysOnToolIds.map((id) => [id, true])),
'lobe-web-browsing': true,
'lobe-cloud-sandbox': true,
},
}),
functionCallChecker: () => true,
});
const result = engine.generateToolsDetailed({
toolIds: [],
model: 'gpt-4',
provider: 'openai',
excludeDefaultToolIds: manualModeExcludeToolIds,
});
// Discovery tools should be excluded from defaults in manual mode
expect(result.enabledToolIds).not.toContain('lobe-activator');
expect(result.enabledToolIds).not.toContain('lobe-skill-store');
// Execution tools and other defaults should still be available
expect(result.enabledToolIds).toContain('lobe-skills');
expect(result.enabledToolIds).toContain('lobe-web-browsing');
expect(result.enabledToolIds).toContain('lobe-cloud-sandbox');
});
it('should inject lobe-activator and lobe-skill-store in auto mode (no excludeDefaultToolIds)', () => {
const engine = new ToolsEngine({
manifestSchemas: builtinManifests,
defaultToolIds,
enableChecker: createEnableChecker({
rules: {
...Object.fromEntries(alwaysOnToolIds.map((id) => [id, true])),
'lobe-web-browsing': true,
'lobe-cloud-sandbox': true,
},
}),
functionCallChecker: () => true,
});
const result = engine.generateToolsDetailed({
toolIds: [],
model: 'gpt-4',
provider: 'openai',
// No excludeDefaultToolIds = auto mode
});
// All default tools should be injected in auto mode
expect(result.enabledToolIds).toContain('lobe-activator');
expect(result.enabledToolIds).toContain('lobe-skill-store');
expect(result.enabledToolIds).toContain('lobe-skills');
expect(result.enabledToolIds).toContain('lobe-web-browsing');
expect(result.enabledToolIds).toContain('lobe-cloud-sandbox');
});
it('should keep externally enabled tools (sandbox, web browsing) available in manual mode', () => {
const engine = new ToolsEngine({
manifestSchemas: builtinManifests,
defaultToolIds,
enableChecker: createEnableChecker({
rules: {
...Object.fromEntries(alwaysOnToolIds.map((id) => [id, true])),
'lobe-web-browsing': true,
'lobe-cloud-sandbox': true,
},
}),
functionCallChecker: () => true,
});
const result = engine.generateToolsDetailed({
toolIds: [],
model: 'gpt-4',
provider: 'openai',
excludeDefaultToolIds: manualModeExcludeToolIds,
});
// Web browsing and sandbox should remain available even in manual mode
expect(result.enabledToolIds).toContain('lobe-web-browsing');
expect(result.enabledToolIds).toContain('lobe-cloud-sandbox');
expect(result.enabledToolIds).toHaveLength(3); // skills + web-browsing + cloud-sandbox
});
it('should not affect skipDefaultTools behavior', () => {
const engine = new ToolsEngine({
manifestSchemas: builtinManifests,
defaultToolIds,
enableChecker: () => true,
functionCallChecker: () => true,
});
// skipDefaultTools should still skip ALL defaults
const result = engine.generateToolsDetailed({
toolIds: [],
model: 'gpt-4',
provider: 'openai',
skipDefaultTools: true,
});
expect(result.enabledToolIds).toEqual([]);
expect(result.tools).toBeUndefined();
});
});
describe('skipDefaultTools', () => {
it('should not include default tools when skipDefaultTools is true in generateTools', () => {
const engine = new ToolsEngine({
@@ -163,7 +163,7 @@ describe('createEnableChecker', () => {
// BUG: Tools NOT in rules currently default to true,
// but should default to false to prevent unintended tool activation
// This is the regression test for the "all 7 builtin tools enabled" bug
expect(checker(makeParams('lobe-tools'))).toBe(false);
expect(checker(makeParams('lobe-activator'))).toBe(false);
expect(checker(makeParams('lobe-skills'))).toBe(false);
expect(checker(makeParams('lobe-skill-store'))).toBe(false);
});
@@ -193,7 +193,7 @@ describe('createEnableChecker', () => {
expect(checker(makeParams('memory'))).toBe(false);
// Default tools NOT in rules: should be disabled
expect(checker(makeParams('lobe-tools'))).toBe(false);
expect(checker(makeParams('lobe-activator'))).toBe(false);
expect(checker(makeParams('lobe-skills'))).toBe(false);
expect(checker(makeParams('lobe-skill-store'))).toBe(false);
});
@@ -34,7 +34,7 @@ export interface EnableCheckerConfig {
*/
export function createEnableChecker(config: EnableCheckerConfig): PluginEnableChecker {
return ({ pluginId, context, manifest }) => {
// 1. Explicit activation bypass (e.g. tools activated via lobe-tools)
// 1. Explicit activation bypass (e.g. tools activated via lobe-activator)
if (config.allowExplicitActivation && context?.isExplicitActivation) return true;
// 2. Platform-specific filter (return undefined = fall through)
@@ -68,6 +68,12 @@ export type FunctionCallChecker = (model: string, provider: string) => boolean;
export interface GenerateToolsParams {
/** Additional context information */
context?: ToolsGenerationContext;
/**
* Tool IDs to exclude from the default tools list.
* These IDs will be filtered out from defaultToolIds before merging.
* Useful for manual skill mode where only discovery tools should be excluded.
*/
excludeDefaultToolIds?: string[];
/** Model name */
model: string;
/** Provider name */
+1 -1
View File
@@ -126,7 +126,7 @@ export interface RuntimeStepContext {
*/
activatedSkills?: StepActivatedSkill[];
/**
* Activated tool identifiers accumulated from lobe-tools messages
* Activated tool identifiers accumulated from lobe-activator messages
* Tools once activated remain active for the rest of the conversation
*/
activatedToolIds?: string[];
@@ -1,4 +1,4 @@
import { Icon, Segmented } from '@lobehub/ui';
import { Icon, Segmented, Tooltip } from '@lobehub/ui';
import { SlidersHorizontal, Sparkles } from 'lucide-react';
import { memo } from 'react';
import { useTranslation } from 'react-i18next';
@@ -23,13 +23,19 @@ const SkillActivateMode = memo(() => {
value={currentMode}
options={[
{
icon: <Icon icon={Sparkles} />,
title: t('tools.skillActivateMode.auto.desc'),
label: (
<Tooltip title={t('tools.skillActivateMode.auto.desc')}>
<Icon icon={Sparkles} />
</Tooltip>
),
value: 'auto',
},
{
icon: <Icon icon={SlidersHorizontal} />,
title: t('tools.skillActivateMode.manual.desc'),
label: (
<Tooltip title={t('tools.skillActivateMode.manual.desc')}>
<Icon icon={SlidersHorizontal} />
</Tooltip>
),
value: 'manual',
},
]}
+1 -1
View File
@@ -185,7 +185,7 @@ export default {
'builtins.lobe-page-agent.apiName.updateNode': 'Update node',
'builtins.lobe-page-agent.apiName.wrapNodes': 'Wrap nodes',
'builtins.lobe-page-agent.title': 'Page',
'builtins.lobe-tools.apiName.activateTools': 'Activate Tools',
'builtins.lobe-activator.apiName.activateTools': 'Activate Tools',
'builtins.lobe-skill-store.apiName.importFromMarket': 'Import from Market',
'builtins.lobe-skill-store.apiName.importSkill': 'Import Skill',
'builtins.lobe-skill-store.apiName.searchSkill': 'Search Skills',
+4 -3
View File
@@ -6,7 +6,7 @@ import {
generateSystemPrompt,
RemoteDeviceManifest,
} from '@lobechat/builtin-tool-remote-device';
import { builtinTools } from '@lobechat/builtin-tools';
import { builtinTools, manualModeExcludeToolIds } from '@lobechat/builtin-tools';
import { LOADING_FLAT } from '@lobechat/const';
import type { LobeToolManifest } from '@lobechat/context-engine';
import type { LobeChatDatabase } from '@lobechat/database';
@@ -407,13 +407,14 @@ export class AiAgentService {
];
log('execAgent: agent configured plugins: %O', pluginIds);
// When skillActivateMode is 'manual', skip default tools to give user precise control
// When skillActivateMode is 'manual', exclude only discovery tools (lobe-activator, lobe-skill-store)
// so that externally enabled tools (sandbox, web browsing, etc.) remain available
const isManualMode = agentConfig.chatConfig?.skillActivateMode === 'manual';
const toolsResult = toolsEngine.generateToolsDetailed({
excludeDefaultToolIds: isManualMode ? manualModeExcludeToolIds : undefined,
model,
provider,
skipDefaultTools: isManualMode,
toolIds: pluginIds,
});
@@ -0,0 +1,77 @@
import { builtinSkills } from '@lobechat/builtin-skills';
import { LobeActivatorIdentifier } from '@lobechat/builtin-tool-activator';
import {
ActivatorExecutionRuntime,
type ActivatorRuntimeService,
type ToolManifestInfo,
} from '@lobechat/builtin-tool-activator/executionRuntime';
import { SkillsExecutionRuntime } from '@lobechat/builtin-tool-skills/executionRuntime';
import { AgentSkillModel } from '@/database/models/agentSkill';
import { filterBuiltinSkills } from '@/helpers/skillFilters';
import { type ServerRuntimeRegistration } from './types';
/**
* Tools Activator Server Runtime
* Resolves tool manifests from context.toolManifestMap (populated by the agent state).
*/
export const activatorRuntime: ServerRuntimeRegistration = {
factory: async (context) => {
const activatedIds: string[] = [];
// Create SkillsExecutionRuntime for activateSkill delegation
let skillsRuntime: SkillsExecutionRuntime | undefined;
if (context.serverDB && context.userId) {
const skillModel = new AgentSkillModel(context.serverDB, context.userId);
skillsRuntime = new SkillsExecutionRuntime({
builtinSkills: filterBuiltinSkills(builtinSkills),
service: {
findAll: () => skillModel.findAll(),
findById: (id) => skillModel.findById(id),
findByName: (name) => skillModel.findByName(name),
readResource: async () => {
throw new Error('readResource not available in tools runtime');
},
},
});
}
const service: ActivatorRuntimeService = {
activateSkill: skillsRuntime ? (args) => skillsRuntime!.activateSkill(args) : undefined,
getActivatedToolIds: () => [...activatedIds],
getToolManifests: async (identifiers: string[]): Promise<ToolManifestInfo[]> => {
// Note: context.toolManifestMap should only contain discoverable tools.
// The caller is responsible for scoping this map to exclude hidden/internal tools.
const results: ToolManifestInfo[] = [];
for (const id of identifiers) {
const manifest = context.toolManifestMap[id];
if (!manifest) continue;
results.push({
apiDescriptions: manifest.api.map((a) => ({
description: a.description,
name: a.name,
})),
identifier: manifest.identifier,
name: manifest.meta?.title ?? manifest.identifier,
systemRole: manifest.systemRole,
});
}
return results;
},
markActivated: (identifiers: string[]) => {
for (const id of identifiers) {
if (!activatedIds.includes(id)) {
activatedIds.push(id);
}
}
},
};
return new ActivatorExecutionRuntime({ service });
},
identifier: LobeActivatorIdentifier,
};
@@ -7,6 +7,7 @@
* - Per-request runtimes (e.g., CloudSandbox - needs topicId, userId)
*/
import { type ToolExecutionContext } from '../types';
import { activatorRuntime } from './activator';
import { calculatorRuntime } from './calculator';
import { cloudSandboxRuntime } from './cloudSandbox';
import { localSystemRuntime } from './localSystem';
@@ -15,7 +16,6 @@ import { notebookRuntime } from './notebook';
import { remoteDeviceRuntime } from './remoteDevice';
import { skillsRuntime } from './skills';
import { skillStoreRuntime } from './skillStore';
import { toolsActivatorRuntime } from './tools';
import { topicReferenceRuntime } from './topicReference';
import { type ServerRuntimeFactory, type ServerRuntimeRegistration } from './types';
import { webBrowsingRuntime } from './webBrowsing';
@@ -43,7 +43,7 @@ registerRuntimes([
skillStoreRuntime,
skillsRuntime,
memoryRuntime,
toolsActivatorRuntime,
activatorRuntime,
localSystemRuntime,
remoteDeviceRuntime,
topicReferenceRuntime,
@@ -1,54 +0,0 @@
import { LobeToolIdentifier } from '@lobechat/builtin-tool-tools';
import {
type ToolManifestInfo,
ToolsActivatorExecutionRuntime,
type ToolsActivatorRuntimeService,
} from '@lobechat/builtin-tool-tools/executionRuntime';
import { type ServerRuntimeRegistration } from './types';
/**
* Tools Activator Server Runtime
* Resolves tool manifests from context.toolManifestMap (populated by the agent state).
*/
export const toolsActivatorRuntime: ServerRuntimeRegistration = {
factory: (context) => {
const activatedIds: string[] = [];
const service: ToolsActivatorRuntimeService = {
getActivatedToolIds: () => [...activatedIds],
getToolManifests: async (identifiers: string[]): Promise<ToolManifestInfo[]> => {
// Note: context.toolManifestMap should only contain discoverable tools.
// The caller is responsible for scoping this map to exclude hidden/internal tools.
const results: ToolManifestInfo[] = [];
for (const id of identifiers) {
const manifest = context.toolManifestMap[id];
if (!manifest) continue;
results.push({
apiDescriptions: manifest.api.map((a) => ({
description: a.description,
name: a.name,
})),
identifier: manifest.identifier,
name: manifest.meta?.title ?? manifest.identifier,
systemRole: manifest.systemRole,
});
}
return results;
},
markActivated: (identifiers: string[]) => {
for (const id of identifiers) {
if (!activatedIds.includes(id)) {
activatedIds.push(id);
}
}
},
};
return new ToolsActivatorExecutionRuntime({ service });
},
identifier: LobeToolIdentifier,
};
@@ -1,8 +1,8 @@
import { LobeActivatorIdentifier } from '@lobechat/builtin-tool-activator';
import { AgentBuilderIdentifier } from '@lobechat/builtin-tool-agent-builder';
import { AgentManagementIdentifier } from '@lobechat/builtin-tool-agent-management';
import { GroupAgentBuilderIdentifier } from '@lobechat/builtin-tool-group-agent-builder';
import { GTDIdentifier } from '@lobechat/builtin-tool-gtd';
import { LobeToolIdentifier } from '@lobechat/builtin-tool-tools';
import { isDesktop, KLAVIS_SERVER_TYPES, LOBEHUB_SKILL_PROVIDERS } from '@lobechat/const';
import type {
AgentBuilderContext,
@@ -389,9 +389,9 @@ export const contextEngineering = async ({
}
: undefined;
// Build tool discovery config if lobe-tools is enabled
// Build tool discovery config if lobe-activator is enabled
const enabledToolSet = new Set(tools || []);
const isLobeToolsEnabled = enabledToolSet.has(LobeToolIdentifier);
const isLobeToolsEnabled = enabledToolSet.has(LobeActivatorIdentifier);
let toolDiscoveryConfig: ToolDiscoveryConfig | undefined;
if (isLobeToolsEnabled) {
+2 -2
View File
@@ -35,7 +35,7 @@ describe('prepareSelectedSkillPreload', () => {
apiName: 'activateSkill',
arguments: JSON.stringify({ name: 'Grep' }),
id: expect.any(String),
identifier: 'lobe-skills',
identifier: 'lobe-activator',
type: 'builtin',
}),
],
@@ -47,7 +47,7 @@ describe('prepareSelectedSkillPreload', () => {
plugin: expect.objectContaining({
apiName: 'activateSkill',
arguments: JSON.stringify({ name: 'Grep' }),
identifier: 'lobe-skills',
identifier: 'lobe-activator',
type: 'builtin',
}),
role: 'tool',
+5 -5
View File
@@ -1,4 +1,4 @@
import { SkillsApiName, SkillsIdentifier } from '@lobechat/builtin-tool-skills';
import { ActivatorApiName, LobeActivatorIdentifier } from '@lobechat/builtin-tool-activator';
import { resourcesTreePrompt } from '@lobechat/prompts';
import type { RuntimeSelectedSkill, SendPreloadMessage } from '@lobechat/types';
import { nanoid } from '@lobechat/utils';
@@ -120,10 +120,10 @@ const buildPersistedPreloadMessages = (skills: PreloadedSkill[]): SendPreloadMes
role: 'assistant',
tools: [
{
apiName: SkillsApiName.activateSkill,
apiName: ActivatorApiName.activateSkill,
arguments: args,
id: toolCallId,
identifier: SkillsIdentifier,
identifier: LobeActivatorIdentifier,
type: 'builtin',
},
],
@@ -131,9 +131,9 @@ const buildPersistedPreloadMessages = (skills: PreloadedSkill[]): SendPreloadMes
{
content: skill.content,
plugin: {
apiName: SkillsApiName.activateSkill,
apiName: ActivatorApiName.activateSkill,
arguments: args,
identifier: SkillsIdentifier,
identifier: LobeActivatorIdentifier,
type: 'builtin',
},
role: 'tool',
@@ -234,14 +234,14 @@ describe('call_llm executor', () => {
},
phase: 'init',
stepContext: {
activatedToolIds: ['lobe-skills', 'lobe-tools'],
activatedToolIds: ['lobe-skills', 'lobe-activator'],
},
} as any);
expect(toolsEngine.generateToolsDetailed).toHaveBeenCalledWith(
expect.objectContaining({
skipDefaultTools: true,
toolIds: ['lobe-skills', 'lobe-tools'],
toolIds: ['lobe-skills', 'lobe-activator'],
}),
);
expect(chatService.createAssistantMessageStream).toHaveBeenCalledWith(
@@ -346,7 +346,7 @@ export const createAgentExecutors = (context: {
const messages = llmPayload.messages.filter((message) => message.id !== assistantMessageId);
// Expand dynamically activated tools (from lobe-tools activateTools API)
// Expand dynamically activated tools (from lobe-activator activateTools API)
// and merge them into the agent config for this LLM call
const activatedToolIds = runtimeContext?.stepContext?.activatedToolIds;
let resolvedAgentConfig = context.agentConfig;
@@ -376,7 +376,7 @@ describe('ConversationLifecycle actions', () => {
expect.objectContaining({
apiName: 'activateSkill',
arguments: JSON.stringify({ name: 'User Memory' }),
identifier: 'lobe-skills',
identifier: 'lobe-activator',
}),
],
}),
@@ -391,7 +391,7 @@ describe('ConversationLifecycle actions', () => {
expect.objectContaining({
apiName: 'activateSkill',
arguments: JSON.stringify({ name: 'Instruction' }),
identifier: 'lobe-skills',
identifier: 'lobe-activator',
}),
],
}),
@@ -893,7 +893,7 @@ describe('StreamingExecutor actions', () => {
expect(generateToolsDetailed).toHaveBeenCalledWith(
expect.objectContaining({
skipDefaultTools: false,
skipDefaultTools: undefined,
toolIds: ['lobe-artifacts', 'lobe-notebook'],
}),
);
@@ -7,6 +7,7 @@ import {
} from '@lobechat/agent-runtime';
import { AgentRuntime, computeStepContext, GeneralChatAgent } from '@lobechat/agent-runtime';
import { PageAgentIdentifier } from '@lobechat/builtin-tool-page-agent';
import { manualModeExcludeToolIds } from '@lobechat/builtin-tools';
import { dynamicInterventionAudits } from '@lobechat/builtin-tools/dynamicInterventionAudits';
import { isDesktop } from '@lobechat/const';
import { type ToolsEngine } from '@lobechat/context-engine';
@@ -171,14 +172,15 @@ export class StreamingExecutorActionImpl {
{ model: agentConfigData.model, provider: agentConfigData.provider! },
effectivePluginIds,
);
// When skillActivateMode is 'manual', skipDefaultTools gives user precise control
// When skillActivateMode is 'manual', exclude only discovery tools (lobe-activator, lobe-skill-store)
// so that externally enabled tools (sandbox, web browsing, etc.) remain available
const isManualMode = agentConfig.chatConfig?.skillActivateMode === 'manual';
const toolsDetailed = toolsEngine.generateToolsDetailed({
excludeDefaultToolIds: isManualMode ? manualModeExcludeToolIds : undefined,
model: agentConfigData.model,
provider: agentConfigData.provider!,
skipDefaultTools: disableTools || isManualMode,
skipDefaultTools: disableTools,
toolIds: mergedToolIds,
});
@@ -488,7 +490,7 @@ export class StreamingExecutorActionImpl {
const currentDBMessages = this.#get().dbMessagesMap[messageKey] || [];
// Use selectTodosFromMessages selector (shared with UI display)
const todos = selectTodosFromMessages(currentDBMessages);
// Accumulate activated tool IDs from lobe-tools messages
// Accumulate activated tool IDs from lobe-activator messages
const activatedToolIds = selectActivatedToolIdsFromMessages(currentDBMessages);
// Accumulate activated skills from activateSkill messages
const activatedSkills = selectActivatedSkillsFromMessages(currentDBMessages);
@@ -1,6 +1,6 @@
import { LobeActivatorIdentifier } from '@lobechat/builtin-tool-activator';
import { GTDIdentifier } from '@lobechat/builtin-tool-gtd';
import { SkillsIdentifier } from '@lobechat/builtin-tool-skills';
import { LobeToolIdentifier } from '@lobechat/builtin-tool-tools';
import {
type StepActivatedSkill,
type StepContextTodos,
@@ -156,7 +156,7 @@ const inboxActiveTopicDbMessages = (state: ChatStoreState) => {
// ============= Activated Tools Selectors ========== //
/**
* Accumulate activated tool identifiers from all lobe-tools messages.
* Accumulate activated tool identifiers from all lobe-activator messages.
*
* Unlike todos (which take the latest snapshot), activated tools are
* cumulative once a tool is activated it stays active for the rest
@@ -173,7 +173,8 @@ export const selectActivatedToolIdsFromMessages = (
for (const msg of messages) {
if (
msg.role === 'tool' &&
msg.plugin?.identifier === LobeToolIdentifier &&
(msg.plugin?.identifier === LobeActivatorIdentifier ||
msg.plugin?.identifier === 'lobe-tools') &&
msg.pluginState?.activatedTools
) {
const activatedTools = msg.pluginState.activatedTools as Array<{ identifier?: string }>;
@@ -209,7 +210,9 @@ export const selectActivatedSkillsFromMessages = (
for (const msg of messages) {
if (
msg.role === 'tool' &&
msg.plugin?.identifier === SkillsIdentifier &&
(msg.plugin?.identifier === SkillsIdentifier ||
msg.plugin?.identifier === LobeActivatorIdentifier ||
msg.plugin?.identifier === 'lobe-tools') &&
msg.plugin?.apiName === 'activateSkill' &&
msg.pluginState?.id &&
msg.pluginState?.name
@@ -18,7 +18,7 @@ vi.mock('@/store/tool/selectors/tool', () => ({
}));
// Import after mocks
const { toolsActivatorExecutor } = await import('../lobe-tools');
const { activatorExecutor } = await import('../lobe-activator');
const makeBuiltinTool = (identifier: string, discoverable?: boolean) => ({
discoverable,
@@ -39,7 +39,7 @@ const makePlugin = (identifier: string) => ({
},
});
describe('lobe-tools executor discovery allowlist', () => {
describe('lobe-activator executor discovery allowlist', () => {
beforeEach(() => {
vi.clearAllMocks();
});
@@ -58,7 +58,7 @@ describe('lobe-tools executor discovery allowlist', () => {
{ description: 'desc', identifier: 'web-browsing', name: 'web-browsing' },
]);
const result = await toolsActivatorExecutor.invoke(
const result = await activatorExecutor.invoke(
'activateTools',
{ identifiers: ['web-browsing', 'internal-admin'] },
{ messageId: 'msg-1', operationId: 'op-1' },
@@ -83,7 +83,7 @@ describe('lobe-tools executor discovery allowlist', () => {
mockAvailableToolsForDiscovery.mockReturnValue([]);
const result = await toolsActivatorExecutor.invoke(
const result = await activatorExecutor.invoke(
'activateTools',
{ identifiers: ['secret-tool'] },
{ messageId: 'msg-1', operationId: 'op-1' },
@@ -108,7 +108,7 @@ describe('lobe-tools executor discovery allowlist', () => {
{ description: 'desc', identifier: 'community-plugin', name: 'community-plugin' },
]);
const result = await toolsActivatorExecutor.invoke(
const result = await activatorExecutor.invoke(
'activateTools',
{ identifiers: ['community-plugin'] },
{ messageId: 'msg-1', operationId: 'op-1' },
@@ -17,11 +17,11 @@ import { memoryExecutor } from '@lobechat/builtin-tool-memory/executor';
import { topicReferenceExecutor } from '@lobechat/builtin-tool-topic-reference/executor';
import type { BuiltinToolContext, BuiltinToolResult, IBuiltinToolExecutor } from '../types';
import { activatorExecutor } from './lobe-activator';
import { notebookExecutor } from './lobe-notebook';
import { pageAgentExecutor } from './lobe-page-agent';
import { skillStoreExecutor } from './lobe-skill-store';
import { skillsExecutor } from './lobe-skills';
import { toolsActivatorExecutor } from './lobe-tools';
import { webBrowsing } from './lobe-web-browsing';
// ==================== Import and register all executors ====================
@@ -140,7 +140,7 @@ registerExecutors([
pageAgentExecutor,
skillStoreExecutor,
skillsExecutor,
toolsActivatorExecutor,
activatorExecutor,
topicReferenceExecutor,
webBrowsing,
]);
@@ -1,24 +1,39 @@
/**
* Lobe Tools Executor
*
* Creates and exports the ToolsActivatorExecutor instance for registration.
* Creates and exports the ActivatorExecutor instance for registration.
* Resolves tool manifests from the tool store (installedPlugins + builtinTools).
*
* State tracking (getActivatedToolIds / markActivated) is intentionally a no-op
* because the activated state is persisted in message pluginState and accumulated
* by selectActivatedToolIdsFromMessages at each agentic loop step.
*/
import { builtinSkills } from '@lobechat/builtin-skills';
import {
ActivatorExecutionRuntime,
type ActivatorRuntimeService,
type ToolManifestInfo,
ToolsActivatorExecutionRuntime,
type ToolsActivatorRuntimeService,
} from '@lobechat/builtin-tool-tools/executionRuntime';
import { ToolsActivatorExecutor } from '@lobechat/builtin-tool-tools/executor';
} from '@lobechat/builtin-tool-activator/executionRuntime';
import { ActivatorExecutor } from '@lobechat/builtin-tool-activator/executor';
import { SkillsExecutionRuntime } from '@lobechat/builtin-tool-skills/executionRuntime';
import { filterBuiltinSkills } from '@/helpers/skillFilters';
import { agentSkillService } from '@/services/skill';
import { getToolStoreState } from '@/store/tool';
import { toolSelectors } from '@/store/tool/selectors/tool';
const service: ToolsActivatorRuntimeService = {
const skillsRuntime = new SkillsExecutionRuntime({
builtinSkills: filterBuiltinSkills(builtinSkills),
service: {
findAll: () => agentSkillService.list(),
findById: (id) => agentSkillService.getById(id),
findByName: (name) => agentSkillService.getByName(name),
readResource: (id, path) => agentSkillService.readResource(id, path),
},
});
const service: ActivatorRuntimeService = {
activateSkill: (args) => skillsRuntime.activateSkill(args),
getActivatedToolIds: () => [],
getToolManifests: async (identifiers: string[]): Promise<ToolManifestInfo[]> => {
const s = getToolStoreState();
@@ -70,6 +85,6 @@ const service: ToolsActivatorRuntimeService = {
markActivated: () => {},
};
const runtime = new ToolsActivatorExecutionRuntime({ service });
const runtime = new ActivatorExecutionRuntime({ service });
export const toolsActivatorExecutor = new ToolsActivatorExecutor(runtime);
export const activatorExecutor = new ActivatorExecutor(runtime);