38b78d8a4a
Swap the voice synthesis backend from chatterbox-fast (:8197 bespoke /tts)
to dots-tts (rednote-hilab dots.tts-soar, :8198 OpenAI-shaped
/v1/audio/speech), operator-directed after an A/B win. tts.py stays the
single swap seam.
- gateway body OpenAI-shaped: {input, voice, response_format, stream}
(was chatterbox {text, voice, format, stream})
- sample rate 24000 -> 48000 Hz (browser Web Audio SR)
- default voice glados_25s -> glados; donut voice carries over
- serialized single-consumer (satisfied by the existing DEC-5 lock)
- affect stays dropped (dots has no emotion knob, same as chatterbox)
DOTS_TTS_URL replaces CHATTERBOX_TTS_URL; RATATOSKR_TTS_URL override
unchanged. chatterbox-fast :8197 kept up as rollback. Contract amended
(donut_voiced_interview.contract.md). Live-verified end-to-end on :8765
(RIFF/WAVE 48kHz mono s16le through /api/tts). 520 tests green.
97 lines
5.2 KiB
TOML
97 lines
5.2 KiB
TOML
[build-system]
|
|
requires = ["hatchling"]
|
|
build-backend = "hatchling.build"
|
|
|
|
[project]
|
|
name = "ratatoskr"
|
|
version = "0.22.2"
|
|
description = "Worldtree Conversation API debug console (web + headless CLI) — multi-pane observability"
|
|
readme = "README.md"
|
|
requires-python = ">=3.12"
|
|
license = { file = "LICENSE" }
|
|
authors = [{ name = "Vuong Hoang" }]
|
|
keywords = ["worldtree", "debug", "sse", "web", "observability"]
|
|
|
|
# Network transport for the injected AsyncClient (INV-CUT-1); SSE parsing is
|
|
# owned by worldtree-sdk post-cutover (#20 slice-7 dropped httpx-sse).
|
|
dependencies = [
|
|
"httpx>=0.27",
|
|
"worldtree-sdk==1.2.0", # #20 cutover: the consumer client layer (gitea PyPI); the hand-rolled wrappers now live behind ratatoskr.wt. 1.2.0 = response-side allocation caps + a new exported `ResponseTooLarge` (a ProtocolError, NOT a ConnectionDropped — retrying an oversized response is futile; caps: 2xx body 108,004,096 B, SSE frame 540,000 B; the caps assume a 2.5.0 server, which worldtree-dev runs, so safe on legal traffic). We catch it explicitly at the stream + read surfaces (INV-CUT-2). Absorbed WT spec 2.4.0/2.5.0 (zero-schema, no generated-type change). 1.1.2 = closed the SSE turn-stream traversal we caught in 1.1.1 (quote safe="" at turn_stream.py:185). 1.1.1 = path-encoding correctness fix + additive define_or_reuse / set_persona_state_raw (our parity #6) + 64 KiB error-body alloc cap. Same frozen wire as 1.0.0 (drop-in).
|
|
]
|
|
|
|
[project.optional-dependencies]
|
|
web = [
|
|
"starlette>=0.40",
|
|
"uvicorn[standard]>=0.30",
|
|
]
|
|
# Tier-3 Bifrost consumer: the durable memory.* + affect.* persistence
|
|
# provider Worldtree writes into. Opt-in extra — distinct deployment surface
|
|
# from the debug TUI. Recipe: bifrost/docs/implementing-a-consumer.md.
|
|
provider = [
|
|
"ratatoskr[web]", # reuse the starlette + uvicorn ASGI stack
|
|
"bifrost==1.1.5", # consumer engines + library. 1.1.5 = gate ALL optional store verbs → clean unsupported_capability (not 500), extending 1.1.4's maintenance-verb backstop to the full optional-verb set + a v0.6 memory verb-floor conformance harness (frozen wire v0.6, no schema change). 1.1.4 = hasattr-gate backstop for the maintenance verbs (mark_superseded/mark_invalid/patch_many/delete_many/upsert_edges/get_edges_for → unimplemented verb degrades to unsupported_capability 400, never AttributeError/500/retry-storm; we surfaced it via WT #364) + 1.1.3 scan/cursor conformance harness + 1.1.2 frozen-v0.6 fix. 1.1.1 = frozen-wire serialization fix (ADR-0008): additive capability fields are gated on the NEGOTIATED wire, so a v0.6-negotiated describe_store handshake stays v0.6-clean. 1.1.0 leaked the v0.7-additive `sortable_chunk_fields` into v0.6 StoreCapabilities → a strict v0.6 client (additionalProperties:false) rejects our server's handshake. Wire schemas + pins UNCHANGED (serialization-correctness only); our v0.7 handshake with Worldtree b47 is unaffected. (1.1.0 = wire v0.7 additive: memory.scan sort + sortable_chunk_fields; 1.0.0 = first STABLE, wire v0.6 FROZEN; 0.8.0/v0.6 scope_all/scope_any #11; 0.7.0/v0.5 agent_self)
|
|
"jsonschema>=4", # bifrost runtime dep — envelope validation
|
|
"sqlite-vec>=0.1.6", # vector index for the memory plane (vec0 virtual table)
|
|
]
|
|
dev = [
|
|
"pytest>=8",
|
|
"pytest-asyncio>=0.24",
|
|
"respx>=0.21", # httpx mocking for SSE-recorded snapshot tests
|
|
"ruff>=0.6",
|
|
"mypy>=1.11",
|
|
"pyyaml>=6", # used by docs/contracts/contract_parser.py and scripts/contract_drift_check.py
|
|
"ratatoskr[web]", # web extras included in dev so test_web_* can import starlette
|
|
]
|
|
|
|
[project.scripts]
|
|
ratatoskr = "ratatoskr.cli:main"
|
|
ratatoskr-web = "ratatoskr.web.entrypoint:main"
|
|
ratatoskr-provider = "ratatoskr.provider.serve:main"
|
|
ratatoskr-memory-provider = "ratatoskr.provider.serve_memory:main"
|
|
ratatoskr-combined-provider = "ratatoskr.provider.serve_combined:main"
|
|
|
|
[project.urls]
|
|
Repository = "https://gitea.phasefinal.com/vh/ratatoskr"
|
|
"Design Brief" = "https://gitea.phasefinal.com/vh/brokkr-smithy/src/branch/main/docs/ratatoskr-design-brief.md"
|
|
|
|
# Worldtree spec pin — see docs/SPEC-PIN.md for the full bump procedure.
|
|
# Ratatoskr is built against Worldtree at this commit; the vendored
|
|
# spec snapshot in docs/ reflects that SHA.
|
|
[tool.ratatoskr.spec-pin]
|
|
worldtree-spec-rev = "c9e59ec"
|
|
worldtree-version = "v1.0.0b22"
|
|
pinned-on = "2026-07-06"
|
|
|
|
# Bifrost lives on the auth-gated gitea PyPI index (not public PyPI).
|
|
# uv reads the credential from UV_INDEX_GITEA_USERNAME / _PASSWORD or ~/.netrc.
|
|
[[tool.uv.index]]
|
|
name = "gitea"
|
|
url = "https://gitea.phasefinal.com/api/packages/vh/pypi/simple/"
|
|
|
|
[tool.uv.sources]
|
|
bifrost = { index = "gitea" }
|
|
worldtree-sdk = { index = "gitea" }
|
|
|
|
[tool.hatch.build.targets.wheel]
|
|
packages = ["src/ratatoskr"]
|
|
|
|
# Issue #16: ship the web companion's static HTML in the wheel so
|
|
# importlib.resources can locate it post-install.
|
|
[tool.hatch.build.targets.wheel.force-include]
|
|
"src/ratatoskr/web/static" = "ratatoskr/web/static"
|
|
|
|
[tool.pytest.ini_options]
|
|
asyncio_mode = "auto"
|
|
testpaths = ["tests"]
|
|
|
|
[tool.ruff]
|
|
line-length = 100
|
|
target-version = "py312"
|
|
|
|
[tool.ruff.lint]
|
|
select = ["E", "F", "I", "B", "UP", "RUF"]
|
|
|
|
[tool.mypy]
|
|
python_version = "3.12"
|
|
strict = true
|