-
Notifications
You must be signed in to change notification settings - Fork 0
Development
The crate uses Rust edition 2024 and commits Cargo.lock. All project targets enforce that lockfile; Cargo downloads missing locked dependencies when network access is available:
cargo build --release --locked
# Equivalent project target:
make buildmake build runs cargo build --release --locked. Use cargo fetch --locked separately only when you intentionally want to pre-populate a Cargo cache.
Run the daemon from source only after stopping the installed service, because both bind the same runtime sockets:
systemctl --user stop voice-input.service
VOICE_INPUT_ASSET_DIR="$PWD/assets" cargo run --locked -- daemonThe source daemon still reads the normal user config and runtime directory. Restart the installed service when finished.
src/
main.rs TLS provider initialization and top-level exit handling
args.rs hand-written CLI parsing/help
app.rs command dispatch and Settings activation/launch
daemon.rs control socket, capture service, session pipeline
config.rs public TOML schema, defaults, legacy migration
credentials.rs systemd/environment resolution and stdin encryption
agent_context.rs focused Pi/Codex validation and sanitization
backend.rs ASR trait, controls, and events
backend/
local_cli.rs /usr/bin/voxtype adapter
qwen_realtime.rs Alibaba WebSocket streaming adapter
qwen_batch.rs Qwen full-audio compatible-HTTP pass
text.rs transcript extraction and OpenCC conversion
llm.rs refinement prompt, shared deadline, fail-open behavior
output.rs Wayland/XWayland target detection and text emission
state.rs state machine snapshot and atomic persistence
waveform.rs PCM analysis, ASR packetizer, Unix socket publisher
wav.rs temporary PCM16 WAV writer
paths.rs, setup.rs installed paths and setup helpers
assets/
config.toml canonical public sample/default reference
voice-input*.service systemd user-unit templates
quickshell/ resident QML HUD
quickshell-settings/ on-demand FloatingWindow Settings QML
pi/ Pi session-registry extension
omarchy-*.conf/jsonc Hyprland and Waybar snippets
.github/workflows/ci.yml CI checks
packaging/ currently empty placeholder
contrib/omarchy/ currently empty Hyprland/Waybar placeholders
Keep assets/config.toml, Rust defaults, and Settings defaults synchronized when changing a public field. The resident HUD and on-demand Settings are separate Quickshell configurations with different lifecycles.
Run the complete local validation target, which checks QML and runs the Rust formatter, all-target check, tests, and Clippy with warnings denied:
make validate
make hud-shaders QSB=/usr/lib/qt6/bin/qsbSet QMLLINT or QSB explicitly if those Qt tools are installed elsewhere. CI performs the same Rust checks, parses every QML asset, builds and inspects the HUD's cross-RHI .qsb shader, and rejects obsolete runtime assets and source references so the removed desktop stack cannot return accidentally.
Current unit tests are embedded in modules and cover, among other things:
- current and legacy TOML parsing;
- local-backend transcript extraction from plain and logged output;
- Qwen event parsing and transcript assembly;
- LLM response validation, retry policy, OpenRouter sorting, and the shared 1–30 second budget with five-second fallback reservation using local mock HTTP servers;
- Pi/Codex JSONL extraction, redaction, and truncation;
- waveform chunk independence, symmetry, NDJSON framing, and ASR packet preservation;
- Wayland/XWayland effective output mode and the 120-character paste threshold;
- credential trimming and NUL rejection;
- versioned Settings NDJSON, exact-source revision conflicts, full-field validation, atomic save permissions, credential keep/replace, and separate restart-failure reporting.
Tests do not exercise a live microphone, compositor, Alibaba/OpenAI-compatible account, real Kitty/Pi/Codex process, Quickshell rendering/IPC activation, or actual clipboard restoration. Those require manual integration checks.
Use non-sensitive test text and a disposable clipboard value.
- Start both user services and confirm all three runtime files/sockets exist.
- Test
record start,stop,toggle, andcancelfrom a terminal. - Test the intended Hyprland binding, including modifier release.
- Verify realtime partial text, Server VAD waveform visibility, and silent cancellation.
- Run a recording past the configured duration limit and confirm it stops and finalizes automatically. Under simulated realtime backpressure, confirm capture/HUD remain responsive and incomplete remote text is recovered from the full buffer.
- If enabled, verify final-pass replacement and
/usr/bin/voxtypefallback separately. - Exercise short Wayland direct type, long Wayland paste, and an XWayland target.
- Confirm clipboard restoration and Fcitx5 restoration.
- Move/reset the HUD and test a monitor focus change/hotplug.
- Restart Pi after installing the extension, then test Pi and Codex context independently.
- Open Settings twice and verify the second command activates the existing
FloatingWindow; close it and verify the on-demand instance exits. - Test a stale revision conflict, a config-only save, credential keep/replace, Test LLM with entered/store credentials, and a separately reported daemon restart failure.
- Review timing logs and Settings diagnostics for accidental content before attaching them to a report.
- Fail open to recognized text: LLM failure must not discard valid ASR output.
- One refinement deadline: contextual work and fallback share one budget capped at 30 seconds; normal budgets reserve five seconds for transcript-only recovery.
- No capture backpressure: realtime ASR and waveform/HUD clients must not block capture. A lagging bounded queue must fail into complete-buffer recovery rather than silently accepting incomplete text.
-
Explicit backend identity: local fallback remains a configured executable, defaulting to
/usr/bin/voxtype. -
Secrets stay on stdin: Settings replacements travel QML stdin → Rust →
systemd-credsstdin, never config/argv/environment/log/response; field clearing in managed QML/JavaScript memory remains best effort. -
Rust owns persistence: keep validation,
0700/0600permissions, atomic replacement, full-field preservation, and exact-source conflict checks out of QML. - Validate external context: retain process/session/path checks, size limits, redaction, and prompt isolation.
-
Atomic state: concurrent writers must remain serialized through
StateHandleand temporary-file replacement.
There is currently no distro package recipe in packaging/; installation is implemented by the Makefile. make install:
- installs one release binary to
$(PREFIX)/bin(default~/.local/bin); - installs the resident HUD and on-demand Settings assets to
$(PREFIX)/share/voice-input; - installs the Pi extension under
~/.pi/agent/extensions; - renders unit templates into
~/.config/systemd/user; - creates private config and encrypted-credential directories;
- creates a sample config only when none exists;
- may migrate specifically recognized older Voxtype config/credential files;
- removes obsolete installed
hud.pyandsettings.pyfiles during upgrades.
PREFIX changes binary/share destinations, but the service, Pi extension, config, and credential locations have separate Make variables and user-home defaults. Packagers should set all relevant variables or stage files explicitly rather than assuming PREFIX relocates everything.
Service templates contain @VOICE_INPUT_BIN@, @VOICE_INPUT_ASSET_DIR@, and @VOICE_INPUT_QUICKSHELL_DIR@; render them to final absolute paths. Keep /usr/bin/qs and optional external command dependencies visible in package metadata. Do not package local configs, encrypted blobs, runtime state, recordings, JSONL sessions, or logs.
The repository's contribution guide defines the current Rust, QML, shader, bounded-resource, error-handling, and validation standards.
- Open an issue or focused proposal for behavior that affects privacy, provider protocols, or desktop assumptions.
- Create a small topic branch and keep unrelated local configuration out of the patch.
- Add or update unit tests for pure logic. For desktop/network behavior, document a reproducible manual test.
- Update
assets/config.toml, Settings, Rust defaults, README, and both Wiki languages when public behavior changes. - Run
make validate, compile the HUD shader, and rungit diff --checkas described in the contribution guide. - Inspect the diff for credentials, user-specific absolute paths, transcripts, session files, recordings, and generated artifacts.
- Submit a pull request explaining the reason, compatibility impact, privacy/data-flow change, and test evidence.
CI runs on pushes and pull requests with read-only repository contents permission. It checks Rust formatting, all targets, tests, Clippy, QML parsing, cross-RHI shader assets, and rejects obsolete desktop-runtime assets/references; passing CI does not replace the manual compositor/audio/provider/Quickshell checks above.
See also: Architecture · Security and Privacy
English Home · 简体中文首页 · Source repository · MIT License
Voice Input is an independent community project. HUD and Settings require Quickshell 0.3+. Review Security and Privacy before enabling remote ASR, LLM refinement, pre-roll, agent context, or replacing credentials in Settings.
Voice Input 是独立的社区项目。HUD 和 Settings 需要 Quickshell 0.3 或更高版本。启用远程 ASR、LLM refinement、pre-roll、Agent 上下文,或者在 Settings 中替换 credential 前,请阅读安全与隐私。