Fix interrupted run replay state
This commit is contained in:
@@ -257,6 +257,109 @@ class GuiServerTests(unittest.TestCase):
|
||||
self.assertEqual(payload['status'], 'running')
|
||||
self.assertEqual(payload['current_stage'], 'first stage')
|
||||
|
||||
def test_cancel_run_marks_streaming_session_tail_cancelled(self) -> None:
|
||||
with tempfile.TemporaryDirectory() as d:
|
||||
root = Path(d)
|
||||
client, state = _build_client(root)
|
||||
session_root = root / 'accounts' / 'alice' / 'sessions'
|
||||
save_agent_session(
|
||||
StoredAgentSession(
|
||||
session_id='thread-1',
|
||||
model_config={'model': 'test-model'},
|
||||
runtime_config={'cwd': str(root)},
|
||||
system_prompt_parts=('system prompt',),
|
||||
user_context={},
|
||||
system_context={},
|
||||
messages=(
|
||||
{'role': 'user', 'content': 'hello'},
|
||||
{
|
||||
'role': 'assistant',
|
||||
'content': '我先看看文件',
|
||||
'tool_calls': [
|
||||
{
|
||||
'id': 'call-1',
|
||||
'function': {'name': 'list_dir', 'arguments': '{}'},
|
||||
}
|
||||
],
|
||||
},
|
||||
{
|
||||
'role': 'tool',
|
||||
'content': '',
|
||||
'tool_call_id': 'call-1',
|
||||
'state': 'streaming',
|
||||
'metadata': {'phase': 'starting'},
|
||||
},
|
||||
),
|
||||
turns=1,
|
||||
tool_calls=1,
|
||||
usage={},
|
||||
total_cost_usd=0.0,
|
||||
file_history=(),
|
||||
budget_state={'status': 'running'},
|
||||
plugin_state={},
|
||||
),
|
||||
directory=session_root,
|
||||
)
|
||||
state.run_manager.start('alice', 'thread-1')
|
||||
|
||||
response = client.post(
|
||||
'/api/runs/cancel',
|
||||
json={'account_id': 'alice', 'session_id': 'thread-1'},
|
||||
)
|
||||
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertTrue(response.json()['cancelled'])
|
||||
stored = load_agent_session('thread-1', directory=session_root)
|
||||
self.assertEqual(stored.messages[-1]['role'], 'assistant')
|
||||
self.assertEqual(stored.messages[-1]['stop_reason'], 'cancelled')
|
||||
self.assertEqual(
|
||||
stored.messages[-1]['metadata']['status'],
|
||||
'cancelled',
|
||||
)
|
||||
self.assertNotEqual(stored.messages[-1].get('state'), 'streaming')
|
||||
|
||||
def test_latest_run_reports_interrupted_for_orphaned_streaming_session(self) -> None:
|
||||
with tempfile.TemporaryDirectory() as d:
|
||||
root = Path(d)
|
||||
client, _ = _build_client(root)
|
||||
session_root = root / 'accounts' / 'alice' / 'sessions'
|
||||
save_agent_session(
|
||||
StoredAgentSession(
|
||||
session_id='thread-1',
|
||||
model_config={'model': 'test-model'},
|
||||
runtime_config={'cwd': str(root)},
|
||||
system_prompt_parts=('system prompt',),
|
||||
user_context={},
|
||||
system_context={},
|
||||
messages=(
|
||||
{'role': 'user', 'content': 'hello'},
|
||||
{
|
||||
'role': 'tool',
|
||||
'content': '',
|
||||
'tool_call_id': 'call-1',
|
||||
'state': 'streaming',
|
||||
'metadata': {'phase': 'starting'},
|
||||
},
|
||||
),
|
||||
turns=1,
|
||||
tool_calls=1,
|
||||
usage={},
|
||||
total_cost_usd=0.0,
|
||||
file_history=(),
|
||||
budget_state={'status': 'running'},
|
||||
plugin_state={},
|
||||
),
|
||||
directory=session_root,
|
||||
)
|
||||
|
||||
response = client.get(
|
||||
'/api/runs/latest',
|
||||
params={'account_id': 'alice', 'session_id': 'thread-1'},
|
||||
)
|
||||
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertEqual(response.json()['status'], 'interrupted')
|
||||
|
||||
def test_chat_uses_account_scoped_model_config(self) -> None:
|
||||
with tempfile.TemporaryDirectory() as d:
|
||||
client, _ = _build_client(Path(d))
|
||||
|
||||
Reference in New Issue
Block a user