Fold thinking deltas into the turn's stream-ordered entries as a thinking entry, merged back-to-back the way the stream delivers them, instead of one flat string rendered above every call. Each thinking block now sits where it streamed — between the calls it precedes. Live turns keep their thinking expanded; finished turns render it collapsed.
76 lines
2.0 KiB
Vue
76 lines
2.0 KiB
Vue
<script setup lang="ts">
|
|
// A turn's stream-ordered middle: tool rows, pieces of the thinking
|
|
// trace, the agent's asks, its handovers — each at the position the
|
|
// stream delivered it, so an ask sits at the tool call that raised it
|
|
// and thinking sits between the calls it precedes.
|
|
import type { TurnEntry } from '~/composables/useTranscript'
|
|
import type { ConsentAnswer } from '~/composables/useClaw'
|
|
|
|
defineProps<{
|
|
entries: TurnEntry[]
|
|
/** A live turn's thinking blocks start expanded; finished ones collapse. */
|
|
openThinking?: boolean
|
|
}>()
|
|
|
|
const emit = defineEmits<{
|
|
consentAnswer: [id: string, answer: ConsentAnswer]
|
|
consentDeny: [id: string]
|
|
downloadAttachment: [id: string, name: string]
|
|
}>()
|
|
</script>
|
|
|
|
<template>
|
|
<div v-if="entries.length > 0" class="entries">
|
|
<template v-for="(entry, index) in entries" :key="index">
|
|
<TurnToolRow v-if="entry.kind === 'tool'" :row="entry.row" />
|
|
<details v-else-if="entry.kind === 'thinking'" class="thinking" :open="openThinking">
|
|
<summary>thinking</summary>
|
|
<pre>{{ entry.text }}</pre>
|
|
</details>
|
|
<TurnConsentCard
|
|
v-else-if="entry.kind === 'consent'"
|
|
:consent="entry.consent"
|
|
@answer="(id, answer) => emit('consentAnswer', id, answer)"
|
|
@deny="(id) => emit('consentDeny', id)"
|
|
/>
|
|
<TurnAttachmentCard
|
|
v-else
|
|
:attachment="entry.attachment"
|
|
@download="(id, name) => emit('downloadAttachment', id, name)"
|
|
/>
|
|
</template>
|
|
</div>
|
|
</template>
|
|
|
|
<style scoped>
|
|
.entries {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 4px;
|
|
margin-bottom: 10px;
|
|
}
|
|
|
|
.thinking {
|
|
color: var(--text3);
|
|
}
|
|
|
|
.thinking summary {
|
|
cursor: pointer;
|
|
font-size: 11px;
|
|
letter-spacing: 0.1em;
|
|
text-transform: uppercase;
|
|
}
|
|
|
|
.thinking pre {
|
|
margin: 6px 0 0;
|
|
padding: 8px 10px;
|
|
background: var(--surface);
|
|
border: 1px solid var(--border);
|
|
border-radius: 6px;
|
|
color: var(--text3);
|
|
font-style: italic;
|
|
white-space: pre-wrap;
|
|
overflow-wrap: anywhere;
|
|
}
|
|
</style>
|