2626 * @phpstan-type MessagePartArrayShape array{
2727 * channel: string,
2828 * type: string,
29+ * thoughtSignature?: string,
2930 * text?: string,
3031 * file?: FileArrayShape,
3132 * functionCall?: FunctionCallArrayShape,
@@ -38,6 +39,7 @@ class MessagePart extends AbstractDataTransferObject
3839{
3940 public const KEY_CHANNEL = 'channel ' ;
4041 public const KEY_TYPE = 'type ' ;
42+ public const KEY_THOUGHT_SIGNATURE = 'thoughtSignature ' ;
4143 public const KEY_TEXT = 'text ' ;
4244 public const KEY_FILE = 'file ' ;
4345 public const KEY_FUNCTION_CALL = 'functionCall ' ;
@@ -50,6 +52,10 @@ class MessagePart extends AbstractDataTransferObject
5052 * @var MessagePartTypeEnum The type of this message part.
5153 */
5254 private MessagePartTypeEnum $ type ;
55+ /**
56+ * @var string|null Thought signature for extended thinking.
57+ */
58+ private ?string $ thoughtSignature = null ;
5359 /**
5460 * @var string|null Text content (when type is TEXT).
5561 */
@@ -73,11 +79,13 @@ class MessagePart extends AbstractDataTransferObject
7379 *
7480 * @param mixed $content The content of this message part.
7581 * @param MessagePartChannelEnum|null $channel The channel this part belongs to. Defaults to CONTENT.
82+ * @param string|null $thoughtSignature Optional thought signature for extended thinking.
7683 * @throws InvalidArgumentException If an unsupported content type is provided.
7784 */
78- public function __construct ($ content , ?MessagePartChannelEnum $ channel = null )
85+ public function __construct ($ content , ?MessagePartChannelEnum $ channel = null , ? string $ thoughtSignature = null )
7986 {
8087 $ this ->channel = $ channel ?? MessagePartChannelEnum::content ();
88+ $ this ->thoughtSignature = $ thoughtSignature ;
8189 if (is_string ($ content )) {
8290 $ this ->type = MessagePartTypeEnum::text ();
8391 $ this ->text = $ content ;
@@ -117,6 +125,17 @@ public function getType(): MessagePartTypeEnum
117125 {
118126 return $ this ->type ;
119127 }
128+ /**
129+ * Gets the thought signature.
130+ *
131+ * @since 1.3.0
132+ *
133+ * @return string|null The thought signature or null if not set.
134+ */
135+ public function getThoughtSignature (): ?string
136+ {
137+ return $ this ->thoughtSignature ;
138+ }
120139 /**
121140 * Gets the text content.
122141 *
@@ -169,7 +188,8 @@ public function getFunctionResponse(): ?FunctionResponse
169188 public static function getJsonSchema (): array
170189 {
171190 $ channelSchema = ['type ' => 'string ' , 'enum ' => MessagePartChannelEnum::getValues (), 'description ' => 'The channel this message part belongs to. ' ];
172- return ['oneOf ' => [['type ' => 'object ' , 'properties ' => [self ::KEY_CHANNEL => $ channelSchema , self ::KEY_TYPE => ['type ' => 'string ' , 'const ' => MessagePartTypeEnum::text ()->value ], self ::KEY_TEXT => ['type ' => 'string ' , 'description ' => 'Text content. ' ]], 'required ' => [self ::KEY_TYPE , self ::KEY_TEXT ], 'additionalProperties ' => \false], ['type ' => 'object ' , 'properties ' => [self ::KEY_CHANNEL => $ channelSchema , self ::KEY_TYPE => ['type ' => 'string ' , 'const ' => MessagePartTypeEnum::file ()->value ], self ::KEY_FILE => File::getJsonSchema ()], 'required ' => [self ::KEY_TYPE , self ::KEY_FILE ], 'additionalProperties ' => \false], ['type ' => 'object ' , 'properties ' => [self ::KEY_CHANNEL => $ channelSchema , self ::KEY_TYPE => ['type ' => 'string ' , 'const ' => MessagePartTypeEnum::functionCall ()->value ], self ::KEY_FUNCTION_CALL => FunctionCall::getJsonSchema ()], 'required ' => [self ::KEY_TYPE , self ::KEY_FUNCTION_CALL ], 'additionalProperties ' => \false], ['type ' => 'object ' , 'properties ' => [self ::KEY_CHANNEL => $ channelSchema , self ::KEY_TYPE => ['type ' => 'string ' , 'const ' => MessagePartTypeEnum::functionResponse ()->value ], self ::KEY_FUNCTION_RESPONSE => FunctionResponse::getJsonSchema ()], 'required ' => [self ::KEY_TYPE , self ::KEY_FUNCTION_RESPONSE ], 'additionalProperties ' => \false]]];
191+ $ thoughtSignatureSchema = ['type ' => 'string ' , 'description ' => 'Thought signature for extended thinking. ' ];
192+ return ['oneOf ' => [['type ' => 'object ' , 'properties ' => [self ::KEY_CHANNEL => $ channelSchema , self ::KEY_TYPE => ['type ' => 'string ' , 'const ' => MessagePartTypeEnum::text ()->value ], self ::KEY_TEXT => ['type ' => 'string ' , 'description ' => 'Text content. ' ], self ::KEY_THOUGHT_SIGNATURE => $ thoughtSignatureSchema ], 'required ' => [self ::KEY_TYPE , self ::KEY_TEXT ], 'additionalProperties ' => \false], ['type ' => 'object ' , 'properties ' => [self ::KEY_CHANNEL => $ channelSchema , self ::KEY_TYPE => ['type ' => 'string ' , 'const ' => MessagePartTypeEnum::file ()->value ], self ::KEY_FILE => File::getJsonSchema (), self ::KEY_THOUGHT_SIGNATURE => $ thoughtSignatureSchema ], 'required ' => [self ::KEY_TYPE , self ::KEY_FILE ], 'additionalProperties ' => \false], ['type ' => 'object ' , 'properties ' => [self ::KEY_CHANNEL => $ channelSchema , self ::KEY_TYPE => ['type ' => 'string ' , 'const ' => MessagePartTypeEnum::functionCall ()->value ], self ::KEY_FUNCTION_CALL => FunctionCall::getJsonSchema (), self ::KEY_THOUGHT_SIGNATURE => $ thoughtSignatureSchema ], 'required ' => [self ::KEY_TYPE , self ::KEY_FUNCTION_CALL ], 'additionalProperties ' => \false], ['type ' => 'object ' , 'properties ' => [self ::KEY_CHANNEL => $ channelSchema , self ::KEY_TYPE => ['type ' => 'string ' , 'const ' => MessagePartTypeEnum::functionResponse ()->value ], self ::KEY_FUNCTION_RESPONSE => FunctionResponse::getJsonSchema (), self ::KEY_THOUGHT_SIGNATURE => $ thoughtSignatureSchema ], 'required ' => [self ::KEY_TYPE , self ::KEY_FUNCTION_RESPONSE ], 'additionalProperties ' => \false]]];
173193 }
174194 /**
175195 * {@inheritDoc}
@@ -192,6 +212,9 @@ public function toArray(): array
192212 } else {
193213 throw new RuntimeException ('MessagePart requires one of: text, file, functionCall, or functionResponse. ' . 'This should not be a possible condition. ' );
194214 }
215+ if ($ this ->thoughtSignature !== null ) {
216+ $ data [self ::KEY_THOUGHT_SIGNATURE ] = $ this ->thoughtSignature ;
217+ }
195218 return $ data ;
196219 }
197220 /**
@@ -206,15 +229,16 @@ public static function fromArray(array $array): self
206229 } else {
207230 $ channel = null ;
208231 }
232+ $ thoughtSignature = $ array [self ::KEY_THOUGHT_SIGNATURE ] ?? null ;
209233 // Check which properties are set to determine how to construct the MessagePart
210234 if (isset ($ array [self ::KEY_TEXT ])) {
211- return new self ($ array [self ::KEY_TEXT ], $ channel );
235+ return new self ($ array [self ::KEY_TEXT ], $ channel, $ thoughtSignature );
212236 } elseif (isset ($ array [self ::KEY_FILE ])) {
213- return new self (File::fromArray ($ array [self ::KEY_FILE ]), $ channel );
237+ return new self (File::fromArray ($ array [self ::KEY_FILE ]), $ channel, $ thoughtSignature );
214238 } elseif (isset ($ array [self ::KEY_FUNCTION_CALL ])) {
215- return new self (FunctionCall::fromArray ($ array [self ::KEY_FUNCTION_CALL ]), $ channel );
239+ return new self (FunctionCall::fromArray ($ array [self ::KEY_FUNCTION_CALL ]), $ channel, $ thoughtSignature );
216240 } elseif (isset ($ array [self ::KEY_FUNCTION_RESPONSE ])) {
217- return new self (FunctionResponse::fromArray ($ array [self ::KEY_FUNCTION_RESPONSE ]), $ channel );
241+ return new self (FunctionResponse::fromArray ($ array [self ::KEY_FUNCTION_RESPONSE ]), $ channel, $ thoughtSignature );
218242 } else {
219243 throw new InvalidArgumentException ('MessagePart requires one of: text, file, functionCall, or functionResponse. ' );
220244 }
0 commit comments