qqq 0.1.4

Quick Query Quorum: an in-memory multi-user chat with an AI facilitator
qqq-0.1.4 is not a library.

QQQ

Quick Query Quorum is a minimal, in-memory multi-user chat with an OpenAI-compatible AI facilitator. It provides one self-contained Rust binary and a browser interface with no database or frontend build step.

Sessions, credentials, history, and generated audio exist only in process memory and disappear on restart. Participant tokens remain in browser sessionStorage; they are sent as bearer credentials and never appear in URLs or session views.

The first interaction is a private AI conversation, not a group session. QQQ creates a joinable session only after the user explicitly requests a group conversation and provides a concrete group purpose. Display names and language are optional.

Install

Install the latest release from crates.io:

cargo install qqq

Create the configuration and start QQQ:

cp .env.example .env
# Set OPENAI_API_KEY and CHAT_MODEL for text mode.
qqq

Open http://127.0.0.1:8787 and press the orb.

To run directly from a checkout, use cargo run --release. Exported variables override values loaded from .env.

Docker

Release images are published for linux/amd64 and linux/arm64:

docker run --rm -p 8787:8787 \
  --env-file .env \
  -e QQQ_BIND=0.0.0.0:8787 \
  ghcr.io/maxylev/qqq:latest

Pin a version tag such as 0.1.2 in production. QQQ must bind to 0.0.0.0 inside a container for the published port to be reachable.

Configuration

Variable Default Purpose
QQQ_BIND 127.0.0.1:8787 Listener address
OPENAI_BASE_URL https://openrouter.ai/api/v1 OpenAI-compatible API base URL
OPENAI_API_KEY required Server-only provider credential
CHAT_MODEL required Chat-completion model
STT_MODEL unset Speech-to-text model; set with both TTS variables to enable voice mode
TTS_MODEL unset Text-to-speech model; set with STT model and TTS voice to enable voice mode
TTS_VOICE unset Text-to-speech voice; set with both model variables to enable voice mode
TTS_FORMAT mp3 Speech response format
OPENAI_HTTP_REFERER unset Optional provider attribution header
OPENAI_APP_TITLE unset Optional provider attribution header
MAX_SESSIONS 100 Maximum active in-memory sessions
MAX_PARTICIPANTS_PER_SESSION 8 Maximum participants per session
SESSION_TTL_SECONDS 14400 Idle session lifetime
MAX_HISTORY_MESSAGES 512 Append-only history limit
MAX_AUDIO_BYTES 10000000 Multipart audio upload limit
INPUT_BATCH_MS 350 Model input batching interval
DELIVERY_TIMEOUT_SECONDS 45 Delivery progress timeout
DEFAULT_LANGUAGE en Onboarding and STT fallback language
PRIVATE_CONVERSATION_PROMPT built-in private-assistant prompt Private onboarding system prompt; must preserve explicit group intent and concrete-purpose requirements
GROUP_SESSION_PROTOCOL_PROMPT built-in delivery protocol Appended to the model-generated, use-case-specific group prompt after promotion

The selected provider and base URL must support chat completions. Voice mode also requires speech generation and transcription.

API Model

Public routes are GET / and GET /health. POST /api/sessions initially creates a private provisional conversation; it becomes joinable and URL-addressable only after explicit promotion through bootstrap. Joining uses POST /api/sessions/:id/join. All other session routes require bearer authentication, including the WebSocket hello at /api/sessions/:id/ws.

History begins with one stable system message and is append-only. User messages preserve arrival order, and each assistant send_messages tool call remains paired with its tool result. Each session runs one model call at a time. Deliveries play in FIFO order. Each dispatch independently may update the displayed next-speaker hint when it completes; participant input remains open to every connected participant.

Development

Run the same checks as CI:

cargo fmt --all -- --check
cargo clippy --all-targets --all-features -- -D warnings
cargo test --all-features
cargo package --locked
docker build -t qqq:dev .

Offline tests exercise in-process Axum routes, authorization, multipart and raw audio validation, delivery transitions, and WebSocket semantics.

Live Provider Tests

Ignored live tests use real provider requests and spend credits. Put credentials and model names in the ignored .env.test, then source it without printing its contents:

set -a
source .env.test
set +a
cargo test live_ -- --ignored --test-threads=1

The paid suite validates private-to-group promotion, a generic three-participant dispatch scenario, forced tool calls, and a real TTS-to-STT round trip. A manually dispatched Live provider E2E GitHub workflow runs the same checks with secrets from the protected openrouter-e2e environment.

HTTPS And Limits

Mobile microphone access requires trusted HTTPS. Terminate TLS at a same-origin reverse proxy; QQQ intentionally does not implement TLS:

location / {
    proxy_pass http://127.0.0.1:8787;
    proxy_http_version 1.1;
    proxy_set_header Host $host;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
}

QQQ intentionally provides one process with no persistence, accounts, recovery, audio broadcast, database, or history truncation. A session closes when it reaches its history limit.

License

QQQ is available under the MIT License.