From 85cca36ddba014c196ee377d198dd57d0d694c25 Mon Sep 17 00:00:00 2001 From: fengxiangdebaozi <10845145+fengxiangdebaozi@user.noreply.gitee.com> Date: Thu, 18 Jun 2026 17:05:53 +0800 Subject: [PATCH] =?UTF-8?q?feat(roundtable):=20=E5=85=A5=E5=BA=93=E9=97=A8?= =?UTF-8?q?=E6=8E=A7=E2=80=94=E2=80=94=E6=9C=AA=E6=8C=82=E8=BD=BD=E5=85=A5?= =?UTF-8?q?=E5=BA=93=E6=8A=80=E8=83=BD=E5=88=99=E4=B8=8D=E6=98=BE=E7=A4=BA?= =?UTF-8?q?=E5=85=A5=E5=BA=93=E6=8C=89=E9=92=AE=E3=80=81=E4=B9=9F=E4=B8=8D?= =?UTF-8?q?=E6=89=A7=E8=A1=8C=E5=85=A5=E5=BA=93?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 门控改为「是否挂载了入库相关技能」:按 name/name_zh/description 含 `ingest` 或「入库」 识别任意启用的入库相关技能,不写死示例技能名(真实入库技能改名也能自动识别; 知识库检索类技能不误命中)。 - 操作层加保险:runIngest 在 ingestAvailableRef 为假时直接 no-op,未挂载技能/非深链 即使被触发也不执行任何入库动作。 Co-Authored-By: Claude Opus 4.8 (1M context) --- .../src/roundtable-planning/api/ingest.ts | 23 ++++++++++++++++--- .../hooks/useStep3Summary.ts | 2 ++ 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/frontend-web/src/roundtable-planning/api/ingest.ts b/frontend-web/src/roundtable-planning/api/ingest.ts index c0cc44ed..9f89a8ed 100644 --- a/frontend-web/src/roundtable-planning/api/ingest.ts +++ b/frontend-web/src/roundtable-planning/api/ingest.ts @@ -7,14 +7,31 @@ */ import { loadSkills } from "@/core/skills/api"; -/** 入库技能名(示例/真实共用同一名字,方便无缝替换)。 */ +/** 示例入库技能名(真实技能可改名;门控按「入库相关」关键字判断,不写死此名)。 */ export const INGEST_SKILL_NAME = "knowledge-base-ingest"; -/** 入库技能是否存在且启用。失败回退 false(不弹入库询问)。 */ +/** + * 是否为「入库相关」技能:按 name / name_zh / description 含 `ingest` 或「入库」判断。 + * 这样示例技能(knowledge-base-ingest)与**后续改了名的真实入库技能**都能识别; + * 而知识库**检索**类技能(如 knowledge-base-search「知识库检索」)不含「入库」/`ingest`,不会误命中。 + */ +export function isIngestRelatedSkill(s: { + name?: string; + name_zh?: string | null; + description?: string; +}): boolean { + const hay = `${s.name ?? ""} ${s.name_zh ?? ""} ${s.description ?? ""}`.toLowerCase(); + return hay.includes("ingest") || hay.includes("入库"); +} + +/** + * 是否**挂载了**可用的入库相关技能(存在且启用)。失败回退 false。 + * 为 false 时第三步不显示入库按钮、不触发任何入库操作。 + */ export async function isIngestSkillAvailable(): Promise { try { const skills = await loadSkills(); - return skills.some((s) => s.name === INGEST_SKILL_NAME && s.enabled); + return skills.some((s) => s.enabled && isIngestRelatedSkill(s)); } catch { return false; } diff --git a/frontend-web/src/roundtable-planning/hooks/useStep3Summary.ts b/frontend-web/src/roundtable-planning/hooks/useStep3Summary.ts index 9535d910..c5f2af36 100644 --- a/frontend-web/src/roundtable-planning/hooks/useStep3Summary.ts +++ b/frontend-web/src/roundtable-planning/hooks/useStep3Summary.ts @@ -1253,6 +1253,8 @@ export function useStep3Summary( */ const runIngest = useCallback( async (opts?: { note?: string }) => { + // 未挂载入库技能(或非深链模式)→ 不执行任何入库操作。 + if (!ingestAvailableRef.current) return; setPendingIngestClarification(null); setIngestStatus("running"); const myRun = ++ingestRunRef.current;