cognesy / instructor-messages
Message and message lists handling for Instructor PHP library
Installs: 57
Dependents: 5
Suggesters: 0
Security: 0
Stars: 0
Watchers: 0
Forks: 0
pkg:composer/cognesy/instructor-messages
Requires
- php: ^8.2
- cognesy/instructor-utils: ^1.16
Requires (Dev)
- icanhazstring/composer-unused: ^0.9.0
- jetbrains/phpstorm-attributes: ^1.2
- maglnet/composer-require-checker: ^4.16
- pestphp/pest: ^2.34
- phpstan/phpstan: ^1.11
- roave/security-advisories: dev-latest
- vimeo/psalm: ^6.0
README
Utilities for representing chat messages, multimodal content parts, and message stores. The API is immutable and designed for composing OpenAI-compatible message payloads.
Canonical content-part shape
Non-text parts are emitted in nested form. Legacy flat inputs are accepted and normalized on output.
Content stores parts in a ContentParts collection. Use partsList() if you need the value object.
You can also build content directly from a ContentParts collection via Content::fromParts().
parts() remains for backward compatibility but is deprecated.
Messages now use an internal MessageList collection for immutable operations while keeping the public API unchanged. Use messageList() if you need the value object.
You can construct a Messages instance from a MessageList via Messages::fromList().
Use headList() / tailList() when you need MessageList for partitions.
head() and tail() remain for backward compatibility but are deprecated.
all() remains for backward compatibility but is deprecated.
// text ['type' => 'text', 'text' => 'hello'] // image ['type' => 'image_url', 'image_url' => ['url' => 'https://example.com/image.jpg']] // audio ['type' => 'input_audio', 'input_audio' => ['data' => '...base64...', 'format' => 'wav']] // file ['type' => 'file', 'file' => ['file_data' => 'data:...base64...', 'file_name' => 'report.pdf', 'file_id' => 'file-...']]
Quick example
use Cognesy\Messages\Content; use Cognesy\Messages\Message; use Cognesy\Messages\ContentPart; use Cognesy\Messages\Utils\Image; $message = new Message('user', Content::text('Describe this image:')); $message = $message->addContentPart(ContentPart::image(Image::fromUrl('https://example.com/cat.jpg', 'image/jpeg'))); $payload = $message->toArray();
Migration notes (2026-01-05)
- Non-text content parts are now emitted in nested form (e.g.
image_url,file,input_audio). Flat legacy inputs are still accepted but normalized on output. - File payloads use
file_name(nested underfile) as the canonical key. Messages::filter()with no callback now returns all non-empty messages (previously it returned an empty collection).