Download the PHP package monoverse/voicebot-laravel-sync without Composer
On this page you can find all versions of the php package monoverse/voicebot-laravel-sync. It is possible to download/install these versions without Composer. Possible dependencies are resolved automatically.
Informations about the package voicebot-laravel-sync
monoverse/voicebot-laravel-sync
Sync your Laravel catalog and content to VoiceBot for an AI sales assistant — signed, incremental, swiss-watch reliable.
This package is a producer client for the VoiceBot canonical signed-ingest contract (ADR-045 / ADR-055). It pairs with VoiceBot once, then pushes your products, categories, pages and more over an HMAC-signed protocol: a full snapshot for the baseline and small incremental deltas after that. Voice stays on the server — this package never embeds any LLM SDK; it only streams your data to the ingest endpoint.
- Signed — every request is HMAC-SHA256 signed (protocol v2); the shared secret is stored encrypted at rest and never logged or printed.
- Incremental — a per-entity watermark means deltas push only what changed.
- Memory-safe — snapshots stream as gzipped NDJSON straight from disk; the full catalog is never held in memory.
- Adaptive — point each entity kind at your model with a small column map, or bind a fully custom source.
Requirements
- PHP 8.2+ (Laravel 13 requires PHP 8.3+)
- Laravel 10, 11, 12 or 13
- An
APP_KEY(used to encrypt the stored shared secret)
Install from Packagist
The package is published on public Packagist
as monoverse/voicebot-laravel-sync — install it with a plain Composer require:
Publish the config and run migrations (auto-discovery registers the service provider):
The package registers its migrations, so a plain php artisan migrate creates three
tables: voicebot_connections (encrypted secret), voicebot_sync_state (per-kind
watermark) and voicebot_dead_letter (parked failures). No migration publish step is
required; publish them only if you want to customise the schema.
The ingest base URL must be
https://(plaintexthttp://is rejected — an HMAC over http would leak the signature).localhost/127.0.0.1are allowed for local dev.
Pair
Copy your publishable key (pk_...) from your VoiceBot dashboard, then:
The command stores your tenant id + shared secret (encrypted) and prints the tenant id.
The shared secret is never printed or logged. For non-interactive CI, set
VOICEBOT_PUBLIC_KEY and run php artisan voicebot:pair.
VOICEBOT_SITE_URL (defaults to APP_URL) is sent as the storefront site_url and must
match the domain bound to the key in your dashboard (apex/www are treated as equal). A
mismatch fails with a clear domain_mismatch hint — point VOICEBOT_SITE_URL at the
registered storefront domain.
Legacy fallback. The earlier one-time pair code (
VB-XXXX-XXXX, envVOICEBOT_PAIR_CODE) still works: pass it as the argument or set the env var. Pairing resolves the credential in order: CLI argument →VOICEBOT_PUBLIC_KEY→VOICEBOT_PAIR_CODE. Already-paired installs keep their stored secret — re-pairing is not required.
Map your models
Open config/voicebot.php and, for each kind you have, set the model and a column map.
Map keys are dot paths under payload; values are either a column name or a closure
receiving the model.
Mapping rules that matter
- Money is integer minor units.
199.99 UAH→19999. Never send a float/decimal. - Categories and tags are slug lists (
['kava', 'napoi']), not objects. - Page
content_textis plain text — strip HTML. external_idsupplies the raw id only; the package wraps it tolaravel:{kind}:{id}. Parent references follow the same shape, e.g.'payload.parent_external_id' => fn ($m) => $m->parent_id ? 'laravel:category:'.$m->parent_id : null.- Soft deletes are detected automatically (model uses
SoftDeletes) and pushed as delete ops during deltas. Hard deletes are reconciled by the nightly full snapshot's server-side tombstone pass.
Custom source (full control)
For anything the config map can't express, implement EntitySource and point the kind's
source at your class (resolved from the container):
upserts() and deletes() must return a streaming LazyCollection — never
materialise the whole catalog.
Verify before the first push
Doctor checks pairing, backend reachability, and — per enabled kind — a resolvable model,
a non-empty map, and the backend-required payload fields on a sampled mapped row. It emits
one sample mapped record per kind and pushes nothing. Fix every FAIL before syncing.
Sync
Exit codes (cron-friendly)
| Code | Meaning | Action |
|---|---|---|
0 |
success | — |
1 |
transient failure (network/5xx) or a delta that dead-lettered ops | cron alerts, retry next run |
2 |
config error (not paired, empty snapshot, bad model, bad --since) |
a retry won't help; fix config |
Signed requests retry on connection errors only — never on 429/5xx — because the
backend consumes the request nonce before it can return an error status, so a blind
retry would be rejected as a replay. The unsigned pair handshake and the snapshot
upload (no HMAC) do retry on 429/5xx with backoff that honours Retry-After.
Failed delta ops land in voicebot_dead_letter (never silently dropped). Re-failures
of the same op across runs increment its attempts; once it hits
sync.dead_letter_max_attempts the row is flagged exhausted for manual review/replay.
Unpair
Tells the backend to disconnect, then wipes the locally stored tenant id + shared secret. The local credentials are cleared even if the remote call fails, so you can always re-pair. Run this before pairing a different tenant.
Schedule
Prerequisite: a system cron entry that ticks Laravel's scheduler every minute:
Laravel 11 / 12 — routes/console.php
Laravel 10 — app/Console/Kernel.php
Tune cadence to your catalog volatility — the package ships no hardcoded schedule.
Entity coverage
product, variation, category, tag, attribute, page, post, cpt, menu,
menu_item, site, shipping_method, payment_method. Enable only the kinds you have.
Security
- The shared secret is stored encrypted (
encryptedcast over LaravelCrypt, keyed byAPP_KEY) and is never logged, printed, or returned in any output. - Every signed request carries an HMAC over
METHOD\npath\nts\nnonce\nbody_sha256; the exact bytes hashed are the exact bytes sent, so the server's body check always matches. - Requests use a fresh 16-byte nonce and a current timestamp (server enforces a 300s
replay window). Retries honour
Retry-After.
Configuration reference
All knobs are env-overridable; see config/voicebot.php. Key ones:
| Env | Default | Purpose |
|---|---|---|
VOICEBOT_BASE_URL |
https://api.monoverse.tech |
Ingest base URL |
VOICEBOT_PUBLIC_KEY |
— | Publishable key (pk_...) for pair-by-key (preferred) |
VOICEBOT_PAIR_CODE |
— | Legacy one-time pair code (CI fallback) |
VOICEBOT_SITE_URL |
APP_URL |
Sent as site_url / X-VoiceBot-Site-Url; must match the key's bound domain |
VOICEBOT_SYNC_CHUNK_SIZE |
200 |
Rows per DB chunk while streaming |
VOICEBOT_SYNC_QUEUE |
default | Queue connection for --queue |
VOICEBOT_CURRENCY |
UAH |
Convenience for example maps |
Publishing (maintainers)
This package lives in the VoiceBot monorepo at packages/laravel-sync/ and is published to
public Packagist via a read-only subtree split of this directory into the standalone
mirror repo Monoverse1/voicebot-laravel-sync. Releases are tag-driven: push a
monorepo tag laravel-sync-vX.Y.Z and the
publish-laravel-sync workflow splits +
mirrors the tag, which Packagist then indexes. The full runbook (one-time Packagist setup,
required secrets/vars, the release flow) is in PUBLISHING.md;
v0.1.0 was seeded manually and is already live on the mirror.
License
Proprietary © Monoverse.
All versions of voicebot-laravel-sync with dependencies
illuminate/contracts Version ^10.0 || ^11.0 || ^12.0 || ^13.0
illuminate/support Version ^10.0 || ^11.0 || ^12.0 || ^13.0
illuminate/console Version ^10.0 || ^11.0 || ^12.0 || ^13.0
illuminate/http Version ^10.0 || ^11.0 || ^12.0 || ^13.0
illuminate/database Version ^10.0 || ^11.0 || ^12.0 || ^13.0
guzzlehttp/guzzle Version ^7.5
guzzlehttp/psr7 Version ^2.0
spatie/laravel-package-tools Version ^1.93