feat(inspect): local prompts resolved like the server's

A file chosen on the Inspect page now shows the prompts and resolution
the server's inspector gives the same records: buildLocalPayload takes
its roles from the local resolver instead of the interim open roles, so
the legacy fill applies exactly where it does for Images.

The resolver reads the server's own node table. The page fetches
web/js/inspection-semantics.json once through the API client as it
mounts, before any selection; the static route serves that one JSON
file by exact path (every other JSON stays forbidden). A table that
cannot be fetched answers "The inspector's node table is unavailable."
as the server does, and a later selection asks again.

The Copy settings summary deviation is numbered D117.
This commit is contained in:
Vito Sansevero
2026-10-22 18:15:40 -07:00
parent 564de9e3f1
commit e8df5c54e3
20 changed files with 298 additions and 51 deletions
+12 -5
View File
@@ -105,6 +105,9 @@ STATIC_MIME_TYPES = {
".html": "text/html",
}
_STATIC_SEPARATORS = re.compile(r"[\\/]+")
# Served by exact request path beside the extension allow-list: the browser's
# copy of the inspection node table (local Inspect resolves with it, #249).
STATIC_EXACT_FILES = {("js", "inspection-semantics.json"): "application/json"}
def _resolve_static_file(root, filepath):
@@ -475,15 +478,19 @@ class PromptManagerAPI(
def _serve_static_file(self, subdir, filepath):
"""Serve ``web/<subdir>/<filepath>``; 403 outside it, 404 when missing."""
root = os.path.join(_get_project_root(), "web", subdir)
file_path = _resolve_static_file(root, filepath)
if file_path is None:
return web.Response(text="Forbidden", status=403)
exact = STATIC_EXACT_FILES.get((subdir, filepath))
if exact is not None:
file_path, content_type = os.path.join(root, filepath), exact
else:
file_path = _resolve_static_file(root, filepath)
if file_path is None:
return web.Response(text="Forbidden", status=403)
content_type = STATIC_MIME_TYPES[os.path.splitext(file_path)[1].lower()]
if not os.path.isfile(file_path):
return web.Response(text="Not Found", status=404)
ext = os.path.splitext(file_path)[1].lower()
with open(file_path, "rb") as f:
content = f.read()
return web.Response(body=content, content_type=STATIC_MIME_TYPES[ext])
return web.Response(body=content, content_type=content_type)
def _serve_html_page(self, filename, title, cache=True):
"""Serve ``web/<filename>``; 404 when missing, 500 when unreadable."""