Wire admin studio SSR and search infrastructure

This commit is contained in:
2026-05-01 11:46:06 +02:00
parent 257b0dbef6
commit 18cea8b0f0
329 changed files with 197465 additions and 2741 deletions

View File

@@ -4,6 +4,7 @@ declare(strict_types=1);
namespace App\Services\Vision;
use Illuminate\Http\UploadedFile;
use Illuminate\Http\Client\PendingRequest;
use Illuminate\Http\Client\Response;
use Illuminate\Support\Facades\Http;
@@ -38,6 +39,27 @@ final class VectorGatewayClient
return is_array($json) ? $json : [];
}
public function upsertByFileContents(string $contents, string $filename, int|string $id, array $metadata = []): array
{
$response = $this->request()
->attach('file', $contents, $filename)
->post(
$this->url((string) config('vision.vector_gateway.upsert_file_endpoint', '/vectors/upsert/file')),
[
'id' => (string) $id,
'metadata_json' => $metadata === [] ? null : json_encode($metadata, JSON_THROW_ON_ERROR),
]
);
if ($response->failed()) {
throw new RuntimeException($this->failureMessage('Vector upsert', $response));
}
$json = $response->json();
return is_array($json) ? $json : [];
}
/**
* @return list<array{id: int|string, score: float, metadata: array<string, mixed>}>
*/
@@ -58,6 +80,45 @@ final class VectorGatewayClient
return $this->extractMatches($response->json());
}
/**
* @return list<array{id: int|string, score: float, metadata: array<string, mixed>}>
*/
public function searchByFileContents(string $contents, string $filename, int $limit = 5): array
{
$response = $this->request()
->attach('file', $contents, $filename)
->post(
$this->url((string) config('vision.vector_gateway.search_file_endpoint', '/vectors/search/file')),
[
'limit' => max(1, $limit),
]
);
if ($response->failed()) {
throw new RuntimeException($this->failureMessage('Vector search', $response));
}
return $this->extractMatches($response->json());
}
/**
* @return list<array{id: int|string, score: float, metadata: array<string, mixed>}>
*/
public function searchByUploadedFile(UploadedFile $file, int $limit = 5): array
{
$realPath = $file->getRealPath();
if (! is_string($realPath) || $realPath === '') {
throw new RuntimeException('Uploaded file has no readable temporary path for vector search.');
}
$contents = file_get_contents($realPath);
if (! is_string($contents) || $contents === '') {
throw new RuntimeException('Unable to read uploaded image bytes for vector search.');
}
return $this->searchByFileContents($contents, $file->getClientOriginalName() ?: 'search-image', $limit);
}
public function deleteByIds(array $ids): array
{
$response = $this->postJson(