From 5af516f9c209a9a7248b8fd11f0456fe3cda19c5 Mon Sep 17 00:00:00 2001 From: jenkins Date: Tue, 29 Sep 2026 08:09:48 -0500 Subject: [PATCH] hermes: pin account-listed Claude context variant and bound ingress --- scripts/ops/hermes_suite_probe.py | 6 +++++- services/hermes/scripts/suite_backends.py | 8 ++++++-- services/hermes/scripts/suite_contract.py | 1 + services/hermes/suite-planner-deployment.yaml | 2 +- services/hermes/suite-planner-ingress.yaml | 14 +++++++++++++- 5 files changed, 26 insertions(+), 5 deletions(-) diff --git a/scripts/ops/hermes_suite_probe.py b/scripts/ops/hermes_suite_probe.py index 4b136fac..e96551c2 100644 --- a/scripts/ops/hermes_suite_probe.py +++ b/scripts/ops/hermes_suite_probe.py @@ -60,7 +60,11 @@ def api(path, value=None, *, key=None, token=None, method=None): return response.status, json.load(response) except HTTPError as exc: try: - return exc.code, json.load(exc) + try: + value = json.load(exc) + except ValueError: + value = {"error": {"code": "request_too_large" if exc.code == 413 else "http_error"}} + return exc.code, value finally: exc.close() diff --git a/services/hermes/scripts/suite_backends.py b/services/hermes/scripts/suite_backends.py index e2f7a79c..66c51bb4 100644 --- a/services/hermes/scripts/suite_backends.py +++ b/services/hermes/scripts/suite_backends.py @@ -97,7 +97,7 @@ def claude_command(model, max_cost): "--strict-mcp-config", "--mcp-config", '{"mcpServers":{}}', "--setting-sources", "", "--disable-slash-commands", "--permission-mode", "dontAsk", "--no-chrome", - "--model", model, "--effort", "medium", "--max-budget-usd", str(max_cost), + "--model", MODELS["claude"]["cli_model"], "--effort", "medium", "--max-budget-usd", str(max_cost), "--max-turns", "3", "--system-prompt", SYSTEM, "--json-schema", encoded(SCHEMA).decode()] @@ -111,6 +111,7 @@ def claude_environment(directory, token): for key in ("DISABLE_COMPACT", "DISABLE_AUTO_COMPACT", "DISABLE_TELEMETRY", "DISABLE_ERROR_REPORTING", "DISABLE_AUTOUPDATER", "DISABLE_UPDATES", "DISABLE_PROMPT_CACHING", "CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC", + "CLAUDE_CODE_DISABLE_BACKGROUND_TASKS", "CLAUDE_CODE_DISABLE_TERMINAL_TITLE", "CLAUDE_CODE_DISABLE_AUTO_MEMORY", "CLAUDE_CODE_SKIP_PROMPT_HISTORY"): env[key] = "1" return env @@ -161,7 +162,10 @@ def parse_claude(raw, expected_model): if not models or set(models) - aliases: observed = [name if re.fullmatch(r"claude-[a-z0-9.-]+(?:\[1m\])?", name) else "unrecognized" for name in models] - raise Problem("model_changed", 502, observed_models=observed) + limits_seen = [{k: v for k, v in entry.items() + if k in {"contextWindow", "maxOutputTokens"} and type(v) is int} + for entry in models.values() if isinstance(entry, dict)] + raise Problem("model_changed", 502, observed_models=observed, limits=limits_seen) for limits in models.values(): if (limits.get("contextWindow") != 1000000 or limits.get("maxOutputTokens") != 64000 or limits.get("canonicalModel") != expected_model diff --git a/services/hermes/scripts/suite_contract.py b/services/hermes/scripts/suite_contract.py index b2f606e3..f2d28163 100644 --- a/services/hermes/scripts/suite_contract.py +++ b/services/hermes/scripts/suite_contract.py @@ -20,6 +20,7 @@ MODELS = { "output": 2048, "overhead": 1024, "backend": "ollama-model-gate", "enabled": True, "reasoning": "none"}, "claude": {"model": "claude-fable-5", "context": 1000000, + "cli_model": "claude-fable-5[1m]", "output": 64000, "overhead": 8192, "backend": "claude-code-2.1.226", "enabled": True, "reasoning": "medium"}, "codex": {"model": "gpt-6-astra", "context": 258400, diff --git a/services/hermes/suite-planner-deployment.yaml b/services/hermes/suite-planner-deployment.yaml index d4cc7a6d..c176967f 100644 --- a/services/hermes/suite-planner-deployment.yaml +++ b/services/hermes/suite-planner-deployment.yaml @@ -36,7 +36,7 @@ spec: app: hermes-suite-planner annotations: fluentbit.io/exclude: "true" - ai.bstein.dev/config-rev: suite-v3-20260929 + ai.bstein.dev/config-rev: suite-v4-20260929 vault.hashicorp.com/agent-inject: "true" vault.hashicorp.com/agent-pre-populate-only: "true" vault.hashicorp.com/agent-init-first: "true" diff --git a/services/hermes/suite-planner-ingress.yaml b/services/hermes/suite-planner-ingress.yaml index 9c18fd9b..077bc191 100644 --- a/services/hermes/suite-planner-ingress.yaml +++ b/services/hermes/suite-planner-ingress.yaml @@ -9,6 +9,18 @@ spec: prefixes: [/suite-planning] --- apiVersion: traefik.io/v1alpha1 +kind: Middleware +metadata: + name: hermes-suite-body-limit + namespace: hermes +spec: + buffering: + maxRequestBodyBytes: 1048576 + memRequestBodyBytes: 1048576 + maxResponseBodyBytes: 2097152 + memResponseBodyBytes: 2097152 +--- +apiVersion: traefik.io/v1alpha1 kind: ServersTransport metadata: name: hermes-suite-planner @@ -26,7 +38,7 @@ metadata: namespace: hermes annotations: traefik.ingress.kubernetes.io/router.entrypoints: websecure - traefik.ingress.kubernetes.io/router.middlewares: hermes-hermes-model-gate-lan-allowlist@kubernetescrd,hermes-hermes-suite-prefix@kubernetescrd + traefik.ingress.kubernetes.io/router.middlewares: hermes-hermes-model-gate-lan-allowlist@kubernetescrd,hermes-hermes-suite-body-limit@kubernetescrd,hermes-hermes-suite-prefix@kubernetescrd traefik.ingress.kubernetes.io/router.tls: "true" traefik.ingress.kubernetes.io/service.serverstransport: hermes-hermes-suite-planner@kubernetescrd spec: