atlasbot: add internal endpoint and portal wiring

This commit is contained in:
Brad Stein 2026-01-26 22:43:58 -03:00
parent 689bf10995
commit c8662a624e
5 changed files with 85 additions and 1 deletions

View File

@ -28,6 +28,7 @@ spec:
{{ with secret "kv/data/atlas/shared/chat-ai-keys-runtime" }}
export CHAT_KEY_MATRIX="{{ .Data.data.matrix }}"
export CHAT_KEY_HOMEPAGE="{{ .Data.data.homepage }}"
export AI_ATLASBOT_TOKEN="{{ .Data.data.homepage }}"
{{ end }}
{{ with secret "kv/data/atlas/shared/portal-e2e-client" }}
export PORTAL_E2E_CLIENT_ID="{{ .Data.data.client_id }}"
@ -66,6 +67,10 @@ spec:
value: qwen2.5-coder:7b-instruct-q4_0
- name: AI_CHAT_TIMEOUT_SEC
value: "480"
- name: AI_ATLASBOT_ENDPOINT
value: http://atlasbot.comms.svc.cluster.local:8090/v1/answer
- name: AI_ATLASBOT_TIMEOUT_SEC
value: "5"
- name: AI_NODE_NAME
valueFrom:
fieldRef:

View File

@ -16,7 +16,7 @@ spec:
labels:
app: atlasbot
annotations:
checksum/atlasbot-configmap: manual-atlasbot-24
checksum/atlasbot-configmap: manual-atlasbot-25
vault.hashicorp.com/agent-inject: "true"
vault.hashicorp.com/role: "comms"
vault.hashicorp.com/agent-inject-secret-turn-secret: "kv/data/atlas/comms/turn-shared-secret"
@ -87,6 +87,11 @@ spec:
value: "480"
- name: ATLASBOT_THINKING_INTERVAL_SEC
value: "120"
- name: ATLASBOT_HTTP_PORT
value: "8090"
ports:
- name: http
containerPort: 8090
resources:
requests:
cpu: 100m

View File

@ -0,0 +1,15 @@
apiVersion: v1
kind: Service
metadata:
name: atlasbot
namespace: comms
labels:
app: atlasbot
spec:
selector:
app: atlasbot
ports:
- name: http
port: 8090
targetPort: 8090
type: ClusterIP

View File

@ -14,6 +14,7 @@ resources:
- guest-register-deployment.yaml
- guest-register-service.yaml
- atlasbot-deployment.yaml
- atlasbot-service.yaml
- wellknown.yaml
- atlasbot-rbac.yaml
- mas-secrets-ensure-rbac.yaml

View File

@ -5,6 +5,7 @@ import re
import ssl
import threading
import time
from http.server import BaseHTTPRequestHandler, HTTPServer
from typing import Any
from urllib import error, parse, request
@ -1089,6 +1090,62 @@ def _normalize_reply(value: Any) -> str:
return text
# Internal HTTP endpoint for cluster answers (website uses this).
class _AtlasbotHandler(BaseHTTPRequestHandler):
server_version = "AtlasbotHTTP/1.0"
def _write_json(self, status: int, payload: dict[str, Any]):
body = json.dumps(payload).encode("utf-8")
self.send_response(status)
self.send_header("Content-Type", "application/json")
self.send_header("Content-Length", str(len(body)))
self.end_headers()
self.wfile.write(body)
def _authorized(self) -> bool:
if not ATLASBOT_INTERNAL_TOKEN:
return True
token = self.headers.get("X-Internal-Token", "")
return token == ATLASBOT_INTERNAL_TOKEN
def do_GET(self): # noqa: N802
if self.path == "/health":
self._write_json(200, {"status": "ok"})
return
self._write_json(404, {"error": "not_found"})
def do_POST(self): # noqa: N802
if self.path != "/v1/answer":
self._write_json(404, {"error": "not_found"})
return
if not self._authorized():
self._write_json(401, {"error": "unauthorized"})
return
try:
length = int(self.headers.get("Content-Length", "0"))
except ValueError:
length = 0
raw = self.rfile.read(length) if length > 0 else b""
try:
payload = json.loads(raw.decode("utf-8")) if raw else {}
except json.JSONDecodeError:
self._write_json(400, {"error": "invalid_json"})
return
prompt = str(payload.get("prompt") or payload.get("question") or "").strip()
if not prompt:
self._write_json(400, {"error": "missing_prompt"})
return
inventory = node_inventory_live()
answer = structured_answer(prompt, inventory=inventory, metrics_summary="")
self._write_json(200, {"answer": answer})
def _start_http_server():
server = HTTPServer(("0.0.0.0", ATLASBOT_HTTP_PORT), _AtlasbotHandler)
thread = threading.Thread(target=server.serve_forever, daemon=True)
thread.start()
# Conversation state.
history = collections.defaultdict(list) # (room_id, sender|None) -> list[str] (short transcript)
@ -1326,6 +1383,7 @@ def login_with_retry():
def main():
load_kb()
_start_http_server()
token = login_with_retry()
try:
room_id = resolve_alias(token, ROOM_ALIAS)