Backup #988

ID988
Dateipfad/var/www/dev.campus.systemische-tools.de/src/UseCases/Content/GenerateContentUseCase.php
Version4
Typ modified
Größe4.3 KB
Hashe95477ea55eecfcb16050953253575fb86d1c1514fca519b0847e7d575be4a38
Datum2025-12-24 00:50:44
Geändert vonclaude-code-hook
GrundClaude Code Pre-Hook Backup vor Edit-Operation
Datei existiert Ja

Dateiinhalt

<?php

declare(strict_types=1);

namespace UseCases\Content;

// @responsibility: Orchestriert Content-Generierung via Python-Pipeline

class GenerateContentUseCase
{
    private string $pipelinePath;
    private string $pythonPath;

    /** @var array<string> Allowed Python commands */
    private const ALLOWED_COMMANDS = ['generate', 'critique', 'revise'];

    public function __construct(
        ?string $pipelinePath = null,
        ?string $pythonPath = null
    ) {
        $this->pipelinePath = $pipelinePath ?? '/var/www/scripts/pipeline';
        $this->pythonPath = $pythonPath ?? $this->pipelinePath . '/venv/bin/python';
    }

    /**
     * Generate content for an order (synchronous)
     */
    public function generate(int $orderId, string $model, string $collection, int $contextLimit): ContentGenerationResult
    {
        $result = $this->callPython('generate', $orderId, [$model, $collection, $contextLimit]);

        return ContentGenerationResult::fromPythonResult($result);
    }

    /**
     * Start async content generation (returns immediately)
     */
    public function generateAsync(int $orderId, string $model, string $collection, int $contextLimit): bool
    {
        $scriptPath = $this->pipelinePath . '/web_generate.py';
        $logPath = '/tmp/content_gen_' . $orderId . '.log';
        $dbPassword = $_ENV['MARIADB_ROOT_PASSWORD'] ?? '';

        $cmd = sprintf(
            'nohup env DB_PASSWORD=%s %s %s generate %d %s %s %d > %s 2>&1 &',
            escapeshellarg($dbPassword),
            escapeshellarg($this->pythonPath),
            escapeshellarg($scriptPath),
            $orderId,
            escapeshellarg($model),
            escapeshellarg($collection),
            $contextLimit,
            escapeshellarg($logPath)
        );

        exec($cmd); // nosemgrep: exec-use

        return true;
    }

    /**
     * Run critique on a version
     */
    public function critique(int $versionId, string $model): ContentGenerationResult
    {
        $result = $this->callPython('critique', $versionId, [$model]);

        return ContentGenerationResult::fromPythonResult($result);
    }

    /**
     * Create revision of a version
     */
    public function revise(int $versionId, string $model): ContentGenerationResult
    {
        $result = $this->callPython('revise', $versionId, [$model]);

        return ContentGenerationResult::fromPythonResult($result);
    }

    /**
     * Call Python script with command and arguments
     *
     * @param string $command Command to execute (generate, critique, revise)
     * @param int $entityId Order or version ID
     * @param array<mixed> $args Additional arguments
     * @return array<string,mixed> Result from Python script
     */
    private function callPython(string $command, int $entityId, array $args = []): array
    {
        // Validate command against whitelist
        if (!in_array($command, self::ALLOWED_COMMANDS, true)) {
            return ['error' => 'Ungültiger Command: ' . $command];
        }

        $scriptPath = $this->pipelinePath . '/web_generate.py';

        // Build command array for proc_open (safer than shell_exec)
        $cmdArray = [
            $this->pythonPath,
            $scriptPath,
            $command,
            (string) $entityId,
            ...$args,
        ];

        $descriptors = [
            0 => ['pipe', 'r'],
            1 => ['pipe', 'w'],
            2 => ['pipe', 'w'],
        ];

        $process = proc_open($cmdArray, $descriptors, $pipes); // nosemgrep: exec-use

        if (!is_resource($process)) {
            return ['error' => 'Script konnte nicht gestartet werden'];
        }

        fclose($pipes[0]);
        $stdout = stream_get_contents($pipes[1]);
        $stderr = stream_get_contents($pipes[2]);
        fclose($pipes[1]);
        fclose($pipes[2]);
        $exitCode = proc_close($process);

        $output = $stdout . $stderr;

        if ($exitCode !== 0 && $output === '') {
            return ['error' => 'Script fehlgeschlagen (Exit: ' . $exitCode . ')'];
        }

        if (preg_match('/\{[\s\S]*\}/', $output, $matches)) {
            $result = json_decode($matches[0], true);
            if (json_last_error() === JSON_ERROR_NONE) {
                return $result;
            }
        }

        return ['error' => 'Ungültige Antwort: ' . substr($output, 0, 500)];
    }
}

Vollständig herunterladen

Aktionen

Herunterladen

Andere Versionen dieser Datei

ID Version Typ Größe Datum
1013 5 modified 4.3 KB 2025-12-24 01:27
988 4 modified 4.3 KB 2025-12-24 00:50
976 3 modified 4.2 KB 2025-12-24 00:14
973 2 modified 3.4 KB 2025-12-24 00:11
716 1 modified 3.5 KB 2025-12-23 07:55

← Zurück zur Übersicht