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,132 @@
import json
import subprocess
import sys
from pathlib import Path
from codexpi.database import Database, utcnow
from codexpi.message_results import collect_event, recover_results, snapshot_changes, workspace_snapshot
from codexpi.session_worker import main
def test_commands_are_deduplicated_and_failures_preserved():
results = {}
collect_event(results, {'type': 'item.started', 'item': {'id': 'c', 'type': 'command_execution', 'command': 'false'}}, '2026-09-13T10:00:00Z')
collect_event(results, {'type': 'item.completed', 'item': {'id': 'c', 'type': 'command_execution', 'command': 'false', 'exit_code': 1, 'aggregated_output': 'failure'}}, '2026-09-13T10:00:02Z')
assert len(results['actions']) == 1
assert results['actions'][0]['status'] == 'error'
assert results['actions'][0]['duration'] == 2000
assert results['actions'][0]['output'] == 'failure'
def test_snapshot_excludes_preexisting_changes(tmp_path):
subprocess.run(['git', 'init', str(tmp_path)], check=True, capture_output=True)
(tmp_path / 'existing.txt').write_text('already changed')
(tmp_path / 'edited.txt').write_text('before')
(tmp_path / 'deleted.txt').write_text('before')
before = workspace_snapshot(str(tmp_path))
(tmp_path / 'edited.txt').write_text('after')
(tmp_path / 'deleted.txt').unlink()
(tmp_path / 'new.txt').write_text('new')
assert snapshot_changes(before, workspace_snapshot(str(tmp_path))) == [
{'path': 'deleted.txt', 'status': 'D'}, {'path': 'edited.txt', 'status': 'M'}, {'path': 'new.txt', 'status': 'A'}]
def test_recovery_does_not_mix_queued_prompts(tmp_path):
path = tmp_path / 'events.jsonl'
events = [
{'type': 'queue.started', 'data': {'id': 'first'}},
{'type': 'codex.event', 'at': '2026-09-13T10:00:00Z', 'data': {'type': 'item.completed', 'item': {'id': 'c', 'type': 'command_execution', 'command': 'ls', 'exit_code': 0}}},
{'type': 'codex.event', 'at': '2026-09-13T10:00:01Z', 'data': {'type': 'item.completed', 'item': {'type': 'agent_message', 'text': 'Checking files'}}},
{'type': 'codex.event', 'at': '2026-09-13T10:00:02Z', 'data': {'type': 'item.completed', 'item': {'type': 'agent_message', 'text': 'First answer'}}},
{'type': 'codex.event', 'at': '2026-09-13T10:00:02Z', 'data': {'type': 'error', 'message': 'Temporary transport error'}},
{'type': 'codex.event', 'at': '2026-09-13T10:00:02Z', 'data': {'type': 'turn.failed', 'error': {'message': 'Selected model is at capacity.'}}},
{'type': 'queue.started', 'data': {'id': 'second'}},
{'type': 'codex.event', 'at': '2026-09-13T10:00:00Z', 'data': {'type': 'item.completed', 'item': {'type': 'file_change', 'changes': [{'path': 'app.py', 'kind': 'update'}]}}},
{'type': 'codex.event', 'at': '2026-09-13T10:00:03Z', 'data': {'type': 'item.completed', 'item': {'type': 'agent_message', 'text': 'Second answer'}}},
{'type': 'queue.started', 'data': {'id': 'third'}},
{'type': 'codex.event', 'at': '2026-09-13T10:00:04Z', 'data': {'type': 'output', 'text': 'CLI authentication failed'}},
{'type': 'queue.finished', 'data': {'id': 'third', 'returncode': 1, 'status': 'failed'}},
]
path.write_text('\n'.join(map(json.dumps, events)) + '\n{broken')
recovered = recover_results([path])
assert len(recovered['first']['actions']) == 1
assert recovered['first']['files'] == []
assert recovered['first']['progress'] == ['Checking files']
assert recovered['first']['answer'] == 'First answer'
assert recovered['first']['error'] == 'Selected model is at capacity.'
assert recovered['second']['actions'] == []
assert recovered['second']['files'] == [{'path': 'app.py', 'status': 'update'}]
assert recovered['second']['progress'] == []
assert recovered['second']['answer'] == 'Second answer'
assert recovered['third']['error'] == 'CLI authentication failed'
def test_worker_persists_structured_engine_error(tmp_path, monkeypatch):
repo = tmp_path / 'repo'
repo.mkdir()
executable = tmp_path / 'fake-codex'
executable.write_text('''#!/usr/bin/env python3
import json, sys
print(json.dumps({'type':'error','message':'Selected model is at capacity.'}))
print(json.dumps({'type':'turn.failed','error':{'message':'Selected model is at capacity.'}}))
sys.exit(1)
''')
executable.chmod(0o755)
db = Database(tmp_path / 'db.sqlite')
db.initialize()
stamp = utcnow()
db.execute('INSERT INTO projects(id,name,path,created_at) VALUES(?,?,?,?)', ('p', 'Demo', str(repo), stamp))
db.execute('INSERT INTO conversations(id,project_id,title,status,created_at,updated_at) VALUES(?,?,?,?,?,?)', ('c', 'p', 'Demo', 'running', stamp, stamp))
db.execute('INSERT INTO prompt_queue(id,conversation_id,content,status,created_at) VALUES(?,?,?,?,?)', ('q', 'c', 'Build', 'running', stamp))
monkeypatch.setattr(sys, 'argv', ['worker', '--database', str(db.path), '--events', str(tmp_path / 'events.jsonl'), '--conversation', 'c', '--cwd', str(repo), '--codex', str(executable), '--queue', 'q'])
assert main() == 1
assert db.one('SELECT status,error FROM prompt_queue WHERE id=?', ('q',)) == {
'status': 'failed',
'error': 'Selected model is at capacity.',
}
def test_worker_persists_results_per_message(tmp_path, monkeypatch):
repo = tmp_path / 'repo'
repo.mkdir()
subprocess.run(['git', 'init', str(repo)], check=True, capture_output=True)
(repo / 'preexisting.txt').write_text('preexisting dirty file')
executable = tmp_path / 'fake-codex'
executable.write_text('''#!/usr/bin/env python3
import json, sys
from pathlib import Path
if sys.argv[-1].startswith('first'):
Path('changed.txt').write_text('new content')
print(json.dumps({'type':'item.completed','item':{'id':'c','type':'command_execution','command':'write file','exit_code':0}}))
print(json.dumps({'type':'item.completed','item':{'type':'agent_message','text':'Progress'}}))
print(json.dumps({'type':'item.completed','item':{'type':'agent_message','text':'Answer'}}))
''')
executable.chmod(0o755)
db = Database(tmp_path / 'db.sqlite')
db.initialize()
stamp = utcnow()
db.execute('INSERT INTO projects(id,name,path,created_at) VALUES(?,?,?,?)', ('p', 'Demo', str(repo), stamp))
db.execute('INSERT INTO conversations(id,project_id,title,status,created_at,updated_at) VALUES(?,?,?,?,?,?)', ('c', 'p', 'Demo', 'running', stamp, stamp))
for identifier, status in [('first', 'running'), ('second', 'queued')]:
db.execute('INSERT INTO prompt_queue(id,conversation_id,content,status,created_at) VALUES(?,?,?,?,?)', (identifier, 'c', identifier, status, stamp))
monkeypatch.setattr(sys, 'argv', ['worker', '--database', str(db.path), '--events', str(tmp_path / 'events.jsonl'), '--conversation', 'c', '--cwd', str(repo), '--codex', str(executable), '--queue', 'first'])
started_before = utcnow()
assert main() == 0
events = [json.loads(line) for line in (tmp_path / 'events.jsonl').read_text().splitlines()]
starts = [event['data'] for event in events if event['type'] == 'queue.started']
assert len(starts) == 2
for start in starts:
stored = db.one('SELECT started_at FROM prompt_queue WHERE id=?', (start['id'],))
assert stored['started_at'] == start['started_at']
assert start['started_at'] >= started_before
stored_messages = db.all('SELECT * FROM messages')
rows = {json.loads(row['metadata'])['queue_id']: json.loads(row['metadata']) for row in stored_messages}
answers = {json.loads(row['metadata'])['queue_id']: row['content'] for row in stored_messages}
assert len(rows['first']['actions']) == 1
assert rows['first']['files'] == [{'path': 'changed.txt', 'status': 'A'}]
assert rows['second']['actions'] == []
assert rows['second']['files'] == []
assert rows['first']['progress'] == ['Progress']
assert rows['second']['progress'] == ['Progress']
assert answers == {'first': 'Answer', 'second': 'Answer'}