mirror of https://github.com/nextcloud/server
Since 27.1.0
Signed-off-by: Marcel Klehr <mklehr@gmx.net>
This commit is contained in:
parent
49ea56b306
commit
069962d04f
|
@ -226,7 +226,7 @@ interface IRegistrationContext {
|
|||
*
|
||||
* @param string $providerClass
|
||||
* @psalm-param class-string<ILanguageModelProvider> $providerClass
|
||||
* @since 28.0.0
|
||||
* @since 27.1.0
|
||||
*/
|
||||
public function registerLanguageModelProvider(string $providerClass): void;
|
||||
|
||||
|
|
|
@ -27,13 +27,13 @@ namespace OCP\Common\Exception;
|
|||
/**
|
||||
* This is thrown whenever something was expected to exist but doesn't
|
||||
*
|
||||
* @since 28.0.0
|
||||
* @since 27.1.0
|
||||
*/
|
||||
class NotFoundException extends \Exception {
|
||||
/**
|
||||
* Constructor
|
||||
* @param string $msg the error message
|
||||
* @since 28.0.0
|
||||
* @since 27.1.0
|
||||
*/
|
||||
public function __construct(string $msg) {
|
||||
parent::__construct($msg);
|
||||
|
|
|
@ -46,7 +46,7 @@ abstract class AbstractLanguageModelTask implements ILanguageModelTask {
|
|||
* @param string $appId
|
||||
* @param string|null $userId
|
||||
* @param string $identifier An arbitrary identifier for this task. max length: 255 chars
|
||||
* @since 28.0.0
|
||||
* @since 27.1.0
|
||||
*/
|
||||
final public function __construct(
|
||||
protected string $input,
|
||||
|
@ -58,13 +58,13 @@ abstract class AbstractLanguageModelTask implements ILanguageModelTask {
|
|||
|
||||
/**
|
||||
* @return string
|
||||
* @since 28.0.0
|
||||
* @since 27.1.0
|
||||
*/
|
||||
abstract public function getType(): string;
|
||||
|
||||
/**
|
||||
* @return string|null
|
||||
* @since 28.0.0
|
||||
* @since 27.1.0
|
||||
*/
|
||||
final public function getOutput(): ?string {
|
||||
return $this->output;
|
||||
|
@ -72,7 +72,7 @@ abstract class AbstractLanguageModelTask implements ILanguageModelTask {
|
|||
|
||||
/**
|
||||
* @param string|null $output
|
||||
* @since 28.0.0
|
||||
* @since 27.1.0
|
||||
*/
|
||||
final public function setOutput(?string $output): void {
|
||||
$this->output = $output;
|
||||
|
@ -80,7 +80,7 @@ abstract class AbstractLanguageModelTask implements ILanguageModelTask {
|
|||
|
||||
/**
|
||||
* @psalm-return ILanguageModelTask::STATUS_*
|
||||
* @since 28.0.0
|
||||
* @since 27.1.0
|
||||
*/
|
||||
final public function getStatus(): int {
|
||||
return $this->status;
|
||||
|
@ -88,7 +88,7 @@ abstract class AbstractLanguageModelTask implements ILanguageModelTask {
|
|||
|
||||
/**
|
||||
* @psalm-param ILanguageModelTask::STATUS_* $status
|
||||
* @since 28.0.0
|
||||
* @since 27.1.0
|
||||
*/
|
||||
final public function setStatus(int $status): void {
|
||||
$this->status = $status;
|
||||
|
@ -96,7 +96,7 @@ abstract class AbstractLanguageModelTask implements ILanguageModelTask {
|
|||
|
||||
/**
|
||||
* @return int|null
|
||||
* @since 28.0.0
|
||||
* @since 27.1.0
|
||||
*/
|
||||
final public function getId(): ?int {
|
||||
return $this->id;
|
||||
|
@ -104,7 +104,7 @@ abstract class AbstractLanguageModelTask implements ILanguageModelTask {
|
|||
|
||||
/**
|
||||
* @param int|null $id
|
||||
* @since 28.0.0
|
||||
* @since 27.1.0
|
||||
*/
|
||||
final public function setId(?int $id): void {
|
||||
$this->id = $id;
|
||||
|
@ -112,7 +112,7 @@ abstract class AbstractLanguageModelTask implements ILanguageModelTask {
|
|||
|
||||
/**
|
||||
* @return string
|
||||
* @since 28.0.0
|
||||
* @since 27.1.0
|
||||
*/
|
||||
final public function getInput(): string {
|
||||
return $this->input;
|
||||
|
@ -120,7 +120,7 @@ abstract class AbstractLanguageModelTask implements ILanguageModelTask {
|
|||
|
||||
/**
|
||||
* @return string
|
||||
* @since 28.0.0
|
||||
* @since 27.1.0
|
||||
*/
|
||||
final public function getAppId(): string {
|
||||
return $this->appId;
|
||||
|
@ -128,7 +128,7 @@ abstract class AbstractLanguageModelTask implements ILanguageModelTask {
|
|||
|
||||
/**
|
||||
* @return string
|
||||
* @since 28.0.0
|
||||
* @since 27.1.0
|
||||
*/
|
||||
final public function getIdentifier(): string {
|
||||
return $this->identifier;
|
||||
|
@ -136,7 +136,7 @@ abstract class AbstractLanguageModelTask implements ILanguageModelTask {
|
|||
|
||||
/**
|
||||
* @return string|null
|
||||
* @since 28.0.0
|
||||
* @since 27.1.0
|
||||
*/
|
||||
final public function getUserId(): ?string {
|
||||
return $this->userId;
|
||||
|
@ -144,7 +144,7 @@ abstract class AbstractLanguageModelTask implements ILanguageModelTask {
|
|||
|
||||
/**
|
||||
* @return array
|
||||
* @since 28.0.0
|
||||
* @since 27.1.0
|
||||
*/
|
||||
public function jsonSerialize() {
|
||||
return [
|
||||
|
@ -167,7 +167,7 @@ abstract class AbstractLanguageModelTask implements ILanguageModelTask {
|
|||
* @param string $identifier
|
||||
* @return ILanguageModelTask
|
||||
* @throws \InvalidArgumentException
|
||||
* @since 28.0.0
|
||||
* @since 27.1.0
|
||||
*/
|
||||
final public static function factory(string $type, string $input, ?string $userId, string $appId, string $identifier = ''): ILanguageModelTask {
|
||||
if (!in_array($type, array_keys(self::TYPES))) {
|
||||
|
|
|
@ -29,11 +29,11 @@ use OCP\EventDispatcher\Event;
|
|||
use OCP\LanguageModel\ILanguageModelTask;
|
||||
|
||||
/**
|
||||
* @since 28.0.0
|
||||
* @since 27.1.0
|
||||
*/
|
||||
abstract class AbstractLanguageModelEvent extends Event {
|
||||
/**
|
||||
* @since 28.0.0
|
||||
* @since 27.1.0
|
||||
*/
|
||||
public function __construct(
|
||||
private ILanguageModelTask $task
|
||||
|
@ -43,7 +43,7 @@ abstract class AbstractLanguageModelEvent extends Event {
|
|||
|
||||
/**
|
||||
* @return ILanguageModelTask
|
||||
* @since 28.0.0
|
||||
* @since 27.1.0
|
||||
*/
|
||||
public function getTask(): ILanguageModelTask {
|
||||
return $this->task;
|
||||
|
|
|
@ -5,13 +5,13 @@ namespace OCP\LanguageModel\Events;
|
|||
use OCP\LanguageModel\ILanguageModelTask;
|
||||
|
||||
/**
|
||||
* @since 28.0.0
|
||||
* @since 27.1.0
|
||||
*/
|
||||
class TaskFailedEvent extends AbstractLanguageModelEvent {
|
||||
/**
|
||||
* @param ILanguageModelTask $task
|
||||
* @param string $errorMessage
|
||||
* @since 28.0.0
|
||||
* @since 27.1.0
|
||||
*/
|
||||
public function __construct(
|
||||
ILanguageModelTask $task,
|
||||
|
@ -22,7 +22,7 @@ class TaskFailedEvent extends AbstractLanguageModelEvent {
|
|||
|
||||
/**
|
||||
* @return string
|
||||
* @since 28.0.0
|
||||
* @since 27.1.0
|
||||
*/
|
||||
public function getErrorMessage(): string {
|
||||
return $this->errorMessage;
|
||||
|
|
|
@ -5,12 +5,12 @@ namespace OCP\LanguageModel\Events;
|
|||
use OCP\LanguageModel\ILanguageModelTask;
|
||||
|
||||
/**
|
||||
* @since 28.0.0
|
||||
* @since 27.1.0
|
||||
*/
|
||||
class TaskSuccessfulEvent extends AbstractLanguageModelEvent {
|
||||
/**
|
||||
* @param ILanguageModelTask $task
|
||||
* @since 28.0.0
|
||||
* @since 27.1.0
|
||||
*/
|
||||
public function __construct(ILanguageModelTask $task) {
|
||||
parent::__construct($task);
|
||||
|
|
|
@ -26,18 +26,18 @@ declare(strict_types=1);
|
|||
namespace OCP\LanguageModel;
|
||||
|
||||
/**
|
||||
* @since 28.0.0
|
||||
* @since 27.1.0
|
||||
* @template-extends AbstractLanguageModelTask<ILanguageModelProvider>
|
||||
*/
|
||||
final class FreePromptTask extends AbstractLanguageModelTask {
|
||||
/**
|
||||
* @since 28.0.0
|
||||
* @since 27.1.0
|
||||
*/
|
||||
public const TYPE = 'free_prompt';
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
* @since 28.0.0
|
||||
* @since 27.1.0
|
||||
*/
|
||||
public function visitProvider(ILanguageModelProvider $provider): string {
|
||||
return $provider->prompt($this->getInput());
|
||||
|
@ -45,7 +45,7 @@ final class FreePromptTask extends AbstractLanguageModelTask {
|
|||
|
||||
/**
|
||||
* @inheritDoc
|
||||
* @since 28.0.0
|
||||
* @since 27.1.0
|
||||
*/
|
||||
public function canUseProvider(ILanguageModelProvider $provider): bool {
|
||||
return true;
|
||||
|
@ -53,7 +53,7 @@ final class FreePromptTask extends AbstractLanguageModelTask {
|
|||
|
||||
/**
|
||||
* @inheritDoc
|
||||
* @since 28.0.0
|
||||
* @since 27.1.0
|
||||
*/
|
||||
public function getType(): string {
|
||||
return self::TYPE;
|
||||
|
|
|
@ -28,18 +28,18 @@ namespace OCP\LanguageModel;
|
|||
/**
|
||||
* This LanguageModel Task represents headline generation
|
||||
* which generates a headline for the passed text
|
||||
* @since 28.0.0
|
||||
* @since 27.1.0
|
||||
* @template-extends AbstractLanguageModelTask<IHeadlineProvider>
|
||||
*/
|
||||
final class HeadlineTask extends AbstractLanguageModelTask {
|
||||
/**
|
||||
* @since 28.0.0
|
||||
* @since 27.1.0
|
||||
*/
|
||||
public const TYPE = 'headline';
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
* @since 28.0.0
|
||||
* @since 27.1.0
|
||||
*/
|
||||
public function visitProvider(ILanguageModelProvider $provider): string {
|
||||
if (!$this->canUseProvider($provider)) {
|
||||
|
@ -50,7 +50,7 @@ final class HeadlineTask extends AbstractLanguageModelTask {
|
|||
|
||||
/**
|
||||
* @inheritDoc
|
||||
* @since 28.0.0
|
||||
* @since 27.1.0
|
||||
*/
|
||||
public function canUseProvider(ILanguageModelProvider $provider): bool {
|
||||
return $provider instanceof IHeadlineProvider;
|
||||
|
@ -58,7 +58,7 @@ final class HeadlineTask extends AbstractLanguageModelTask {
|
|||
|
||||
/**
|
||||
* @inheritDoc
|
||||
* @since 28.0.0
|
||||
* @since 27.1.0
|
||||
*/
|
||||
public function getType(): string {
|
||||
return self::TYPE;
|
||||
|
|
|
@ -31,13 +31,13 @@ use RuntimeException;
|
|||
/**
|
||||
* This LanguageModel Provider represents headline generation
|
||||
* which generates a headline for the passed text
|
||||
* @since 28.0.0
|
||||
* @since 27.1.0
|
||||
*/
|
||||
interface IHeadlineProvider extends ILanguageModelProvider {
|
||||
/**
|
||||
* @param string $text The text to find headline for
|
||||
* @returns string the headline
|
||||
* @since 28.0.0
|
||||
* @since 27.1.0
|
||||
* @throws RuntimeException If the text could not be transcribed
|
||||
*/
|
||||
public function findHeadline(string $text): string;
|
||||
|
|
|
@ -33,30 +33,30 @@ use RuntimeException;
|
|||
/**
|
||||
* API surface for apps interacting with and making use of LanguageModel providers
|
||||
* without known which providers are installed
|
||||
* @since 28.0.0
|
||||
* @since 27.1.0
|
||||
*/
|
||||
interface ILanguageModelManager {
|
||||
/**
|
||||
* @since 28.0.0
|
||||
* @since 27.1.0
|
||||
*/
|
||||
public function hasProviders(): bool;
|
||||
|
||||
/**
|
||||
* @return string[]
|
||||
* @since 28.0.0
|
||||
* @since 27.1.0
|
||||
*/
|
||||
public function getAvailableTaskClasses(): array;
|
||||
|
||||
/**
|
||||
* @return string[]
|
||||
* @since 28.0.0
|
||||
* @since 27.1.0
|
||||
*/
|
||||
public function getAvailableTaskTypes(): array;
|
||||
|
||||
/**
|
||||
* @throws PreConditionNotMetException If no or not the requested provider was registered but this method was still called
|
||||
* @throws RuntimeException If something else failed
|
||||
* @since 28.0.0
|
||||
* @since 27.1.0
|
||||
*/
|
||||
public function runTask(ILanguageModelTask $task): string;
|
||||
|
||||
|
@ -66,7 +66,7 @@ interface ILanguageModelManager {
|
|||
* If inference fails a \OCP\LanguageModel\Events\TaskFailedEvent will be dispatched instead
|
||||
*
|
||||
* @throws PreConditionNotMetException If no or not the requested provider was registered but this method was still called
|
||||
* @since 28.0.0
|
||||
* @since 27.1.0
|
||||
*/
|
||||
public function scheduleTask(ILanguageModelTask $task) : void;
|
||||
|
||||
|
@ -75,7 +75,7 @@ interface ILanguageModelManager {
|
|||
* @return ILanguageModelTask
|
||||
* @throws RuntimeException If the query failed
|
||||
* @throws NotFoundException If the task could not be found
|
||||
* @since 28.0.0
|
||||
* @since 27.1.0
|
||||
*/
|
||||
public function getTask(int $id): ILanguageModelTask;
|
||||
}
|
||||
|
|
|
@ -31,18 +31,18 @@ use RuntimeException;
|
|||
/**
|
||||
* This is the minimum interface that is implemented by apps that
|
||||
* implement a LanguageModel provider
|
||||
* @since 28.0.0
|
||||
* @since 27.1.0
|
||||
*/
|
||||
interface ILanguageModelProvider {
|
||||
/**
|
||||
* @since 28.0.0
|
||||
* @since 27.1.0
|
||||
*/
|
||||
public function getName(): string;
|
||||
|
||||
/**
|
||||
* @param string $prompt The prompt to call the model with
|
||||
* @return string the output
|
||||
* @since 28.0.0
|
||||
* @since 27.1.0
|
||||
* @throws RuntimeException If the text could not be transcribed
|
||||
*/
|
||||
public function prompt(string $prompt): string;
|
||||
|
|
|
@ -26,33 +26,33 @@ declare(strict_types=1);
|
|||
namespace OCP\LanguageModel;
|
||||
|
||||
/**
|
||||
* @since 28.0.0
|
||||
* @since 27.1.0
|
||||
* @template T of ILanguageModelProvider
|
||||
*/
|
||||
interface ILanguageModelTask extends \JsonSerializable {
|
||||
/**
|
||||
* @since 28.0.0
|
||||
* @since 27.1.0
|
||||
*/
|
||||
public const STATUS_FAILED = 4;
|
||||
/**
|
||||
* @since 28.0.0
|
||||
* @since 27.1.0
|
||||
*/
|
||||
public const STATUS_SUCCESSFUL = 3;
|
||||
/**
|
||||
* @since 28.0.0
|
||||
* @since 27.1.0
|
||||
*/
|
||||
public const STATUS_RUNNING = 2;
|
||||
/**
|
||||
* @since 28.0.0
|
||||
* @since 27.1.0
|
||||
*/
|
||||
public const STATUS_SCHEDULED = 1;
|
||||
/**
|
||||
* @since 28.0.0
|
||||
* @since 27.1.0
|
||||
*/
|
||||
public const STATUS_UNKNOWN = 0;
|
||||
|
||||
/**
|
||||
* @since 28.0.0
|
||||
* @since 27.1.0
|
||||
*/
|
||||
public const TYPES = [
|
||||
FreePromptTask::TYPE => FreePromptTask::class,
|
||||
|
@ -65,7 +65,7 @@ interface ILanguageModelTask extends \JsonSerializable {
|
|||
* @psalm-param T $provider
|
||||
* @param ILanguageModelProvider $provider
|
||||
* @return string
|
||||
* @since 28.0.0
|
||||
* @since 27.1.0
|
||||
*/
|
||||
public function visitProvider(ILanguageModelProvider $provider): string;
|
||||
|
||||
|
@ -73,74 +73,74 @@ interface ILanguageModelTask extends \JsonSerializable {
|
|||
* @psalm-param T $provider
|
||||
* @param ILanguageModelProvider $provider
|
||||
* @return bool
|
||||
* @since 28.0.0
|
||||
* @since 27.1.0
|
||||
*/
|
||||
public function canUseProvider(ILanguageModelProvider $provider): bool;
|
||||
|
||||
|
||||
/**
|
||||
* @return string
|
||||
* @since 28.0.0
|
||||
* @since 27.1.0
|
||||
*/
|
||||
public function getType(): string;
|
||||
|
||||
/**
|
||||
* @return ILanguageModelTask::STATUS_*
|
||||
* @since 28.0.0
|
||||
* @since 27.1.0
|
||||
*/
|
||||
public function getStatus(): int;
|
||||
|
||||
/**
|
||||
* @param ILanguageModelTask::STATUS_* $status
|
||||
* @since 28.0.0
|
||||
* @since 27.1.0
|
||||
*/
|
||||
public function setStatus(int $status): void;
|
||||
|
||||
/**
|
||||
* @param int|null $id
|
||||
* @since 28.0.0
|
||||
* @since 27.1.0
|
||||
*/
|
||||
public function setId(?int $id): void;
|
||||
|
||||
/**
|
||||
* @return int|null
|
||||
* @since 28.0.0
|
||||
* @since 27.1.0
|
||||
*/
|
||||
public function getId(): ?int;
|
||||
|
||||
/**
|
||||
* @return string
|
||||
* @since 28.0.0
|
||||
* @since 27.1.0
|
||||
*/
|
||||
public function getInput(): string;
|
||||
|
||||
/**
|
||||
* @param string|null $output
|
||||
* @since 28.0.0
|
||||
* @since 27.1.0
|
||||
*/
|
||||
public function setOutput(?string $output): void;
|
||||
|
||||
/**
|
||||
* @return null|string
|
||||
* @since 28.0.0
|
||||
* @since 27.1.0
|
||||
*/
|
||||
public function getOutput(): ?string;
|
||||
|
||||
/**
|
||||
* @return string
|
||||
* @since 28.0.0
|
||||
* @since 27.1.0
|
||||
*/
|
||||
public function getAppId(): string;
|
||||
|
||||
/**
|
||||
* @return string
|
||||
* @since 28.0.0
|
||||
* @since 27.1.0
|
||||
*/
|
||||
public function getIdentifier(): string;
|
||||
|
||||
/**
|
||||
* @return string|null
|
||||
* @since 28.0.0
|
||||
* @since 27.1.0
|
||||
*/
|
||||
public function getUserId(): ?string;
|
||||
}
|
||||
|
|
|
@ -31,13 +31,13 @@ use RuntimeException;
|
|||
/**
|
||||
* This LanguageModel Provider implements summarization
|
||||
* which sums up the passed text.
|
||||
* @since 28.0.0
|
||||
* @since 27.1.0
|
||||
*/
|
||||
interface ISummaryProvider extends ILanguageModelProvider {
|
||||
/**
|
||||
* @param string $text The text to summarize
|
||||
* @returns string the summary
|
||||
* @since 28.0.0
|
||||
* @since 27.1.0
|
||||
* @throws RuntimeException If the text could not be transcribed
|
||||
*/
|
||||
public function summarize(string $text): string;
|
||||
|
|
|
@ -31,13 +31,13 @@ use RuntimeException;
|
|||
/**
|
||||
* This LanguageModel Provider implements topics synthesis
|
||||
* which outputs comma-separated topics for the passed text
|
||||
* @since 28.0.0
|
||||
* @since 27.1.0
|
||||
*/
|
||||
interface ITopicsProvider extends ILanguageModelProvider {
|
||||
/**
|
||||
* @param string $text The text to find topics for
|
||||
* @returns string the topics, comma separated
|
||||
* @since 28.0.0
|
||||
* @since 27.1.0
|
||||
* @throws RuntimeException If the text could not be transcribed
|
||||
*/
|
||||
public function findTopics(string $text): string;
|
||||
|
|
|
@ -28,18 +28,18 @@ namespace OCP\LanguageModel;
|
|||
/**
|
||||
* This is an absctract LanguageModel Task represents summarization
|
||||
* which sums up the passed text.
|
||||
* @since 28.0.0
|
||||
* @since 27.1.0
|
||||
* @template-extends AbstractLanguageModelTask<ISummaryProvider>
|
||||
*/
|
||||
final class SummaryTask extends AbstractLanguageModelTask {
|
||||
/**
|
||||
* @since 28.0.0
|
||||
* @since 27.1.0
|
||||
*/
|
||||
public const TYPE = 'summarize';
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
* @since 28.0.0
|
||||
* @since 27.1.0
|
||||
*/
|
||||
public function visitProvider(ILanguageModelProvider $provider): string {
|
||||
if (!$this->canUseProvider($provider)) {
|
||||
|
@ -50,7 +50,7 @@ final class SummaryTask extends AbstractLanguageModelTask {
|
|||
|
||||
/**
|
||||
* @inheritDoc
|
||||
* @since 28.0.0
|
||||
* @since 27.1.0
|
||||
*/
|
||||
public function canUseProvider(ILanguageModelProvider $provider): bool {
|
||||
return $provider instanceof ISummaryProvider;
|
||||
|
@ -58,7 +58,7 @@ final class SummaryTask extends AbstractLanguageModelTask {
|
|||
|
||||
/**
|
||||
* @inheritDoc
|
||||
* @since 28.0.0
|
||||
* @since 27.1.0
|
||||
*/
|
||||
public function getType(): string {
|
||||
return self::TYPE;
|
||||
|
|
|
@ -28,18 +28,18 @@ namespace OCP\LanguageModel;
|
|||
/**
|
||||
* This LanguageModel Task represents topics synthesis
|
||||
* which outputs comma-separated topics for the passed text
|
||||
* @since 28.0.0
|
||||
* @since 27.1.0
|
||||
* @template-extends AbstractLanguageModelTask<ITopicsProvider>
|
||||
*/
|
||||
final class TopicsTask extends AbstractLanguageModelTask {
|
||||
/**
|
||||
* @since 28.0.0
|
||||
* @since 27.1.0
|
||||
*/
|
||||
public const TYPE = 'topics';
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
* @since 28.0.0
|
||||
* @since 27.1.0
|
||||
*/
|
||||
public function visitProvider(ILanguageModelProvider $provider): string {
|
||||
if (!$this->canUseProvider($provider)) {
|
||||
|
@ -50,7 +50,7 @@ final class TopicsTask extends AbstractLanguageModelTask {
|
|||
|
||||
/**
|
||||
* @inheritDoc
|
||||
* @since 28.0.0
|
||||
* @since 27.1.0
|
||||
*/
|
||||
public function canUseProvider(ILanguageModelProvider $provider): bool {
|
||||
return $provider instanceof ITopicsProvider;
|
||||
|
@ -58,7 +58,7 @@ final class TopicsTask extends AbstractLanguageModelTask {
|
|||
|
||||
/**
|
||||
* @inheritDoc
|
||||
* @since 28.0.0
|
||||
* @since 27.1.0
|
||||
*/
|
||||
public function getType(): string {
|
||||
return self::TYPE;
|
||||
|
|
Loading…
Reference in New Issue