|
|
@@ -10,6 +10,12 @@ from cyber_agent.application import (
|
|
|
CandidateReviewAction,
|
|
|
)
|
|
|
from cyber_agent.application.candidate import CandidateLedger, CandidatePointer
|
|
|
+from cyber_agent.core.artifacts import ArtifactRef
|
|
|
+from cyber_agent.core.run_snapshot import (
|
|
|
+ RunConfigSnapshotV2,
|
|
|
+ persist_run_config_snapshot,
|
|
|
+)
|
|
|
+from cyber_agent.core.runner import RunConfig
|
|
|
from cyber_agent.core.task_protocol import (
|
|
|
Finding,
|
|
|
Hypothesis,
|
|
|
@@ -105,6 +111,25 @@ class ApplicationReferenceEndToEndTest(unittest.IsolatedAsyncioTestCase):
|
|
|
state = new_task_protocol(brief)
|
|
|
initialize_task_progress(state, effective_at_sequence=1)
|
|
|
context["task_protocol"] = state
|
|
|
+ child_config = RunConfig(
|
|
|
+ trace_id=trace_id,
|
|
|
+ uid=root.uid,
|
|
|
+ parent_trace_id=root.trace_id,
|
|
|
+ context=context,
|
|
|
+ enable_research_flow=False,
|
|
|
+ )
|
|
|
+ binding.configure_run_config(child_config, role_id)
|
|
|
+ context["effective_run_limits"] = dict(
|
|
|
+ child_config.effective_run_limits
|
|
|
+ )
|
|
|
+ child_config.context = context
|
|
|
+ persist_run_config_snapshot(
|
|
|
+ context,
|
|
|
+ RunConfigSnapshotV2.from_run_config(
|
|
|
+ child_config,
|
|
|
+ memory_identity=None,
|
|
|
+ ),
|
|
|
+ )
|
|
|
child = Trace(
|
|
|
trace_id=trace_id,
|
|
|
mode="agent",
|
|
|
@@ -128,10 +153,18 @@ class ApplicationReferenceEndToEndTest(unittest.IsolatedAsyncioTestCase):
|
|
|
validation_scopes=["evidence"],
|
|
|
),
|
|
|
)
|
|
|
- fact_ref = await components.facts.verify(
|
|
|
- question="What does an agent framework supply?",
|
|
|
- root_trace_id=root.trace_id,
|
|
|
+ raw_fact_result = await binding.tool_registry.execute(
|
|
|
+ "verify_fact",
|
|
|
+ {"question": "What does an agent framework supply?"},
|
|
|
uid=root.uid,
|
|
|
+ context={
|
|
|
+ "trace_id": fact_child.trace_id,
|
|
|
+ "store": store,
|
|
|
+ },
|
|
|
+ allowed_tool_names={"verify_fact"},
|
|
|
+ )
|
|
|
+ fact_ref = ArtifactRef.model_validate(
|
|
|
+ json.loads(raw_fact_result)["artifact_ref"]
|
|
|
)
|
|
|
await runner.task_protocol_service.update_progress(
|
|
|
fact_child.trace_id,
|
|
|
@@ -228,10 +261,38 @@ class ApplicationReferenceEndToEndTest(unittest.IsolatedAsyncioTestCase):
|
|
|
self.assertEqual("passed", validation_a.result.outcome)
|
|
|
self.assertEqual("failed", validation_b.result.outcome)
|
|
|
self.assertEqual(1, components.facts.calls)
|
|
|
+ self.assertEqual(
|
|
|
+ 1,
|
|
|
+ binding.tool_registry.get_stats("verify_fact")[
|
|
|
+ "verify_fact"
|
|
|
+ ]["call_count"],
|
|
|
+ )
|
|
|
self.assertEqual(1, llm_calls)
|
|
|
frozen_a = validation_a.result.model_dump(mode="json")
|
|
|
|
|
|
- restored_runner, _restored_config = await runtime.restore(root.trace_id)
|
|
|
+ await runner._mark_trace_stopped(root.trace_id, root.head_sequence)
|
|
|
+ await runner._mark_trace_stopped(writer.trace_id, writer.head_sequence)
|
|
|
+ restarted_components = build_reference_components(
|
|
|
+ artifacts=components.artifacts,
|
|
|
+ candidates=components.candidates,
|
|
|
+ projector=components.projector,
|
|
|
+ )
|
|
|
+ restarted_registry = ApplicationRegistry()
|
|
|
+ restarted_registry.register(
|
|
|
+ restarted_components.application,
|
|
|
+ restarted_components.services,
|
|
|
+ )
|
|
|
+ restarted_runtime = ApplicationRuntime(
|
|
|
+ registry=restarted_registry,
|
|
|
+ trace_store=store,
|
|
|
+ llm_call=llm_call,
|
|
|
+ )
|
|
|
+ restored_runner, restored_config = await restarted_runtime.restore(
|
|
|
+ writer.trace_id
|
|
|
+ )
|
|
|
+ self.assertEqual("writer", restored_config.role_id)
|
|
|
+ self.assertEqual(0, restarted_components.context.list_calls)
|
|
|
+ self.assertEqual(0, restarted_components.context.resolve_calls)
|
|
|
await restored_runner.candidate_service.apply_review_actions(
|
|
|
root.trace_id,
|
|
|
writer.trace_id,
|
|
|
@@ -259,7 +320,10 @@ class ApplicationReferenceEndToEndTest(unittest.IsolatedAsyncioTestCase):
|
|
|
)
|
|
|
self.assertEqual("passed", validation_b2.result.outcome)
|
|
|
self.assertEqual(2, llm_calls)
|
|
|
- self.assertEqual(1, components.facts.calls)
|
|
|
+ self.assertEqual(
|
|
|
+ 1,
|
|
|
+ components.facts.calls + restarted_components.facts.calls,
|
|
|
+ )
|
|
|
self.assertEqual(
|
|
|
frozen_a,
|
|
|
(await restored_runner.validate_recursive_trace(
|
|
|
@@ -288,8 +352,8 @@ class ApplicationReferenceEndToEndTest(unittest.IsolatedAsyncioTestCase):
|
|
|
|
|
|
await restored_runner.event_service.try_pump(root.trace_id)
|
|
|
before_replay = dict(components.projector.rows)
|
|
|
- await runtime.reconcile_events(root.trace_id)
|
|
|
- await runtime.reconcile_events(root.trace_id)
|
|
|
+ await restarted_runtime.reconcile_events(root.trace_id)
|
|
|
+ await restarted_runtime.reconcile_events(root.trace_id)
|
|
|
self.assertEqual(before_replay, components.projector.rows)
|
|
|
adopted_keys = [
|
|
|
key for key in components.projector.rows
|