| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141 |
- import { Component, OnInit, OnDestroy, ViewChild, ElementRef, AfterViewChecked } from '@angular/core';
- import { CommonModule } from '@angular/common';
- import { FormsModule } from '@angular/forms';
- import { MatCardModule } from '@angular/material/card';
- import { MatInputModule } from '@angular/material/input';
- import { MatButtonModule } from '@angular/material/button';
- import { MatListModule } from '@angular/material/list';
- import { MatSelectModule } from '@angular/material/select';
- import { io, Socket } from 'socket.io-client';
- import { webConfig } from '../config';
- import { ThoughtPayload } from '../interfaces/interface';
- interface ChatMessage {
- content: string;
- sender: 'user' | 'bot';
- }
- @Component({
- selector: 'app-chat',
- standalone: true,
- imports: [
- CommonModule,
- FormsModule,
- MatCardModule,
- MatInputModule,
- MatButtonModule,
- MatListModule,
- MatSelectModule
- ],
- templateUrl: './chat.component.html',
- styleUrls: ['./chat.component.css']
- })
- export class ChatComponent implements OnInit, OnDestroy, AfterViewChecked {
- @ViewChild('scrollContainer') private scrollContainer!: ElementRef;
- messages: ChatMessage[] = [];
- inputMessage = '';
- loading = false;
- agentThoughts: ThoughtPayload[] = [];
- // Models
- models: ('openai' | 'gemini')[] = ['openai', 'gemini'];
- currentProvider: 'openai' | 'gemini' = 'openai';
- modelName: string = ''
- private socket!: Socket;
- ngOnInit() {
- this.initSocketConnection();
- }
- ngOnDestroy() {
- if (this.socket) this.socket.disconnect();
- }
- ngAfterViewChecked() {
- this.scrollToBottom();
- }
- private initSocketConnection() {
- this.socket = io(`${webConfig.exposedUrl}/ffb`);
- this.socket.on('connect', () => {
- console.log('Connected to FFB Gateway');
- // Request current model for this session
- this.socket.emit('get_model', {}, (res: any) => {
- // nothing happens. Response shoudl be in 'current model' event
- });
- });
- this.socket.on('agent_thought', (payload: ThoughtPayload) => {
- this.agentThoughts.push(payload);
- });
- this.socket.on('chat_response', (payload: { message: string }) => {
- this.messages.push({ content: payload.message, sender: 'bot' });
- this.loading = false;
- });
- this.socket.on('current_model', (data: any) => {
- // Update dropdown if server sends a model change
- if (data?.provider) {
- this.currentProvider = data.provider;
- this.modelName = data.modelName
- }
- });
- this.socket.on('error', (err) => console.error('Socket error:', err));
- }
- sendMessage() {
- const trimmedMessage = this.inputMessage.trim();
- if (!trimmedMessage || this.loading) return;
- this.messages.push({ content: trimmedMessage, sender: 'user' });
- this.loading = true;
- this.agentThoughts = [];
- this.socket.emit('chat', { message: trimmedMessage });
- this.inputMessage = '';
- }
- switchModel(model: 'openai' | 'gemini') {
- console.log('Switching model to:', model); // Debug log
- if (model === this.currentProvider) return; // Prevent switching to same model
- // Emit to backend
- this.socket.emit('switch_model', { provider: model }, (res: any) => {
- console.log('Switching model:', res?.data?.provider);
- });
- this.socket.emit('get_model', {}, (res: any) => {
- });
- }
- // Called by mat-select on selection change
- onModelSelect(event: any) {
- console.log('Dropdown selection:', event.value); // Debug log
- this.switchModel(event.value);
- }
- private scrollToBottom(): void {
- try {
- const el = this.scrollContainer.nativeElement;
- el.scrollTop = el.scrollHeight;
- } catch { }
- }
- // --- Template Helpers ---
- asString(key: unknown): string {
- return String(key);
- }
- shouldShowAttribute(key: unknown, value: any): boolean {
- const sKey = String(key);
- return !['node', 'status'].includes(sKey) && value != null && value !== '';
- }
- isObject(value: any): boolean {
- return value !== null && typeof value === 'object';
- }
- }
|