mirror of
https://github.com/nextcloud/server.git
synced 2026-05-28 04:32:30 -04:00
fix: weed out some psalm errors and run cs:fix
Signed-off-by: Marcel Klehr <mklehr@gmx.net>
This commit is contained in:
parent
00894e2420
commit
8352b27c11
17 changed files with 204 additions and 96 deletions
|
|
@ -26,6 +26,7 @@ declare(strict_types=1);
|
|||
namespace OC\TaskProcessing;
|
||||
|
||||
use OC\AppFramework\Bootstrap\Coordinator;
|
||||
use OC\Files\SimpleFS\SimpleFile;
|
||||
use OC\TaskProcessing\Db\TaskMapper;
|
||||
use OCP\AppFramework\Db\DoesNotExistException;
|
||||
use OCP\AppFramework\Db\MultipleObjectsReturnedException;
|
||||
|
|
@ -33,7 +34,6 @@ use OCP\BackgroundJob\IJobList;
|
|||
use OCP\EventDispatcher\IEventDispatcher;
|
||||
use OCP\Files\AppData\IAppDataFactory;
|
||||
use OCP\Files\File;
|
||||
use OCP\Files\Folder;
|
||||
use OCP\Files\GenericFileException;
|
||||
use OCP\Files\IAppData;
|
||||
use OCP\Files\IRootFolder;
|
||||
|
|
@ -47,7 +47,6 @@ use OCP\SpeechToText\ISpeechToTextProviderWithUserId;
|
|||
use OCP\TaskProcessing\EShapeType;
|
||||
use OCP\TaskProcessing\Events\TaskFailedEvent;
|
||||
use OCP\TaskProcessing\Events\TaskSuccessfulEvent;
|
||||
use OCP\TaskProcessing\Exception\Exception;
|
||||
use OCP\TaskProcessing\Exception\NotFoundException;
|
||||
use OCP\TaskProcessing\Exception\ProcessingException;
|
||||
use OCP\TaskProcessing\Exception\ValidationException;
|
||||
|
|
@ -71,7 +70,7 @@ class Manager implements IManager {
|
|||
public const LEGACY_PREFIX_TEXTTOIMAGE = 'legacy:TextToImage:';
|
||||
public const LEGACY_PREFIX_SPEECHTOTEXT = 'legacy:SpeechToText:';
|
||||
|
||||
/** @var |null */
|
||||
/** @var list<IProvider>|null */
|
||||
private ?array $providers = null;
|
||||
|
||||
/** @var array<string,array{name: string, description: string, inputShape: array<string, ShapeDescriptor>, optionalInputShape: array<string, ShapeDescriptor>, outputShape: array<string, ShapeDescriptor>, optionalOutputShape: array<string, ShapeDescriptor>}>|null */
|
||||
|
|
@ -281,10 +280,10 @@ class Manager implements IManager {
|
|||
}
|
||||
try {
|
||||
$this->provider->generate($input['input'], $resources);
|
||||
}catch (\RuntimeException $e) {
|
||||
} catch (\RuntimeException $e) {
|
||||
throw new ProcessingException($e->getMessage(), 0, $e);
|
||||
}
|
||||
return ['images' => array_map(fn(File $file) => base64_encode($file->getContent()), $files)];
|
||||
return ['images' => array_map(fn (File $file) => base64_encode($file->getContent()), $files)];
|
||||
}
|
||||
};
|
||||
$newProviders[$newProvider->getId()] = $newProvider;
|
||||
|
|
@ -358,7 +357,7 @@ class Manager implements IManager {
|
|||
}
|
||||
try {
|
||||
$result = $this->provider->transcribeFile($file);
|
||||
}catch (\RuntimeException $e) {
|
||||
} catch (\RuntimeException $e) {
|
||||
throw new ProcessingException($e->getMessage(), 0, $e);
|
||||
}
|
||||
return ['output' => $result];
|
||||
|
|
@ -443,7 +442,7 @@ class Manager implements IManager {
|
|||
* @return IProvider
|
||||
* @throws \OCP\TaskProcessing\Exception\Exception
|
||||
*/
|
||||
private function _getPreferredProvider(string $taskType){
|
||||
private function _getPreferredProvider(string $taskType) {
|
||||
$providers = $this->getProviders();
|
||||
foreach ($providers as $provider) {
|
||||
if ($provider->getTaskType() === $taskType) {
|
||||
|
|
@ -454,12 +453,12 @@ class Manager implements IManager {
|
|||
}
|
||||
|
||||
/**
|
||||
* @param array<string, ShapeDescriptor> $spec
|
||||
* @param array<string, mixed> $io
|
||||
* @param ShapeDescriptor[] $spec
|
||||
* @param array $io
|
||||
* @return void
|
||||
* @throws ValidationException
|
||||
*/
|
||||
private function validateInput(array $spec, array $io, bool $optional = false) {
|
||||
private function validateInput(array $spec, array $io, bool $optional = false): void {
|
||||
foreach ($spec as $key => $descriptor) {
|
||||
$type = $descriptor->getShapeType();
|
||||
if (!isset($io[$key])) {
|
||||
|
|
@ -471,49 +470,50 @@ class Manager implements IManager {
|
|||
if ($type === EShapeType::Text && !is_string($io[$key])) {
|
||||
throw new \OCP\TaskProcessing\Exception\ValidationException('Non-text item provided for Text key: "' . $key . '"');
|
||||
}
|
||||
if ($type === EShapeType::ListOfTexts && (!is_array($io[$key]) || count(array_filter($io[$key], fn($item) => !is_string($item))) > 0)) {
|
||||
if ($type === EShapeType::ListOfTexts && (!is_array($io[$key]) || count(array_filter($io[$key], fn ($item) => !is_string($item))) > 0)) {
|
||||
throw new \OCP\TaskProcessing\Exception\ValidationException('None-text list item provided for ListOfTexts key: "' . $key . '"');
|
||||
}
|
||||
if ($type === EShapeType::Number && !is_numeric($io[$key])) {
|
||||
throw new \OCP\TaskProcessing\Exception\ValidationException('None-numeric item provided for Number key: "' . $key . '"');
|
||||
}
|
||||
if ($type === EShapeType::ListOfNumbers && (!is_array($io[$key]) || count(array_filter($io[$key], fn($item) => !is_numeric($item))) > 0)) {
|
||||
if ($type === EShapeType::ListOfNumbers && (!is_array($io[$key]) || count(array_filter($io[$key], fn ($item) => !is_numeric($item))) > 0)) {
|
||||
throw new \OCP\TaskProcessing\Exception\ValidationException('None-numeric list item provided for ListOfNumbers key: "' . $key . '"');
|
||||
}
|
||||
if ($type === EShapeType::Image && !is_numeric($io[$key])) {
|
||||
throw new \OCP\TaskProcessing\Exception\ValidationException('None-image item provided for Image key: "' . $key . '"');
|
||||
}
|
||||
if ($type === EShapeType::ListOfImages && (!is_array($io[$key]) || count(array_filter($io[$key], fn($item) => !is_numeric($item))) > 0)) {
|
||||
if ($type === EShapeType::ListOfImages && (!is_array($io[$key]) || count(array_filter($io[$key], fn ($item) => !is_numeric($item))) > 0)) {
|
||||
throw new \OCP\TaskProcessing\Exception\ValidationException('None-image list item provided for ListOfImages key: "' . $key . '"');
|
||||
}
|
||||
if ($type === EShapeType::Audio && !is_numeric($io[$key])) {
|
||||
throw new \OCP\TaskProcessing\Exception\ValidationException('None-audio item provided for Audio key: "' . $key . '"');
|
||||
}
|
||||
if ($type === EShapeType::ListOfAudio && (!is_array($io[$key]) || count(array_filter($io[$key], fn($item) => !is_numeric($item))) > 0)) {
|
||||
if ($type === EShapeType::ListOfAudio && (!is_array($io[$key]) || count(array_filter($io[$key], fn ($item) => !is_numeric($item))) > 0)) {
|
||||
throw new \OCP\TaskProcessing\Exception\ValidationException('None-audio list item provided for ListOfAudio key: "' . $key . '"');
|
||||
}
|
||||
if ($type === EShapeType::Video && !is_numeric($io[$key])) {
|
||||
throw new \OCP\TaskProcessing\Exception\ValidationException('None-video item provided for Video key: "' . $key . '"');
|
||||
}
|
||||
if ($type === EShapeType::ListOfVideo && (!is_array($io[$key]) || count(array_filter($io[$key], fn($item) => !is_numeric($item))) > 0)) {
|
||||
if ($type === EShapeType::ListOfVideo && (!is_array($io[$key]) || count(array_filter($io[$key], fn ($item) => !is_numeric($item))) > 0)) {
|
||||
throw new \OCP\TaskProcessing\Exception\ValidationException('None-video list item provided for ListOfTexts key: "' . $key . '"');
|
||||
}
|
||||
if ($type === EShapeType::File && !is_numeric($io[$key])) {
|
||||
throw new \OCP\TaskProcessing\Exception\ValidationException('None-file item provided for File key: "' . $key . '"');
|
||||
}
|
||||
if ($type === EShapeType::ListOfFiles && (!is_array($io[$key]) || count(array_filter($io[$key], fn($item) => !is_numeric($item))) > 0)) {
|
||||
if ($type === EShapeType::ListOfFiles && (!is_array($io[$key]) || count(array_filter($io[$key], fn ($item) => !is_numeric($item))) > 0)) {
|
||||
throw new \OCP\TaskProcessing\Exception\ValidationException('None-audio list item provided for ListOfFiles key: "' . $key . '"');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, ShapeDescriptor> $spec
|
||||
* @param ShapeDescriptor[] $spec
|
||||
* @param array $io
|
||||
* @param bool $optional
|
||||
* @return void
|
||||
* @throws ValidationException
|
||||
*/
|
||||
private function validateOutput(array $spec, array $io, bool $optional = false) {
|
||||
private function validateOutput(array $spec, array $io, bool $optional = false): void {
|
||||
foreach ($spec as $key => $descriptor) {
|
||||
$type = $descriptor->getShapeType();
|
||||
if (!isset($io[$key])) {
|
||||
|
|
@ -525,37 +525,37 @@ class Manager implements IManager {
|
|||
if ($type === EShapeType::Text && !is_string($io[$key])) {
|
||||
throw new \OCP\TaskProcessing\Exception\ValidationException('Non-text item provided for Text key: "' . $key . '"');
|
||||
}
|
||||
if ($type === EShapeType::ListOfTexts && (!is_array($io[$key]) || count(array_filter($io[$key], fn($item) => !is_string($item))) > 0)) {
|
||||
if ($type === EShapeType::ListOfTexts && (!is_array($io[$key]) || count(array_filter($io[$key], fn ($item) => !is_string($item))) > 0)) {
|
||||
throw new \OCP\TaskProcessing\Exception\ValidationException('None-text list item provided for ListOfTexts key: "' . $key . '"');
|
||||
}
|
||||
if ($type === EShapeType::Number && !is_numeric($io[$key])) {
|
||||
throw new \OCP\TaskProcessing\Exception\ValidationException('None-numeric item provided for Number key: "' . $key . '"');
|
||||
}
|
||||
if ($type === EShapeType::ListOfNumbers && (!is_array($io[$key]) || count(array_filter($io[$key], fn($item) => !is_numeric($item))) > 0)) {
|
||||
if ($type === EShapeType::ListOfNumbers && (!is_array($io[$key]) || count(array_filter($io[$key], fn ($item) => !is_numeric($item))) > 0)) {
|
||||
throw new \OCP\TaskProcessing\Exception\ValidationException('None-numeric list item provided for ListOfNumbers key: "' . $key . '"');
|
||||
}
|
||||
if ($type === EShapeType::Image && !is_string($io[$key])) {
|
||||
throw new \OCP\TaskProcessing\Exception\ValidationException('None-image item provided for Image key: "' . $key . '". Expecting base64 encoded image data.');
|
||||
}
|
||||
if ($type === EShapeType::ListOfImages && (!is_array($io[$key]) || count(array_filter($io[$key], fn($item) => !is_string($item))) > 0)) {
|
||||
if ($type === EShapeType::ListOfImages && (!is_array($io[$key]) || count(array_filter($io[$key], fn ($item) => !is_string($item))) > 0)) {
|
||||
throw new \OCP\TaskProcessing\Exception\ValidationException('None-image list item provided for ListOfImages key: "' . $key . '". Expecting base64 encoded image data.');
|
||||
}
|
||||
if ($type === EShapeType::Audio && !is_string($io[$key])) {
|
||||
throw new \OCP\TaskProcessing\Exception\ValidationException('None-audio item provided for Audio key: "' . $key . '". Expecting base64 encoded audio data.');
|
||||
}
|
||||
if ($type === EShapeType::ListOfAudio && (!is_array($io[$key]) || count(array_filter($io[$key], fn($item) => !is_string($item))) > 0)) {
|
||||
if ($type === EShapeType::ListOfAudio && (!is_array($io[$key]) || count(array_filter($io[$key], fn ($item) => !is_string($item))) > 0)) {
|
||||
throw new \OCP\TaskProcessing\Exception\ValidationException('None-audio list item provided for ListOfAudio key: "' . $key . '". Expecting base64 encoded audio data.');
|
||||
}
|
||||
if ($type === EShapeType::Video && !is_string($io[$key])) {
|
||||
throw new \OCP\TaskProcessing\Exception\ValidationException('None-video item provided for Video key: "' . $key . '". Expecting base64 encoded video data.');
|
||||
}
|
||||
if ($type === EShapeType::ListOfVideo && (!is_array($io[$key]) || count(array_filter($io[$key], fn($item) => !is_string($item))) > 0)) {
|
||||
if ($type === EShapeType::ListOfVideo && (!is_array($io[$key]) || count(array_filter($io[$key], fn ($item) => !is_string($item))) > 0)) {
|
||||
throw new \OCP\TaskProcessing\Exception\ValidationException('None-video list item provided for ListOfTexts key: "' . $key . '". Expecting base64 encoded video data.');
|
||||
}
|
||||
if ($type === EShapeType::File && !is_string($io[$key])) {
|
||||
throw new \OCP\TaskProcessing\Exception\ValidationException('None-file item provided for File key: "' . $key . '". Expecting base64 encoded file data.');
|
||||
}
|
||||
if ($type === EShapeType::ListOfFiles && (!is_array($io[$key]) || count(array_filter($io[$key], fn($item) => !is_string($item))) > 0)) {
|
||||
if ($type === EShapeType::ListOfFiles && (!is_array($io[$key]) || count(array_filter($io[$key], fn ($item) => !is_string($item))) > 0)) {
|
||||
throw new \OCP\TaskProcessing\Exception\ValidationException('None-audio list item provided for ListOfFiles key: "' . $key . '". Expecting base64 encoded image data.');
|
||||
}
|
||||
}
|
||||
|
|
@ -567,8 +567,8 @@ class Manager implements IManager {
|
|||
* @return array<string, mixed>
|
||||
*/
|
||||
private function removeSuperfluousArrayKeys(array $array, ...$specs): array {
|
||||
$keys = array_unique(array_reduce($specs, fn($carry, $spec) => $carry + array_keys($spec), []));
|
||||
$values = array_map(fn(string $key) => $array[$key], $keys);
|
||||
$keys = array_unique(array_reduce($specs, fn ($carry, $spec) => $carry + array_keys($spec), []));
|
||||
$values = array_map(fn (string $key) => $array[$key], $keys);
|
||||
return array_combine($keys, $values);
|
||||
}
|
||||
|
||||
|
|
@ -701,7 +701,7 @@ class Manager implements IManager {
|
|||
$task->setStatus(Task::STATUS_FAILED);
|
||||
$task->setErrorMessage($error);
|
||||
$this->logger->warning('A TaskProcessing ' . $task->getTaskType() . ' task with id ' . $id . ' failed with the following message: ' . $error);
|
||||
} else if ($result !== null) {
|
||||
} elseif ($result !== null) {
|
||||
$taskTypes = $this->getAvailableTaskTypes();
|
||||
$outputShape = $taskTypes[$task->getTaskType()]['outputShape'];
|
||||
$optionalOutputShape = $taskTypes[$task->getTaskType()]['optionalOutputShape'];
|
||||
|
|
@ -738,7 +738,7 @@ class Manager implements IManager {
|
|||
}
|
||||
if ($task->getStatus() === Task::STATUS_SUCCESSFUL) {
|
||||
$event = new TaskSuccessfulEvent($task);
|
||||
}else{
|
||||
} else {
|
||||
$event = new TaskFailedEvent($task, $error);
|
||||
}
|
||||
$this->dispatcher->dispatchTyped($event);
|
||||
|
|
@ -773,7 +773,7 @@ class Manager implements IManager {
|
|||
public function getUserTasksByApp(?string $userId, string $appId, ?string $identifier = null): array {
|
||||
try {
|
||||
$taskEntities = $this->taskMapper->findUserTasksByApp($userId, $appId, $identifier);
|
||||
return array_map(fn($taskEntity) => $taskEntity->toPublicTask(), $taskEntities);
|
||||
return array_map(fn ($taskEntity) => $taskEntity->toPublicTask(), $taskEntities);
|
||||
} catch (\OCP\DB\Exception $e) {
|
||||
throw new \OCP\TaskProcessing\Exception\Exception('There was a problem finding a task', 0, $e);
|
||||
} catch (\JsonException $e) {
|
||||
|
|
@ -784,52 +784,52 @@ class Manager implements IManager {
|
|||
/**
|
||||
* Takes task input or output data and replaces fileIds with base64 data
|
||||
*
|
||||
* @param array<string, ShapeDescriptor> ...$specs the specs
|
||||
* @param array $inputOutput
|
||||
* @return array<string, mixed>
|
||||
* @param ShapeDescriptor[] ...$specs the specs
|
||||
* @param array $input
|
||||
* @return array
|
||||
* @throws GenericFileException
|
||||
* @throws LockedException
|
||||
* @throws NotPermittedException
|
||||
* @throws ValidationException
|
||||
*/
|
||||
public function fillInputOutputFileData(array $inputOutput, ...$specs): array {
|
||||
*/
|
||||
public function fillInputFileData(array $input, ...$specs): array {
|
||||
$newInputOutput = [];
|
||||
$spec = array_reduce($specs, fn($carry, $spec) => $carry + $spec, []);
|
||||
$spec = array_reduce($specs, fn ($carry, $spec) => $carry + $spec, []);
|
||||
foreach($spec as $key => $descriptor) {
|
||||
$type = $descriptor->getShapeType();
|
||||
if (!isset($inputOutput[$key])) {
|
||||
if (!isset($input[$key])) {
|
||||
continue;
|
||||
}
|
||||
if (!in_array(EShapeType::from($type->value % 10), [EShapeType::Image, EShapeType::Audio, EShapeType::Video, EShapeType::File], true)) {
|
||||
$newInputOutput[$key] = $inputOutput[$key];
|
||||
$newInputOutput[$key] = $input[$key];
|
||||
continue;
|
||||
}
|
||||
if ($type->value < 10) {
|
||||
$node = $this->rootFolder->getFirstNodeById((int)$inputOutput[$key]);
|
||||
$node = $this->rootFolder->getFirstNodeById((int)$input[$key]);
|
||||
if ($node === null) {
|
||||
$node = $this->rootFolder->getFirstNodeByIdInPath((int)$inputOutput[$key], '/' . $this->rootFolder->getAppDataDirectoryName() . '/');
|
||||
$node = $this->rootFolder->getFirstNodeByIdInPath((int)$input[$key], '/' . $this->rootFolder->getAppDataDirectoryName() . '/');
|
||||
if (!$node instanceof File) {
|
||||
throw new ValidationException('File id given for key "' . $key . '" is not a file');
|
||||
}
|
||||
} else if (!$node instanceof File) {
|
||||
} elseif (!$node instanceof File) {
|
||||
throw new ValidationException('File id given for key "' . $key . '" is not a file');
|
||||
}
|
||||
// TODO: Validate if userId has access to this file
|
||||
$newInputOutput[$key] = base64_encode($node->getContent());
|
||||
$newInputOutput[$key] = $node;
|
||||
} else {
|
||||
$newInputOutput[$key] = [];
|
||||
foreach ($inputOutput[$key] as $item) {
|
||||
$node = $this->rootFolder->getFirstNodeById((int)$inputOutput[$key]);
|
||||
foreach ($input[$key] as $item) {
|
||||
$node = $this->rootFolder->getFirstNodeById((int)$input[$key]);
|
||||
if ($node === null) {
|
||||
$node = $this->rootFolder->getFirstNodeByIdInPath((int)$inputOutput[$key], '/' . $this->rootFolder->getAppDataDirectoryName() . '/');
|
||||
$node = $this->rootFolder->getFirstNodeByIdInPath((int)$input[$key], '/' . $this->rootFolder->getAppDataDirectoryName() . '/');
|
||||
if (!$node instanceof File) {
|
||||
throw new ValidationException('File id given for key "' . $key . '" is not a file');
|
||||
}
|
||||
} else if (!$node instanceof File) {
|
||||
} elseif (!$node instanceof File) {
|
||||
throw new ValidationException('File id given for key "' . $key . '" is not a file');
|
||||
}
|
||||
// TODO: Validate if userId has access to this file
|
||||
$newInputOutput[$key][] = base64_encode($node->getContent());
|
||||
$newInputOutput[$key][] = $node;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -839,40 +839,42 @@ class Manager implements IManager {
|
|||
/**
|
||||
*Takes task input or output and replaces base64 data with file ids
|
||||
*
|
||||
* @param array<string, mixed> $inputOutput
|
||||
* @param array<string, ShapeDescriptor> ...$specs the specs that define which keys to keep
|
||||
* @return array<string, mixed>
|
||||
* @param array $output
|
||||
* @param ShapeDescriptor[] ...$specs the specs that define which keys to keep
|
||||
* @return array
|
||||
* @throws NotPermittedException
|
||||
*/
|
||||
public function encapsulateInputOutputFileData(array $inputOutput, ...$specs): array {
|
||||
$newInputOutput = [];
|
||||
public function encapsulateOutputFileData(array $output, ...$specs): array {
|
||||
$newOutput = [];
|
||||
try {
|
||||
$folder = $this->appData->getFolder('TaskProcessing');
|
||||
} catch (\OCP\Files\NotFoundException) {
|
||||
$folder = $this->appData->newFolder('TaskProcessing');
|
||||
}
|
||||
$spec = array_reduce($specs, fn($carry, $spec) => $carry + $spec, []);
|
||||
$spec = array_reduce($specs, fn ($carry, $spec) => $carry + $spec, []);
|
||||
foreach($spec as $key => $descriptor) {
|
||||
$type = $descriptor->getShapeType();
|
||||
if (!isset($inputOutput[$key])) {
|
||||
if (!isset($output[$key])) {
|
||||
continue;
|
||||
}
|
||||
if (!in_array(EShapeType::from($type->value % 10), [EShapeType::Image, EShapeType::Audio, EShapeType::Video, EShapeType::File], true)) {
|
||||
$newInputOutput[$key] = $inputOutput[$key];
|
||||
$newOutput[$key] = $output[$key];
|
||||
continue;
|
||||
}
|
||||
if ($type->value < 10) {
|
||||
$file = $folder->newFile((string) rand(0, 10000000), base64_decode($inputOutput[$key]));
|
||||
$newInputOutput[$key] = $file->getId();
|
||||
/** @var SimpleFile $file */
|
||||
$file = $folder->newFile((string) rand(0, 10000000), $output[$key]);
|
||||
$newOutput[$key] = $file->getId(); // polymorphic call to SimpleFile
|
||||
} else {
|
||||
$newInputOutput = [];
|
||||
foreach ($inputOutput[$key] as $item) {
|
||||
$file = $folder->newFile((string) rand(0, 10000000), base64_decode($item));
|
||||
$newInputOutput[$key][] = $file->getId();
|
||||
$newOutput = [];
|
||||
foreach ($output[$key] as $item) {
|
||||
/** @var SimpleFile $file */
|
||||
$file = $folder->newFile((string) rand(0, 10000000), $item);
|
||||
$newOutput[$key][] = $file->getId();
|
||||
}
|
||||
}
|
||||
}
|
||||
return $newInputOutput;
|
||||
return $newOutput;
|
||||
}
|
||||
|
||||
public function prepareInputData(Task $task): array {
|
||||
|
|
@ -884,7 +886,7 @@ class Manager implements IManager {
|
|||
$this->validateInput($inputShape, $input);
|
||||
$this->validateInput($optionalInputShape, $input, true);
|
||||
$input = $this->removeSuperfluousArrayKeys($input, $inputShape, $optionalInputShape);
|
||||
$input = $this->fillInputOutputFileData($input, $inputShape, $optionalInputShape);
|
||||
$input = $this->fillInputFileData($input, $inputShape, $optionalInputShape);
|
||||
return $input;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -121,12 +121,4 @@ interface ISimpleFile {
|
|||
* @since 14.0.0
|
||||
*/
|
||||
public function write();
|
||||
|
||||
/**
|
||||
* Returns the file id
|
||||
*
|
||||
* @return int
|
||||
* @since 30.0.0
|
||||
*/
|
||||
public function getId(): int;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,6 +25,10 @@ declare(strict_types=1);
|
|||
|
||||
namespace OCP\TaskProcessing;
|
||||
|
||||
/**
|
||||
* The input and output Shape types
|
||||
* @since 30.0.0
|
||||
*/
|
||||
enum EShapeType: int {
|
||||
case Number = 0;
|
||||
case Text = 1;
|
||||
|
|
@ -39,4 +43,3 @@ enum EShapeType: int {
|
|||
case ListOfVideo = 14;
|
||||
case ListOfFiles = 15;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2,6 +2,9 @@
|
|||
|
||||
namespace OCP\TaskProcessing\Exception;
|
||||
|
||||
/**
|
||||
* @since 30.0.0
|
||||
*/
|
||||
class NotFoundException extends Exception {
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,9 @@
|
|||
|
||||
namespace OCP\TaskProcessing\Exception;
|
||||
|
||||
/**
|
||||
* @since 30.0.0
|
||||
*/
|
||||
class ValidationException extends Exception {
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@ interface IManager {
|
|||
public function getProviders(): array;
|
||||
|
||||
/**
|
||||
* @return array<string,array{name: string, description: string, inputShape: array<string, ShapeDescriptor>, optionalInputShape: array<string, ShapeDescriptor>, outputShape: array<string, ShapeDescriptor>, optionalOutputShape: array<string, ShapeDescriptor>}>
|
||||
* @return array<string,array{name: string, description: string, inputShape: ShapeDescriptor[], optionalInputShape: array<string, ShapeDescriptor>, outputShape: array<string, ShapeDescriptor>, optionalOutputShape: array<string, ShapeDescriptor>}>
|
||||
* @since 30.0.0
|
||||
*/
|
||||
public function getAvailableTaskTypes(): array;
|
||||
|
|
@ -109,6 +109,7 @@ interface IManager {
|
|||
* @throws ValidationException
|
||||
* @throws Exception
|
||||
* @throws NotFoundException
|
||||
* @since 30.0.0
|
||||
*/
|
||||
public function setTaskProgress(int $id, float $progress): bool;
|
||||
|
||||
|
|
@ -152,6 +153,7 @@ interface IManager {
|
|||
* @throws GenericFileException
|
||||
* @throws LockedException
|
||||
* @throws ValidationException
|
||||
* @since 30.0.0
|
||||
*/
|
||||
public function prepareInputData(Task $task): array;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,9 +26,6 @@ declare(strict_types=1);
|
|||
|
||||
namespace OCP\TaskProcessing;
|
||||
|
||||
use OCP\TextProcessing\ITaskType;
|
||||
use RuntimeException;
|
||||
|
||||
/**
|
||||
* This is the interface that is implemented by apps that
|
||||
* implement a task processing provider
|
||||
|
|
@ -66,7 +63,7 @@ interface IProvider {
|
|||
* Returns the shape of optional input parameters
|
||||
*
|
||||
* @since 30.0.0
|
||||
* @psalm-return array{string, ShapeDescriptor}
|
||||
* @psalm-return ShapeDescriptor[]
|
||||
*/
|
||||
public function getOptionalInputShape(): array;
|
||||
|
||||
|
|
@ -74,7 +71,7 @@ interface IProvider {
|
|||
* Returns the shape of optional output parameters
|
||||
*
|
||||
* @since 30.0.0
|
||||
* @psalm-return array{string, ShapeDescriptor}
|
||||
* @psalm-return ShapeDescriptor[]
|
||||
*/
|
||||
public function getOptionalOutputShape(): array;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -59,7 +59,7 @@ interface ITaskType {
|
|||
* Returns the shape of the input array
|
||||
*
|
||||
* @since 30.0.0
|
||||
* @psalm-return array{string, ShapeDescriptor}
|
||||
* @psalm-return ShapeDescriptor[]
|
||||
*/
|
||||
public function getInputShape(): array;
|
||||
|
||||
|
|
@ -67,7 +67,7 @@ interface ITaskType {
|
|||
* Returns the shape of the output array
|
||||
*
|
||||
* @since 30.0.0
|
||||
* @psalm-return array{string, ShapeDescriptor}
|
||||
* @psalm-return ShapeDescriptor[]
|
||||
*/
|
||||
public function getOutputShape(): array;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,17 @@
|
|||
|
||||
namespace OCP\TaskProcessing;
|
||||
|
||||
/**
|
||||
* Data object for input output shape entries
|
||||
* @since 30.0.0
|
||||
*/
|
||||
class ShapeDescriptor {
|
||||
/**
|
||||
* @param string $name
|
||||
* @param string $description
|
||||
* @param EShapeType $shapeType
|
||||
* @since 30.0.0
|
||||
*/
|
||||
public function __construct(
|
||||
private string $name,
|
||||
private string $description,
|
||||
|
|
@ -10,14 +20,26 @@ class ShapeDescriptor {
|
|||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
* @since 30.0.0
|
||||
*/
|
||||
public function getName(): string {
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
* @since 30.0.0
|
||||
*/
|
||||
public function getDescription(): string {
|
||||
return $this->description;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return EShapeType
|
||||
* @since 30.0.0
|
||||
*/
|
||||
public function getShapeType(): EShapeType {
|
||||
return $this->shapeType;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,11 +26,6 @@ declare(strict_types=1);
|
|||
namespace OCP\TaskProcessing;
|
||||
|
||||
use DateTime;
|
||||
use OCP\Files\AppData\IAppDataFactory;
|
||||
use OCP\Files\NotFoundException;
|
||||
use OCP\Files\NotPermittedException;
|
||||
use OCP\IImage;
|
||||
use OCP\Image;
|
||||
use OCP\TaskProcessing\Exception\ValidationException;
|
||||
|
||||
/**
|
||||
|
|
@ -158,6 +153,7 @@ final class Task implements \JsonSerializable {
|
|||
}
|
||||
|
||||
/**
|
||||
* @return array<string, mixed>|null
|
||||
* @since 30.0.0
|
||||
*/
|
||||
final public function getOutput(): ?array {
|
||||
|
|
@ -165,7 +161,7 @@ final class Task implements \JsonSerializable {
|
|||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
* @return array<string, mixed>
|
||||
* @since 30.0.0
|
||||
*/
|
||||
final public function getInput(): array {
|
||||
|
|
|
|||
|
|
@ -36,7 +36,10 @@ use OCP\TaskProcessing\ShapeDescriptor;
|
|||
* @since 30.0.0
|
||||
*/
|
||||
class AudioToText implements ITaskType {
|
||||
const ID = 'core:audio2text';
|
||||
/**
|
||||
* @since 30.0.0
|
||||
*/
|
||||
public const ID = 'core:audio2text';
|
||||
|
||||
private IL10N $l;
|
||||
|
||||
|
|
@ -67,10 +70,18 @@ class AudioToText implements ITaskType {
|
|||
return $this->l->t('Transcribe the things said in an audio');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
* @since 30.0.0
|
||||
*/
|
||||
public function getId(): string {
|
||||
return self::ID;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return ShapeDescriptor[]
|
||||
* @since 30.0.0
|
||||
*/
|
||||
public function getInputShape(): array {
|
||||
return [
|
||||
'input' => new ShapeDescriptor(
|
||||
|
|
@ -81,6 +92,10 @@ class AudioToText implements ITaskType {
|
|||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return ShapeDescriptor[]
|
||||
* @since 30.0.0
|
||||
*/
|
||||
public function getOutputShape(): array {
|
||||
return [
|
||||
'output' => new ShapeDescriptor(
|
||||
|
|
|
|||
|
|
@ -36,7 +36,10 @@ use OCP\TaskProcessing\ShapeDescriptor;
|
|||
* @since 30.0.0
|
||||
*/
|
||||
class TextToImage implements ITaskType {
|
||||
const ID = 'core:text2image';
|
||||
/**
|
||||
* @since 30.0.0
|
||||
*/
|
||||
public const ID = 'core:text2image';
|
||||
|
||||
private IL10N $l;
|
||||
|
||||
|
|
@ -67,10 +70,18 @@ class TextToImage implements ITaskType {
|
|||
return $this->l->t('Generate an image from a text prompt');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
* @since 30.0.0
|
||||
*/
|
||||
public function getId(): string {
|
||||
return self::ID;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return ShapeDescriptor[]
|
||||
* @since 30.0.0
|
||||
*/
|
||||
public function getInputShape(): array {
|
||||
return [
|
||||
'input' => new ShapeDescriptor(
|
||||
|
|
@ -86,6 +97,10 @@ class TextToImage implements ITaskType {
|
|||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return ShapeDescriptor[]
|
||||
* @since 30.0.0
|
||||
*/
|
||||
public function getOutputShape(): array {
|
||||
return [
|
||||
'images' => new ShapeDescriptor(
|
||||
|
|
|
|||
|
|
@ -36,7 +36,10 @@ use OCP\TaskProcessing\ShapeDescriptor;
|
|||
* @since 30.0.0
|
||||
*/
|
||||
class TextToText implements ITaskType {
|
||||
const ID = 'core:text2text';
|
||||
/**
|
||||
* @since 30.0.0
|
||||
*/
|
||||
public const ID = 'core:text2text';
|
||||
|
||||
private IL10N $l;
|
||||
|
||||
|
|
@ -67,10 +70,18 @@ class TextToText implements ITaskType {
|
|||
return $this->l->t('Runs an arbitrary prompt through a language model that retuns a reply');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
* @since 30.0.0
|
||||
*/
|
||||
public function getId(): string {
|
||||
return self::ID;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return ShapeDescriptor[]
|
||||
* @since 30.0.0
|
||||
*/
|
||||
public function getInputShape(): array {
|
||||
return [
|
||||
'input' => new ShapeDescriptor(
|
||||
|
|
@ -81,6 +92,10 @@ class TextToText implements ITaskType {
|
|||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return ShapeDescriptor[]
|
||||
* @since 30.0.0
|
||||
*/
|
||||
public function getOutputShape(): array {
|
||||
return [
|
||||
'output' => new ShapeDescriptor(
|
||||
|
|
|
|||
|
|
@ -36,7 +36,10 @@ use OCP\TaskProcessing\ShapeDescriptor;
|
|||
* @since 30.0.0
|
||||
*/
|
||||
class TextToTextHeadline implements ITaskType {
|
||||
const ID = 'core:text2text:headline';
|
||||
/**
|
||||
* @since 30.0.0
|
||||
*/
|
||||
public const ID = 'core:text2text:headline';
|
||||
|
||||
private IL10N $l;
|
||||
|
||||
|
|
@ -67,10 +70,18 @@ class TextToTextHeadline implements ITaskType {
|
|||
return $this->l->t('Generates a possible headline for a text.');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
* @since 30.0.0
|
||||
*/
|
||||
public function getId(): string {
|
||||
return self::ID;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return ShapeDescriptor[]
|
||||
* @since 30.0.0
|
||||
*/
|
||||
public function getInputShape(): array {
|
||||
return [
|
||||
'input' => new ShapeDescriptor(
|
||||
|
|
@ -81,6 +92,10 @@ class TextToTextHeadline implements ITaskType {
|
|||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return ShapeDescriptor[]
|
||||
* @since 30.0.0
|
||||
*/
|
||||
public function getOutputShape(): array {
|
||||
return [
|
||||
'output' => new ShapeDescriptor(
|
||||
|
|
|
|||
|
|
@ -36,7 +36,10 @@ use OCP\TaskProcessing\ShapeDescriptor;
|
|||
* @since 30.0.0
|
||||
*/
|
||||
class TextToTextSummary implements ITaskType {
|
||||
const ID = 'core:text2text:summary';
|
||||
/**
|
||||
* @since 30.0.0
|
||||
*/
|
||||
public const ID = 'core:text2text:summary';
|
||||
private IL10N $l;
|
||||
|
||||
/**
|
||||
|
|
@ -66,10 +69,18 @@ class TextToTextSummary implements ITaskType {
|
|||
return $this->l->t('Summarizes a text');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
* @since 30.0.0
|
||||
*/
|
||||
public function getId(): string {
|
||||
return self::ID;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return ShapeDescriptor[]
|
||||
* @since 30.0.0
|
||||
*/
|
||||
public function getInputShape(): array {
|
||||
return [
|
||||
'input' => new ShapeDescriptor(
|
||||
|
|
@ -80,6 +91,10 @@ class TextToTextSummary implements ITaskType {
|
|||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return ShapeDescriptor[]
|
||||
* @since 30.0.0
|
||||
*/
|
||||
public function getOutputShape(): array {
|
||||
return [
|
||||
'output' => new ShapeDescriptor(
|
||||
|
|
|
|||
|
|
@ -36,7 +36,10 @@ use OCP\TaskProcessing\ShapeDescriptor;
|
|||
* @since 30.0.0
|
||||
*/
|
||||
class TextToTextTopics implements ITaskType {
|
||||
const ID = 'core:text2text:topics';
|
||||
/**
|
||||
* @since 30.0.0
|
||||
*/
|
||||
public const ID = 'core:text2text:topics';
|
||||
|
||||
private IL10N $l;
|
||||
|
||||
|
|
@ -67,10 +70,18 @@ class TextToTextTopics implements ITaskType {
|
|||
return $this->l->t('Extracts topics from a text and outputs them separated by commas');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
* @since 30.0.0
|
||||
*/
|
||||
public function getId(): string {
|
||||
return self::ID;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return ShapeDescriptor[]
|
||||
* @since 30.0.0
|
||||
*/
|
||||
public function getInputShape(): array {
|
||||
return [
|
||||
'input' => new ShapeDescriptor(
|
||||
|
|
@ -81,6 +92,10 @@ class TextToTextTopics implements ITaskType {
|
|||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return ShapeDescriptor[]
|
||||
* @since 30.0.0
|
||||
*/
|
||||
public function getOutputShape(): array {
|
||||
return [
|
||||
'output' => new ShapeDescriptor(
|
||||
|
|
|
|||
|
|
@ -13,9 +13,7 @@ use OC\AppFramework\Bootstrap\RegistrationContext;
|
|||
use OC\AppFramework\Bootstrap\ServiceRegistration;
|
||||
use OC\EventDispatcher\EventDispatcher;
|
||||
use OC\TaskProcessing\Db\TaskMapper;
|
||||
use OC\TaskProcessing\Db\Task as DbTask;
|
||||
use OC\TaskProcessing\Manager;
|
||||
use OCP\AppFramework\Db\DoesNotExistException;
|
||||
use OCP\AppFramework\Utility\ITimeFactory;
|
||||
use OCP\BackgroundJob\IJobList;
|
||||
use OCP\EventDispatcher\IEventDispatcher;
|
||||
|
|
@ -43,7 +41,7 @@ use Psr\Log\LoggerInterface;
|
|||
use Test\BackgroundJob\DummyJobList;
|
||||
|
||||
class AudioToImage implements ITaskType {
|
||||
const ID = 'test:audiotoimage';
|
||||
public const ID = 'test:audiotoimage';
|
||||
|
||||
public function getId(): string {
|
||||
return self::ID;
|
||||
|
|
@ -135,7 +133,7 @@ class SuccessfulSyncProvider implements IProvider, ISynchronousProvider {
|
|||
}
|
||||
|
||||
class FailingSyncProvider implements IProvider, ISynchronousProvider {
|
||||
const ERROR_MESSAGE = 'Failure';
|
||||
public const ERROR_MESSAGE = 'Failure';
|
||||
public function getId(): string {
|
||||
return 'test:sync:fail';
|
||||
}
|
||||
|
|
@ -258,7 +256,7 @@ class TaskProcessingTest extends \Test\TestCase {
|
|||
->with('core', 'ai.textprocessing_provider_preferences', '')
|
||||
->willReturn('');
|
||||
|
||||
$this->eventDispatcher = $this->createMock(IEventDispatcher::class);
|
||||
$this->eventDispatcher = $this->createMock(IEventDispatcher::class);
|
||||
|
||||
$this->manager = new Manager(
|
||||
$this->coordinator,
|
||||
|
|
|
|||
Loading…
Reference in a new issue