import argparse
import json
import random
import sys
from pathlib import Path
DESCRIPTION = """\
Write a large synthetic session, for benchmarking a render at scale.
The turns are drawn from the committed fixtures rather than invented, so the
shapes are the harness's own: every built-in tool's call and result, prose,
thinking, and code in the languages the corpus actually carries. They are dealt
out in a seeded order and stamped with fresh ids and timestamps until the file
reaches the size asked for, so the same arguments always write the same session.
A session this long measures a different thing from the small fixtures. Syntax
highlighting compiles a language's regexes once, so a session that meets its
languages early and then runs for megabytes is dominated by the per-byte work
(matching, markup, allocation) where a short one is dominated by that one-time
compile. Benchmark both, and expect a change to move them differently.
"""
MEGABYTE = 1024 * 1024
SOURCES = ("playground.jsonl", "session.jsonl", "answers.jsonl")
def turns(fixtures: Path) -> list[list[dict]]:
grouped: list[list[dict]] = []
for source in SOURCES:
for line in (fixtures / source).read_text().splitlines():
entry = json.loads(line)
if grouped and answers_a_call(entry):
grouped[-1].append(entry)
else:
grouped.append([entry])
return grouped
def answers_a_call(entry: dict) -> bool:
content = entry.get("message", {}).get("content")
if entry.get("type") != "user" or not isinstance(content, list):
return False
return any(block.get("type") == "tool_result" for block in content)
def restamp(unit: list[dict], ordinal: int, second: int) -> list[dict]:
calls: dict[str, str] = {}
stamped = []
for offset, entry in enumerate(unit):
turn = json.loads(json.dumps(entry))
turn["timestamp"] = timestamp(second + offset)
message = turn.get("message")
if isinstance(message, dict):
if "id" in message:
message["id"] = f"msg_{ordinal}_{offset}"
renumber(message.get("content"), ordinal, calls)
if isinstance(message.get("content"), str):
message["content"] = f"[turn {ordinal}] {message['content']}"
stamped.append(turn)
return stamped
def renumber(content: object, ordinal: int, calls: dict[str, str]) -> None:
if not isinstance(content, list):
return
for index, block in enumerate(content):
if not isinstance(block, dict):
continue
if block.get("type") == "tool_use":
calls[block["id"]] = f"call_{ordinal}_{index}"
block["id"] = calls[block["id"]]
if block.get("type") == "tool_result":
answered = block.get("tool_use_id")
block["tool_use_id"] = calls.get(answered, f"call_{ordinal}_{index}")
if block.get("type") == "text" and isinstance(block.get("text"), str):
block["text"] = f"[turn {ordinal}] {block['text']}"
def timestamp(second: int) -> str:
day, rest = divmod(second, 86400)
hour, rest = divmod(rest, 3600)
minute, second = divmod(rest, 60)
return f"2026-{1 + day // 28:02d}-{1 + day % 28:02d}T{hour:02d}:{minute:02d}:{second:02d}Z"
def deal(units: list[list[dict]], budget: int, seed: int) -> list[str]:
shuffler = random.Random(seed)
lines: list[str] = []
written = ordinal = second = 0
deck: list[list[dict]] = []
while written < budget:
if not deck:
deck = list(units)
shuffler.shuffle(deck)
unit = deck.pop()
for turn in restamp(unit, ordinal, second):
line = json.dumps(turn)
lines.append(line)
written += len(line) + 1
ordinal += 1
second += len(unit) + shuffler.randrange(1, 30)
return lines
def main() -> None:
parser = argparse.ArgumentParser(
description=DESCRIPTION, formatter_class=argparse.RawDescriptionHelpFormatter
)
parser.add_argument("--megabytes", type=float, required=True, help="how large to make it")
parser.add_argument("--output", type=Path, required=True, help="where to write it")
parser.add_argument("--fixtures", type=Path, default=Path("tests/fixtures"))
parser.add_argument("--seed", type=int, default=1387, help="which session to write")
arguments = parser.parse_args()
units = turns(arguments.fixtures)
lines = deal(units, int(arguments.megabytes * MEGABYTE), arguments.seed)
arguments.output.parent.mkdir(parents=True, exist_ok=True)
arguments.output.write_text("\n".join(lines) + "\n")
written = arguments.output.stat().st_size
print(f"{arguments.output}: {len(lines):,} turns, {written / MEGABYTE:.1f} MB", file=sys.stderr)
if __name__ == "__main__":
main()