Installation:
composer require arnaudmoncondhuy/synapse-chat:^0.1 arnaudmoncondhuy/synapse-core
Register Bundle (config/bundles.php):
ArnaudMoncondhuy\SynapseChat\SynapseChatBundle::class => ['all' => true],
Enable Routes (config/routes.yaml):
synapse_chat:
resource: '@SynapseChatBundle/config/routes.yaml'
prefix: /api
Security Configuration (config/packages/security.yaml):
access_control:
- { path: ^/api/chat, roles: ROLE_USER }
- { path: ^/api/csrf, roles: PUBLIC_ACCESS }
First Use Case: Embed the chat component in a Twig template:
{% include '@Synapse/chat/component.html.twig' %}
Template Integration: Use the provided Twig templates for a full-page chat or embeddable component:
{% include '@Synapse/chat/component.html.twig' with {
title: 'Support Chat',
placeholder: 'Ask me anything...'
} %}
Stimulus Controller:
The synapse_chat_controller handles:
/api/chat.API Interaction:
/api/chat with X-CSRF-Token.messageReceived and responseComplete events./api/estimate-cost before sending.Conversation Management: Use the API endpoints to:
GET /api/conversations.POST /api/conversation/reset.POST /api/memory/confirm or POST /api/memory/manual.Asset Integration: Include assets in your layout:
{% include '@Synapse/chat/assets.html.twig' %}
X-CSRF-Token header for POST requests. For SPAs, fetch the token via GET /api/csrf-token.ROLE_USER).config/packages/synapse_chat.yaml:
synapse_chat:
default_preset_name: "default"
templates/bundles/SynapseChat/ to modify UI.CSRF Mismatch:
X-CSRF-Token header causes 403 errors.synapse_chat.api_csrf_enabled: true) and ensure the token is included in requests. For SPAs, fetch the token dynamically:
const csrfToken = await fetch('/api/csrf-token').then(res => res.text());
Streaming Disconnections:
connect() {
this.streaming = this.connectStreaming();
}
disconnect() {
this.streaming?.close();
}
connectStreaming() {
const eventSource = new EventSource('/api/chat?stream=true');
eventSource.onmessage = (e) => this.messageReceived(JSON.parse(e.data));
eventSource.onerror = () => this.connectStreaming(); // Auto-reconnect
return eventSource;
}
Token Limits:
/api/estimate-cost to check token usage before sending:
const cost = await fetch('/api/estimate-cost', {
method: 'POST',
headers: { 'X-CSRF-Token': csrfToken },
body: JSON.stringify({ message: userInput })
}).then(res => res.json());
if (cost.output_tokens > MAX_ALLOWED) {
showWarning("Message too long. Try shortening it.");
}
Memory Management:
ProposeMemoryTool responses:
messageReceived(chunk) {
if (chunk.type === 'tool_call' && chunk.tool_use.name === 'ProposeMemoryTool') {
showMemoryConfirmation(chunk.tool_use.input);
}
}
NDJSON Validation:
Stimulus Events:
messageReceived(event) {
console.log('Chunk:', event.detail.chunk);
}
API Logs:
config/packages/dev/synapse_chat.yaml:
synapse_chat:
debug: true
var/log/dev.log) for API errors.Custom Templates:
@Synapse/chat/component.html.twig) in templates/bundles/SynapseChat/.Stimulus Extensions:
synapse_chat_controller by adding custom methods:
static get targets() { return [...super.targets(), 'customTarget']; }
API Middleware:
/api/chat for custom logic (e.g., logging, rate limiting):
# config/routes.yaml
synapse_chat:
resource: '@SynapseChatBundle/config/routes.yaml'
prefix: /api
defaults: { _controller: 'App\Controller\ChatMiddleware::process' }
Translation Overrides:
translations/synapse_chat.en.yaml:
synapse:
chat:
input_area:
placeholder: "Ask your custom question here..."
How can I help you explore Laravel packages today?