Files
elizaos--eliza/packages/training/scripts/test_append_voice_model_version.py
wehub-resource-sync 426e9eeabd
Voice Workbench / headless workbench (mocked backends) (push) Has been cancelled
Voice Workbench / real acoustic lane (nightly, provisioned only) (push) Has been cancelled
ci / test (push) Has been cancelled
ci / lint-and-format (push) Has been cancelled
ci / build (push) Has been cancelled
ci / dev-startup (push) Has been cancelled
gitleaks / gitleaks (push) Has been cancelled
Markdown Links / Relative Markdown Links (push) Has been cancelled
Quality (Extended) / Homepage Build (PR smoke) (push) Has been cancelled
Quality (Extended) / Comment-only diff guard (push) Has been cancelled
Quality (Extended) / Format + Type Safety Ratchet (push) Has been cancelled
Quality (Extended) / Develop Gate (secret scan + UI determinism) (push) Has been cancelled
Quality (Extended) / Develop Gate (lint) (push) Has been cancelled
Chat shell gestures / Chat shell gesture + parity e2e (push) Has been cancelled
Cloud Gateway Discord / Test (push) Has been cancelled
Benchmark Bridge Tests / benchmark (bunx @biomejs/biome check packages/lifeops-bench/src, benchmark-lint) (push) Has been cancelled
Benchmark Bridge Tests / benchmark (bunx vitest run --config packages/lifeops-bench/vitest.config.ts --root packages/lifeops-bench --passWithNoTests, benchmark-tests) (push) Has been cancelled
Build Agent Image / build-and-push (push) Has been cancelled
Dev Smoke / bun run dev onboarding chat (push) Has been cancelled
Dev Smoke / Vite HMR dependency-level smoke (push) Has been cancelled
Electrobun Submodule Guard / electrobun gitlink is fetchable (push) Has been cancelled
Publish @elizaos/example-code / check_npm (push) Has been cancelled
Publish @elizaos/example-code / publish_npm (push) Has been cancelled
Publish @elizaos/plugin-elizacloud / verify_version (push) Has been cancelled
Publish @elizaos/plugin-elizacloud / publish_npm (push) Has been cancelled
Sandbox Live Smoke / Sandbox live smoke (push) Has been cancelled
Snap Build & Test / Build Snap (amd64) (push) Has been cancelled
Snap Build & Test / Build Snap (arm64) (push) Has been cancelled
Test Packaging / elizaos CLI global-install smoke (node + bun) (push) Has been cancelled
Cloud Gateway Webhook / Test (push) Has been cancelled
Cloud Tests / lint-and-types (push) Has been cancelled
Cloud Tests / unit-tests (push) Has been cancelled
Cloud Tests / integration-tests (push) Has been cancelled
Cloud Tests / e2e-tests (push) Has been cancelled
CodeQL Advanced / Analyze (javascript-typescript) (push) Has been cancelled
Deploy Apps Worker (Product 2) / Determine environment (push) Has been cancelled
Deploy Apps Worker (Product 2) / Deploy apps worker to apps-control host (${{ needs.determine-env.outputs.environment }}) (push) Has been cancelled
Deploy Eliza Provisioning Worker / Determine environment (push) Has been cancelled
Deploy Eliza Provisioning Worker / Deploy worker to Hetzner host (${{ needs.determine-env.outputs.environment }} @ ${{ needs.determine-env.outputs.deployment_sha }}) (push) Has been cancelled
Dev Smoke / Classify changed paths (push) Has been cancelled
supply-chain / sbom (push) Has been cancelled
supply-chain / vulnerability-scan (push) Has been cancelled
Build, Push & Deploy to Phala Cloud / build-and-push (push) Has been cancelled
Test Packaging / Validate Packaging Configs (push) Has been cancelled
Test Packaging / Build & Test PyPI Package (push) Has been cancelled
Test Packaging / PyPI on Python ${{ matrix.python }} (push) Has been cancelled
Test Packaging / Pack & Test JS Tarballs (push) Has been cancelled
UI Fixture E2E / ui-fixture-e2e (push) Has been cancelled
UI Fixture E2E / fixture-e2e (push) Has been cancelled
UI Story Gate / story-gate (push) Has been cancelled
vault-ci / test (macos-latest) (push) Has been cancelled
vault-ci / test (ubuntu-latest) (push) Has been cancelled
vault-ci / test (windows-latest) (push) Has been cancelled
vault-ci / app-core wiring tests (push) Has been cancelled
verify-patches / verify patches/CHECKSUMS.sha256 (push) Has been cancelled
Voice Benchmark Smoke / voice-emotion fixture smoke (push) Has been cancelled
Voice Benchmark Smoke / voiceagentbench fixture smoke (push) Has been cancelled
Voice Benchmark Smoke / voicebench-quality unit smoke (push) Has been cancelled
Voice Benchmark Smoke / voicebench TypeScript unit (no audio) (push) Has been cancelled
Voice Benchmark Smoke / voice bench smoke summary (push) Has been cancelled
Windows CI / windows ([bun run --cwd packages/app-core test bun run --cwd packages/elizaos test bun run --cwd packages/cloud/shared test], app-and-cli) (push) Has been cancelled
Windows CI / windows ([bun run --cwd packages/scenario-runner test bun run --cwd packages/vault test bun run --cwd packages/security test bun run --cwd plugins/plugin-coding-tools test], framework-packages) (push) Has been cancelled
Windows CI / windows ([bun run --cwd plugins/plugin-elizacloud test bun run --cwd plugins/plugin-discord test bun run --cwd plugins/plugin-anthropic test bun run --cwd plugins/plugin-openai test bun run --cwd plugins/plugin-app-control test bun run --cwd plugins/pl… (push) Has been cancelled
Windows CI / windows ([node packages/scripts/run-turbo.mjs run build --filter=@elizaos/core --filter=@elizaos/shared --filter=@elizaos/agent --concurrency=4 node packages/scripts/run-bash-linux-only.mjs scripts/verify-riscv64-buildpaths.sh node packages/scripts/run… (push) Has been cancelled
Windows CI / windows ([node packages/scripts/run-turbo.mjs run typecheck --filter=@elizaos/core --filter=@elizaos/shared --filter=@elizaos/cloud-shared --concurrency=4 bun run --cwd packages/core test bun run --cwd packages/shared test], core-runtime, 75) (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:43:05 +08:00

315 lines
8.3 KiB
Python

"""Tests for `append_voice_model_version.py`.
Covers:
- Validates `--id` against the known voice model set.
- Asset parsing rejects bad shape / bad sha256 / bad quant.
- Idempotent re-run (no double-write) when the entry already exists.
- `--append-changelog` inserts an H3 under the matching H2.
- `--dry-run` writes nothing to disk.
"""
from __future__ import annotations
import json
import os
import subprocess
import sys
from pathlib import Path
from textwrap import dedent
REPO_ROOT = Path(__file__).resolve().parents[3]
SCRIPT = (
REPO_ROOT / "packages" / "training" / "scripts" / "append_voice_model_version.py"
)
VOICE_MODELS_TS_TEMPLATE = dedent(
"""\
export const VOICE_MODEL_VERSIONS: ReadonlyArray<VoiceModelVersion> = [
{
id: "kokoro",
version: "0.1.0",
publishedToHfAt: "2026-05-14T00:00:00Z",
hfRepo: "elizaos/eliza-1-voice-kokoro-same",
hfRevision: "main",
ggufAssets: [],
evalDeltas: { netImprovement: true },
changelogEntry: "Initial release.",
minBundleVersion: "0.0.0",
},
];
"""
)
CHANGELOG_MD_TEMPLATE = dedent(
"""\
# Eliza voice sub-models — changelog
## kokoro
### 0.1.0 — 2026-05-14
- Initial release.
"""
)
def _setup_workspace(tmp_path: Path) -> tuple[Path, Path]:
ts_path = tmp_path / "voice-models.ts"
md_path = tmp_path / "CHANGELOG.md"
ts_path.write_text(VOICE_MODELS_TS_TEMPLATE, encoding="utf-8")
md_path.write_text(CHANGELOG_MD_TEMPLATE, encoding="utf-8")
return ts_path, md_path
def _run(*args: str) -> subprocess.CompletedProcess[str]:
return subprocess.run(
[sys.executable, str(SCRIPT), *args],
capture_output=True,
text=True,
check=False,
env={**os.environ, "PYTHONDONTWRITEBYTECODE": "1"},
)
def test_unknown_id_rejected(tmp_path: Path) -> None:
ts_path, _ = _setup_workspace(tmp_path)
res = _run(
"--id",
"not-a-real-id",
"--version",
"0.2.0",
"--hf-repo",
"elizaos/foo",
"--hf-revision",
"main",
"--min-bundle",
"0.0.0",
"--changelog-entry",
"hi",
"--voice-models-ts",
str(ts_path),
)
assert res.returncode != 0
assert "invalid choice" in res.stderr or "not-a-real-id" in res.stderr
def test_invalid_semver_rejected(tmp_path: Path) -> None:
ts_path, _ = _setup_workspace(tmp_path)
res = _run(
"--id",
"kokoro",
"--version",
"bogus",
"--hf-repo",
"elizaos/eliza-1-voice-kokoro-same",
"--hf-revision",
"main",
"--min-bundle",
"0.0.0",
"--changelog-entry",
"hi",
"--voice-models-ts",
str(ts_path),
)
assert res.returncode == 2
def test_bad_asset_rejected(tmp_path: Path) -> None:
ts_path, _ = _setup_workspace(tmp_path)
res = _run(
"--id",
"kokoro",
"--version",
"0.2.0",
"--hf-repo",
"elizaos/eliza-1-voice-kokoro-same",
"--hf-revision",
"main",
"--asset",
"kokoro.onnx:not-a-sha:1024:onnx-fp16",
"--min-bundle",
"0.0.0",
"--changelog-entry",
"hi",
"--voice-models-ts",
str(ts_path),
)
assert res.returncode != 0
def test_writes_new_version_block(tmp_path: Path) -> None:
ts_path, _ = _setup_workspace(tmp_path)
res = _run(
"--id",
"kokoro",
"--version",
"0.2.0",
"--parent-version",
"0.1.0",
"--hf-repo",
"elizaos/eliza-1-voice-kokoro-same",
"--hf-revision",
"abc123def456abc123def456abc123def456abcd",
"--asset",
"kokoro.onnx:" + "a" * 64 + ":2048:onnx-fp16",
"--min-bundle",
"0.1.0",
"--net-improvement",
"true",
"--rtf-delta",
"-0.05",
"--mos-delta",
"0.12",
"--changelog-entry",
"sam clone v2 (lower RTF, higher MOS).",
"--voice-models-ts",
str(ts_path),
)
assert res.returncode == 0, res.stderr
contents = ts_path.read_text(encoding="utf-8")
assert 'id: "kokoro"' in contents
assert 'version: "0.2.0"' in contents
assert 'parentVersion: "0.1.0"' in contents
assert "sha256: " + json.dumps("a" * 64) in contents
assert "quant: " + json.dumps("onnx-fp16") in contents
# The new entry must appear before the existing 0.1.0 entry (reverse-chrono).
idx_new = contents.find('version: "0.2.0"')
idx_old = contents.find('version: "0.1.0"')
assert idx_new < idx_old
assert "rtfDelta: -0.05" in contents
assert "mosDelta: 0.12" in contents
assert "netImprovement: true" in contents
def test_idempotent_rerun(tmp_path: Path) -> None:
ts_path, _ = _setup_workspace(tmp_path)
common = [
"--id",
"kokoro",
"--version",
"0.2.0",
"--parent-version",
"0.1.0",
"--hf-repo",
"elizaos/eliza-1-voice-kokoro-same",
"--hf-revision",
"main",
"--asset",
"kokoro.onnx:" + "a" * 64 + ":2048:onnx-fp16",
"--min-bundle",
"0.1.0",
"--net-improvement",
"true",
"--changelog-entry",
"sam v2.",
"--voice-models-ts",
str(ts_path),
]
res1 = _run(*common)
assert res1.returncode == 0, res1.stderr
contents1 = ts_path.read_text(encoding="utf-8")
res2 = _run(*common)
assert res2.returncode == 0, res2.stderr
contents2 = ts_path.read_text(encoding="utf-8")
# Second run leaves the file unchanged.
assert contents1 == contents2
# The version literal appears exactly once.
assert contents2.count('version: "0.2.0"') == 1
def test_append_changelog_inserts_h3(tmp_path: Path) -> None:
ts_path, md_path = _setup_workspace(tmp_path)
res = _run(
"--id",
"kokoro",
"--version",
"0.2.0",
"--parent-version",
"0.1.0",
"--hf-repo",
"elizaos/eliza-1-voice-kokoro-same",
"--hf-revision",
"abc",
"--asset",
"kokoro.onnx:" + "b" * 64 + ":1024:onnx-fp16",
"--min-bundle",
"0.1.0",
"--net-improvement",
"true",
"--changelog-entry",
"sam v2 with lower RTF.",
"--voice-models-ts",
str(ts_path),
"--changelog-md",
str(md_path),
"--append-changelog",
)
assert res.returncode == 0, res.stderr
md_contents = md_path.read_text(encoding="utf-8")
assert "### 0.2.0 — " in md_contents
assert "sam v2 with lower RTF." in md_contents
# H2 ordering preserved.
assert md_contents.index("## kokoro") < md_contents.index("### 0.2.0")
# Reverse chrono: new H3 above the old one.
assert md_contents.index("### 0.2.0") < md_contents.index("### 0.1.0")
def test_dry_run_writes_nothing(tmp_path: Path) -> None:
ts_path, md_path = _setup_workspace(tmp_path)
ts_before = ts_path.read_text(encoding="utf-8")
md_before = md_path.read_text(encoding="utf-8")
res = _run(
"--id",
"kokoro",
"--version",
"0.2.0",
"--parent-version",
"0.1.0",
"--hf-repo",
"elizaos/eliza-1-voice-kokoro-same",
"--hf-revision",
"main",
"--asset",
"kokoro.onnx:" + "c" * 64 + ":1024:onnx-fp16",
"--min-bundle",
"0.1.0",
"--net-improvement",
"true",
"--changelog-entry",
"sam v2.",
"--voice-models-ts",
str(ts_path),
"--changelog-md",
str(md_path),
"--append-changelog",
"--dry-run",
)
assert res.returncode == 0, res.stderr
assert ts_path.read_text(encoding="utf-8") == ts_before
assert md_path.read_text(encoding="utf-8") == md_before
def test_successor_requires_net_improvement(tmp_path: Path) -> None:
ts_path, _ = _setup_workspace(tmp_path)
res = _run(
"--id",
"kokoro",
"--version",
"0.2.0",
"--parent-version",
"0.1.0",
"--hf-repo",
"elizaos/eliza-1-voice-kokoro-same",
"--hf-revision",
"main",
"--min-bundle",
"0.1.0",
"--changelog-entry",
"sam v2.",
"--voice-models-ts",
str(ts_path),
)
assert res.returncode == 2
assert "--net-improvement is required" in res.stderr