{
"tool_response": {
"filePath": "\/var\/www\/tools\/ki-tasks\/cli.php",
"oldString": " private function stats(): int\n {\n $taskRepo = new TaskRepository();\n $resultRepo = new TaskResultRepository();\n\n $taskStats = $taskRepo->getStatistics();\n $tokenStats = $resultRepo->getTokenStatistics();",
"newString": " private function stats(): int\n {\n $taskStats = $this->taskRepo->getStatistics();\n $tokenStats = $this->resultRepo->getTokenStatistics();",
"originalFile": "#!\/usr\/bin\/env php\n<?php\n\/**\n * KI-Task-Management CLI\n *\n * Usage:\n * php cli.php create --title=\"Task\" [--type=ai_task] [--description=\"...\"]\n * php cli.php list [--status=pending] [--type=ai_task] [--limit=10]\n * php cli.php show <id>\n * php cli.php assign <id> --to=<name> --type=<ollama|claude|anthropic_api|human> [--model=mistral]\n * php cli.php execute <id> [--model=mistral] [--executor=ollama]\n * php cli.php status <id> <new_status>\n * php cli.php complete <id> [--result=\"...\"]\n * php cli.php delete <id>\n * php cli.php stats\n *\/\n\nrequire_once '\/var\/www\/dev.campus.systemische-tools.de\/config\/config.php';\nrequire_once '\/var\/www\/dev.campus.systemische-tools.de\/config\/database.php';\nrequire_once '\/var\/www\/dev.campus.systemische-tools.de\/config\/autoload.php';\n\nuse UseCases\\Task\\CreateTaskUseCase;\nuse UseCases\\Task\\GetTasksUseCase;\nuse UseCases\\Task\\AssignTaskUseCase;\nuse UseCases\\Task\\UpdateTaskStatusUseCase;\nuse UseCases\\Task\\SaveTaskResultUseCase;\nuse UseCases\\Task\\ExecuteAITaskUseCase;\nuse UseCases\\Task\\DeleteTaskUseCase;\nuse Infrastructure\\Persistence\\TaskRepository;\nuse Infrastructure\\Persistence\\TaskAssignmentRepository;\nuse Infrastructure\\Persistence\\TaskResultRepository;\nuse Infrastructure\\Persistence\\TaskCommentRepository;\n\nclass TaskCLI\n{\n private array $args = [];\n private array $options = [];\n\n \/\/ Database connection\n private \\PDO $pdo;\n\n \/\/ Repositories (shared instances)\n private TaskRepository $taskRepo;\n private TaskAssignmentRepository $assignmentRepo;\n private TaskResultRepository $resultRepo;\n private TaskCommentRepository $commentRepo;\n\n public function __construct(array $argv)\n {\n $this->parseArgs($argv);\n $this->initDatabase();\n $this->initRepositories();\n }\n\n private function initDatabase(): void\n {\n $dsn = sprintf('mysql:host=%s;dbname=%s;charset=utf8mb4', KI_DEV_DB_HOST, KI_DEV_DB_NAME);\n $this->pdo = new \\PDO($dsn, KI_DEV_DB_USER, KI_DEV_DB_PASS, [\n \\PDO::ATTR_ERRMODE => \\PDO::ERRMODE_EXCEPTION,\n \\PDO::ATTR_DEFAULT_FETCH_MODE => \\PDO::FETCH_ASSOC,\n ]);\n }\n\n private function initRepositories(): void\n {\n $this->taskRepo = new TaskRepository($this->pdo);\n $this->assignmentRepo = new TaskAssignmentRepository($this->pdo);\n $this->resultRepo = new TaskResultRepository($this->pdo);\n $this->commentRepo = new TaskCommentRepository($this->pdo);\n }\n\n private function parseArgs(array $argv): void\n {\n array_shift($argv);\n\n foreach ($argv as $arg) {\n if (str_starts_with($arg, '--')) {\n $parts = explode('=', substr($arg, 2), 2);\n $this->options[$parts[0]] = $parts[1] ?? true;\n } else {\n $this->args[] = $arg;\n }\n }\n }\n\n public function run(): int\n {\n $command = $this->args[0] ?? 'help';\n\n try {\n return match ($command) {\n 'create' => $this->create(),\n 'list' => $this->list(),\n 'show' => $this->show(),\n 'assign' => $this->assign(),\n 'execute' => $this->execute(),\n 'status' => $this->updateStatus(),\n 'complete' => $this->complete(),\n 'delete' => $this->delete(),\n 'stats' => $this->stats(),\n 'help', '--help', '-h' => $this->help(),\n default => $this->help()\n };\n } catch (\\Exception $e) {\n $this->error($e->getMessage());\n return 1;\n }\n }\n\n private function create(): int\n {\n $title = $this->options['title'] ?? null;\n if (!$title) {\n $this->error('--title is required');\n return 1;\n }\n\n $data = [\n 'title' => $title,\n 'type' => $this->options['type'] ?? 'human_task',\n 'created_by' => $this->options['created-by'] ?? (getenv('USER') ?: 'cli'),\n 'created_by_type' => 'human',\n ];\n\n if (isset($this->options['description'])) {\n $data['description'] = $this->options['description'];\n }\n\n $useCase = new CreateTaskUseCase($this->taskRepo, $this->commentRepo);\n $task = $useCase->execute($data);\n\n $this->success(\"Task #{$task->getId()} erstellt: {$task->getTitle()}\");\n return 0;\n }\n\n private function list(): int\n {\n $filters = [];\n if (isset($this->options['status'])) {\n $filters['status'] = $this->options['status'];\n }\n if (isset($this->options['type'])) {\n $filters['type'] = $this->options['type'];\n }\n\n $limit = (int) ($this->options['limit'] ?? 20);\n\n $useCase = new GetTasksUseCase($this->taskRepo, $this->assignmentRepo, $this->resultRepo);\n $tasks = $useCase->execute($filters, $limit);\n\n if (empty($tasks)) {\n $this->info('Keine Tasks gefunden.');\n return 0;\n }\n\n $this->output(sprintf(\n \"%-5s %-35s %-12s %-12s %s\",\n 'ID', 'Titel', 'Typ', 'Status', 'Erstellt'\n ));\n $this->output(str_repeat('-', 85));\n\n foreach ($tasks as $task) {\n $this->output(sprintf(\n \"%-5d %-35s %-12s %-12s %s\",\n $task->getId(),\n mb_substr($task->getTitle(), 0, 33) . (mb_strlen($task->getTitle()) > 33 ? '..' : ''),\n $task->getType()->value,\n $task->getStatus()->value,\n $task->getCreatedAt()->format('Y-m-d H:i')\n ));\n }\n\n return 0;\n }\n\n private function show(): int\n {\n $id = $this->args[1] ?? null;\n if (!$id) {\n $this->error('Task ID required');\n return 1;\n }\n\n $useCase = new GetTasksUseCase($this->taskRepo, $this->assignmentRepo, $this->resultRepo);\n $details = $useCase->getTaskWithDetails((int) $id);\n\n if (!$details) {\n $this->error(\"Task #{$id} not found\");\n return 1;\n }\n\n $task = $details['task'];\n\n $this->output(\"Task #{$task['id']}: {$task['title']}\");\n $this->output(str_repeat('=', 60));\n $this->output(\"Status: {$task['status']}\");\n $this->output(\"Typ: {$task['type']}\");\n $this->output(\"Erstellt: {$task['created_at']} von {$task['created_by']}\");\n\n if ($task['description']) {\n $this->output(\"\\nBeschreibung:\\n{$task['description']}\");\n }\n\n if (!empty($details['assignments'])) {\n $this->output(\"\\nZuweisungen:\");\n foreach ($details['assignments'] as $a) {\n $this->output(\" - {$a['assignee']} ({$a['assignee_type']}) - {$a['status']}\");\n }\n }\n\n if (!empty($details['results'])) {\n $this->output(\"\\nErgebnisse:\");\n foreach ($details['results'] as $r) {\n $tokens = $r['tokens_total'] ? \"{$r['tokens_total']} tokens\" : '-';\n $this->output(\" - {$r['executor']} ({$r['model_name']}) - {$r['status']} - {$tokens}\");\n }\n }\n\n return 0;\n }\n\n private function assign(): int\n {\n $id = $this->args[1] ?? null;\n $assignee = $this->options['to'] ?? null;\n $type = $this->options['type'] ?? null;\n\n if (!$id || !$assignee || !$type) {\n $this->error('Usage: assign <id> --to=<name> --type=<ollama|claude|anthropic_api|human>');\n return 1;\n }\n\n $data = [\n 'assignee' => $assignee,\n 'assignee_type' => $type,\n 'assigned_by' => getenv('USER') ?: 'cli',\n 'assigned_by_type' => 'human',\n ];\n\n if (isset($this->options['model'])) {\n $data['model_name'] = $this->options['model'];\n }\n\n $useCase = new AssignTaskUseCase($this->taskRepo, $this->assignmentRepo, $this->commentRepo);\n $assignment = $useCase->execute((int) $id, $data);\n\n $this->success(\"Task #{$id} zugewiesen an {$assignee} ({$type})\");\n return 0;\n }\n\n private function execute(): int\n {\n $id = $this->args[1] ?? null;\n if (!$id) {\n $this->error('Task ID required');\n return 1;\n }\n\n $options = [\n 'executor_type' => $this->options['executor'] ?? 'ollama',\n 'model' => $this->options['model'] ?? 'mistral',\n 'auto_complete' => isset($this->options['auto-complete']),\n ];\n\n $this->info(\"Führe Task #{$id} mit {$options['executor_type']} ({$options['model']}) aus...\");\n\n $saveResultUseCase = new SaveTaskResultUseCase($this->taskRepo, $this->resultRepo, $this->commentRepo);\n $updateStatusUseCase = new UpdateTaskStatusUseCase($this->taskRepo, $this->commentRepo);\n $useCase = new ExecuteAITaskUseCase($this->taskRepo, $saveResultUseCase, $updateStatusUseCase);\n $result = $useCase->execute((int) $id, $options);\n\n if ($result->getStatus() === 'success') {\n $this->success(\"Erfolgreich ausgeführt!\");\n $this->output(\"Tokens: {$result->getTokensTotal()} | Dauer: {$result->getDurationMs()}ms\");\n\n if ($result->getResponse()) {\n $this->output(\"\\nAntwort:\\n\" . str_repeat('-', 40));\n $this->output($result->getResponse());\n }\n } else {\n $this->error(\"Fehler: \" . $result->getErrorMessage());\n }\n\n return 0;\n }\n\n private function updateStatus(): int\n {\n $id = $this->args[1] ?? null;\n $status = $this->args[2] ?? null;\n\n if (!$id || !$status) {\n $this->error('Usage: status <id> <pending|in_progress|completed|failed|cancelled>');\n return 1;\n }\n\n $useCase = new UpdateTaskStatusUseCase($this->taskRepo, $this->commentRepo);\n $task = $useCase->execute((int) $id, $status, getenv('USER') ?:... [TRUNCATED-28aa101575794991]",
"structuredPatch": [
{
"oldStart": 343,
"oldLines": 12,
"newStart": 343,
"newLines": 9,
"lines": [
" ",
" private function stats(): int",
" {",
"- $taskRepo = new TaskRepository();",
"- $resultRepo = new TaskResultRepository();",
"+ $taskStats = $this->taskRepo->getStatistics();",
"+ $tokenStats = $this->resultRepo->getTokenStatistics();",
" ",
"- $taskStats = $taskRepo->getStatistics();",
"- $tokenStats = $resultRepo->getTokenStatistics();",
"-",
" $this->output(\"Task-Statistiken\");",
" $this->output(str_repeat('=', 40));",
" $this->output(\"Gesamt: {$taskStats['total']}\");"
]
}
],
"userModified": false,
"replaceAll": false
}
}