|
|
@@ -61,6 +61,16 @@
|
|
|
<div v-else-if="isStepOpen(item.key)" class="ai-trace__detail">
|
|
|
<ToolCallPanel :step="item.step" :message-id="messageId" />
|
|
|
</div>
|
|
|
+
|
|
|
+ <!-- 图谱直接挂在 get_case_graph 这一次工具调用下面,位置与产物卡片一致 -->
|
|
|
+ <GraphAnalysisBlock
|
|
|
+ v-if="graphOf(item.step)"
|
|
|
+ :key="`graph-${item.step.id}`"
|
|
|
+ class="ai-trace__graph"
|
|
|
+ :payload="graphOf(item.step)!.payload"
|
|
|
+ :query="graphOf(item.step)!.query"
|
|
|
+ :meta="graphOf(item.step)!.meta"
|
|
|
+ />
|
|
|
</template>
|
|
|
</template>
|
|
|
</div>
|
|
|
@@ -87,14 +97,17 @@
|
|
|
* 2. 历史消息 —— 后端只存了"思考全文 + 工具事件数组",没有时序字段,按 ReAct 常见形态
|
|
|
* (思考 i → 工具 i,多余的顺序接到末尾)近似排列。要精确还原需后端落库时一并保存事件顺序。
|
|
|
*/
|
|
|
- import { computed, onBeforeUnmount, ref, watch } from 'vue';
|
|
|
+ import { computed, defineAsyncComponent, onBeforeUnmount, ref, watch } from 'vue';
|
|
|
import type { ToolStep } from '../api/types';
|
|
|
import type { TraceNode } from '../store/chatStream';
|
|
|
import { toolLabel } from '../utils/constants';
|
|
|
+ import { parseGraphToolStep } from '../utils/graphToolData';
|
|
|
import { parseJsonPayload } from '../utils/parseMessageContent';
|
|
|
import Icon from '@/core/components/Icon/src/Icon.vue';
|
|
|
import ToolCallPanel from './ToolCallPanel.vue';
|
|
|
|
|
|
+ const GraphAnalysisBlock = defineAsyncComponent(() => import('./graph/GraphAnalysisBlock.vue'));
|
|
|
+
|
|
|
const props = withDefaults(
|
|
|
defineProps<{
|
|
|
/** 思考全文(多段之间以空行分隔)—— 历史消息的近似排列用 */
|
|
|
@@ -113,6 +126,18 @@
|
|
|
{ thinking: '', thinkingActive: false, steps: () => [], trace: () => [], active: false },
|
|
|
);
|
|
|
|
|
|
+ /** 每个 get_case_graph 工具步骤对应一个图谱块,渲染在该工具调用下方 */
|
|
|
+ const graphItemsByStep = computed(() => {
|
|
|
+ const map = new Map<string, NonNullable<ReturnType<typeof parseGraphToolStep>>>();
|
|
|
+ (props.steps || []).forEach((step) => {
|
|
|
+ const item = parseGraphToolStep(step);
|
|
|
+ if (item) map.set(String(step.id), item);
|
|
|
+ });
|
|
|
+ return map;
|
|
|
+ });
|
|
|
+
|
|
|
+ const graphOf = (step: ToolStep) => graphItemsByStep.value.get(String(step.id)) || null;
|
|
|
+
|
|
|
/* ---------------- 条目组装 ---------------- */
|
|
|
|
|
|
interface ThinkItem {
|
|
|
@@ -593,6 +618,10 @@
|
|
|
padding-left: 10px;
|
|
|
border-left: 2px solid var(--ai-border);
|
|
|
}
|
|
|
+
|
|
|
+ &__graph {
|
|
|
+ margin: 4px 0 var(--ai-sp-2);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
@keyframes ai-trace-pulse {
|