Files
ASPIC/agent_notes.php
T

182 lines
7.9 KiB
PHP

<?php
/**
* ASPIC — agent_notes.php
* (renommé le 2 septembre 2026, ex-lilou_notes.php — n'a plus de raison de
* porter le nom d'un seul agent maintenant que ASP_Agents en porte
* plusieurs, voir plus bas et journal section 27)
*
* Étape 1 du pilotage vocal, volontairement "sans interprétation" (1er
* septembre 2026, décision de Jean-Marc) : reçoit le texte dicté à un agent
* entre une phrase d'ouverture ("Lilou, ajoute une tâche...", "Viktor, un
* truc à faire...", "Lilou, note ça dans ma todolist...") et une phrase de
* clôture ("c'est tout Lilou") ou d'annulation ("Lilou annule"), et
* l'enregistre tel quel, ligne par ligne — aucune tentative de
* compréhension du CONTENU ici (demande explicite de Jean-Marc). Objectif :
* accumuler un vrai corpus d'essais réels avant de définir des règles
* d'interprétation (étape 2, envisagée via n8n, avec des règles modifiables
* par l'utilisateur — voir réflexions stratégiques, section 10).
*
* POST uniquement, corps JSON : { "agent": "...", "lignes": [...] }
*
* "agent" (ajouté le 2 septembre 2026, suite de ASP_Agents/CVX_AgentTraitant
* — voir journal section 27 et réflexions stratégiques) : nom de l'agent
* reconnu en tête de la phrase d'ouverture ("Viktor", "Matilda"...), un
* seul par lot puisqu'une notation entière s'adresse à un seul assistant.
* Copié tel quel dans CVX_AgentTraitant sur chaque ligne du lot (colonne
* plate, pas de table de lots séparée — cohérent avec le reste de cette
* table). Absent ou vide (compatibilité ascendante avec un micro.js pas
* encore au courant des autres agents) : on retombe sur l'agent marqué
* ASP_Agents.AGN_Defaut = 'O' — plus de nom d'agent figé en dur ici depuis
* le retrait de Lilou le 2 septembre 2026 (voir plus bas et journal
* section 27) : l'agent de repli peut changer sans toucher au code.
*
* Format de chaque entrée de "lignes" (évolution du 2 septembre 2026,
* demande de Jean-Marc) : soit un objet {"texte": "...", "type": "..."},
* soit une simple chaîne (compatibilité avec un ancien micro.js non
* redéployé — traitée alors comme une ligne de type "contenu"). Types
* possibles : "ouverture" (phrase déclenchante elle-même), "contenu"
* (dictée proprement dite), "cloture" ou "annulation" (phrase de fin,
* distinguées cette fois — contrairement au contenu, dont le traitement ne
* change pas selon clôture ou annulation, décision du 1er septembre
* inchangée). Objectif : qu'un futur robot sache, sans ré-analyser le texte
* brut, où commence/finit un lot, s'il doit être exécuté ou écarté, et à
* quel assistant le router (CVX_AgentTraitant).
*
* Stockage (2 septembre 2026, pivot décidé par Jean-Marc) : le fichier
* texte global (notes_lilou/dictees.txt) est abandonné — l'essai du matin
* même une fois le fichier créé manuellement à la racine n'a rien donné
* (voir journal, section 27), sans compter le souci de droits d'écriture
* sur notes_lilou/ jamais vraiment résolu. Chaque ligne est désormais
* enregistrée directement dans la table ASP_ConsignesVoix (une ligne =
* une consigne = une ligne de dictée), même pattern de connexion que les
* autres endpoints (todolist.php, contacts.php) via getDbConnection().
* Nom de table volontairement générique ("ConsignesVoix"), pas centré sur
* "Lilou" — l'assistante n'étant qu'une des interfaces possibles vers ce
* mécanisme.
*
* Session utilisateur : accès réservé aux utilisateurs identifiés, même
* principe que les autres endpoints (todolist.php, contacts.php...).
*/
session_start();
header('Content-Type: application/json; charset=utf-8');
require __DIR__ . '/db.php';
if (empty($_SESSION['USR_Code'])) {
http_response_code(401);
echo json_encode(['error' => 'Non identifié — veuillez vous connecter.']);
exit;
}
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
http_response_code(405);
echo json_encode(['error' => 'Méthode non autorisée']);
exit;
}
$data = json_decode(file_get_contents('php://input'), true) ?? [];
$lignes = $data['lignes'] ?? [];
if (!is_array($lignes) || count($lignes) === 0) {
http_response_code(400);
echo json_encode(['error' => 'Aucune ligne à enregistrer']);
exit;
}
const TYPES_VALIDES = ['ouverture', 'contenu', 'cloture', 'annulation'];
try {
$pdo = getDbConnection();
} catch (PDOException $e) {
http_response_code(500);
echo json_encode(['error' => 'Connexion base de données impossible']);
exit;
}
$agent = trim((string) ($data['agent'] ?? ''));
if ($agent === '') {
// Agent par défaut piloté par la donnée (2 septembre 2026, décision de
// Jean-Marc : plus question de figer un nom d'agent en dur ici — après
// Lilou, retirée de ASP_Agents le même jour pour cause de confusions
// récurrentes, un prochain agent par défaut pourrait tout aussi bien
// changer). AGN_Defaut ('O'/'N') désigne l'agent de repli directement
// en base, modifiable par Jean-Marc sans toucher au code. Repli
// supplémentaire sur le premier agent de la table si aucun n'est
// marqué par défaut (ne devrait pas arriver en usage normal, simple
// filet de sécurité pour ne jamais laisser CVX_AgentTraitant vide).
try {
// AGN_Nom renommée AGN_Prenom en base (7 septembre 2026, nuit).
$stmtDefaut = $pdo->query(
"SELECT AGN_Prenom FROM ASP_Agents WHERE AGN_Defaut = 'O' ORDER BY AGN_Incr ASC LIMIT 1"
);
$agent = $stmtDefaut->fetchColumn();
if ($agent === false || $agent === '') {
$stmtPremier = $pdo->query('SELECT AGN_Prenom FROM ASP_Agents ORDER BY AGN_Incr ASC LIMIT 1');
$agent = $stmtPremier->fetchColumn();
}
} catch (PDOException $e) {
$agent = false;
}
if ($agent === false || $agent === '') {
$agent = 'Agent';
}
}
if (mb_strlen($agent) > 20) {
$agent = mb_substr($agent, 0, 20);
}
// Un seul horodatage pour tout le lot reçu dans cet appel (même principe
// que l'ancien fichier texte, qui datait le bloc entier plutôt que chaque
// ligne individuellement — les lignes d'un même lot ont été dictées à
// quelques secondes d'écart, la distinction n'aurait pas de sens).
$horodatage = date('Y-m-d H:i:s');
$codeUser = $_SESSION['USR_Code'];
$stmt = $pdo->prepare(
'INSERT INTO ASP_ConsignesVoix (CVX_Consigne, CVX_Type, CVX_DateHeure, CVX_CodeUser, CVX_AgentTraitant) VALUES (?, ?, ?, ?, ?)'
);
$enregistrees = 0;
try {
foreach ($lignes as $entree) {
// Accepte un objet {texte, type} (nouveau format) ou une simple
// chaîne (ancien format, avant l'ajout du type par ligne) —
// traitée alors comme une ligne de contenu ordinaire.
if (is_array($entree)) {
$texte = trim((string) ($entree['texte'] ?? ''));
$type = (string) ($entree['type'] ?? 'contenu');
} else {
$texte = trim((string) $entree);
$type = 'contenu';
}
if ($texte === '') {
continue;
}
if (!in_array($type, TYPES_VALIDES, true)) {
$type = 'contenu';
}
// CVX_Consigne est un varchar(200) : une dictée plus longue est
// tronquée plutôt que de faire échouer tout le lot (mb_substr pour
// ne pas couper un caractère accentué en deux) — pas de perte
// totale d'une ligne pour un dépassement de quelques caractères.
if (mb_strlen($texte) > 200) {
$texte = mb_substr($texte, 0, 200);
}
$stmt->execute([$texte, $type, $horodatage, $codeUser, $agent]);
$enregistrees++;
}
} catch (PDOException $e) {
http_response_code(500);
echo json_encode(['error' => 'Erreur base de données : ' . $e->getMessage()]);
exit;
}
if ($enregistrees === 0) {
http_response_code(400);
echo json_encode(['error' => 'Aucune ligne à enregistrer']);
exit;
}
echo json_encode(['success' => true, 'lignes_enregistrees' => $enregistrees]);