aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lib/private/TaskProcessing/Manager.php126
-rw-r--r--lib/public/Files/SimpleFS/ISimpleFile.php8
-rw-r--r--lib/public/TaskProcessing/EShapeType.php5
-rw-r--r--lib/public/TaskProcessing/Exception/NotFoundException.php3
-rw-r--r--lib/public/TaskProcessing/Exception/ValidationException.php3
-rw-r--r--lib/public/TaskProcessing/IManager.php4
-rw-r--r--lib/public/TaskProcessing/IProvider.php7
-rw-r--r--lib/public/TaskProcessing/ITaskType.php4
-rw-r--r--lib/public/TaskProcessing/ShapeDescriptor.php22
-rw-r--r--lib/public/TaskProcessing/Task.php8
-rw-r--r--lib/public/TaskProcessing/TaskTypes/AudioToText.php17
-rw-r--r--lib/public/TaskProcessing/TaskTypes/TextToImage.php17
-rw-r--r--lib/public/TaskProcessing/TaskTypes/TextToText.php17
-rw-r--r--lib/public/TaskProcessing/TaskTypes/TextToTextHeadline.php17
-rw-r--r--lib/public/TaskProcessing/TaskTypes/TextToTextSummary.php17
-rw-r--r--lib/public/TaskProcessing/TaskTypes/TextToTextTopics.php17
-rw-r--r--tests/lib/TaskProcessing/TaskProcessingTest.php8
17 files changed, 204 insertions, 96 deletions
diff --git a/lib/private/TaskProcessing/Manager.php b/lib/private/TaskProcessing/Manager.php
index 08cf9679087..9ea92691f2a 100644
--- a/lib/private/TaskProcessing/Manager.php
+++ b/lib/private/TaskProcessing/Manager.php
@@ -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;
}
}
diff --git a/lib/public/Files/SimpleFS/ISimpleFile.php b/lib/public/Files/SimpleFS/ISimpleFile.php
index cf848d33724..8afc3108836 100644
--- a/lib/public/Files/SimpleFS/ISimpleFile.php
+++ b/lib/public/Files/SimpleFS/ISimpleFile.php
@@ -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;
}
diff --git a/lib/public/TaskProcessing/EShapeType.php b/lib/public/TaskProcessing/EShapeType.php
index 514451da068..3da7391daa1 100644
--- a/lib/public/TaskProcessing/EShapeType.php
+++ b/lib/public/TaskProcessing/EShapeType.php
@@ -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;
}
-
diff --git a/lib/public/TaskProcessing/Exception/NotFoundException.php b/lib/public/TaskProcessing/Exception/NotFoundException.php
index ef3eee9009c..9c8636051ea 100644
--- a/lib/public/TaskProcessing/Exception/NotFoundException.php
+++ b/lib/public/TaskProcessing/Exception/NotFoundException.php
@@ -2,6 +2,9 @@
namespace OCP\TaskProcessing\Exception;
+/**
+ * @since 30.0.0
+ */
class NotFoundException extends Exception {
}
diff --git a/lib/public/TaskProcessing/Exception/ValidationException.php b/lib/public/TaskProcessing/Exception/ValidationException.php
index 82de81226b4..b17da89919d 100644
--- a/lib/public/TaskProcessing/Exception/ValidationException.php
+++ b/lib/public/TaskProcessing/Exception/ValidationException.php
@@ -2,6 +2,9 @@
namespace OCP\TaskProcessing\Exception;
+/**
+ * @since 30.0.0
+ */
class ValidationException extends Exception {
}
diff --git a/lib/public/TaskProcessing/IManager.php b/lib/public/TaskProcessing/IManager.php
index 73e4c85701e..11b969ec379 100644
--- a/lib/public/TaskProcessing/IManager.php
+++ b/lib/public/TaskProcessing/IManager.php
@@ -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;
}
diff --git a/lib/public/TaskProcessing/IProvider.php b/lib/public/TaskProcessing/IProvider.php
index be6aa33d125..5768294fd96 100644
--- a/lib/public/TaskProcessing/IProvider.php
+++ b/lib/public/TaskProcessing/IProvider.php
@@ -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;
}
diff --git a/lib/public/TaskProcessing/ITaskType.php b/lib/public/TaskProcessing/ITaskType.php
index bdac1ec397e..a1c6f002433 100644
--- a/lib/public/TaskProcessing/ITaskType.php
+++ b/lib/public/TaskProcessing/ITaskType.php
@@ -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;
}
diff --git a/lib/public/TaskProcessing/ShapeDescriptor.php b/lib/public/TaskProcessing/ShapeDescriptor.php
index 0c770b7d07e..58d4b5d8e7f 100644
--- a/lib/public/TaskProcessing/ShapeDescriptor.php
+++ b/lib/public/TaskProcessing/ShapeDescriptor.php
@@ -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;
}
diff --git a/lib/public/TaskProcessing/Task.php b/lib/public/TaskProcessing/Task.php
index a467c0d57d0..71b5dae84ca 100644
--- a/lib/public/TaskProcessing/Task.php
+++ b/lib/public/TaskProcessing/Task.php
@@ -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 {
diff --git a/lib/public/TaskProcessing/TaskTypes/AudioToText.php b/lib/public/TaskProcessing/TaskTypes/AudioToText.php
index c074c154341..604b99729a4 100644
--- a/lib/public/TaskProcessing/TaskTypes/AudioToText.php
+++ b/lib/public/TaskProcessing/TaskTypes/AudioToText.php
@@ -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(
diff --git a/lib/public/TaskProcessing/TaskTypes/TextToImage.php b/lib/public/TaskProcessing/TaskTypes/TextToImage.php
index 264238afee5..0b52524b7d3 100644
--- a/lib/public/TaskProcessing/TaskTypes/TextToImage.php
+++ b/lib/public/TaskProcessing/TaskTypes/TextToImage.php
@@ -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(
diff --git a/lib/public/TaskProcessing/TaskTypes/TextToText.php b/lib/public/TaskProcessing/TaskTypes/TextToText.php
index 436c47aa8ee..76cc5d2781d 100644
--- a/lib/public/TaskProcessing/TaskTypes/TextToText.php
+++ b/lib/public/TaskProcessing/TaskTypes/TextToText.php
@@ -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(
diff --git a/lib/public/TaskProcessing/TaskTypes/TextToTextHeadline.php b/lib/public/TaskProcessing/TaskTypes/TextToTextHeadline.php
index e524c83fe55..219f6272cc9 100644
--- a/lib/public/TaskProcessing/TaskTypes/TextToTextHeadline.php
+++ b/lib/public/TaskProcessing/TaskTypes/TextToTextHeadline.php
@@ -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(
diff --git a/lib/public/TaskProcessing/TaskTypes/TextToTextSummary.php b/lib/public/TaskProcessing/TaskTypes/TextToTextSummary.php
index 4db13b24a24..7564ed7cd0b 100644
--- a/lib/public/TaskProcessing/TaskTypes/TextToTextSummary.php
+++ b/lib/public/TaskProcessing/TaskTypes/TextToTextSummary.php
@@ -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(
diff --git a/lib/public/TaskProcessing/TaskTypes/TextToTextTopics.php b/lib/public/TaskProcessing/TaskTypes/TextToTextTopics.php
index f2f0c5c1b7d..b0376968c24 100644
--- a/lib/public/TaskProcessing/TaskTypes/TextToTextTopics.php
+++ b/lib/public/TaskProcessing/TaskTypes/TextToTextTopics.php
@@ -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(
diff --git a/tests/lib/TaskProcessing/TaskProcessingTest.php b/tests/lib/TaskProcessing/TaskProcessingTest.php
index 65ee5382883..01bb0253853 100644
--- a/tests/lib/TaskProcessing/TaskProcessingTest.php
+++ b/tests/lib/TaskProcessing/TaskProcessingTest.php
@@ -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,