Compare commits

..

2 Commits

4 changed files with 47 additions and 4 deletions

View File

@ -19,7 +19,7 @@ site config:
{
"translation": {
"provider": "geniehive",
"base_url": "http://127.0.0.1:8800",
"base_url": "http://172.24.50.65:8800",
"model": "scientific_translator",
"api_key": "change-me-client-key",
"timeout": 120,
@ -30,11 +30,11 @@ site config:
Recommended meaning of the fields:
- `base_url`: GenieHive control-plane URL or a reverse-proxied client URL.
- `base_url`: GenieHive control-plane URL or a reverse-proxied client URL. For the TalkOrigins proof-of-concept from `bwng.us`, use `http://172.24.50.65:8800`.
- `provider`: translation backend. The supported provider is currently
`geniehive`.
- `model`: a GenieHive role ID or directly addressable model name.
- `api_key`: the GenieHive client key.
- `api_key`: the GenieHive client key, sent as the `X-Api-Key` request header.
- `timeout`: request timeout in seconds.
- `system_prompt`: the translation policy for the client.
@ -95,6 +95,12 @@ For local development:
- `model`: a translation-focused GenieHive role
- `timeout`: `120`
For the current ZeroTier-backed TalkOrigins proof-of-concept:
- `base_url`: `http://172.24.50.65:8800`
- `model`: `scientific_translator`
- `api_key`: `change-me-client-key`
For production or a LAN host:
- use the reverse-proxied GenieHive URL

View File

@ -34,6 +34,14 @@
{ "code": "hi", "name": "हिन्दी" }
]
},
"translation": {
"provider": "geniehive",
"base_url": "http://172.24.50.65:8800",
"model": "scientific_translator",
"api_key": "change-me-client-key",
"timeout": 120,
"system_prompt": "You are a careful scientific translator. Preserve meaning, structure, citations, and technical terms. Return only the translation."
},
"navigation": [
{ "label": "Start Here", "href": "#start" },
{ "label": "Key Resources", "href": "#resources" },

View File

@ -60,7 +60,7 @@ class GenieHiveTranslator:
data = json.dumps(payload).encode("utf-8")
headers = {"Content-Type": "application/json"}
if self.config.api_key:
headers["Authorization"] = f"Bearer {self.config.api_key}"
headers["X-Api-Key"] = self.config.api_key
req = request.Request(url, data=data, headers=headers, method="POST")
try:
with request.urlopen(req, timeout=self.config.timeout) as resp:

View File

@ -5,6 +5,7 @@ import unittest
from pathlib import Path
from types import SimpleNamespace
import sys
from unittest.mock import patch
ROOT = Path(__file__).resolve().parents[1]
sys.path.insert(0, str(ROOT))
@ -313,6 +314,34 @@ class SciSiteForgeTests(unittest.TestCase):
self.assertIn("Spanish", user_text)
self.assertIn("evolución", user_text)
def test_geniehive_translator_uses_geniehive_api_key_header(self) -> None:
translator = GenieHiveTranslator(
TranslationConfig(base_url="http://geniehive.local:8800", model="translation-role", api_key="abc123")
)
captured: dict[str, object] = {}
class FakeResponse:
def __enter__(self):
return self
def __exit__(self, exc_type, exc, tb):
return False
def read(self):
return b'{"choices":[{"message":{"content":"Hola"}}]}'
def fake_urlopen(req, timeout):
captured["headers"] = dict(req.header_items())
captured["timeout"] = timeout
return FakeResponse()
with patch("scisiteforge.translations.request.urlopen", fake_urlopen):
self.assertEqual(translator.translate("Hello", "Spanish"), "Hola")
headers = captured["headers"]
self.assertEqual(headers["X-api-key"], "abc123")
self.assertNotIn("Authorization", headers)
def test_translate_site_builds_translator_from_config(self) -> None:
from tempfile import TemporaryDirectory