Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@
import json

from forecasting_tools.agents_and_tools.source_archive.config import ArchiveConfig
from forecasting_tools.agents_and_tools.source_archive.cost import (
RunCost,
write_cost_report,
)
from forecasting_tools.agents_and_tools.source_archive.models import (
StoredCapture,
url_hash,
Expand Down Expand Up @@ -87,3 +91,22 @@ def test_captured_status_wins_over_failure(tmp_path):
config,
)
assert read_outcomes(store, config)["https://a.test"] == "stored"


def test_read_outcomes_ignores_cost_reports(tmp_path):
"""Cost reports live under reports/ too (``<run_id>_cost.json``, a JSON
dict, not a list of rows) — read_outcomes must skip them, not crash."""
store = LocalBlobStore(tmp_path)
config = ArchiveConfig(s3_prefix="t")
write_run_report(
store,
"r1",
PipelineSummary(
outcomes=[CaptureOutcome(url="https://a.test", status="stored")]
),
config,
)
write_cost_report(store, "r1", RunCost(run_id="r1", archived=1), config)

out = read_outcomes(store, config)
assert out == {"https://a.test": "stored"}
6 changes: 5 additions & 1 deletion forecasting_tools/agents_and_tools/source_archive/reports.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,12 +73,16 @@ def read_outcomes(store: BlobStore, config: ArchiveConfig) -> dict[str, str]:
prefix = config.s3_prefix.rstrip("/")
out: dict[str, str] = {}
for key in store.list_keys(f"{prefix}/reports/"):
if not key.endswith(".json"):
# reports/ also holds per-run cost breakdowns (``<run_id>_cost.json``,
# a dict) — only run reports (a list of outcome rows) belong here.
if not key.endswith(".json") or key.endswith("_cost.json"):
continue
try:
rows = json.loads(store.get(key).decode("utf-8"))
except (UnicodeDecodeError, ValueError):
continue
if not isinstance(rows, list):
continue
for r in rows:
url = canonicalize_url(r.get("url", ""))
status = r.get("status", "")
Expand Down
Loading