Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Synapse Toon Laravel Package

vinkius-labs/synapse-toon

Synapse Toon converts PHP arrays, Eloquent models, and JSON payloads into TOON, a compact token-efficient format for LLM prompts. Cut prompt size and API costs while keeping structured data readable, with simple Laravel helpers and configurable encoding.

View on GitHub
Deep Wiki
Context7

Getting Started

This is a v1.0.0 with no prior assessment and no upgrade path to worry about — treat it as greenfield evaluation, not adoption of a proven dependency.

Prerequisites: PHP 8.2/8.3, Laravel 11.x or 12.x. Nothing older.

composer require vinkius-labs/synapse-toon

Where to look first, in this order:

  1. SynapseToonPayloadAnalyzer — do not wire the encoder into anything until you've run your real payloads through this. The 25–45% figures in the release notes come from an e-commerce feed, a chat completion, and a nested GraphQL query. Your payload shape determines your number, and for short or heterogeneous payloads the ratio can go negative. Measure before you commit.
  2. SynapseToonEncoder / SynapseToonDecoder — verify round-trip fidelity on your own data before trusting "lossless." See Gotchas.
  3. SynapseToonLLMRouter — check the pluggable client interface early, because it's the seam you'll bind your existing LLM client (OpenAI, Anthropic, Bedrock) behind.

Best first use case: a single endpoint that returns a large, structurally homogeneous array to an LLM — a product feed, a search result set, a table dump. That's the shape TOON is designed for and where the savings are real. Avoid starting with GraphQL, SSE, or the batch job; those are the highest-integration-cost surfaces and they all sit on top of an encoder you haven't validated yet.

Roll out behind a feature flag on one route, compare analyzer output against the current JSON, and only then widen.

Implementation Patterns

Encode at the boundary, not in your domain. The cleanest integration is response-level: a middleware or response macro that inspects the outgoing payload and encodes it, plus a negotiation check for who's asking. Keeping encoder calls out of controllers, resources, and services means you can disable the whole thing with one flag.

Content negotiation over silent substitution. Serve TOON under its own media type (e.g. application/toon) and honour Accept. Silently swapping application/json for a TOON body will break every non-LLM consumer of that route — HTTP clients, mobile apps, browser fetch handlers, third-party webhooks. This is the single decision most likely to cause an incident.

Edge cache: cache the encoded artifact, not the raw payload. SynapseToonEdgeCache is explicitly "encode-once," so key on something stable — payload identity hash plus encoder/schema version. Encode-on-write, serve-on-read. If you key on request parameters alone you'll serve stale encoded bodies after a payload shape change, and the decoder will happily produce garbage.

Compression is a layer, not a replacement. SynapseToonCompressor picks Brotli/Gzip/Deflate from Accept-Encoding. In practice you'll often have nginx, Cloudflare, or your web server already compressing. Pick one place to compress; double-compressing wastes CPU and confuses debugging. If the package sets Content-Encoding behind a proxy that also sets it, expect ERR_CONTENT_DECODING_FAILED in browsers.

SSE: let the streamer own the flush. SynapseToonSseStreamer's "buffer flush guardrails" are the point — hand it an iterable/generator and let it manage chunk boundaries. Don't manually echo and ob_flush() alongside it.

Batch encoding belongs on the queue with a fan-out limit. SynapseToonProcessLLMBatchJob caps at 100 prompts per dispatch. That cap exists because the serialized job is the payload — keep each dispatch well under your queue driver's message limit (SQS is 256 KB) and use Bus::batch() with allowFailures() so one malformed prompt doesn't kill 99 good ones. Make the job idempotent; retries will re-encode.

Router: bind the interface, fake it in tests. SynapseToonLLMRouter is complexity-aware with pluggable clients, which means your test suite should never hit a real provider. Bind a fake client in the container and assert on the routing decision (which tier was chosen for which prompt) rather than on output text.

RAG and GraphQL are adapters over existing infrastructure. SynapseToonRagService wraps a vector store — you supply the store, it handles snippet thresholds and metadata braiding. Similarly SynapseToonGraphQLAdapter slots into Lighthouse or Rebing as a pipeline step. Integrate these by wrapping your existing service, not by migrating your retrieval or schema layer into the package.

Metrics: write a custom driver that forwards to your existing stack. Driver-agnostic with Log/Prometheus/Datadog built in. If you already run OpenTelemetry or StatsD, a thin custom driver is less operational surface than adding a second metrics path.

Testing pattern: golden-fixture round-trip tests. Capture real production payloads, assert decode(encode($x)) === $x, and assert the analyzer's token delta. Run the fixture set on every package upgrade — you have no compatibility history to lean on.

Gotchas and Tips

"Lossless" needs a precise definition, and you should find it. TOON is a dense tabular encoding. The questions that matter: how are floats round-tripped (trailing zeros, precision, 1.0 vs 1)? null vs missing key? Empty array vs empty object? Unicode, emoji, RTL text? Numeric-looking strings ("007", "1e5")? Date formats? Large integers beyond PHP's float precision? Run a deliberate edge-case corpus through encode/decode before you trust it on money, IDs, or timestamps.

TOON optimises tokens, not bytes — and tokenizer-dependent. The 44.7%/39.8%/34.8% figures are token counts, presumably against a specific tokenizer. Claude, GPT-4o, and Llama tokenize structured text differently. Re-measure with the tokenizer of the model you're actually calling; the analyzer should be your source of truth, not the README table.

The biggest practical risk is consumer compatibility. If the far end is an LLM, the model must actually understand TOON — that's a capability question, not a code question. If the far end is your own Laravel service, you both need the package. If it's a partner or a frontend, you've broken the contract. Never encode a public API response without a negotiated opt-in.

Savings can invert on small payloads. A 3-field object gains nothing and may pay overhead for headers/dictionary. Gate encoding on a size threshold — the analyzer gives you the number to pick.

Dictionary support implies shared state. SynapseToonEncoder has dictionary support; if dictionaries are negotiated, cached, or versioned, an encoder/decoder mismatch silently corrupts output. Pin dictionary version into your cache keys and include it in the content type or a header.

Octane state leakage. SynapseToonEdgeCache is "tuned for Redis and Octane," which is exactly the environment where static properties and singletons persist across requests. If the package holds a dictionary or buffer in a static, one tenant's data can bleed into another's response. Test under Octane specifically, with two different payload shapes in sequence.

Compressor + cache interaction is a cache-poisoning surface. If the response varies by Accept-Encoding (it does), Vary: Accept-Encoding must be set correctly, or a CDN will serve a Brotli body to a client that asked for gzip. Verify with curl -H 'Accept-Encoding: ...' against your CDN, not just locally.

SSE behind proxies. nginx buffers by default — you need X-Accel-Buffering: no or proxy_buffering off. Also watch fastcgi_read_timeout, and confirm the streamer doesn't split multi-byte UTF-8 across chunk boundaries (a mangled emoji in a token stream is hard to trace back).

Batch job payload limits and retries. 100 prompts is the ceiling, not the target. Long prompts × 100 can blow past SQS's 256 KB or Redis queue comfort. Chunk by serialized byte size, set $tries and $backoff deliberately, and make the handler safe to run twice.

Router heuristics need a fallback. Complexity-aware routing will misclassify. Every routed request should have a defined degraded path (default model, or fail-open to the largest model) and the routing decision should be logged with the prompt ID so you can debug a bad answer back to a tier choice.

Metrics cardinality. Don't label token metrics by prompt text or user ID. Bucket it.

v1.0.0 means no deprecation history. The wire format is the risk: if TOON's spec changes in a 1.x minor, your cached encoded artifacts and any cross-service consumers go stale. Pin the version with ~1.0.0 rather than ^1.0, version your cache keys against the package version, and keep the encode path behind a toggle so you can fall back to JSON without a deploy.

Debugging tactic: when output looks wrong, disable encoding at the middleware and diff the JSON against decode(encode($json)). If the diff is non-empty, you've found either a codec bug or an unsupported type — file it with the minimal payload. Keep that diff assertion in your test suite permanently.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
socialdept/atp-orm
cboxdk/laravel-assistant-client
socialdept/atp-resolver
socialdept/tenant-domains
tautvydasr/blade-class-names
socialdept/color-scales
maherelgamil/controller
coleus/widgets
coleus/table
coleus/users
coleus/music
coleus/health
coleus/calendar
coleus/notes
coleus/support
coleus/settings
coleus/apps
seampact/laravel
emmyconceptng/laravel-ng-postcode
jjsquady/round-robin