diff --git a/frontend-web/src/components/workspace/agents/agent-card.tsx b/frontend-web/src/components/workspace/agents/agent-card.tsx
index cfd7e8c2..c28771b0 100644
--- a/frontend-web/src/components/workspace/agents/agent-card.tsx
+++ b/frontend-web/src/components/workspace/agents/agent-card.tsx
@@ -229,6 +229,10 @@ export function AgentCard({ agent, layout = "card", onPublisherClick }: AgentCar
);
const [editPublished, setEditPublished] = useState(agent.published);
const [editIsPrivate, setEditIsPrivate] = useState(agent.is_private);
+ // 会商席位「技能识别强化」开关(弱模型补偿)。默认关。
+ const [editSeatSkillDirective, setEditSeatSkillDirective] = useState(
+ agent.seat_skill_directive ?? false,
+ );
const [editSquareId, setEditSquareId] = useState(agent.square_id ?? "");
const [publishPickerOpen, setPublishPickerOpen] = useState(false);
const { data: publishSquares } = usePublishSquares();
@@ -274,6 +278,7 @@ export function AgentCard({ agent, layout = "card", onPublisherClick }: AgentCar
setEditSquareId(agent.square_id ?? "");
setSelectedSkills(agent.skills ?? []);
setEditCommonQuestions(normalizeAgentQuestions(agent.common_questions));
+ setEditSeatSkillDirective(agent.seat_skill_directive ?? false);
}, [
agent.common_questions,
agent.description,
@@ -282,6 +287,7 @@ export function AgentCard({ agent, layout = "card", onPublisherClick }: AgentCar
agent.published,
agent.square_id,
agent.skills,
+ agent.seat_skill_directive,
editOpen,
]);
@@ -295,6 +301,8 @@ export function AgentCard({ agent, layout = "card", onPublisherClick }: AgentCar
if (agentDetail) {
setEditSoul(agentDetail.soul ?? "");
setEditCommonQuestions(normalizeAgentQuestions(agentDetail.common_questions));
+ // 列表响应不带 config 额外字段(seat_skill_directive 为 null),详情才有真值。
+ setEditSeatSkillDirective(agentDetail.seat_skill_directive ?? false);
} else {
setEditSoul(agent.soul ?? "");
}
@@ -386,6 +394,8 @@ export function AgentCard({ agent, layout = "card", onPublisherClick }: AgentCar
request.skills = selectedSkills;
if (JSON.stringify(nextQuestions) !== JSON.stringify(baselineQuestions))
request.common_questions = nextQuestions;
+ if (editSeatSkillDirective !== ((agentDetail?.seat_skill_directive ?? agent.seat_skill_directive) ?? false))
+ request.seat_skill_directive = editSeatSkillDirective;
if (Object.keys(request).length === 0) {
setEditOpen(false);
@@ -960,6 +970,19 @@ export function AgentCard({ agent, layout = "card", onPublisherClick }: AgentCar
onChange={setEditCommonQuestions}
/>
+
+
+
会商技能识别强化
+
+ 作为会商席位时,把已配置技能(含 SKILL.md 路径与「先 read_file
+ 再用」硬指令)拼进任务,补偿弱模型不识别技能。也可在业务链条配置里打开(任一即生效)。
+
+
+
+
公开发布
diff --git a/frontend-web/src/components/workspace/agents/agent-detail-panel.tsx b/frontend-web/src/components/workspace/agents/agent-detail-panel.tsx
index 9a40afc3..0d6bc0b1 100644
--- a/frontend-web/src/components/workspace/agents/agent-detail-panel.tsx
+++ b/frontend-web/src/components/workspace/agents/agent-detail-panel.tsx
@@ -76,6 +76,8 @@ interface AgentDraft {
published: boolean;
featured: boolean;
templateName: string;
+ /** 会商席位「技能识别强化」开关。 */
+ seatSkillDirective: boolean;
}
function draftFromAgent(agent: Agent): AgentDraft {
@@ -88,6 +90,7 @@ function draftFromAgent(agent: Agent): AgentDraft {
published: agent.published,
featured: agent.featured_order != null,
templateName: agent.template_name ?? "",
+ seatSkillDirective: agent.seat_skill_directive ?? false,
};
}
@@ -295,6 +298,8 @@ export function AgentDetailPanel({
if (draft.soul !== (agent.soul ?? "")) request.soul = draft.soul;
if (draft.templateName.trim() !== (agent.template_name ?? ""))
request.template_name = draft.templateName.trim();
+ if (draft.seatSkillDirective !== (agent.seat_skill_directive ?? false))
+ request.seat_skill_directive = draft.seatSkillDirective;
if (nextPublished !== agent.published) request.published = nextPublished;
if (JSON.stringify(draft.skills) !== JSON.stringify(agent.skills ?? []))
request.skills = draft.skills;
@@ -561,6 +566,21 @@ export function AgentDetailPanel({
配置后,对话生成的 Markdown 文件可一键发布到知识入库接口。
+
+
+
会商技能识别强化
+
+ 作为会商席位时,把已配置技能(含 SKILL.md 路径与「先 read_file
+ 再用」硬指令)拼进任务,补偿弱模型不识别技能。也可在业务链条配置中打开(任一即生效)。
+
+
+
+ setDraft({ ...draft, seatSkillDirective: checked })
+ }
+ />
+
公开发布
diff --git a/frontend-web/src/core/agents/types.ts b/frontend-web/src/core/agents/types.ts
index 0af55b85..283993f8 100644
--- a/frontend-web/src/core/agents/types.ts
+++ b/frontend-web/src/core/agents/types.ts
@@ -58,6 +58,10 @@ export interface Agent {
/** 入库模板名(外部知识入库接口的 templateName)。配置后该智能体会话中的
* Markdown 产物右上角出现"发布入库"按钮。空/缺省 = 不支持入库。 */
template_name?: string | null;
+ /** 会商席位「技能识别强化」开关。作为会商席位运行时,是否把本智能体配置的技能
+ * (名称 + SKILL.md 路径 + 必须先 read_file 的硬指令) 拼进本轮任务以补偿弱模型。
+ * 与业务链条同名开关取 OR。null/false = 关 (默认)。 */
+ seat_skill_directive?: boolean | null;
tags?: Tag[];
featured_order?: number | null;
/** Whether the current user has favorited (收藏) this agent. */
@@ -91,6 +95,8 @@ export interface CreateAgentRequest {
tool_groups?: string[] | null;
common_questions?: AgentQuestion[] | null;
template_name?: string | null;
+ /** 会商席位「技能识别强化」开关;缺省/false = 关。 */
+ seat_skill_directive?: boolean | null;
}
export interface UpdateAgentRequest {
@@ -106,4 +112,6 @@ export interface UpdateAgentRequest {
common_questions?: AgentQuestion[] | null;
/** 入库模板名;传空字符串表示清除。 */
template_name?: string | null;
+ /** 会商席位「技能识别强化」开关;缺省/false = 关。 */
+ seat_skill_directive?: boolean | null;
}
diff --git a/frontend-web/src/pages/NewAgentPage.tsx b/frontend-web/src/pages/NewAgentPage.tsx
index 4ab2564a..f3c165a3 100644
--- a/frontend-web/src/pages/NewAgentPage.tsx
+++ b/frontend-web/src/pages/NewAgentPage.tsx
@@ -83,6 +83,8 @@ export default function NewAgentPage() {
const [modelInput, setModelInput] = useState
("");
const [chatModelInput, setChatModelInput] = useState("");
const [templateNameInput, setTemplateNameInput] = useState("");
+ // 会商席位「技能识别强化」开关(弱模型补偿)。默认关。
+ const [seatSkillDirectiveInput, setSeatSkillDirectiveInput] = useState(false);
const [formError, setFormError] = useState("");
const [agentId, setAgentId] = useState("");
const [agent, setAgent] = useState(null);
@@ -230,6 +232,7 @@ export default function NewAgentPage() {
skills: selectedSkills,
model: modelOverride,
template_name: templateNameInput.trim(),
+ seat_skill_directive: seatSkillDirectiveInput,
});
setAgent(updated);
return updated;
@@ -251,6 +254,7 @@ export default function NewAgentPage() {
skills: selectedSkills,
model: modelOverride,
template_name: templateNameInput.trim(),
+ seat_skill_directive: seatSkillDirectiveInput,
});
setAgentId(created.id);
setAgent(created);
@@ -281,6 +285,7 @@ export default function NewAgentPage() {
selectedSkills,
soulInput,
templateNameInput,
+ seatSkillDirectiveInput,
t.agents.nameStepCheckError,
t.agents.nameStepNetworkError,
validateForm,
diff --git a/frontend-web/src/roundtable-planning/api/multi-agent.ts b/frontend-web/src/roundtable-planning/api/multi-agent.ts
index 316120fc..02c7fd99 100644
--- a/frontend-web/src/roundtable-planning/api/multi-agent.ts
+++ b/frontend-web/src/roundtable-planning/api/multi-agent.ts
@@ -234,6 +234,12 @@ export interface StreamMultiAgentRequest {
reasoningEffort?: "minimal" | "low" | "medium" | "high";
/** 仅 special 用;ultra 档置真,给席位解锁 `task` 子代理工具。 */
subagentEnabled?: boolean;
+ /**
+ * 仅 special 用。会商席位「技能识别强化」开关(沿用所选业务链条配置)。置 true 时后端把该
+ * 席位配置的技能(含 SKILL.md 路径 + 必须先 read_file 的硬指令)拼进本轮任务,补偿弱模型。
+ * 与该席位 agent 自身 config.yaml 的同名开关取 OR。省略 = false(关)。
+ */
+ seatSkillDirective?: boolean;
skillStopNames?: string[];
/**
* 仅 leader 用。置 true 表示这是「派活后让总控判断继续/综合」的轮次:后端会把各已交付
@@ -485,6 +491,8 @@ export async function streamMultiAgent(
thinking_enabled: req.thinkingEnabled,
reasoning_effort: req.reasoningEffort,
subagent_enabled: req.subagentEnabled,
+ // 仅 special 用;会商技能识别强化(沿用所选业务链条开关)。省略 → 后端按 false(关)处理。
+ seat_skill_directive: req.seatSkillDirective ?? false,
skill_stop_names: req.skillStopNames ?? [],
// 仅 leader 用;综合轮让后端注入各席位完整交付正文。省略 → 后端按 false 处理。
synthesis_mode: req.synthesisMode ?? false,
diff --git a/frontend-web/src/roundtable-planning/api/roundtable-jobs.ts b/frontend-web/src/roundtable-planning/api/roundtable-jobs.ts
index bcf251cd..befe38e1 100644
--- a/frontend-web/src/roundtable-planning/api/roundtable-jobs.ts
+++ b/frontend-web/src/roundtable-planning/api/roundtable-jobs.ts
@@ -98,6 +98,9 @@ function toStartBody(p: StartJobPayload) {
seedMessage: p.seedMessage,
threadIds: p.threadIds ?? null,
coordinatorName: p.coordinatorName ?? "roundtable-coordinator",
+ // 每席位技能识别强化映射 {agentId: bool}:沿用所选业务链条里各席位的开关;缺省 {}。
+ // 后端 run_seat 按 agentId 查表,与各席位 agent 自身开关取 OR。
+ seat_skill_directives: p.seatSkillDirectives ?? {},
...(seat
? {
thinking_enabled: seat.thinking_enabled,
diff --git a/frontend-web/src/roundtable-planning/components/BusinessChainPicker.tsx b/frontend-web/src/roundtable-planning/components/BusinessChainPicker.tsx
index 0254d886..9a1b5b36 100644
--- a/frontend-web/src/roundtable-planning/components/BusinessChainPicker.tsx
+++ b/frontend-web/src/roundtable-planning/components/BusinessChainPicker.tsx
@@ -150,18 +150,21 @@ export function BusinessChainPicker({
// 席位模型覆盖(链条配置):按 agent_id 取,空/缺省 = 跟随全局模型。
const modelById = new Map(selectedChain.seats.map((s) => [s.agent_id, s.model ?? null]));
const modelOf = (id: string) => modelById.get(id) ?? null;
+ // 席位「会商技能识别强化」开关(链条配置):按 agent_id 取,缺省 = 关。
+ const skillById = new Map(selectedChain.seats.map((s) => [s.agent_id, s.seat_skill_directive ?? false]));
+ const skillOf = (id: string) => skillById.get(id) ?? false;
// 链条带分层、过滤存活后仍并行 → dag 编排(携带快速/沙箱子模式);否则退回线性 chain。
if (dagPlan) {
// dag:席位顺序按 stage 展平(与 plan 一致)。
const agents = dagPlan.stages
.flatMap((st) => st.agentIds)
- .map((id) => ({ agent_id: id, name: nameOf(id), model: modelOf(id) }));
+ .map((id) => ({ agent_id: id, name: nameOf(id), model: modelOf(id), seat_skill_directive: skillOf(id) }));
onConfirm({ agents, mode: "dag", chain: chainMeta, plan: dagPlan, dagExecMode });
return;
}
- const agents = survivingSeats.map((s) => ({ agent_id: s.agent_id, name: nameOf(s.agent_id), model: modelOf(s.agent_id) }));
+ const agents = survivingSeats.map((s) => ({ agent_id: s.agent_id, name: nameOf(s.agent_id), model: modelOf(s.agent_id), seat_skill_directive: skillOf(s.agent_id) }));
onConfirm({ agents, mode: "chain", chain: chainMeta });
};
diff --git a/frontend-web/src/roundtable-planning/hooks/useStep2Orchestration.ts b/frontend-web/src/roundtable-planning/hooks/useStep2Orchestration.ts
index 70bfb38f..bf8e86e1 100644
--- a/frontend-web/src/roundtable-planning/hooks/useStep2Orchestration.ts
+++ b/frontend-web/src/roundtable-planning/hooks/useStep2Orchestration.ts
@@ -279,6 +279,12 @@ export interface UseStep2OrchestrationOptions {
* 智能体」弹窗确认时的 `SeatSelectionResult.seatMode` 决定。缺省 `pro`。
*/
selectedMode: SeatMode;
+ /**
+ * 每席位「技能识别强化」开关映射 {agentId: bool}(沿用所选业务链条里每个席位的配置)。
+ * 按 agentId 查表后透传给该 special 席位 run,与该席位 agent 自身 config.yaml 的同名开关取
+ * OR。recommend / 未选链条 → 空 {}(各席位仅靠其自身开关)。
+ */
+ seatSkillDirectives?: Record;
/**
* 编排模式:
* - `recommend`(默认)—— 总控自由派活循环(`runOrchestration`);
@@ -434,6 +440,7 @@ export function useStep2Orchestration(
currentStep,
selectedModel,
selectedMode,
+ seatSkillDirectives = {},
orchestrationMode,
orchestrationPlan,
dagExecMode = "fast",
@@ -567,6 +574,8 @@ export function useStep2Orchestration(
const selectedModelRef = useRef(selectedModel);
// 席位执行模式同样打到 ref,让席位调用在编排循环里读到最新值而不重建回调。
const selectedModeRef = useRef(selectedMode);
+ // 每席位技能识别强化映射(所选业务链条各席位开关)同样打到 ref,席位调用按 agentId 读最新值。
+ const seatSkillDirectivesRef = useRef>(seatSkillDirectives);
const agentConfigsRef = useRef>(agentConfigs);
const agentNameToRoleRef = useRef(agentNameToRole);
const threadIdsRef = useRef(threadIds);
@@ -606,6 +615,9 @@ export function useStep2Orchestration(
useEffect(() => {
selectedModeRef.current = selectedMode;
}, [selectedMode]);
+ useEffect(() => {
+ seatSkillDirectivesRef.current = seatSkillDirectives;
+ }, [seatSkillDirectives]);
useEffect(() => {
agentConfigsRef.current = agentConfigs;
}, [agentConfigs]);
@@ -1602,6 +1614,9 @@ export function useStep2Orchestration(
model: perSeatModel || selectedModelRef.current || undefined,
// 席位执行模式(快速/思考/专业问答/多智能体问答)→ thinking/reasoning/subagent。
...seatModeToRequestFields(selectedModeRef.current),
+ // 会商技能识别强化(该席位在所选业务链条里的开关,按 agentId 查表);与该席位
+ // agent 自身开关取 OR。
+ seatSkillDirective: seatSkillDirectivesRef.current[a.agentId] ?? false,
signal: subAborter.signal,
onTextDelta: (text) =>
a.isParallel ? ingestParallelDelta(a.bubbleId, text) : appendToDialogue(a.bubbleId, text),
@@ -2031,6 +2046,9 @@ export function useStep2Orchestration(
model: perSeatModel || selectedModelRef.current || undefined,
// 席位执行模式 → thinking/reasoning/subagent(与推荐/DAG 路径一致)。
...seatModeToRequestFields(selectedModeRef.current),
+ // 会商技能识别强化(该席位在所选业务链条里的开关,按 agentId 查表);与该席位
+ // agent 自身开关取 OR。
+ seatSkillDirective: seatSkillDirectivesRef.current[seat.agent_id] ?? false,
signal: subAborter.signal,
onTextDelta: (text) => appendToDialogue(subBubbleId, text),
onPhaseChange: (phase, toolName, args) => {
@@ -2371,6 +2389,9 @@ export function useStep2Orchestration(
model: perSeatModel || selectedModelRef.current || undefined,
// 席位执行模式 → thinking/reasoning/subagent(与推荐/链条路径一致)。
...seatModeToRequestFields(selectedModeRef.current),
+ // 会商技能识别强化(该席位在所选业务链条里的开关,按 agentId 查表);与该
+ // 席位 agent 自身开关取 OR。
+ seatSkillDirective: seatSkillDirectivesRef.current[agentId] ?? false,
signal: subAborter.signal,
// §6:并行席位走 ref 全量累积 + 节流 flush(只渲染选中的);单节点
// stage 实际串行,1 路流直接 setState 不卡,沿用 appendToDialogue。
diff --git a/frontend-web/src/roundtable-planning/lib/business-chain.ts b/frontend-web/src/roundtable-planning/lib/business-chain.ts
index 46b8d2a6..dfd68c94 100644
--- a/frontend-web/src/roundtable-planning/lib/business-chain.ts
+++ b/frontend-web/src/roundtable-planning/lib/business-chain.ts
@@ -29,6 +29,13 @@ export interface ChainSeat {
* 的 `handleConfirmAgents`)→ 走现有 per-seat 模型链路。
*/
model?: string | null;
+ /**
+ * 可选「会商技能识别强化」开关(弱模型补偿)。true = 该席位作为会商子智能体执行时,把其
+ * 配置的技能(名称 + SKILL.md 路径 + 必须先 read_file 的硬指令)拼进本轮任务。与该席位
+ * 智能体自身的同名开关(智能体编辑里的开关)取 OR。缺省 / false = 关。随 `seats` JSON 落库
+ * (无需 DB 列),在链条编辑器里逐席位开关。
+ */
+ seat_skill_directive?: boolean;
}
/** 一条可复用的业务链条(与后端 `/api/roundtable-chains` 记录对应)。 */
@@ -80,8 +87,9 @@ export interface SeatSelectionResult {
/**
* 有序席位 —— 与现有 `handleConfirmAgents` 入参兼容。dag 模式下按 stage 展平排序。
* `model` 为该席位在来源链条里配置的模型覆盖(空 / 缺省 = 跟随全局模型)。
+ * `seat_skill_directive` 为该席位在来源链条里配置的「技能识别强化」开关(缺省 = 关)。
*/
- agents: Array<{ agent_id: string; name: string; model?: string | null }>;
+ agents: Array<{ agent_id: string; name: string; model?: string | null; seat_skill_directive?: boolean }>;
/**
* 决定 Step 2 走哪种编排:
* - `recommend` 总控自由派活;
@@ -135,6 +143,9 @@ export function buildChainSeatSelection(
// 席位模型覆盖(链条配置):按 agent_id 取,空/缺省 = 跟随全局。
const modelById = new Map(chain.seats.map((s) => [s.agent_id, s.model ?? null]));
const modelOf = (id: string) => modelById.get(id) ?? null;
+ // 席位「技能识别强化」开关(链条配置):按 agent_id 取,缺省 = 关。
+ const skillById = new Map(chain.seats.map((s) => [s.agent_id, s.seat_skill_directive ?? false]));
+ const skillOf = (id: string) => skillById.get(id) ?? false;
const survivingSeats = chain.seats.filter((s) => existingIds.has(s.agent_id));
if (survivingSeats.length < CHAIN_MIN_SEATS) return null;
@@ -156,12 +167,12 @@ export function buildChainSeatSelection(
if (hasParallel || hasGoal || hasCoord) {
const agents = plan.stages
.flatMap((st) => st.agentIds)
- .map((id) => ({ agent_id: id, name: nameOf(id), model: modelOf(id) }));
+ .map((id) => ({ agent_id: id, name: nameOf(id), model: modelOf(id), seat_skill_directive: skillOf(id) }));
return { agents, mode: "dag", chain: chainMeta, plan, dagExecMode: "fast", seatMode: chain.seatMode };
}
}
- const agents = survivingSeats.map((s) => ({ agent_id: s.agent_id, name: nameOf(s.agent_id), model: modelOf(s.agent_id) }));
+ const agents = survivingSeats.map((s) => ({ agent_id: s.agent_id, name: nameOf(s.agent_id), model: modelOf(s.agent_id), seat_skill_directive: skillOf(s.agent_id) }));
return { agents, mode: "chain", chain: chainMeta, seatMode: chain.seatMode };
}
diff --git a/frontend-web/src/roundtable-planning/lib/chain-stages.ts b/frontend-web/src/roundtable-planning/lib/chain-stages.ts
index a077cc0c..0fc1c20f 100644
--- a/frontend-web/src/roundtable-planning/lib/chain-stages.ts
+++ b/frontend-web/src/roundtable-planning/lib/chain-stages.ts
@@ -126,6 +126,20 @@ export function setSeatModel(groups: StageGroups, agentId: string, model: string
});
}
+/**
+ * 设置某个席位的「会商技能识别强化」开关(不可变,供编辑器席位下拉 onChange)。
+ * 按 agent_id 定位,跨 stage 适用。随 `seats` JSON 落库。
+ */
+export function setSeatSkillDirective(groups: StageGroups, agentId: string, enabled: boolean): StageGroups {
+ return groups.map((g) => {
+ if (!g.seats.some((s) => s.agent_id === agentId)) return g;
+ return {
+ ...g,
+ seats: g.seats.map((s) => (s.agent_id === agentId ? { ...s, seat_skill_directive: enabled } : s)),
+ };
+ });
+}
+
// ── 变换(均返回新结构,不可变)──────────────────────────────────────────────
/** 末尾追加一个**新单席位 stage**(线性追加,pool 点击加入默认行为)。 */
diff --git a/frontend-web/src/roundtable-planning/lib/job-types.ts b/frontend-web/src/roundtable-planning/lib/job-types.ts
index 7c1da33e..6c3a9f4e 100644
--- a/frontend-web/src/roundtable-planning/lib/job-types.ts
+++ b/frontend-web/src/roundtable-planning/lib/job-types.ts
@@ -132,6 +132,11 @@ export interface StartJobPayload {
* reasoning/subagent 三字段发给后端。
*/
seatMode?: SeatMode;
+ /**
+ * 每席位「技能识别强化」开关映射 {agentId: bool}(沿用所选业务链条里每个席位的配置)。
+ * 后台席位 run 按 agentId 查表(与各席位智能体自身的同名开关取 OR)决定是否注入。缺省 {}。
+ */
+ seatSkillDirectives?: Record;
}
/** 终态集合——SSE/轮询判定作业是否结束。 */
diff --git a/frontend-web/src/roundtable-planning/pages/BusinessChainEditorPage.tsx b/frontend-web/src/roundtable-planning/pages/BusinessChainEditorPage.tsx
index 9fd1e2eb..5278e721 100644
--- a/frontend-web/src/roundtable-planning/pages/BusinessChainEditorPage.tsx
+++ b/frontend-web/src/roundtable-planning/pages/BusinessChainEditorPage.tsx
@@ -37,6 +37,7 @@ import {
Plus,
Save,
Sliders,
+ Sparkles,
SplitSquareVertical,
Trash2,
UserPlus,
@@ -63,6 +64,12 @@ import {
import { CSS } from "@dnd-kit/utilities";
import { cn } from "@/lib/utils";
+import {
+ DropdownMenu,
+ DropdownMenuContent,
+ DropdownMenuTrigger,
+} from "@/components/ui/dropdown-menu";
+import { Switch } from "@/components/ui/switch";
import { useDesensitizeSubtree } from "@/roundtable-planning/lib/use-desensitize-subtree";
import { TagSearchBar } from "@/components/workspace/tags/tag-search-bar";
import { ModelNameSelect } from "@/components/workspace/model-name-select";
@@ -105,6 +112,7 @@ import {
removeSeat as removeSeatFromGroups,
seatExistsInGroups,
setSeatModel,
+ setSeatSkillDirective,
setStageGoal,
splitSeatToNewStage,
stageGroupsToSeats,
@@ -366,6 +374,11 @@ export default function BusinessChainEditorPage() {
setStageGroups((prev) => setSeatModel(prev, agentId, model));
}, []);
+ // 席位「会商技能识别强化」开关:编辑器席位下拉 onChange。
+ const setSeatSkillDirectiveCb = useCallback((agentId: string, enabled: boolean) => {
+ setStageGroups((prev) => setSeatSkillDirective(prev, agentId, enabled));
+ }, []);
+
// ── 提示词 AI 优化(总控提示词 / 各 Stage 阶段目标)────────────────────────
const [optimizingCoordinator, setOptimizingCoordinator] = useState(false);
const [goalOptimizingIdx, setGoalOptimizingIdx] = useState(null);
@@ -564,6 +577,8 @@ export default function BusinessChainEditorPage() {
description: live?.description ?? s.description ?? "",
// 席位模型覆盖:随席位一起落库(空 → null = 跟随全局)。
model: s.model ?? null,
+ // 席位「会商技能识别强化」开关:随席位一起落库(缺省 = false 关)。
+ seat_skill_directive: s.seat_skill_directive ?? false,
};
});
// 总控编排提示:trim 后空串落 null(清空),与后端「空=不注入」一致。
@@ -1131,6 +1146,7 @@ export default function BusinessChainEditorPage() {
onMergeSeat={mergeSeatToStage}
onSplitSeat={splitSeat}
onSeatModelChange={setSeatModelCb}
+ onSeatSkillDirectiveChange={setSeatSkillDirectiveCb}
onStageGoalChange={setGoal}
goalOptimizingIdx={goalOptimizingIdx}
onOptimizeGoal={handleOptimizeStageGoal}
@@ -1309,6 +1325,7 @@ function StagesColumn({
onMergeSeat,
onSplitSeat,
onSeatModelChange,
+ onSeatSkillDirectiveChange,
onStageGoalChange,
goalOptimizingIdx,
onOptimizeGoal,
@@ -1325,6 +1342,7 @@ function StagesColumn({
onMergeSeat: (agentId: string, targetStageIdx: number) => void;
onSplitSeat: (agentId: string) => void;
onSeatModelChange: (agentId: string, model: string | null) => void;
+ onSeatSkillDirectiveChange: (agentId: string, enabled: boolean) => void;
onStageGoalChange: (stageIdx: number, goal: string) => void;
/** 正在 AI 优化阶段目标的 stage 下标(null = 没有进行中的优化)。 */
goalOptimizingIdx: number | null;
@@ -1423,6 +1441,7 @@ function StagesColumn({
onMergeSeat={onMergeSeat}
onSplitSeat={onSplitSeat}
onSeatModelChange={onSeatModelChange}
+ onSeatSkillDirectiveChange={onSeatSkillDirectiveChange}
onGoalChange={(goal) => onStageGoalChange(stageIdx, goal)}
goalOptimizing={goalOptimizingIdx === stageIdx}
anyGoalOptimizing={goalOptimizingIdx !== null}
@@ -1452,6 +1471,7 @@ function StageSection({
onMergeSeat,
onSplitSeat,
onSeatModelChange,
+ onSeatSkillDirectiveChange,
onGoalChange,
goalOptimizing,
anyGoalOptimizing,
@@ -1470,6 +1490,7 @@ function StageSection({
onMergeSeat: (agentId: string, targetStageIdx: number) => void;
onSplitSeat: (agentId: string) => void;
onSeatModelChange: (agentId: string, model: string | null) => void;
+ onSeatSkillDirectiveChange: (agentId: string, enabled: boolean) => void;
onGoalChange: (goal: string) => void;
/** 本 Stage 的阶段目标正在 AI 优化中。 */
goalOptimizing: boolean;
@@ -1631,6 +1652,7 @@ function StageSection({
onMergeDown={() => onMergeSeat(seat.agent_id, stageIdx + 1)}
onSplit={() => onSplitSeat(seat.agent_id)}
onModelChange={(model) => onSeatModelChange(seat.agent_id, model)}
+ onSkillDirectiveChange={(enabled) => onSeatSkillDirectiveChange(seat.agent_id, enabled)}
onDetail={() => onSeatDetail(seat.agent_id, seat.name)}
/>
))}
@@ -1654,6 +1676,7 @@ function SeatStrip({
onMergeDown,
onSplit,
onModelChange,
+ onSkillDirectiveChange,
onDetail,
}: {
seat: ChainSeat;
@@ -1668,6 +1691,8 @@ function SeatStrip({
onSplit: () => void;
/** 席位模型覆盖变更(null = 清除,跟随全局)。 */
onModelChange: (model: string | null) => void;
+ /** 席位「会商技能识别强化」开关变更。 */
+ onSkillDirectiveChange: (enabled: boolean) => void;
onDetail: () => void;
}) {
const { attributes, listeners, setNodeRef, transform, transition, isDragging } =
@@ -1739,8 +1764,41 @@ function SeatStrip({
- {/* 控制:查看详情 / 并入上一阶段 / 独立成阶段 / 并入下一阶段 / 移除 */}
+ {/* 控制:技能识别强化 / 查看详情 / 并入上一阶段 / 独立成阶段 / 并入下一阶段 / 移除 */}
+ {/* 会商技能识别强化:小图标 → 下拉框(开关 + 说明)。开启 = 高亮。 */}
+
+
+
+
+
+
+
+
会商技能识别强化
+
+ 开启后,该席位作为会商子智能体执行时,会把已配置的技能(含 SKILL.md
+ 路径与「先 read_file 再用」硬指令)拼进任务,补偿弱模型不识别技能。也可在该智能体编辑里打开(任一即生效)。
+
+
+
+
+
+