refactor : IA éditeur — un seul bouton analyse+réécriture combinées

Un seul appel API retourne l'analyse critique ET la proposition d'article
via le séparateur ===CRITIQUE===/===REWRITE===. Le panneau affiche les deux
sections avec un bouton « Appliquer la proposition ».

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-05-16 13:06:23 +02:00
parent e03594c22e
commit c979238b0c
4 changed files with 134 additions and 71 deletions
+82 -2
View File
@@ -10,6 +10,21 @@ PROMPT;
private const SYSTEM_REWRITE = <<<'PROMPT'
Tu es un rédacteur expert. Réécris l'article ci-dessous en améliorant le style, la clarté et la structure, sans modifier le sens ni les faits. Conserve le format markdown, les liens et les références aux images. Réponds uniquement avec l'article réécrit, sans commentaire ni explication.
PROMPT;
private const SYSTEM_ANALYZE = <<<'PROMPT'
Tu es un relecteur et rédacteur expert de blogs. Pour l'article ci-dessous, fais deux choses :
1. Identifie ses faiblesses (arguments faibles, imprécisions, manques de clarté, structure à revoir, points à développer). Sois bref et précis — quelques lignes suffisent.
2. Propose une version améliorée de l'article : meilleur style, clarté, structure. Conserve le sens, les faits, le format markdown, les liens et les références aux images.
Réponds EXACTEMENT dans ce format (les deux séparateurs doivent être présents tels quels) :
===CRITIQUE===
[ton analyse ici]
===REWRITE===
[l'article réécrit ici]
PROMPT;
private string $apiKey;
@@ -40,6 +55,16 @@ PROMPT;
return ['ok' => false, 'error' => "Contenu de l'article vide"];
}
$userMsg = $title !== '' ? "# {$title}\n\n{$content}" : $content;
if ($action === 'analyze') {
$raw = $this->provider === 'claude_code'
? $this->queryClaudeCode(self::SYSTEM_ANALYZE, $userMsg)
: $this->queryAnthropicRaw(self::SYSTEM_ANALYZE, $userMsg, 4096);
if (!$raw['ok']) return $raw;
return $this->parseAnalyzeResponse($raw['text'] ?? '');
}
$systemPrompt = match ($action) {
'critique' => self::SYSTEM_CRITIQUE,
'rewrite' => self::SYSTEM_REWRITE,
@@ -50,8 +75,6 @@ PROMPT;
return ['ok' => false, 'error' => 'Action inconnue'];
}
$userMsg = $title !== '' ? "# {$title}\n\n{$content}" : $content;
if ($this->provider === 'claude_code') {
return $this->queryClaudeCode($systemPrompt, $userMsg);
}
@@ -59,6 +82,63 @@ PROMPT;
return $this->queryAnthropic($action, $systemPrompt, $userMsg);
}
/** @return array{ok: bool, critique?: string, rewrite?: string, error?: string} */
private function parseAnalyzeResponse(string $text): array
{
$parts = preg_split('/===CRITIQUE===|===REWRITE===/', $text);
if (count($parts) < 3) {
// Fallback : pas de séparateurs trouvés, on met tout en critique
return ['ok' => true, 'critique' => trim($text), 'rewrite' => ''];
}
return [
'ok' => true,
'critique' => trim($parts[1]),
'rewrite' => trim($parts[2]),
];
}
/** @return array{ok: bool, text?: string, error?: string} */
private function queryAnthropicRaw(string $systemPrompt, string $userMsg, int $maxTokens): array
{
if ($this->apiKey === '') {
return ['ok' => false, 'error' => 'Clé Anthropic non configurée (ANTHROPIC_API_KEY manquante dans .env)'];
}
$payload = json_encode([
'model' => $this->model,
'max_tokens' => $maxTokens,
'system' => $systemPrompt,
'messages' => [['role' => 'user', 'content' => $userMsg]],
]);
$ch = curl_init('https://api.anthropic.com/v1/messages');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => $payload,
CURLOPT_TIMEOUT => 90,
CURLOPT_HTTPHEADER => [
'x-api-key: ' . $this->apiKey,
'anthropic-version: 2023-06-01',
'Content-Type: application/json',
],
]);
$resp = curl_exec($ch);
$http = (int) curl_getinfo($ch, CURLINFO_HTTP_CODE);
$err = curl_error($ch);
curl_close($ch);
if ($err !== '') return ['ok' => false, 'error' => 'Erreur réseau : ' . $err];
$data = json_decode((string) $resp, true);
if ($http !== 200) {
return ['ok' => false, 'error' => $data['error']['message'] ?? ('Anthropic HTTP ' . $http)];
}
return ['ok' => true, 'text' => $data['content'][0]['text'] ?? ''];
}
/** @return array{ok: bool, text?: string, error?: string} */
private function queryAnthropic(string $action, string $systemPrompt, string $userMsg): array
{