File size: 5,925 Bytes
5e0532d
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
'use client';

import { Shield, BookOpen, Heart, Brain, Sparkles } from 'lucide-react';

interface ThinkingIndicatorProps {
  activeAgent?: string;
  stage?: 'routing' | 'thinking' | 'responding';
}

const agentConfig: Record<string, { icon: typeof Shield; color: string; label: string; description: string }> = {
  Gatekeeper: {
    icon: Shield,
    color: 'purple',
    label: 'Gatekeeper',
    description: 'Analyzing your intent...',
  },
  Theologian: {
    icon: BookOpen,
    color: 'blue',
    label: 'Theologian',
    description: 'Consulting Scripture...',
  },
  Healer: {
    icon: Heart,
    color: 'rose',
    label: 'Healer',
    description: 'Preparing pastoral care...',
  },
  Orchestrator: {
    icon: Brain,
    color: 'amber',
    label: 'Orchestrator',
    description: 'Coordinating response...',
  },
  System: {
    icon: Sparkles,
    color: 'neutral',
    label: 'System',
    description: 'Processing...',
  },
};

const colorClasses: Record<string, { bg: string; border: string; text: string; glow: string; pulse: string }> = {
  purple: {
    bg: 'bg-purple-500/20',
    border: 'border-purple-500/40',
    text: 'text-purple-400',
    glow: 'shadow-[0_0_20px_rgba(168,85,247,0.4)]',
    pulse: 'bg-purple-400',
  },
  blue: {
    bg: 'bg-blue-500/20',
    border: 'border-blue-500/40',
    text: 'text-blue-400',
    glow: 'shadow-[0_0_20px_rgba(59,130,246,0.4)]',
    pulse: 'bg-blue-400',
  },
  rose: {
    bg: 'bg-rose-500/20',
    border: 'border-rose-500/40',
    text: 'text-rose-400',
    glow: 'shadow-[0_0_20px_rgba(244,63,94,0.4)]',
    pulse: 'bg-rose-400',
  },
  amber: {
    bg: 'bg-amber-500/20',
    border: 'border-amber-500/40',
    text: 'text-amber-400',
    glow: 'shadow-[0_0_20px_rgba(245,158,11,0.4)]',
    pulse: 'bg-amber-400',
  },
  neutral: {
    bg: 'bg-neutral-500/20',
    border: 'border-neutral-500/40',
    text: 'text-neutral-400',
    glow: 'shadow-[0_0_20px_rgba(163,163,163,0.4)]',
    pulse: 'bg-neutral-400',
  },
};

export default function ThinkingIndicator({ activeAgent = 'Gatekeeper', stage = 'thinking' }: ThinkingIndicatorProps) {
  const agent = agentConfig[activeAgent] || agentConfig.System;
  const colors = colorClasses[agent.color] || colorClasses.neutral;
  const Icon = agent.icon;

  return (
    <div className="flex gap-3 items-start animate-fade-in">
      {/* Agent Icon with Pulsing Rings */}
      <div className="relative">
        <div className={`w-8 h-8 rounded-full ${colors.bg} flex items-center justify-center border ${colors.border} ${colors.glow} transition-all duration-500`}>
          <Icon className={`w-4 h-4 ${colors.text}`} />
        </div>
        {/* Sonar rings */}
        <div className="absolute inset-0 rounded-full animate-ping-slow opacity-30">
          <div className={`w-full h-full rounded-full ${colors.bg} border ${colors.border}`} />
        </div>
        <div className="absolute inset-0 rounded-full animate-ping-slower opacity-20" style={{ animationDelay: '0.5s' }}>
          <div className={`w-full h-full rounded-full ${colors.bg} border ${colors.border}`} />
        </div>
      </div>

      {/* Thinking Content */}
      <div className={`flex-1 rounded-2xl rounded-tl-sm p-4 ${colors.bg} border ${colors.border} backdrop-blur-sm`}>
        {/* Agent Badge */}
        <div className="flex items-center gap-2 mb-2">
          <span className={`text-[10px] font-mono uppercase tracking-wider ${colors.text}`}>
            {agent.label}
          </span>
          <div className="flex items-center gap-1">
            <span className={`w-1.5 h-1.5 rounded-full ${colors.pulse} animate-pulse`} />
            <span className="text-[10px] text-neutral-500">
              {stage === 'routing' ? 'Routing' : stage === 'responding' ? 'Generating' : 'Thinking'}
            </span>
          </div>
        </div>

        {/* Animated Thinking Dots */}
        <div className="flex items-center gap-3">
          <div className="flex items-center gap-1.5">
            <span className={`w-2 h-2 ${colors.pulse} rounded-full animate-bounce`} style={{ animationDelay: '0ms' }} />
            <span className={`w-2 h-2 ${colors.pulse} rounded-full animate-bounce`} style={{ animationDelay: '150ms' }} />
            <span className={`w-2 h-2 ${colors.pulse} rounded-full animate-bounce`} style={{ animationDelay: '300ms' }} />
          </div>
          <span className="text-sm text-neutral-400 italic">{agent.description}</span>
        </div>

        {/* Swarm Activity Indicator */}
        <div className="mt-3 pt-3 border-t border-white/5">
          <div className="flex items-center gap-2">
            <span className="text-[9px] text-neutral-600 uppercase tracking-wider">Swarm Activity</span>
            <div className="flex-1 h-1 bg-white/5 rounded-full overflow-hidden">
              <div
                className={`h-full ${colors.pulse} opacity-60 rounded-full animate-pulse`}
                style={{ width: '60%' }}
              />
            </div>
          </div>
          <div className="flex gap-1.5 mt-2">
            {Object.entries(agentConfig).slice(0, 4).map(([name, config]) => {
              const isActive = name === activeAgent;
              const agentColors = colorClasses[config.color];
              return (
                <div
                  key={name}
                  className={`flex items-center gap-1 px-1.5 py-0.5 rounded text-[8px] transition-all duration-300 ${
                    isActive
                      ? `${agentColors.bg} ${agentColors.border} border ${agentColors.text}`
                      : 'bg-white/5 text-neutral-600'
                  }`}
                >
                  <config.icon className="w-2.5 h-2.5" />
                  <span className="hidden sm:inline">{name.slice(0, 4)}</span>
                </div>
              );
            })}
          </div>
        </div>
      </div>
    </div>
  );
}