From 9a3e9314f19cc2aa5170710146925c12a31a3017 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Louis-F=C3=A9lix=20Nothias?= Date: Fri, 10 Jul 2026 11:42:32 +0200 Subject: [PATCH 1/2] test(pricing): pin that single-agent memory is summed into run cost --- tests/pricing_test.py | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/tests/pricing_test.py b/tests/pricing_test.py index a43ff79..27484e3 100644 --- a/tests/pricing_test.py +++ b/tests/pricing_test.py @@ -225,6 +225,44 @@ def _cost_for(model_id_value): print("โœ… list model_id priced against first element (no unhashable crash)") +def test_single_agent_memory_is_priced(): + """A single-agent run's memory must be summed into the run's cost. + + ``single_agent_factory`` saves its memory as ``task_single_agent.json`` + (``save_agent_memories(agent, MEMORY_PATH, "single_agent")``), so the + ``task_`` prefix matches it. The run folder is named ``single_agent_*``, + which is a directory rather than a memory file. + """ + print("\n๐Ÿงช Testing single-agent memory is priced...") + + from sources.utils.pricing import PricingCalculator + + model_pricing = {"deepseek/deepseek-chat": {"input": 0.27, "output": 1.10}} + expected = (1000 * 0.27 + 500 * 1.10) / 1_000_000 + + with tempfile.TemporaryDirectory() as tmp: + memory_dir = os.path.join(tmp, "memory") + workflow_dir = os.path.join(tmp, "workflow") + run_uuid = "single_agent_20260101_abc123" + os.makedirs(os.path.join(memory_dir, run_uuid)) + os.makedirs(os.path.join(workflow_dir, run_uuid)) + + with open(os.path.join(workflow_dir, run_uuid, "state_result.json"), "w") as fh: + json.dump({"model_id": "deepseek/deepseek-chat"}, fh) + + steps = [{"token_usage": {"input_tokens": 1000, "output_tokens": 500, "total_tokens": 1500}}] + with open(os.path.join(memory_dir, run_uuid, "task_single_agent.json"), "w") as fh: + json.dump(steps, fh) + + config = SimpleNamespace( + memory_dir=memory_dir, workflow_dir=workflow_dir, model_pricing=model_pricing + ) + cost = PricingCalculator(config).calculate_cost(run_uuid) + + assert abs(cost - expected) < 1e-9, f"single-agent memory: got {cost}, expected {expected}" + print("โœ… task_single_agent.json still priced") + + def run_all_tests(): """Run all pricing tests.""" print("Starting pricing functionality tests...\n") @@ -235,6 +273,7 @@ def run_all_tests(): test_pricing_fallback_behavior() test_pricing_data_format() test_calculate_cost_handles_scalar_and_list_model_id() + test_single_agent_memory_is_priced() print("\n๐ŸŽ‰ All pricing tests passed successfully!") return True From e27abb36ec2318113f2dfa61cb64e8083e03e1b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Louis-F=C3=A9lix=20Nothias?= Date: Fri, 10 Jul 2026 11:42:32 +0200 Subject: [PATCH 2/2] chore(pricing): drop the dead single_agent memory-file prefix --- sources/utils/pricing.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sources/utils/pricing.py b/sources/utils/pricing.py index ecf06e0..9567edb 100644 --- a/sources/utils/pricing.py +++ b/sources/utils/pricing.py @@ -282,7 +282,7 @@ def calculate_cost(self, uuid: str) -> float: if model_id: try: for file in os.listdir(memory_path): - if (file.startswith("task_") or file.startswith("single_agent")) and file.endswith(".json"): + if file.startswith("task_") and file.endswith(".json"): with open(memory_path / file) as f: steps = json.load(f) token_usage = {