ultisuite-client/lib/ai/chat-context.ts
R3D347HR4Y 2a0958b70d
Some checks are pending
E2E / Playwright e2e (push) Waiting to run
feat: update agenda references to use ULTICAL_APP_NAME and enhance AI usage sections
- Replaced hardcoded "Agenda" labels with dynamic ULTICAL_APP_NAME in various components for consistency.
- Introduced new AiUsageSection and CompteAiUsageSection components to track AI usage and costs.
- Updated settings and metadata to reflect changes in AI cost policies and usage limits.
- Enhanced user interface elements for better accessibility and user experience across admin settings.
2026-06-16 10:46:31 +02:00

96 lines
3.8 KiB
TypeScript

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_SESSION"
token_secret?: string
mcp_url?: string
enabled_tools?: string[]
session_id?: string
}
| { type: "ULTI_OPEN_LINK"; href: string }
| { type: "ULTI_TOOL_RESULT"; payload: unknown }
export function buildEmbedSearchParams(
context: AiChatContext,
defaultModel?: string,
): string {
const params = new URLSearchParams()
const model = defaultModel?.trim()
if (model) params.set("model", model)
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, UltiCal).",
"Réponds en français sauf demande contraire. Utilise les tools disponibles pour agir sur les données utilisateur.",
"Recherche suite (index local) via suite_search ; recherche web publique via web_search si configurée.",
"Après chaque appel d'outil, réponds toujours en langage naturel : résume le résultat, cite les sources (sujet, chemin, nom), propose la suite.",
"Ne termine jamais un tour utilisateur avec uniquement un appel d'outil sans texte explicatif.",
"Respecte strictement le paramètre limit des tools (ne demande pas plus de résultats que nécessaire).",
]
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")
}