- {agent.name || agent.agent_id}
+
+
+
- {agent.description && (
-
- {agent.description}
+
+
+
+ {agent.name || agent.agent_id}
- )}
+ {agent.description && (
+
+ {agent.description}
+
+ )}
+
-
+ {/* 加入按钮:只有点它才加入(点卡片其它区域是看详情)。已加入显示「已加入」。 */}
+
{inChain ? (
已加入
) : (
-
{
+ e.stopPropagation();
+ onAdd();
+ }}
className={cn(
- "border border-transparent bg-muted px-2 py-1 text-[10px] font-semibold text-muted-foreground transition-all group-hover:border-primary/30 group-hover:bg-primary/10 group-hover:text-primary",
+ "inline-flex items-center gap-1 border border-primary/30 bg-primary/5 px-2 py-1 text-[10px] font-semibold text-primary transition-all hover:bg-primary/10",
R_CTRL,
)}
>
- 点击加入
-
+
+ 加入
+
)}
@@ -923,6 +1048,8 @@ function StagesColumn({
onRemoveSeat,
onMergeSeat,
onSplitSeat,
+ onStageGoalChange,
+ onSeatDetail,
}: {
stageGroups: StageGroups;
seatCount: number;
@@ -934,6 +1061,8 @@ function StagesColumn({
onRemoveSeat: (agentId: string) => void;
onMergeSeat: (agentId: string, targetStageIdx: number) => void;
onSplitSeat: (agentId: string) => void;
+ onStageGoalChange: (stageIdx: number, goal: string) => void;
+ onSeatDetail: (agentId: string, name?: string) => void;
}) {
// 跨 Stage 的全局序号(头像编号):每个 Stage 起始累加。
const stageStartIndex = useMemo(() => {
@@ -941,10 +1070,12 @@ function StagesColumn({
let acc = 0;
for (const g of stageGroups) {
out.push(acc);
- acc += g.length;
+ acc += g.seats.length;
}
return out;
}, [stageGroups]);
+ // 是否含并行 stage → 决定提示「目标仅对含并行的分层链条生效」。
+ const hasParallelStage = stageGroups.some((g) => g.seats.length > 1);
return (
onRemoveStage(stageIdx)}
onReorderStage={(dir) => onReorderStage(stageIdx, dir)}
onRemoveSeat={onRemoveSeat}
onMergeSeat={onMergeSeat}
onSplitSeat={onSplitSeat}
+ onGoalChange={(goal) => onStageGoalChange(stageIdx, goal)}
+ onSeatDetail={onSeatDetail}
/>
))}
@@ -1040,27 +1174,35 @@ function StageSection({
group,
stageCount,
startIndex,
+ hasParallelStage,
onRemoveStage,
onReorderStage,
onRemoveSeat,
onMergeSeat,
onSplitSeat,
+ onGoalChange,
+ onSeatDetail,
}: {
stageIdx: number;
- group: ChainSeat[];
+ group: StageGroup;
stageCount: number;
startIndex: number;
+ /** 整条链是否含并行 stage(决定目标输入框的提示语,目标仅 dag 模式生效)。 */
+ hasParallelStage: boolean;
onRemoveStage: () => void;
onReorderStage: (dir: -1 | 1) => void;
onRemoveSeat: (agentId: string) => void;
onMergeSeat: (agentId: string, targetStageIdx: number) => void;
onSplitSeat: (agentId: string) => void;
+ onGoalChange: (goal: string) => void;
+ onSeatDetail: (agentId: string, name?: string) => void;
}) {
const { setNodeRef, isOver } = useDroppable({ id: STAGE_PREFIX + stageIdx });
- const isParallel = group.length > 1;
+ const seats = group.seats;
+ const isParallel = seats.length > 1;
const isFirstStage = stageIdx === 0;
const isLastStage = stageIdx === stageCount - 1;
- const seatItemIds = group.map((s) => SEAT_PREFIX + s.agent_id);
+ const seatItemIds = seats.map((s) => SEAT_PREFIX + s.agent_id);
return (
@@ -1086,7 +1228,7 @@ function StageSection({
: "border-border bg-muted text-muted-foreground",
)}
>
- {isParallel ? `并行 ${group.length}` : "串行"}
+ {isParallel ? `并行 ${seats.length}` : "串行"}
@@ -1131,18 +1273,45 @@ function StageSection({
+ {/* 本阶段目标:告诉总控本阶段要产出什么、如何依赖上一阶段产出(仅含并行的分层链条生效)。 */}
+ {seats.length > 0 && (
+
+ )}
+
{/* Stage 内席位 */}
- {group.length === 0 ? (
+ {seats.length === 0 ? (
空 Stage —— 把席位拖到此处,或删除该 Stage。
) : (
- {group.map((seat, i) => (
+ {seats.map((seat, i) => (
onMergeSeat(seat.agent_id, stageIdx - 1)}
onMergeDown={() => onMergeSeat(seat.agent_id, stageIdx + 1)}
onSplit={() => onSplitSeat(seat.agent_id)}
+ onDetail={() => onSeatDetail(seat.agent_id, seat.name)}
/>
))}
@@ -1176,6 +1346,7 @@ function SeatStrip({
onMergeUp,
onMergeDown,
onSplit,
+ onDetail,
}: {
seat: ChainSeat;
globalIndex: number;
@@ -1187,6 +1358,7 @@ function SeatStrip({
onMergeUp: () => void;
onMergeDown: () => void;
onSplit: () => void;
+ onDetail: () => void;
}) {
const { attributes, listeners, setNodeRef, transform, transition, isDragging } =
useSortable({ id: SEAT_PREFIX + seat.agent_id });
@@ -1236,8 +1408,19 @@ function SeatStrip({
)}
- {/* 控制:并入上一阶段 / 独立成阶段 / 并入下一阶段 / 移除 */}
+ {/* 控制:查看详情 / 并入上一阶段 / 独立成阶段 / 并入下一阶段 / 移除 */}
+