Spaces:
Running
Running
File size: 5,833 Bytes
c8365f5 | 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 | import asyncio
import sys
import types
def _install_tool_stubs(writes, image_url="https://example.test/generated.png"):
tools_pkg = types.ModuleType("tools")
registry = types.ModuleType("tools.registry")
async def write_file(path, content):
writes[path] = content
# Il registry reale usa il contratto `ok` per le operazioni filesystem.
return {"ok": True, "path": path}
async def generate_image(prompt, width=512, height=512, prefer_internal=True):
# Il percorso interattivo deve ottenere un URL renderizzabile subito,
# senza attendere il cold-start del generatore interno.
assert prefer_internal is False
return {"url": image_url, "prompt": prompt, "width": width, "height": height}
registry.TOOL_REGISTRY = {
"write_file": {"_fn": write_file},
"generate_image": {"_fn": generate_image},
}
sys.modules["tools"] = tools_pkg
sys.modules["tools.registry"] = registry
api_pkg = types.ModuleType("api")
speculative = types.ModuleType("api.speculative")
speculative.get_speculative_result = lambda *_args, **_kwargs: None
sys.modules["api"] = api_pkg
sys.modules["api.speculative"] = speculative
def test_direct_csv_conversion_writes_vfs_content_and_returns_terminal_output():
writes = {}
_install_tool_stubs(writes)
from agents.unified_loop_tools import DirectToolsMixin
class Harness(DirectToolsMixin):
def _max_tokens_for_goal(self, _goal):
return 4096
events = []
async def on_step(event):
events.append(event)
goal = """Converti e2e_metrics.csv in un file chiamato e2e_metrics.json.
--- **File allegati:**
### 📎 e2e_metrics.csv (excel, 66B)
```
mese,richieste,successi
2026-01,12,11
2026-02,15,14
```
"""
output, called, succeeded, errors = asyncio.run(
Harness()._run_direct_tools(goal, on_step=on_step)
)
assert output.startswith("[DIRECT_TERMINAL]\nE2E_CONVERSION_OK")
assert called == 1
assert succeeded == 1
assert errors == 0
assert '"richieste": 15' in writes["e2e_metrics.json"]
assert any(event.get("action") == "file_written" for event in events)
def test_direct_inline_csv_conversion_writes_source_and_semantically_equivalent_json():
writes = {}
_install_tool_stubs(writes)
from agents.unified_loop_tools import DirectToolsMixin
class Harness(DirectToolsMixin):
def _max_tokens_for_goal(self, _goal):
return 4096
events = []
async def on_step(event):
events.append(event)
goal = """Esegui solo nel workspace VFS locale questa conversione deterministica.
Crea capability_catalog.csv con contenuto esatto: id,name,active
1,alpha,true
2,beta,false
. Poi crea capability_catalog.json con lo stesso catalogo come array JSON valido di due oggetti.
Non usare rete, shell, servizi esterni o provider aggiuntivi."""
output, called, succeeded, errors = asyncio.run(
Harness()._run_direct_tools(goal, on_step=on_step)
)
assert output.startswith("[DIRECT_TERMINAL]\nE2E_CONVERSION_OK")
assert "verificati 2 record" in output
assert called == 1
assert succeeded == 1
assert errors == 0
assert writes["capability_catalog.csv"] == "id,name,active\n1,alpha,true\n2,beta,false\n"
assert writes["capability_catalog.json"] == (
'[\n {\n "id": 1,\n "name": "alpha",\n "active": "true"\n },\n'
' {\n "id": 2,\n "name": "beta",\n "active": "false"\n }\n]\n'
)
assert {event.get("path") for event in events if event.get("action") == "file_written"} == {
"capability_catalog.csv", "capability_catalog.json"
}
def test_textual_checkout_plan_does_not_trigger_direct_image_generation():
writes = {}
_install_tool_stubs(writes)
from agents.unified_loop_tools import DirectToolsMixin
class Harness(DirectToolsMixin):
def _max_tokens_for_goal(self, _goal):
return 4096
events = []
async def on_step(event):
events.append(event)
output, called, succeeded, errors = asyncio.run(
Harness()._run_direct_tools(
"Crea un breve piano per verificare un errore intermittente nel checkout e indica il primo dato da raccogliere.",
on_step=on_step,
)
)
assert "E2E_IMAGE_OK" not in output
assert not any(event.get("action") == "file_written" for event in events)
assert not any(path.startswith("generated-image-") for path in writes)
assert (called, succeeded, errors) == (0, 0, 0)
def test_direct_image_returns_renderable_terminal_markdown_without_llm():
writes = {}
_install_tool_stubs(writes)
from agents.unified_loop_tools import DirectToolsMixin
class Harness(DirectToolsMixin):
def _max_tokens_for_goal(self, _goal):
return 4096
events = []
async def on_step(event):
events.append(event)
output, called, succeeded, errors = asyncio.run(
Harness()._run_direct_tools(
"Genera un’immagine quadrata di un aeroplanino arancione su fondo blu notte.",
on_step=on_step,
)
)
assert output.startswith("[DIRECT_TERMINAL]\n
assert "E2E_IMAGE_OK" in output
assert "aeroplanino%20arancione" in output
assert "File VFS: `generated-image-" in output
image_event = next(event for event in events if event.get("action") == "file_written")
assert image_event["path"].startswith("generated-image-")
assert image_event["path"].endswith(".jpg")
assert image_event["source_url"].startswith("https://image.pollinations.ai/prompt/")
assert image_event["mime_type"] == "image/jpeg"
assert called == 1
assert succeeded == 1
assert errors == 0
|