Files
ai-video-fullstack/backend/tests/test_opencode_tasks.py
T

72 lines
4.3 KiB
Python
Raw Normal View History

import json
import unittest
import httpx
from services.background_tasks.opencode import OpenCodeExecutor
class OpenCodeTaskTest(unittest.IsolatedAsyncioTestCase):
async def test_persisted_result_keeps_long_assistant_text(self):
text = "重要前提:仅完成部分修改。" + "结果" * 10000 + "仍有失败。"
async def respond(request):
if request.url.path.endswith("/message"):
return httpx.Response(200, json=[{"info": {"role": "assistant", "parentID": "msg_test", "time": {"completed": 1}}, "parts": [{"type": "text", "text": text}]}])
return httpx.Response(200, json={})
executor = OpenCodeExecutor({"url": "https://remote.test", "directory": "/demo"}, {}, transport=httpx.MockTransport(respond))
state = await executor.snapshot({"session_id": "ses_test", "message_id": "msg_test"})
self.assertEqual(state["result"], text)
async def test_correlated_completion_ignores_initial_idle_and_other_sessions(self):
handle = {"session_id": "ses_test", "message_id": "msg_test"}
submitted = False
snapshots = 0
updates = []
async def respond(request):
nonlocal submitted, snapshots
self.assertEqual(request.url.params["directory"], "/workspace/demo")
if request.url.path == "/event":
events = [
{"type": "session.idle", "properties": {"sessionID": "ses_other"}},
{"type": "session.idle", "properties": {"sessionID": "ses_test"}},
{"type": "message.updated", "properties": {"info": {"sessionID": "ses_test"}}},
]
return httpx.Response(200, text="".join("data: " + json.dumps(e) + "\n\n" for e in events))
if request.url.path.endswith("prompt_async"):
self.assertFalse(submitted)
payload = json.loads(request.content)
self.assertEqual(payload["messageID"], "msg_test")
self.assertEqual(payload["agent"], "build")
self.assertEqual(payload["model"], {"providerID": "test-provider", "modelID": "test-model"})
self.assertEqual(payload["system"], "通用说明\n\n项目 demo")
submitted = True
return httpx.Response(204)
if request.url.path.endswith("/message"):
snapshots += 1
parent = "old_message" if snapshots == 1 else "msg_test"
return httpx.Response(200, json=[{"info": {"role": "assistant", "parentID": parent, "time": {"completed": 1}}, "parts": [{"type": "text", "text": "测试通过"}]}])
if request.url.path == "/session/status":
return httpx.Response(200, json={})
raise AssertionError(request.url)
executor = OpenCodeExecutor({"url": "https://remote.test", "directory": "/workspace/demo", "agent": "build",
"model_provider_id": "test-provider", "model_id": "test-model",
"instructions": "通用说明", "_backend": {"instructions": "项目 {{project}}"},
"_variables": {"project": "demo"}}, {}, transport=httpx.MockTransport(respond))
async def emit(event):
updates.append(event)
result = await executor.run(handle, "修复测试", emit)
self.assertEqual(result["status"], "succeeded")
self.assertEqual(result["result"], "测试通过")
self.assertEqual(snapshots, 2)
self.assertEqual(updates[0]["status"], "submitted")
async def test_resume_reads_results_without_resubmitting(self):
async def respond(request):
self.assertEqual(request.method, "GET")
if request.url.path.endswith("/message"):
return httpx.Response(200, json=[{"info": {"role": "assistant", "parentID": "msg_test", "time": {"completed": 1}}, "parts": []}])
return httpx.Response(200, json={})
executor = OpenCodeExecutor({"url": "https://remote.test", "directory": "/demo"}, {}, transport=httpx.MockTransport(respond))
async def emit(event):
self.fail("completed task should not restart")
state = await executor.run({"session_id": "ses_test", "message_id": "msg_test"}, "ignored", emit, resume=True)
self.assertEqual(state["status"], "succeeded")