Skip to content

Commit de14d31

Browse files
Move LLM work to background
1 parent 170060c commit de14d31

File tree

5 files changed

+100
-58
lines changed

5 files changed

+100
-58
lines changed
Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,23 @@
1-
<?php declare(strict_types=1);
1+
<?php
2+
3+
declare(strict_types=1);
24

35
namespace Reconmap\Cli\Commands;
46

57
use Reconmap\Services\QueueProcessor;
8+
use Reconmap\Tasks\AiTaskProcessor;
69
use Reconmap\Tasks\TaskResultProcessor;
710
use Symfony\Component\Console\Command\Command;
811
use Symfony\Component\Console\Input\InputInterface;
912
use Symfony\Component\Console\Output\OutputInterface;
1013

1114
class TaskProcessorCommand extends Command
1215
{
13-
public function __construct(private readonly QueueProcessor $queueProcessor,
14-
private readonly TaskResultProcessor $taskResultProcessor)
15-
{
16+
public function __construct(
17+
private readonly QueueProcessor $queueProcessor,
18+
private readonly TaskResultProcessor $taskResultProcessor,
19+
private readonly AiTaskProcessor $aiTaskProcessor,
20+
) {
1621
parent::__construct();
1722
}
1823

@@ -24,6 +29,7 @@ protected function configure(): void
2429

2530
protected function execute(InputInterface $input, OutputInterface $output): int
2631
{
27-
return $this->queueProcessor->run($this->taskResultProcessor, 'tasks:queue');
32+
return $this->queueProcessor->run($this->taskResultProcessor, 'tasks:queue') +
33+
$this->queueProcessor->run($this->aiTaskProcessor, 'llm:queue');
2834
}
2935
}
Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
1-
<?php declare(strict_types=1);
1+
<?php
2+
3+
declare(strict_types=1);
24

35
namespace Reconmap\Controllers\Agents;
46

57
use OpenApi\Attributes as OpenApi;
8+
use Psr\Http\Message\ResponseInterface;
69
use Psr\Http\Message\ServerRequestInterface;
710
use Reconmap\Controllers\Controller;
811
use Reconmap\Http\Docs\Default200OkResponse;
@@ -15,14 +18,16 @@
1518
class BootAgentController extends Controller
1619
{
1720

18-
public function __construct(private readonly AgentRepository $repository)
19-
{
20-
}
21+
public function __construct(private readonly AgentRepository $repository) {}
2122

22-
public function __invoke(ServerRequestInterface $request): array
23+
public function __invoke(ServerRequestInterface $request): ResponseInterface
2324
{
2425
$info = $this->getJsonBodyDecoded($request);
2526

26-
return $this->repository->updateLastBootAt($info);
27+
if ($this->repository->updateLastBootAt($info)) {
28+
return $this->createNoContentResponse();
29+
}
30+
31+
return $this->createBadRequestResponse();
2732
}
2833
}
Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
1-
<?php declare(strict_types=1);
1+
<?php
2+
3+
declare(strict_types=1);
24

35
namespace Reconmap\Controllers\Agents;
46

57
use OpenApi\Attributes as OpenApi;
8+
use Psr\Http\Message\ResponseInterface;
69
use Psr\Http\Message\ServerRequestInterface;
710
use Reconmap\Controllers\Controller;
811
use Reconmap\Http\Docs\Default200OkResponse;
@@ -15,12 +18,14 @@
1518
class PingAgentController extends Controller
1619
{
1720

18-
public function __construct(private readonly AgentRepository $repository)
19-
{
20-
}
21+
public function __construct(private readonly AgentRepository $repository) {}
2122

22-
public function __invoke(ServerRequestInterface $request): array
23+
public function __invoke(ServerRequestInterface $request): ResponseInterface
2324
{
24-
return $this->repository->updateLastPingAt();
25+
if ($this->repository->updateLastPingAt()) {
26+
return $this->createNoContentResponse();
27+
}
28+
29+
return $this->createBadRequestResponse();
2530
}
2631
}

src/Controllers/Vulnerabilities/GenerateVulnerabilityRemediationController.php

Lines changed: 11 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,65 +1,35 @@
1-
<?php declare(strict_types=1);
1+
<?php
2+
3+
declare(strict_types=1);
24

35
namespace Reconmap\Controllers\Vulnerabilities;
46

5-
use LLPhant\Chat\OllamaChat;
6-
use LLPhant\OllamaConfig;
77
use Psr\Http\Message\ResponseInterface;
88
use Psr\Http\Message\ServerRequestInterface;
99
use Reconmap\Controllers\Controller;
1010
use Reconmap\Models\AuditActions\AuditActions;
11-
use Reconmap\Models\Notification;
12-
use Reconmap\Repositories\NotificationsRepository;
13-
use Reconmap\Repositories\VulnerabilityRepository;
1411
use Reconmap\Services\ActivityPublisherService;
1512
use Reconmap\Services\ApplicationConfig;
1613
use Reconmap\Services\RedisServer;
1714

1815
class GenerateVulnerabilityRemediationController extends Controller
1916
{
20-
public function __construct(private readonly VulnerabilityRepository $repository,
21-
private readonly ActivityPublisherService $activityPublisherService,
22-
private readonly NotificationsRepository $notificationsRepository,
23-
private readonly RedisServer $redisServer,
24-
private readonly ApplicationConfig $config,
25-
)
26-
{
27-
}
17+
public function __construct(
18+
private readonly ActivityPublisherService $activityPublisherService,
19+
private readonly RedisServer $redisServer,
20+
private readonly ApplicationConfig $config,
21+
) {}
2822

2923
public function __invoke(ServerRequestInterface $request, array $args): ResponseInterface
3024
{
3125
$vulnerabilityId = intval($args['vulnerabilityId']);
3226

33-
$appConfig = $this->config->getSettings('integrations');
34-
35-
$config = new OllamaConfig();
36-
$config->url = $appConfig['ollama']['url'];
37-
$config->model = $appConfig['ollama']['model'];
38-
$config->stream = false;
39-
40-
$vulnerability = $this->repository->findById($vulnerabilityId);
41-
42-
$chat = new OllamaChat($config);
43-
$chat->setSystemMessage('You are a vulnerability and pentesting expert system');
44-
$remediation = $chat->generateText('Write instructions on how to remediate this vulnerability: ' . $vulnerability['summary']);
45-
46-
$success = $this->repository->updateById($vulnerabilityId, ['remediation' => $remediation]);
47-
4827
$loggedInUserId = $request->getAttribute('userId');
4928

50-
$notification = new Notification();
51-
$notification->toUserId = $loggedInUserId;
52-
$notification->title = "AI job completed";
53-
$notification->content = "The vulnerability remediation instructions have now been generated";
54-
$this->notificationsRepository->insert($notification);
55-
$this->redisServer->lPush("notifications:queue", json_encode(['type' => 'message']));
56-
57-
if ($success) {
58-
$this->auditAction($loggedInUserId, $vulnerabilityId);
59-
return $this->createNoContentResponse();
60-
}
29+
$this->redisServer->lPush("llm:queue", json_encode(['vulnerabilityId' => $vulnerabilityId, 'loggedInUserId' => $loggedInUserId]));
6130

62-
return $this->createBadRequestResponse();
31+
$this->auditAction($loggedInUserId, $vulnerabilityId);
32+
return $this->createNoContentResponse();
6333
}
6434

6535
private function auditAction(int $loggedInUserId, int $vulnerabilityId): void

src/Tasks/AiTaskProcessor.php

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Reconmap\Tasks;
6+
7+
use LLPhant\Chat\OllamaChat;
8+
use LLPhant\OllamaConfig;
9+
use Psr\Log\LoggerInterface;
10+
use Reconmap\Models\Notification;
11+
use Reconmap\Repositories\NotificationsRepository;
12+
use Reconmap\Repositories\VulnerabilityRepository;
13+
use Reconmap\Services\ApplicationConfig;
14+
use Reconmap\Services\RedisServer;
15+
16+
readonly class AiTaskProcessor implements ItemProcessor
17+
{
18+
public function __construct(
19+
private ApplicationConfig $config,
20+
private LoggerInterface $logger,
21+
private readonly VulnerabilityRepository $repository,
22+
private readonly NotificationsRepository $notificationsRepository,
23+
private readonly RedisServer $redisServer,
24+
) {}
25+
26+
public function process(object $message): void
27+
{
28+
$this->logger->debug('Processing LLM job');
29+
30+
try {
31+
$appConfig = $this->config->getSettings('integrations');
32+
33+
$config = new OllamaConfig();
34+
$config->url = $appConfig['ollama']['url'];
35+
$config->model = $appConfig['ollama']['model'];
36+
$config->stream = false;
37+
38+
$vulnerability = $this->repository->findById($message->vulnerabilityId);
39+
$this->logger->debug($vulnerability['summary']);
40+
$chat = new OllamaChat($config);
41+
$chat->setSystemMessage('You are a vulnerability and pentesting expert system');
42+
$remediation = $chat->generateText('Write instructions on how to remediate this vulnerability: ' . $vulnerability['summary']);
43+
44+
$success = $this->repository->updateById($message->vulnerabilityId, ['remediation' => $remediation]);
45+
46+
$notification = new Notification();
47+
$notification->toUserId = $message->loggedInUserId;
48+
$notification->title = "AI job completed";
49+
$notification->content = "The vulnerability remediation instructions have now been generated";
50+
$this->notificationsRepository->insert($notification);
51+
$this->redisServer->lPush("notifications:queue", json_encode(['type' => 'message']));
52+
} catch (\Exception $e) {
53+
$this->logger->error($e->getMessage());
54+
}
55+
}
56+
}

0 commit comments

Comments
 (0)