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,374 @@
from __future__ import annotations
import json
import sys
PNG = b"\x89PNG\r\n\x1a\n" + b"test-image"
def create_plain_conversation(logged_in):
client, app, projects, _, headers = logged_in
folder = projects / "queue-project"
folder.mkdir()
project = client.post("/api/projects", headers=headers, json={"name": "Queue", "path": str(folder)}).json()
conversation = client.post(
f"/api/projects/{project['id']}/conversations", headers=headers, json={"title": "Photos"}
).json()
return client, app, project, conversation, headers
def test_image_upload_is_authenticated_validated_and_private(logged_in):
client, _, _, conversation, headers = create_plain_conversation(logged_in)
uploaded = client.post(
f"/api/conversations/{conversation['id']}/attachments",
headers=headers,
files={"image": ("screen.png", PNG, "image/png")},
)
assert uploaded.status_code == 201
attachment = uploaded.json()
assert attachment["content_type"] == "image/png"
assert attachment["url"].startswith("/api/attachments/")
fetched = client.get(attachment["url"])
assert fetched.status_code == 200
assert fetched.content == PNG
client.cookies.clear()
assert client.get(attachment["url"]).status_code == 401
def test_invalid_image_payload_is_rejected(logged_in):
client, _, _, conversation, headers = create_plain_conversation(logged_in)
response = client.post(
f"/api/conversations/{conversation['id']}/attachments",
headers=headers,
files={"image": ("fake.png", b"not-an-image", "image/png")},
)
assert response.status_code == 415
def test_conversation_can_display_an_image_from_its_worktree(logged_in):
client, app, _, conversation, _ = create_plain_conversation(logged_in)
workspace = app.state.settings.data_dir / "worktrees" / conversation["id"]
output = workspace / "output"
output.mkdir(parents=True)
(output / "result.webp").write_bytes(b"RIFFxxxxWEBPpreview")
(output / "notes.txt").write_text("not an image", encoding="utf-8")
app.state.db.execute(
"UPDATE conversations SET worktree_path=? WHERE id=?",
(str(workspace), conversation["id"]),
)
response = client.get(
f"/api/conversations/{conversation['id']}/files/image",
params={"path": "output/result.webp"},
)
assert response.status_code == 200
assert response.headers["content-type"].startswith("image/webp")
assert response.headers["content-disposition"].startswith("inline;")
assert client.get(
f"/api/conversations/{conversation['id']}/files/image",
params={"path": "output/notes.txt"},
).status_code == 415
assert client.get(
f"/api/conversations/{conversation['id']}/files/image",
params={"path": "../secret.png"},
).status_code == 404
def test_conversation_can_download_an_artifact_from_its_worktree(logged_in):
client, app, _, conversation, _ = create_plain_conversation(logged_in)
workspace = app.state.settings.data_dir / "worktrees" / conversation["id"]
output = workspace / "output"
output.mkdir(parents=True)
(output / "boards.zip").write_bytes(b"PK\x03\x04archive")
app.state.db.execute(
"UPDATE conversations SET worktree_path=? WHERE id=?",
(str(workspace), conversation["id"]),
)
response = client.get(
f"/api/conversations/{conversation['id']}/files/download",
params={"path": "output/boards.zip"},
)
assert response.status_code == 200
assert response.content == b"PK\x03\x04archive"
assert response.headers["content-disposition"].startswith("attachment;")
assert "no-store" in response.headers["cache-control"]
assert client.get(
f"/api/conversations/{conversation['id']}/files/download",
params={"path": "../secret.zip"},
).status_code == 404
client.cookies.clear()
assert client.get(
f"/api/conversations/{conversation['id']}/files/download",
params={"path": "output/boards.zip"},
).status_code == 401
def test_regular_file_can_be_uploaded_and_downloaded(logged_in):
client, _, _, conversation, headers = create_plain_conversation(logged_in)
payload = b"hello from an attached document\n"
uploaded = client.post(
f"/api/conversations/{conversation['id']}/attachments",
headers=headers,
files={"image": ("notes.txt", payload, "text/plain")},
)
assert uploaded.status_code == 201
attachment = uploaded.json()
assert attachment["original_name"] == "notes.txt"
assert attachment["content_type"] == "text/plain"
fetched = client.get(attachment["url"])
assert fetched.status_code == 200
assert fetched.content == payload
assert fetched.headers["content-disposition"].startswith("attachment;")
def test_file_larger_than_ten_megabytes_can_be_uploaded(logged_in):
client, _, _, conversation, headers = create_plain_conversation(logged_in)
payload = b"x" * (10 * 1024 * 1024 + 1)
uploaded = client.post(
f"/api/conversations/{conversation['id']}/attachments",
headers=headers,
files={"image": ("large.txt", payload, "text/plain")},
)
assert uploaded.status_code == 201
assert uploaded.json()["size"] == len(payload)
def test_file_over_configured_limit_is_rejected_and_removed(logged_in, monkeypatch):
client, app, _, conversation, headers = create_plain_conversation(logged_in)
monkeypatch.setattr("codexpi.main.MAX_ATTACHMENT_BYTES", 4)
response = client.post(
f"/api/conversations/{conversation['id']}/attachments",
headers=headers,
files={"image": ("too-large.txt", b"12345", "text/plain")},
)
assert response.status_code == 413
assert not app.state.db.one("SELECT id FROM attachments WHERE conversation_id=?", (conversation["id"],))
assert not any((app.state.settings.data_dir / "uploads" / conversation["id"]).iterdir())
def test_text_attachment_can_be_opened_and_edited_by_its_owner(logged_in):
client, app, _, conversation, headers = create_plain_conversation(logged_in)
uploaded = client.post(
f"/api/conversations/{conversation['id']}/attachments",
headers=headers,
files={"image": ("long-message.txt", b"original text", "text/plain")},
).json()
updated = client.put(
uploaded["url"],
headers={**headers, "Content-Type": "text/plain; charset=utf-8"},
content="edited text with accents: été".encode(),
)
assert updated.status_code == 200
assert updated.json()["size"] == len("edited text with accents: été".encode())
fetched = client.get(uploaded["url"])
assert fetched.status_code == 200
assert fetched.content == "edited text with accents: été".encode()
assert app.state.db.one("SELECT size FROM attachments WHERE id=?", (uploaded["id"],))["size"] == len(fetched.content)
client.cookies.clear()
assert client.put(uploaded["url"], content=b"forbidden").status_code == 401
def test_binary_attachment_cannot_be_edited_as_text(logged_in):
client, _, _, conversation, headers = create_plain_conversation(logged_in)
uploaded = client.post(
f"/api/conversations/{conversation['id']}/attachments",
headers=headers,
files={"image": ("archive.bin", b"\x00\x01\x02", "application/octet-stream")},
).json()
response = client.put(
uploaded["url"],
headers={**headers, "Content-Type": "text/plain"},
content=b"replacement",
)
assert response.status_code == 415
def test_oversized_text_edit_keeps_original_file(logged_in, monkeypatch):
client, _, _, conversation, headers = create_plain_conversation(logged_in)
uploaded = client.post(
f"/api/conversations/{conversation['id']}/attachments",
headers=headers,
files={"image": ("notes.txt", b"keep me", "text/plain")},
).json()
monkeypatch.setattr("codexpi.main.MAX_EDITABLE_TEXT_BYTES", 4)
response = client.put(uploaded["url"], headers=headers, content=b"12345")
assert response.status_code == 413
assert client.get(uploaded["url"]).content == b"keep me"
def test_messages_can_be_queued_while_codex_is_running(logged_in):
client, app, _, conversation, headers = create_plain_conversation(logged_in)
app.state.codex.codex_bin = sys.executable
app.state.db.execute("UPDATE conversations SET status='running' WHERE id=?", (conversation["id"],))
first = client.post(
f"/api/conversations/{conversation['id']}/queue", headers=headers, json={"content": "Second task"}
)
second = client.post(
f"/api/conversations/{conversation['id']}/queue", headers=headers, json={"content": "Third task"}
)
assert first.status_code == 202 and first.json()["status"] == "queued"
assert second.status_code == 202 and second.json()["position"] == 2
queued = client.get(f"/api/conversations/{conversation['id']}/queue").json()
assert [item["content"] for item in queued] == ["Second task", "Third task"]
cancelled = client.delete(f"/api/conversations/{conversation['id']}/queue/{first.json()['id']}", headers=headers)
assert cancelled.status_code == 200
def test_running_action_can_be_stopped_without_cancelling_waiting_messages(logged_in, monkeypatch):
client, app, _, conversation, headers = create_plain_conversation(logged_in)
stamp = "2026-09-18T12:00:00+00:00"
app.state.db.execute(
"INSERT INTO prompt_queue(id,conversation_id,content,status,created_at,started_at) VALUES(?,?,?,?,?,?)",
("running-task", conversation["id"], "wrong task", "running", stamp, stamp),
)
app.state.db.execute(
"INSERT INTO prompt_queue(id,conversation_id,content,status,created_at) VALUES(?,?,?,?,?)",
("next-task", conversation["id"], "keep this", "queued", stamp),
)
app.state.db.execute(
"UPDATE conversations SET status='running',worker_pid=4242 WHERE id=?",
(conversation["id"],),
)
monkeypatch.setattr(app.state.codex, "_worker_is_alive", lambda pid, conversation_id: True)
assert client.post(f"/api/conversations/{conversation['id']}/stop").status_code == 403
assert app.state.db.one("SELECT status FROM prompt_queue WHERE id='running-task'")["status"] == "running"
stopped = client.post(f"/api/conversations/{conversation['id']}/stop", headers=headers)
assert stopped.status_code == 200
assert stopped.json() == {"ok": True, "queue_id": "running-task"}
assert app.state.db.one("SELECT status FROM prompt_queue WHERE id='running-task'")["status"] == "cancelled"
assert app.state.db.one("SELECT status FROM prompt_queue WHERE id='next-task'")["status"] == "queued"
assert client.post(f"/api/conversations/{conversation['id']}/stop", headers=headers).status_code == 409
def test_orphaned_worker_is_released(logged_in, monkeypatch):
client, app, _, conversation, _ = create_plain_conversation(logged_in)
stamp = "2026-09-14T00:00:00+00:00"
app.state.db.execute(
"INSERT INTO prompt_queue(id,conversation_id,content,status,created_at,started_at) VALUES(?,?,?,?,?,?)",
("orphaned-task", conversation["id"], "stuck", "running", stamp, stamp),
)
app.state.db.execute(
"UPDATE conversations SET status='running',worker_pid=999999 WHERE id=?",
(conversation["id"],),
)
monkeypatch.setattr(app.state.codex, "_worker_is_alive", lambda pid, conversation_id: False)
assert app.state.codex.recover_orphaned_workers() == 1
task = app.state.db.one("SELECT status,finished_at,error FROM prompt_queue WHERE id='orphaned-task'")
restored = app.state.db.one("SELECT status,worker_pid FROM conversations WHERE id=?", (conversation["id"],))
assert task["status"] == "failed" and task["finished_at"] and "libérée" in task["error"]
assert restored == {"status": "failed", "worker_pid": None}
def test_waiting_messages_can_be_edited_and_cleared(logged_in):
client, app, _, conversation, headers = create_plain_conversation(logged_in)
app.state.codex.codex_bin = sys.executable
app.state.db.execute("UPDATE conversations SET status='running' WHERE id=?", (conversation["id"],))
first = client.post(
f"/api/conversations/{conversation['id']}/queue", headers=headers, json={"content": "Initial text"}
).json()
second = client.post(
f"/api/conversations/{conversation['id']}/queue", headers=headers, json={"content": "Another task"}
).json()
edited = client.put(
f"/api/conversations/{conversation['id']}/queue/{first['id']}",
headers=headers,
json={"content": "Edited text"},
)
assert edited.status_code == 200
queued = client.get(f"/api/conversations/{conversation['id']}/queue").json()
assert queued[0]["content"] == "Edited text"
messages = client.get(f"/api/conversations/{conversation['id']}/messages").json()
assert messages[0]["content"] == "Edited text"
assert messages[0]["metadata"]["queue_status"] == "queued"
cleared = client.delete(f"/api/conversations/{conversation['id']}/queue", headers=headers)
assert cleared.status_code == 200
assert cleared.json()["cancelled"] == 2
assert client.get(f"/api/conversations/{conversation['id']}/queue").json() == []
messages = client.get(f"/api/conversations/{conversation['id']}/messages").json()
assert all(message["metadata"]["queue_status"] == "cancelled" for message in messages)
def test_failed_message_exposes_copyable_error_details(logged_in):
client, app, _, conversation, _ = create_plain_conversation(logged_in)
stamp = "2026-10-15T08:44:00+00:00"
app.state.db.execute(
"INSERT INTO prompt_queue(id,conversation_id,content,status,created_at,started_at,finished_at,error) "
"VALUES(?,?,?,?,?,?,?,?)",
("failed-task", conversation["id"], "Build", "failed", stamp, stamp, stamp, "Selected model is at capacity."),
)
app.state.db.add_message(
conversation["id"], "user", "Build", {"queue_id": "failed-task"}
)
message = client.get(f"/api/conversations/{conversation['id']}/messages").json()[0]
assert message["metadata"]["queue_status"] == "failed"
assert message["metadata"]["queue_error"] == "Selected model is at capacity."
def test_large_action_outputs_are_compacted_only_in_the_messages_response(logged_in):
client, app, _, conversation, _ = create_plain_conversation(logged_in)
original_output = "first useful line\n" + ("x" * 20_000) + "\nlast useful line"
message_id = app.state.db.add_message(
conversation["id"],
"assistant",
"Done",
{
"actions": [
{
"id": "large-output",
"command": "build",
"output": original_output,
"status": "done",
}
]
},
)
for index in range(4):
app.state.db.add_message(conversation["id"], "assistant", f"Recent answer {index}")
message = client.get(f"/api/conversations/{conversation['id']}/messages").json()[0]
action = message["metadata"]["actions"][0]
assert action["output"].startswith("first useful line")
assert action["output"].endswith("last useful line")
assert len(action["output"].encode("utf-8")) <= 2_048
assert action["output_truncated"] is True
assert action["output_original_bytes"] == len(original_output.encode("utf-8"))
stored = app.state.db.one("SELECT metadata FROM messages WHERE id=?", (message_id,))
assert json.loads(stored["metadata"])["actions"][0]["output"] == original_output
def test_conversation_can_branch_from_an_earlier_message(logged_in):
client, app, project, conversation, headers = create_plain_conversation(logged_in)
app.state.db.execute(
"UPDATE conversations SET model=?,reasoning_effort=? WHERE id=?",
("gpt-5.6-sol", "high", conversation["id"]),
)
first_id = app.state.db.add_message(conversation["id"], "user", "First request")
app.state.db.add_message(conversation["id"], "assistant", "First answer")
app.state.db.add_message(conversation["id"], "user", "Later request")
branched = client.post(
f"/api/conversations/{conversation['id']}/branch",
headers=headers,
json={"message_id": first_id},
)
assert branched.status_code == 201
branch = branched.json()
assert "bootstrap_context" not in branch
assert branch["parent_conversation_id"] == conversation["id"]
assert branch["forked_from_message_id"] == first_id
assert branch["model"] == "gpt-5.6-sol" and branch["reasoning_effort"] == "high"
copied = client.get(f"/api/conversations/{branch['id']}/messages").json()
assert [message["content"] for message in copied] == ["First request"]
stored = app.state.db.one("SELECT bootstrap_context FROM conversations WHERE id=?", (branch["id"],))
assert "First request" in stored["bootstrap_context"]
listed = client.get(f"/api/projects/{project['id']}/conversations").json()
assert all("bootstrap_context" not in item for item in listed)