🐛 fix(ai-safety): 修正完全模式执行口径与本地工具失败判定

- 修正完全模式下 DML 与过程调用的安全提示和限制说明
- 区分连接探针失败与可恢复 SQL 执行错误,避免数据探针被误终止
- 修复本地 execute_sql 写语句结果返回 affectedRows
- 补充 AI 安全、本地工具执行与 SQL 限制回归测试
This commit is contained in:
Syngnat
2026-06-17 09:49:59 +08:00
parent 7ff3e00759
commit 3e140c1bc6
14 changed files with 254 additions and 24 deletions

View File

@@ -18,6 +18,7 @@ import { dispatchAIChatPayload } from './aiChatPayloadDispatch';
import {
buildToolResultMessage,
executeLocalAIToolCall,
type ExecuteLocalAIToolCallResult,
type AIToolContextEntry,
} from './aiLocalToolExecutor';
@@ -96,6 +97,7 @@ export const useAIChatLocalTools = ({
}
const results: AIChatMessage[] = [];
const executions: ExecuteLocalAIToolCallResult[] = [];
const currentConnections = useStore.getState().connections;
for (const toolCall of toolCalls) {
const currentState = useStore.getState();
@@ -119,6 +121,7 @@ export const useAIChatLocalTools = ({
userPromptSettings,
dynamicModels,
});
executions.push(execution);
const toolResultMsg: AIChatMessage = buildToolResultMessage({
id: nextMessageId(),
timestamp: Date.now(),
@@ -130,8 +133,9 @@ export const useAIChatLocalTools = ({
await new Promise((resolve) => setTimeout(resolve, 150));
}
const anySuccess = results.some((message) => message.success === true);
if (anySuccess) {
const roundCountsAsFailure = executions.length > 0
&& executions.every((execution) => execution.success !== true && execution.countsAsProbeFailure !== false);
if (!roundCountsAsFailure) {
toolCallRoundRef.current = 0;
} else {
toolCallRoundRef.current += 1;