|
|
@@ -1,6 +1,5 @@
|
|
|
<script setup lang="ts">
|
|
|
import { computed, ref } from 'vue'
|
|
|
-import AppIcon from '@/components/common/AppIcon.vue'
|
|
|
import type { UiToolCall } from './types'
|
|
|
|
|
|
const props = defineProps<{ tool: UiToolCall }>()
|
|
|
@@ -16,24 +15,21 @@ const detail = computed(() => {
|
|
|
<template>
|
|
|
<div class="tool-trace" :class="`tool-trace--${tool.status}`">
|
|
|
<button type="button" @click="open = !open">
|
|
|
- <span class="tool-trace__icon"><AppIcon name="tools" :size="14" /></span>
|
|
|
- <span class="tool-trace__copy"><strong>{{ tool.name }}</strong><small>{{ statusLabel }}<template v-if="tool.durationMs"> · {{ tool.durationMs }} ms</template></small></span>
|
|
|
- <span v-if="tool.status === 'running'" class="tool-trace__pulse" />
|
|
|
- <AppIcon name="chevron-down" :size="13" :class="{ rotated: open }" />
|
|
|
+ <span class="tool-trace__caret" :class="{ open }">›</span>
|
|
|
+ <strong>{{ tool.name }}</strong>
|
|
|
+ <small v-if="tool.status === 'error'">{{ statusLabel }}</small>
|
|
|
</button>
|
|
|
<pre v-if="open && detail">{{ detail }}</pre>
|
|
|
</div>
|
|
|
</template>
|
|
|
|
|
|
<style scoped>
|
|
|
-.tool-trace { margin: 7px 0; border: 1px solid var(--line); border-radius: 10px; background: var(--surface); overflow: hidden; }
|
|
|
-.tool-trace > button { display: flex; width: 100%; min-height: 42px; align-items: center; gap: 9px; padding: 6px 9px; border: 0; background: transparent; color: var(--text-secondary); cursor: pointer; text-align: left; }
|
|
|
-.tool-trace > button:hover { background: var(--surface-soft); }
|
|
|
-.tool-trace__icon { display: grid; place-items: center; width: 26px; height: 26px; border-radius: 7px; background: var(--surface-soft); }
|
|
|
-.tool-trace__copy { display: flex; min-width: 0; flex: 1; flex-direction: column; }.tool-trace__copy strong { color: var(--text-primary); font-size: 10px; font-weight: 580; }.tool-trace__copy small { margin-top: 2px; color: var(--text-muted); font-size: 9px; }
|
|
|
-.tool-trace__pulse { width: 5px; height: 5px; border-radius: 50%; background: var(--warning); animation: pulse 1s ease infinite; }
|
|
|
-.rotated { transform: rotate(180deg); }.app-icon { transition: transform 140ms ease; }
|
|
|
-pre { max-height: 260px; margin: 0; padding: 10px 12px; overflow: auto; border-top: 1px solid var(--line); background: var(--surface-soft); color: var(--text-secondary); font: 10px/1.55 var(--font-code); white-space: pre-wrap; overflow-wrap: anywhere; }
|
|
|
-.tool-trace--error { border-color: color-mix(in srgb, var(--danger) 30%, var(--line)); }
|
|
|
-@keyframes pulse { 50% { opacity: .3; } }
|
|
|
+.tool-trace { margin: 7px 0; color: var(--text-muted); }
|
|
|
+.tool-trace > button { display: inline-flex; min-height: 22px; align-items: center; gap: 7px; padding: 0; border: 0; background: transparent; color: inherit; cursor: pointer; font: 10px/1.5 var(--font-code); text-align: left; }
|
|
|
+.tool-trace > button:hover { color: var(--text-secondary); }
|
|
|
+.tool-trace > button strong { font: inherit; font-weight: 400; letter-spacing: .01em; }
|
|
|
+.tool-trace > button small { color: var(--danger); font: inherit; }
|
|
|
+.tool-trace__caret { display: inline-block; width: 9px; color: var(--text-muted); font-size: 13px; line-height: 1; transition: transform 120ms ease; }.tool-trace__caret.open { transform: rotate(90deg); }
|
|
|
+pre { max-width: min(680px, 100%); max-height: 260px; margin: 4px 0 2px 16px; padding: 8px 10px; overflow: auto; border-left: 1px dashed var(--line-strong); background: transparent; color: var(--text-secondary); font: 10px/1.55 var(--font-code); white-space: pre-wrap; overflow-wrap: anywhere; }
|
|
|
+.tool-trace--error { color: var(--danger); }
|
|
|
</style>
|