Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bcdcd71090 |
+2
-1
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|||||||
|
|
||||||
[project]
|
[project]
|
||||||
name = "ratatoskr"
|
name = "ratatoskr"
|
||||||
version = "0.17.1"
|
version = "0.17.2"
|
||||||
description = "Worldtree Conversation API debug TUI — multi-pane observability dashboard"
|
description = "Worldtree Conversation API debug TUI — multi-pane observability dashboard"
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
requires-python = ">=3.12"
|
requires-python = ">=3.12"
|
||||||
@@ -47,6 +47,7 @@ dev = [
|
|||||||
[project.scripts]
|
[project.scripts]
|
||||||
ratatoskr = "ratatoskr.cli:main"
|
ratatoskr = "ratatoskr.cli:main"
|
||||||
ratatoskr-web = "ratatoskr.web.entrypoint:main"
|
ratatoskr-web = "ratatoskr.web.entrypoint:main"
|
||||||
|
ratatoskr-provider = "ratatoskr.provider.serve:main"
|
||||||
|
|
||||||
[project.urls]
|
[project.urls]
|
||||||
Repository = "https://gitea.phasefinal.com/vh/ratatoskr"
|
Repository = "https://gitea.phasefinal.com/vh/ratatoskr"
|
||||||
|
|||||||
@@ -0,0 +1,40 @@
|
|||||||
|
"""Runnable entrypoint: serve the affect provider as an ASGI app.
|
||||||
|
|
||||||
|
For the live negotiation smoke against a Worldtree instance. Config from env:
|
||||||
|
- RATATOSKR_HEIMDALL_KEY (required): HS256 shared key for the consumer, utf-8.
|
||||||
|
- RATATOSKR_AFFECT_DB (default "affect.db"): SQLite path; ":memory:" = ephemeral.
|
||||||
|
- RATATOSKR_CONSUMER_ID (default "ratatoskr").
|
||||||
|
- RATATOSKR_PROVIDER_HOST (default "0.0.0.0"), RATATOSKR_PROVIDER_PORT (default 8390).
|
||||||
|
"""
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import os
|
||||||
|
from collections.abc import Mapping
|
||||||
|
|
||||||
|
from ratatoskr.provider.affect_store import build_affect_provider_app, open_affect_store
|
||||||
|
|
||||||
|
|
||||||
|
def build_app_from_env(env: Mapping[str, str] | None = None):
|
||||||
|
"""Build the affect ASGI app from environment config (testable seam)."""
|
||||||
|
env = os.environ if env is None else env
|
||||||
|
key = env.get("RATATOSKR_HEIMDALL_KEY")
|
||||||
|
if not key:
|
||||||
|
raise RuntimeError(
|
||||||
|
"RATATOSKR_HEIMDALL_KEY is required to serve the affect provider"
|
||||||
|
)
|
||||||
|
store = open_affect_store(env.get("RATATOSKR_AFFECT_DB", "affect.db"))
|
||||||
|
return build_affect_provider_app(
|
||||||
|
store,
|
||||||
|
heimdall_key=key.encode(),
|
||||||
|
consumer_id=env.get("RATATOSKR_CONSUMER_ID", "ratatoskr"),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def main() -> None:
|
||||||
|
import uvicorn
|
||||||
|
|
||||||
|
uvicorn.run(
|
||||||
|
build_app_from_env(),
|
||||||
|
host=os.environ.get("RATATOSKR_PROVIDER_HOST", "0.0.0.0"),
|
||||||
|
port=int(os.environ.get("RATATOSKR_PROVIDER_PORT", "8390")),
|
||||||
|
)
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
"""Tests for the affect-provider serve entrypoint (ratatoskr.provider.serve).
|
||||||
|
|
||||||
|
Only the env -> app seam is unit-tested; uvicorn.run is the untestable shell.
|
||||||
|
"""
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
from ratatoskr.provider.serve import build_app_from_env
|
||||||
|
|
||||||
|
|
||||||
|
def test_build_app_from_env_requires_heimdall_key():
|
||||||
|
with pytest.raises(RuntimeError):
|
||||||
|
build_app_from_env({"RATATOSKR_AFFECT_DB": ":memory:"})
|
||||||
|
|
||||||
|
|
||||||
|
def test_build_app_from_env_builds_app_with_routes():
|
||||||
|
app = build_app_from_env(
|
||||||
|
{"RATATOSKR_HEIMDALL_KEY": "shared-secret", "RATATOSKR_AFFECT_DB": ":memory:"}
|
||||||
|
)
|
||||||
|
paths = {getattr(r, "path", None) for r in app.routes}
|
||||||
|
assert "/bifrost/handshake" in paths
|
||||||
|
assert "/bifrost/affect-call" in paths
|
||||||
Reference in New Issue
Block a user