"""LabAgent — in-flow feedback over LIVE sandbox telemetry (REQ-3-007). v0.3 re-grounding: consumes a TraceDigest computed from the learner's real trace (grading/features.compute_digest over TraceStore events) — the v0.2 corpus scenarios are retired from this path (corpus dormancy, Task 6-1-04). No session chat — each request is one live-trace read. """ from collections.abc import AsyncIterator from ..config import Settings from ..corpus.learner_context import LearnerContext, get_learner_context from ..grading.features import TraceDigest from ..llm.base import LLMProvider from ..prompts.lab import SYSTEM_PROMPT, render_context, render_digest_timeline from .base import BaseAgent class LabAgent(BaseAgent): name = "lab" def __init__(self, provider: LLMProvider, settings: Settings) -> None: super().__init__(provider, settings) def system_prompt(self, learner_context: LearnerContext | None = None) -> str: ctx = learner_context or get_learner_context() return SYSTEM_PROMPT.format_map(render_context(ctx)) async def stream_feedback( self, digest: TraceDigest | None, learner_context: LearnerContext | None = None, ) -> AsyncIterator[str]: """Feedback grounded in the learner's live trace digest.""" timeline = render_digest_timeline(digest) async for token in self.stream_reply( history=None, user_input=timeline, learner_context=learner_context ): yield token