mirror of
https://github.com/kevinveenbirkenbach/computer-playbook.git
synced 2026-11-07 03:15:56 +00:00
Of the 76 open code scanning alerts, 39 point at code that can change. svc-ai-mcp-adapter: - A path argument that is empty or made only of dots is refused. Percent-encoding keeps a separator inside its segment, but "." and ".." need none, so an upstream that resolves dot segments could answer from a path the contract does not name. - parse_duration splits on the units. The pattern it used before rescanned a long run of digits from every start position. Tests and the README generators: - Every Jinja environment built with autoescape=False and a "noqa: S701" uses select_autoescape now, as six test modules and utils/templating/jinja.py already did. It escapes templates named *.html, *.htm and *.xml, which none of these call sites loads. - Dead code goes: a doubled "rel" block in the email lint, an unread _SKIP_DIRS, and a module that _resolve returned to no caller. - Two "except ...: pass" blocks become contextlib.suppress and assertRaises. - Nine test modules import unittest.mock one way instead of two, and one lookup test imports its module once. Closes #807 Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
96 lines
3.2 KiB
Python
96 lines
3.2 KiB
Python
"""OpenClaw refuses to boot on a model entry that misses a key.
|
|
|
|
The gateway validates its whole configuration before it serves anything, and
|
|
a rejected file is not a degraded start but a crash loop: OpenClaw retries,
|
|
trips its own restart breaker after four unclean boots, and the container
|
|
exits 128 while the deploy sits in the health check until it gives up.
|
|
|
|
The provider block reached the repository without ever being rendered in a
|
|
test - every case here passed OPENCLAW_LITELLM_ENABLED=False, so the block was
|
|
skipped and its shape was never checked against anything.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import importlib.util
|
|
import json
|
|
import unittest
|
|
|
|
from jinja2 import Environment, FileSystemLoader, select_autoescape
|
|
|
|
from . import PROJECT_ROOT
|
|
|
|
OPENCLAW = PROJECT_ROOT / "roles/web-app-openclaw/templates"
|
|
FILTERS = PROJECT_ROOT / "plugins/filter/mcp/authorization.py"
|
|
|
|
MODEL = "qwen2.5:0.5b"
|
|
|
|
CONTEXT = {
|
|
"OPENCLAW_URL": "https://claw.example.org",
|
|
"OPENCLAW_LITELLM_ENABLED": True,
|
|
"OPENCLAW_LITELLM_PROVIDER": "litellm",
|
|
"OPENCLAW_LITELLM_MODEL": MODEL,
|
|
"OPENCLAW_LITELLM_BASE_URL": "http://litellm:4000/v1",
|
|
"OPENCLAW_LITELLM_API_KEY": "sk-" + "x" * 20,
|
|
"OPENCLAW_MCP_SERVERS": [],
|
|
}
|
|
|
|
|
|
def _filters() -> dict:
|
|
spec = importlib.util.spec_from_file_location("mcp_authorization", FILTERS)
|
|
module = importlib.util.module_from_spec(spec)
|
|
spec.loader.exec_module(module)
|
|
filters = dict(module.FilterModule().filters())
|
|
filters.update({"to_json": json.dumps, "bool": bool})
|
|
return filters
|
|
|
|
|
|
def _render(**overrides) -> dict:
|
|
"""Return the gateway config as OpenClaw would parse it.
|
|
|
|
Args:
|
|
overrides: context values replacing the defaults.
|
|
"""
|
|
env = Environment(
|
|
loader=FileSystemLoader(str(OPENCLAW)), autoescape=select_autoescape()
|
|
)
|
|
env.filters.update(_filters())
|
|
return json.loads(
|
|
env.get_template("openclaw.json.j2").render(**{**CONTEXT, **overrides})
|
|
)
|
|
|
|
|
|
class TestOpenClawModelProvider(unittest.TestCase):
|
|
def _entry(self, **overrides) -> dict:
|
|
"""Return the provider's single model entry.
|
|
|
|
Args:
|
|
overrides: context values replacing the defaults.
|
|
"""
|
|
return _render(**overrides)["models"]["providers"]["litellm"]["models"][0]
|
|
|
|
def test_the_model_entry_carries_both_keys_the_gateway_validates(self) -> None:
|
|
self.assertEqual({"id": MODEL, "name": MODEL}, self._entry())
|
|
|
|
def test_the_name_matches_the_id(self) -> None:
|
|
"""Which key reaches the API is the upstream's choice, not ours."""
|
|
entry = self._entry()
|
|
self.assertEqual(entry["id"], entry["name"])
|
|
|
|
def test_the_primary_agent_model_names_the_same_provider(self) -> None:
|
|
rendered = _render()
|
|
self.assertEqual(
|
|
f"litellm/{MODEL}",
|
|
rendered["agents"]["defaults"]["model"]["primary"],
|
|
)
|
|
self.assertIn("litellm", rendered["models"]["providers"])
|
|
|
|
def test_the_block_disappears_when_litellm_is_off(self) -> None:
|
|
rendered = _render(OPENCLAW_LITELLM_ENABLED=False)
|
|
self.assertNotIn("models", rendered)
|
|
self.assertNotIn("agents", rendered)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|