F1: add correlated OpenCode HTTP and SSE task adapter

This commit is contained in:
Xin Wang
2026-10-23 15:57:33 +08:00
parent 82d479f9e1
commit bae5ec3c58
3 changed files with 202 additions and 1 deletions
+54
View File
@@ -0,0 +1,54 @@
import json
import unittest
import httpx
from services.background_tasks.opencode import OpenCodeExecutor
class OpenCodeTaskTest(unittest.IsolatedAsyncioTestCase):
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)
self.assertEqual(json.loads(request.content)["messageID"], "msg_test")
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"}, {}, 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")