Aokie Receptionist Kit — a Windows app + certified USB Bluetooth dongle that turns your existing phone into an AI-answered reception line. Pair your phone to Aokie as a Bluetooth hands-free device using the bundled dongle (see the compatibility matrix below — Aokie talks WinUSB directly to specific chipsets, not the generic Windows Bluetooth stack); incoming cellular calls route their audio to the PC over Bluetooth HFP, and Aokie answers them with a local LLM + TTS pipeline. Aokie also handles SMS over Bluetooth MAP, greets known callers by name via PBAP, and can drive an appointment-booking and ordering flow from inside the call. By default everything runs on-device — no cloud, no API keys, no companion app — but the AI providers are pluggable so you can swap in an OpenAI-compatible HTTP endpoint or run llama.cpp as a sidecar if you'd rather.
Scope in one line: Windows PC + certified Bluetooth dongle + one paired phone + one call at a time. Built for sole-trader and small- business reception flows. Multi-line / call-queue / multi-device is deliberately out of scope.
One call at a time. Aokie pairs to a single phone over HFP and serves one in-progress call. There's one SCO link per active call, one transcription stream, one LLM turn loop. A second incoming call while the first is live goes to the phone's voicemail (or whatever the carrier's busy-signal behaviour is). Multi-line / call-queue support isn't on the roadmap — Aokie is built for sole-trader and small-business reception flows where missing a second simultaneous call is preferable to a half-handled one.
Platform support: Windows is the supported target. Linux is a developer preview — the libusb transport, udev rule renderer, and diagnostic commands work end-to-end in the Rust stack, but packaging, pkexec udev install, and end-to-end SCO audio on real Linux hardware are still outstanding. Run on Windows for any production use; treat Linux Aokie as a contributor-only build until that work lands.
Every turn, every SMS, every booking, and every order is logged to SQLite so the History page and the Messages / Appointments / Orders pages all show live state.
The Bluetooth stack is dongle-aware: HFP codec selection, SCO transfer sizing, and PCM endpoint quirks vary by chip family. We test against what we can verify, and grade other dongles by what's known to work versus what's known to misbehave.
| Status | Chipset / dongle | What works | Known limitations |
|---|---|---|---|
| Certified | Broadcom BCM20702A0 (0a5c:21ec) | HFP (mSBC + CVSD), SCO, MAP, PBAP, MNS push | None blocking. Occasional Win32-87 stream resets at TTS-pause boundaries (auto-recovers). |
| Beta | Realtek RTL8761 family (0bda:8761 and kin) | HFP, MAP, PBAP | mSBC requires AOKIE_HFP_CODEC=wbs to force the transparent voice setting. CVSD-only fallback is unreliable on stock firmware. |
| Beta | CSR8510 (0a12:0001) | HFP, MAP, PBAP | SCO TX FIFO underruns more often than Broadcom; expect occasional clicks at long TTS pauses. |
| Unsupported | Built-in laptop Bluetooth (Intel AX2xx / AX3xx) | n/a | Aokie needs exclusive WinUSB ownership of the dongle, which orphans every other Bluetooth profile in Windows for the duration. Use a dedicated USB dongle instead. |
| Unsupported | Apple AirPods / Bluetooth speakers | n/a | Aokie pairs with a phone (HFP audio gateway), not headsets. The host role is the receptionist, not the listener. |
If your dongle isn't listed, Aokie will probably enumerate and run, but HFP audio quality, MAP/PBAP timing, and SCO error rates are not guaranteed. The Pairing page's diagnostic runtime button captures the controller report and event stream so a debug session can confirm end-to-end connectivity before going live.
RCS messages won't reach Aokie — disable RCS or accept SMS-only on the paired phone. Bluetooth MAP only carries SMS/MMS; there is no Bluetooth-side path for RCS (Pixel-to-Pixel chat, Google Messages "chat features", Apple's iMessage-style RCS). When RCS is enabled on the paired phone, the carrier may auto-upgrade an SMS thread to RCS without warning, after which Aokie will see the MNS session open and then go dead silent — new messages just never arrive. On Pixel / Android: open Google Messages → Settings → RCS chats and turn it off, or pair a phone whose default messaging app is SMS-only. This is a platform limitation, not an Aokie bug; the only fix is for one of the OS / carrier / Bluetooth-MAP spec stakeholders to add a path, which currently does not exist. See
docs/TROUBLESHOOTING.mdfor the full diagnosis flow.
Other limitations worth knowing up-front:
aokie_radio: a from-scratch Rust HCI / L2CAP /
RFCOMM / SCO / SDP / OBEX / HFP / MAP / PBAP stack that talks to
the dongle directly over WinUSB. No vendored C, no FFI shim.
Includes a pairing store, eSCO with mSBC wide-band + CVSD
fallback, and a cargo run --bin aokie-radio-diag tool for
bring-up (Windows only — the binary exit(1)s on other platforms;
Linux uses the Tauri-side diagnostic commands instead). SCO iso submission, voice setting, alt selection, and
Broadcom vendor routing mirror BTstack's USB transport (hci.c +
hci_transport_h2_winusb.c) — see ISSUES.md for the audit
history if you need to add support for a new chipset.aokie_dongle: Rust SetupAPI enumeration plus a
generated WinUSB INF that's installed by aokie-driver-helper (an
elevated sidecar pointed at by the AOKIE_WINUSB_HELPER env var).ai::{LlmProvider, TtsProvider, SttProvider} traits with adapters for the catalogue below. Active
provider is picked per-surface from <app_data>/ai_providers.json
and is hot-swappable at runtime via Settings → AI Providers.rustfft mel front-end matching torch.stft(center=True).Qwen 3.5 4B Q4_K_M (GGUF) from the catalogue
to route through the bundled llama-server sidecar (text-only),
or OpenAI-compatible HTTP for any remote / LM Studio / Ollama
endpoint. Provider switch unloads the previous in-process runtime
immediately so memory drops on save.ort + rustfft pipeline, supports .safetensors
voice states and reference-wav cloning via the mimi_encoder).
Or Sherpa-onnx TTS — VITS / Piper / Kokoro voice bundles
via sherpa-onnx, broader voice catalogue at the cost of bundle
download size.sherpa-rs for endpoint detection during calls.AOKIE_VERBOSE_LOGS=1.website/ Marketing / sales site (Vite + React + TS,
│ handwritten CSS, editorial aesthetic)
aokie-desktop/
├── src/ React frontend
│ ├── pages/ Dashboard · Pairing · Settings · AI Stack ·
│ │ Messages · Appointments · Orders · History · Call Detail
│ ├── stores/ Zustand stores (call / transcript / connection /
│ │ config / toast / theme)
│ └── hooks/ useAppInit, useBluetooth, …
└── src-tauri/ Rust backend
└── src/
├── ai/ Provider trait + adapters (LLM / TTS / STT)
│ ├── adapters/ OnnxGenAi, HttpOpenAi, OnnxTts, SherpaOnnx*, WhisperCandle
│ └── runtimes/ Heavy modules each adapter wraps
├── commands/ Tauri commands (Bluetooth / USB / ML / call log /
│ SMS / calendar / orders / AI config)
├── sidecars/ External-process lifecycle (llama_server)
├── bluetooth/ Thin wrapper over aokie_radio
├── aokie_radio/ From-scratch HCI/L2CAP/RFCOMM/SCO/SDP/OBEX/HFP/MAP/PBAP
│ ├── obex.rs, bmessage.rs, vcard.rs
│ ├── map_*.rs MAS read, MNS push, MAP listing, runtime driver
│ └── pbap.rs, pbap_runtime.rs
├── aokie_dongle/ USB dongle enumeration + WinUSB INF generator
├── bin/aokie-driver-helper.rs Elevated WinUSB driver-installer helper (validated args)
├── bin/aokie-radio-diag.rs CLI for hardware bring-up + diagnostics
├── calendar/ Bookings + service catalogue
├── orders/ Products + order lifecycle
├── msbc/ Pure-Rust SBC + H2 framing for mSBC SCO
├── vad/ Silero VAD wrapper
├── redact.rs Phone / Text Display wrappers (PII off by default)
├── notepad.rs Continuous caller transcription buffer
├── streaming.rs Sentence extractor + streaming TTS controller
└── database/ SQLite schema + migrations + central open helper
npmdefault = ["custom-protocol", "sherpa"] in
aokie-desktop/src-tauri/Cargo.toml. The sherpa feature pulls in
sherpa-rs-sys, which CMake-builds espeak-ng + piper-phonemize +
cppjieba + openfst from source on first compile (~5 min cold).
Stock VS Build Tools handles this on a dev box; if you want a
faster bring-up build, opt out with
--no-default-features --features custom-protocol — Aokie falls
back to stub Sherpa runtimes whose load() returns "feature not
compiled in" (the rest of the provider stack — Pocket-TTS, Whisper,
Parakeet, Moonshine, Qwen3-ASR, llama-server — keeps working).
CUDA isn't needed: Gemma 4 on CPU is slower than GPU but Whisper
and Pocket-TTS are fine.cuda cargo feature for
GPU-accelerated Gemma 4. See docs/CUDA_SETUP.md for the toolkit
layout and the bundle-resource overrides needed for a CUDA release.0a5c:21ec) verified
end-to-end with bidirectional mSBC SCO; other WinUSB-capable
adapters should work after running the in-app driver installer,
but only Broadcom 21ec has been exercised through the full call
flow so far.cd aokie-desktop
npm install
npm run tauri:dev
npm run tauri:dev runs scripts/dev-with-port.mjs, which probes for
a free port starting at 5173 and pins Vite + Tauri to it. Plain
npm run tauri dev works too but can fail when an old Vite server
is still bound to the configured port.
CUDA isn't in the default feature set, so opt in by passing cargo args
through the tauri-cli's -- separator:
cd aokie-desktop
npm install
npm run tauri:dev -- -- --features cuda
For a CUDA release bundle, override bundle.resources at build time
so the cuDNN family + provider DLLs ship alongside the exe — see the
inline note in aokie-desktop/src-tauri/Cargo.toml next to the cuda
feature for the full resource list, and docs/CUDA_SETUP.md for how
to populate aokie-desktop/src-tauri/resources/ with the DLLs.
On first launch, open Settings → AI Stack and download the model files. The default catalogue pulls ~7 GB total — Gemma 4 E4B (≈5.5 GB), Whisper (≈1.5 GB), Pocket-TTS (≈250 MB). Plan for ~15-30 minutes on a typical home connection; the AI Stack page reports per-file progress and resumes interrupted downloads on retry. The smaller catalogue entries (Gemma 4 E2B at ≈2.5 GB, Qwen 3.5 4B GGUF at ≈2.5 GB) are listed in the AI Providers picker if you'd rather trade quality for download size on a slow link. Then in Pairing:
Place a test call. The caller's audio routes to Aokie instead of the phone's earpiece, the AI greeting plays into the caller's earpiece, and Aokie transcribes each turn live. Post-call extraction lands any bookings or orders the caller arranged into the dashboard.
All runtime config (system prompt, greeting, voice selection, auto-answer
delay) lives in Settings, persists via Zustand persist, and is mirrored
to disk so the Rust backend can read it on startup. The SQLite schema is
created automatically on first run under the app data directory.
The active AI providers (LLM / TTS / STT) are picked from the
bundled defaults plus an optional override at
<app_data>/ai_providers.json. Set the kind field per surface to
swap engines:
| Surface | Built-in kind values |
|---|---|
llm | onnx-genai (in-process Gemma 4) · openai-http (any OpenAI-compatible endpoint) · llama-server (bundled llama.cpp sidecar — pulls a GGUF and serves it over HTTP locally) |
tts | onnx-tts (in-process Pocket-TTS) · sherpa-onnx-tts (VITS / Piper / Kokoro) |
stt | whisper-candle (in-process Whisper) · sherpa-onnx-stt (Whisper bundles via sherpa) · parakeet-onnx (NVIDIA Parakeet-Unified-EN-0.6B FastConformer + RNN-T) · moonshine-onnx (UsefulSensors Moonshine, encoder-decoder seq2seq) · qwen3-asr-onnx (Alibaba Qwen3-ASR-0.6B, multilingual) |
Edit, save, and the cache hot-reloads — no app restart needed. The
startup warm-up only loads the in-process runtime that matches the
active kind, so switching to openai-http doesn't waste GPU memory
on an unused Gemma load.
The warm-up itself is also opt-out: Settings → AI model warm-up
flips between "Fast calls" (preload Whisper / Gemma / Pocket-TTS at
launch — first call answers without model-load latency) and "Fast
startup" (defer the warm to first inference — the launch-to-
dashboard window is shorter and idle memory is smaller, in
exchange for a multi-second first-call latency). Each
initialize_* command is idempotent, so deferring is safe.
CI runs in three tiers: fast Linux gates on every push/PR, Windows shape coverage on Windows-relevant push/PR, and dependency audits on a weekly cron + manual dispatch. The split keeps round-trip latency tolerable on JS-only / docs-only changes (Linux Rust + Vite finish in ~3-8 min cached) while still gating Bluetooth / WinUSB / Tauri-config changes on the slower Windows runner.
frontend-fast (ubuntu-latest) (every push/PR) — ESLint,
build-mode tsc -b (catches tsconfig.node.json drift tsc --noEmit would miss), and a Vite production build.frontend-windows (windows-latest) (manual / scheduled) —
Same checks on a Windows runner; catches Win32-specific frontend
regressions (path separators, CRLF, native-dep build errors).
Manual because cold runner is 8-12 min and CRLF rarely breaks.rust-fast (ubuntu-latest) (every push/PR) — cargo fmt --check + cargo check --lib + cargo test --lib for the
cross-platform code (parsers, msbc, MAP/PBAP wire-format,
calendar, orders, redact, fuzz harnesses).rust-windows (windows-latest) (auto on push/PR touching
aokie-desktop/src-tauri/** or this workflow; manual dispatch
for ad-hoc runs) — cargo check/test on the full lib and
the aokie-driver-helper bin under --no-default-features --features custom-protocol. The sherpa cargo feature is
opt-out: with it off, sherpa-rs-sys's CMake build (which
windows-latest can't satisfy without ZLIB / ICU dev libs) is
skipped and the runtime falls back to stub SherpaOnnxTtsRuntime
/ SherpaOnnxSttRuntime / StreamingVad impls. That catches
Windows regressions in the WinUSB transport, aokie_dongle, the
SetupAPI / WinTrust / catalog-sign surfaces, and any windows- sys version drift. Production Windows release builds keep
default = ["custom-protocol", "sherpa"] and still pull
sherpa-rs in for the full provider catalogue.audit-rust (weekly cron + manual) — cargo audit --deny warnings plus cargo deny check. Off the PR critical path so
cycles don't page on every transitive-dep advisory.audit-js (weekly cron + manual) — npm audit --audit-level=high. Same
off-the-PR-path rationale.No remaining Windows lib-coverage gap — the sherpa feature gate
let CI's Windows job compile and test the full lib. The only
Windows-specific path still skipped on CI is hardware-in-loop
testing (real BT dongle, real SCO audio); that stays a manual /
nightly step on the dev box.
aokie-desktop/src-tauri/.cargo/config.toml carries Windows-specific
build settings (target-dir = "C:\\t" MAX_PATH workaround + Visual
Studio 2022 CMake generator pins). cargo's [env] table is
non-forcing, so contributors on Linux / macOS can override
CARGO_TARGET_DIR and the CMAKE_GENERATOR* vars in their shell
without editing the file.
End-to-end happy path is verified: pair → answer → bidirectional
mSBC audio → Whisper / Gemma / Pocket-TTS turns → MAP message
push → post-call booking extraction. See ISSUES.md for the
current open list (low-severity at time of writing — Win32 87
bursts during heavy SCO TX, ACL accumulator desync during long
MAP messages; both auto-recover and don't block calls).
For the consolidated "what's shippable today, what's pilot-only,
what blocks public release" view (signing status, hardware support,
CI gates, pre-ship checklist, recording opt-in story), see
docs/RELEASE_READINESS.md. It's the
single source of truth — other docs should point back to it instead
of re-stating release status.
%APPDATA%/com.aokie.app/ on Windows,
~/.local/share/com.aokie.app/ on Linux) has the details.db-error event when they fail; the toast is the surface. Common
cause is a locked DB (some other process holding the file).0000 fallback). The bounded runtime drives ACL / SDP / RFCOMM / HFP
responses, accepts SCO/eSCO links, reports incoming PCM stats, auto-answers
when AOKIE_RADIO_AUTO_ANSWER=1, writes SCO silence when
AOKIE_RADIO_SCO_TX_SILENCE=1, and writes a 440 Hz test tone when
AOKIE_RADIO_SCO_TX_TONE=1. Diagnostic link keys persist under the app
data directory at aokie_radio/pairing_store.json. The same hardware
checks are available from the terminal on Windows with
cargo run --bin aokie-radio-diag -- hci-interfaces,
probe, init, or runtime 5 from aokie-desktop/src-tauri. The
binary refuses to run on Linux / macOS — those platforms have access
to the same diagnostics through the in-app aokie_radio_* Tauri
commands instead.
Set AOKIE_RADIO_DUMP=1 for transport-level hex dumps while testing
hardware. Set AOKIE_VERBOSE_LOGS=1 to disable PII redaction in
logs (off by default — phone numbers + message bodies + transcripts
mask).This project is proprietary to Aokie (aokie.com).
406 commits
Rust
78.0%
TypeScript
17.9%
JavaScript
2.5%
Aokie Receptionist Kit — a Windows app + certified USB Bluetooth dongle that turns your existing phone into an AI-answered reception line. Pair your phone to Aokie as a Bluetooth hands-free device using the bundled dongle (see the compatibility matrix below — Aokie talks WinUSB directly to specific chipsets, not the generic Windows Bluetooth stack); incoming cellular calls route their audio to the PC over Bluetooth HFP, and Aokie answers them with a local LLM + TTS pipeline. Aokie also handles SMS over Bluetooth MAP, greets known callers by name via PBAP, and can drive an appointment-booking and ordering flow from inside the call. By default everything runs on-device — no cloud, no API keys, no companion app — but the AI providers are pluggable so you can swap in an OpenAI-compatible HTTP endpoint or run llama.cpp as a sidecar if you'd rather.
Scope in one line: Windows PC + certified Bluetooth dongle + one paired phone + one call at a time. Built for sole-trader and small- business reception flows. Multi-line / call-queue / multi-device is deliberately out of scope.
One call at a time. Aokie pairs to a single phone over HFP and serves one in-progress call. There's one SCO link per active call, one transcription stream, one LLM turn loop. A second incoming call while the first is live goes to the phone's voicemail (or whatever the carrier's busy-signal behaviour is). Multi-line / call-queue support isn't on the roadmap — Aokie is built for sole-trader and small-business reception flows where missing a second simultaneous call is preferable to a half-handled one.
Platform support: Windows is the supported target. Linux is a developer preview — the libusb transport, udev rule renderer, and diagnostic commands work end-to-end in the Rust stack, but packaging, pkexec udev install, and end-to-end SCO audio on real Linux hardware are still outstanding. Run on Windows for any production use; treat Linux Aokie as a contributor-only build until that work lands.
Every turn, every SMS, every booking, and every order is logged to SQLite so the History page and the Messages / Appointments / Orders pages all show live state.
The Bluetooth stack is dongle-aware: HFP codec selection, SCO transfer sizing, and PCM endpoint quirks vary by chip family. We test against what we can verify, and grade other dongles by what's known to work versus what's known to misbehave.
| Status | Chipset / dongle | What works | Known limitations |
|---|---|---|---|
| Certified | Broadcom BCM20702A0 (0a5c:21ec) | HFP (mSBC + CVSD), SCO, MAP, PBAP, MNS push | None blocking. Occasional Win32-87 stream resets at TTS-pause boundaries (auto-recovers). |
| Beta | Realtek RTL8761 family (0bda:8761 and kin) | HFP, MAP, PBAP | mSBC requires AOKIE_HFP_CODEC=wbs to force the transparent voice setting. CVSD-only fallback is unreliable on stock firmware. |
| Beta | CSR8510 (0a12:0001) | HFP, MAP, PBAP | SCO TX FIFO underruns more often than Broadcom; expect occasional clicks at long TTS pauses. |
| Unsupported | Built-in laptop Bluetooth (Intel AX2xx / AX3xx) | n/a | Aokie needs exclusive WinUSB ownership of the dongle, which orphans every other Bluetooth profile in Windows for the duration. Use a dedicated USB dongle instead. |
| Unsupported | Apple AirPods / Bluetooth speakers | n/a | Aokie pairs with a phone (HFP audio gateway), not headsets. The host role is the receptionist, not the listener. |
If your dongle isn't listed, Aokie will probably enumerate and run, but HFP audio quality, MAP/PBAP timing, and SCO error rates are not guaranteed. The Pairing page's diagnostic runtime button captures the controller report and event stream so a debug session can confirm end-to-end connectivity before going live.
RCS messages won't reach Aokie — disable RCS or accept SMS-only on the paired phone. Bluetooth MAP only carries SMS/MMS; there is no Bluetooth-side path for RCS (Pixel-to-Pixel chat, Google Messages "chat features", Apple's iMessage-style RCS). When RCS is enabled on the paired phone, the carrier may auto-upgrade an SMS thread to RCS without warning, after which Aokie will see the MNS session open and then go dead silent — new messages just never arrive. On Pixel / Android: open Google Messages → Settings → RCS chats and turn it off, or pair a phone whose default messaging app is SMS-only. This is a platform limitation, not an Aokie bug; the only fix is for one of the OS / carrier / Bluetooth-MAP spec stakeholders to add a path, which currently does not exist. See
docs/TROUBLESHOOTING.mdfor the full diagnosis flow.
Other limitations worth knowing up-front:
aokie_radio: a from-scratch Rust HCI / L2CAP /
RFCOMM / SCO / SDP / OBEX / HFP / MAP / PBAP stack that talks to
the dongle directly over WinUSB. No vendored C, no FFI shim.
Includes a pairing store, eSCO with mSBC wide-band + CVSD
fallback, and a cargo run --bin aokie-radio-diag tool for
bring-up (Windows only — the binary exit(1)s on other platforms;
Linux uses the Tauri-side diagnostic commands instead). SCO iso submission, voice setting, alt selection, and
Broadcom vendor routing mirror BTstack's USB transport (hci.c +
hci_transport_h2_winusb.c) — see ISSUES.md for the audit
history if you need to add support for a new chipset.aokie_dongle: Rust SetupAPI enumeration plus a
generated WinUSB INF that's installed by aokie-driver-helper (an
elevated sidecar pointed at by the AOKIE_WINUSB_HELPER env var).ai::{LlmProvider, TtsProvider, SttProvider} traits with adapters for the catalogue below. Active
provider is picked per-surface from <app_data>/ai_providers.json
and is hot-swappable at runtime via Settings → AI Providers.rustfft mel front-end matching torch.stft(center=True).Qwen 3.5 4B Q4_K_M (GGUF) from the catalogue
to route through the bundled llama-server sidecar (text-only),
or OpenAI-compatible HTTP for any remote / LM Studio / Ollama
endpoint. Provider switch unloads the previous in-process runtime
immediately so memory drops on save.ort + rustfft pipeline, supports .safetensors
voice states and reference-wav cloning via the mimi_encoder).
Or Sherpa-onnx TTS — VITS / Piper / Kokoro voice bundles
via sherpa-onnx, broader voice catalogue at the cost of bundle
download size.sherpa-rs for endpoint detection during calls.AOKIE_VERBOSE_LOGS=1.website/ Marketing / sales site (Vite + React + TS,
│ handwritten CSS, editorial aesthetic)
aokie-desktop/
├── src/ React frontend
│ ├── pages/ Dashboard · Pairing · Settings · AI Stack ·
│ │ Messages · Appointments · Orders · History · Call Detail
│ ├── stores/ Zustand stores (call / transcript / connection /
│ │ config / toast / theme)
│ └── hooks/ useAppInit, useBluetooth, …
└── src-tauri/ Rust backend
└── src/
├── ai/ Provider trait + adapters (LLM / TTS / STT)
│ ├── adapters/ OnnxGenAi, HttpOpenAi, OnnxTts, SherpaOnnx*, WhisperCandle
│ └── runtimes/ Heavy modules each adapter wraps
├── commands/ Tauri commands (Bluetooth / USB / ML / call log /
│ SMS / calendar / orders / AI config)
├── sidecars/ External-process lifecycle (llama_server)
├── bluetooth/ Thin wrapper over aokie_radio
├── aokie_radio/ From-scratch HCI/L2CAP/RFCOMM/SCO/SDP/OBEX/HFP/MAP/PBAP
│ ├── obex.rs, bmessage.rs, vcard.rs
│ ├── map_*.rs MAS read, MNS push, MAP listing, runtime driver
│ └── pbap.rs, pbap_runtime.rs
├── aokie_dongle/ USB dongle enumeration + WinUSB INF generator
├── bin/aokie-driver-helper.rs Elevated WinUSB driver-installer helper (validated args)
├── bin/aokie-radio-diag.rs CLI for hardware bring-up + diagnostics
├── calendar/ Bookings + service catalogue
├── orders/ Products + order lifecycle
├── msbc/ Pure-Rust SBC + H2 framing for mSBC SCO
├── vad/ Silero VAD wrapper
├── redact.rs Phone / Text Display wrappers (PII off by default)
├── notepad.rs Continuous caller transcription buffer
├── streaming.rs Sentence extractor + streaming TTS controller
└── database/ SQLite schema + migrations + central open helper
npmdefault = ["custom-protocol", "sherpa"] in
aokie-desktop/src-tauri/Cargo.toml. The sherpa feature pulls in
sherpa-rs-sys, which CMake-builds espeak-ng + piper-phonemize +
cppjieba + openfst from source on first compile (~5 min cold).
Stock VS Build Tools handles this on a dev box; if you want a
faster bring-up build, opt out with
--no-default-features --features custom-protocol — Aokie falls
back to stub Sherpa runtimes whose load() returns "feature not
compiled in" (the rest of the provider stack — Pocket-TTS, Whisper,
Parakeet, Moonshine, Qwen3-ASR, llama-server — keeps working).
CUDA isn't needed: Gemma 4 on CPU is slower than GPU but Whisper
and Pocket-TTS are fine.cuda cargo feature for
GPU-accelerated Gemma 4. See docs/CUDA_SETUP.md for the toolkit
layout and the bundle-resource overrides needed for a CUDA release.0a5c:21ec) verified
end-to-end with bidirectional mSBC SCO; other WinUSB-capable
adapters should work after running the in-app driver installer,
but only Broadcom 21ec has been exercised through the full call
flow so far.cd aokie-desktop
npm install
npm run tauri:dev
npm run tauri:dev runs scripts/dev-with-port.mjs, which probes for
a free port starting at 5173 and pins Vite + Tauri to it. Plain
npm run tauri dev works too but can fail when an old Vite server
is still bound to the configured port.
CUDA isn't in the default feature set, so opt in by passing cargo args
through the tauri-cli's -- separator:
cd aokie-desktop
npm install
npm run tauri:dev -- -- --features cuda
For a CUDA release bundle, override bundle.resources at build time
so the cuDNN family + provider DLLs ship alongside the exe — see the
inline note in aokie-desktop/src-tauri/Cargo.toml next to the cuda
feature for the full resource list, and docs/CUDA_SETUP.md for how
to populate aokie-desktop/src-tauri/resources/ with the DLLs.
On first launch, open Settings → AI Stack and download the model files. The default catalogue pulls ~7 GB total — Gemma 4 E4B (≈5.5 GB), Whisper (≈1.5 GB), Pocket-TTS (≈250 MB). Plan for ~15-30 minutes on a typical home connection; the AI Stack page reports per-file progress and resumes interrupted downloads on retry. The smaller catalogue entries (Gemma 4 E2B at ≈2.5 GB, Qwen 3.5 4B GGUF at ≈2.5 GB) are listed in the AI Providers picker if you'd rather trade quality for download size on a slow link. Then in Pairing:
Place a test call. The caller's audio routes to Aokie instead of the phone's earpiece, the AI greeting plays into the caller's earpiece, and Aokie transcribes each turn live. Post-call extraction lands any bookings or orders the caller arranged into the dashboard.
All runtime config (system prompt, greeting, voice selection, auto-answer
delay) lives in Settings, persists via Zustand persist, and is mirrored
to disk so the Rust backend can read it on startup. The SQLite schema is
created automatically on first run under the app data directory.
The active AI providers (LLM / TTS / STT) are picked from the
bundled defaults plus an optional override at
<app_data>/ai_providers.json. Set the kind field per surface to
swap engines:
| Surface | Built-in kind values |
|---|---|
llm | onnx-genai (in-process Gemma 4) · openai-http (any OpenAI-compatible endpoint) · llama-server (bundled llama.cpp sidecar — pulls a GGUF and serves it over HTTP locally) |
tts | onnx-tts (in-process Pocket-TTS) · sherpa-onnx-tts (VITS / Piper / Kokoro) |
stt | whisper-candle (in-process Whisper) · sherpa-onnx-stt (Whisper bundles via sherpa) · parakeet-onnx (NVIDIA Parakeet-Unified-EN-0.6B FastConformer + RNN-T) · moonshine-onnx (UsefulSensors Moonshine, encoder-decoder seq2seq) · qwen3-asr-onnx (Alibaba Qwen3-ASR-0.6B, multilingual) |
Edit, save, and the cache hot-reloads — no app restart needed. The
startup warm-up only loads the in-process runtime that matches the
active kind, so switching to openai-http doesn't waste GPU memory
on an unused Gemma load.
The warm-up itself is also opt-out: Settings → AI model warm-up
flips between "Fast calls" (preload Whisper / Gemma / Pocket-TTS at
launch — first call answers without model-load latency) and "Fast
startup" (defer the warm to first inference — the launch-to-
dashboard window is shorter and idle memory is smaller, in
exchange for a multi-second first-call latency). Each
initialize_* command is idempotent, so deferring is safe.
CI runs in three tiers: fast Linux gates on every push/PR, Windows shape coverage on Windows-relevant push/PR, and dependency audits on a weekly cron + manual dispatch. The split keeps round-trip latency tolerable on JS-only / docs-only changes (Linux Rust + Vite finish in ~3-8 min cached) while still gating Bluetooth / WinUSB / Tauri-config changes on the slower Windows runner.
frontend-fast (ubuntu-latest) (every push/PR) — ESLint,
build-mode tsc -b (catches tsconfig.node.json drift tsc --noEmit would miss), and a Vite production build.frontend-windows (windows-latest) (manual / scheduled) —
Same checks on a Windows runner; catches Win32-specific frontend
regressions (path separators, CRLF, native-dep build errors).
Manual because cold runner is 8-12 min and CRLF rarely breaks.rust-fast (ubuntu-latest) (every push/PR) — cargo fmt --check + cargo check --lib + cargo test --lib for the
cross-platform code (parsers, msbc, MAP/PBAP wire-format,
calendar, orders, redact, fuzz harnesses).rust-windows (windows-latest) (auto on push/PR touching
aokie-desktop/src-tauri/** or this workflow; manual dispatch
for ad-hoc runs) — cargo check/test on the full lib and
the aokie-driver-helper bin under --no-default-features --features custom-protocol. The sherpa cargo feature is
opt-out: with it off, sherpa-rs-sys's CMake build (which
windows-latest can't satisfy without ZLIB / ICU dev libs) is
skipped and the runtime falls back to stub SherpaOnnxTtsRuntime
/ SherpaOnnxSttRuntime / StreamingVad impls. That catches
Windows regressions in the WinUSB transport, aokie_dongle, the
SetupAPI / WinTrust / catalog-sign surfaces, and any windows- sys version drift. Production Windows release builds keep
default = ["custom-protocol", "sherpa"] and still pull
sherpa-rs in for the full provider catalogue.audit-rust (weekly cron + manual) — cargo audit --deny warnings plus cargo deny check. Off the PR critical path so
cycles don't page on every transitive-dep advisory.audit-js (weekly cron + manual) — npm audit --audit-level=high. Same
off-the-PR-path rationale.No remaining Windows lib-coverage gap — the sherpa feature gate
let CI's Windows job compile and test the full lib. The only
Windows-specific path still skipped on CI is hardware-in-loop
testing (real BT dongle, real SCO audio); that stays a manual /
nightly step on the dev box.
aokie-desktop/src-tauri/.cargo/config.toml carries Windows-specific
build settings (target-dir = "C:\\t" MAX_PATH workaround + Visual
Studio 2022 CMake generator pins). cargo's [env] table is
non-forcing, so contributors on Linux / macOS can override
CARGO_TARGET_DIR and the CMAKE_GENERATOR* vars in their shell
without editing the file.
End-to-end happy path is verified: pair → answer → bidirectional
mSBC audio → Whisper / Gemma / Pocket-TTS turns → MAP message
push → post-call booking extraction. See ISSUES.md for the
current open list (low-severity at time of writing — Win32 87
bursts during heavy SCO TX, ACL accumulator desync during long
MAP messages; both auto-recover and don't block calls).
For the consolidated "what's shippable today, what's pilot-only,
what blocks public release" view (signing status, hardware support,
CI gates, pre-ship checklist, recording opt-in story), see
docs/RELEASE_READINESS.md. It's the
single source of truth — other docs should point back to it instead
of re-stating release status.
%APPDATA%/com.aokie.app/ on Windows,
~/.local/share/com.aokie.app/ on Linux) has the details.db-error event when they fail; the toast is the surface. Common
cause is a locked DB (some other process holding the file).0000 fallback). The bounded runtime drives ACL / SDP / RFCOMM / HFP
responses, accepts SCO/eSCO links, reports incoming PCM stats, auto-answers
when AOKIE_RADIO_AUTO_ANSWER=1, writes SCO silence when
AOKIE_RADIO_SCO_TX_SILENCE=1, and writes a 440 Hz test tone when
AOKIE_RADIO_SCO_TX_TONE=1. Diagnostic link keys persist under the app
data directory at aokie_radio/pairing_store.json. The same hardware
checks are available from the terminal on Windows with
cargo run --bin aokie-radio-diag -- hci-interfaces,
probe, init, or runtime 5 from aokie-desktop/src-tauri. The
binary refuses to run on Linux / macOS — those platforms have access
to the same diagnostics through the in-app aokie_radio_* Tauri
commands instead.
Set AOKIE_RADIO_DUMP=1 for transport-level hex dumps while testing
hardware. Set AOKIE_VERBOSE_LOGS=1 to disable PII redaction in
logs (off by default — phone numbers + message bodies + transcripts
mask).This project is proprietary to Aokie (aokie.com).
406 commits
Rust
78.0%
TypeScript
17.9%
JavaScript
2.5%