Ctrl K
ComunidadGuías…

tests/plugins/conftest.py

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
"""A tiny fake ``ToolContext``: a ``LocalExecEnv`` over a temp workspace, and
a ``record`` that folds ``fs`` entries through ``reduce_fs`` at once — what the
runner does between calls."""

from __future__ import annotations

import os
from dataclasses import dataclass, field
from pathlib import Path
from typing import Any

import pytest

from noeta.backends.execenvs.local import LocalExecEnv
from noeta.core.tool import Tool, ToolContext, ToolOutput
from noeta.core.types import Image, Text
from noeta.plugins.fs.state import FS, FsState, reduce_fs
from noeta.plugins.shell.state import SHELL, ShellState, reduce_shell, shell_state


@dataclass
class Harness:
    env: LocalExecEnv
    state: dict[str, Any] = field(default_factory=dict)
    records: list[tuple[str, str, Any]] = field(default_factory=list)
    spill_dir: str | None = None
    task_id: str = "task-1"
    calls: int = 0
    #: Calls run as if a person allowed them at an approval prompt.
    approved: bool = False
    #: Calls run as if a permission layer allowed them by its settings.
    allowed_outright: bool = False
    model: str = ""

    @property
    def root(self) -> Path:
        return Path(self.env.cwd)

    @property
    def fs(self) -> FsState:
        value = self.state.get(FS)
        return value if isinstance(value, FsState) else FsState()

    @property
    def shell(self) -> ShellState:
        return shell_state(self.state)

    def record(self, ext: str, kind: str, data: Any) -> None:
        self.records.append((ext, kind, data))
        if ext == FS:
            self.state[FS] = reduce_fs(self.state.get(FS), kind, data)
        elif ext == SHELL:
            self.state[SHELL] = reduce_shell(self.state.get(SHELL), kind, data)

    def ctx(self, call_id: str | None = None) -> ToolContext:
        self.calls += 1
        return ToolContext(
            task_id=self.task_id,
            call_id=call_id or f"call-{self.calls}",
            env=self.env,
            state=self.state,
            record=self.record,
            spill_dir=self.spill_dir,
            approved=self.approved,
            allowed_outright=self.allowed_outright,
            model=self.model,
        )

    async def call(self, tool: Tool, **input: Any) -> ToolOutput:
        return await tool.run(input, self.ctx())


def text_of(out: ToolOutput) -> str:
    return "".join(b.text for b in out.content if isinstance(b, Text))


def images_of(out: ToolOutput) -> list[Image]:
    return [b for b in out.content if isinstance(b, Image)]


@pytest.fixture
def ws(tmp_path: Path) -> Path:
    root = tmp_path / "ws"
    root.mkdir()
    return Path(os.path.realpath(root))


@pytest.fixture
def h(ws: Path) -> Harness:
    return Harness(env=LocalExecEnv(str(ws)))