From 43dc8b6da2a6a57f8a60da3982e1f6629c42f4c0 Mon Sep 17 00:00:00 2001 From: npmrun <1549469775@qq.com> Date: Mon, 10 Aug 2026 00:26:28 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=A2=9E=E5=8A=A0=E5=AE=A1=E6=89=B9?= =?UTF-8?q?=E8=AE=BE=E7=BD=AE=E5=8A=9F=E8=83=BD=EF=BC=8C=E6=94=AF=E6=8C=81?= =?UTF-8?q?=E6=89=8B=E5=8A=A8=E5=92=8C=E8=87=AA=E5=8A=A8=E5=AE=A1=E6=89=B9?= =?UTF-8?q?=E6=A8=A1=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/pages/settings/preferences.vue | 129 +++++++++++++++++++++++ packages/drizzle-pkg/db.sqlite | Bin 1220608 -> 1220608 bytes server/api/agents/[agentSlug]/chat/index.post.ts | 3 + server/service/agent/chat-engine.ts | 11 +- server/service/config/registry.ts | 8 ++ 5 files changed, 150 insertions(+), 1 deletion(-) diff --git a/app/pages/settings/preferences.vue b/app/pages/settings/preferences.vue index 4356882..1642998 100644 --- a/app/pages/settings/preferences.vue +++ b/app/pages/settings/preferences.vue @@ -12,8 +12,10 @@ interface ModelOption { const models = ref([]); const preferredModelId = ref(null); +const reviewApprovalMode = ref("manual"); const loading = ref(false); const saving = ref(false); +const savingApproval = ref(false); async function loadModels() { try { @@ -37,6 +39,8 @@ async function loadUserConfig() { ); const val = res.data?.config?.preferredLlmModelId; preferredModelId.value = typeof val === "number" && val > 0 ? val : null; + const approvalVal = res.data?.config?.reviewApprovalMode; + reviewApprovalMode.value = typeof approvalVal === "string" && ["manual", "all-pass"].includes(approvalVal) ? approvalVal : "manual"; } catch { preferredModelId.value = null; } @@ -64,6 +68,23 @@ async function handleSave() { } } +async function handleSaveApproval() { + savingApproval.value = true; + try { + await $fetch("/api/config/me", { + method: "PUT", + body: { key: "reviewApprovalMode", value: reviewApprovalMode.value }, + }); + const { $toast } = useNuxtApp(); + $toast?.success?.("审批设置已保存"); + } catch { + const { $toast } = useNuxtApp(); + $toast?.error?.("保存失败,请稍后重试"); + } finally { + savingApproval.value = false; + } +} + onMounted(async () => { loading.value = true; await Promise.all([loadModels(), loadUserConfig()]); @@ -116,6 +137,60 @@ onMounted(async () => { + +
+
+

审批设置

+

Agent 调用工具时的审批策略

+
+ +
+
+ + + +
+ +
+ +
+
+
@@ -247,4 +322,58 @@ onMounted(async () => { padding: 24px; } } + +.approval-options { + display: flex; + flex-direction: column; + gap: 12px; +} + +.approval-option { + display: flex; + align-items: flex-start; + gap: 12px; + padding: 16px; + border: 1px solid var(--color-hairline); + border-radius: 8px; + cursor: pointer; + transition: all 0.15s ease; +} + +.approval-option:hover { + border-color: var(--color-primary); +} + +.approval-option.active { + border-color: var(--color-primary); + background: rgba(204, 120, 92, 0.05); +} + +.approval-radio { + margin-top: 2px; + accent-color: var(--color-primary); + cursor: pointer; +} + +.approval-content { + display: flex; + flex-direction: column; + gap: 4px; +} + +.approval-label { + font-size: 14px; + font-weight: 500; + color: var(--color-ink); +} + +.approval-desc { + font-size: 13px; + color: var(--color-muted); + line-height: 1.5; +} + +.settings-card + .settings-card { + margin-top: 24px; +} diff --git a/packages/drizzle-pkg/db.sqlite b/packages/drizzle-pkg/db.sqlite index fa66cd8e2b36db5f4ae1d4e2910d96b14848a475..1cc6767512ab4f5e6e310f65a03b5b9f6be98ac8 100644 GIT binary patch delta 28589 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 C*I;J= diff --git a/server/api/agents/[agentSlug]/chat/index.post.ts b/server/api/agents/[agentSlug]/chat/index.post.ts index 1613d1d..b04d248 100644 --- a/server/api/agents/[agentSlug]/chat/index.post.ts +++ b/server/api/agents/[agentSlug]/chat/index.post.ts @@ -57,8 +57,10 @@ export default defineEventHandler(async (event) => { const ip = getRequestIP(event, { xForwardedFor: true }) || "unknown"; let preferredModelId: number | null = null; + let reviewApprovalMode: string = "manual"; if (identity.userId) { preferredModelId = (await getConfigUser(event, "preferredLlmModelId")) ?? null; + reviewApprovalMode = (await getConfigUser(event, "reviewApprovalMode")) ?? "manual"; } const globalDefaultModelId = (await getConfigGlobal("agentDefaultModelId")) ?? null; @@ -84,6 +86,7 @@ export default defineEventHandler(async (event) => { ip, preferredModelId, globalDefaultModelId, + reviewApprovalMode, requestId: event.context.requestId, registerAbort: registerAbortController, unregisterAbort: unregisterAbortController, diff --git a/server/service/agent/chat-engine.ts b/server/service/agent/chat-engine.ts index 56d6e39..7315d06 100644 --- a/server/service/agent/chat-engine.ts +++ b/server/service/agent/chat-engine.ts @@ -46,6 +46,7 @@ export interface ChatEngineParams { ip: string; preferredModelId?: number | null; globalDefaultModelId?: number | null; + reviewApprovalMode?: string; requestId?: string; registerAbort: (sessionId: string, controller: AbortController) => void; unregisterAbort: (sessionId: string) => void; @@ -434,13 +435,21 @@ export async function executeChat(params: ChatEngineParams): Promise "approved" as const + : undefined; + const result = streamText({ model: languageModel, system: systemPrompt, messages: modelMessages, abortSignal: serverAbortController.signal, ...(Object.keys(tools).length > 0 - ? { tools, stopWhen: stepCountIs(maxSteps) } + ? { + tools, + stopWhen: stepCountIs(maxSteps), + ...(toolApproval ? { toolApproval } : {}), + } : {}), ...(thinkingEnabled ? { diff --git a/server/service/config/registry.ts b/server/service/config/registry.ts index cd8078f..eb17d8b 100644 --- a/server/service/config/registry.ts +++ b/server/service/config/registry.ts @@ -134,6 +134,14 @@ const CONFIG_REGISTRY = { userOverridable: true, validate: (value: number) => Number.isInteger(value) && value >= 0, }), + reviewApprovalMode: defineConfig({ + key: "reviewApprovalMode", + scope: "user", + valueType: "string", + defaultValue: "manual", + userOverridable: true, + validate: (value: string) => ["manual", "all-pass"].includes(value), + }), } as const; export type KnownConfigKey = keyof typeof CONFIG_REGISTRY;