feat: publish CodexPi contest snapshot
Some checks are pending
Qualité / tests (push) Waiting to run

This commit is contained in:
CodexPi
2026-11-14 20:23:59 +01:00
commit 995b17a6e2
295 changed files with 36803 additions and 0 deletions

View File

@@ -0,0 +1,288 @@
from __future__ import annotations
import importlib.util
import json
import threading
import time
import urllib.error
import urllib.request
from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer
from pathlib import Path
import pytest
from codexpi.database import Database
from codexpi.local_ai_bridge_service import LocalAIBridgeError, LocalAIBridgeService
MODELS = [
{
"name": "qwen2.5-coder:14b",
"size": 8_988_000_000,
"details": {"parameter_size": "14.8B", "quantization_level": "Q4_K_M"},
"capabilities": ["completion", "tools"],
},
{
"name": "gemma3:12b",
"size": 8_149_000_000,
"details": {"parameter_size": "12.2B", "quantization_level": "Q4_K_M"},
"capabilities": ["completion", "vision"],
},
]
def load_bridge_script():
path = Path(__file__).parents[1] / "scripts" / "codexpi_ai_bridge.py"
spec = importlib.util.spec_from_file_location("codexpi_ai_bridge_test", path)
assert spec and spec.loader
module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(module)
return module
class FakeOllamaHandler(BaseHTTPRequestHandler):
protocol_version = "HTTP/1.0"
def log_message(self, *_args) -> None:
return
def _send(self, value: dict, status: int = 200) -> None:
body = json.dumps(value).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 do_GET(self) -> None:
if self.path in {"/api/tags", "/v1/models"}:
self._send({"models": MODELS})
elif self.path == "/api/experimental/model-recommendations":
self._send({"recommendations": [{
"model": "qwen3:8b",
"description": "Local reasoning and tools",
"vram_bytes": 6_000_000_000,
"thinking": {"values": [False, True], "default": True},
}]})
else:
self._send({"error": "missing"}, 404)
def do_POST(self) -> None:
length = int(self.headers.get("Content-Length") or 0)
payload = json.loads(self.rfile.read(length) or b"{}")
if self.path == "/v1/chat/completions":
self._send({"choices": [{"message": {"role": "assistant", "content": payload.get("model")}}]})
elif self.path == "/api/show":
self._send({"capabilities": ["completion", "tools"]})
elif self.path == "/api/pull":
rows = [
{"status": "pulling manifest"},
{"status": "pulling layer", "digest": "sha256:one", "total": 100, "completed": 35},
{"status": "pulling layer", "digest": "sha256:one", "total": 100, "completed": 100},
{"status": "verifying sha256 digest"},
{"status": "success"},
]
body = b"".join(json.dumps(item).encode("utf-8") + b"\n" for item in rows)
self.send_response(200)
self.send_header("Content-Type", "application/x-ndjson")
self.send_header("Content-Length", str(len(body)))
self.end_headers()
self.wfile.write(body)
else:
self._send({"error": "missing"}, 404)
@pytest.fixture
def fake_ollama():
server = ThreadingHTTPServer(("127.0.0.1", 0), FakeOllamaHandler)
thread = threading.Thread(target=server.serve_forever, daemon=True)
thread.start()
try:
yield server
finally:
server.shutdown()
server.server_close()
thread.join(timeout=2)
def test_local_ai_pairing_encrypts_token_and_writes_isolated_opencode_config(tmp_path, fake_ollama):
db = Database(tmp_path / "codexpi.db")
db.initialize()
service = LocalAIBridgeService(db, "test-secret", tmp_path / "data")
pairing = service.create_pairing("owner")
token = "a" * 48
bridge = service.pair(
pairing["pairing_id"], pairing["code"], "PC bureau", "Windows",
"127.0.0.1", fake_ollama.server_address[1], token,
)
assert bridge["connected"] is True
assert bridge["default_model"] == "qwen2.5-coder:14b"
assert bridge["models"][0]["capabilities"] == ["completion", "tools"]
assert "token" not in bridge and "token_encrypted" not in bridge
stored = db.one("SELECT token_encrypted FROM local_ai_bridges WHERE id=?", (bridge["id"],))
assert stored and stored["token_encrypted"] != token
assert service.token_path.read_text(encoding="utf-8") == token
config = json.loads(service.config_path.read_text(encoding="utf-8"))
assert config["model"] == "ollama/qwen2.5-coder:14b"
assert config["providers"]["ollama"]["settings"]["baseURL"].endswith("/v1")
assert token not in service.config_path.read_text(encoding="utf-8")
with pytest.raises(LocalAIBridgeError, match="déjà utilisé"):
service.pair(
pairing["pairing_id"], pairing["code"], "PC bureau", "Windows",
"127.0.0.1", fake_ollama.server_address[1], token,
)
changed = service.configure(bridge["id"], "gemma3:12b")
assert changed["default_model"] == "gemma3:12b"
assert json.loads(service.config_path.read_text(encoding="utf-8"))["model"] == "ollama/gemma3:12b"
service.revoke(bridge["id"])
assert not service.config_path.exists() and not service.token_path.exists()
def test_local_ai_service_rejects_public_addresses(tmp_path):
db = Database(tmp_path / "codexpi.db")
db.initialize()
service = LocalAIBridgeService(db, "test-secret", tmp_path / "data")
pairing = service.create_pairing("owner")
with pytest.raises(LocalAIBridgeError, match="réseau local"):
service.pair(pairing["pairing_id"], pairing["code"], "PC", "Windows", "8.8.8.8", 11435, "x" * 48)
def test_invalid_pairing_code_never_triggers_network_probe(tmp_path, monkeypatch):
db = Database(tmp_path / "codexpi.db")
db.initialize()
service = LocalAIBridgeService(db, "test-secret", tmp_path / "data")
pairing = service.create_pairing("owner")
probed = False
def fail_if_probed(*_args, **_kwargs):
nonlocal probed
probed = True
raise AssertionError("the bridge must not be contacted")
monkeypatch.setattr(service, "probe", fail_if_probed)
with pytest.raises(LocalAIBridgeError, match="Code d’association invalide"):
service.pair(
pairing["pairing_id"], "wrong-pairing-code", "PC", "Windows",
"127.0.0.1", 11435, "x" * 48,
)
assert probed is False
def test_pc_bridge_requires_bearer_and_only_proxies_ollama_routes(fake_ollama):
bridge = load_bridge_script()
upstream = f"http://127.0.0.1:{fake_ollama.server_address[1]}"
server = bridge.create_server("127.0.0.1", 0, upstream, "private-token")
thread = threading.Thread(target=server.serve_forever, daemon=True)
thread.start()
base = f"http://127.0.0.1:{server.server_address[1]}"
try:
with pytest.raises(urllib.error.HTTPError) as unauthorized:
urllib.request.urlopen(base + "/api/tags", timeout=2)
assert unauthorized.value.code == 401
request = urllib.request.Request(base + "/api/tags", headers={"Authorization": "Bearer private-token"})
with urllib.request.urlopen(request, timeout=2) as response:
assert json.loads(response.read())["models"][0]["name"] == "qwen2.5-coder:14b"
forbidden = urllib.request.Request(base + "/api/delete", headers={"Authorization": "Bearer private-token"})
with pytest.raises(urllib.error.HTTPError) as missing:
urllib.request.urlopen(forbidden, timeout=2)
assert missing.value.code == 404
chat = urllib.request.Request(
base + "/v1/chat/completions",
data=json.dumps({"model": "qwen2.5-coder:14b", "messages": []}).encode("utf-8"),
method="POST",
headers={"Authorization": "Bearer private-token", "Content-Type": "application/json"},
)
with urllib.request.urlopen(chat, timeout=2) as response:
assert json.loads(response.read())["choices"][0]["message"]["content"] == "qwen2.5-coder:14b"
pull = urllib.request.Request(
base + "/api/pull",
data=json.dumps({"model": "qwen3:8b", "stream": True}).encode("utf-8"),
method="POST",
headers={"Authorization": "Bearer private-token", "Content-Type": "application/json"},
)
with urllib.request.urlopen(pull, timeout=2) as response:
events = [json.loads(line) for line in response if line.strip()]
assert events[-1]["status"] == "success"
finally:
server.shutdown()
server.server_close()
thread.join(timeout=2)
def test_local_ai_settings_flow_exposes_models_without_exposing_token(logged_in, monkeypatch):
client, app, _, _, headers = logged_in
monkeypatch.setattr(app.state.local_ai, "probe", lambda *_args, **_kwargs: app.state.local_ai._models({"models": MODELS}))
created = client.post("/api/local-ai/pairings", headers=headers)
assert created.status_code == 201
pairing = created.json()
paired = client.post("/api/local-ai/agent/pair", json={
"pairing_id": pairing["pairing_id"],
"code": pairing["code"],
"name": "RTX 3060",
"platform": "Windows",
"address": "127.0.0.1",
"port": 11435,
"token": "z" * 48,
})
assert paired.status_code == 201
bridge = paired.json()
assert bridge["default_model"] == "qwen2.5-coder:14b"
assert "token" not in json.dumps(bridge)
listed = client.get("/api/local-ai/bridges")
assert listed.status_code == 200 and listed.json()[0]["name"] == "RTX 3060"
options = client.get("/api/codex/options").json()
assert options["local_default_model"] == "ollama/qwen2.5-coder:14b"
assert options["local_models"][0]["id"] == "ollama/qwen2.5-coder:14b"
assert next(item for item in options["engines"] if item["id"] == "opencode")["label"] == "OpenCode · PC local"
assert client.get("/api/local-ai/connector").status_code == 200
assert client.get("/api/local-ai/guide").status_code == 200
catalog = client.get(f"/api/local-ai/bridges/{bridge['id']}/catalog")
assert catalog.status_code == 200
assert any(item["name"] == "qwen2.5-coder:14b" and item["installed"] for item in catalog.json()["models"])
updated = client.put(
f"/api/local-ai/bridges/{bridge['id']}", headers=headers,
json={"default_model": "gemma3:12b", "active": True},
)
assert updated.status_code == 200 and updated.json()["default_model"] == "gemma3:12b"
revoked = client.delete(f"/api/local-ai/bridges/{bridge['id']}", headers=headers)
assert revoked.status_code == 200
assert client.get("/api/local-ai/bridges").json() == []
def test_local_ai_pull_tracks_real_stream_progress(tmp_path, fake_ollama):
db = Database(tmp_path / "codexpi.db")
db.initialize()
service = LocalAIBridgeService(db, "test-secret", tmp_path / "data")
pairing = service.create_pairing("owner")
bridge = service.pair(
pairing["pairing_id"], pairing["code"], "PC bureau", "Windows",
"127.0.0.1", fake_ollama.server_address[1], "p" * 48,
)
catalog = service.catalog(bridge["id"])
recommended = next(item for item in catalog["models"] if item["name"] == "qwen3:8b")
assert recommended["recommended"] is True
assert recommended["fit"] in {"ideal", "possible", "heavy"}
job = service.start_pull(bridge["id"], "qwen3:8b")
deadline = time.monotonic() + 3
while time.monotonic() < deadline:
current = service.list_pulls(bridge["id"])[0]
if current["status"] not in {"queued", "downloading", "verifying"}:
break
time.sleep(0.02)
assert current["status"] == "completed"
assert current["progress"] == 100.0
assert current["total"] == 100
assert json.loads(service.pulls_path.read_text(encoding="utf-8"))[0]["status"] == "completed"