symfony/ai-surreal-db-message-store
SurrealDB Message Store integration for Symfony AI Chat. Persist and retrieve chat messages using SurrealDB, with guidance for HTTP-based SurrealDB setups. Part of the Symfony AI ecosystem; contribute or report issues in the main symfony/ai repo.
Since this package is Symfony-specific, a Laravel developer would need to create a custom bridge. Here’s the minimal path:
Install Dependencies
composer require symfony/ai-surreal-db-message-store symfony/http-client symfony/serializer
Create a Laravel-Compatible Message Store
Create a new class extending Laravel’s MessageStore contract (or implement a custom interface):
// app/Services/SurrealDbMessageStore.php
namespace App\Services;
use Symfony\Component\Ai\Chat\MessageStore\MessageStoreInterface;
use Symfony\Component\Ai\Chat\Message;
use Symfony\Component\HttpClient\HttpClient;
use Symfony\Component\Serializer\SerializerInterface;
class SurrealDbMessageStore implements MessageStoreInterface
{
public function __construct(
private string $surrealdbUrl,
private string $namespace,
private string $database,
private string $rootUser,
private string $rootPass
) {}
public function save(Message $message): void
{
$client = HttpClient::create();
$serializer = new SerializerInterface(); // Use Symfony's serializer or Laravel's JSON
$data = [
'type' => 'create',
'table' => 'messages',
'record' => [
'content' => $message->getContent(),
'user_id' => $message->getUserId(),
'timestamp' => now()->toIso8601String(),
'metadata' => $message->getMetadata() ?? [],
],
];
$client->request('POST', $this->surrealdbUrl, [
'auth_basic' => [$this->rootUser, $this->rootPass],
'json' => $data,
]);
}
// Implement find(), delete(), etc.
}
Configure SurrealDB Connection
Add to .env:
SURREALDB_URL=http://localhost:8000
SURREALDB_NS=test
SURREALDB_DB=chat
SURREALDB_ROOT_USER=root
SURREALDB_ROOT_PASS=root
Bind to Laravel’s Service Container
In AppServiceProvider:
public function register()
{
$this->app->singleton(SurrealDbMessageStore::class, function ($app) {
return new SurrealDbMessageStore(
config('surrealdb.url'),
config('surrealdb.namespace'),
config('surrealdb.database'),
config('surrealdb.root_user'),
config('surrealdb.root_pass')
);
});
}
First Use Case: Storing a Chat Message
use App\Services\SurrealDbMessageStore;
use Symfony\Component\Ai\Chat\Message;
$messageStore = app(SurrealDbMessageStore::class);
$message = new Message(
userId: 'user-123',
content: 'Hello, AI!',
metadata: ['sentiment' => 'positive']
);
$messageStore->save($message);
Real-Time Chat Integration
// Example: Live chat updates via Laravel Echo/Pusher
SurrealDB::query("DEFINE TABLE messages CHANGE {
AFTER CREATE: {
SELECT * FROM messages WHERE id = NEW.id;
}
}");
Conversation Threading
-- SurrealDB schema
CREATE TABLE conversations;
CREATE TABLE messages;
ALTER TABLE messages ADD COLUMN conversation_id STRING;
$messages = $messageStore->findBy(['conversation_id' => $convId]);
Metadata Attachment
$message->setMetadata([
'embeddings' => $vectorData,
'user_tags' => ['premium', 'active']
]);
Authentication: SurrealDB uses NSM (Namespace/Database/Role) auth. For Laravel, create a custom guard:
// app/Providers/Auth/SurrealdbAuthProvider.php
class SurrealDbAuthProvider
{
public function getToken(): string
{
return base64_encode("{$this->rootUser}:{$this->rootPass}");
}
}
Error Handling: Wrap SurrealDB calls in Laravel’s exception handler:
try {
$response = $client->request('POST', $url, [...]);
$response->toArray();
} catch (\Exception $e) {
Log::error("SurrealDB Error: " . $e->getMessage());
throw new \RuntimeException("Failed to store message", 0, $e);
}
Batch Operations: Use SurrealDB’s SCRIPT for bulk inserts:
$script = "BEGIN TRANSACTION;
CREATE messages SET {$jsonPayload};
COMMIT;";
$client->request('POST', $url, ['json' => ['query' => $script]]);
Laravel Events: Trigger events on message storage:
event(new MessageStored($message));
Schema-less Chaos
SCRIPT to enforce basic constraints:
DEFINE FIELD messages.content ASSERT $value IS STRING;
HTTP Latency
Authentication Quirks
$token = SurrealDB::signin($namespace, $database, $user, $pass);
$client->setDefaultOptions(['headers' => ['Authorization' => "Token $token"]]);
No Native Laravel Support
HttpClient. Tip: Replace with Laravel’s Http facade:
use Illuminate\Support\Facades\Http;
$response = Http::withBasicAuth($user, $pass)
->post($url, $data);
Limited Querying
SELECT with FILTER for basic queries:
$messages = $client->request('POST', $url, [
'json' => [
'query' => 'SELECT * FROM messages FILTER user_id = "user-123"'
]
]);
Enable SurrealDB Logging
SurrealDB::setLogLevel(3); // Enable debug logs
Validate HTTP Requests
Use Laravel’s tap to inspect requests:
$response = Http::post($url, $data)->tap(function ($response) {
Log::debug("SurrealDB Response: " . $response->body());
});
Check SurrealDB Status
curl http://localhost:8000/status
Custom Serialization Override Symfony’s serializer with Laravel’s JSON:
use Illuminate\Support\Facades\JSON;
$data = JSON::encode([
'content' => $message->content,
'metadata' => $message->metadata
]);
WebSocket Integration Use Laravel Echo with SurrealDB’s WebSocket:
// resources/js/bootstrap.js
import Echo from 'laravel-echo';
window.Pusher = require('pusher-js');
window.Echo = new Echo({
broadcaster: 'surrealdb',
key: 'your-surrealdb-ws-key',
wsHost: 'localhost',
wsPort: 8000,
forceTLS: false,
disableStats: true,
});
Fork and Extend Fork the package to add Laravel-specific features (e.g., queue support):
// app/Jobs/SaveMessageToSurrealDB.php
class SaveMessageToSurrealDB implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable;
public function handle()
{
$messageStore = app(SurrealDbMessageStore::class);
$messageStore->save($this->message);
}
}
Hybrid Storage Combine SurrealDB with Laravel’s cache for read-heavy workloads:
How can I help you explore Laravel packages today?