This commit is contained in:
team 1
2026-05-06 11:02:48 +02:00
parent 4832c2e287
commit 433ce2046f
3 changed files with 175 additions and 3 deletions

View File

@@ -3006,6 +3006,15 @@ final readonly class AgentRunner
return $shopResults;
}
return $this->sortDecoratedShopProductsByLength($decorated);
}
/**
* @param array<int, array{index: int, length: float|null, product: mixed}> $decorated
* @return ShopProductResult[]
*/
private function sortDecoratedShopProductsByLength(array $decorated): array
{
usort($decorated, static function (array $a, array $b): int {
if ($a['length'] === null && $b['length'] === null) {
return $a['index'] <=> $b['index'];
@@ -3041,6 +3050,112 @@ final readonly class AgentRunner
return false;
}
/**
* @return array{type: string, value: float}|null
*/
private function resolveShopResultLengthFilter(string $prompt, string $shopSearchQuery): ?array
{
if (!$this->agentRunnerConfig->isShopResultLengthFilterEnabled()) {
return null;
}
$text = trim($prompt . ' ' . $shopSearchQuery);
if ($text === '') {
return null;
}
foreach ($this->agentRunnerConfig->getShopResultMinLengthFilterPatterns() as $pattern) {
$value = $this->extractShopLengthFilterPatternValue($pattern, $text);
if ($value !== null) {
return ['type' => 'min', 'value' => $value];
}
}
foreach ($this->agentRunnerConfig->getShopResultMaxLengthFilterPatterns() as $pattern) {
$value = $this->extractShopLengthFilterPatternValue($pattern, $text);
if ($value !== null) {
return ['type' => 'max', 'value' => $value];
}
}
return null;
}
private function extractShopLengthFilterPatternValue(string $pattern, string $text): ?float
{
if (@preg_match($pattern, $text, $matches) !== 1) {
return null;
}
$value = $matches['value'] ?? ($matches[1] ?? null);
if (!is_scalar($value)) {
return null;
}
$normalized = str_replace(',', '.', (string) $value);
if (!is_numeric($normalized)) {
return null;
}
return (float) $normalized;
}
/**
* @param ShopProductResult[] $shopResults
* @param array{type: string, value: float} $lengthFilter
* @return ShopProductResult[]
*/
private function filterDirectShopAnswerResultsByLength(array $shopResults, array $lengthFilter): array
{
$decorated = [];
foreach (array_values($shopResults) as $index => $product) {
if (!$product instanceof ShopProductResult) {
continue;
}
$length = $this->extractShopProductLengthMeters($product);
if ($length === null) {
continue;
}
if (($lengthFilter['type'] === 'min' && $length < $lengthFilter['value'])
|| ($lengthFilter['type'] === 'max' && $length > $lengthFilter['value'])
) {
continue;
}
$decorated[] = [
'index' => $index,
'length' => $length,
'product' => $product,
];
}
return $this->sortDecoratedShopProductsByLength($decorated);
}
/**
* @param array{type: string, value: float} $lengthFilter
*/
private function buildDirectShopAnswerLengthFilterNote(array $lengthFilter): string
{
$template = $lengthFilter['type'] === 'max'
? $this->agentRunnerConfig->getDirectShopResultAnswerMaxLengthFilterNote()
: $this->agentRunnerConfig->getDirectShopResultAnswerMinLengthFilterNote();
return str_replace('{value}', $this->formatShopLengthFilterValue($lengthFilter['value']), $template);
}
private function formatShopLengthFilterValue(float $value): string
{
if (abs($value - round($value)) < 0.00001) {
return (string) (int) round($value);
}
return rtrim(rtrim(str_replace('.', ',', sprintf('%.2F', $value)), '0'), ',');
}
private function extractShopProductLengthMeters(ShopProductResult $product): ?float
{
$text = trim(implode(' ', array_filter([
@@ -3153,13 +3268,26 @@ final readonly class AgentRunner
return '';
}
if ($shopResults === []) {
$answerShopResults = $shopResults;
$lengthFilter = $this->resolveShopResultLengthFilter($prompt, $shopSearchQuery);
if ($lengthFilter !== null) {
$answerShopResults = $this->filterDirectShopAnswerResultsByLength($answerShopResults, $lengthFilter);
}
if ($answerShopResults === []) {
return $this->agentRunnerConfig->getDirectShopResultAnswerNoResultsMessage();
}
$lines = [$this->agentRunnerConfig->getDirectShopResultAnswerIntro()];
if ($this->isShopResultLengthSortRequested($prompt . ' ' . $shopSearchQuery)) {
if ($lengthFilter !== null) {
$note = trim($this->buildDirectShopAnswerLengthFilterNote($lengthFilter));
if ($note !== '') {
$lines[] = $note;
}
}
if ($lengthFilter !== null || $this->isShopResultLengthSortRequested($prompt . ' ' . $shopSearchQuery)) {
$note = trim($this->agentRunnerConfig->getDirectShopResultAnswerSortedByLengthNote());
if ($note !== '') {
$lines[] = $note;
@@ -3167,7 +3295,7 @@ final readonly class AgentRunner
}
$lines[] = '';
foreach ($this->buildDirectShopProductLines($shopResults, 'accessory_or_consumable') as $line) {
foreach ($this->buildDirectShopProductLines($answerShopResults, 'accessory_or_consumable') as $line) {
$lines[] = $line;
}