Repository navigation
Architecture
Pavel Erokhin edited this page Oct 22, 2026
·
5 revisions
The backend is one Bun process with MongoDB beside it. A question goes through it like this.
- The plugin posts to
/api/v2/chat.src/features/auth/caller.tsidentifies the server by its license orPLUGIN_TOKENand names its tenant;src/features/chat/validates the body and opens the SSE stream. -
src/features/billing/gate.tsdecides who pays: the plugin's own key, a license with money left, or the backend's key on a self-hosted backend. Limits count per tenant. -
src/agent/assembles the prompt fromsrc/prompts/*.md, the player's memories, and the session, then runs the Mastra agent. - When the model calls a game tool, the bridge in
src/features/chat/sends atool_callevent and waits for the plugin'sPOST /api/v2/chat/{run}/tools/{call}. - Server tools (
search_web,exact_calculations,memories) run insrc/features/tools/, andget_locationsadds the death history from MongoDB. - The answer streams back. Afterwards the session is saved to MongoDB, sealed, folded into a summary when it grows too long, and the run's numbers land in MongoDB.
The bridge keeps pending calls in memory, so the backend runs as one instance.
| Path | What it does |
|---|---|
src/application/ |
Entrypoint, routes, shared dependencies |
src/features/chat/ |
POST /api/v2/chat: the SSE stream and the tool bridge |
src/features/ask, src/features/askx
|
v1 endpoints; their request and response shapes stay |
src/features/tools/ |
Client tool definitions (run by the plugin) and the server tools |
src/features/users/ |
Sessions and memories for /allay new, /allay memory, /allay forget; a player's export and erasure |
src/features/auth/ |
Who sent a request, and its tenant |
src/infrastructure/database/migrations.ts |
What runs on start, and the migrate command |
src/agent/ |
The agent runner, prompt assembly, the session summarizer, askx command validation |
src/prompts/*.md |
The system prompts, bundled into the build |
src/infrastructure/ |
Sessions, memories, deaths, players' state, and export links in MongoDB, sealed by crypto/data.ts; the OpenRouter provider; traces, sealed by observability/sealing.ts
|
src/features/billing/, src/infrastructure/billing/
|
Who pays, plans, licenses, budget windows, payments |
src/features/telegram/ |
The payment bot: Stars invoices, payments, renewals, refunds |
src/features/settings/ |
Every setting with its type, bounds, and default (settings.definitions.ts) |
src/features/admin/, src/infrastructure/admin/
|
The admin panel's API, accounts, sessions, the audit log |
admin/ |
The panel: React, Vite, shadcn/ui, TanStack Router and Query |
docs/protocol-v2.md |
The contract with the plugin |
The prompts live in src/prompts: minecraft-ask.md, minecraft-askx.md, minecraft-task.md for automation agents, and telegram.md. They ship inside the build. Each run appends who asks, their language, and the server version.
A setting is read through settings.get(...) where it's used: the environment first, then MongoDB, then the default. A save in the panel applies to the next run. Only what the backend needs to start reads process.env directly.
Everything is in MongoDB (since 6.8; Redis before):
- Players' data, sealed (since 6.9): chat sessions and their summaries, public and task threads (keyed by tenant first), memories and places, deaths, players' state, and the words in Mastra's traces.
-
In the clear: licenses and payments, admin accounts, panel sessions (by the cookie's digest), the audit log, stored settings (their secrets sealed), the
runscollection with its rollups (players as pseudonyms), the player directory that names pseudonyms for the panel, consents, and export links (by the token's digest).
Next: Building from source