57 lines
1.9 KiB
PHP
57 lines
1.9 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace App\Chatbot\Mcp\Tool;
|
|
|
|
use App\Chatbot\Mcp\ToolCallRunner;
|
|
use App\Chatbot\Search\ContentSearch;
|
|
use App\Repository\ContentDocumentRepository;
|
|
use Mcp\Capability\Attribute\McpTool;
|
|
use Mcp\Capability\Attribute\Schema;
|
|
use Mcp\Exception\ToolCallException;
|
|
use Mcp\Schema\Result\CallToolResult;
|
|
use Mcp\Schema\ToolAnnotations;
|
|
|
|
#[McpTool(
|
|
name: 'get_document',
|
|
description: 'Read the full text of one search_content hit, by its url. Editorial text can be out of date: take dates, prices, pickups and inclusions from search_trips and get_trip instead.',
|
|
annotations: new ToolAnnotations(readOnlyHint: true, openWorldHint: false),
|
|
)]
|
|
final class GetDocumentTool
|
|
{
|
|
private const BODY_LIMIT = 20000;
|
|
|
|
public function __construct(
|
|
private readonly ContentDocumentRepository $repository,
|
|
private readonly ToolCallRunner $runner,
|
|
) {
|
|
}
|
|
|
|
public function __invoke(
|
|
#[Schema(description: 'A url returned by search_content.', minLength: 1)]
|
|
string $url,
|
|
): CallToolResult {
|
|
return $this->runner->run('get_document', get_defined_vars(), function () use ($url): array {
|
|
$document = $this->repository->findOneIndexedByUrl(trim($url));
|
|
|
|
if (null === $document) {
|
|
throw new ToolCallException('No document at this url. Use a url returned by search_content.');
|
|
}
|
|
|
|
$body = $document->getBodyMd();
|
|
$truncated = mb_strlen($body) > self::BODY_LIMIT;
|
|
|
|
return [
|
|
'type' => ContentSearch::publicType($document->getType()),
|
|
'title' => $document->getTitle(),
|
|
'url' => $document->getUrl(),
|
|
'site' => $document->getSite(),
|
|
'breadcrumb' => $document->getBreadcrumb(),
|
|
'body' => $truncated ? mb_substr($body, 0, self::BODY_LIMIT) : $body,
|
|
'truncated' => $truncated,
|
|
];
|
|
});
|
|
}
|
|
}
|