andy-stack_vaultkeeper-ai/Components/ThoughtIndicator.svelte
Andrew Beal 2bc12691d3 feat: add early tool call feedback for improved UI responsiveness
Emit tool call start events immediately when tools begin execution,
allowing UI to display contextual "thinking" messages (e.g., "Generating
note contents..." for WriteVaultFile) before tool completion. Add
Spinner to ThoughtIndicator component for visual feedback during tool
operations.
2026-02-16 17:40:14 +00:00

82 lines
No EOL
2 KiB
Svelte

<script lang="ts">
import { fade } from "svelte/transition";
import Spinner from "./Spinner.svelte";
export let thought: string | null = null;
export let thoughtIndicatorElement: HTMLElement | undefined = undefined;
export let editModeActive : boolean = false;
$: isVisible = thought !== null && thought.trim().length > 0;
</script>
{#if isVisible}
<div class="ai-thought-container" in:fade={{ duration: 200 }} out:fade={{ duration: 200 }} bind:this={thoughtIndicatorElement}>
<div class="ai-thought-bubble">
<span><Spinner {editModeActive}/> {thought}</span>
</div>
</div>
{/if}
<style>
.ai-thought-container {
margin-top: 0.25rem;
margin-bottom: 0.25rem;
}
.ai-thought-bubble {
--border-width: 1px;
position: relative;
display: inline-flex;
align-items: center;
border-radius: 10px;
max-width: 100%;
}
.ai-thought-bubble span {
position: relative;
z-index: 1;
background: var(--background-primary-alt);
border-radius: 10px;
padding: 0.55rem 0.7rem;
font-size: var(--font-smallest);
color: var(--text-muted);
font-style: italic;
word-wrap: break-word;
width: 100%;
display: inline-flex;
align-items: center;
gap: 0.5rem;
}
.ai-thought-bubble::after {
position: absolute;
content: "";
top: calc(-1 * var(--border-width));
left: calc(-1 * var(--border-width));
z-index: 0;
width: calc(100% + var(--border-width) * 2);
height: calc(100% + var(--border-width) * 2);
background: linear-gradient(
60deg,
hsl(224, 85%, 66%),
hsl(269, 85%, 66%),
hsl(314, 85%, 66%),
hsl(359, 85%, 66%),
hsl(44, 85%, 66%),
hsl(89, 85%, 66%),
hsl(134, 85%, 66%),
hsl(179, 85%, 66%)
);
background-size: 300% 300%;
background-position: 0 50%;
border-radius: 10px;
animation: moveGradient 3s alternate infinite;
}
@keyframes moveGradient {
50% {
background-position: 100% 50%;
}
}
</style>