Files
veridian/app/components/Message/Agent/Reasoning.vue
T

69 lines
2.4 KiB
Vue

<script setup lang="ts">
import type { MessagePart } from '~/composables/useChat';
import ReasoningBody from './ReasoningBody.vue';
const props = defineProps<{
part: Readonly<MessagePart>;
}>();
const reasoningOpen = ref(!props.part.finished);
const bodyRef = ref<InstanceType<typeof ReasoningBody> | null>(null);
watch(
() => props.part.finished,
() => {
reasoningOpen.value = !props.part.finished;
},
);
const toggleReasoning = async () => {
if (!props.part.finished) return;
reasoningOpen.value = !reasoningOpen.value;
if (!reasoningOpen.value) return;
await nextTick();
bodyRef.value?.scrollToBottom('instant');
bodyRef.value?.handleScroll();
};
const formatDuration = (ms: number) => {
const seconds = ms / 1000;
const minutes = Math.floor(seconds / 60);
const hours = Math.floor(minutes / 60);
if (hours > 0) {
return `${hours}h ${minutes % 60}m ${(seconds % 60).toFixed(1)}s`;
} else if (minutes > 0) {
return `${minutes}m ${(seconds % 60).toFixed(1)}s`;
} else {
return `${seconds.toFixed(1)}s`;
}
}
</script>
<template>
<div class="text-[--text-tertiary]">
<button @click="toggleReasoning" :class="[
'w-full @hover:bg-[var(--color-hover)] rounded-lg p-1 flex justify-between items-center transition-colors duration-200 ease-[cubic-bezier(0.5,_1,_0.89,_1)]',
part.finished ? '' : 'cursor-default'
]">
<span class="flex items-center gap-1">
<span
class="w-6 h-6 flex-shrink-0 rounded-lg overflow-hidden bg-[var(--bg-surface)] flex items-center justify-center">
<span class="i-mynaui-atom text-3 text-[var(--reasoning-accent)]"></span>
</span>
<span v-if="!part.finished" class="animate-pulse">
Deep Thinking
</span>
<span v-else>
Deeply Thought (in {{ formatDuration(new Date(part.lastUpdatedAt).getTime() - new
Date(part.createdAt).getTime()) }})
</span>
</span>
<span class="i-mynaui-chevron-down w-4 h-4 text-[var(--text-secondary)]"
:class="reasoningOpen ? '' : '-rotate-90'"></span>
</button>
<ReasoningBody v-if="reasoningOpen" ref="bodyRef" :part="part" />
</div>
</template>