fix: route all agent loopback calls through internal_api_base() helper (#3322)

#2753 made the agent loopback base port-configurable but only for
_COOKBOOK_BASE in tool_implementations. Several other in-process loopback
calls still hardcoded http://localhost:7000 and broke off port 7000:
cookbook_serve_lifecycle (model-endpoints x2, shell/exec), builtin_actions
(model/serve), task_routes (calendar x3), and the gallery/email calls in
tool_implementations.

Extract the resolution (ODYSSEUS_INTERNAL_BASE / APP_PORT / 7000 fallback,
127.0.0.1 to avoid IPv6 ambiguity) into core.constants.internal_api_base()
and route every call site through it. Rename the now-misnamed _COOKBOOK_BASE
to _INTERNAL_BASE since it serves gallery/email/calendar/serve too. Adds a
test for the resolver plus a regression guard against reintroducing the
literal.

Part of #2752.

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Kenny Van de Maele
2026-06-07 23:22:09 +02:00
committed by GitHub
parent d85c5e335e
commit 76c1f42ab0
6 changed files with 116 additions and 53 deletions
+4 -3
View File
@@ -19,6 +19,7 @@ import time
from pathlib import Path
import httpx
from core.constants import internal_api_base
logger = logging.getLogger(__name__)
@@ -58,7 +59,7 @@ async def _delete_endpoint_for_task(task: dict) -> None:
try:
async with httpx.AsyncClient(timeout=8) as client:
r = await client.get(
"http://localhost:7000/api/model-endpoints",
f"{internal_api_base()}/api/model-endpoints",
headers=_internal_headers(),
)
if r.status_code >= 400:
@@ -73,7 +74,7 @@ async def _delete_endpoint_for_task(task: dict) -> None:
ep = next((e for e in eps if hostport in (e.get("base_url") or "")), None)
if ep:
await client.delete(
f"http://localhost:7000/api/model-endpoints/{ep['id']}",
f"{internal_api_base()}/api/model-endpoints/{ep['id']}",
headers=_internal_headers(),
)
logger.info(
@@ -108,7 +109,7 @@ async def _stop_serve(session_id: str, remote_host: str = "", ssh_port: str = ""
try:
async with httpx.AsyncClient(timeout=15) as client:
r = await client.post(
"http://localhost:7000/api/shell/exec",
f"{internal_api_base()}/api/shell/exec",
json={"command": cmd},
headers=_internal_headers(),
)