mirror of
https://github.com/hellodigua/ChatLab.git
synced 2026-05-07 05:20:59 +08:00
feat: 重构 AI 工具分类体系
This commit is contained in:
@@ -1,31 +1,20 @@
|
||||
/**
|
||||
* 内置工具目录查询
|
||||
*
|
||||
* 提供前端展示所需的工具名称列表。
|
||||
* TS 工具名称列表位于 tools/definitions/index.ts,
|
||||
* SQL 工具名称列表位于 tools/definitions/sql-analysis.ts。
|
||||
* 基于 TOOL_REGISTRY 提供前端展示所需的工具目录(含分类信息)。
|
||||
*/
|
||||
|
||||
import { SQL_TOOL_NAMES, getSqlToolCatalog } from '../tools/definitions/sql-analysis'
|
||||
import { TS_TOOL_NAMES } from '../tools/definitions'
|
||||
import { TOOL_REGISTRY } from '../tools/definitions'
|
||||
import type { ToolCategory } from '../tools/types'
|
||||
|
||||
/**
|
||||
* 获取所有内置工具的名称列表(TS + SQL,供前端展示勾选列表)
|
||||
*/
|
||||
export function getAllBuiltinToolNames(): string[] {
|
||||
return [...TS_TOOL_NAMES, ...SQL_TOOL_NAMES]
|
||||
export interface BuiltinToolCatalogEntry {
|
||||
name: string
|
||||
category: ToolCategory
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取所有内置工具的目录信息(名称 + 描述,供前端展示)
|
||||
* 获取所有内置工具的目录(含分类),供前端展示
|
||||
*/
|
||||
export function getAllBuiltinToolCatalog(): Array<{ name: string; description: string }> {
|
||||
return getSqlToolCatalog()
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取内置 TS 工具的名称列表
|
||||
*/
|
||||
export function getBuiltinTsToolNames(): string[] {
|
||||
return TS_TOOL_NAMES
|
||||
export function getBuiltinToolCatalog(): BuiltinToolCatalogEntry[] {
|
||||
return TOOL_REGISTRY.map((e) => ({ name: e.name, category: e.category }))
|
||||
}
|
||||
|
||||
@@ -19,4 +19,4 @@ export {
|
||||
isGeneralAssistant,
|
||||
} from './manager'
|
||||
export { parseAssistantFile, serializeAssistant } from './parser'
|
||||
export { getBuiltinTsToolNames, getAllBuiltinToolNames, getAllBuiltinToolCatalog } from './builtinTools'
|
||||
export { getBuiltinToolCatalog, type BuiltinToolCatalogEntry } from './builtinTools'
|
||||
|
||||
@@ -1,33 +1,46 @@
|
||||
/**
|
||||
* 工具定义聚合
|
||||
* 收集 definitions/ 下所有工具的 createTool 工厂函数
|
||||
* 工具定义聚合 + 统一注册表
|
||||
*
|
||||
* TOOL_REGISTRY 是全局唯一的工具清单,驱动后端加载和前端目录展示。
|
||||
* 新增工具只需在此追加一条 ToolRegistryEntry。
|
||||
*/
|
||||
|
||||
export { createTool as createSearchMessages } from './search-messages'
|
||||
export { createTool as createGetRecentMessages } from './get-recent-messages'
|
||||
export { createTool as createGetMemberStats } from './get-member-stats'
|
||||
export { createTool as createGetTimeStats } from './get-time-stats'
|
||||
export { createTool as createGetMembers } from './get-group-members'
|
||||
export { createTool as createGetMemberNameHistory } from './get-member-name-history'
|
||||
export { createTool as createGetConversationBetween } from './get-conversation-between'
|
||||
export { createTool as createGetMessageContext } from './get-message-context'
|
||||
export { createTool as createSearchSessions } from './search-sessions'
|
||||
export { createTool as createGetSessionMessages } from './get-session-messages'
|
||||
export { createTool as createGetSessionSummaries } from './get-session-summaries'
|
||||
export { createTool as createGetChatOverview } from './get-chat-overview'
|
||||
export { sqlToolFactories, getSqlToolCatalog, SQL_TOOL_NAMES } from './sql-analysis'
|
||||
import type { ToolRegistryEntry } from '../types'
|
||||
|
||||
export const TS_TOOL_NAMES = [
|
||||
'get_chat_overview',
|
||||
'search_messages',
|
||||
'get_recent_messages',
|
||||
'get_member_stats',
|
||||
'get_time_stats',
|
||||
'get_members',
|
||||
'get_member_name_history',
|
||||
'get_conversation_between',
|
||||
'get_message_context',
|
||||
'search_sessions',
|
||||
'get_session_messages',
|
||||
'get_session_summaries',
|
||||
import { createTool as createGetChatOverview } from './get-chat-overview'
|
||||
import { createTool as createSearchMessages } from './search-messages'
|
||||
import { createTool as createGetRecentMessages } from './get-recent-messages'
|
||||
import { createTool as createGetMessageContext } from './get-message-context'
|
||||
import { createTool as createSearchSessions } from './search-sessions'
|
||||
import { createTool as createGetSessionMessages } from './get-session-messages'
|
||||
import { createTool as createGetMembers } from './get-group-members'
|
||||
import { createTool as createGetMemberStats } from './get-member-stats'
|
||||
import { createTool as createGetTimeStats } from './get-time-stats'
|
||||
import { createTool as createGetMemberNameHistory } from './get-member-name-history'
|
||||
import { createTool as createGetConversationBetween } from './get-conversation-between'
|
||||
import { createTool as createGetSessionSummaries } from './get-session-summaries'
|
||||
|
||||
import { sqlToolEntries } from './sql-analysis'
|
||||
|
||||
export { sqlToolEntries } from './sql-analysis'
|
||||
|
||||
export const TOOL_REGISTRY: ToolRegistryEntry[] = [
|
||||
// ==================== Core 工具(始终加载) ====================
|
||||
{ name: 'get_chat_overview', factory: createGetChatOverview, category: 'core' },
|
||||
{ name: 'search_messages', factory: createSearchMessages, category: 'core' },
|
||||
{ name: 'get_recent_messages', factory: createGetRecentMessages, category: 'core' },
|
||||
{ name: 'get_message_context', factory: createGetMessageContext, category: 'core' },
|
||||
{ name: 'search_sessions', factory: createSearchSessions, category: 'core' },
|
||||
{ name: 'get_session_messages', factory: createGetSessionMessages, category: 'core' },
|
||||
{ name: 'get_members', factory: createGetMembers, category: 'core' },
|
||||
|
||||
// ==================== Analysis 工具(按需加载) ====================
|
||||
{ name: 'get_member_stats', factory: createGetMemberStats, category: 'analysis' },
|
||||
{ name: 'get_time_stats', factory: createGetTimeStats, category: 'analysis' },
|
||||
{ name: 'get_member_name_history', factory: createGetMemberNameHistory, category: 'analysis' },
|
||||
{ name: 'get_conversation_between', factory: createGetConversationBetween, category: 'analysis' },
|
||||
{ name: 'get_session_summaries', factory: createGetSessionSummaries, category: 'analysis' },
|
||||
|
||||
// SQL 分析工具
|
||||
...sqlToolEntries,
|
||||
]
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
*/
|
||||
|
||||
import type { AgentTool } from '@mariozechner/pi-agent-core'
|
||||
import type { ToolContext } from '../types'
|
||||
import type { ToolContext, ToolRegistryEntry } from '../types'
|
||||
import type { CustomSqlToolDef } from '../../assistant/types'
|
||||
import { createSqlTool } from '../../assistant/sqlToolRunner'
|
||||
import { t as i18nT } from '../../../i18n'
|
||||
@@ -193,6 +193,15 @@ export const sqlToolFactories = SQL_TOOL_DEFS.map(
|
||||
createSqlTool(def, context)
|
||||
)
|
||||
|
||||
/**
|
||||
* SQL 工具注册表条目(全部为 analysis 类别)
|
||||
*/
|
||||
export const sqlToolEntries: ToolRegistryEntry[] = SQL_TOOL_DEFS.map((def) => ({
|
||||
name: def.name,
|
||||
factory: (context: ToolContext): AgentTool<any> => createSqlTool(def, context),
|
||||
category: 'analysis' as const,
|
||||
}))
|
||||
|
||||
/**
|
||||
* 所有内置 SQL 工具的名称集合(用于前端分组展示)
|
||||
*/
|
||||
|
||||
@@ -7,21 +7,9 @@
|
||||
|
||||
import type { AgentTool } from '@mariozechner/pi-agent-core'
|
||||
import type { ToolContext } from './types'
|
||||
import {
|
||||
createSearchMessages,
|
||||
createGetRecentMessages,
|
||||
createGetMemberStats,
|
||||
createGetTimeStats,
|
||||
createGetMembers,
|
||||
createGetMemberNameHistory,
|
||||
createGetConversationBetween,
|
||||
createGetMessageContext,
|
||||
createSearchSessions,
|
||||
createGetSessionMessages,
|
||||
createGetSessionSummaries,
|
||||
createGetChatOverview,
|
||||
sqlToolFactories,
|
||||
} from './definitions'
|
||||
import { TOOL_REGISTRY } from './definitions'
|
||||
|
||||
const CORE_TOOL_NAMES = new Set(TOOL_REGISTRY.filter((e) => e.category === 'core').map((e) => e.name))
|
||||
import { t as i18nT } from '../../i18n'
|
||||
import { preprocessMessages, type PreprocessableMessage } from '../preprocessor'
|
||||
import { formatMessageCompact } from './utils/format'
|
||||
@@ -31,24 +19,6 @@ import type { SkillDef } from '../skills/types'
|
||||
// 导出类型
|
||||
export * from './types'
|
||||
|
||||
type ToolFactory = (context: ToolContext) => AgentTool<any>
|
||||
|
||||
const coreFactories: ToolFactory[] = [
|
||||
createGetChatOverview,
|
||||
createSearchMessages,
|
||||
createGetRecentMessages,
|
||||
createGetMemberStats,
|
||||
createGetTimeStats,
|
||||
createGetMembers,
|
||||
createGetMemberNameHistory,
|
||||
createGetConversationBetween,
|
||||
createGetMessageContext,
|
||||
createSearchSessions,
|
||||
createGetSessionMessages,
|
||||
createGetSessionSummaries,
|
||||
...sqlToolFactories,
|
||||
]
|
||||
|
||||
/**
|
||||
* 将工具返回的结构化数据格式化为 LLM 友好的纯文本
|
||||
*
|
||||
@@ -208,21 +178,23 @@ function anonymizeMessageNames(messages: PreprocessableMessage[], ownerPlatformI
|
||||
/**
|
||||
* 获取所有可用的 AgentTool
|
||||
*
|
||||
* 根据配置动态过滤工具(如:语义搜索工具仅在启用 Embedding 时可用)
|
||||
* 根据当前 locale 动态翻译工具描述
|
||||
* 统一包装预处理层
|
||||
* - Core 工具始终加载,不受 allowedTools 白名单影响
|
||||
* - Analysis 工具仅在 allowedTools 中显式列出时才加载(opt-in)
|
||||
*
|
||||
* @param context 工具上下文
|
||||
* @param allowedTools 工具名称白名单(为空或 undefined 时返回全部工具)
|
||||
* @param allowedTools analysis 工具白名单(仅控制 analysis 工具)
|
||||
*/
|
||||
export function getAllTools(context: ToolContext, allowedTools?: string[]): AgentTool<any>[] {
|
||||
let tools: AgentTool<any>[] = coreFactories.map((f) => f(context))
|
||||
const coreTools = TOOL_REGISTRY.filter((e) => e.category === 'core').map((e) => e.factory(context))
|
||||
|
||||
let analysisTools: AgentTool<any>[] = []
|
||||
if (allowedTools && allowedTools.length > 0) {
|
||||
tools = tools.filter((t) => allowedTools.includes(t.name))
|
||||
analysisTools = TOOL_REGISTRY.filter((e) => e.category === 'analysis' && allowedTools.includes(e.name)).map((e) =>
|
||||
e.factory(context)
|
||||
)
|
||||
}
|
||||
|
||||
return tools.map(translateTool).map((t) => wrapWithPreprocessing(t, context))
|
||||
return [...coreTools, ...analysisTools].map(translateTool).map((t) => wrapWithPreprocessing(t, context))
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -272,7 +244,7 @@ export function createActivateSkillTool(
|
||||
}
|
||||
|
||||
if (skill.tools.length > 0 && allowedTools && allowedTools.length > 0) {
|
||||
const missing = skill.tools.filter((t) => !allowedTools.includes(t))
|
||||
const missing = skill.tools.filter((t) => !CORE_TOOL_NAMES.has(t) && !allowedTools.includes(t))
|
||||
if (missing.length > 0) {
|
||||
const msg = isZh
|
||||
? `当前助手缺少该技能所需的工具:${missing.join(', ')}`
|
||||
|
||||
@@ -2,8 +2,19 @@
|
||||
* AI Tools 类型定义
|
||||
*/
|
||||
|
||||
import type { AgentTool } from '@mariozechner/pi-agent-core'
|
||||
import type { PreprocessConfig } from '../preprocessor'
|
||||
|
||||
export type ToolCategory = 'core' | 'analysis'
|
||||
|
||||
export type ToolFactory = (context: ToolContext) => AgentTool<any>
|
||||
|
||||
export interface ToolRegistryEntry {
|
||||
name: string
|
||||
factory: ToolFactory
|
||||
category: ToolCategory
|
||||
}
|
||||
|
||||
/** Owner 信息(当前用户在对话中的身份) */
|
||||
export interface OwnerInfo {
|
||||
/** Owner 的 platformId */
|
||||
|
||||
@@ -673,11 +673,11 @@ export function registerAIHandlers({ win }: IpcContext): void {
|
||||
}
|
||||
})
|
||||
|
||||
ipcMain.handle('assistant:getBuiltinTsToolNames', async () => {
|
||||
ipcMain.handle('assistant:getBuiltinToolCatalog', async () => {
|
||||
try {
|
||||
return assistantManager.getBuiltinTsToolNames()
|
||||
return assistantManager.getBuiltinToolCatalog()
|
||||
} catch (error) {
|
||||
console.error('Failed to get builtin ts tool names:', error)
|
||||
console.error('Failed to get builtin tool catalog:', error)
|
||||
return []
|
||||
}
|
||||
})
|
||||
|
||||
@@ -725,8 +725,8 @@ export const assistantApi = {
|
||||
return ipcRenderer.invoke('assistant:getBuiltinCatalog')
|
||||
},
|
||||
|
||||
getBuiltinTsToolNames: (): Promise<string[]> => {
|
||||
return ipcRenderer.invoke('assistant:getBuiltinTsToolNames')
|
||||
getBuiltinToolCatalog: (): Promise<Array<{ name: string; category: 'core' | 'analysis' }>> => {
|
||||
return ipcRenderer.invoke('assistant:getBuiltinToolCatalog')
|
||||
},
|
||||
|
||||
importAssistant: (builtinId: string): Promise<{ success: boolean; error?: string }> => {
|
||||
|
||||
Vendored
+1
-1
@@ -721,7 +721,7 @@ interface AssistantApi {
|
||||
delete: (id: string) => Promise<{ success: boolean; error?: string }>
|
||||
reset: (id: string) => Promise<{ success: boolean; error?: string }>
|
||||
getBuiltinCatalog: () => Promise<BuiltinAssistantInfo[]>
|
||||
getBuiltinTsToolNames: () => Promise<string[]>
|
||||
getBuiltinToolCatalog: () => Promise<Array<{ name: string; category: 'core' | 'analysis' }>>
|
||||
importAssistant: (builtinId: string) => Promise<{ success: boolean; error?: string }>
|
||||
reimportAssistant: (id: string) => Promise<{ success: boolean; error?: string }>
|
||||
importFromMd: (rawMd: string) => Promise<{ success: boolean; id?: string; error?: string }>
|
||||
|
||||
@@ -49,8 +49,8 @@ description: Use when 用户希望根据一句自然语言需求创建新的 Cha
|
||||
- `applicableChatTypes`
|
||||
- `supportedLocales`
|
||||
- 生成普通 assistant 文件时,不要写 `builtinId`
|
||||
- 如果角色是通用且无需限制工具,优先省略 `allowedBuiltinTools` 字段,而不是硬塞一长串“全量工具”
|
||||
- `allowedBuiltinTools` 只能使用当前真实存在的工具名,不得臆造、不得引用旧名字
|
||||
- 如果角色无需分析工具,优先省略 `allowedBuiltinTools`(默认仅核心工具可用)
|
||||
- `allowedBuiltinTools` 仅填写分析工具名(核心工具始终可用,无需列出),不得臆造、不得引用旧名字
|
||||
- 最终写入路径固定为 `assistant/<locale>/<assistant-id>.md`
|
||||
- 目标语言固定为 `zh`、`en`、`ja`
|
||||
- 三个语言版本保持同一角色定位,但允许按语言做自然的本地化调整,不做机械直译
|
||||
@@ -120,24 +120,22 @@ description: Use when 用户希望根据一句自然语言需求创建新的 Cha
|
||||
|
||||
## 工具选择规则
|
||||
|
||||
- 默认原则:尽量放宽,除非明显不适合该角色
|
||||
- 先看角色是否真的需要工具白名单
|
||||
- 若角色边界宽泛,可省略 `allowedBuiltinTools`
|
||||
- 若角色边界明确,再按真实工具集合选择白名单
|
||||
- 选择时优先保留完成该角色所必需的基础检索工具,例如:
|
||||
- 消息搜索
|
||||
- 最近消息
|
||||
- 上下文查看
|
||||
- session 检索
|
||||
- 仅在角色明显聚焦时再额外限制,例如:
|
||||
- 强运营分析:保留群分析、排行、趋势工具
|
||||
- 强情感洞察:保留互动关系、对话回顾、上下文工具
|
||||
- 强客服分析:保留对话、上下文、未回复问题、消息类型工具
|
||||
工具分为两类:
|
||||
- **核心工具(core)**:始终启用,无需在 `allowedBuiltinTools` 中列出。包括:get_chat_overview, search_messages, get_recent_messages, get_message_context, search_sessions, get_session_messages, get_members
|
||||
- **分析工具(analysis)**:需在 `allowedBuiltinTools` 中显式列出才会启用
|
||||
|
||||
`allowedBuiltinTools` 仅用于控制分析工具,核心工具始终可用:
|
||||
- 若角色不需要分析工具,可省略 `allowedBuiltinTools`(默认仅核心工具可用)
|
||||
- 若角色需要特定分析能力,列出所需的分析工具名称
|
||||
- 仅在角色明显聚焦时选择对应的分析工具,例如:
|
||||
- 强运营分析:get_member_stats, get_time_stats, member_activity_trend, silent_members
|
||||
- 强情感洞察:mutual_interaction_pairs, reply_interaction_ranking, get_conversation_between
|
||||
- 强客服分析:unanswered_messages, message_type_breakdown, get_conversation_between
|
||||
|
||||
生成前做一次自检:
|
||||
|
||||
- 是否引用了不存在的工具名
|
||||
- 是否遗漏了完成该角色所需的基础工具
|
||||
- `allowedBuiltinTools` 中是否误放了核心工具(核心工具无需列出)
|
||||
- 是否包含明显与场景冲突的工具
|
||||
|
||||
## 输出模板
|
||||
@@ -153,8 +151,8 @@ applicableChatTypes:
|
||||
supportedLocales:
|
||||
- zh
|
||||
allowedBuiltinTools:
|
||||
- search_messages
|
||||
- get_recent_messages
|
||||
- get_member_stats
|
||||
- get_time_stats
|
||||
presetQuestions:
|
||||
- 示例问题 1
|
||||
- 示例问题 2
|
||||
@@ -182,7 +180,7 @@ presetQuestions:
|
||||
- `name`:允许本地化,不必逐字对应
|
||||
- `applicableChatTypes`:仅在能明确判断时写入;通用角色可省略
|
||||
- `supportedLocales`:按文件所属语言写单元素数组
|
||||
- `allowedBuiltinTools`:仅在需要限制工具范围时写入
|
||||
- `allowedBuiltinTools`:仅填写需要的分析工具名(核心工具无需列出,始终可用)
|
||||
- `presetQuestions`:建议 3 到 5 条,贴近该语言用户的自然表达
|
||||
|
||||
## 正文写法规则
|
||||
@@ -220,6 +218,6 @@ presetQuestions:
|
||||
- 把 assistant 产物写到 `skill/` 或 `skills/`,而不是 `assistant/`
|
||||
- 机械照抄 `.docs/ai/assistantSystem.md` 的旧字段
|
||||
- 在未确认中文预览前就直接落盘
|
||||
- 把所有工具名都塞进 `allowedBuiltinTools`
|
||||
- 把核心工具名塞进 `allowedBuiltinTools`(核心工具始终可用,不需要列出)
|
||||
- 多语言版本仅做逐字翻译,导致预设问题和语气不自然
|
||||
- 发现同名文件已存在,却直接覆盖
|
||||
|
||||
@@ -39,11 +39,16 @@ const localeOptions = [
|
||||
{ value: 'ja', label: '日本語' },
|
||||
]
|
||||
|
||||
const BUILTIN_TS_TOOLS = computed(() =>
|
||||
assistantStore.builtinTsToolNames.map((name) => ({
|
||||
name,
|
||||
description: t(`ai.assistant.builtinToolDesc.${name}`),
|
||||
}))
|
||||
const coreTools = computed(() =>
|
||||
assistantStore.builtinToolCatalog
|
||||
.filter((e) => e.category === 'core')
|
||||
.map((e) => ({ name: e.name, description: t(`ai.assistant.builtinToolDesc.${e.name}`) }))
|
||||
)
|
||||
|
||||
const analysisTools = computed(() =>
|
||||
assistantStore.builtinToolCatalog
|
||||
.filter((e) => e.category === 'analysis')
|
||||
.map((e) => ({ name: e.name, description: t(`ai.assistant.builtinToolDesc.${e.name}`) }))
|
||||
)
|
||||
|
||||
const form = ref({
|
||||
@@ -60,8 +65,8 @@ const newQuestion = ref('')
|
||||
const toolBadgeCount = computed(() => form.value.allowedBuiltinTools.length)
|
||||
|
||||
onMounted(async () => {
|
||||
if (assistantStore.builtinTsToolNames.length === 0) {
|
||||
await assistantStore.loadBuiltinTsToolNames()
|
||||
if (assistantStore.builtinToolCatalog.length === 0) {
|
||||
await assistantStore.loadBuiltinToolCatalog()
|
||||
}
|
||||
})
|
||||
|
||||
@@ -219,16 +224,15 @@ function toggleBuiltinTool(toolName: string) {
|
||||
}
|
||||
}
|
||||
|
||||
function isToolChecked(toolName: string): boolean {
|
||||
if (form.value.allowedBuiltinTools.length === 0) return true
|
||||
function isAnalysisToolChecked(toolName: string): boolean {
|
||||
return form.value.allowedBuiltinTools.includes(toolName)
|
||||
}
|
||||
|
||||
function selectAllTools() {
|
||||
form.value.allowedBuiltinTools = BUILTIN_TS_TOOLS.value.map((t) => t.name)
|
||||
function selectAllAnalysisTools() {
|
||||
form.value.allowedBuiltinTools = analysisTools.value.map((t) => t.name)
|
||||
}
|
||||
|
||||
function clearAllTools() {
|
||||
function clearAllAnalysisTools() {
|
||||
form.value.allowedBuiltinTools = []
|
||||
}
|
||||
|
||||
@@ -427,40 +431,74 @@ function closeModal() {
|
||||
</div>
|
||||
|
||||
<!-- 工具管理 Tab -->
|
||||
<div v-show="activeTab === 'tools'" class="space-y-6">
|
||||
<!-- 内置工具勾选区 -->
|
||||
<div v-show="activeTab === 'tools'" class="space-y-5">
|
||||
<!-- 核心工具区(始终启用) -->
|
||||
<div>
|
||||
<div class="mb-2 flex items-center justify-between">
|
||||
<h3 class="mb-1 text-sm font-medium text-gray-700 dark:text-gray-300">
|
||||
{{ t('ai.assistant.config.coreTools') }}
|
||||
</h3>
|
||||
<p class="mb-2.5 text-[10px] text-gray-400">
|
||||
{{ t('ai.assistant.config.coreToolsHint') }}
|
||||
</p>
|
||||
<div class="grid grid-cols-2 gap-1.5">
|
||||
<label
|
||||
v-for="tool in coreTools"
|
||||
:key="tool.name"
|
||||
class="flex items-start gap-2 rounded-md border border-gray-200 bg-gray-50/50 px-2.5 py-2 opacity-70 dark:border-gray-700 dark:bg-gray-800/30"
|
||||
>
|
||||
<input
|
||||
type="checkbox"
|
||||
checked
|
||||
disabled
|
||||
class="mt-0.5 h-3.5 w-3.5 shrink-0 rounded border-gray-300 text-gray-400"
|
||||
/>
|
||||
<div class="min-w-0">
|
||||
<div class="truncate text-xs font-medium text-gray-600 dark:text-gray-400">{{ tool.name }}</div>
|
||||
<div class="truncate text-[10px] text-gray-400 dark:text-gray-500">{{ tool.description }}</div>
|
||||
</div>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 分析工具区(按需开启) -->
|
||||
<div>
|
||||
<div class="mb-1 flex items-center justify-between">
|
||||
<h3 class="text-sm font-medium text-gray-700 dark:text-gray-300">
|
||||
{{ t('ai.assistant.config.builtinTools') }}
|
||||
{{ t('ai.assistant.config.analysisTools') }}
|
||||
</h3>
|
||||
<div v-if="!readonly" class="flex gap-2">
|
||||
<button class="text-[10px] text-primary-500 hover:text-primary-600" @click="selectAllTools">
|
||||
<button
|
||||
class="text-[10px] text-primary-500 hover:text-primary-600"
|
||||
@click="selectAllAnalysisTools"
|
||||
>
|
||||
{{ t('ai.assistant.config.selectAll') }}
|
||||
</button>
|
||||
<span class="text-[10px] text-gray-300 dark:text-gray-600">|</span>
|
||||
<button class="text-[10px] text-primary-500 hover:text-primary-600" @click="clearAllTools">
|
||||
<button
|
||||
class="text-[10px] text-primary-500 hover:text-primary-600"
|
||||
@click="clearAllAnalysisTools"
|
||||
>
|
||||
{{ t('ai.assistant.config.deselectAll') }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<p class="mb-3 text-[10px] text-gray-400">
|
||||
{{ t('ai.assistant.config.builtinToolsHint') }}
|
||||
<p class="mb-2.5 text-[10px] text-gray-400">
|
||||
{{ t('ai.assistant.config.analysisToolsHint') }}
|
||||
</p>
|
||||
<div class="grid grid-cols-2 gap-1.5">
|
||||
<label
|
||||
v-for="tool in BUILTIN_TS_TOOLS"
|
||||
v-for="tool in analysisTools"
|
||||
:key="tool.name"
|
||||
class="flex cursor-pointer items-start gap-2 rounded-md border px-2.5 py-2 transition-colors"
|
||||
:class="
|
||||
isToolChecked(tool.name)
|
||||
isAnalysisToolChecked(tool.name)
|
||||
? 'border-primary-200 bg-primary-50/50 dark:border-primary-800 dark:bg-primary-950/20'
|
||||
: 'border-gray-200 dark:border-gray-700'
|
||||
"
|
||||
>
|
||||
<input
|
||||
type="checkbox"
|
||||
:checked="form.allowedBuiltinTools.includes(tool.name)"
|
||||
:checked="isAnalysisToolChecked(tool.name)"
|
||||
:disabled="readonly"
|
||||
class="mt-0.5 h-3.5 w-3.5 shrink-0 rounded border-gray-300 text-primary-600 focus:ring-primary-500"
|
||||
@change="toggleBuiltinTool(tool.name)"
|
||||
|
||||
@@ -253,6 +253,10 @@
|
||||
"presetQuestions": "Preset Questions",
|
||||
"addQuestion": "Add a question...",
|
||||
"builtinTools": "Built-in Tools",
|
||||
"coreTools": "Core Tools",
|
||||
"coreToolsHint": "Essential data retrieval tools, always enabled",
|
||||
"analysisTools": "Analysis Tools",
|
||||
"analysisToolsHint": "Enable on demand. Only checked tools will be available to AI",
|
||||
"selectAll": "Select All",
|
||||
"deselectAll": "Deselect All",
|
||||
"builtinToolsHint": "No selection = all tools available. Only checked tools will be enabled.",
|
||||
@@ -303,13 +307,21 @@
|
||||
"get_recent_messages": "Get recent messages",
|
||||
"get_message_context": "Get message context",
|
||||
"get_conversation_between": "Get conversation between two members",
|
||||
"get_members": "Get group members",
|
||||
"get_members": "Get members",
|
||||
"get_member_stats": "Get member statistics",
|
||||
"get_member_name_history": "Get member name history",
|
||||
"get_time_stats": "Get time statistics",
|
||||
"search_sessions": "Search sessions",
|
||||
"get_session_messages": "Get session messages",
|
||||
"get_session_summaries": "Get session summaries"
|
||||
"get_session_summaries": "Get session summaries",
|
||||
"message_type_breakdown": "Message type distribution",
|
||||
"peak_chat_hours_by_member": "Member peak hours",
|
||||
"member_activity_trend": "Member activity trend",
|
||||
"silent_members": "Silent member detection",
|
||||
"reply_interaction_ranking": "Reply interaction ranking",
|
||||
"mutual_interaction_pairs": "Mutual interaction pairs",
|
||||
"member_message_length_stats": "Message length stats",
|
||||
"unanswered_messages": "Unanswered messages"
|
||||
}
|
||||
},
|
||||
"skill": {
|
||||
|
||||
@@ -253,6 +253,10 @@
|
||||
"presetQuestions": "プリセット質問",
|
||||
"addQuestion": "質問を追加...",
|
||||
"builtinTools": "標準ツール",
|
||||
"coreTools": "コアツール",
|
||||
"coreToolsHint": "基本データ取得ツール、常に有効、無効化不可",
|
||||
"analysisTools": "分析ツール",
|
||||
"analysisToolsHint": "必要に応じて有効化。チェックしたツールのみ AI が利用可能",
|
||||
"selectAll": "すべて選択",
|
||||
"deselectAll": "すべて解除",
|
||||
"builtinToolsHint": "何も選ばなければ全ツールを使います。選択した場合は、そのツールだけが有効になります。",
|
||||
@@ -303,13 +307,21 @@
|
||||
"get_recent_messages": "最近のメッセージを取得",
|
||||
"get_message_context": "メッセージのコンテキストを取得",
|
||||
"get_conversation_between": "2人のやり取りを取得",
|
||||
"get_members": "グループメンバー一覧を取得",
|
||||
"get_members": "メンバー一覧を取得",
|
||||
"get_member_stats": "メンバー統計を取得",
|
||||
"get_member_name_history": "メンバーの名前変更履歴を取得",
|
||||
"get_time_stats": "時間統計を取得",
|
||||
"search_sessions": "セッションを検索",
|
||||
"get_session_messages": "セッションメッセージを取得",
|
||||
"get_session_summaries": "セッション要約を取得"
|
||||
"get_session_summaries": "セッション要約を取得",
|
||||
"message_type_breakdown": "メッセージ種別分布",
|
||||
"peak_chat_hours_by_member": "メンバー活動時間帯",
|
||||
"member_activity_trend": "メンバー活動トレンド",
|
||||
"silent_members": "沈黙メンバー検出",
|
||||
"reply_interaction_ranking": "返信インタラクションランキング",
|
||||
"mutual_interaction_pairs": "相互インタラクションペア",
|
||||
"member_message_length_stats": "メッセージ長さ統計",
|
||||
"unanswered_messages": "未返信メッセージ"
|
||||
}
|
||||
},
|
||||
"skill": {
|
||||
|
||||
@@ -253,6 +253,10 @@
|
||||
"presetQuestions": "预设问题",
|
||||
"addQuestion": "添加新问题...",
|
||||
"builtinTools": "内置工具",
|
||||
"coreTools": "核心工具",
|
||||
"coreToolsHint": "基础数据获取工具,始终启用,不可关闭",
|
||||
"analysisTools": "分析工具",
|
||||
"analysisToolsHint": "按需开启的分析能力,勾选后才会对 AI 可用",
|
||||
"selectAll": "全选",
|
||||
"deselectAll": "全不选",
|
||||
"builtinToolsHint": "不勾选任何工具 = 全部工具可用。勾选后仅开放已选工具。",
|
||||
@@ -303,13 +307,21 @@
|
||||
"get_recent_messages": "获取最近消息",
|
||||
"get_message_context": "获取消息上下文",
|
||||
"get_conversation_between": "获取两人对话",
|
||||
"get_members": "获取群成员列表",
|
||||
"get_members": "获取成员列表",
|
||||
"get_member_stats": "获取成员统计",
|
||||
"get_member_name_history": "获取成员改名历史",
|
||||
"get_time_stats": "获取时间统计",
|
||||
"search_sessions": "搜索会话",
|
||||
"get_session_messages": "获取会话消息",
|
||||
"get_session_summaries": "获取会话摘要"
|
||||
"get_session_summaries": "获取会话摘要",
|
||||
"message_type_breakdown": "消息类型分布",
|
||||
"peak_chat_hours_by_member": "成员活跃时段",
|
||||
"member_activity_trend": "成员活跃趋势",
|
||||
"silent_members": "沉默成员检测",
|
||||
"reply_interaction_ranking": "回复互动排行",
|
||||
"mutual_interaction_pairs": "互动好友配对",
|
||||
"member_message_length_stats": "消息长度统计",
|
||||
"unanswered_messages": "未回复消息"
|
||||
}
|
||||
},
|
||||
"skill": {
|
||||
|
||||
@@ -253,6 +253,10 @@
|
||||
"presetQuestions": "預設問題",
|
||||
"addQuestion": "新增問題...",
|
||||
"builtinTools": "內建工具",
|
||||
"coreTools": "核心工具",
|
||||
"coreToolsHint": "基礎資料取得工具,始終啟用,無法關閉",
|
||||
"analysisTools": "分析工具",
|
||||
"analysisToolsHint": "按需開啟的分析能力,勾選後才會對 AI 可用",
|
||||
"selectAll": "全選",
|
||||
"deselectAll": "全不選",
|
||||
"builtinToolsHint": "若未勾選任何工具,代表全部可用;勾選後僅開放所選工具。",
|
||||
@@ -303,13 +307,21 @@
|
||||
"get_recent_messages": "取得最近訊息",
|
||||
"get_message_context": "取得訊息上下文",
|
||||
"get_conversation_between": "取得兩人對話",
|
||||
"get_members": "取得群成員列表",
|
||||
"get_members": "取得成員列表",
|
||||
"get_member_stats": "取得成員統計",
|
||||
"get_member_name_history": "取得成員改名歷史",
|
||||
"get_time_stats": "取得時間統計",
|
||||
"search_sessions": "搜尋會話",
|
||||
"get_session_messages": "取得會話訊息",
|
||||
"get_session_summaries": "取得會話摘要"
|
||||
"get_session_summaries": "取得會話摘要",
|
||||
"message_type_breakdown": "訊息類型分佈",
|
||||
"peak_chat_hours_by_member": "成員活躍時段",
|
||||
"member_activity_trend": "成員活躍趨勢",
|
||||
"silent_members": "沉默成員偵測",
|
||||
"reply_interaction_ranking": "回覆互動排行",
|
||||
"mutual_interaction_pairs": "互動好友配對",
|
||||
"member_message_length_stats": "訊息長度統計",
|
||||
"unanswered_messages": "未回覆訊息"
|
||||
}
|
||||
},
|
||||
"skill": {
|
||||
|
||||
@@ -56,8 +56,8 @@ export const useAssistantStore = defineStore('assistant', () => {
|
||||
/** @deprecated 本地内置目录已清空,保留兼容 */
|
||||
const builtinCatalog = ref<BuiltinAssistantInfo[]>([])
|
||||
|
||||
/** 内置 TS 工具名称列表 */
|
||||
const builtinTsToolNames = ref<string[]>([])
|
||||
/** 内置工具目录(含分类) */
|
||||
const builtinToolCatalog = ref<Array<{ name: string; category: 'core' | 'analysis' }>>([])
|
||||
|
||||
/** 云端市场目录 */
|
||||
const cloudCatalog = ref<CloudAssistantItem[]>([])
|
||||
@@ -122,11 +122,11 @@ export const useAssistantStore = defineStore('assistant', () => {
|
||||
}
|
||||
}
|
||||
|
||||
async function loadBuiltinTsToolNames(): Promise<void> {
|
||||
async function loadBuiltinToolCatalog(): Promise<void> {
|
||||
try {
|
||||
builtinTsToolNames.value = await window.assistantApi.getBuiltinTsToolNames()
|
||||
builtinToolCatalog.value = await window.assistantApi.getBuiltinToolCatalog()
|
||||
} catch (error) {
|
||||
console.error('[AssistantStore] Failed to load builtin ts tool names:', error)
|
||||
console.error('[AssistantStore] Failed to load builtin tool catalog:', error)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -311,7 +311,7 @@ export const useAssistantStore = defineStore('assistant', () => {
|
||||
selectedAssistant,
|
||||
isLoaded,
|
||||
builtinCatalog,
|
||||
builtinTsToolNames,
|
||||
builtinToolCatalog,
|
||||
cloudCatalog,
|
||||
cloudLoading,
|
||||
cloudError,
|
||||
@@ -324,7 +324,7 @@ export const useAssistantStore = defineStore('assistant', () => {
|
||||
hasMoreAssistants,
|
||||
loadAssistants,
|
||||
loadBuiltinCatalog,
|
||||
loadBuiltinTsToolNames,
|
||||
loadBuiltinToolCatalog,
|
||||
fetchCloudCatalog,
|
||||
importFromCloud,
|
||||
isCloudItemImported,
|
||||
|
||||
Reference in New Issue
Block a user