File manager - Edit - /home/bdwebsol/public_html/demo.bdwebsolution.com/DTO.zip
Back
PK !��\��ͷ�4 �4 File.phpnu ȯ�� <?php declare (strict_types=1); namespace WordPress\AiClient\Files\DTO; use WordPress\AiClient\Common\AbstractDataTransferObject; use WordPress\AiClient\Common\Exception\InvalidArgumentException; use WordPress\AiClient\Common\Exception\RuntimeException; use WordPress\AiClient\Files\Enums\FileTypeEnum; use WordPress\AiClient\Files\ValueObjects\MimeType; /** * Represents a file in the AI client. * * This DTO automatically detects whether a file is a URL, base64 data, or local file path * and handles them appropriately. * * @since 0.1.0 * * @phpstan-type FileArrayShape array{ * fileType: string, * url?: string, * mimeType: string, * base64Data?: string * } * * @extends AbstractDataTransferObject<FileArrayShape> */ class File extends AbstractDataTransferObject { public const KEY_FILE_TYPE = 'fileType'; public const KEY_MIME_TYPE = 'mimeType'; public const KEY_URL = 'url'; public const KEY_BASE64_DATA = 'base64Data'; /** * @var MimeType The MIME type of the file. */ private MimeType $mimeType; /** * @var FileTypeEnum The type of file storage. */ private FileTypeEnum $fileType; /** * @var string|null The URL for remote files. */ private ?string $url = null; /** * @var string|null The base64 data for inline files. */ private ?string $base64Data = null; /** * Constructor. * * @since 0.1.0 * * @param string $file The file string (URL, base64 data, or local path). * @param string|null $mimeType The MIME type of the file (optional). * @throws InvalidArgumentException If the file format is invalid or MIME type cannot be determined. */ public function __construct(string $file, ?string $mimeType = null) { // Detect and process the file type (will set MIME type if possible) $this->detectAndProcessFile($file, $mimeType); } /** * Detects the file type and processes it accordingly. * * @since 0.1.0 * * @param string $file The file string to process. * @param string|null $providedMimeType The explicitly provided MIME type. * @throws InvalidArgumentException If the file format is invalid or MIME type cannot be determined. */ private function detectAndProcessFile(string $file, ?string $providedMimeType): void { // Check if it's a URL if ($this->isUrl($file)) { $this->fileType = FileTypeEnum::remote(); $this->url = $file; $this->mimeType = $this->determineMimeType($providedMimeType, null, $file); return; } // Data URI pattern. $dataUriPattern = '/^data:(?:([a-zA-Z0-9][a-zA-Z0-9!#$&\-\^_+.]*\/[a-zA-Z0-9][a-zA-Z0-9!#$&\-\^_+.]*' . '(?:;[a-zA-Z0-9\-]+=[a-zA-Z0-9\-]+)*)?;)?base64,([A-Za-z0-9+\/]*={0,2})$/'; // Check if it's a data URI. if (preg_match($dataUriPattern, $file, $matches)) { $this->fileType = FileTypeEnum::inline(); $this->base64Data = $matches[2]; // Extract just the base64 data $extractedMimeType = empty($matches[1]) ? null : $matches[1]; $this->mimeType = $this->determineMimeType($providedMimeType, $extractedMimeType, null); return; } // Check if it's a local file path (before base64 check) if (file_exists($file) && is_file($file)) { $this->fileType = FileTypeEnum::inline(); $this->base64Data = $this->convertFileToBase64($file); $this->mimeType = $this->determineMimeType($providedMimeType, null, $file); return; } // Check if it's plain base64 if (preg_match('/^[A-Za-z0-9+\/]*={0,2}$/', $file)) { if ($providedMimeType === null) { throw new InvalidArgumentException('MIME type is required when providing plain base64 data without data URI format.'); } $this->fileType = FileTypeEnum::inline(); $this->base64Data = $file; $this->mimeType = new MimeType($providedMimeType); return; } throw new InvalidArgumentException('Invalid file provided. Expected URL, base64 data, or valid local file path.'); } /** * Checks if a string is a valid URL. * * @since 0.1.0 * * @param string $string The string to check. * @return bool True if the string is a URL. */ private function isUrl(string $string): bool { return filter_var($string, \FILTER_VALIDATE_URL) !== \false && preg_match('/^https?:\/\//i', $string); } /** * Converts a local file to base64. * * @since 0.1.0 * * @param string $filePath The path to the local file. * @return string The base64-encoded file data. * @throws RuntimeException If the file cannot be read. */ private function convertFileToBase64(string $filePath): string { $fileContent = @file_get_contents($filePath); if ($fileContent === \false) { throw new RuntimeException(sprintf('Unable to read file: %s', $filePath)); } return base64_encode($fileContent); } /** * Gets the file type. * * @since 0.1.0 * * @return FileTypeEnum The file type. */ public function getFileType(): FileTypeEnum { return $this->fileType; } /** * Checks if the file is an inline file. * * @since 0.1.0 * * @return bool True if the file is inline (base64/data URI). */ public function isInline(): bool { return $this->fileType->isInline(); } /** * Checks if the file is a remote file. * * @since 0.1.0 * * @return bool True if the file is remote (URL). */ public function isRemote(): bool { return $this->fileType->isRemote(); } /** * Gets the URL for remote files. * * @since 0.1.0 * * @return string|null The URL, or null if not a remote file. */ public function getUrl(): ?string { return $this->url; } /** * Gets the base64-encoded data for inline files. * * @since 0.1.0 * * @return string|null The plain base64-encoded data (without data URI prefix), or null if not an inline file. */ public function getBase64Data(): ?string { return $this->base64Data; } /** * Gets the data as a data URI for inline files. * * @since 0.1.0 * * @return string|null The data URI in format: data:[mimeType];base64,[data], or null if not an inline file. */ public function getDataUri(): ?string { if ($this->base64Data === null) { return null; } return sprintf('data:%s;base64,%s', $this->getMimeType(), $this->base64Data); } /** * Gets the MIME type of the file as a string. * * @since 0.1.0 * * @return string The MIME type string value. */ public function getMimeType(): string { return (string) $this->mimeType; } /** * Gets the MIME type object. * * @since 0.1.0 * * @return MimeType The MIME type object. */ public function getMimeTypeObject(): MimeType { return $this->mimeType; } /** * Checks if the file is a video. * * @since 0.1.0 * * @return bool True if the file is a video. */ public function isVideo(): bool { return $this->mimeType->isVideo(); } /** * Checks if the file is an image. * * @since 0.1.0 * * @return bool True if the file is an image. */ public function isImage(): bool { return $this->mimeType->isImage(); } /** * Checks if the file is audio. * * @since 0.1.0 * * @return bool True if the file is audio. */ public function isAudio(): bool { return $this->mimeType->isAudio(); } /** * Checks if the file is text. * * @since 0.1.0 * * @return bool True if the file is text. */ public function isText(): bool { return $this->mimeType->isText(); } /** * Checks if the file is a document. * * @since 0.1.0 * * @return bool True if the file is a document. */ public function isDocument(): bool { return $this->mimeType->isDocument(); } /** * Checks if the file is a specific MIME type. * * @since 0.1.0 * * @param string $type The mime type to check (e.g. 'image', 'text', 'video', 'audio'). * * @return bool True if the file is of the specified type. */ public function isMimeType(string $type): bool { return $this->mimeType->isType($type); } /** * Determines the MIME type from various sources. * * @since 0.1.0 * * @param string|null $providedMimeType The explicitly provided MIME type. * @param string|null $extractedMimeType The MIME type extracted from data URI. * @param string|null $pathOrUrl The file path or URL to extract extension from. * @return MimeType The determined MIME type. * @throws InvalidArgumentException If MIME type cannot be determined. */ private function determineMimeType(?string $providedMimeType, ?string $extractedMimeType, ?string $pathOrUrl): MimeType { // Prefer explicitly provided MIME type if ($providedMimeType !== null) { return new MimeType($providedMimeType); } // Use extracted MIME type from data URI if ($extractedMimeType !== null) { return new MimeType($extractedMimeType); } // Try to determine from file extension if ($pathOrUrl !== null) { $parsedUrl = parse_url($pathOrUrl); $path = $parsedUrl['path'] ?? $pathOrUrl; // Remove query string and fragment if present $cleanPath = strtok($path, '?#'); if ($cleanPath === \false) { $cleanPath = $path; } $extension = pathinfo($cleanPath, \PATHINFO_EXTENSION); if (!empty($extension)) { try { return MimeType::fromExtension($extension); } catch (InvalidArgumentException $e) { // Extension not recognized, continue to error unset($e); } } } throw new InvalidArgumentException('Unable to determine MIME type. Please provide it explicitly.'); } /** * {@inheritDoc} * * @since 0.1.0 */ public static function getJsonSchema(): array { return ['type' => 'object', 'oneOf' => [['properties' => [self::KEY_FILE_TYPE => ['type' => 'string', 'const' => FileTypeEnum::REMOTE, 'description' => 'The file type.'], self::KEY_MIME_TYPE => ['type' => 'string', 'description' => 'The MIME type of the file.', 'pattern' => '^[a-zA-Z0-9][a-zA-Z0-9!#$&\-\^_+.]*\/[a-zA-Z0-9]' . '[a-zA-Z0-9!#$&\-\^_+.]*$'], self::KEY_URL => ['type' => 'string', 'format' => 'uri', 'description' => 'The URL to the remote file.']], 'required' => [self::KEY_FILE_TYPE, self::KEY_MIME_TYPE, self::KEY_URL]], ['properties' => [self::KEY_FILE_TYPE => ['type' => 'string', 'const' => FileTypeEnum::INLINE, 'description' => 'The file type.'], self::KEY_MIME_TYPE => ['type' => 'string', 'description' => 'The MIME type of the file.', 'pattern' => '^[a-zA-Z0-9][a-zA-Z0-9!#$&\-\^_+.]*\/[a-zA-Z0-9]' . '[a-zA-Z0-9!#$&\-\^_+.]*$'], self::KEY_BASE64_DATA => ['type' => 'string', 'description' => 'The base64-encoded file data.']], 'required' => [self::KEY_FILE_TYPE, self::KEY_MIME_TYPE, self::KEY_BASE64_DATA]]]]; } /** * {@inheritDoc} * * @since 0.1.0 * * @return FileArrayShape */ public function toArray(): array { $data = [self::KEY_FILE_TYPE => $this->fileType->value, self::KEY_MIME_TYPE => $this->getMimeType()]; if ($this->url !== null) { $data[self::KEY_URL] = $this->url; } elseif (!$this->fileType->isRemote() && $this->base64Data !== null) { $data[self::KEY_BASE64_DATA] = $this->base64Data; } else { throw new RuntimeException('File requires either url or base64Data. This should not be a possible condition.'); } return $data; } /** * {@inheritDoc} * * @since 0.1.0 */ public static function fromArray(array $array): self { static::validateFromArrayData($array, [self::KEY_FILE_TYPE]); // Check which properties are set to determine how to construct the File $mimeType = $array[self::KEY_MIME_TYPE] ?? null; if (isset($array[self::KEY_URL])) { return new self($array[self::KEY_URL], $mimeType); } elseif (isset($array[self::KEY_BASE64_DATA])) { return new self($array[self::KEY_BASE64_DATA], $mimeType); } else { throw new InvalidArgumentException('File requires either url or base64Data.'); } } /** * Performs a deep clone of the file. * * This method ensures that the MimeType value object is cloned to prevent * any shared references between the original and cloned file. * * @since 0.4.2 */ public function __clone() { $this->mimeType = clone $this->mimeType; } } PK ��\�]���5 �5 GenerativeAiResult.phpnu ȯ�� <?php declare (strict_types=1); namespace WordPress\AiClient\Results\DTO; use WordPress\AiClient\Common\AbstractDataTransferObject; use WordPress\AiClient\Common\Exception\InvalidArgumentException; use WordPress\AiClient\Common\Exception\RuntimeException; use WordPress\AiClient\Files\DTO\File; use WordPress\AiClient\Messages\DTO\Message; use WordPress\AiClient\Providers\DTO\ProviderMetadata; use WordPress\AiClient\Providers\Models\DTO\ModelMetadata; use WordPress\AiClient\Results\Contracts\ResultInterface; /** * Represents the result of a generative AI operation. * * This DTO contains the generated candidates along with usage statistics * and metadata from the AI provider. * * @since 0.1.0 * * @phpstan-import-type CandidateArrayShape from Candidate * @phpstan-import-type TokenUsageArrayShape from TokenUsage * @phpstan-import-type ProviderMetadataArrayShape from ProviderMetadata * @phpstan-import-type ModelMetadataArrayShape from ModelMetadata * * @phpstan-type GenerativeAiResultArrayShape array{ * id: string, * candidates: array<CandidateArrayShape>, * tokenUsage: TokenUsageArrayShape, * providerMetadata: ProviderMetadataArrayShape, * modelMetadata: ModelMetadataArrayShape, * additionalData?: array<string, mixed> * } * * @extends AbstractDataTransferObject<GenerativeAiResultArrayShape> */ class GenerativeAiResult extends AbstractDataTransferObject implements ResultInterface { public const KEY_ID = 'id'; public const KEY_CANDIDATES = 'candidates'; public const KEY_TOKEN_USAGE = 'tokenUsage'; public const KEY_PROVIDER_METADATA = 'providerMetadata'; public const KEY_MODEL_METADATA = 'modelMetadata'; public const KEY_ADDITIONAL_DATA = 'additionalData'; /** * @var string Unique identifier for this result. */ private string $id; /** * @var Candidate[] The generated candidates. */ private array $candidates; /** * @var TokenUsage Token usage statistics. */ private \WordPress\AiClient\Results\DTO\TokenUsage $tokenUsage; /** * @var ProviderMetadata Provider metadata. */ private ProviderMetadata $providerMetadata; /** * @var ModelMetadata Model metadata. */ private ModelMetadata $modelMetadata; /** * @var array<string, mixed> Additional data. */ private array $additionalData; /** * Constructor. * * @since 0.1.0 * * @param string $id Unique identifier for this result. * @param Candidate[] $candidates The generated candidates. * @param TokenUsage $tokenUsage Token usage statistics. * @param ProviderMetadata $providerMetadata Provider metadata. * @param ModelMetadata $modelMetadata Model metadata. * @param array<string, mixed> $additionalData Additional data. * @throws InvalidArgumentException If no candidates provided. */ public function __construct(string $id, array $candidates, \WordPress\AiClient\Results\DTO\TokenUsage $tokenUsage, ProviderMetadata $providerMetadata, ModelMetadata $modelMetadata, array $additionalData = []) { if (empty($candidates)) { throw new InvalidArgumentException('At least one candidate must be provided'); } $this->id = $id; $this->candidates = $candidates; $this->tokenUsage = $tokenUsage; $this->providerMetadata = $providerMetadata; $this->modelMetadata = $modelMetadata; $this->additionalData = $additionalData; } /** * {@inheritDoc} * * @since 0.1.0 */ public function getId(): string { return $this->id; } /** * Gets the generated candidates. * * @since 0.1.0 * * @return Candidate[] The candidates. */ public function getCandidates(): array { return $this->candidates; } /** * {@inheritDoc} * * @since 0.1.0 */ public function getTokenUsage(): \WordPress\AiClient\Results\DTO\TokenUsage { return $this->tokenUsage; } /** * Gets the provider metadata. * * @since 0.1.0 * * @return ProviderMetadata The provider metadata. */ public function getProviderMetadata(): ProviderMetadata { return $this->providerMetadata; } /** * Gets the model metadata. * * @since 0.1.0 * * @return ModelMetadata The model metadata. */ public function getModelMetadata(): ModelMetadata { return $this->modelMetadata; } /** * {@inheritDoc} * * @since 0.1.0 */ public function getAdditionalData(): array { return $this->additionalData; } /** * Gets the total number of candidates. * * @since 0.1.0 * * @return int The total number of candidates. */ public function getCandidateCount(): int { return count($this->candidates); } /** * Checks if the result has multiple candidates. * * @since 0.1.0 * * @return bool True if there are multiple candidates, false otherwise. */ public function hasMultipleCandidates(): bool { return $this->getCandidateCount() > 1; } /** * Converts the first candidate to text. * * Only text from the content channel is considered. Text within model thought or reasoning is ignored. * * @since 0.1.0 * * @return string The text content. * @throws RuntimeException If no text content. */ public function toText(): string { $message = $this->candidates[0]->getMessage(); foreach ($message->getParts() as $part) { $channel = $part->getChannel(); $text = $part->getText(); if ($channel->isContent() && $text !== null) { return $text; } } throw new RuntimeException('No text content found in first candidate'); } /** * Converts the first candidate to a file. * * Only files from the content channel are considered. Files within model thought or reasoning are ignored. * * @since 0.1.0 * * @return File The file. * @throws RuntimeException If no file content. */ public function toFile(): File { $message = $this->candidates[0]->getMessage(); foreach ($message->getParts() as $part) { $channel = $part->getChannel(); $file = $part->getFile(); if ($channel->isContent() && $file !== null) { return $file; } } throw new RuntimeException('No file content found in first candidate'); } /** * Converts the first candidate to an image file. * * @since 0.1.0 * * @return File The image file. * @throws RuntimeException If no image content. */ public function toImageFile(): File { $file = $this->toFile(); if (!$file->isImage()) { throw new RuntimeException(sprintf('File is not an image. MIME type: %s', $file->getMimeType())); } return $file; } /** * Converts the first candidate to an audio file. * * @since 0.1.0 * * @return File The audio file. * @throws RuntimeException If no audio content. */ public function toAudioFile(): File { $file = $this->toFile(); if (!$file->isAudio()) { throw new RuntimeException(sprintf('File is not an audio file. MIME type: %s', $file->getMimeType())); } return $file; } /** * Converts the first candidate to a video file. * * @since 0.1.0 * * @return File The video file. * @throws RuntimeException If no video content. */ public function toVideoFile(): File { $file = $this->toFile(); if (!$file->isVideo()) { throw new RuntimeException(sprintf('File is not a video file. MIME type: %s', $file->getMimeType())); } return $file; } /** * Converts the first candidate to a message. * * @since 0.1.0 * * @return Message The message. */ public function toMessage(): Message { return $this->candidates[0]->getMessage(); } /** * Converts all candidates to text. * * @since 0.1.0 * * @return list<string> Array of text content. */ public function toTexts(): array { $texts = []; foreach ($this->candidates as $candidate) { $message = $candidate->getMessage(); foreach ($message->getParts() as $part) { $channel = $part->getChannel(); $text = $part->getText(); if ($channel->isContent() && $text !== null) { $texts[] = $text; break; } } } return $texts; } /** * Converts all candidates to files. * * @since 0.1.0 * * @return list<File> Array of files. */ public function toFiles(): array { $files = []; foreach ($this->candidates as $candidate) { $message = $candidate->getMessage(); foreach ($message->getParts() as $part) { $channel = $part->getChannel(); $file = $part->getFile(); if ($channel->isContent() && $file !== null) { $files[] = $file; break; } } } return $files; } /** * Converts all candidates to image files. * * @since 0.1.0 * * @return list<File> Array of image files. */ public function toImageFiles(): array { return array_values(array_filter($this->toFiles(), fn(File $file) => $file->isImage())); } /** * Converts all candidates to audio files. * * @since 0.1.0 * * @return list<File> Array of audio files. */ public function toAudioFiles(): array { return array_values(array_filter($this->toFiles(), fn(File $file) => $file->isAudio())); } /** * Converts all candidates to video files. * * @since 0.1.0 * * @return list<File> Array of video files. */ public function toVideoFiles(): array { return array_values(array_filter($this->toFiles(), fn(File $file) => $file->isVideo())); } /** * Converts all candidates to messages. * * @since 0.1.0 * * @return list<Message> Array of messages. */ public function toMessages(): array { return array_values(array_map(fn(\WordPress\AiClient\Results\DTO\Candidate $candidate) => $candidate->getMessage(), $this->candidates)); } /** * {@inheritDoc} * * @since 0.1.0 */ public static function getJsonSchema(): array { return ['type' => 'object', 'properties' => [self::KEY_ID => ['type' => 'string', 'description' => 'Unique identifier for this result.'], self::KEY_CANDIDATES => ['type' => 'array', 'items' => \WordPress\AiClient\Results\DTO\Candidate::getJsonSchema(), 'minItems' => 1, 'description' => 'The generated candidates.'], self::KEY_TOKEN_USAGE => \WordPress\AiClient\Results\DTO\TokenUsage::getJsonSchema(), self::KEY_PROVIDER_METADATA => ProviderMetadata::getJsonSchema(), self::KEY_MODEL_METADATA => ModelMetadata::getJsonSchema(), self::KEY_ADDITIONAL_DATA => ['type' => 'object', 'additionalProperties' => \true, 'description' => 'Additional data included in the API response.']], 'required' => [self::KEY_ID, self::KEY_CANDIDATES, self::KEY_TOKEN_USAGE, self::KEY_PROVIDER_METADATA, self::KEY_MODEL_METADATA]]; } /** * {@inheritDoc} * * @since 0.1.0 * * @return GenerativeAiResultArrayShape */ public function toArray(): array { return [self::KEY_ID => $this->id, self::KEY_CANDIDATES => array_map(fn(\WordPress\AiClient\Results\DTO\Candidate $candidate) => $candidate->toArray(), $this->candidates), self::KEY_TOKEN_USAGE => $this->tokenUsage->toArray(), self::KEY_PROVIDER_METADATA => $this->providerMetadata->toArray(), self::KEY_MODEL_METADATA => $this->modelMetadata->toArray(), self::KEY_ADDITIONAL_DATA => $this->additionalData]; } /** * {@inheritDoc} * * @since 0.1.0 */ public static function fromArray(array $array): self { static::validateFromArrayData($array, [self::KEY_ID, self::KEY_CANDIDATES, self::KEY_TOKEN_USAGE, self::KEY_PROVIDER_METADATA, self::KEY_MODEL_METADATA]); $candidates = array_map(fn(array $candidateData) => \WordPress\AiClient\Results\DTO\Candidate::fromArray($candidateData), $array[self::KEY_CANDIDATES]); return new self($array[self::KEY_ID], $candidates, \WordPress\AiClient\Results\DTO\TokenUsage::fromArray($array[self::KEY_TOKEN_USAGE]), ProviderMetadata::fromArray($array[self::KEY_PROVIDER_METADATA]), ModelMetadata::fromArray($array[self::KEY_MODEL_METADATA]), $array[self::KEY_ADDITIONAL_DATA] ?? []); } /** * Performs a deep clone of the result. * * This method ensures that all nested objects (candidates, token usage, metadata) * are cloned to prevent modifications to the cloned result from affecting the original. * * @since 0.4.2 */ public function __clone() { $clonedCandidates = []; foreach ($this->candidates as $candidate) { $clonedCandidates[] = clone $candidate; } $this->candidates = $clonedCandidates; $this->tokenUsage = clone $this->tokenUsage; $this->providerMetadata = clone $this->providerMetadata; $this->modelMetadata = clone $this->modelMetadata; } } PK ��\�jL TokenUsage.phpnu ȯ�� <?php declare (strict_types=1); namespace WordPress\AiClient\Results\DTO; use WordPress\AiClient\Common\AbstractDataTransferObject; /** * Represents token usage statistics for an AI operation. * * This DTO tracks the number of tokens used in prompts and completions, * which is important for monitoring usage and costs. * * Note that thought tokens are a subset of completion tokens, not additive. * In other words: completionTokens - thoughtTokens = tokens of actual output content. * * @since 0.1.0 * * @phpstan-type TokenUsageArrayShape array{ * promptTokens: int, * completionTokens: int, * totalTokens: int, * thoughtTokens?: int * } * * @extends AbstractDataTransferObject<TokenUsageArrayShape> */ class TokenUsage extends AbstractDataTransferObject { public const KEY_PROMPT_TOKENS = 'promptTokens'; public const KEY_COMPLETION_TOKENS = 'completionTokens'; public const KEY_TOTAL_TOKENS = 'totalTokens'; public const KEY_THOUGHT_TOKENS = 'thoughtTokens'; /** * @var int Number of tokens in the prompt. */ private int $promptTokens; /** * @var int Number of tokens in the completion, including any thought tokens. */ private int $completionTokens; /** * @var int Total number of tokens used. */ private int $totalTokens; /** * @var int|null Number of tokens used for thinking, as a subset of completion tokens. */ private ?int $thoughtTokens; /** * Constructor. * * @since 0.1.0 * * @param int $promptTokens Number of tokens in the prompt. * @param int $completionTokens Number of tokens in the completion, including any thought tokens. * @param int $totalTokens Total number of tokens used. * @param int|null $thoughtTokens Number of tokens used for thinking, as a subset of completion tokens. */ public function __construct(int $promptTokens, int $completionTokens, int $totalTokens, ?int $thoughtTokens = null) { $this->promptTokens = $promptTokens; $this->completionTokens = $completionTokens; $this->totalTokens = $totalTokens; $this->thoughtTokens = $thoughtTokens; } /** * Gets the number of prompt tokens. * * @since 0.1.0 * * @return int The prompt token count. */ public function getPromptTokens(): int { return $this->promptTokens; } /** * Gets the number of completion tokens, including any thought tokens. * * @since 0.1.0 * * @return int The completion token count. */ public function getCompletionTokens(): int { return $this->completionTokens; } /** * Gets the total number of tokens. * * @since 0.1.0 * * @return int The total token count. */ public function getTotalTokens(): int { return $this->totalTokens; } /** * Gets the number of thought tokens, which is a subset of the completion token count. * * @since 1.3.0 * * @return int|null The thought token count or null if not available. */ public function getThoughtTokens(): ?int { return $this->thoughtTokens; } /** * {@inheritDoc} * * @since 0.1.0 */ public static function getJsonSchema(): array { return ['type' => 'object', 'properties' => [self::KEY_PROMPT_TOKENS => ['type' => 'integer', 'description' => 'Number of tokens in the prompt.'], self::KEY_COMPLETION_TOKENS => ['type' => 'integer', 'description' => 'Number of tokens in the completion, including any thought tokens.'], self::KEY_TOTAL_TOKENS => ['type' => 'integer', 'description' => 'Total number of tokens used.'], self::KEY_THOUGHT_TOKENS => ['type' => 'integer', 'description' => 'Number of tokens used for thinking, as a subset of completion tokens.']], 'required' => [self::KEY_PROMPT_TOKENS, self::KEY_COMPLETION_TOKENS, self::KEY_TOTAL_TOKENS]]; } /** * {@inheritDoc} * * @since 0.1.0 * * @return TokenUsageArrayShape */ public function toArray(): array { $data = [self::KEY_PROMPT_TOKENS => $this->promptTokens, self::KEY_COMPLETION_TOKENS => $this->completionTokens, self::KEY_TOTAL_TOKENS => $this->totalTokens]; if ($this->thoughtTokens !== null) { $data[self::KEY_THOUGHT_TOKENS] = $this->thoughtTokens; } return $data; } /** * {@inheritDoc} * * @since 0.1.0 */ public static function fromArray(array $array): self { static::validateFromArrayData($array, [self::KEY_PROMPT_TOKENS, self::KEY_COMPLETION_TOKENS, self::KEY_TOTAL_TOKENS]); return new self($array[self::KEY_PROMPT_TOKENS], $array[self::KEY_COMPLETION_TOKENS], $array[self::KEY_TOTAL_TOKENS], $array[self::KEY_THOUGHT_TOKENS] ?? null); } } PK ��\��y� � Candidate.phpnu ȯ�� <?php declare (strict_types=1); namespace WordPress\AiClient\Results\DTO; use WordPress\AiClient\Common\AbstractDataTransferObject; use WordPress\AiClient\Common\Exception\InvalidArgumentException; use WordPress\AiClient\Messages\DTO\Message; use WordPress\AiClient\Results\Enums\FinishReasonEnum; /** * Represents a candidate response from an AI model. * * When generating content, AI models can produce multiple candidates. * Each candidate contains a message and metadata about why generation stopped. * * @since 0.1.0 * * @phpstan-import-type MessageArrayShape from Message * * @phpstan-type CandidateArrayShape array{message: MessageArrayShape, finishReason: string} * * @extends AbstractDataTransferObject<CandidateArrayShape> */ class Candidate extends AbstractDataTransferObject { public const KEY_MESSAGE = 'message'; public const KEY_FINISH_REASON = 'finishReason'; /** * @var Message The generated message. */ private Message $message; /** * @var FinishReasonEnum The reason generation stopped. */ private FinishReasonEnum $finishReason; /** * Constructor. * * @since 0.1.0 * * @param Message $message The generated message. * @param FinishReasonEnum $finishReason The reason generation stopped. */ public function __construct(Message $message, FinishReasonEnum $finishReason) { if (!$message->getRole()->isModel()) { throw new InvalidArgumentException('Message must be a model message.'); } $this->message = $message; $this->finishReason = $finishReason; } /** * Gets the generated message. * * @since 0.1.0 * * @return Message The message. */ public function getMessage(): Message { return $this->message; } /** * Gets the finish reason. * * @since 0.1.0 * * @return FinishReasonEnum The finish reason. */ public function getFinishReason(): FinishReasonEnum { return $this->finishReason; } /** * {@inheritDoc} * * @since 0.1.0 */ public static function getJsonSchema(): array { return ['type' => 'object', 'properties' => [self::KEY_MESSAGE => Message::getJsonSchema(), self::KEY_FINISH_REASON => ['type' => 'string', 'enum' => FinishReasonEnum::getValues(), 'description' => 'The reason generation stopped.']], 'required' => [self::KEY_MESSAGE, self::KEY_FINISH_REASON]]; } /** * {@inheritDoc} * * @since 0.1.0 * * @return CandidateArrayShape */ public function toArray(): array { return [self::KEY_MESSAGE => $this->message->toArray(), self::KEY_FINISH_REASON => $this->finishReason->value]; } /** * {@inheritDoc} * * @since 0.1.0 */ public static function fromArray(array $array): self { static::validateFromArrayData($array, [self::KEY_MESSAGE, self::KEY_FINISH_REASON]); $messageData = $array[self::KEY_MESSAGE]; return new self(Message::fromArray($messageData), FinishReasonEnum::from($array[self::KEY_FINISH_REASON])); } /** * Performs a deep clone of the candidate. * * This method ensures that the message object is cloned to prevent * modifications to the cloned candidate from affecting the original. * * @since 0.4.2 */ public function __clone() { $this->message = clone $this->message; } } PK ���\2���d d ProviderModelsMetadata.phpnu ȯ�� <?php declare (strict_types=1); namespace WordPress\AiClient\Providers\DTO; use WordPress\AiClient\Common\AbstractDataTransferObject; use WordPress\AiClient\Common\Exception\InvalidArgumentException; use WordPress\AiClient\Providers\Models\DTO\ModelMetadata; /** * Represents metadata about a provider and its available models. * * This class combines provider information with the models that * the provider offers, facilitating model discovery and selection. * * @since 0.1.0 * * @phpstan-import-type ProviderMetadataArrayShape from ProviderMetadata * @phpstan-import-type ModelMetadataArrayShape from ModelMetadata * * @phpstan-type ProviderModelsMetadataArrayShape array{ * provider: ProviderMetadataArrayShape, * models: list<ModelMetadataArrayShape> * } * * @extends AbstractDataTransferObject<ProviderModelsMetadataArrayShape> */ class ProviderModelsMetadata extends AbstractDataTransferObject { public const KEY_PROVIDER = 'provider'; public const KEY_MODELS = 'models'; /** * @var ProviderMetadata The provider metadata. */ protected \WordPress\AiClient\Providers\DTO\ProviderMetadata $provider; /** * @var list<ModelMetadata> The available models. */ protected array $models; /** * Constructor. * * @since 0.1.0 * * @param ProviderMetadata $provider The provider metadata. * @param list<ModelMetadata> $models The available models. * * @throws InvalidArgumentException If models is not a list. */ public function __construct(\WordPress\AiClient\Providers\DTO\ProviderMetadata $provider, array $models) { if (!array_is_list($models)) { throw new InvalidArgumentException('Models must be a list array.'); } $this->provider = $provider; $this->models = $models; } /** * Creates a deep clone of this metadata. * * Clones the provider metadata and all model metadata objects * to ensure the cloned instance is independent of the original. * * @since 0.4.2 */ public function __clone() { // Clone provider metadata $this->provider = clone $this->provider; // Deep clone models array (ModelMetadata has __clone) $clonedModels = []; foreach ($this->models as $model) { $clonedModels[] = clone $model; } $this->models = $clonedModels; } /** * Gets the provider metadata. * * @since 0.1.0 * * @return ProviderMetadata The provider metadata. */ public function getProvider(): \WordPress\AiClient\Providers\DTO\ProviderMetadata { return $this->provider; } /** * Gets the available models. * * @since 0.1.0 * * @return list<ModelMetadata> The available models. */ public function getModels(): array { return $this->models; } /** * {@inheritDoc} * * @since 0.1.0 */ public static function getJsonSchema(): array { return ['type' => 'object', 'properties' => [self::KEY_PROVIDER => \WordPress\AiClient\Providers\DTO\ProviderMetadata::getJsonSchema(), self::KEY_MODELS => ['type' => 'array', 'items' => ModelMetadata::getJsonSchema(), 'description' => 'The available models for this provider.']], 'required' => [self::KEY_PROVIDER, self::KEY_MODELS]]; } /** * {@inheritDoc} * * @since 0.1.0 * * @return ProviderModelsMetadataArrayShape */ public function toArray(): array { return [self::KEY_PROVIDER => $this->provider->toArray(), self::KEY_MODELS => array_map(static fn(ModelMetadata $model): array => $model->toArray(), $this->models)]; } /** * {@inheritDoc} * * @since 0.1.0 */ public static function fromArray(array $array): self { static::validateFromArrayData($array, [self::KEY_PROVIDER, self::KEY_MODELS]); return new self(\WordPress\AiClient\Providers\DTO\ProviderMetadata::fromArray($array[self::KEY_PROVIDER]), array_map(static fn(array $modelData): ModelMetadata => ModelMetadata::fromArray($modelData), $array[self::KEY_MODELS])); } } PK ���\N��� � ProviderMetadata.phpnu ȯ�� <?php declare (strict_types=1); namespace WordPress\AiClient\Providers\DTO; use WordPress\AiClient\Common\AbstractDataTransferObject; use WordPress\AiClient\Common\Exception\InvalidArgumentException; use WordPress\AiClient\Providers\Enums\ProviderTypeEnum; use WordPress\AiClient\Providers\Http\Enums\RequestAuthenticationMethod; /** * Represents metadata about an AI provider. * * This class contains information about an AI provider, including its * unique identifier, display name, and type (cloud, server, or client). * * @since 0.1.0 * @since 1.2.0 Added optional description property. * @since 1.3.0 Added optional logoPath property. * * @phpstan-type ProviderMetadataArrayShape array{ * id: string, * name: string, * description?: ?string, * type: string, * credentialsUrl?: ?string, * authenticationMethod?: ?string, * logoPath?: ?string * } * * @extends AbstractDataTransferObject<ProviderMetadataArrayShape> */ class ProviderMetadata extends AbstractDataTransferObject { public const KEY_ID = 'id'; public const KEY_NAME = 'name'; public const KEY_DESCRIPTION = 'description'; public const KEY_TYPE = 'type'; public const KEY_CREDENTIALS_URL = 'credentialsUrl'; public const KEY_AUTHENTICATION_METHOD = 'authenticationMethod'; public const KEY_LOGO_PATH = 'logoPath'; /** * @var string The provider's unique identifier. */ protected string $id; /** * @var string The provider's display name. */ protected string $name; /** * @var string|null The provider's description. */ protected ?string $description; /** * @var ProviderTypeEnum The provider type. */ protected ProviderTypeEnum $type; /** * @var string|null The URL where users can get credentials. */ protected ?string $credentialsUrl; /** * @var RequestAuthenticationMethod|null The authentication method. */ protected ?RequestAuthenticationMethod $authenticationMethod; /** * @var string|null The full path to the provider's logo image file. */ protected ?string $logoPath; /** * Constructor. * * @since 0.1.0 * @since 1.2.0 Added optional $description parameter. * @since 1.3.0 Added optional $logoPath parameter. * * @param string $id The provider's unique identifier. * @param string $name The provider's display name. * @param ProviderTypeEnum $type The provider type. * @param string|null $credentialsUrl The URL where users can get credentials. * @param RequestAuthenticationMethod|null $authenticationMethod The authentication method. * @param string|null $description The provider's description. * @param string|null $logoPath The full path to the provider's logo image file. * @throws InvalidArgumentException If the provider ID contains invalid characters. */ public function __construct(string $id, string $name, ProviderTypeEnum $type, ?string $credentialsUrl = null, ?RequestAuthenticationMethod $authenticationMethod = null, ?string $description = null, ?string $logoPath = null) { if (!preg_match('/^[a-z0-9\-_]+$/', $id)) { throw new InvalidArgumentException(sprintf( // phpcs:ignore Generic.Files.LineLength.TooLong 'Invalid provider ID "%s". Only lowercase alphanumeric characters, hyphens, and underscores are allowed.', $id )); } $this->id = $id; $this->name = $name; $this->description = $description; $this->type = $type; $this->credentialsUrl = $credentialsUrl; $this->authenticationMethod = $authenticationMethod; $this->logoPath = $logoPath; } /** * Gets the provider's unique identifier. * * @since 0.1.0 * * @return string The provider ID. */ public function getId(): string { return $this->id; } /** * Gets the provider's display name. * * @since 0.1.0 * * @return string The provider name. */ public function getName(): string { return $this->name; } /** * Gets the provider's description. * * @since 1.2.0 * * @return string|null The provider description. */ public function getDescription(): ?string { return $this->description; } /** * Gets the provider type. * * @since 0.1.0 * * @return ProviderTypeEnum The provider type. */ public function getType(): ProviderTypeEnum { return $this->type; } /** * Gets the credentials URL. * * @since 0.1.0 * * @return string|null The credentials URL. */ public function getCredentialsUrl(): ?string { return $this->credentialsUrl; } /** * Gets the authentication method. * * @since 0.4.0 * * @return RequestAuthenticationMethod|null The authentication method. */ public function getAuthenticationMethod(): ?RequestAuthenticationMethod { return $this->authenticationMethod; } /** * Gets the full path to the provider's logo image file. * * @since 1.3.0 * * @return string|null The full path to the logo image file. */ public function getLogoPath(): ?string { return $this->logoPath; } /** * {@inheritDoc} * * @since 0.1.0 * @since 1.2.0 Added description to schema. * @since 1.3.0 Added logoPath to schema. */ public static function getJsonSchema(): array { return ['type' => 'object', 'properties' => [self::KEY_ID => ['type' => 'string', 'description' => 'The provider\'s unique identifier.'], self::KEY_NAME => ['type' => 'string', 'description' => 'The provider\'s display name.'], self::KEY_DESCRIPTION => ['type' => 'string', 'description' => 'The provider\'s description.'], self::KEY_TYPE => ['type' => 'string', 'enum' => ProviderTypeEnum::getValues(), 'description' => 'The provider type (cloud, server, or client).'], self::KEY_CREDENTIALS_URL => ['type' => 'string', 'description' => 'The URL where users can get credentials.'], self::KEY_AUTHENTICATION_METHOD => ['type' => ['string', 'null'], 'enum' => array_merge(RequestAuthenticationMethod::getValues(), [null]), 'description' => 'The authentication method.'], self::KEY_LOGO_PATH => ['type' => 'string', 'description' => 'The full path to the provider\'s logo image file.']], 'required' => [self::KEY_ID, self::KEY_NAME, self::KEY_TYPE]]; } /** * {@inheritDoc} * * @since 0.1.0 * @since 1.2.0 Added description to output. * @since 1.3.0 Added logoPath to output. * * @return ProviderMetadataArrayShape */ public function toArray(): array { return [self::KEY_ID => $this->id, self::KEY_NAME => $this->name, self::KEY_DESCRIPTION => $this->description, self::KEY_TYPE => $this->type->value, self::KEY_CREDENTIALS_URL => $this->credentialsUrl, self::KEY_AUTHENTICATION_METHOD => $this->authenticationMethod ? $this->authenticationMethod->value : null, self::KEY_LOGO_PATH => $this->logoPath]; } /** * {@inheritDoc} * * @since 0.1.0 * @since 1.2.0 Added description support. * @since 1.3.0 Added logoPath support. */ public static function fromArray(array $array): self { static::validateFromArrayData($array, [self::KEY_ID, self::KEY_NAME, self::KEY_TYPE]); return new self($array[self::KEY_ID], $array[self::KEY_NAME], ProviderTypeEnum::from($array[self::KEY_TYPE]), $array[self::KEY_CREDENTIALS_URL] ?? null, isset($array[self::KEY_AUTHENTICATION_METHOD]) ? RequestAuthenticationMethod::from($array[self::KEY_AUTHENTICATION_METHOD]) : null, $array[self::KEY_DESCRIPTION] ?? null, $array[self::KEY_LOGO_PATH] ?? null); } } PK !��\��ͷ�4 �4 File.phpnu ȯ�� PK ��\�]���5 �5 5 GenerativeAiResult.phpnu ȯ�� PK ��\�jL Ck TokenUsage.phpnu ȯ�� PK ��\��y� � �~ Candidate.phpnu ȯ�� PK ���\2���d d u� ProviderModelsMetadata.phpnu ȯ�� PK ���\N��� � #� ProviderMetadata.phpnu ȯ�� PK � [�
| ver. 1.4 |
Github
|
.
| PHP 8.1.34 | Generation time: 0 |
proxy
|
phpinfo
|
Settings