后端 parallel_agents.py:每个并行席位 excluded_tools 增加 agent_orchestration (派活) 与 bash(脚本逃逸),并在任务消息里加「角色边界」护栏——根治弱模型拿到 带「总控/业务链条」语气的任务后模仿总控输出「总控调度指令…」、绕道 glob/bash 翻找派活脚本的问题。新增 /api/parallel-agents/auth/token 取 token 端点 (auth/csrf 豁免)。 parallel-agents-vue 面板:协作澄清卡片、步骤图标/步骤展示、API 与类型完善等。 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
96 lines
3.5 KiB
Vue
96 lines
3.5 KiB
Vue
<script setup lang="ts">
|
||
/**
|
||
* 步骤条 / 思维链卡 —— 1:1 复刻圆桌 Step2 的 MessageStepsCard + ChainOfThought:
|
||
* slate 边框卡 + 每步「图标列(带竖向连接线) + 中文文案 + 时间 + 参数子节点」。
|
||
*/
|
||
import { computed, ref } from "vue";
|
||
import type { DialogueStep } from "@/types";
|
||
import { getStepArgs, getStepDisplay } from "@/lib/step-display";
|
||
import StepIcon from "./StepIcon.vue";
|
||
|
||
const props = defineProps<{ steps: DialogueStep[]; streaming?: boolean }>();
|
||
const open = ref(true);
|
||
|
||
const rows = computed(() =>
|
||
props.steps.map((s, i) => {
|
||
const display = getStepDisplay(s.key, s.label, s.args);
|
||
return {
|
||
step: s,
|
||
display,
|
||
args: getStepArgs(s.key, s.args),
|
||
// 最后一步在 streaming 时为「进行中」(前景色),其余为已完成(次级色)。
|
||
active: props.streaming && i === props.steps.length - 1,
|
||
isLast: i === props.steps.length - 1,
|
||
};
|
||
}),
|
||
);
|
||
</script>
|
||
|
||
<template>
|
||
<div class="pa-surface pa-border mb-2 w-full gap-1 rounded-lg border p-0.5">
|
||
<button
|
||
type="button"
|
||
class="flex w-full items-center gap-1.5 rounded-md px-2 py-1 text-left text-[11px] font-semibold pa-text-muted"
|
||
@click="open = !open"
|
||
>
|
||
<span class="inline-block transition-transform" :class="open ? 'rotate-90' : ''">▶</span>
|
||
<span>执行步骤({{ steps.length }})</span>
|
||
</button>
|
||
|
||
<div v-show="open" class="space-y-2 px-3 pb-2 pt-0.5">
|
||
<div
|
||
v-for="row in rows"
|
||
:key="row.step.id"
|
||
class="flex gap-2 text-sm"
|
||
:class="row.active ? 'pa-text' : 'pa-text-muted'"
|
||
>
|
||
<!-- 图标列 + 竖向连接线 -->
|
||
<div class="relative mt-0.5">
|
||
<StepIcon :name="row.display.icon" :size="16" />
|
||
<div
|
||
v-if="!row.isLast"
|
||
class="absolute left-1/2 -mx-px w-px"
|
||
style="top: 26px; bottom: -8px; background: var(--pa-border)"
|
||
/>
|
||
</div>
|
||
<!-- 文案 + 时间 + 参数 -->
|
||
<div class="min-w-0 flex-1 space-y-1 overflow-hidden">
|
||
<div class="leading-snug">
|
||
<span class="font-medium pa-text">{{ row.display.label }}</span>
|
||
<span class="ml-2 font-mono text-[11px] pa-text-muted">{{ row.step.ts }}</span>
|
||
</div>
|
||
|
||
<!-- 参数子节点(按 kind 渲染,对齐 renderStepArgs) -->
|
||
<template v-if="row.args">
|
||
<span
|
||
v-if="row.args.kind === 'chip'"
|
||
class="pa-surface pa-border inline-block max-w-full truncate rounded border px-1.5 py-0.5 text-[11px] pa-text-muted"
|
||
>
|
||
{{ row.args.text }}
|
||
</span>
|
||
<pre
|
||
v-else-if="row.args.kind === 'code'"
|
||
class="pa-md max-h-60 overflow-auto rounded-md p-2 text-[11px]"
|
||
><code>{{ row.args.text }}</code></pre>
|
||
<span
|
||
v-else-if="row.args.kind === 'text'"
|
||
class="line-clamp-2 block text-[11px] leading-snug pa-text-muted"
|
||
>
|
||
{{ row.args.text }}
|
||
</span>
|
||
<span v-else-if="row.args.kind === 'kv'" class="flex flex-wrap gap-1">
|
||
<span
|
||
v-for="p in row.args.pairs"
|
||
:key="p.k"
|
||
class="pa-surface pa-border inline-block rounded border px-1.5 py-0.5 text-[11px] pa-text-muted"
|
||
>
|
||
<span class="opacity-60">{{ p.k }}:</span> {{ p.v }}
|
||
</span>
|
||
</span>
|
||
</template>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</template>
|