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
2 changes: 1 addition & 1 deletion sources/utils/pricing.py
Original file line number Diff line number Diff line change
Expand Up @@ -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 = {
Expand Down
39 changes: 39 additions & 0 deletions tests/pricing_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -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")
Expand All @@ -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
Expand Down