Files
MyGoNavi/frontend/src/components/ai/aiLocalToolExecutor.ts
Syngnat 4162a6491b feat(ai-tools): 新增外部 SQL 目录探针
- 新增外部 SQL 目录快照构建与本地工具执行入口
- 补充内置工具目录、系统提示和状态文案
- 覆盖 AI 面板、工具注册与探针链路测试
2026-06-09 03:26:04 +08:00

175 lines
4.8 KiB
TypeScript

import type { SqlLog } from '../../store';
import type {
AIChatMessage,
AIContextItem,
AIMCPToolDescriptor,
AISkillConfig,
AIToolCall,
AIUserPromptSettings,
SavedConnection,
SavedQuery,
SqlSnippet,
ExternalSQLDirectory,
TabData,
} from '../../types';
import { executeDatabaseToolCall } from './aiDatabaseToolExecutor';
import {
buildDefaultLocalToolRuntime,
type AILocalToolRuntime,
type AIToolContextEntry,
} from './aiLocalToolRuntime';
import { executeSnapshotInspectionToolCall } from './aiSnapshotInspectionToolExecutor';
export type { AILocalToolRuntime, AIToolContextEntry } from './aiLocalToolRuntime';
export interface ExecuteLocalAIToolCallOptions {
toolCall: AIToolCall;
connections: SavedConnection[];
activeContext?: { connectionId: string; dbName: string } | null;
aiContexts?: Record<string, AIContextItem[]>;
aiChatHistory?: Record<string, AIChatMessage[]>;
aiChatSessions?: Array<{ id: string; title: string; updatedAt: number }>;
activeSessionId?: string | null;
tabs?: TabData[];
activeTabId?: string | null;
mcpTools: AIMCPToolDescriptor[];
toolContextMap: Map<string, AIToolContextEntry>;
sqlLogs?: SqlLog[];
savedQueries?: SavedQuery[];
sqlSnippets?: SqlSnippet[];
externalSQLDirectories?: ExternalSQLDirectory[];
skills?: AISkillConfig[];
userPromptSettings?: AIUserPromptSettings;
dynamicModels?: string[];
runtime?: Partial<AILocalToolRuntime>;
}
export interface ExecuteLocalAIToolCallResult {
content: string;
success: boolean;
toolName: string;
}
const buildToolName = (toolCall: AIToolCall, descriptor?: AIMCPToolDescriptor) =>
descriptor?.title || descriptor?.originalName || toolCall.function.name;
export async function executeLocalAIToolCall({
toolCall,
connections,
activeContext = null,
aiContexts = {},
aiChatHistory = {},
aiChatSessions = [],
activeSessionId = null,
tabs = [],
activeTabId = null,
mcpTools,
toolContextMap,
sqlLogs = [],
savedQueries = [],
sqlSnippets = [],
externalSQLDirectories = [],
skills = [],
userPromptSettings,
dynamicModels = [],
runtime,
}: ExecuteLocalAIToolCallOptions): Promise<ExecuteLocalAIToolCallResult> {
const mergedRuntime: AILocalToolRuntime = { ...buildDefaultLocalToolRuntime(), ...(runtime || {}) };
const descriptor = mcpTools.find((tool) => tool.alias === toolCall.function.name);
try {
const args = JSON.parse(toolCall.function.arguments || '{}');
const snapshotInspectionResult = await executeSnapshotInspectionToolCall({
toolName: toolCall.function.name,
args,
activeContext,
aiContexts,
aiChatHistory,
aiChatSessions,
activeSessionId,
connections,
tabs,
activeTabId,
mcpTools,
sqlLogs,
savedQueries,
sqlSnippets,
externalSQLDirectories,
skills,
userPromptSettings,
dynamicModels,
runtime: mergedRuntime,
});
if (snapshotInspectionResult) {
return {
content: snapshotInspectionResult.content,
success: snapshotInspectionResult.success,
toolName: buildToolName(toolCall, descriptor),
};
}
const databaseToolResult = await executeDatabaseToolCall({
toolName: toolCall.function.name,
args,
connections,
toolContextMap,
runtime: mergedRuntime,
});
if (databaseToolResult) {
return {
content: databaseToolResult.content,
success: databaseToolResult.success,
toolName: buildToolName(toolCall, descriptor),
};
}
if (!descriptor) {
return {
content: `Unknown function: ${toolCall.function.name}`,
success: false,
toolName: buildToolName(toolCall),
};
}
try {
const result = await mergedRuntime.callMCPTool?.(toolCall.function.name, toolCall.function.arguments || '{}');
return {
content: String(result?.content || (result?.isError ? 'MCP 工具调用失败' : '')),
success: !!result && !result.isError,
toolName: buildToolName(toolCall, descriptor),
};
} catch (error: any) {
return {
content: `MCP 工具调用失败: ${error?.message || error}`,
success: false,
toolName: buildToolName(toolCall, descriptor),
};
}
} catch (error: any) {
return {
content: error?.message || String(error),
success: false,
toolName: buildToolName(toolCall, descriptor),
};
}
}
export function buildToolResultMessage(params: {
id: string;
timestamp: number;
toolCall: AIToolCall;
execution: ExecuteLocalAIToolCallResult;
}): AIChatMessage {
const { id, timestamp, toolCall, execution } = params;
return {
id,
role: 'tool',
content: execution.content,
timestamp,
tool_call_id: toolCall.id,
tool_name: execution.toolName,
success: execution.success,
};
}