2026-03-28 13:52:11 +01:00
|
|
|
|
import { Type } from '@google/genai';
|
feat: website analysis pipeline, voice agent, configurator improvements
- Site analysis: cheerio HTML parsing, inline tech stack detection (~20 CMS/framework/analytics signatures), Google PageSpeed API integration
- Gemini Live voice agent: WebSocket-based real-time voice mode with live transcript, selection chips, and mid-conversation website analysis
- Type/Talk mode toggle with silent capability detection
- Stepped progress animation during brief generation (4 animated steps)
- URL + thoughts fields in Step 2, phone + contact preference in Step 3
- AI prompt improvements: dedicated website analysis section, 30-min call, concrete benefits, industry depth
- Email redesign: branded templates with logo, proper markdown rendering for both client and admin
- French locale support for AI-generated briefs
- Smaller checkmark, compact booking CTA, expanded brief area
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 13:41:35 +01:00
|
|
|
|
|
|
|
|
|
|
// ─── Constants ────────────────────────────────────────────────────────────────
|
|
|
|
|
|
|
|
|
|
|
|
export const GEMINI_LIVE_MODEL = 'gemini-3.1-flash-live-preview';
|
|
|
|
|
|
|
|
|
|
|
|
// ─── Agent Tools ─────────────────────────────────────────────────────────────
|
|
|
|
|
|
|
|
|
|
|
|
export const AGENT_TOOLS = [
|
|
|
|
|
|
{
|
|
|
|
|
|
name: 'update_selections',
|
|
|
|
|
|
description:
|
|
|
|
|
|
'Emit structured project data as it is confirmed during conversation. Call incrementally as each detail is captured.',
|
|
|
|
|
|
parameters: {
|
|
|
|
|
|
type: Type.OBJECT,
|
|
|
|
|
|
properties: {
|
|
|
|
|
|
services: {
|
|
|
|
|
|
type: Type.ARRAY,
|
|
|
|
|
|
items: { type: Type.STRING },
|
|
|
|
|
|
description: 'Selected services: web, systems, infrastructure',
|
|
|
|
|
|
},
|
|
|
|
|
|
aiEnabled: {
|
|
|
|
|
|
type: Type.BOOLEAN,
|
|
|
|
|
|
description: 'Whether AI integration is requested',
|
|
|
|
|
|
},
|
|
|
|
|
|
aiTypes: {
|
|
|
|
|
|
type: Type.ARRAY,
|
|
|
|
|
|
items: { type: Type.STRING },
|
|
|
|
|
|
description: 'AI types: teammate, customer-facing, data-intelligence, notsure',
|
|
|
|
|
|
},
|
|
|
|
|
|
industry: { type: Type.STRING, description: 'Industry sector' },
|
|
|
|
|
|
timeline: { type: Type.STRING, description: 'Timeline preference' },
|
|
|
|
|
|
currentSiteUrl: { type: Type.STRING, description: 'Current website URL' },
|
|
|
|
|
|
scope: { type: Type.STRING, description: 'Project goals/scope summary' },
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
name: 'analyze_website',
|
|
|
|
|
|
description:
|
|
|
|
|
|
'Analyze a website URL to understand its current technology, performance, and structure. Call when the user provides their current website URL.',
|
|
|
|
|
|
parameters: {
|
|
|
|
|
|
type: Type.OBJECT,
|
|
|
|
|
|
properties: {
|
|
|
|
|
|
url: { type: Type.STRING, description: 'The website URL to analyze' },
|
|
|
|
|
|
},
|
|
|
|
|
|
required: ['url'],
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
name: 'complete_brief',
|
|
|
|
|
|
description:
|
|
|
|
|
|
'Generate and send the project brief. Call once all information is collected and the user has confirmed their name and email.',
|
|
|
|
|
|
parameters: {
|
|
|
|
|
|
type: Type.OBJECT,
|
|
|
|
|
|
properties: {
|
|
|
|
|
|
name: { type: Type.STRING },
|
|
|
|
|
|
email: { type: Type.STRING },
|
|
|
|
|
|
company: { type: Type.STRING },
|
|
|
|
|
|
phone: { type: Type.STRING },
|
|
|
|
|
|
contactPreference: { type: Type.STRING },
|
|
|
|
|
|
services: { type: Type.ARRAY, items: { type: Type.STRING } },
|
|
|
|
|
|
aiEnabled: { type: Type.BOOLEAN },
|
|
|
|
|
|
aiTypes: { type: Type.ARRAY, items: { type: Type.STRING } },
|
|
|
|
|
|
industry: { type: Type.STRING },
|
|
|
|
|
|
timeline: { type: Type.STRING },
|
|
|
|
|
|
currentSiteUrl: { type: Type.STRING },
|
|
|
|
|
|
currentSiteThoughts: { type: Type.STRING },
|
|
|
|
|
|
scope: { type: Type.STRING },
|
|
|
|
|
|
},
|
|
|
|
|
|
required: ['name', 'email', 'services'],
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
|
|
// ─── System Prompt ────────────────────────────────────────────────────────────
|
|
|
|
|
|
|
|
|
|
|
|
export function buildSystemPrompt(locale: string): string {
|
|
|
|
|
|
const isFr = locale === 'fr';
|
|
|
|
|
|
|
|
|
|
|
|
if (isFr) {
|
|
|
|
|
|
return `Tu es l'assistant de projets LetsBe, un consultant amical et compétent pour LetsBe Solutions. Tu mènes toute cette conversation en français.
|
|
|
|
|
|
|
|
|
|
|
|
Présente-toi ainsi : "Bonjour, je suis l'assistant de projets LetsBe. Parlez-moi de votre projet et je préparerai un brief personnalisé pour vous."
|
|
|
|
|
|
|
|
|
|
|
|
Ton rôle est de guider naturellement la conversation à travers les sujets suivants :
|
|
|
|
|
|
1. Quels services ils recherchent (web, logiciels sur mesure, infrastructure privée)
|
|
|
|
|
|
2. S'ils souhaitent une intégration IA — et si oui, quel type (assistant interne, IA pour les clients, intelligence de données, ou pas encore sûr)
|
|
|
|
|
|
3. Leur secteur d'activité
|
|
|
|
|
|
4. Leur calendrier préféré
|
|
|
|
|
|
5. S'ils ont un site web actuel (propose de l'analyser si c'est le cas)
|
|
|
|
|
|
6. Leurs objectifs et la portée du projet
|
|
|
|
|
|
7. Enfin, leur prénom, nom et adresse e-mail pour envoyer le brief
|
|
|
|
|
|
|
|
|
|
|
|
Instructions :
|
|
|
|
|
|
- Appelle update_selections chaque fois qu'un point est confirmé dans la conversation.
|
|
|
|
|
|
- Appelle analyze_website dès que l'utilisateur fournit une URL — puis intègre naturellement les résultats dans la discussion.
|
|
|
|
|
|
- Appelle complete_brief une fois que le nom et l'e-mail sont confirmés.
|
|
|
|
|
|
- Garde tes réponses concises : 2 à 3 phrases maximum par tour.
|
|
|
|
|
|
- Sois chaleureux, direct et professionnel — jamais générique.
|
|
|
|
|
|
|
|
|
|
|
|
Faits clés sur LetsBe à mentionner si pertinent :
|
|
|
|
|
|
- Tout est développé sur mesure — aucun template, aucun constructeur de pages
|
|
|
|
|
|
- Infrastructure privée : le client possède et contrôle entièrement ses données et serveurs
|
|
|
|
|
|
- Petite équipe expérimentée avec des décennies d'expérience combinée
|
|
|
|
|
|
- Intégration IA profonde dans tous types de systèmes
|
|
|
|
|
|
- Souveraineté numérique et protection des données comme priorité`;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return `You are the LetsBe project assistant, a friendly and knowledgeable project consultant for LetsBe Solutions.
|
|
|
|
|
|
|
|
|
|
|
|
Introduce yourself: "Hi, I'm the LetsBe project assistant. Tell me about your project and I'll put together a personalized brief for you."
|
|
|
|
|
|
|
|
|
|
|
|
Your role is to walk through the following topics naturally in conversation:
|
|
|
|
|
|
1. What services they need (web, custom software, private infrastructure)
|
|
|
|
|
|
2. Whether they want AI integration — and if so, what kind (internal teammate, customer-facing, data intelligence, or not sure yet)
|
|
|
|
|
|
3. Their industry
|
|
|
|
|
|
4. Their timeline preference
|
|
|
|
|
|
5. Whether they have a current website (offer to analyze it if they do)
|
|
|
|
|
|
6. Their goals and project scope
|
|
|
|
|
|
7. Finally, their name and email to send the brief
|
|
|
|
|
|
|
|
|
|
|
|
Instructions:
|
|
|
|
|
|
- Call update_selections each time a data point is confirmed during the conversation.
|
|
|
|
|
|
- Call analyze_website as soon as the user provides a URL — then discuss the findings naturally.
|
|
|
|
|
|
- Call complete_brief once name and email are confirmed.
|
|
|
|
|
|
- Keep responses concise: 2–3 sentences maximum per turn.
|
|
|
|
|
|
- Be warm, direct, and professional — never generic.
|
|
|
|
|
|
|
|
|
|
|
|
Key facts about LetsBe to reference when relevant:
|
|
|
|
|
|
- Everything is custom-built from scratch — no templates, no page builders
|
|
|
|
|
|
- Private infrastructure: the client fully owns and controls their data and servers
|
|
|
|
|
|
- Small, experienced team with decades of combined expertise in design and engineering
|
|
|
|
|
|
- Deep AI integration into any type of system they build
|
|
|
|
|
|
- Data sovereignty and digital privacy as a core focus`;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// ─── Live Config ──────────────────────────────────────────────────────────────
|
|
|
|
|
|
|
|
|
|
|
|
export function buildLiveConfig(locale: string) {
|
|
|
|
|
|
return {
|
|
|
|
|
|
responseModalities: ['AUDIO'],
|
|
|
|
|
|
systemInstruction: buildSystemPrompt(locale),
|
|
|
|
|
|
tools: [{ functionDeclarations: AGENT_TOOLS }],
|
|
|
|
|
|
speechConfig: {
|
|
|
|
|
|
voiceConfig: {
|
|
|
|
|
|
prebuiltVoiceConfig: { voiceName: 'Aoede' },
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
};
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// ─── Ephemeral Token ──────────────────────────────────────────────────────────
|
|
|
|
|
|
|
2026-03-28 13:52:11 +01:00
|
|
|
|
export function generateEphemeralToken(locale: string) {
|
feat: website analysis pipeline, voice agent, configurator improvements
- Site analysis: cheerio HTML parsing, inline tech stack detection (~20 CMS/framework/analytics signatures), Google PageSpeed API integration
- Gemini Live voice agent: WebSocket-based real-time voice mode with live transcript, selection chips, and mid-conversation website analysis
- Type/Talk mode toggle with silent capability detection
- Stepped progress animation during brief generation (4 animated steps)
- URL + thoughts fields in Step 2, phone + contact preference in Step 3
- AI prompt improvements: dedicated website analysis section, 30-min call, concrete benefits, industry depth
- Email redesign: branded templates with logo, proper markdown rendering for both client and admin
- French locale support for AI-generated briefs
- Smaller checkmark, compact booking CTA, expanded brief area
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 13:41:35 +01:00
|
|
|
|
const config = buildLiveConfig(locale);
|
|
|
|
|
|
return { config, model: GEMINI_LIVE_MODEL };
|
|
|
|
|
|
}
|