330 lines
9.2 KiB
TypeScript
330 lines
9.2 KiB
TypeScript
import api from '../api';
|
|
|
|
// ============================================================================
|
|
// TYPES & INTERFACES
|
|
// ============================================================================
|
|
|
|
export interface TeamsbotSession {
|
|
id: string;
|
|
instanceId: string;
|
|
mandateId: string;
|
|
meetingLink: string;
|
|
botName: string;
|
|
backgroundImageUrl?: string;
|
|
status: 'pending' | 'joining' | 'active' | 'leaving' | 'ended' | 'error';
|
|
startedAt?: string;
|
|
endedAt?: string;
|
|
startedByUserId: string;
|
|
bridgeSessionId?: string;
|
|
meetingChatId?: string;
|
|
summary?: string;
|
|
errorMessage?: string;
|
|
transcriptSegmentCount: number;
|
|
botResponseCount: number;
|
|
creationDate?: string;
|
|
lastModified?: string;
|
|
}
|
|
|
|
export interface TeamsbotTranscript {
|
|
id: string;
|
|
sessionId: string;
|
|
speaker?: string;
|
|
text: string;
|
|
timestamp: string;
|
|
confidence: number;
|
|
language?: string;
|
|
isFinal: boolean;
|
|
}
|
|
|
|
export interface TeamsbotBotResponse {
|
|
id: string;
|
|
sessionId: string;
|
|
responseText: string;
|
|
responseType: 'audio' | 'chat' | 'both';
|
|
detectedIntent: 'addressed' | 'question' | 'proactive' | 'none';
|
|
reasoning?: string;
|
|
triggeredByTranscriptId?: string;
|
|
modelName?: string;
|
|
processingTime: number;
|
|
priceCHF: number;
|
|
timestamp?: string;
|
|
}
|
|
|
|
export type TeamsbotResponseChannel = 'voice' | 'chat' | 'both';
|
|
export type TeamsbotJoinMode = 'systemBot' | 'anonymous' | 'userAccount';
|
|
|
|
export interface TeamsbotConfig {
|
|
botName: string;
|
|
backgroundImageUrl?: string;
|
|
aiSystemPrompt: string;
|
|
responseMode: 'auto' | 'manual' | 'transcribeOnly';
|
|
responseChannel: TeamsbotResponseChannel;
|
|
language: string;
|
|
voiceId?: string;
|
|
browserBotUrl?: string;
|
|
botAccountEmail?: string;
|
|
botAccountPassword?: string;
|
|
triggerIntervalSeconds: number;
|
|
triggerCooldownSeconds: number;
|
|
contextWindowSegments: number;
|
|
}
|
|
|
|
export interface TeamsbotSessionStats {
|
|
transcriptSegments: number;
|
|
botResponses: number;
|
|
totalCostCHF: number;
|
|
totalProcessingTime: number;
|
|
speakers: string[];
|
|
}
|
|
|
|
export interface StartSessionRequest {
|
|
meetingLink: string;
|
|
botName?: string;
|
|
backgroundImageUrl?: string;
|
|
connectionId?: string;
|
|
joinMode?: TeamsbotJoinMode;
|
|
sessionContext?: string;
|
|
}
|
|
|
|
export interface ConfigUpdateRequest {
|
|
botName?: string;
|
|
backgroundImageUrl?: string;
|
|
aiSystemPrompt?: string;
|
|
responseMode?: 'auto' | 'manual' | 'transcribeOnly';
|
|
responseChannel?: TeamsbotResponseChannel;
|
|
language?: string;
|
|
voiceId?: string;
|
|
browserBotUrl?: string;
|
|
botAccountEmail?: string;
|
|
botAccountPassword?: string;
|
|
triggerIntervalSeconds?: number;
|
|
triggerCooldownSeconds?: number;
|
|
contextWindowSegments?: number;
|
|
}
|
|
|
|
// Voice/Language Types (from Google TTS API)
|
|
export interface VoiceLanguage {
|
|
code: string;
|
|
name: string;
|
|
}
|
|
|
|
export interface VoiceOption {
|
|
name: string;
|
|
languageCodes: string[];
|
|
ssmlGender: string;
|
|
naturalSampleRateHertz: number;
|
|
}
|
|
|
|
// Auth Detection Test Types
|
|
export interface AuthTestResult {
|
|
variantId: string;
|
|
variantName: string;
|
|
success: boolean;
|
|
pageType: 'v2' | 'lightMeetings' | 'error' | 'unknown';
|
|
finalUrl: string;
|
|
hasSignInLink: boolean;
|
|
hasNameInput: boolean;
|
|
hasJoinButton: boolean;
|
|
authAttempted: boolean;
|
|
authSuccess: boolean | null;
|
|
screenshot?: string;
|
|
durationMs: number;
|
|
error?: string;
|
|
detectedSignals: string[];
|
|
}
|
|
|
|
export interface AuthTestResults {
|
|
meetingUrl: string;
|
|
timestamp: string;
|
|
variants: AuthTestResult[];
|
|
recommendation: string;
|
|
}
|
|
|
|
// SSE Event Types
|
|
export interface TeamsbotSSEEvent {
|
|
type: 'transcript' | 'botResponse' | 'analysis' | 'suggestedResponse' | 'statusChange' | 'error' | 'ping' | 'sessionState';
|
|
data: any;
|
|
timestamp?: string;
|
|
}
|
|
|
|
// ============================================================================
|
|
// API FUNCTIONS
|
|
// ============================================================================
|
|
|
|
/**
|
|
* Start a new Teams Bot session.
|
|
*/
|
|
export async function startSession(instanceId: string, request: StartSessionRequest): Promise<{ session: TeamsbotSession }> {
|
|
const response = await api.post(`/api/teamsbot/${instanceId}/sessions`, request);
|
|
return response.data;
|
|
}
|
|
|
|
/**
|
|
* List all sessions for a feature instance.
|
|
*/
|
|
export async function listSessions(instanceId: string, includeEnded = true): Promise<{ sessions: TeamsbotSession[] }> {
|
|
const response = await api.get(`/api/teamsbot/${instanceId}/sessions`, {
|
|
params: { includeEnded },
|
|
});
|
|
return response.data;
|
|
}
|
|
|
|
/**
|
|
* Get session details with transcripts and bot responses.
|
|
*/
|
|
export async function getSession(
|
|
instanceId: string,
|
|
sessionId: string,
|
|
includeTranscripts = true,
|
|
includeResponses = true,
|
|
): Promise<{
|
|
session: TeamsbotSession;
|
|
transcripts?: TeamsbotTranscript[];
|
|
botResponses?: TeamsbotBotResponse[];
|
|
stats?: TeamsbotSessionStats;
|
|
}> {
|
|
const response = await api.get(`/api/teamsbot/${instanceId}/sessions/${sessionId}`, {
|
|
params: { includeTranscripts, includeResponses },
|
|
});
|
|
return response.data;
|
|
}
|
|
|
|
/**
|
|
* Stop an active session.
|
|
*/
|
|
export async function stopSession(instanceId: string, sessionId: string): Promise<{ status: string; sessionId: string }> {
|
|
const response = await api.post(`/api/teamsbot/${instanceId}/sessions/${sessionId}/stop`);
|
|
return response.data;
|
|
}
|
|
|
|
/**
|
|
* Delete a session and all related data.
|
|
*/
|
|
export async function deleteSession(instanceId: string, sessionId: string): Promise<{ deleted: boolean }> {
|
|
const response = await api.delete(`/api/teamsbot/${instanceId}/sessions/${sessionId}`);
|
|
return response.data;
|
|
}
|
|
|
|
/**
|
|
* Get teamsbot configuration (instance-level defaults).
|
|
*/
|
|
export async function getConfig(instanceId: string): Promise<{ config: TeamsbotConfig }> {
|
|
const response = await api.get(`/api/teamsbot/${instanceId}/config`);
|
|
return response.data;
|
|
}
|
|
|
|
/**
|
|
* Update teamsbot configuration (instance-level defaults).
|
|
*/
|
|
export async function updateConfig(instanceId: string, updates: ConfigUpdateRequest): Promise<{ config: TeamsbotConfig }> {
|
|
const response = await api.put(`/api/teamsbot/${instanceId}/config`, updates);
|
|
return response.data;
|
|
}
|
|
|
|
/**
|
|
* Get per-user settings merged with instance defaults.
|
|
*/
|
|
export async function getUserSettings(instanceId: string): Promise<{ settings: any; effectiveConfig: TeamsbotConfig }> {
|
|
const response = await api.get(`/api/teamsbot/${instanceId}/settings`);
|
|
return response.data;
|
|
}
|
|
|
|
/**
|
|
* Update per-user settings.
|
|
*/
|
|
export async function updateUserSettings(instanceId: string, updates: ConfigUpdateRequest): Promise<{ settings: any; effectiveConfig: TeamsbotConfig }> {
|
|
const response = await api.put(`/api/teamsbot/${instanceId}/settings`, updates);
|
|
return response.data;
|
|
}
|
|
|
|
/**
|
|
* Reset per-user settings to instance defaults.
|
|
*/
|
|
export async function resetUserSettings(instanceId: string): Promise<{ settings: null; effectiveConfig: TeamsbotConfig }> {
|
|
const response = await api.delete(`/api/teamsbot/${instanceId}/settings`);
|
|
return response.data;
|
|
}
|
|
|
|
export interface SystemBot {
|
|
id: string;
|
|
mandateId: string;
|
|
name: string;
|
|
email: string;
|
|
isActive: boolean;
|
|
creationDate?: string;
|
|
}
|
|
|
|
/**
|
|
* List system bot accounts for this mandate.
|
|
*/
|
|
export async function listSystemBots(instanceId: string): Promise<{ bots: SystemBot[] }> {
|
|
const response = await api.get(`/api/teamsbot/${instanceId}/system-bots`);
|
|
return response.data;
|
|
}
|
|
|
|
/**
|
|
* Test TTS voice with AI-generated sample text. Returns base64-encoded audio.
|
|
*/
|
|
export async function testVoice(
|
|
instanceId: string,
|
|
botName: string,
|
|
language: string,
|
|
voiceId?: string,
|
|
): Promise<{ success: boolean; audio?: string; format?: string; text?: string; error?: string }> {
|
|
const response = await api.post(`/api/teamsbot/${instanceId}/voice/test`, {
|
|
botName,
|
|
language,
|
|
voiceId,
|
|
});
|
|
return response.data;
|
|
}
|
|
|
|
/**
|
|
* Fetch available TTS languages from Google Cloud.
|
|
* Returns array of language codes (e.g. ["de-DE", "en-US", ...])
|
|
*/
|
|
export async function fetchLanguages(): Promise<string[]> {
|
|
try {
|
|
const response = await api.get('/voice-google/languages');
|
|
return response.data?.languages || [];
|
|
} catch {
|
|
return [];
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Fetch available TTS voices for a language from Google Cloud.
|
|
*/
|
|
export async function fetchVoices(languageCode: string): Promise<VoiceOption[]> {
|
|
try {
|
|
const response = await api.get('/voice-google/voices', {
|
|
params: { languageCode },
|
|
});
|
|
return response.data?.voices || [];
|
|
} catch {
|
|
return [];
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Run auth detection tests against a Teams meeting URL.
|
|
* Tests 5 browser configuration variants to determine which ones
|
|
* receive the /v2/ (authenticated) vs light-meetings (anonymous) page.
|
|
* Does NOT join the meeting.
|
|
*/
|
|
export async function testAuth(instanceId: string, meetingUrl: string): Promise<AuthTestResults> {
|
|
const response = await api.post(`/api/teamsbot/${instanceId}/test-auth`, { meetingUrl }, {
|
|
timeout: 300000, // 5 minutes — tests run sequentially
|
|
});
|
|
return response.data;
|
|
}
|
|
|
|
/**
|
|
* Create an SSE EventSource for live session streaming.
|
|
* Returns the EventSource instance for the caller to manage.
|
|
*/
|
|
export function createSessionStream(instanceId: string, sessionId: string): EventSource {
|
|
const baseUrl = api.defaults.baseURL || '';
|
|
const url = `${baseUrl}/api/teamsbot/${instanceId}/sessions/${sessionId}/stream`;
|
|
return new EventSource(url, { withCredentials: true });
|
|
}
|