Spaces:
Sleeping
Sleeping
File size: 13,372 Bytes
14184e3 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 | import re
from app.agents.shell_visual_engine import ShellGrounding, ShellSetupCode, ShellVisualEngine
class _FakeClient:
def __init__(self, obj):
self._obj = obj
def structured_complete(self, messages, schema, **kw):
return self._obj
def test_extract_grounding_3d_happy_path_keeps_anchor():
chunks = [{"source": "paper.pdf", "text": "The hemoglobin molecule forms a tetramer of four globular subunits."}]
grounding = ShellGrounding(
renderable=True,
anchor="forms a tetramer of four globular subunits",
scene_brief="Render hemoglobin as four globular subunits arranged as a tetramer.",
)
engine = ShellVisualEngine(client=_FakeClient(grounding))
result = engine._extract_grounding("hemoglobin", "3d", chunks, "high_school")
assert result.renderable is True
assert result.anchor == "forms a tetramer of four globular subunits"
assert result.scene_brief == "Render hemoglobin as four globular subunits arranged as a tetramer."
def test_extract_grounding_2d_anim_happy_path_keeps_anchor():
chunks = [{"source": "paper.pdf", "text": "During depolarization, sodium ions rush into the cell, flipping the membrane potential."}]
grounding = ShellGrounding(
renderable=True,
anchor="sodium ions rush into the cell, flipping the membrane potential",
scene_brief="Animate sodium ions flowing into the cell as the membrane potential flips positive.",
)
engine = ShellVisualEngine(client=_FakeClient(grounding))
result = engine._extract_grounding("depolarization", "2d_anim", chunks, "high_school")
assert result.renderable is True
assert result.anchor == "sodium ions rush into the cell, flipping the membrane potential"
assert result.scene_brief == "Animate sodium ions flowing into the cell as the membrane potential flips positive."
def test_extract_grounding_decline_path_returned_as_is():
chunks = [{"source": "paper.pdf", "text": "This section discusses abstract policy tradeoffs with no physical form."}]
grounding = ShellGrounding(
renderable=False,
decline_reason="'policy tradeoffs' has no concrete spatial object in the source — better explored in chat.",
)
engine = ShellVisualEngine(client=_FakeClient(grounding))
result = engine._extract_grounding("policy tradeoffs", "3d", chunks, "high_school")
assert result.renderable is False
assert result.anchor == ""
assert result.decline_reason == "'policy tradeoffs' has no concrete spatial object in the source — better explored in chat."
def test_extract_grounding_discards_hallucinated_anchor():
chunks = [{"source": "paper.pdf", "text": "The heart has four chambers that pump blood through the body."}]
grounding = ShellGrounding(
renderable=True,
anchor="this text was never in the source at all",
scene_brief="Render a four-chambered heart pumping blood.",
)
engine = ShellVisualEngine(client=_FakeClient(grounding))
result = engine._extract_grounding("heart anatomy", "3d", chunks, "high_school")
assert result.renderable is True
assert result.anchor == ""
assert result.scene_brief == "Render a four-chambered heart pumping blood."
def _engine():
return ShellVisualEngine(client=_FakeClient(None))
def test_assemble_shell_replaces_setup_code_token_for_both_kinds():
engine = _engine()
for kind in ("3d", "2d_anim"):
html = engine._assemble_shell(kind, "group.add(new THREE.Mesh());" + "x" * 30)
assert "{SETUP_CODE_JSON}" not in html
def test_assemble_shell_escapes_hostile_script_close_tag():
hostile = "group.add(new THREE.Mesh()); /* </script><script>alert(1)</script> */"
engine = _engine()
for kind in ("3d", "2d_anim"):
html = engine._assemble_shell(kind, hostile)
# The raw closing tag from the hostile string must never survive unescaped.
assert "<script>alert(1)</script>" not in html
# It must appear only in its escaped form -- both occurrences from the
# hostile string end up as the literal 3-char sequence <\/script>.
assert html.count("<\\/script>") == 2
def test_assemble_shell_globals_lockdown_params_present_for_both_kinds():
shadowed_names = ["window", "document", "fetch", "eval", "parent", "top", "self", "Function"]
engine = _engine()
for kind in ("3d", "2d_anim"):
html = engine._assemble_shell(kind, "y" * 40)
for name in shadowed_names:
assert f'"{name}"' in html
def test_assemble_shell_globals_lockdown_param_and_arg_counts_match_for_both_kinds():
"""Regression guard for the parity the module docstring calls out: the
`new Function("api", <shadowed names...>, SETUP_CODE_JSON)` parameter
list and the real invocation `contentFn(api, undefined, undefined, ...)`
must pass exactly the same number of positional arguments -- one real
value (`api`) plus exactly one `undefined` per shadowed name. If a future
edit added or removed a shadowed name in only one of the two spots, it
would either leave a dangerous global un-shadowed (security gap) or throw
a runtime arity mismatch -- nothing else in this file catches that today.
"""
engine = _engine()
for kind in ("3d", "2d_anim"):
html = engine._assemble_shell(kind, "v" * 40)
function_call_match = re.search(r"new Function\(([^)]*)\)", html)
assert function_call_match, f"could not find a `new Function(...)` call for kind={kind}"
# Every argument to `new Function` here is a quoted string literal --
# the shadowed param names, plus the setup-code body (itself a JSON
# string literal) as the trailing argument. Extracting each quoted
# token this way (rather than a naive comma split) stays correct even
# though the setup-code string could itself contain commas.
function_args = re.findall(r'"(?:[^"\\]|\\.)*"', function_call_match.group(1))
# The last quoted argument is the function body (the setup code), not
# a shadowed name -- everything before it is a parameter name (api +
# the shadowed globals).
param_name_count = len(function_args) - 1
invocation_matches = re.findall(r"contentFn\(([^)]*)\)", html)
assert len(invocation_matches) == 1, f"expected exactly one contentFn(...) call site for kind={kind}"
invocation_args = [arg.strip() for arg in invocation_matches[0].split(",")]
arg_count = len(invocation_args)
assert param_name_count == arg_count, (
f"kind={kind}: new Function declares {param_name_count} parameter names "
f"but contentFn(...) passes {arg_count} arguments -- these must match "
"exactly (api's real value + one undefined per shadowed global)"
)
def test_assemble_shell_3d_has_pinned_threejs_cdn_2d_does_not():
engine = _engine()
html_3d = engine._assemble_shell("3d", "z" * 40)
html_2d = engine._assemble_shell("2d_anim", "z" * 40)
assert "https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js" in html_3d
assert "https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/examples/js/controls/OrbitControls.js" in html_3d
assert "three.js/r128" not in html_2d
def test_assemble_shell_no_dark_background_uses_cream():
engine = _engine()
for kind in ("3d", "2d_anim"):
html = engine._assemble_shell(kind, "w" * 40)
assert "#0f0f0f" not in html
assert "#FAF7F2" in html
def test_assemble_shell_has_well_formed_script_block():
engine = _engine()
for kind in ("3d", "2d_anim"):
html = engine._assemble_shell(kind, "group.add(new THREE.Mesh()); return { update: function(t) {} };")
blocks = re.findall(r"<script[^>]*>(.*?)</script>", html, re.DOTALL)
assert len(blocks) >= 1
class _StagedFakeClient:
"""Fakes the two internal `structured_complete` calls `generate()` makes (grounding,
then setup-code) with a single client, dispatching on the schema class passed as the
second argument -- and records every call's (schema, messages) for later inspection.
If `setup_code_response` is left None, a setup-code-stage call is treated as a test
failure (used to prove the decline path never reaches that stage)."""
def __init__(self, grounding_response, setup_code_response=None):
self._grounding_response = grounding_response
self._setup_code_response = setup_code_response
self.calls = [] # list of (schema, messages)
def structured_complete(self, messages, schema, **kw):
self.calls.append((schema, messages))
if schema is ShellGrounding:
return self._grounding_response
if schema is ShellSetupCode:
if self._setup_code_response is None:
raise AssertionError("setup-code stage should never have been reached on the decline path")
return self._setup_code_response
raise AssertionError(f"unexpected schema passed to structured_complete: {schema}")
def _setup_code_messages(client):
calls = [messages for schema, messages in client.calls if schema is ShellSetupCode]
assert len(calls) == 1, "expected exactly one ShellSetupCode structured_complete call"
return calls[0]
def test_generate_3d_happy_path_returns_assembled_html():
grounding = ShellGrounding(renderable=True, scene_brief="Render a tetrahedron with four triangular faces.")
setup = ShellSetupCode(
setup_code="const { THREE, scene, camera, group } = api; group.add(new THREE.Mesh());"
)
client = _StagedFakeClient(grounding, setup)
engine = ShellVisualEngine(client=client)
chunks = [{"source": "paper.pdf", "text": "A tetrahedron has four triangular faces."}]
result = engine.generate("tetrahedron", "3d", chunks, "high_school")
assert result.animation_type == "3d"
assert result.html_code
assert "<script>" in result.html_code
assert result.explanation == grounding.scene_brief
def test_generate_2d_anim_happy_path_returns_assembled_html():
grounding = ShellGrounding(renderable=True, scene_brief="Animate a ball bouncing under gravity.")
setup = ShellSetupCode(
setup_code="const { ctx, width, height } = api; return { draw(ctx, width, height, time, dt) {} };"
)
client = _StagedFakeClient(grounding, setup)
engine = ShellVisualEngine(client=client)
chunks = [{"source": "paper.pdf", "text": "A ball bounces under gravity, losing height each bounce."}]
result = engine.generate("bouncing ball", "2d_anim", chunks, "high_school")
assert result.animation_type == "2d_anim"
assert result.html_code
assert "<script>" in result.html_code
assert result.explanation == grounding.scene_brief
def test_generate_decline_path_short_circuits_before_setup_code():
grounding = ShellGrounding(
renderable=False,
decline_reason="'policy tradeoffs' has no concrete spatial object in the source — better explored in chat.",
)
# No setup_code_response given -- any structured_complete(..., ShellSetupCode) call raises.
client = _StagedFakeClient(grounding, setup_code_response=None)
engine = ShellVisualEngine(client=client)
chunks = [{"source": "paper.pdf", "text": "This section discusses abstract policy tradeoffs."}]
result = engine.generate("policy tradeoffs", "3d", chunks, "high_school")
assert result.animation_type == "2d_text"
assert "policy tradeoffs" in result.html_code
assert result.explanation == grounding.decline_reason
# Exactly one structured_complete call happened, and it was the grounding stage --
# the setup-code stage was genuinely never reached.
assert len(client.calls) == 1
assert client.calls[0][0] is ShellGrounding
def test_generate_setup_code_prompt_instructs_group_not_scene_for_3d():
grounding = ShellGrounding(renderable=True, scene_brief="Render a tetrahedron with four triangular faces.")
setup = ShellSetupCode(setup_code="const { THREE, scene, camera, group } = api; group.add(new THREE.Mesh());")
client = _StagedFakeClient(grounding, setup)
engine = ShellVisualEngine(client=client)
chunks = [{"source": "paper.pdf", "text": "A tetrahedron has four triangular faces."}]
engine.generate("tetrahedron", "3d", chunks, "high_school")
prompt_text = " ".join(m["content"] for m in _setup_code_messages(client))
assert "Do NOT call `scene.add(...)` directly" in prompt_text
assert "add every mesh/line/points/group you create to `group`" in prompt_text
def test_generate_setup_code_prompt_never_sees_raw_source_text():
marker = "UNIQUE_SOURCE_MARKER_TEXT_12345"
grounding = ShellGrounding(renderable=True, scene_brief="Render a tetrahedron with four triangular faces.")
setup = ShellSetupCode(setup_code="const { THREE, scene, camera, group } = api; group.add(new THREE.Mesh());")
client = _StagedFakeClient(grounding, setup)
engine = ShellVisualEngine(client=client)
chunks = [{"source": "paper.pdf", "text": f"A tetrahedron has four triangular faces. {marker}"}]
engine.generate("tetrahedron", "3d", chunks, "high_school")
prompt_text = " ".join(m["content"] for m in _setup_code_messages(client))
assert marker not in prompt_text
assert grounding.scene_brief in prompt_text
|