Skip to content

Commit 115a9e1

Browse files
OskarStarkchr-hertel
authored andcommitted
feat: use intersection type AbstractUid&TimeBasedUidInterface for flexible message IDs (#384)
This PR updates the message ID type from `TimeBasedUidInterface` to `AbstractUid&TimeBasedUidInterface` using PHP's intersection types. This change provides more flexibility while maintaining type safety. Using the intersection type `AbstractUid&TimeBasedUidInterface` ensures that: - ✅ Both `toRfc4122()` (from AbstractUid) and `getDateTime()` (from TimeBasedUidInterface) are available - ✅ Implementations can use any time-based UID type (UUID v1/v6/v7 or ULID) - ✅ Type safety is maintained - ✅ All existing tests pass without modification - Updated `MessageInterface::getId()` return type - Updated all message implementations (AssistantMessage, SystemMessage, UserMessage, ToolCallMessage) - Updated anonymous class in tests 1. **Flexibility**: Users can now implement messages with either UUID or ULID 2. **Type Safety**: The intersection type guarantees all necessary methods are available 3. **Future Proof**: Any new Symfony UID types that extend AbstractUid and implement TimeBasedUidInterface will work None - this is backwards compatible since all existing UUID implementations already satisfy the new type constraint. All existing tests pass. The implementation has been verified to work with both UUID and ULID.
1 parent 1089e85 commit 115a9e1

10 files changed

+71
-11
lines changed

src/platform/src/Message/AssistantMessage.php

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,16 @@
1212
namespace Symfony\AI\Platform\Message;
1313

1414
use Symfony\AI\Platform\Response\ToolCall;
15+
use Symfony\Component\Uid\AbstractUid;
16+
use Symfony\Component\Uid\TimeBasedUidInterface;
1517
use Symfony\Component\Uid\Uuid;
1618

1719
/**
1820
* @author Denis Zunke <[email protected]>
1921
*/
2022
final readonly class AssistantMessage implements MessageInterface
2123
{
22-
public Uuid $id;
24+
public AbstractUid&TimeBasedUidInterface $id;
2325

2426
/**
2527
* @param ?ToolCall[] $toolCalls
@@ -36,7 +38,7 @@ public function getRole(): Role
3638
return Role::Assistant;
3739
}
3840

39-
public function getId(): Uuid
41+
public function getId(): AbstractUid&TimeBasedUidInterface
4042
{
4143
return $this->id;
4244
}

src/platform/src/Message/MessageInterface.php

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@
1111

1212
namespace Symfony\AI\Platform\Message;
1313

14-
use Symfony\Component\Uid\Uuid;
14+
use Symfony\Component\Uid\AbstractUid;
15+
use Symfony\Component\Uid\TimeBasedUidInterface;
1516

1617
/**
1718
* @author Denis Zunke <[email protected]>
@@ -20,5 +21,5 @@ interface MessageInterface
2021
{
2122
public function getRole(): Role;
2223

23-
public function getId(): Uuid;
24+
public function getId(): AbstractUid&TimeBasedUidInterface;
2425
}

src/platform/src/Message/SystemMessage.php

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,16 @@
1111

1212
namespace Symfony\AI\Platform\Message;
1313

14+
use Symfony\Component\Uid\AbstractUid;
15+
use Symfony\Component\Uid\TimeBasedUidInterface;
1416
use Symfony\Component\Uid\Uuid;
1517

1618
/**
1719
* @author Denis Zunke <[email protected]>
1820
*/
1921
final readonly class SystemMessage implements MessageInterface
2022
{
21-
public Uuid $id;
23+
public AbstractUid&TimeBasedUidInterface $id;
2224

2325
public function __construct(public string $content)
2426
{
@@ -30,7 +32,7 @@ public function getRole(): Role
3032
return Role::System;
3133
}
3234

33-
public function getId(): Uuid
35+
public function getId(): AbstractUid&TimeBasedUidInterface
3436
{
3537
return $this->id;
3638
}

src/platform/src/Message/ToolCallMessage.php

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,16 @@
1212
namespace Symfony\AI\Platform\Message;
1313

1414
use Symfony\AI\Platform\Response\ToolCall;
15+
use Symfony\Component\Uid\AbstractUid;
16+
use Symfony\Component\Uid\TimeBasedUidInterface;
1517
use Symfony\Component\Uid\Uuid;
1618

1719
/**
1820
* @author Denis Zunke <[email protected]>
1921
*/
2022
final readonly class ToolCallMessage implements MessageInterface
2123
{
22-
public Uuid $id;
24+
public AbstractUid&TimeBasedUidInterface $id;
2325

2426
public function __construct(
2527
public ToolCall $toolCall,
@@ -33,7 +35,7 @@ public function getRole(): Role
3335
return Role::ToolCall;
3436
}
3537

36-
public function getId(): Uuid
38+
public function getId(): AbstractUid&TimeBasedUidInterface
3739
{
3840
return $this->id;
3941
}

src/platform/src/Message/UserMessage.php

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
use Symfony\AI\Platform\Message\Content\ContentInterface;
1616
use Symfony\AI\Platform\Message\Content\Image;
1717
use Symfony\AI\Platform\Message\Content\ImageUrl;
18+
use Symfony\Component\Uid\AbstractUid;
19+
use Symfony\Component\Uid\TimeBasedUidInterface;
1820
use Symfony\Component\Uid\Uuid;
1921

2022
/**
@@ -27,7 +29,7 @@
2729
*/
2830
public array $content;
2931

30-
public Uuid $id;
32+
public AbstractUid&TimeBasedUidInterface $id;
3133

3234
public function __construct(
3335
ContentInterface ...$content,
@@ -41,7 +43,7 @@ public function getRole(): Role
4143
return Role::User;
4244
}
4345

44-
public function getId(): Uuid
46+
public function getId(): AbstractUid&TimeBasedUidInterface
4547
{
4648
return $this->id;
4749
}

src/platform/tests/ContractTest.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@
4242
use Symfony\AI\Platform\Message\SystemMessage;
4343
use Symfony\AI\Platform\Message\UserMessage;
4444
use Symfony\AI\Platform\Model;
45+
use Symfony\Component\Uid\AbstractUid;
46+
use Symfony\Component\Uid\TimeBasedUidInterface;
4547
use Symfony\Component\Uid\Uuid;
4648

4749
#[Large]
@@ -208,7 +210,7 @@ public function getRole(): Role
208210
return Role::User;
209211
}
210212

211-
public function getId(): Uuid
213+
public function getId(): AbstractUid&TimeBasedUidInterface
212214
{
213215
return Uuid::v7();
214216
}

src/platform/tests/Message/AssistantMessageTest.php

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@
2020
use Symfony\AI\Platform\Message\Role;
2121
use Symfony\AI\Platform\Response\ToolCall;
2222
use Symfony\AI\Platform\Tests\Helper\UuidAssertionTrait;
23+
use Symfony\Component\Uid\AbstractUid;
24+
use Symfony\Component\Uid\TimeBasedUidInterface;
2325
use Symfony\Component\Uid\UuidV7;
2426

2527
#[CoversClass(AssistantMessage::class)]
@@ -86,4 +88,14 @@ public function sameMessagesHaveDifferentUids(): void
8688
self::assertIsUuidV7($message1->getId()->toRfc4122());
8789
self::assertIsUuidV7($message2->getId()->toRfc4122());
8890
}
91+
92+
#[Test]
93+
public function messageIdImplementsRequiredInterfaces(): void
94+
{
95+
$message = new AssistantMessage('test');
96+
97+
self::assertInstanceOf(AbstractUid::class, $message->getId());
98+
self::assertInstanceOf(TimeBasedUidInterface::class, $message->getId());
99+
self::assertInstanceOf(UuidV7::class, $message->getId());
100+
}
89101
}

src/platform/tests/Message/SystemMessageTest.php

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818
use Symfony\AI\Platform\Message\Role;
1919
use Symfony\AI\Platform\Message\SystemMessage;
2020
use Symfony\AI\Platform\Tests\Helper\UuidAssertionTrait;
21+
use Symfony\Component\Uid\AbstractUid;
22+
use Symfony\Component\Uid\TimeBasedUidInterface;
2123
use Symfony\Component\Uid\UuidV7;
2224

2325
#[CoversClass(SystemMessage::class)]
@@ -66,4 +68,14 @@ public function sameMessagesHaveDifferentUids(): void
6668
self::assertIsUuidV7($message1->getId()->toRfc4122());
6769
self::assertIsUuidV7($message2->getId()->toRfc4122());
6870
}
71+
72+
#[Test]
73+
public function messageIdImplementsRequiredInterfaces(): void
74+
{
75+
$message = new SystemMessage('test');
76+
77+
self::assertInstanceOf(AbstractUid::class, $message->getId());
78+
self::assertInstanceOf(TimeBasedUidInterface::class, $message->getId());
79+
self::assertInstanceOf(UuidV7::class, $message->getId());
80+
}
6981
}

src/platform/tests/Message/ToolCallMessageTest.php

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@
1919
use Symfony\AI\Platform\Message\ToolCallMessage;
2020
use Symfony\AI\Platform\Response\ToolCall;
2121
use Symfony\AI\Platform\Tests\Helper\UuidAssertionTrait;
22+
use Symfony\Component\Uid\AbstractUid;
23+
use Symfony\Component\Uid\TimeBasedUidInterface;
2224
use Symfony\Component\Uid\UuidV7;
2325

2426
#[CoversClass(ToolCallMessage::class)]
@@ -72,4 +74,15 @@ public function sameMessagesHaveDifferentUids(): void
7274
self::assertIsUuidV7($message1->getId()->toRfc4122());
7375
self::assertIsUuidV7($message2->getId()->toRfc4122());
7476
}
77+
78+
#[Test]
79+
public function messageIdImplementsRequiredInterfaces(): void
80+
{
81+
$toolCall = new ToolCall('foo', 'bar');
82+
$message = new ToolCallMessage($toolCall, 'test');
83+
84+
self::assertInstanceOf(AbstractUid::class, $message->getId());
85+
self::assertInstanceOf(TimeBasedUidInterface::class, $message->getId());
86+
self::assertInstanceOf(UuidV7::class, $message->getId());
87+
}
7588
}

src/platform/tests/Message/UserMessageTest.php

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@
2222
use Symfony\AI\Platform\Message\Role;
2323
use Symfony\AI\Platform\Message\UserMessage;
2424
use Symfony\AI\Platform\Tests\Helper\UuidAssertionTrait;
25+
use Symfony\Component\Uid\AbstractUid;
26+
use Symfony\Component\Uid\TimeBasedUidInterface;
2527
use Symfony\Component\Uid\UuidV7;
2628

2729
#[CoversClass(UserMessage::class)]
@@ -116,4 +118,14 @@ public function sameMessagesHaveDifferentUids(): void
116118
self::assertIsUuidV7($message1->getId()->toRfc4122());
117119
self::assertIsUuidV7($message2->getId()->toRfc4122());
118120
}
121+
122+
#[Test]
123+
public function messageIdImplementsRequiredInterfaces(): void
124+
{
125+
$message = new UserMessage(new Text('test'));
126+
127+
self::assertInstanceOf(AbstractUid::class, $message->getId());
128+
self::assertInstanceOf(TimeBasedUidInterface::class, $message->getId());
129+
self::assertInstanceOf(UuidV7::class, $message->getId());
130+
}
119131
}

0 commit comments

Comments
 (0)