Files
Netherwarlord 8f246fabbc feat: add plugin framework with UI contributions and suite selection
- Implemented PluginBlocks component to render various plugin UI elements.
- Created SuitePicker for selecting test suites and questions.
- Introduced usePluginUI hook for managing plugin UI state and manifest.
- Developed DocsPage for comprehensive plugin framework documentation.
- Added PluginPage to render pages declared by plugins based on the current path.
2026-07-28 03:00:55 -04:00

90 lines
2.7 KiB
Python

"""Server-side access to named test suites.
The engine keeps suites in two tiers — read-only built-ins under
``.core/suites/`` and user-owned custom ones under ``tests/<slug>/`` — and this
module is the thin server layer over :mod:`suites` in the core.
Everything here speaks **qualified question IDs** (``"<suite>/<file>"``). Bare
filenames are ambiguous the moment a run draws from more than one suite, and
resolving one to the wrong question would hand a grader the wrong prompt and
produce a confident, wrong score in silence.
"""
from __future__ import annotations
from typing import Dict, List, Optional, Sequence
from .core_bridge import ( # noqa: F401 (several are re-exported for the API)
TESTS_DIR,
ReadOnlySuiteError,
Suite,
SuiteError,
create_suite,
delete_suite,
duplicate_suite,
find_prompts,
get_suite,
list_suites,
load_prompts,
load_suite_prompts,
save_suite_tests,
split_question_id,
update_suite,
)
__all__ = [
"ReadOnlySuiteError",
"Suite",
"SuiteError",
"create_suite",
"delete_suite",
"duplicate_suite",
"get_suite",
"list_suites",
"load_suite_prompts",
"resolve_selections",
"save_suite_tests",
"update_suite",
]
def resolve_selections(
selections: Optional[Sequence[object]] = None,
question_ids: Optional[Sequence[str]] = None,
) -> List[Dict[str, str]]:
"""Turn a run request into an ordered list of prompts.
``selections`` is a list of objects with ``.suite`` and optional
``.filenames``; a suite with no filenames contributes all of its questions.
``question_ids`` is the older flat form and must be fully qualified.
Passing neither means every built-in suite.
"""
if selections:
prompts: List[Dict[str, str]] = []
seen = set()
for selection in selections:
slug = getattr(selection, "suite", None) or ""
get_suite(slug) # raises SuiteError for an unknown slug
filenames = getattr(selection, "filenames", None)
chosen = (
load_suite_prompts(slug)
if not filenames
else find_prompts([f"{slug}/{name}" for name in filenames])
)
for entry in chosen:
if entry["id"] not in seen:
seen.add(entry["id"])
prompts.append(entry)
return prompts
if question_ids:
bare = [qid for qid in question_ids if "/" not in qid]
if bare:
raise SuiteError(
"Bare filenames are ambiguous across suites: "
f"{', '.join(sorted(bare))}. Use '<suite>/<file>' IDs, or 'selections'."
)
return find_prompts(list(question_ids))
return load_prompts(None)