Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
112 commits
Select commit Hold shift + click to select a range
80ec3b0
Remove v3 code and documents
prineycom Nov 9, 2026
acaa830
Add the voca agent package with the web entry
prineycom Nov 9, 2026
353c90c
Test the web entry and the import boundaries
prineycom Nov 9, 2026
e6197aa
Add the empty voca web page
prineycom Nov 9, 2026
346ee62
Add the stand environment and its example
prineycom Nov 9, 2026
b0f7d6c
Fetch and verify livekit-server by SHA256SUMS
prineycom Nov 9, 2026
c32e5ce
Start and stop the stand services
prineycom Nov 9, 2026
dafc8be
Add audio.cpp and llama-server placeholders for 0.2 and 0.3
prineycom Nov 9, 2026
31f70ee
Describe the bench directory
prineycom Nov 9, 2026
e14e041
Run CI on the v4 layout and flow branches
prineycom Nov 9, 2026
946320a
Document the v4 layout, checks and 0.1 reproduction
prineycom Nov 9, 2026
c7cd913
Pin vite 8.3.6 so the lock needs no release-age exclusions
prineycom Nov 9, 2026
4fd28f6
Pin the toolchain in mise.toml
prineycom Nov 9, 2026
c9f7f50
Check both LiveKit signalling paths like livekit-client
prineycom Nov 9, 2026
5e13621
Merge VOCA-2: Репозиторий и запуск (0.1)
prineycom Nov 9, 2026
c3cbd4c
Add httpx to the agent environment for the Hermes bench
prineycom Nov 9, 2026
9684dfb
Add the Hermes Runs API bench client for G7
prineycom Nov 9, 2026
1a6336f
Document the Hermes preflight (0.4) and its variables
prineycom Nov 9, 2026
de2ffbd
Keep the restart run longer than the gateway drain
prineycom Nov 9, 2026
1a02e65
Add the G7 report for the Hermes Runs API
prineycom Nov 9, 2026
c610471
Accept a cancelled run after a gateway restart
prineycom Nov 9, 2026
5e4aa92
Record the engineer's G7 decisions in the report
prineycom Nov 9, 2026
8423a5a
Pass backend-down when the run ends within the deadline
prineycom Nov 9, 2026
91f341a
Note backend-down under the fallback decision
prineycom Nov 9, 2026
63a801e
Quote the engineer's fallback decision in the G7 report
prineycom Nov 9, 2026
4c62da1
Merge VOCA-3: Hermes preflight — G7 (0.4)
prineycom Nov 9, 2026
518b276
Unpack whole archives with the untar source in fetch.sh
prineycom Nov 9, 2026
c267a42
List llama.cpp b11869 in SHA256SUMS
prineycom Nov 9, 2026
d713c37
List the Bolt-E4B UD-Q4_K_XL model in SHA256SUMS
prineycom Nov 9, 2026
6031328
Add VOCA_LLAMA_BIN for the llama.cpp release
prineycom Nov 9, 2026
4f0e312
Start llama-server with the profile B command
prineycom Nov 9, 2026
16a0793
Add livekit-agents with the openai plugin
prineycom Nov 9, 2026
d8d1350
Check chat_template_kwargs and tool_calls through openai.LLM
prineycom Nov 9, 2026
e36f680
Measure G3: Russian dialogs and delegate scenarios
prineycom Nov 9, 2026
adcc55f
Measure G4: TTFT and decode on 2K to 8K context
prineycom Nov 9, 2026
fe6fe6f
Report G3 and G4
prineycom Nov 9, 2026
7925431
Document the 0.3 LLM stand
prineycom Nov 9, 2026
a21124e
Measure the two-turn mechanic: fast phrase, then a thinking turn
prineycom Nov 9, 2026
e35a483
Report the two-turn mechanic and the engineer's decision
prineycom Nov 9, 2026
9e71bd0
List llm_two_turn.py in bench/README
prineycom Nov 9, 2026
5701124
Check B alone in the two-turn G3 criteria
prineycom Nov 9, 2026
02a5f47
Add the missing 8K warm-3 row to the G4 points table
prineycom Nov 9, 2026
bc90a99
Quote the engineer's two-turn decision exactly
prineycom Nov 9, 2026
f62714f
Recount two-turn G3 on the B text alone
prineycom Nov 9, 2026
93e7b9e
Mark two-turn G3 as not passed
prineycom Nov 9, 2026
b4bb663
Describe llm_common.py without a script count
prineycom Nov 9, 2026
e99fb8d
Merge VOCA-4: Стенд LLM — G3, G4 (0.3)
prineycom Nov 9, 2026
7ded963
Find tar members stored with a ./ prefix in fetch.sh
prineycom Nov 9, 2026
4b4b710
List audio.cpp 0.9.4 and its models in SHA256SUMS
prineycom Nov 9, 2026
5ab6d92
Add VOCA_AUDIOCPP_BIN to env.sh and .env.example
prineycom Nov 9, 2026
72b64dc
Serve Parakeet q8_0 offline and Supertonic with voice F1
prineycom Nov 9, 2026
24145f2
Start audiocpp_server through audiocpp.sh and up.sh audio
prineycom Nov 9, 2026
7f35cfb
Add livekit-plugins-silero for the StreamAdapter VAD
prineycom Nov 9, 2026
6e3b7c2
Add the shared audio bench module and the G1/G2 corpora
prineycom Nov 9, 2026
9eba224
Add stt_ru.py: samples, record, recordings, rtf5
prineycom Nov 9, 2026
ea693d9
Add tts_ru.py: check, render, listen, soak
prineycom Nov 9, 2026
a393f59
Add audio_parallel.py: STT during TTS and decode threads
prineycom Nov 9, 2026
99744a9
Run audiocpp_server with 6 threads, chosen by the decode measurement
prineycom Nov 9, 2026
294e080
Document the audio stand in README 0.2, AGENTS.md and bench/README
prineycom Nov 10, 2026
3207deb
Skip silent samples in stt_ru.py samples
prineycom Nov 10, 2026
0a75063
Read bench answers as bytes and accept the Russian layout
prineycom Nov 10, 2026
77f211d
List Parakeet v3 f16, the G1 fallback quant, in SHA256SUMS
prineycom Nov 10, 2026
99a4365
Take single-key answers in listen and keep one row per phrase and var…
prineycom Nov 10, 2026
6802cae
List Supertonic 3 f16, the G2 fallback, in SHA256SUMS
prineycom Nov 10, 2026
5713b64
Read notes with IUTF8 so backspace erases a whole Cyrillic letter
prineycom Nov 10, 2026
1051238
Add the tts_ru.py A/B of spelled-out numbers, f16, 16 steps and voices
prineycom Nov 10, 2026
d0ee136
Add the blind tts_ru.py ab2 of F4 quants and steps, with a stress-mar…
prineycom Nov 10, 2026
a216c95
Default the Supertonic voice to F4, chosen in the G2 listening
prineycom Nov 10, 2026
53a03d6
Add ruaccent 1.5.8.3 and its pinned models for text preparation befor…
prineycom Nov 10, 2026
4967acf
Add tts_pipeline.py: LLM reply, ruaccent stress and TTS to first sound
prineycom Nov 10, 2026
62e69b6
Document the G2 fallbacks, text preparation and the new bench commands
prineycom Nov 10, 2026
6b13569
Link ruaccent koziev through scripts/ruaccent-setup.sh and measure a …
prineycom Nov 10, 2026
6fa0053
Document scripts/ruaccent-setup.sh and tts_pipeline.py chunks
prineycom Nov 10, 2026
1f82268
Keep transformers below 5 so ruaccent stresses out-of-dictionary words
prineycom Nov 10, 2026
d84dcf0
Add tts_pipeline.py think: accuracy and first-sound delay with thinki…
prineycom Nov 10, 2026
4a09bac
Add tts_pipeline.py caps: capital stressed vowel at the start of a ph…
prineycom Nov 10, 2026
c8d5d8c
Document tts_pipeline.py think and caps and the transformers bound
prineycom Nov 10, 2026
e65d11a
Add tts_pipeline.py caps-listen
prineycom Nov 10, 2026
fd14fba
Fill the G1/G2 report: statuses, A/B rounds, the text path and wiring…
prineycom Nov 10, 2026
51a7d20
Report a missing tar member instead of exiting silently under pipefail
prineycom Nov 10, 2026
ce8ea60
Stop soak when render has no rows for the variant and voice
prineycom Nov 10, 2026
18accd6
Add tts_ru.py voiceprobe and apply the review notes to the report
prineycom Nov 10, 2026
a20c41a
Name voiceprobe among the commands that need the A/B server
prineycom Nov 10, 2026
a0df15d
Merge VOCA-5: Стенд аудио — G1, G2 (0.2)
prineycom Nov 10, 2026
9355334
Add llama.cpp b12167 and LFM3-1.7B Q4_K_M to SHA256SUMS
prineycom Nov 10, 2026
d07ac20
Default llama-server to b12167 and add VOCA_LLM_PROFILE
prineycom Nov 10, 2026
f73c552
Load the llm model from a VOCA_LLM_PROFILE profile
prineycom Nov 10, 2026
f0006d0
Take the bench model from /v1/models and write its results to its dir…
prineycom Nov 10, 2026
70f7ac1
Keep tts_pipeline think running when a reply has no content
prineycom Nov 10, 2026
7f5e860
Add the LFM3-1.7B report on the E0 cases
prineycom Nov 10, 2026
b1b960b
Document llama.cpp b12167 and the LLM profiles
prineycom Nov 10, 2026
f6e2112
Add think --digits and accept abbreviated digit answers
prineycom Nov 10, 2026
19174d7
Report LFM3-1.7B numbers as digits and recompute the recommendation
prineycom Nov 10, 2026
716f154
Fix the reply counts behind the timing stats in the LFM3 report
prineycom Nov 10, 2026
b568ad0
Merge VOCA-7: Стенд LFM3-1.7B на кейсах E0
prineycom Nov 10, 2026
3e02070
Add the LFM2.5-2.6B GGUF to SHA256SUMS
prineycom Nov 10, 2026
8ba2e51
Add the lfm2.5-2.6b llama-server profile
prineycom Nov 10, 2026
a0303e1
Report the LFM2.5-2.6B runs on the E0 cases
prineycom Nov 10, 2026
a3b8119
List the lfm2.5-2.6b profile and its report in the README
prineycom Nov 10, 2026
2f2152c
Quote reply 05 verbatim and source the LFM3 digit counts in the LFM2.…
prineycom Nov 10, 2026
a1f83cb
Merge VOCA-8: Стенд LFM2.5-2.6B на кейсах E0
prineycom Nov 10, 2026
4ea773d
Default the stand LLM profile to lfm2.5-2.6b
prineycom Nov 11, 2026
1e41464
Name lfm2.5-2.6b the default profile in .env.example
prineycom Nov 11, 2026
789f319
Mark lfm2.5-2.6b the default profile and bolt-e4b an alternative
prineycom Nov 11, 2026
fd29216
Rename DEFAULT_MODEL to ROOT_OUTPUT_MODEL in the bench
prineycom Nov 11, 2026
e442833
Name lfm2.5-2.6b the agent's model in the stand variables
prineycom Nov 11, 2026
05d4467
Describe LFM2.5-2.6B as the agent's model in README 0.3
prineycom Nov 11, 2026
7c718d6
Make lfm2.5-2.6b the default in README 0.3.1 and record the decision
prineycom Nov 11, 2026
a51595b
Say in the bench README which profile the stand starts
prineycom Nov 11, 2026
c1f8ffd
Merge VOCA-9: switch the agent's LLM to LFM2.5-2.6B
prineycom Nov 11, 2026
7567dbe
Note the later b12167 default in the G3/G4 report and mise trust in t…
prineycom Nov 11, 2026
1e2a57c
Merge VOCA-10: E0 documentation fixes before ship
prineycom Nov 11, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 40 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# VOCA stand settings. This is a bash file: only scripts/*.sh read it, through
# scripts/env.sh. Each line keeps a value already set in the environment.
# devkey/secret are the built-in keys of `livekit-server --dev`; they cannot be
# changed without a livekit-server config.

# Root of downloaded tools: <root>/<tool>/<version>/ (scripts/SHA256SUMS "apps").
VOCA_APPS_DIR="${VOCA_APPS_DIR:-$HOME/Apps}"
# Root of downloaded models (scripts/SHA256SUMS "models").
VOCA_MODELS_DIR="${VOCA_MODELS_DIR:-$HOME/models}"
# livekit-server release binary (scripts/fetch.sh puts it here).
VOCA_LIVEKIT_BIN="${VOCA_LIVEKIT_BIN:-$VOCA_APPS_DIR/livekit/1.13.11/livekit-server}"
# audio.cpp server release binary, CPU build 0.9.4 (scripts/fetch.sh puts it here).
VOCA_AUDIOCPP_BIN="${VOCA_AUDIOCPP_BIN:-$VOCA_APPS_DIR/audio.cpp/0.9.4/audiocpp_server}"
# llama-server of the llama.cpp CUDA release (scripts/fetch.sh puts it here; libraries sit next to it); b11869 is the build of the VOCA-4/5 measurements, kept in SHA256SUMS.
VOCA_LLAMA_BIN="${VOCA_LLAMA_BIN:-$VOCA_APPS_DIR/llama.cpp/llama-b12167/llama-server}"
# llama-server model profile: scripts/llm-profiles/<name>.sh; only this model is loaded. lfm2.5-2.6b is the agent's model (the default); bolt-e4b and lfm3-1.7b are alternatives.
VOCA_LLM_PROFILE="${VOCA_LLM_PROFILE:-lfm2.5-2.6b}"
# Address livekit-server announces for media (--node-ip).
VOCA_LIVEKIT_NODE_IP="${VOCA_LIVEKIT_NODE_IP:-127.0.0.1}"
# LiveKit API key that signs tokens (livekit-server --dev key).
VOCA_LIVEKIT_API_KEY="${VOCA_LIVEKIT_API_KEY:-devkey}"
# LiveKit API secret that signs tokens (livekit-server --dev secret).
VOCA_LIVEKIT_API_SECRET="${VOCA_LIVEKIT_API_SECRET:-secret}"
# Address voca web listens on.
VOCA_WEB_HOST="${VOCA_WEB_HOST:-127.0.0.1}"
# Port voca web listens on.
VOCA_WEB_PORT="${VOCA_WEB_PORT:-8083}"
# LiveKit URL the page receives with its token.
VOCA_PUBLIC_LIVEKIT_URL="${VOCA_PUBLIC_LIVEKIT_URL:-ws://127.0.0.1:7880}"

# voca.priney.com (deployment.md): uncomment to serve the stand over the tailnet.
# VOCA_WEB_HOST=100.108.140.49
# VOCA_LIVEKIT_NODE_IP=100.108.140.49
# VOCA_PUBLIC_LIVEKIT_URL=wss://voca.priney.com

# Hermes (VOCA-3, bench/hermes_runs.py): API server of the main Hermes profile; values in README "Воспроизведение с нуля" 0.4
# Hermes API URL; https://hermes.priney.com for the stand.
VOCA_HERMES_URL="${VOCA_HERMES_URL:-}"
# API_SERVER_KEY of the Hermes profile; never committed.
VOCA_HERMES_KEY="${VOCA_HERMES_KEY:-}"
44 changes: 23 additions & 21 deletions .github/workflows/checks.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,39 +3,41 @@ name: checks
on:
pull_request:
push:
branches: [main]
branches: [main, "flow/**"]

permissions:
contents: read

jobs:
app:
agent:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262
- uses: astral-sh/setup-uv@d0d8abe699bfb85fec6de9f7adb5ae17292296ff
with:
version: 0.12.4
- uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065
with:
python-version: 3.13.15
version: 0.12.23
- run: (cd agent && uv sync --locked --group dev)
- run: (cd agent && uv run --offline --no-sync ruff format --check src tests ../bench)
- run: (cd agent && uv run --offline --no-sync ruff check src tests ../bench)
- run: (cd agent && uv run --offline --no-sync mypy)
- run: (cd agent && uv run --offline --no-sync pytest -q)
- run: bash -n scripts/*.sh scripts/llm-profiles/*.sh
- run: git diff --check

web:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262
- uses: pnpm/action-setup@f40ffcd9367d9f12939873eb1018b921a783ffaa
with:
version: 10.34.5
package_json_file: web/package.json
- uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020
with:
node-version: 22.23.2
node-version: 24.21.0
cache: pnpm
cache-dependency-path: frontend/pnpm-lock.yaml
- run: (cd backend && uv sync --locked --group dev)
- run: pnpm --dir frontend install --frozen-lockfile
- run: (cd backend && uv run --offline --no-sync ruff format --check src tests)
- run: (cd backend && uv run --offline --no-sync ruff check src tests)
- run: (cd backend && uv run --offline --no-sync mypy src/voca)
- run: (cd backend && uv run --offline --no-sync pytest -q)
- run: pnpm --dir frontend format:check
- run: pnpm --dir frontend lint
- run: pnpm --dir frontend typecheck
- run: pnpm --dir frontend test
- run: pnpm --dir frontend build
- run: git diff --check
cache-dependency-path: web/pnpm-lock.yaml
- run: pnpm --dir web install --frozen-lockfile
- run: pnpm --dir web format:check
- run: pnpm --dir web lint
- run: pnpm --dir web typecheck
- run: pnpm --dir web build
5 changes: 3 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@ __pycache__/
.pytest_cache/
.mypy_cache/
.ruff_cache/
frontend/node_modules/
frontend/dist/
web/node_modules/
web/dist/
.local/
.env
.env.*
!.env.example
176 changes: 176 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,176 @@
# AGENTS.md — VOCA

VOCA v4 is a local voice assistant: LiveKit carries the voice, audio.cpp
recognises and speaks, llama-server answers, and longer work is delegated to
Hermes. This file is the working contract for agents and contributors.

## Layout

- `agent/` — the Python package `voca` (uv project, Python 3.13). `voca web`
serves the page, `GET /healthz` and `POST /api/token`.
- `web/` — the page (Vite + TypeScript, `livekit-client`); `pnpm --dir web build`
writes `web/dist/`, which `voca web` serves.
- `bench/` — stand scripts and their reports; they run in the `agent/`
environment (`bench/README.md`).
- `scripts/` — the stand: `up.sh`, `down.sh`, `fetch.sh`, `env.sh`, the
`SHA256SUMS` of every download, the audio.cpp `server.json` template and
`llm-profiles/`, one llama-server model profile per file.
- `.local/` — only what VOCA itself creates: logs, pid files, the assembled
`server.json`, recordings. Never committed.

## Checks

From the repository root:

```sh
(cd agent && uv sync --locked --group dev)
(cd agent && uv run --offline --no-sync ruff format --check src tests ../bench)
(cd agent && uv run --offline --no-sync ruff check src tests ../bench)
(cd agent && uv run --offline --no-sync mypy)
(cd agent && uv run --offline --no-sync pytest -q)
pnpm --dir web install --frozen-lockfile
pnpm --dir web format:check
pnpm --dir web lint
pnpm --dir web typecheck
pnpm --dir web build
bash -n scripts/*.sh scripts/llm-profiles/*.sh
git diff --check
```

The tests need no network, no models and no livekit-server. CI runs exactly
these commands and never starts the stand. `scripts/fetch.sh --check` checks the
stand's downloads; it is a stand check, not a CI check.

## Stand variables

`scripts/env.sh` is the only place of defaults; every script sources it. It reads
`.env` from the repository root when present. `.env` is a bash file (copy
`.env.example`), and a value already set in the environment wins over it.
`voca web` reads the `VOCA_*` variables from the environment that `scripts/env.sh`
exports; it does not read `.env` itself.

| Variable | Default | Meaning |
| --- | --- | --- |
| `VOCA_APPS_DIR` | `$HOME/Apps` | Root of downloaded tools, `apps/` in `SHA256SUMS` |
| `VOCA_MODELS_DIR` | `$HOME/models` | Root of downloaded models, `models/` in `SHA256SUMS` |
| `VOCA_LIVEKIT_BIN` | `$VOCA_APPS_DIR/livekit/1.13.11/livekit-server` | livekit-server release binary |
| `VOCA_AUDIOCPP_BIN` | `$VOCA_APPS_DIR/audio.cpp/0.9.4/audiocpp_server` | audio.cpp server release binary (CPU); its ggml libraries sit next to it |
| `VOCA_LLAMA_BIN` | `$VOCA_APPS_DIR/llama.cpp/llama-b12167/llama-server` | llama-server of the llama.cpp CUDA release; its libraries sit next to it |
| `VOCA_LLM_PROFILE` | `lfm2.5-2.6b` | llama-server model profile, `scripts/llm-profiles/<name>.sh`; only this model is loaded. `lfm2.5-2.6b` is the agent's model; `bolt-e4b` and `lfm3-1.7b` are alternatives, set explicitly |
| `VOCA_LIVEKIT_NODE_IP` | `127.0.0.1` | `--node-ip`: the address livekit-server announces for media |
| `VOCA_LIVEKIT_API_KEY` | `devkey` | Key that signs tokens; the built-in key of `livekit-server --dev` |
| `VOCA_LIVEKIT_API_SECRET` | `secret` | Secret that signs tokens; the built-in secret of `livekit-server --dev` |
| `VOCA_WEB_HOST` | `127.0.0.1` | Address `voca web` listens on |
| `VOCA_WEB_PORT` | `8083` | Port `voca web` listens on |
| `VOCA_PUBLIC_LIVEKIT_URL` | `ws://127.0.0.1:7880` | LiveKit URL returned with each token |
| `VOCA_HERMES_URL` | empty | Hermes API server URL for `bench/hermes_runs.py`; `https://hermes.priney.com` on the stand |
| `VOCA_HERMES_KEY` | empty | `API_SERVER_KEY` of the Hermes profile; a secret, only in `.env` |

Everything downloaded lives outside the clone, in the machine's shared
directories `~/Apps/<tool>/<version>/` and `~/models/`; a variable with that
default names each path. `devkey`/`secret` cannot change without a
livekit-server config.

## Downloads

`scripts/SHA256SUMS` lists every download, one file per line, fields separated
by spaces, `#` starts a comment:

```
<sha256> <root>/<tool>/<version>/<file> <source>
```

- `<root>`: `apps` resolves to `$VOCA_APPS_DIR`, `models` to `$VOCA_MODELS_DIR`.
The path is relative and has no `..`.
- `<source>`: `https://…` downloads the file; `tar:<archive>` extracts `<file>`
from `<archive>`, where the member is `<file>` or `./<file>`;
`untar:<archive>` unpacks the whole `<archive>` without its top-level
directory. The archive is in the same directory, listed on an earlier line.

`scripts/fetch.sh` walks the file in order. An existing file is verified and
never overwritten: a mismatch stops with «удалите файл и повторите». A missing
`https` file is downloaded to `<file>.part`, verified and moved in place; a
missing `tar:` file is extracted and verified. A missing `untar:` file unpacks
the whole archive into its directory without the archive's top-level directory,
keeping files that already exist, and is verified; the next lines of the same
archive then find their files and only verify them. Each line prints
`fetched <path>` or `ok <path>`. An unknown root, an absolute path or `..` stops
with the line number.

`scripts/fetch.sh --check` writes nothing and prints `OK`, `MISSING` or
`MISMATCH <path>` per line; it exits 1 when any line is not `OK`.

A new download (audio.cpp, llama-server, models) is one line in `SHA256SUMS`
plus a path variable with its default in `scripts/env.sh` and `.env.example`.

## Stand

`scripts/up.sh [livekit|audio|llm|web …]` (no arguments: all four) checks every
named service first and starts nothing when a check fails: the binary or build
exists, the service is not already running, its ports are free. It then starts
them in order with logs in `.local/logs/<name>.log` and pids in
`.local/run/<name>.pid`, and waits up to 20 s for each (120 s for `audio` and
`llm`). `scripts/down.sh [names…]` stops them in reverse order.

`scripts/audiocpp.sh [--check]` renders `scripts/server.json` into
`.local/server.json` with `envsubst '${VOCA_MODELS_DIR}'`, then checks that
`VOCA_AUDIOCPP_BIN` is executable, every model path in the rendered config exists
and its port (8082) is free; with `--check` it stops there. Otherwise it `exec`s
`audiocpp_server --config .local/server.json --no-ui` (README 0.2): Parakeet as
`asr` in `mode: offline`, Supertonic as `tts` in `mode: streaming` with voice `F4`.

`scripts/ruaccent-setup.sh` verifies the ruaccent `koziev/` files in
`$VOCA_MODELS_DIR/ruaccent/accentuator-b78ae5e/` against `SHA256SUMS` and links
them into the `ruaccent` package of `agent/.venv`; it is idempotent, and
`bench/tts_pipeline.py` stops without the link.

`scripts/llama.sh [--check]` sources the profile
`scripts/llm-profiles/$VOCA_LLM_PROFILE.sh` (README 0.3.1), which sets `model`
and `args`; an unknown profile or a missing profile file stops it. It then
checks that `VOCA_LLAMA_BIN` is executable, the profile's model exists and port
8081 is free; with `--check` it stops there. Otherwise it `exec`s llama-server
with the shared flags — `--alias "$VOCA_LLM_PROFILE"`, `--jinja`,
`127.0.0.1:8081`, `-c 16384`, `-fa on`, q8_0 KV cache, `--parallel 1`, `-t 2`,
all layers on the GPU — plus the profile's `args`. Extra arguments are
appended to the command. Sampling is set on the server by the profile, from
the model card; chat template kwargs come from the client.

livekit-server runs as `--dev --bind 0.0.0.0 --node-ip "$VOCA_LIVEKIT_NODE_IP"`.

`scripts/check-rtc.sh [page-url]` (default `http://$VOCA_WEB_HOST:$VOCA_WEB_PORT`)
checks LiveKit signalling as a real client would. It takes a token from
`<page-url>/api/token`, maps the returned `url` (`ws`/`wss`) to `http`/`https`,
and expects `200` from both validate paths of livekit-client:

- `/rtc/validate?access_token=<token>` — the v0 signal path;
- `/rtc/v1/validate?access_token=<token>&join_request=<…>` — the v1 path, which
livekit-server rejects with 400 `join_request is required` without the second
parameter.

`join_request` is generated, never hard-coded, the same way livekit-client 2.23
builds it in `createJoinRequestConnectionParams`: a `livekit.JoinRequest` with
`ClientInfo` (`sdk` JS, `version` from `web/package.json`, `protocol` 17 and
`client_protocol` 2 — the client's `protocolVersion` and `clientProtocol`) and
`ConnectionSettings(auto_subscribe=True)`, gzip-compressed into a
`livekit.WrappedJoinRequest` (`compression` GZIP), URL-safe base64. The protobuf
classes come from `livekit-api` in the `agent/` environment.

## Ports

| Port | Service |
| --- | --- |
| 7880 TCP | livekit-server HTTP and WebSocket signalling |
| 7881 TCP | livekit-server media over TCP |
| 7882 UDP | livekit-server media over UDP |
| 8083 TCP | `voca web` (`VOCA_WEB_PORT`) |
| 8082 TCP | audio.cpp server (127.0.0.1) |
| 8081 TCP | llama-server (127.0.0.1) |

Deviation from `derive:eb1id854:§1`: `voca web` listens on 8083, not 8090,
because 8090 is taken on the stand host (hyperhdr).

## References

- `derive:8kki4ynb` — target architecture v4.
- `derive:eb1id854` — detailed design.
- E0 epic research: https://draft.yokeloop.com/artifacts/voca-1-e0-llm-hermes-iim7wlw3
Loading
Loading