export type AiEmbedApp = "mail" | "drive" | "contacts" | "docs" | "standalone" export type AiChatContext = { app: AiEmbedApp temporary?: boolean messageId?: string accountId?: string drivePath?: string fileId?: string contactId?: string subject?: string snippet?: string /** UltiDocs — titre affiché */ documentTitle?: string /** Chemin du fichier source (.docx, .md…) si sidecar */ sourcePath?: string /** Extrait texte du document */ documentExcerpt?: string /** Sélection courante dans l'éditeur */ selectionText?: string /** JSON TipTap (éventuellement tronqué) */ documentJson?: string /** Prompt système additionnel (non sérialisé en URL) */ systemPromptExtra?: string } export type AiPostMessage = | { type: "ULTI_CONTEXT_UPDATE" context: AiChatContext systemPrompt?: string } | { type: "ULTI_DOCS_APPLY"; payload: unknown } | { type: "ULTI_ASSISTANT_TEXT"; text: string } | { type: "ULTI_THEME"; theme: "light" | "dark" } | { type: "ULTI_OPEN_LINK"; href: string } | { type: "ULTI_TOOL_RESULT"; payload: unknown } export function buildEmbedSearchParams(context: AiChatContext): string { const params = new URLSearchParams() if (context.temporary !== false) params.set("temporary-chat", "true") if (context.app) params.set("app", context.app) if (context.messageId) params.set("message_id", context.messageId) if (context.accountId) params.set("account_id", context.accountId) if (context.drivePath) params.set("path", context.drivePath) if (context.fileId) params.set("file_id", context.fileId) if (context.contactId) params.set("contact_id", context.contactId) if (context.subject) params.set("subject", context.subject) if (context.snippet) params.set("snippet", context.snippet) return params.toString() } export function systemPromptFromContext(context: AiChatContext): string { const lines = [ "Tu es UltiAI, l'assistant intégré à la suite Ultimail (mail, drive, contacts).", "Réponds en français sauf demande contraire. Utilise les tools disponibles pour agir sur les données utilisateur.", ] if (context.app === "mail" && context.subject) { lines.push(`Contexte mail — sujet: ${context.subject}`) if (context.snippet) lines.push(`Extrait: ${context.snippet}`) } if (context.app === "drive" && context.drivePath) { lines.push(`Contexte drive — fichier/dossier: ${context.drivePath}`) } if (context.app === "contacts" && context.contactId) { lines.push(`Contexte contacts — fiche: ${context.contactId}`) } if (context.app === "docs") { if (context.documentTitle) lines.push(`Document: ${context.documentTitle}`) if (context.drivePath) lines.push(`Sidecar: ${context.drivePath}`) if (context.sourcePath) lines.push(`Source: ${context.sourcePath}`) if (context.selectionText) lines.push(`Sélection: ${context.selectionText}`) if (context.documentExcerpt) lines.push(`Contenu:\n${context.documentExcerpt}`) } if (context.systemPromptExtra) { lines.push("", context.systemPromptExtra) } return lines.join("\n") }