Files
dreamstudio/app/Services/Runware/RunwareClient.php
T

78 lines
2.2 KiB
PHP
Raw Normal View History

<?php
namespace App\Services\Runware;
use Illuminate\Support\Facades\Http;
use RuntimeException;
/**
* Thin wrapper around Runware's HTTP API. Image and video generation use the
* batched task-array endpoint (POST /v1, body is a JSON array of tasks);
* text/LLM generation uses Runware's separate OpenAI-compatible endpoint
* (POST /v1/chat/completions). See https://runware.ai/docs/platform/introduction
* and https://runware.ai/docs/platform/openai.
*/
class RunwareClient
{
public function __construct(
protected string $apiKey,
protected string $baseUrl,
) {}
/**
* @param array<int, array<string, mixed>> $tasks
* @return array<int, array<string, mixed>>
*/
public function runTasks(array $tasks): array
{
$response = Http::withToken($this->apiKey)
->timeout(120)
->post($this->baseUrl, $tasks);
if ($response->failed()) {
throw new RuntimeException('Runware API request failed: '.$response->body());
}
$data = $response->json('data');
if (! is_array($data)) {
throw new RuntimeException('Unexpected Runware response shape: '.$response->body());
}
foreach ($data as $result) {
if (isset($result['error']) || ($result['status'] ?? null) === 'error') {
throw new RuntimeException('Runware task failed: '.json_encode($result));
}
}
return $data;
}
public function pollTask(string $taskUUID): array
{
$results = $this->runTasks([[
'taskType' => 'getResponse',
'taskUUID' => $taskUUID,
]]);
return $results[0] ?? throw new RuntimeException("No poll result for task {$taskUUID}");
}
/**
* @param array<string, mixed> $payload
* @return array<string, mixed>
*/
public function chatCompletion(array $payload): array
{
$response = Http::withToken($this->apiKey)
->timeout(120)
->post(rtrim($this->baseUrl, '/').'/chat/completions', $payload);
if ($response->failed()) {
throw new RuntimeException('Runware chat completion failed: '.$response->body());
}
return $response->json();
}
}