address review: top-level AnalysisRunDeps import, asserts, e2e tests
- Move AnalysisRunDeps to the module-level import in _tools.py. - Swap the RuntimeError guards in _require_rag and execute_code for plain asserts with the same diagnostic messages. Apply the same treatment to the ty-reachability guard in Sandbox._ensure_initialized. - Add end-to-end lifespan tests for both skills that drive _run_skill with TestModel, covering the sub-agent entry path that the existing tool-level tests bypass. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
e736a8c73a
commit
206c4ffcf2
4 changed files with 35 additions and 15 deletions
|
|
@ -277,11 +277,8 @@ class Sandbox:
|
|||
external_functions=self._build_external_functions(),
|
||||
os=self._vfs,
|
||||
)
|
||||
repl = self._repl
|
||||
vfs = self._vfs
|
||||
if repl is None or vfs is None:
|
||||
raise RuntimeError("Sandbox initialization failed")
|
||||
return repl, vfs
|
||||
assert self._repl is not None and self._vfs is not None
|
||||
return self._repl, self._vfs
|
||||
|
||||
async def execute(self, code: str) -> SandboxResult:
|
||||
"""Execute Python code in the Monty REPL.
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ from pydantic_ai import RunContext
|
|||
from haiku.rag.agents.research.models import Citation
|
||||
from haiku.rag.client import HaikuRAG
|
||||
from haiku.rag.config.models import AppConfig
|
||||
from haiku.rag.skills._deps import RAGRunDeps
|
||||
from haiku.rag.skills._deps import AnalysisRunDeps, RAGRunDeps
|
||||
from haiku.rag.store.models.chunk import SearchResult
|
||||
|
||||
|
||||
|
|
@ -76,10 +76,9 @@ def _get_state(ctx: RunContext[RAGRunDeps], state_type: type[BaseModel]) -> Any:
|
|||
|
||||
|
||||
def _require_rag(ctx: RunContext[RAGRunDeps]) -> HaikuRAG:
|
||||
if ctx.deps is None or ctx.deps.rag is None:
|
||||
raise RuntimeError(
|
||||
"RAGRunDeps.rag is not set — skill lifespan must run before tools."
|
||||
)
|
||||
assert ctx.deps is not None and ctx.deps.rag is not None, (
|
||||
"RAGRunDeps.rag is not set — skill lifespan must run before tools."
|
||||
)
|
||||
return ctx.deps.rag
|
||||
|
||||
|
||||
|
|
@ -227,7 +226,6 @@ def create_skill_tools(
|
|||
tools["get_document"] = get_document
|
||||
|
||||
if "execute_code" in tool_names:
|
||||
from haiku.rag.skills._deps import AnalysisRunDeps
|
||||
|
||||
async def execute_code(ctx: RunContext[AnalysisRunDeps], code: str) -> str:
|
||||
"""Execute Python code in a sandboxed interpreter.
|
||||
|
|
@ -242,10 +240,9 @@ def create_skill_tools(
|
|||
Args:
|
||||
code: Python code to execute.
|
||||
"""
|
||||
if ctx.deps is None or ctx.deps.sandbox is None:
|
||||
raise RuntimeError(
|
||||
"AnalysisRunDeps.sandbox is not set — skill lifespan must run before execute_code."
|
||||
)
|
||||
assert ctx.deps is not None and ctx.deps.sandbox is not None, (
|
||||
"AnalysisRunDeps.sandbox is not set — skill lifespan must run before execute_code."
|
||||
)
|
||||
sandbox = ctx.deps.sandbox
|
||||
result = await sandbox.execute(code)
|
||||
|
||||
|
|
|
|||
|
|
@ -266,6 +266,19 @@ class TestAnalysisLifespan:
|
|||
assert skill.deps_type is AnalysisRunDeps
|
||||
assert skill.lifespan is not None
|
||||
|
||||
async def test_run_skill_end_to_end_opens_client_and_sandbox(
|
||||
self, allow_model_requests, rag_db
|
||||
):
|
||||
"""Full sub-agent path: lifespan builds client + sandbox, tools see them."""
|
||||
from pydantic_ai.models.test import TestModel
|
||||
|
||||
from haiku.rag.skills.analysis import create_skill
|
||||
from haiku.skills.agent import _run_skill
|
||||
|
||||
skill = create_skill(db_path=rag_db)
|
||||
result, *_ = await _run_skill(TestModel(), skill, "Print the document count.")
|
||||
assert result
|
||||
|
||||
async def test_lifespan_clears_executions_citations_searches(self, rag_db):
|
||||
from haiku.rag.agents.research.models import Citation
|
||||
from haiku.rag.skills._deps import AnalysisRunDeps, make_analysis_lifespan
|
||||
|
|
|
|||
|
|
@ -359,6 +359,19 @@ class TestLifespan:
|
|||
assert skill.deps_type is RAGRunDeps
|
||||
assert skill.lifespan is not None
|
||||
|
||||
async def test_run_skill_end_to_end_opens_and_closes_client(
|
||||
self, allow_model_requests, rag_db
|
||||
):
|
||||
"""Full sub-agent path: lifespan opens the client, tools see it, lifespan closes it."""
|
||||
from pydantic_ai.models.test import TestModel
|
||||
|
||||
from haiku.rag.skills.rag import create_skill
|
||||
from haiku.skills.agent import _run_skill
|
||||
|
||||
skill = create_skill(db_path=rag_db)
|
||||
result, *_ = await _run_skill(TestModel(), skill, "List the documents.")
|
||||
assert result
|
||||
|
||||
async def test_lifespan_clears_citations_and_searches_but_keeps_index(self, rag_db):
|
||||
from haiku.rag.agents.research.models import Citation
|
||||
from haiku.rag.skills._deps import RAGRunDeps, make_rag_lifespan
|
||||
|
|
|
|||
Loading…
Reference in a new issue