mirror of
https://github.com/tinyhumansai/openhuman.git
synced 2026-07-28 13:32:23 +00:00
* feat(voice): add dedicated voice assistance module for STT/TTS Extracts speech-to-text (whisper.cpp) and text-to-speech (piper) into a dedicated `src/openhuman/voice/` domain module with its own RPC namespace (`openhuman.voice_*`). Adds proactive availability checking via `voice_status` so the UI can show clear errors when binaries/models are missing instead of failing silently at transcription time. - New module: voice/types.rs, voice/ops.rs, voice/schemas.rs, voice/mod.rs - 4 RPC endpoints: voice_status, voice_transcribe, voice_transcribe_bytes, voice_tts - 21 unit tests + 1 integration test (json_rpc_e2e) - Frontend updated to use voice_* endpoints with status check on mode switch Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * style: fix cargo fmt in voice/ops.rs Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * test(e2e): add voice mode integration spec Tests switching to voice input mode, verifying status check fires, recording button renders, and switching back to text mode restores text input. Also checks reply mode toggle visibility. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: remove unused waitForText import in voice-mode e2e spec Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * feat(voice): in-process whisper engine and LLM post-processing - Add whisper-rs (0.16) for in-process whisper.cpp inference, eliminating cold-start latency from subprocess-per-call (~1-3s) to warm inference (~50ms). Model is loaded once during bootstrap and reused across calls. Falls back to whisper-cli subprocess if in-process loading fails. - Add LLM post-processing layer that passes raw transcription through Ollama to fix grammar, punctuation, and filler words. Accepts optional conversation context to disambiguate names and technical terms. Gracefully degrades to raw whisper output if Ollama is unavailable. - Update voice RPC endpoints with new optional params (context, skip_cleanup) and return both cleaned text and raw_text. - Update frontend to pass conversation history as context for voice transcription cleanup, and update TypeScript interfaces to match. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * style: apply cargo fmt formatting fixes Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix(build): make whisper-rs optional behind `whisper` feature flag The whisper-rs crate requires cmake to compile whisper.cpp from source, which is not available in the CI environment. Move it behind an optional cargo feature so CI builds succeed without cmake. The whisper_engine module now compiles as a no-op stub when the feature is disabled, returning "whisper feature not compiled in" errors. Desktop builds can opt in with `--features whisper`. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * style: cargo fmt whisper_engine.rs Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix(ci): make whisper-rs mandatory and install cmake in CI Revert whisper-rs from optional to mandatory dependency. Add cmake installation to all CI workflows (build, typecheck, test, release) and the CI Docker image so whisper-rs can compile whisper.cpp from source. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * style: cargo fmt whisper_engine.rs Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: address code review findings across voice module - whisper_engine: validate WAV sample rate (must be 16kHz) and channel count (1 or 2) before feeding audio to whisper - speech: offload load_engine and transcribe_in_process to tokio::task::spawn_blocking to avoid blocking the Tokio runtime - ops: use RAII guard for WHISPER_BIN env var in test to prevent races and ensure restore on panic; log temp file cleanup failures instead of silently ignoring; sanitize paths in debug logs to basenames only - postprocess: add test for disabled cleanup config returning raw text - voice-mode.spec: assert failure when neither voice CTA nor unavailable message appears; make reply mode test runnable in isolation with auth/nav setup Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * style: apply cargo fmt Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
329 lines
14 KiB
YAML
329 lines
14 KiB
YAML
name: Release Packages
|
|
|
|
# Triggered after the main release.yml publishes a release.
|
|
# By the time this fires, macOS (aarch64 + x86_64) and Linux x86_64
|
|
# CLI tarballs are already attached to the release by release.yml.
|
|
#
|
|
# This workflow adds:
|
|
# 1. Linux arm64 CLI tarball
|
|
# 2. Homebrew tap formula update
|
|
# 3. Debian apt repository (gh-pages)
|
|
# 4. npm package publish
|
|
# 5. Smoke tests for each channel
|
|
# 6. One-time backlog issue for future package managers
|
|
|
|
on:
|
|
release:
|
|
types: [published]
|
|
|
|
permissions:
|
|
contents: write
|
|
pages: write
|
|
id-token: write
|
|
issues: write
|
|
|
|
concurrency:
|
|
group: release-packages-${{ github.event.release.tag_name }}
|
|
cancel-in-progress: false
|
|
|
|
jobs:
|
|
|
|
# ────────────────────────────────────────────────────────────────────────────
|
|
# 1. Build Linux arm64 CLI tarball (native runner)
|
|
# Requires: ubuntu-24.04-arm GitHub-hosted runner (free for public repos).
|
|
# If this runner type is unavailable on your plan, replace runs-on with
|
|
# ubuntu-22.04 and add: uses: taiki-e/install-action@cross + use
|
|
# `cross build --target aarch64-unknown-linux-gnu` instead of plain cargo.
|
|
# ────────────────────────────────────────────────────────────────────────────
|
|
build-cli-linux-arm64:
|
|
name: Build Linux arm64 CLI tarball
|
|
runs-on: ubuntu-24.04-arm
|
|
steps:
|
|
- name: Checkout tag
|
|
uses: actions/checkout@v4
|
|
with:
|
|
ref: ${{ github.event.release.tag_name }}
|
|
fetch-depth: 1
|
|
submodules: true
|
|
|
|
- name: Install Rust
|
|
uses: dtolnay/rust-toolchain@1.93.0
|
|
|
|
- name: Cache Cargo
|
|
uses: Swatinem/rust-cache@v2
|
|
with:
|
|
key: linux-arm64-release
|
|
|
|
- name: Install system dependencies
|
|
run: |
|
|
sudo apt-get update -qq
|
|
sudo apt-get install -y --no-install-recommends \
|
|
pkg-config libssl-dev build-essential cmake
|
|
|
|
- name: Build CLI binary and package tarball
|
|
env:
|
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
OPENHUMAN_SENTRY_DSN: ${{ vars.OPENHUMAN_SENTRY_DSN }}
|
|
run: |
|
|
cargo build --release --bin openhuman-core
|
|
VERSION="${{ github.event.release.tag_name }}"
|
|
bash scripts/release/package-cli-tarball.sh \
|
|
target/release/openhuman-core \
|
|
"${VERSION#v}" \
|
|
aarch64-unknown-linux-gnu
|
|
|
|
# ────────────────────────────────────────────────────────────────────────────
|
|
# 2. Update Homebrew tap
|
|
# Requires secret: HOMEBREW_TAP_TOKEN (PAT or App token with contents:write
|
|
# on tinyhumansai/homebrew-openhuman)
|
|
# ────────────────────────────────────────────────────────────────────────────
|
|
update-homebrew:
|
|
name: Update Homebrew tap formula
|
|
runs-on: ubuntu-latest
|
|
needs: [build-cli-linux-arm64]
|
|
steps:
|
|
- name: Checkout main repo (for formula template)
|
|
uses: actions/checkout@v4
|
|
with:
|
|
ref: ${{ github.event.release.tag_name }}
|
|
path: src
|
|
|
|
- name: Checkout Homebrew tap
|
|
uses: actions/checkout@v4
|
|
with:
|
|
repository: tinyhumansai/homebrew-openhuman
|
|
token: ${{ secrets.HOMEBREW_TAP_TOKEN }}
|
|
path: tap
|
|
|
|
- name: Update Homebrew formula
|
|
env:
|
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
run: |
|
|
bash src/scripts/release/update-homebrew.sh \
|
|
"${{ github.event.release.tag_name }}" \
|
|
src/packages/homebrew/openhuman.rb \
|
|
tap
|
|
|
|
# ────────────────────────────────────────────────────────────────────────────
|
|
# 3. Build Debian apt repository and deploy to GitHub Pages
|
|
# Requires: APT_SIGNING_KEY (ASCII-armor GPG private key secret)
|
|
# APT_SIGNING_KEY_ID (key fingerprint / ID)
|
|
# GitHub Pages must be enabled (Settings → Pages → Source: gh-pages branch)
|
|
# ────────────────────────────────────────────────────────────────────────────
|
|
build-apt-repo:
|
|
name: Build apt repository
|
|
runs-on: ubuntu-22.04
|
|
needs: [build-cli-linux-arm64]
|
|
steps:
|
|
- name: Checkout tag
|
|
uses: actions/checkout@v4
|
|
with:
|
|
ref: ${{ github.event.release.tag_name }}
|
|
fetch-depth: 1
|
|
|
|
- name: Install apt-repo build tools
|
|
run: |
|
|
sudo apt-get update -qq
|
|
sudo apt-get install -y --no-install-recommends \
|
|
dpkg-dev apt-utils gnupg2
|
|
|
|
- name: Import GPG signing key
|
|
env:
|
|
APT_SIGNING_KEY: ${{ secrets.APT_SIGNING_KEY }}
|
|
run: |
|
|
echo "$APT_SIGNING_KEY" | gpg --batch --import
|
|
gpg --list-secret-keys
|
|
|
|
- name: Checkout gh-pages branch
|
|
uses: actions/checkout@v4
|
|
with:
|
|
ref: gh-pages
|
|
path: gh-pages
|
|
fetch-depth: 0
|
|
|
|
- name: Build .deb packages, apt repo, and deploy to gh-pages
|
|
env:
|
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
APT_SIGNING_KEY_ID: ${{ secrets.APT_SIGNING_KEY_ID }}
|
|
run: |
|
|
bash scripts/release/build-apt-packages.sh \
|
|
"${{ github.event.release.tag_name }}" \
|
|
--deploy-gh-pages gh-pages
|
|
|
|
# ────────────────────────────────────────────────────────────────────────────
|
|
# 4. Publish npm package
|
|
# Requires secret: NPM_TOKEN (automation token from npmjs.com)
|
|
# ────────────────────────────────────────────────────────────────────────────
|
|
publish-npm:
|
|
name: Publish npm package
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- name: Checkout tag
|
|
uses: actions/checkout@v4
|
|
with:
|
|
ref: ${{ github.event.release.tag_name }}
|
|
fetch-depth: 1
|
|
|
|
- name: Setup Node.js
|
|
uses: actions/setup-node@v4
|
|
with:
|
|
node-version: 24.x
|
|
registry-url: 'https://registry.npmjs.org'
|
|
|
|
- name: Set version and publish
|
|
env:
|
|
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
|
run: bash scripts/release/publish-npm.sh "${{ github.event.release.tag_name }}"
|
|
|
|
# ────────────────────────────────────────────────────────────────────────────
|
|
# 5. Smoke test: Homebrew
|
|
# ────────────────────────────────────────────────────────────────────────────
|
|
smoke-homebrew:
|
|
name: Smoke — Homebrew (${{ matrix.os }})
|
|
runs-on: ${{ matrix.os }}
|
|
needs: [update-homebrew]
|
|
continue-on-error: true
|
|
strategy:
|
|
fail-fast: false
|
|
matrix:
|
|
os: [macos-latest, ubuntu-22.04]
|
|
steps:
|
|
- name: Install Homebrew (Linux)
|
|
if: runner.os == 'Linux'
|
|
run: |
|
|
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
|
|
echo "/home/linuxbrew/.linuxbrew/bin" >> "$GITHUB_PATH"
|
|
|
|
- name: Tap and install
|
|
run: |
|
|
brew tap tinyhumansai/openhuman
|
|
brew install openhuman
|
|
|
|
- name: Smoke test
|
|
run: openhuman --version
|
|
|
|
# ────────────────────────────────────────────────────────────────────────────
|
|
# 6. Smoke test: apt
|
|
# ────────────────────────────────────────────────────────────────────────────
|
|
smoke-apt:
|
|
name: Smoke — apt (ubuntu-22.04)
|
|
runs-on: ubuntu-22.04
|
|
needs: [build-apt-repo]
|
|
continue-on-error: true
|
|
steps:
|
|
- name: Add apt repository
|
|
run: |
|
|
sudo apt-get install -y --no-install-recommends gnupg2 curl ca-certificates
|
|
curl -fsSL https://tinyhumansai.github.io/openhuman/apt/KEY.gpg \
|
|
| sudo gpg --dearmor -o /etc/apt/keyrings/openhuman.gpg
|
|
echo "deb [signed-by=/etc/apt/keyrings/openhuman.gpg arch=amd64] \
|
|
https://tinyhumansai.github.io/openhuman/apt stable main" \
|
|
| sudo tee /etc/apt/sources.list.d/openhuman.list
|
|
|
|
- name: Install and smoke test
|
|
run: |
|
|
sudo apt-get update
|
|
sudo apt-get install -y openhuman
|
|
openhuman --version
|
|
|
|
# ────────────────────────────────────────────────────────────────────────────
|
|
# 7. Smoke test: npm
|
|
# ────────────────────────────────────────────────────────────────────────────
|
|
smoke-npm:
|
|
name: Smoke — npm (${{ matrix.os }})
|
|
runs-on: ${{ matrix.os }}
|
|
needs: [publish-npm]
|
|
continue-on-error: true
|
|
strategy:
|
|
fail-fast: false
|
|
matrix:
|
|
os: [ubuntu-latest, macos-latest]
|
|
steps:
|
|
- name: Setup Node.js
|
|
uses: actions/setup-node@v4
|
|
with:
|
|
node-version: 24.x
|
|
|
|
- name: Wait for npm propagation, then install
|
|
run: |
|
|
VERSION="${{ github.event.release.tag_name }}"
|
|
VERSION="${VERSION#v}"
|
|
# npm can take up to ~2 min to propagate a new publish
|
|
for i in 1 2 3 4 5; do
|
|
npm install -g "openhuman@${VERSION}" && break || sleep 30
|
|
done
|
|
|
|
- name: Smoke test
|
|
run: openhuman --version
|
|
|
|
# ────────────────────────────────────────────────────────────────────────────
|
|
# 8. File the "future package managers" backlog issue (once ever)
|
|
# ────────────────────────────────────────────────────────────────────────────
|
|
create-backlog-issue:
|
|
name: Create backlog issue (once)
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- name: Create issue if it doesn't exist
|
|
uses: actions/github-script@v7
|
|
with:
|
|
script: |
|
|
const { owner, repo } = context.repo;
|
|
const label = 'distribution-backlog';
|
|
const title = '[Backlog] Package manager distribution — next tiers';
|
|
|
|
// Check for existing open or closed issue with this exact title
|
|
const { data: existing } = await github.rest.issues.listForRepo({
|
|
owner, repo,
|
|
state: 'all',
|
|
labels: label,
|
|
per_page: 10,
|
|
});
|
|
if (existing.some(i => i.title === title)) {
|
|
core.info('Backlog issue already exists — skipping.');
|
|
return;
|
|
}
|
|
|
|
// Ensure the label exists
|
|
try {
|
|
await github.rest.issues.createLabel({
|
|
owner, repo,
|
|
name: label,
|
|
color: '0075ca',
|
|
description: 'Package distribution backlog',
|
|
});
|
|
} catch (_) { /* label may already exist */ }
|
|
|
|
const body = `## Summary
|
|
|
|
Track remaining package manager channels. Each tier reflects expected maintenance commitment from the core team.
|
|
|
|
## Tier 1 — Official (core team maintains)
|
|
|
|
- [ ] **npx / pnpm dlx** — zero-install via the npm package already published; document the one-liner: \`npx openhuman@latest\`
|
|
- [ ] **Scoop (Windows)** — needs a Windows binary (un-comment the Windows matrix in \`release.yml\` first); add a \`tinyhumansai/scoop-openhuman\` bucket
|
|
|
|
## Tier 2 — Community-supported (PRs welcome, core team reviews)
|
|
|
|
- [ ] **AUR (Arch Linux)** — add \`PKGBUILD\` pointing at the GitHub release tarball; list in \`packages/\`
|
|
- [ ] **Nix / nixpkgs** — upstream a \`pkgs/tools/openhuman/default.nix\` derivation; document local flake overlay as interim
|
|
|
|
## Tier 3 — Planned (no timeline)
|
|
|
|
- [ ] **Snap / Snapcraft** — \`snapcraft.yaml\`, publish to Snap Store
|
|
- [ ] **Flatpak** — \`org.tinyhumans.Openhuman.yaml\`, publish to Flathub
|
|
- [ ] **WinGet** — manifest in \`microsoft/winget-pkgs\` once Windows binary is stable
|
|
|
|
## Acceptance criteria
|
|
|
|
- [ ] Each official channel has a CI smoke test (install + \`openhuman --version\`)
|
|
- [ ] Install commands appear in \`docs/install.md\`
|
|
- [ ] Checksums shipped for all artifacts
|
|
`;
|
|
const issue = await github.rest.issues.create({
|
|
owner, repo,
|
|
title,
|
|
body,
|
|
labels: [label],
|
|
});
|
|
core.info(\`Created backlog issue: \${issue.data.html_url}\`);
|